CustusX  15.3.4-beta
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxVideoConnectionWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
34 
35 #include <boost/bind.hpp>
36 
37 #include <QDir>
38 #include <QStackedWidget>
39 #include <QPushButton>
40 #include <QFileDialog>
41 
42 #include "vtkImageData.h"
43 
44 #include "cxTime.h"
45 #include "cxLogger.h"
46 #include "cxProbeSector.h"
48 #include "cxStringProperty.h"
49 #include "cxHelperWidgets.h"
50 #include "cxDataInterface.h"
51 #include "cxTrackingService.h"
52 #include "cxOptionsWidget.h"
53 #include "cxVideoService.h"
54 #include "cxPatientModelService.h"
56 #include "cxStreamerService.h"
57 #include "cxVideoSource.h"
58 #include "cxViewService.h"
59 #include "cxImage.h"
60 #include "cxProfile.h"
61 
62 namespace cx
63 {
64 
66  BaseWidget(parent, "IGTLinkWidget", "Video Connection"),
67  mServices(services)
68 {
69  mOptions = profile()->getXmlSettings().descend("video");
70 
71  QString defaultConnection = mServices->videoService->getConnectionMethod();
72  mConnectionSelector = StringProperty::initialize("Connection", "", "Method for connecting to Video Server", defaultConnection, QStringList(), mOptions.getElement("video"));
73  connect(mConnectionSelector.get(), SIGNAL(changed()), this, SLOT(selectGuiForConnectionMethodSlot()));
74 
76 
77  mStackedWidget = new QStackedWidget(this);
78  QFrame* frame = this->wrapStackedWidgetInAFrame();
83 
84  mToptopLayout = new QVBoxLayout(this);
86  mToptopLayout->addWidget(frame);
87  mToptopLayout->addWidget(mConnectButton);
90  mToptopLayout->addStretch();
91 
92  connect(mServices->videoService.get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
93  connect(mServices->videoService.get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
94 
95  this->addExistingStreamerServices(); //Need to add StreamerServices already existing at this point, since we will only get signals when new Services are added
96 
98 }
99 
101 {
102  if (mServices->videoService)
103  {
104  disconnect(mServices->videoService.get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
105  disconnect(mServices->videoService.get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
106  }
107 }
108 
109 void VideoConnectionWidget::addExistingStreamerServices()
110 {
111  QList<StreamerService *> services = mServices->videoService->getStreamerServices();
112  foreach(StreamerService* service, services)
113  {
114  this->onServiceAdded(service);
115  }
116 }
117 
119 {
120  QWidget* widget = this->createStreamerWidget(service);
121  QWidget* serviceWidget = this->wrapVerticalStretch(widget);
122  mStackedWidget->addWidget(serviceWidget);
123  mStreamerServiceWidgets[service->getName()] = serviceWidget;
124 
125  this->addServiceToSelector(service->getName());
126 }
127 
128 QWidget* VideoConnectionWidget::createStreamerWidget(StreamerService* service)
129 {
130  QString serviceName = service->getName();
131  QDomElement element = mOptions.getElement("video");
132  std::vector<PropertyPtr> adapters = service->getSettings(element);
133 
134  OptionsWidget* widget = new OptionsWidget(mServices->visualizationService, mServices->patientModelService, this);
135  widget->setOptions(serviceName, adapters, false);
136 
137  connect(mConnectionSelectionWidget, SIGNAL(detailsTriggered()), widget, SLOT(toggleAdvanced()));
138 
139  return widget;
140 }
141 
143 {
144  this->removeServiceFromSelector(service->getName());
145  this->removeServiceWidget(service->getName());
146 }
147 
148 void VideoConnectionWidget::addServiceToSelector(QString name)
149 {
150  QStringList range = mConnectionSelector->getValueRange();
151  range.append(name);
152  range.removeDuplicates();
153  mConnectionSelector->setValueRange(range);
154 }
155 
156 void VideoConnectionWidget::removeServiceFromSelector(QString name)
157 {
158  QStringList range = mConnectionSelector->getValueRange();
159  int index = range.indexOf(name);
160  if(mConnectionSelector->getValue() == name)
161  mConnectionSelector->setValue(range[0]);
162  range.removeAt(index);
163  mConnectionSelector->setValueRange(range);
164 }
165 
166 void VideoConnectionWidget::removeServiceWidget(QString name)
167 {
168  QWidget* serviceWidget = mStreamerServiceWidgets[name];
169  mStackedWidget->removeWidget(serviceWidget);
170  delete serviceWidget;
171  mStreamerServiceWidgets.erase(name);
172 }
173 
175 {
177 }
178 
180 {
181  QFrame* frame = new QFrame(this);
182  frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
183  frame->setSizePolicy(frame->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
184  QVBoxLayout* frameLayout = new QVBoxLayout(frame);
185  frameLayout->addWidget(mStackedWidget);
186 
187  return frame;
188 }
189 
191 {
192  QWidget* retval = new QWidget(this);
193  QVBoxLayout* layout = new QVBoxLayout(retval);
194  layout->addWidget(input);
195  layout->addStretch();
196  layout->setMargin(0);
197  layout->setSpacing(0);
198  return retval;
199 }
200 
202 {
203  return "<html>"
204  "<h3><Setup IGTLink connection.</h3>"
205  "<p>Lets you set up a connection to a streaming server using IGTLink.</p>"
206  "<p><i></i></p>"
207  "</html>";
208 }
209 
211 {
212  QString name = mConnectionSelector->getValue();
213  //Need to set connection method in VideoConneectionManager before calling useDirectLink(), useLocalServer() and useRemoteServer()
214  mServices->videoService->setConnectionMethod(mConnectionSelector->getValue());
215 
216  QWidget* serviceWidget = mStreamerServiceWidgets[name];
217  if(serviceWidget)
218  mStackedWidget->setCurrentWidget(serviceWidget);
219 }
220 
222 {
223  if (mServices->videoService->isConnected())
224  mServices->videoService->closeConnection();
225  else
226  mServices->videoService->openConnection();
227 }
228 
230 {
231  QPushButton* connectButton = new QPushButton("Connect", this);
232  connectButton->setToolTip("Connect/disconnect to the video server using the seleted method");
233  connect(connectButton, SIGNAL(clicked()), this, SLOT(toggleConnectServer()));
234  return connectButton;
235 }
236 
238 {
239  QPushButton* importstreamimagebutton = new QPushButton("Import image from stream", this);
240  importstreamimagebutton->setToolTip("Import a single image/volume from the real time stream");
241  importstreamimagebutton->setDisabled(true);
242  connect(importstreamimagebutton, SIGNAL(clicked()), this, SLOT(importStreamImageSlot()));
243 
244  return importstreamimagebutton;
245 }
246 
248 {
249  mImportStreamImageButton->setEnabled(mServices->videoService->isConnected());
250  if (mServices->videoService->isConnected())
251  mConnectButton->setText("Disconnect Server");
252  else
253  mConnectButton->setText("Connect Server");
254 
255  this->adjustSize();
256 }
257 
259 {
260  if (!mServices->videoService->isConnected())
261  {
262  reportWarning("Video is not connected");
263  return;
264  }
265  Transform3D rMd = Transform3D::Identity();
266  ToolPtr probe = mServices->trackingService->getFirstProbe();
267  VideoSourcePtr videoSource;
268  if (probe)
269  {
270  videoSource = probe->getProbe()->getRTSource();
271  rMd = calculate_rMd_ForAProbeImage(probe);
272  }
273  else
274  videoSource = mServices->videoService->getActiveVideoSource();
275 
276  if (!videoSource)
277  {
278  reportWarning("No Video data source");
279  return;
280  }
281  if (!videoSource->validData())
282  {
283  reportWarning("No valid video data");
284  return;
285  }
286 
287  vtkImageDataPtr input;
288  input = videoSource->getVtkImageData();
289  if (!input)
290  {
291  reportWarning("No Video data");
292  return;
293  }
294  QString filename = generateFilename(videoSource);
295 
296  this->saveAndImportSnapshot(input, filename, rMd);
297 
298 }
299 
301 {
302  Transform3D rMd = Transform3D::Identity();
303  Transform3D rMpr = mServices->patientModelService->get_rMpr();
304  Transform3D prMt = probe->get_prMt();
305  Transform3D tMu = probe->getProbe()->getSector()->get_tMu();
306  Transform3D uMv = probe->getProbe()->getSector()->get_uMv();
307  rMd = rMpr * prMt * tMu * uMv;
308  return rMd;
309 }
310 
312 {
313  vtkImageDataPtr input = videoSource->getVtkImageData();
314  int* extent = input->GetExtent();
315  QString filename;
316  QString format = timestampSecondsFormat();
317  if (extent[5] - extent[4] > 0)
318  filename = "3DRTSnapshot_";
319  else
320  filename = "2DRTSnapshot_";
321 
322  filename += videoSource->getName() + QDateTime::currentDateTime().toString(format);
323  return filename;
324 }
325 
327 {
328  vtkImageDataPtr copiedImage = vtkImageDataPtr::New();
329  copiedImage->DeepCopy(input);
330 
331  ImagePtr output = mServices->patientModelService->createSpecificData<Image>(filename);
332  output->setVtkImageData(input);
333  output->get_rMd_History()->setRegistration(rMd);
334  mServices->patientModelService->insertData(output);
335 
336  mServices->visualizationService->autoShowData(output);
337  report(QString("Saved snapshot %1 from active video source").arg(output->getName()));
338 }
339 
340 } //end namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:142
QString generateFilename(VideoSourcePtr videoSource)
boost::shared_ptr< class StringPropertyActiveVideoSource > StringPropertyActiveVideoSourcePtr
DetailedLabeledComboBoxWidget * mConnectionSelectionWidget
void onServiceAdded(StreamerService *service)
void connected(bool on)
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:61
virtual void setVtkImageData(const vtkImageDataPtr &data, bool resetTransferFunctions=true)
Definition: cxImage.cpp:290
virtual std::vector< PropertyPtr > getSettings(QDomElement root)=0
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
static StringPropertyActiveVideoSourcePtr New()
QString timestampSecondsFormat()
Definition: cxTime.cpp:39
QDomElement getElement()
return the current element
void onServiceRemoved(StreamerService *service)
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
Composite widget for string selection with .
A volumetric data set.
Definition: cxImage.h:64
boost::shared_ptr< class VideoSource > VideoSourcePtr
virtual QString getName()=0
StringPropertyActiveVideoSourcePtr mActiveVideoSourceSelector
QWidget * wrapVerticalStretch(QWidget *input)
Transform3D calculate_rMd_ForAProbeImage(ToolPtr probe)
static StringPropertyPtr initialize(const QString &uid, QString name, QString help, QString value, QStringList range, QDomNode root=QDomNode())
virtual QString defaultWhatsThis() const
Returns a short description of what this widget will do for you.
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:108
void saveAndImportSnapshot(vtkImageDataPtr input, QString filename, Transform3D rMd)
void report(QString msg)
Definition: cxLogger.cpp:90
VideoConnectionWidget(VisServicesPtr services, QWidget *parent)
QPushButton * initializeImportStreamImageButton()
QWidget * sscCreateDataWidget(QWidget *parent, PropertyPtr data, QGridLayout *gridLayout, int row)
Create a widget capable of displaying the input data.
StringPropertyActiveVideoSourcePtr initializeActiveVideoSourceSelector()
Abstract class. Interface to Streamers.
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
void setOptions(QString uid, std::vector< PropertyPtr > options, bool showAdvanced)
boost::shared_ptr< class Tool > ToolPtr