CustusX  2023.01.05-dev+develop.0da12
An IGT application
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) 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 
12 #include <cxProbeConfigWidget.h>
13 #include <QGroupBox>
14 #include <QInputDialog>
15 #include <QMessageBox>
16 #include <QCheckBox>
18 #include "cxDoubleWidgets.h"
19 #include "cxToolProperty.h"
20 #include "cxVector3DWidget.h"
21 #include "cxDoubleSpanSlider.h"
22 #include "cxHelperWidgets.h"
23 #include "cxTypeConversions.h"
24 #include "cxDoublePairProperty.h"
25 #include "cxVisServices.h"
26 
27 namespace cx
28 {
29 
30 ProbeConfigWidget::ProbeConfigWidget(VisServicesPtr services, QWidget* parent) : BaseWidget(parent, "probe_config_widget", "Probe Configuration")
31 {
32  mServices = services;
33  mUpdating = false;
34  this->setToolTip("Edit ultrasound probe configuration");
35 
36  QVBoxLayout* topLayout = new QVBoxLayout(this);
37  TrackingServicePtr ts = mServices->tracking();
38  mActiveProbeConfig = StringPropertyActiveProbeConfiguration::New(ts);
39  connect(mActiveProbeConfig.get(), &StringPropertyActiveProbeConfiguration::changed, this, &ProbeConfigWidget::activeProbeConfigurationChangedSlot);
40  mActiveProbeConfigWidget = new LabeledComboBoxWidget(this, mActiveProbeConfig);
41  topLayout->addWidget(mActiveProbeConfigWidget);
42 
43  mOrigin = Vector3DProperty::initialize("Origin",
44  "Origin",
45  "Origin of tool space in the probe image.\nUnits in pixels.",
46  Vector3D(0,0,0),
47  DoubleRange(-1000,1000,1),
48  1,
49  QDomNode());
50  connect(mOrigin.get(), SIGNAL(changed()), this, SLOT(guiOriginSettingsChanged()));
51 
52  // define origin group
53  Vector3DWidget* mOriginWidget = Vector3DWidget::createSmallHorizontal(this, mOrigin);
54  mOriginWidget->showDim(2, false);
55 
56  // define cropping group
57  QGroupBox* cropGroupBox = new QGroupBox("Crop Box", this);
58  cropGroupBox->setToolTip("Define cropping box for the probe image.\nUnits in pixels.");
59  QVBoxLayout* cropLayout = new QVBoxLayout(cropGroupBox);
60  topLayout->addWidget(cropGroupBox);
61 
62  QStringList bbCaptions = QStringList() << "X (pixels)" << "Y (pixels)";
63  mBBWidget = new BoundingBoxWidget(this, bbCaptions);
64  cropLayout->addWidget(mBBWidget);
65  connect(mBBWidget, &BoundingBoxWidget::changed, this, &ProbeConfigWidget::guiImageSettingsChanged);
66 
67  // create sector group
68  QGroupBox* sectorGroupBox = new QGroupBox("Sector");
69  sectorGroupBox->setToolTip("Define probe sector parameters.\nUnits in pixels and degrees.");
70  QVBoxLayout* sectorLayout = new QVBoxLayout(sectorGroupBox);
71  topLayout->addWidget(sectorGroupBox);
72 
73  sectorLayout->addWidget(mOriginWidget);
74  DoublePairPropertyPtr depthProperty = DoublePairProperty::initialize("Depth", "Depth", "Define probe depth.\nUnits in pixels.", DoubleRange(0, 1000, 1), 1);
75  mDepthWidget = new SliderRangeGroupWidget(this, depthProperty);
76  connect(mDepthWidget, SIGNAL(valueChanged(double, double)), this, SLOT(guiProbeSectorChanged()));
77  sectorLayout->addWidget(mDepthWidget);
78 
79  mWidth = DoubleProperty::initialize("width", "Width", "Width of probe sector", 0,
80  DoubleRange(0, M_PI, M_PI/180), 0);
81  mWidth->setInternal2Display(180.0/M_PI);
82  connect(mWidth.get(), SIGNAL(changed()), this, SLOT(guiProbeSectorChanged()));
83  sectorLayout->addWidget(new SpinBoxAndSliderGroupWidget(this, mWidth, 0, 0));
84 
85  // create buttons bar
86  QHBoxLayout* buttonsLayout = new QHBoxLayout;
87  topLayout->addLayout(buttonsLayout);
88 
89  mSyncBoxToSector = new QCheckBox("Sync Box to Sector", this);
90  mSyncBoxToSector->setChecked(true);
91  mSyncBoxToSector->setToolTip(""
92  "Synchronize Crop Box to Probe Sector,\n"
93  "changes in the sector will reset the crop box.");
94  connect(mSyncBoxToSector, SIGNAL(toggled(bool)), this, SLOT(syncBoxToSectorChanged()));
95  buttonsLayout->addWidget(mSyncBoxToSector);
96 
97  buttonsLayout->addStretch();
98  this->createAction(this,
99  QIcon(":/icons/preset_remove.png"),
100  "Delete the current probe config", "",
101  SLOT(deletePresetSlot()),
102  buttonsLayout);
103 
104  this->createAction(this,
105  QIcon(":/icons/preset_save.png"),
106  "Add the current setting as a probe config", "",
107  SLOT(savePresetSlot()),
108  buttonsLayout);
109 
110  topLayout->addStretch();
111 }
112 
114 {
115 }
116 
117 void ProbeConfigWidget::syncBoxToSectorChanged()
118 {
119 
120 }
121 
122 void ProbeConfigWidget::savePresetSlot()
123 {
124  if (!mActiveProbeConfig->getTool())
125  return;
126  ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
127 // ProbeImplPtr probe = boost::dynamic_pointer_cast<ProbeImpl>(mActiveProbeConfig->getTool()->getProbe());
128  if (!probe)
129  return;
130 
131  // use the previously selected config as a suggestion for new config name.
132  QString oldname = probe->getConfigName(probe->getConfigId());
133  if (oldname.isEmpty())
134  oldname = mLastKnownProbeConfigName;
135 
136  QString newName = QString("%1 (2)").arg(oldname);
137 
138  bool ok;
139  newName = QInputDialog::getText(this, "Save Config",
140  "Config Name", QLineEdit::Normal,
141  newName, &ok);
142  if (!ok || newName.isEmpty())
143  return;
144 
145  QStringList existingConfigs = probe->getConfigIdList();
146  QString newUid;
147 
148  // is name exists: overwrite.
149  for (int i=0; i<existingConfigs.size(); ++i)
150  {
151  if (newName==probe->getConfigName(existingConfigs[i]))
152  {
153  newUid = existingConfigs[i];
154  }
155  }
156 
157  if (newUid.isEmpty())
158  {
159  newUid = newName;
160 // Width: Max, Depth: 45 mm
161  newUid.remove(QRegExp("(:|\\s|\\(|\\)|,)")); // remove fancy characters from uid
162  QString root = newUid;
163  int i=2;
164  while (existingConfigs.contains(newUid))
165  {
166  newUid = QString("%1_%2").arg(root).arg(i++);
167  }
168  }
169 
170  probe->saveCurrentConfig(newUid, newName);
171 }
172 
173 void ProbeConfigWidget::deletePresetSlot()
174 {
175  ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
176 // ProbeImplPtr probe = boost::dynamic_pointer_cast<ProbeImpl>(mActiveProbeConfig->getTool()->getProbe());
177  if (!probe)
178  return;
179 
180  QString message = QString("Do you really want to delete configuration\n%1?").arg(probe->getConfigName(probe->getConfigId()));
181  if (QMessageBox::warning(this,
182  "Delete Config",
183  message,
184  QMessageBox::No | QMessageBox::Yes) != QMessageBox::Yes)
185  {
186  return;
187  }
188 
189  probe->removeCurrentConfig();
190 }
191 
192 
193 void ProbeConfigWidget::activeProbeConfigurationChangedSlot()
194 {
195  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
196  if (!probe)
197  return;
198  ProbeDefinition data = probe->getProbeDefinition();
199  mUpdating= true;
200 
201  DoubleBoundingBox3D range(0, data.getSize().width(), 0, data.getSize().height());
202  mBBWidget->setValue(data.getClipRect_p(), range);
203 
204  mOrigin->setValue(data.getOrigin_p());
205 
206  double sx = data.getSpacing()[0]; // mm/pix
207  double sy = data.getSpacing()[1];
208 
209  mDepthWidget->setValue(data.getDepthStart()/sy, data.getDepthEnd()/sy);
210  mDepthWidget->setRange(DoubleRange(0, range.range()[1]*1.5, 1));
211 
212  mWidth->setValue(data.getWidth());
213 
214  if (data.getType()== ProbeDefinition::tLINEAR)
215  {
216  mWidth->setValueRange(DoubleRange(0, range.range()[0]*1.5*sx, 1.0*sx));
217  mWidth->setInternal2Display(1.0/sx);
218  }
219  if (data.getType()== ProbeDefinition::tSECTOR)
220  {
221  mWidth->setValueRange(DoubleRange(0, M_PI, M_PI/180));
222  mWidth->setInternal2Display(180.0/M_PI);
223  }
224 
225  if (!probe->getConfigId().isEmpty())
226  {
227  mLastKnownProbeConfigName = probe->getConfigName(probe->getConfigId());
228  }
229  mUpdating= false;
230 }
231 
232 
233 void ProbeConfigWidget::guiProbeSectorChanged()
234 {
235  if (mUpdating)
236  return;
237  if(!mActiveProbeConfig->getTool())
238  return;
239  // need a cx probe here, in order to set data.
240  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
241  if (!probe)
242  return;
243  ProbeDefinition data = probe->getProbeDefinition();
244 
245 // double sx = data.getSpacing()[0]; // mm/pix
246  double sy = data.getSpacing()[1];
247 
248  data.setSector(mDepthWidget->getValue().first*sy, mDepthWidget->getValue().second*sy, mWidth->getValue());
249 
250  if (mSyncBoxToSector->isChecked())
252 
253  probe->setProbeDefinition(data);
254 }
255 
256 void ProbeConfigWidget::guiImageSettingsChanged()
257 {
258  if (mUpdating)
259  return;
260  // need a cx probe here, in order to set data.
261  if (!mActiveProbeConfig->getTool())
262  return;
263  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
264  if (!probe)
265  return;
266  ProbeDefinition data = probe->getProbeDefinition();
267 
268  data.setClipRect_p(mBBWidget->getValue());
269 
270  probe->setProbeDefinition(data);
271 }
272 
273 void ProbeConfigWidget::guiOriginSettingsChanged()
274 {
275  if (mUpdating)
276  return;
277  // need a cx probe here, in order to set data.
278  if (!mActiveProbeConfig->getTool())
279  return;
280  cx::ProbePtr probe = mActiveProbeConfig->getTool()->getProbe();
281  if (!probe)
282  return;
283  ProbeDefinition data = probe->getProbeDefinition();
284 
285  // if sync: move clip rect accordingly
286  if (mSyncBoxToSector->isChecked())
287  {
288  // shift
289  Vector3D shift = mOrigin->getValue() - data.getOrigin_p();
291  }
292 
293  data.setOrigin_p(mOrigin->getValue());
294 
295  probe->setProbeDefinition(data);
296 }
297 
298 
299 
300 }
double getWidth() const
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:40
boost::shared_ptr< class TrackingService > TrackingServicePtr
US beam is emitted straight forward.
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:32
void setRange(const DoubleRange &range)
Widget displays/edits a BoundingBox3D.
static StringPropertyActiveProbeConfigurationPtr New(TrackingServicePtr trackingService)
Composite widget for string selection.
void setSector(double depthStart, double depthEnd, double width, double centerOffset=0)
double getDepthStart() const
QAction * createAction(QObject *parent, QIcon iconName, QString text, QString tip, T slot, QLayout *layout=NULL, QToolButton *button=new QToolButton())
Definition: cxBaseWidget.h:129
boost::shared_ptr< Probe > ProbePtr
Definition: cxProbe.h:72
double getDepthEnd() const
Composite widget for scalar data manipulation.
Vector3D getOrigin_p() const
void setOrigin_p(Vector3D origin_p)
std::pair< double, double > getValue() const
US beam is emitted radially in a flat cone.
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
void setClipRect_p(DoubleBoundingBox3D clipRect_p)
Transform3D createTransformTranslate(const Vector3D &translation)
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
void changed()
emit when the underlying data value is changed: The user interface will be updated.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
Definition of characteristics for an Ultrasound Probe Sector.
Vector3D getSpacing() const
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:88
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())
DoubleBoundingBox3D getClipRect_p() const
void setValue(const DoubleBoundingBox3D &value, const DoubleBoundingBox3D &range)
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)
Namespace for all CustusX production code.