CustusX  2023.01.05-dev+develop.0da12
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  mUpdateConnectionInService(true)
50 {
51  this->setToolTip("Connect to a video source");
52  mOptions = profile()->getXmlSettings().descend("video");
53 
54  QString defaultConnection = mServices->video()->getConnectionMethod();
55  mConnectionSelector = StringProperty::initialize("Connection", "", "Method for connecting to Video Server", defaultConnection, QStringList(), mOptions.getElement("video"));
56  connect(mConnectionSelector.get(), SIGNAL(changed()), this, SLOT(setConnectionMethodAndUpdateGuiForConnectionMethodSlot()));
57 
59 
60  mStackedWidget = new QStackedWidget(this);
66 
67  mToptopLayout = new QVBoxLayout(this);
70  mToptopLayout->addWidget(mConnectButton);
73  mToptopLayout->addStretch();
74 
75  connect(mServices->video().get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
76  connect(mServices->video().get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
78 
79  this->addExistingStreamerServices(); //Need to add StreamerServices already existing at this point, since we will only get signals when new Services are added
80 
82 }
83 
85 {
86  if (mServices->video())
87  {
88  disconnect(mServices->video().get(), SIGNAL(StreamerServiceAdded(StreamerService*)), this, SLOT(onServiceAdded(StreamerService*)));
89  disconnect(mServices->video().get(), SIGNAL(StreamerServiceRemoved(StreamerService*)), this, SLOT(onServiceRemoved(StreamerService*)));
91  }
92 }
93 
94 void VideoConnectionWidget::addExistingStreamerServices()
95 {
96  QList<StreamerServicePtr> services = mServices->video()->getStreamerServices();
97  foreach(StreamerServicePtr service, services)
98  {
99  this->onServiceAdded(service.get());
100  }
101 }
102 
104 {
105  QWidget* widget = this->createStreamerWidget(service);
106  QWidget* serviceWidget = this->wrapVerticalStretch(widget);
107  mStackedWidget->addWidget(serviceWidget);
108  mStreamerServiceWidgets[service->getType()] = serviceWidget;
109 
110  this->addServiceToSelector(service);
111 }
112 
113 QWidget* VideoConnectionWidget::createStreamerWidget(StreamerService* service)
114 {
115 // QString serviceName = service->getName();
116  QDomElement element = mOptions.getElement("video");
117  std::vector<PropertyPtr> adapters = service->getSettings(element);
118 
119  OptionsWidget* widget = new OptionsWidget(mServices->view(), mServices->patient(), this);
120  widget->setOptions(service->getType(), adapters, false);
121  widget->setObjectName(service->getType());
122  widget->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
123 
124  connect(mConnectionSelectionWidget, SIGNAL(detailsTriggered()), widget, SLOT(toggleAdvanced()));
125 
126  return widget;
127 }
128 
130 {
131  this->removeServiceFromSelector(service);
132  this->removeServiceWidget(service->getType());
133 }
134 
135 void VideoConnectionWidget::addServiceToSelector(StreamerService *service)
136 {
137  QStringList range = mConnectionSelector->getValueRange();
138  std::map<QString, QString> display = mConnectionSelector->getDisplayNames();
139 
140  range.append(service->getType());
141  range.removeDuplicates();
142  display[service->getType()] = service->getName();
143 
144  mConnectionSelector->setValueRange(range);
145  mConnectionSelector->setDisplayNames(display);
146 }
147 
148 void VideoConnectionWidget::removeServiceFromSelector(StreamerService *service)
149 {
150  QStringList range = mConnectionSelector->getValueRange();
151 
152  int index = range.indexOf(service->getType());
153  if(mConnectionSelector->getValue() == service->getType())
154  mConnectionSelector->setValue(range[0]);
155  range.removeAt(index);
156  mConnectionSelector->setValueRange(range);
157 }
158 
159 void VideoConnectionWidget::removeServiceWidget(QString name)
160 {
161  QWidget* serviceWidget = mStreamerServiceWidgets[name];
162  mStackedWidget->removeWidget(serviceWidget);
163  delete serviceWidget;
164  mStreamerServiceWidgets.erase(name);
165 }
166 
168 {
170 }
171 
173 {
174  QFrame* frame = new QFrame(this);
175  frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
176  frame->setSizePolicy(frame->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
177  QVBoxLayout* frameLayout = new QVBoxLayout(frame);
178  frameLayout->addWidget(mStackedWidget);
179  frame->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
180 
181  return frame;
182 }
183 
185 {
186  QWidget* retval = new QWidget(this);
187  QVBoxLayout* layout = new QVBoxLayout(retval);
188  layout->addWidget(input);
189  retval->setObjectName(input->objectName()); // help propagation
190  layout->addStretch();
191  layout->setMargin(0);
192  layout->setSpacing(0);
193  return retval;
194 }
195 
197 {
198  QString name = mConnectionSelector->getValue();
199  //Need to set connection method in VideoConnectionManager before calling
200  //useDirectLink(), useLocalServer() and useRemoteServer()
201  if(mUpdateConnectionInService)
202  mServices->video()->setConnectionMethod(name);
203  mUpdateConnectionInService = true;
204 
205  QWidget* serviceWidget = mStreamerServiceWidgets[name];
206  if(serviceWidget)
207  {
208  mStackedWidget->setCurrentWidget(serviceWidget);
209  mStackedWidgetFrame->setObjectName(serviceWidget->objectName()); // for improved help
210  }
211 }
212 
214 {
215  QString changedConnectionMethod = mServices->video()->getConnectionMethod();
216 
217  this->mUpdateConnectionInService = false;//Prevent infinite signal loop
218  mConnectionSelector->setValue(changedConnectionMethod);
219 }
220 
222 {
223  if (mServices->video()->isConnected())
224  mServices->video()->closeConnection();
225  else
226  mServices->video()->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->video()->isConnected());
250  if (mServices->video()->isConnected())
251  mConnectButton->setText("Disconnect Server");
252  else
253  mConnectButton->setText("Connect Server");
254 
255  this->adjustSize();
256 }
257 
259 {
260  if (!mServices->video()->isConnected())
261  {
262  reportWarning("Video is not connected");
263  return;
264  }
265  Transform3D rMd = Transform3D::Identity();
266  ToolPtr probe = mServices->tracking()->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->video()->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->patient()->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->patient()->createSpecificData<Image>(filename);
332  output->setVtkImageData(copiedImage);
333  output->get_rMd_History()->setRegistration(rMd);
334  mServices->patient()->insertData(output);
335 
336  mServices->view()->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: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)
void connectionMethodChanged()
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