Fraxinus  17.12-rc3
An IGT application
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 #include "cxHelperWidgets.h"
63 
64 namespace cx
65 {
66 
68  BaseWidget(parent, "igt_link_widget", "Video Connection"),
69  mServices(services)
70 {
71  this->setToolTip("Connect to a video source");
72  mOptions = profile()->getXmlSettings().descend("video");
73 
74  QString defaultConnection = mServices->video()->getConnectionMethod();
75  mConnectionSelector = StringProperty::initialize("Connection", "", "Method for connecting to Video Server", defaultConnection, QStringList(), mOptions.getElement("video"));
76  connect(mConnectionSelector.get(), SIGNAL(changed()), this, SLOT(selectGuiForConnectionMethodSlot()));
77 
79 
80  mStackedWidget = new QStackedWidget(this);
86 
87  mToptopLayout = new QVBoxLayout(this);
90  mToptopLayout->addWidget(mConnectButton);
93  mToptopLayout->addStretch();
94 
95  connect(mServices->video().get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
96  connect(mServices->video().get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
97 
98  this->addExistingStreamerServices(); //Need to add StreamerServices already existing at this point, since we will only get signals when new Services are added
99 
101 }
102 
104 {
105  if (mServices->video())
106  {
107  disconnect(mServices->video().get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
108  disconnect(mServices->video().get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
109  }
110 }
111 
112 void VideoConnectionWidget::addExistingStreamerServices()
113 {
114  QList<StreamerServicePtr> services = mServices->video()->getStreamerServices();
115  foreach(StreamerServicePtr service, services)
116  {
117  this->onServiceAdded(service.get());
118  }
119 }
120 
122 {
123  QWidget* widget = this->createStreamerWidget(service);
124  QWidget* serviceWidget = this->wrapVerticalStretch(widget);
125  mStackedWidget->addWidget(serviceWidget);
126  mStreamerServiceWidgets[service->getType()] = serviceWidget;
127 
128  this->addServiceToSelector(service);
129 }
130 
131 QWidget* VideoConnectionWidget::createStreamerWidget(StreamerService* service)
132 {
133 // QString serviceName = service->getName();
134  QDomElement element = mOptions.getElement("video");
135  std::vector<PropertyPtr> adapters = service->getSettings(element);
136 
137  OptionsWidget* widget = new OptionsWidget(mServices->view(), mServices->patient(), this);
138  widget->setOptions(service->getType(), adapters, false);
139  widget->setObjectName(service->getType());
140  widget->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
141 
142  connect(mConnectionSelectionWidget, SIGNAL(detailsTriggered()), widget, SLOT(toggleAdvanced()));
143 
144  return widget;
145 }
146 
148 {
149  this->removeServiceFromSelector(service);
150  this->removeServiceWidget(service->getType());
151 }
152 
153 void VideoConnectionWidget::addServiceToSelector(StreamerService *service)
154 {
155  QStringList range = mConnectionSelector->getValueRange();
156  std::map<QString, QString> display = mConnectionSelector->getDisplayNames();
157 
158  range.append(service->getType());
159  range.removeDuplicates();
160  display[service->getType()] = service->getName();
161 
162  mConnectionSelector->setValueRange(range);
163  mConnectionSelector->setDisplayNames(display);
164 }
165 
166 void VideoConnectionWidget::removeServiceFromSelector(StreamerService *service)
167 {
168  QStringList range = mConnectionSelector->getValueRange();
169 
170  int index = range.indexOf(service->getType());
171  if(mConnectionSelector->getValue() == service->getType())
172  mConnectionSelector->setValue(range[0]);
173  range.removeAt(index);
174  mConnectionSelector->setValueRange(range);
175 }
176 
177 void VideoConnectionWidget::removeServiceWidget(QString name)
178 {
179  QWidget* serviceWidget = mStreamerServiceWidgets[name];
180  mStackedWidget->removeWidget(serviceWidget);
181  delete serviceWidget;
182  mStreamerServiceWidgets.erase(name);
183 }
184 
186 {
188 }
189 
191 {
192  QFrame* frame = new QFrame(this);
193  frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
194  frame->setSizePolicy(frame->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
195  QVBoxLayout* frameLayout = new QVBoxLayout(frame);
196  frameLayout->addWidget(mStackedWidget);
197  frame->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
198 
199  return frame;
200 }
201 
203 {
204  QWidget* retval = new QWidget(this);
205  QVBoxLayout* layout = new QVBoxLayout(retval);
206  layout->addWidget(input);
207  retval->setObjectName(input->objectName()); // help propagation
208  layout->addStretch();
209  layout->setMargin(0);
210  layout->setSpacing(0);
211  return retval;
212 }
213 
215 {
216  QString name = mConnectionSelector->getValue();
217  //Need to set connection method in VideoConnectionManager before calling
218  //useDirectLink(), useLocalServer() and useRemoteServer()
219  mServices->video()->setConnectionMethod(name);
220 
221  QWidget* serviceWidget = mStreamerServiceWidgets[name];
222  if(serviceWidget)
223  {
224  mStackedWidget->setCurrentWidget(serviceWidget);
225  mStackedWidgetFrame->setObjectName(serviceWidget->objectName()); // for improved help
226  }
227 }
228 
230 {
231  if (mServices->video()->isConnected())
232  mServices->video()->closeConnection();
233  else
234  mServices->video()->openConnection();
235 }
236 
238 {
239  QPushButton* connectButton = new QPushButton("Connect", this);
240  connectButton->setToolTip("Connect/disconnect to the video server using the seleted method");
241  connect(connectButton, SIGNAL(clicked()), this, SLOT(toggleConnectServer()));
242  return connectButton;
243 }
244 
246 {
247  QPushButton* importstreamimagebutton = new QPushButton("Import image from stream", this);
248  importstreamimagebutton->setToolTip("Import a single image/volume from the real time stream");
249  importstreamimagebutton->setDisabled(true);
250  connect(importstreamimagebutton, SIGNAL(clicked()), this, SLOT(importStreamImageSlot()));
251 
252  return importstreamimagebutton;
253 }
254 
256 {
257  mImportStreamImageButton->setEnabled(mServices->video()->isConnected());
258  if (mServices->video()->isConnected())
259  mConnectButton->setText("Disconnect Server");
260  else
261  mConnectButton->setText("Connect Server");
262 
263  this->adjustSize();
264 }
265 
267 {
268  if (!mServices->video()->isConnected())
269  {
270  reportWarning("Video is not connected");
271  return;
272  }
273  Transform3D rMd = Transform3D::Identity();
274  ToolPtr probe = mServices->tracking()->getFirstProbe();
275  VideoSourcePtr videoSource;
276  if (probe)
277  {
278  videoSource = probe->getProbe()->getRTSource();
279  rMd = calculate_rMd_ForAProbeImage(probe);
280  }
281  else
282  videoSource = mServices->video()->getActiveVideoSource();
283 
284  if (!videoSource)
285  {
286  reportWarning("No Video data source");
287  return;
288  }
289  if (!videoSource->validData())
290  {
291  reportWarning("No valid video data");
292  return;
293  }
294 
295  vtkImageDataPtr input;
296  input = videoSource->getVtkImageData();
297  if (!input)
298  {
299  reportWarning("No Video data");
300  return;
301  }
302  QString filename = generateFilename(videoSource);
303 
304  this->saveAndImportSnapshot(input, filename, rMd);
305 
306 }
307 
309 {
310  Transform3D rMd = Transform3D::Identity();
311  Transform3D rMpr = mServices->patient()->get_rMpr();
312  Transform3D prMt = probe->get_prMt();
313  Transform3D tMu = probe->getProbe()->getSector()->get_tMu();
314  Transform3D uMv = probe->getProbe()->getSector()->get_uMv();
315  rMd = rMpr * prMt * tMu * uMv;
316  return rMd;
317 }
318 
320 {
321  vtkImageDataPtr input = videoSource->getVtkImageData();
322  int* extent = input->GetExtent();
323  QString filename;
324  QString format = timestampSecondsFormat();
325  if (extent[5] - extent[4] > 0)
326  filename = "3DRTSnapshot_";
327  else
328  filename = "2DRTSnapshot_";
329 
330  filename += videoSource->getName() + QDateTime::currentDateTime().toString(format);
331  return filename;
332 }
333 
335 {
336  vtkImageDataPtr copiedImage = vtkImageDataPtr::New();
337  copiedImage->DeepCopy(input);
338 
339  ImagePtr output = mServices->patient()->createSpecificData<Image>(filename);
340  output->setVtkImageData(copiedImage);
341  output->get_rMd_History()->setRegistration(rMd);
342  mServices->patient()->insertData(output);
343 
344  mServices->view()->autoShowData(output);
345  report(QString("Saved snapshot %1 from active video source").arg(output->getName()));
346 }
347 
348 } //end namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:181
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:289
virtual std::vector< PropertyPtr > getSettings(QDomElement root)=0
virtual QString getType() const =0
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
QString timestampSecondsFormat()
Definition: cxTime.cpp:39
QDomElement getElement()
return the current element
void onServiceRemoved(StreamerService *service)
static StringPropertyActiveVideoSourcePtr create(VideoServicePtr service)
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
Composite widget for string selection with .
A volumetric data set.
Definition: cxImage.h:66
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())
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:109
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.
boost::shared_ptr< class StreamerService > StreamerServicePtr
StringPropertyActiveVideoSourcePtr initializeActiveVideoSourceSelector()
Abstract class. Interface to Streamers.
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
void setOptions(QString uid, std::vector< PropertyPtr > options, bool showAdvanced)
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr