CustusX  15.3.4-beta
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxProbeConfigWidget.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 
33 #include <cxProbeConfigWidget.h>
34 #include <QGroupBox>
35 #include <QInputDialog>
36 #include <QMessageBox>
37 #include <QCheckBox>
39 #include "cxDoubleWidgets.h"
40 #include "cxToolProperty.h"
41 #include "cxVector3DWidget.h"
42 #include "cxDoubleSpanSlider.h"
43 #include "cxHelperWidgets.h"
44 #include "cxTypeConversions.h"
45 #include "cxDoublePairProperty.h"
46 #include "cxVisServices.h"
47 
48 namespace cx
49 {
50 
51 ProbeConfigWidget::ProbeConfigWidget(VisServicesPtr services, QWidget* parent) : BaseWidget(parent, "ProbeConfigWidget", "Probe Configuration")
52 {
53  mServices = services;
54  mUpdating = false;
55  this->setToolTip(this->defaultWhatsThis());
56 
57  QVBoxLayout* topLayout = new QVBoxLayout(this);
58  TrackingServicePtr ts = mServices->getToolManager();
59  mActiveProbeConfig = StringPropertyActiveProbeConfiguration::New(ts);
60  connect(mActiveProbeConfig.get(), SIGNAL(changed()), this, SLOT(activeProbeConfigurationChangedSlot()));
61  mActiveProbeConfigWidget = new LabeledComboBoxWidget(this, mActiveProbeConfig);
62  topLayout->addWidget(mActiveProbeConfigWidget);
63 
64  mOrigin = Vector3DProperty::initialize("Origin",
65  "Origin",
66  "Origin of tool space in the probe image.\nUnits in pixels.",
67  Vector3D(0,0,0),
68  DoubleRange(-1000,1000,1),
69  1,
70  QDomNode());
71  connect(mOrigin.get(), SIGNAL(changed()), this, SLOT(guiOriginSettingsChanged()));
72 
73  // define origin group
74  Vector3DWidget* mOriginWidget = Vector3DWidget::createSmallHorizontal(this, mOrigin);
75  mOriginWidget->showDim(2, false);
76 
77  // define cropping group
78  QGroupBox* cropGroupBox = new QGroupBox("Crop Box");
79  cropGroupBox->setToolTip("Define cropping box for the probe image.\nUnits in pixels.");
80  QVBoxLayout* cropLayout = new QVBoxLayout(cropGroupBox);
81  topLayout->addWidget(cropGroupBox);
82 
83  mBBWidget = new BoundingBoxWidget(this);
84  mBBWidget->showDim(2, false);
85  cropLayout->addWidget(mBBWidget);
86  connect(mBBWidget, SIGNAL(changed()), this, SLOT(guiImageSettingsChanged()));
87 
88  // create sector group
89  QGroupBox* sectorGroupBox = new QGroupBox("Sector");
90  sectorGroupBox->setToolTip("Define probe sector parameters.\nUnits in pixels and degrees.");
91  QVBoxLayout* sectorLayout = new QVBoxLayout(sectorGroupBox);
92  topLayout->addWidget(sectorGroupBox);
93 
94  sectorLayout->addWidget(mOriginWidget);
95  DoublePairPropertyPtr depthProperty = DoublePairProperty::initialize("Depth", "Depth", "Define probe depth.\nUnits in pixels.", DoubleRange(0, 1000, 1), 1);
96  mDepthWidget = new SliderRangeGroupWidget(this, depthProperty);
97  connect(mDepthWidget, SIGNAL(valueChanged(double, double)), this, SLOT(guiProbeSectorChanged()));
98  sectorLayout->addWidget(mDepthWidget);
99 
100  mWidth = DoubleProperty::initialize("width", "Width", "Width of probe sector", 0,
101  DoubleRange(0, M_PI, M_PI/180), 0);
102  mWidth->setInternal2Display(180.0/M_PI);
103  connect(mWidth.get(), SIGNAL(changed()), this, SLOT(guiProbeSectorChanged()));
104  sectorLayout->addWidget(new SpinBoxAndSliderGroupWidget(this, mWidth, 0, 0));
105 
106  // create buttons bar
107  QHBoxLayout* buttonsLayout = new QHBoxLayout;
108  topLayout->addLayout(buttonsLayout);
109 
110  mSyncBoxToSector = new QCheckBox("Sync Box to Sector", this);
111  mSyncBoxToSector->setChecked(true);
112  mSyncBoxToSector->setToolTip(""
113  "Synchronize Crop Box to Probe Sector,\n"
114  "changes in the sector will reset the crop box.");
115  connect(mSyncBoxToSector, SIGNAL(toggled(bool)), this, SLOT(syncBoxToSectorChanged()));
116  buttonsLayout->addWidget(mSyncBoxToSector);
117 
118  buttonsLayout->addStretch();
119  this->createAction(this,
120  QIcon(":/icons/preset_remove.png"),
121  "Delete the current probe config", "",
122  SLOT(deletePresetSlot()),
123  buttonsLayout);
124 
125  this->createAction(this,
126  QIcon(":/icons/preset_save.png"),
127  "Add the current setting as a probe config", "",
128  SLOT(savePresetSlot()),
129  buttonsLayout);
130 
131  topLayout->addStretch();
132 }
133 
135 {
136 }
137 
138 void ProbeConfigWidget::syncBoxToSectorChanged()
139 {
140 
141 }
142 
143 QString ProbeConfigWidget::defaultWhatsThis() const
144 {
145  return "<html>"
146  "<h3>Probe Configuration</h3>"
147  "<p>"
148  "View and edit the probe configuration. "
149  "Use the origin to define the position of the probe image in relation "
150  "to the tool t space. Set the cropping box and the probe sector parameters "
151  "(depth and width). All can be written back to the ProbeCalibConfigs.xml file."
152  "</p>"
153  "</html>";
154 }
155 
156 void ProbeConfigWidget::savePresetSlot()
157 {
158  if (!mActiveProbeConfig->getTool())
159  return;
160  ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
161 // ProbeImplPtr probe = boost::dynamic_pointer_cast<ProbeImpl>(mActiveProbeConfig->getTool()->getProbe());
162  if (!probe)
163  return;
164 
165  // use the previously selected config as a suggestion for new config name.
166  QString oldname = probe->getConfigName(probe->getConfigId());
167  if (oldname.isEmpty())
168  oldname = mLastKnownProbeConfigName;
169 
170  QString newName = QString("%1 (2)").arg(oldname);
171 
172  bool ok;
173  newName = QInputDialog::getText(this, "Save Config",
174  "Config Name", QLineEdit::Normal,
175  newName, &ok);
176  if (!ok || newName.isEmpty())
177  return;
178 
179  QStringList existingConfigs = probe->getConfigIdList();
180  QString newUid;
181 
182  // is name exists: overwrite.
183  for (int i=0; i<existingConfigs.size(); ++i)
184  {
185  if (newName==probe->getConfigName(existingConfigs[i]))
186  {
187  newUid = existingConfigs[i];
188  }
189  }
190 
191  if (newUid.isEmpty())
192  {
193  newUid = newName;
194 // Width: Max, Depth: 45 mm
195  newUid.remove(QRegExp("(:|\\s|\\(|\\)|,)")); // remove fancy characters from uid
196  QString root = newUid;
197  int i=2;
198  while (existingConfigs.contains(newUid))
199  {
200  newUid = QString("%1_%2").arg(root).arg(i++);
201  }
202  }
203 
204  probe->saveCurrentConfig(newUid, newName);
205 }
206 
207 void ProbeConfigWidget::deletePresetSlot()
208 {
209  ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
210 // ProbeImplPtr probe = boost::dynamic_pointer_cast<ProbeImpl>(mActiveProbeConfig->getTool()->getProbe());
211  if (!probe)
212  return;
213 
214  QString message = QString("Do you really want to delete configuration\n%1?").arg(probe->getConfigName(probe->getConfigId()));
215  if (QMessageBox::warning(this,
216  "Delete Config",
217  message,
218  QMessageBox::No | QMessageBox::Yes) != QMessageBox::Yes)
219  {
220  return;
221  }
222 
223  probe->removeCurrentConfig();
224 }
225 
226 
227 void ProbeConfigWidget::activeProbeConfigurationChangedSlot()
228 {
229  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
230  if (!probe)
231  return;
232  ProbeDefinition data = probe->getProbeData();
233  mUpdating= true;
234 
235  DoubleBoundingBox3D range(0, data.getSize().width(), 0, data.getSize().height());
236  mBBWidget->setValue(data.getClipRect_p(), range);
237 
238  mOrigin->setValue(data.getOrigin_p());
239 
240  double sx = data.getSpacing()[0]; // mm/pix
241  double sy = data.getSpacing()[1];
242 
243  mDepthWidget->setValue(data.getDepthStart()/sy, data.getDepthEnd()/sy);
244  mDepthWidget->setRange(DoubleRange(0, range.range()[1]*1.5, 1));
245 
246  mWidth->setValue(data.getWidth());
247 
248  if (data.getType()== ProbeDefinition::tLINEAR)
249  {
250  mWidth->setValueRange(DoubleRange(0, range.range()[0]*1.5*sx, 1.0*sx));
251  mWidth->setInternal2Display(1.0/sx);
252  }
253  if (data.getType()== ProbeDefinition::tSECTOR)
254  {
255  mWidth->setValueRange(DoubleRange(0, M_PI, M_PI/180));
256  mWidth->setInternal2Display(180.0/M_PI);
257  }
258 
259  if (!probe->getConfigId().isEmpty())
260  {
261  mLastKnownProbeConfigName = probe->getConfigName(probe->getConfigId());
262  }
263  mUpdating= false;
264 }
265 
266 
267 void ProbeConfigWidget::guiProbeSectorChanged()
268 {
269  if (mUpdating)
270  return;
271  if(!mActiveProbeConfig->getTool())
272  return;
273  // need a cx probe here, in order to set data.
274  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
275  if (!probe)
276  return;
277  ProbeDefinition data = probe->getProbeData();
278 
279 // double sx = data.getSpacing()[0]; // mm/pix
280  double sy = data.getSpacing()[1];
281 
282  data.setSector(mDepthWidget->getValue().first*sy, mDepthWidget->getValue().second*sy, mWidth->getValue());
283 
284  if (mSyncBoxToSector->isChecked())
285  data.updateClipRectFromSector();
286 
287  probe->setProbeSector(data);
288 }
289 
290 void ProbeConfigWidget::guiImageSettingsChanged()
291 {
292  if (mUpdating)
293  return;
294  // need a cx probe here, in order to set data.
295  if (!mActiveProbeConfig->getTool())
296  return;
297  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
298  if (!probe)
299  return;
300  ProbeDefinition data = probe->getProbeData();
301 
302  data.setClipRect_p(mBBWidget->getValue());
303 
304  probe->setProbeSector(data);
305 }
306 
307 void ProbeConfigWidget::guiOriginSettingsChanged()
308 {
309  if (mUpdating)
310  return;
311  // need a cx probe here, in order to set data.
312  if (!mActiveProbeConfig->getTool())
313  return;
314  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
315  if (!probe)
316  return;
317  ProbeDefinition data = probe->getProbeData();
318 
319  // if sync: move clip rect accordingly
320  if (mSyncBoxToSector->isChecked())
321  {
322  // shift
323  Vector3D shift = mOrigin->getValue() - data.getOrigin_p();
324  data.setClipRect_p(transform(createTransformTranslate(shift), data.getClipRect_p()));
325  }
326 
327  data.setOrigin_p(mOrigin->getValue());
328 
329  probe->setProbeSector(data);
330 }
331 
332 
333 
334 }
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
bool setValue(double lower, double upper)
Widget for displaying a Vector3D.
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:61
boost::shared_ptr< class TrackingService > TrackingServicePtr
US beam is emitted straight forward.
Definition: cxProbeData.h:123
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:53
void setRange(const DoubleRange &range)
Widget displays/edits a BoundingBox3D.
static StringPropertyActiveProbeConfigurationPtr New(TrackingServicePtr trackingService)
Composite widget for string selection.
QAction * createAction(QObject *parent, QIcon iconName, QString text, QString tip, T slot, QLayout *layout=NULL, QToolButton *button=new QToolButton())
Definition: cxBaseWidget.h:130
boost::shared_ptr< Probe > ProbePtr
Definition: cxProbe.h:93
Composite widget for scalar data manipulation.
std::pair< double, double > getValue() const
US beam is emitted radially in a flat cone.
Definition: cxProbeData.h:122
static Vector3DWidget * createSmallHorizontal(QWidget *parent, Vector3DPropertyBasePtr data)
static Vector3DPropertyPtr initialize(const QString &uid, QString name, QString help, Vector3D value, DoubleRange range, int decimals, QDomNode root=QDomNode())
DoubleBoundingBox3D getValue() const
Transform3D createTransformTranslate(const Vector3D &translation)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:108
boost::shared_ptr< class DoublePairProperty > DoublePairPropertyPtr
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
void setValue(const DoubleBoundingBox3D &value, const DoubleBoundingBox3D &range)
void showDim(int dim, bool visible)
static DoublePairPropertyPtr initialize(const QString &uid, QString name, QString help, DoubleRange range, int decimals, QDomNode root=QDomNode())
#define M_PI
ProbeConfigWidget(VisServicesPtr services, QWidget *parent=NULL)