CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxDoubleWidgets.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 
13 #include "cxDoubleWidgets.h"
14 
15 #include <iostream>
16 #include "cxVector3D.h"
17 #include "cxTypeConversions.h"
18 #include "cxMousePadWidget.h"
19 #include "cxHelperWidgets.h"
20 
21 namespace cx
22 {
23 
25  OptimizedUpdateWidget(parent), mSlider(NULL), mDial(NULL), mSpinBox(NULL), mLabel(NULL), mEdit(NULL), mInfiniteSlider(NULL)
26 {
27  mData = dataInterface;
28  connect(mData.get(), SIGNAL(changed()), this, SLOT(setModified()));
29  this->enableAll(mData->getEnabled());
30 }
31 
33 {
34  mLabel = new QLabel(this);
35  mLabel->setText(mData->getDisplayName());
36 }
37 
39 {
40  if (mLabel)
41  mLabel->setVisible(on);
42 }
43 
45 {
46  mSlider = new DoubleSlider(this);
47  mSlider->setMinimumWidth(50);
48  mSlider->setOrientation(Qt::Horizontal);
49  connect(mSlider, SIGNAL(doubleValueChanged(double)), this, SLOT(doubleValueChanged(double)));
50 }
51 
53 {
54  mDial = new QDial(this);
55  mDial->setMaximumWidth(50);
56  mDial->setMaximumHeight(50);
57  mDial->setNotchesVisible(true);
58  connect(mDial, SIGNAL(valueChanged(int)), this, SLOT(intValueChanged(int)));
59 }
60 
62 {
63  QSize minBarSize = QSize(20, 20);
64  mInfiniteSlider = new MousePadWidget(this, minBarSize);
65  mInfiniteSlider->setFixedYPos(true);
66  connect(mInfiniteSlider, SIGNAL(mouseMoved(QPointF)), this, SLOT(infiniteSliderMouseMoved(QPointF)));
67 }
68 
69 void ScalarInteractionWidget::infiniteSliderMouseMoved(QPointF delta)
70 {
71  double scale = mData->getValueRange().range() / 2.0;
72  // double scale = M_PI_2;
73  double factor = scale * delta.x();
74  double current = mData->getValue();
75  mData->setValue(current + factor);
76 }
77 
79 {
80  mEdit = new DoubleLineEdit(this);
81  connect(mEdit, SIGNAL(editingFinished()), this, SLOT(textEditedSlot()));
82 }
83 
85 {
86  mSpinBox = new QDoubleSpinBox(this);
87  connect(mSpinBox, SIGNAL(valueChanged(double)), this, SLOT(doubleValueChanged(double)));
88 }
89 
94 {
95  QHBoxLayout* topLayout = new QHBoxLayout;
96  topLayout->setMargin(0);
97  topLayout->setSpacing(0);
98  this->setLayout(topLayout);
99 
100  if (mLabel)
101  topLayout->addWidget(mLabel, 0);
102  if (mEdit)
103  topLayout->addWidget(mEdit, 0);
104  if (mSpinBox)
105  topLayout->addWidget(mSpinBox, 0);
106  if (mDial)
107  topLayout->addWidget(mDial, 0);
108  if (mSlider)
109  topLayout->addWidget(mSlider, 1);
110  if (mInfiniteSlider)
111  topLayout->addWidget(mInfiniteSlider, 1);
112 }
113 
117 void ScalarInteractionWidget::addToGridLayout(QGridLayout* gridLayout, int row)
118 {
119  //Since SliderGroupWidget (this) is a widget we need to add this.
120  //If not we will get an invisible widget on top of all the other widgets of the parent
121  gridLayout->addLayout(mergeWidgetsIntoHBoxLayout(mLabel, addDummyMargin(this)), row, 0);
122 
123  QHBoxLayout* controlsLayout = new QHBoxLayout;
124  controlsLayout->setSpacing(0);
125  controlsLayout->setMargin(0);
126  gridLayout->addLayout(controlsLayout, row, 1);
127 
128 
129  if (mEdit)
130  controlsLayout->addWidget(mEdit);
131  if (mSpinBox)
132  controlsLayout->addWidget(mSpinBox);
133  if (mDial)
134  gridLayout->addWidget(mDial, row, 2);
135  if (mSlider)
136  controlsLayout->addWidget(mSlider, 1);
137  if (mInfiniteSlider)
138  controlsLayout->addWidget(mInfiniteSlider, 1);
139 }
140 
141 void ScalarInteractionWidget::build(QGridLayout* gridLayout, int row)
142 {
143  if (gridLayout)
144  this->addToGridLayout(gridLayout, row);
145  else
146  this->addToOwnLayout();
147 
148  this->setModified();
149 }
150 
151 
152 void ScalarInteractionWidget::intValueChanged(int val)
153 {
154  this->doubleValueChanged(val/100.0);
155 }
156 
157 
158 void ScalarInteractionWidget::doubleValueChanged(double val)
159 {
160  val = mData->convertDisplay2Internal(val);
161 
162  if (similar(val, mData->getValue()))
163  return;
164 
165  mData->setValue(val);
166 }
167 
168 void ScalarInteractionWidget::textEditedSlot()
169 {
170  if (!mEdit)
171  return;
172 
173  double defVal = mData->convertInternal2Display(mData->getValue()); // defval in display space
174  double newVal = mData->convertDisplay2Internal(mEdit->getDoubleValue(defVal)); // newval iin internal space
175 
176  if (similar(newVal, mData->getValue()))
177  return;
178 
179  mData->setValue(newVal);
180 }
181 
182 //void ScalarInteractionWidget::setModified()
183 //{
184 // OptimizedUpdateWidget::setModified();
185 // // Problem: If one of the sliders are visible, paint() is not called.
186 // // Force repaint here.
187 // //
188 // // Possible solution: this is obscured by the slider,
189 // // but repaint goes to the children. Maybe design is flawed and we need to
190 // // listen to the children as well?
193 //}
194 
196 {
197  this->enableAll(mData->getEnabled());
198 
199 // std::cout << "ScalarInteractionWidget::prePaintEvent() " << this << " " << mData->getDisplayName() << std::endl;
200  DoubleRange range = mData->getValueRange();
201  DoubleRange dRange(mData->convertInternal2Display(range.min()), mData->convertInternal2Display(range.max()),
202  mData->convertInternal2Display(range.step()));
203 
204  if (mSlider)
205  {
206  mSlider->blockSignals(true);
207  mSlider->setDoubleRange(dRange); // in case the image is changed
208  mSlider->setDoubleValue(mData->convertInternal2Display(mData->getValue()));
209  mSlider->setToolTip(mData->getHelp());
210  mSlider->blockSignals(false);
211  }
212 
213  if (mEdit)
214  {
215  mEdit->blockSignals(true);
216  mEdit->setDoubleValue(mData->convertInternal2Display(mData->getValue()));
217  mEdit->setToolTip(mData->getHelp());
218  mEdit->blockSignals(false);
219  }
220 
221  if (mSpinBox)
222  {
223  mSpinBox->blockSignals(true);
224  mSpinBox->setRange(dRange.min(), dRange.max()); // in case the image is changed
225  mSpinBox->setSingleStep(dRange.step());
226  mSpinBox->setDecimals(mData->getValueDecimals());
227  mSpinBox->setValue(mData->convertInternal2Display(mData->getValue()));
228  mSpinBox->setToolTip(mData->getHelp());
229  mSpinBox->blockSignals(false);
230  }
231 
232  if (mDial)
233  {
234  mDial->blockSignals(true);
235  mDial->setContentsMargins(0,0,0,0);
236  mDial->setRange(dRange.min()*100, dRange.max()*100);
237  mDial->setSingleStep(dRange.step()*100);
238  mDial->setValue(mData->convertInternal2Display(mData->getValue())*100);
239  mDial->setToolTip(mData->getHelp());
240  mDial->blockSignals(false);
241  }
242 
243  if (mLabel)
244  {
245  mLabel->setToolTip(mData->getHelp());
246  }
247 }
248 
249 void ScalarInteractionWidget::enableAll(bool enable)
250 {
251  QWidget::setEnabled(enable);
252 
253  if(mSlider)
254  mSlider->setEnabled(enable);
255  if(mSpinBox)
256  mSpinBox->setEnabled(enable);
257  if(mLabel)
258  mLabel->setEnabled(enable);
259  if(mEdit)
260  mEdit->setEnabled(enable);
261  if(mInfiniteSlider)
262  mInfiniteSlider->setEnabled(enable);
263 }
264 
265 // --------------------------------------------------------
266 // --------------------------------------------------------
267 
268 // --------------------------------------------------------
269 // --------------------------------------------------------
270 
271 
273 {
274  QSize size = QLineEdit::minimumSizeHint();
275  size.setWidth(size.height() * 3);
276  return size;
277 }
278 
280 {
281  QSize size = QLineEdit::minimumSizeHint();
282  return size;
283 }
284 
285 // --------------------------------------------------------
286 // --------------------------------------------------------
287 
288 SliderGroupWidget::SliderGroupWidget(QWidget* parent, DoublePropertyBasePtr dataInterface, QGridLayout* gridLayout,
289  int row) :
290  ScalarInteractionWidget(parent, dataInterface)
291 {
292  this->enableLabel();
293  this->enableSlider();
294  this->enableEdit();
295 
296  this->build(gridLayout, row);
297 }
298 
299 // --------------------------------------------------------
300 // --------------------------------------------------------
301 
303  QGridLayout* gridLayout, int row) :
304  ScalarInteractionWidget(parent, dataInterface)
305 {
306  this->enableLabel();
307  this->enableSpinBox();
308 
309  this->build(gridLayout, row);
310 }
311 
312 // --------------------------------------------------------
313 
315  QGridLayout* gridLayout, int row) :
316  ScalarInteractionWidget(parent, dataInterface)
317 {
318  this->enableLabel();
319  this->enableSpinBox();
320  this->enableSlider();
321 
322  this->build(gridLayout, row);
323 }
324 // --------------------------------------------------------
326  QGridLayout* gridLayout, int row) :
327  ScalarInteractionWidget(parent, dataInterface)
328 {
329  this->enableLabel();
330  this->enableSpinBox();
331  this->enableDial();
332 
333  this->build(gridLayout, row);
334 }
335 
336 // --------------------------------------------------------
337 
339  DoublePropertyBasePtr dataInterface, QGridLayout* gridLayout, int row) :
340  ScalarInteractionWidget(parent, dataInterface)
341 {
342  this->enableLabel();
343  this->enableSpinBox();
344  this->enableInfiniteSlider();
345 
346  this->build(gridLayout, row);
347 }
348 
349 } // namespace cx
QWidget * addDummyMargin(QWidget *widget)
void setDoubleValue(double val)
void build(QGridLayout *gridLayout=0, int row=0)
SpinBoxGroupWidget(QWidget *parent, DoublePropertyBasePtr, QGridLayout *gridLayout=0, int row=0)
double max() const
maximum value
Definition: cxDoubleRange.h:49
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:32
DoublePropertyBasePtr mData
A touchpad-friendly area for performing 1D/2D scroll operations.
SliderGroupWidget(QWidget *parent, DoublePropertyBasePtr, QGridLayout *gridLayout=0, int row=0)
SpinBoxInfiniteSliderGroupWidget(QWidget *parent, DoublePropertyBasePtr, QGridLayout *gridLayout=0, int row=0)
Composite widget for scalar data manipulation.
SpinBoxAndSliderGroupWidget(QWidget *parent, DoublePropertyBasePtr, QGridLayout *gridLayout=0, int row=0)
QHBoxLayout * mergeWidgetsIntoHBoxLayout(QWidget *first, QWidget *second)
virtual QSize sizeHint() const
double getDoubleValue(double defVal=0.0) const
void setDoubleRange(const DoubleRange &range)
ScalarInteractionWidget(QWidget *parent, DoublePropertyBasePtr)
double min() const
minimum value
Definition: cxDoubleRange.h:45
Custom widget for display of double-valued data.
boost::shared_ptr< class DoublePropertyBase > DoublePropertyBasePtr
double step() const
smallest reasonable increment
Definition: cxDoubleRange.h:53
void setFixedYPos(bool on)
A QLineEdit specialized to deal with double data.
void setDoubleValue(double val)
void addToGridLayout(QGridLayout *gridLayout=0, int row=0)
SpinBoxAndDialGroupWidget(QWidget *parent, DoublePropertyBasePtr, QGridLayout *gridLayout=0, int row=0)
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
Interface for all classes following the modified/prepaint paradigm.
virtual QSize minimumSizeHint() const
Namespace for all CustusX production code.