CustusX  18.04-rc1
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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
13 
14 #include <boost/bind.hpp>
15 
16 #include <QDir>
17 #include <QStackedWidget>
18 #include <QPushButton>
19 #include <QFileDialog>
20 
21 #include "vtkImageData.h"
22 
23 #include "cxTime.h"
24 #include "cxLogger.h"
25 #include "cxProbeSector.h"
27 #include "cxStringProperty.h"
28 #include "cxHelperWidgets.h"
29 #include "cxDataInterface.h"
30 #include "cxTrackingService.h"
31 #include "cxOptionsWidget.h"
32 #include "cxVideoService.h"
33 #include "cxPatientModelService.h"
35 #include "cxStreamerService.h"
36 #include "cxVideoSource.h"
37 #include "cxViewService.h"
38 #include "cxImage.h"
39 #include "cxProfile.h"
40 #include "cxHelperWidgets.h"
42 
43 namespace cx
44 {
45 
47  BaseWidget(parent, "igt_link_widget", "Video Connection"),
48  mServices(services)
49 {
50  this->setToolTip("Connect to a video source");
51  mOptions = profile()->getXmlSettings().descend("video");
52 
53  QString defaultConnection = mServices->video()->getConnectionMethod();
54  mConnectionSelector = StringProperty::initialize("Connection", "", "Method for connecting to Video Server", defaultConnection, QStringList(), mOptions.getElement("video"));
55  connect(mConnectionSelector.get(), SIGNAL(changed()), this, SLOT(selectGuiForConnectionMethodSlot()));
56 
58 
59  mStackedWidget = new QStackedWidget(this);
65 
66  mToptopLayout = new QVBoxLayout(this);
69  mToptopLayout->addWidget(mConnectButton);
72  mToptopLayout->addStretch();
73 
74  connect(mServices->video().get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
75  connect(mServices->video().get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
76 
77  this->addExistingStreamerServices(); //Need to add StreamerServices already existing at this point, since we will only get signals when new Services are added
78 
80 }
81 
83 {
84  if (mServices->video())
85  {
86  disconnect(mServices->video().get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
87  disconnect(mServices->video().get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
88  }
89 }
90 
91 void VideoConnectionWidget::addExistingStreamerServices()
92 {
93  QList<StreamerServicePtr> services = mServices->video()->getStreamerServices();
94  foreach(StreamerServicePtr service, services)
95  {
96  this->onServiceAdded(service.get());
97  }
98 }
99 
101 {
102  QWidget* widget = this->createStreamerWidget(service);
103  QWidget* serviceWidget = this->wrapVerticalStretch(widget);
104  mStackedWidget->addWidget(serviceWidget);
105  mStreamerServiceWidgets[service->getType()] = serviceWidget;
106 
107  this->addServiceToSelector(service);
108 }
109 
110 QWidget* VideoConnectionWidget::createStreamerWidget(StreamerService* service)
111 {
112 // QString serviceName = service->getName();
113  QDomElement element = mOptions.getElement("video");
114  std::vector<PropertyPtr> adapters = service->getSettings(element);
115 
116  OptionsWidget* widget = new OptionsWidget(mServices->view(), mServices->patient(), this);
117  widget->setOptions(service->getType(), adapters, false);
118  widget->setObjectName(service->getType());
119  widget->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
120 
121  connect(mConnectionSelectionWidget, SIGNAL(detailsTriggered()), widget, SLOT(toggleAdvanced()));
122 
123  return widget;
124 }
125 
127 {
128  this->removeServiceFromSelector(service);
129  this->removeServiceWidget(service->getType());
130 }
131 
132 void VideoConnectionWidget::addServiceToSelector(StreamerService *service)
133 {
134  QStringList range = mConnectionSelector->getValueRange();
135  std::map<QString, QString> display = mConnectionSelector->getDisplayNames();
136 
137  range.append(service->getType());
138  range.removeDuplicates();
139  display[service->getType()] = service->getName();
140 
141  mConnectionSelector->setValueRange(range);
142  mConnectionSelector->setDisplayNames(display);
143 }
144 
145 void VideoConnectionWidget::removeServiceFromSelector(StreamerService *service)
146 {
147  QStringList range = mConnectionSelector->getValueRange();
148 
149  int index = range.indexOf(service->getType());
150  if(mConnectionSelector->getValue() == service->getType())
151  mConnectionSelector->setValue(range[0]);
152  range.removeAt(index);
153  mConnectionSelector->setValueRange(range);
154 }
155 
156 void VideoConnectionWidget::removeServiceWidget(QString name)
157 {
158  QWidget* serviceWidget = mStreamerServiceWidgets[name];
159  mStackedWidget->removeWidget(serviceWidget);
160  delete serviceWidget;
161  mStreamerServiceWidgets.erase(name);
162 }
163 
165 {
167 }
168 
170 {
171  QFrame* frame = new QFrame(this);
172  frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
173  frame->setSizePolicy(frame->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
174  QVBoxLayout* frameLayout = new QVBoxLayout(frame);
175  frameLayout->addWidget(mStackedWidget);
176  frame->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
177 
178  return frame;
179 }
180 
182 {
183  QWidget* retval = new QWidget(this);
184  QVBoxLayout* layout = new QVBoxLayout(retval);
185  layout->addWidget(input);
186  retval->setObjectName(input->objectName()); // help propagation
187  layout->addStretch();
188  layout->setMargin(0);
189  layout->setSpacing(0);
190  return retval;
191 }
192 
194 {
195  QString name = mConnectionSelector->getValue();
196  //Need to set connection method in VideoConnectionManager before calling
197  //useDirectLink(), useLocalServer() and useRemoteServer()
198  mServices->video()->setConnectionMethod(name);
199 
200  QWidget* serviceWidget = mStreamerServiceWidgets[name];
201  if(serviceWidget)
202  {
203  mStackedWidget->setCurrentWidget(serviceWidget);
204  mStackedWidgetFrame->setObjectName(serviceWidget->objectName()); // for improved help
205  }
206 }
207 
209 {
210  if (mServices->video()->isConnected())
211  mServices->video()->closeConnection();
212  else
213  mServices->video()->openConnection();
214 }
215 
217 {
218  QPushButton* connectButton = new QPushButton("Connect", this);
219  connectButton->setToolTip("Connect/disconnect to the video server using the seleted method");
220  connect(connectButton, SIGNAL(clicked()), this, SLOT(toggleConnectServer()));
221  return connectButton;
222 }
223 
225 {
226  QPushButton* importstreamimagebutton = new QPushButton("Import image from stream", this);
227  importstreamimagebutton->setToolTip("Import a single image/volume from the real time stream");
228  importstreamimagebutton->setDisabled(true);
229  connect(importstreamimagebutton, SIGNAL(clicked()), this, SLOT(importStreamImageSlot()));
230 
231  return importstreamimagebutton;
232 }
233 
235 {
236  mImportStreamImageButton->setEnabled(mServices->video()->isConnected());
237  if (mServices->video()->isConnected())
238  mConnectButton->setText("Disconnect Server");
239  else
240  mConnectButton->setText("Connect Server");
241 
242  this->adjustSize();
243 }
244 
246 {
247  if (!mServices->video()->isConnected())
248  {
249  reportWarning("Video is not connected");
250  return;
251  }
252  Transform3D rMd = Transform3D::Identity();
253  ToolPtr probe = mServices->tracking()->getFirstProbe();
254  VideoSourcePtr videoSource;
255  if (probe)
256  {
257  videoSource = probe->getProbe()->getRTSource();
258  rMd = calculate_rMd_ForAProbeImage(probe);
259  }
260  else
261  videoSource = mServices->video()->getActiveVideoSource();
262 
263  if (!videoSource)
264  {
265  reportWarning("No Video data source");
266  return;
267  }
268  if (!videoSource->validData())
269  {
270  reportWarning("No valid video data");
271  return;
272  }
273 
274  vtkImageDataPtr input;
275  input = videoSource->getVtkImageData();
276  if (!input)
277  {
278  reportWarning("No Video data");
279  return;
280  }
281  QString filename = generateFilename(videoSource);
282 
283  this->saveAndImportSnapshot(input, filename, rMd);
284 
285 }
286 
288 {
289  Transform3D rMd = Transform3D::Identity();
290  Transform3D rMpr = mServices->patient()->get_rMpr();
291  Transform3D prMt = probe->get_prMt();
292  Transform3D tMu = probe->getProbe()->getSector()->get_tMu();
293  Transform3D uMv = probe->getProbe()->getSector()->get_uMv();
294  rMd = rMpr * prMt * tMu * uMv;
295  return rMd;
296 }
297 
299 {
300  vtkImageDataPtr input = videoSource->getVtkImageData();
301  int* extent = input->GetExtent();
302  QString filename;
303  QString format = timestampSecondsFormat();
304  if (extent[5] - extent[4] > 0)
305  filename = "3DRTSnapshot_";
306  else
307  filename = "2DRTSnapshot_";
308 
309  filename += videoSource->getName() + QDateTime::currentDateTime().toString(format);
310  return filename;
311 }
312 
314 {
315  vtkImageDataPtr copiedImage = vtkImageDataPtr::New();
316  copiedImage->DeepCopy(input);
317 
318  ImagePtr output = mServices->patient()->createSpecificData<Image>(filename);
319  output->setVtkImageData(copiedImage);
320  output->get_rMd_History()->setRegistration(rMd);
321  mServices->patient()->insertData(output);
322 
323  mServices->view()->autoShowData(output);
324  report(QString("Saved snapshot %1 from active video source").arg(output->getName()));
325 }
326 
327 } //end namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
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:40
virtual void setVtkImageData(const vtkImageDataPtr &data, bool resetTransferFunctions=true)
Definition: cxImage.cpp:268
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:27
QString timestampSecondsFormat()
Definition: cxTime.cpp:18
QDomElement getElement()
return the current element
void onServiceRemoved(StreamerService *service)
static StringPropertyActiveVideoSourcePtr create(VideoServicePtr service)
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
Composite widget for string selection with .
A volumetric data set.
Definition: cxImage.h:45
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:88
void saveAndImportSnapshot(vtkImageDataPtr input, QString filename, Transform3D rMd)
void report(QString msg)
Definition: cxLogger.cpp:69
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