Fraxinus  16.5.0-fx-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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) 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 
34 #include "cxDoubleWidgets.h"
35 
36 #include <iostream>
37 #include "cxVector3D.h"
38 #include "cxTypeConversions.h"
39 #include "cxMousePadWidget.h"
40 #include "cxHelperWidgets.h"
41 
42 namespace cx
43 {
44 
46  OptimizedUpdateWidget(parent), mSlider(NULL), mDial(NULL), mSpinBox(NULL), mLabel(NULL), mEdit(NULL), mInfiniteSlider(NULL)
47 {
48  mData = dataInterface;
49  connect(mData.get(), SIGNAL(changed()), this, SLOT(setModified()));
50  this->enableAll(mData->getEnabled());
51 }
52 
54 {
55  mLabel = new QLabel(this);
56  mLabel->setText(mData->getDisplayName());
57 }
58 
60 {
61  if (mLabel)
62  mLabel->setVisible(on);
63 }
64 
66 {
67  mSlider = new DoubleSlider(this);
68  mSlider->setMinimumWidth(50);
69  mSlider->setOrientation(Qt::Horizontal);
70  connect(mSlider, SIGNAL(doubleValueChanged(double)), this, SLOT(doubleValueChanged(double)));
71 }
72 
74 {
75  mDial = new QDial(this);
76  mDial->setMaximumWidth(50);
77  mDial->setMaximumHeight(50);
78  mDial->setNotchesVisible(true);
79  connect(mDial, SIGNAL(valueChanged(int)), this, SLOT(intValueChanged(int)));
80 }
81 
83 {
84  QSize minBarSize = QSize(20, 20);
85  mInfiniteSlider = new MousePadWidget(this, minBarSize);
86  mInfiniteSlider->setFixedYPos(true);
87  connect(mInfiniteSlider, SIGNAL(mouseMoved(QPointF)), this, SLOT(infiniteSliderMouseMoved(QPointF)));
88 }
89 
90 void ScalarInteractionWidget::infiniteSliderMouseMoved(QPointF delta)
91 {
92  double scale = mData->getValueRange().range() / 2.0;
93  // double scale = M_PI_2;
94  double factor = scale * delta.x();
95  double current = mData->getValue();
96  mData->setValue(current + factor);
97 }
98 
100 {
101  mEdit = new DoubleLineEdit(this);
102  connect(mEdit, SIGNAL(editingFinished()), this, SLOT(textEditedSlot()));
103 }
104 
106 {
107  mSpinBox = new QDoubleSpinBox(this);
108  connect(mSpinBox, SIGNAL(valueChanged(double)), this, SLOT(doubleValueChanged(double)));
109 }
110 
115 {
116  QHBoxLayout* topLayout = new QHBoxLayout;
117  topLayout->setMargin(0);
118  topLayout->setSpacing(0);
119  this->setLayout(topLayout);
120 
121  if (mLabel)
122  topLayout->addWidget(mLabel, 0);
123  if (mEdit)
124  topLayout->addWidget(mEdit, 0);
125  if (mSpinBox)
126  topLayout->addWidget(mSpinBox, 0);
127  if (mDial)
128  topLayout->addWidget(mDial, 0);
129  if (mSlider)
130  topLayout->addWidget(mSlider, 1);
131  if (mInfiniteSlider)
132  topLayout->addWidget(mInfiniteSlider, 1);
133 }
134 
138 void ScalarInteractionWidget::addToGridLayout(QGridLayout* gridLayout, int row)
139 {
140  //Since SliderGroupWidget (this) is a widget we need to add this.
141  //If not we will get an invisible widget on top of all the other widgets of the parent
142  gridLayout->addLayout(mergeWidgetsIntoHBoxLayout(mLabel, addDummyMargin(this)), row, 0);
143 
144  QHBoxLayout* controlsLayout = new QHBoxLayout;
145  controlsLayout->setSpacing(0);
146  controlsLayout->setMargin(0);
147  gridLayout->addLayout(controlsLayout, row, 1);
148 
149 
150  if (mEdit)
151  controlsLayout->addWidget(mEdit);
152  if (mSpinBox)
153  controlsLayout->addWidget(mSpinBox);
154  if (mDial)
155  gridLayout->addWidget(mDial, row, 2);
156  if (mSlider)
157  controlsLayout->addWidget(mSlider, 1);
158  if (mInfiniteSlider)
159  controlsLayout->addWidget(mInfiniteSlider, 1);
160 }
161 
162 void ScalarInteractionWidget::build(QGridLayout* gridLayout, int row)
163 {
164  if (gridLayout)
165  this->addToGridLayout(gridLayout, row);
166  else
167  this->addToOwnLayout();
168 
169  this->setModified();
170 }
171 
172 
173 void ScalarInteractionWidget::intValueChanged(int val)
174 {
175  this->doubleValueChanged(val/100.0);
176 }
177 
178 
179 void ScalarInteractionWidget::doubleValueChanged(double val)
180 {
181  val = mData->convertDisplay2Internal(val);
182 
183  if (similar(val, mData->getValue()))
184  return;
185 
186  mData->setValue(val);
187 }
188 
189 void ScalarInteractionWidget::textEditedSlot()
190 {
191  if (!mEdit)
192  return;
193 
194  double defVal = mData->convertInternal2Display(mData->getValue()); // defval in display space
195  double newVal = mData->convertDisplay2Internal(mEdit->getDoubleValue(defVal)); // newval iin internal space
196 
197  if (similar(newVal, mData->getValue()))
198  return;
199 
200  mData->setValue(newVal);
201 }
202 
203 //void ScalarInteractionWidget::setModified()
204 //{
205 // OptimizedUpdateWidget::setModified();
206 // // Problem: If one of the sliders are visible, paint() is not called.
207 // // Force repaint here.
208 // //
209 // // Possible solution: this is obscured by the slider,
210 // // but repaint goes to the children. Maybe design is flawed and we need to
211 // // listen to the children as well?
214 //}
215 
217 {
218  this->enableAll(mData->getEnabled());
219 
220 // std::cout << "ScalarInteractionWidget::prePaintEvent() " << this << " " << mData->getDisplayName() << std::endl;
221  DoubleRange range = mData->getValueRange();
222  DoubleRange dRange(mData->convertInternal2Display(range.min()), mData->convertInternal2Display(range.max()),
223  mData->convertInternal2Display(range.step()));
224 
225  if (mSlider)
226  {
227  mSlider->blockSignals(true);
228  mSlider->setDoubleRange(dRange); // in case the image is changed
229  mSlider->setDoubleValue(mData->convertInternal2Display(mData->getValue()));
230  mSlider->setToolTip(mData->getHelp());
231  mSlider->blockSignals(false);
232  }
233 
234  if (mEdit)
235  {
236  mEdit->blockSignals(true);
237  mEdit->setDoubleValue(mData->convertInternal2Display(mData->getValue()));
238  mEdit->setToolTip(mData->getHelp());
239  mEdit->blockSignals(false);
240  }
241 
242  if (mSpinBox)
243  {
244  mSpinBox->blockSignals(true);
245  mSpinBox->setRange(dRange.min(), dRange.max()); // in case the image is changed
246  mSpinBox->setSingleStep(dRange.step());
247  mSpinBox->setDecimals(mData->getValueDecimals());
248  mSpinBox->setValue(mData->convertInternal2Display(mData->getValue()));
249  mSpinBox->setToolTip(mData->getHelp());
250  mSpinBox->blockSignals(false);
251  }
252 
253  if (mDial)
254  {
255  mDial->blockSignals(true);
256  mDial->setContentsMargins(0,0,0,0);
257  mDial->setRange(dRange.min()*100, dRange.max()*100);
258  mDial->setSingleStep(dRange.step()*100);
259  mDial->setValue(mData->convertInternal2Display(mData->getValue())*100);
260  mDial->setToolTip(mData->getHelp());
261  mDial->blockSignals(false);
262  }
263 
264  if (mLabel)
265  {
266  mLabel->setToolTip(mData->getHelp());
267  }
268 }
269 
270 void ScalarInteractionWidget::enableAll(bool enable)
271 {
272  QWidget::setEnabled(enable);
273 
274  if(mSlider)
275  mSlider->setEnabled(enable);
276  if(mSpinBox)
277  mSpinBox->setEnabled(enable);
278  if(mLabel)
279  mLabel->setEnabled(enable);
280  if(mEdit)
281  mEdit->setEnabled(enable);
282  if(mInfiniteSlider)
283  mInfiniteSlider->setEnabled(enable);
284 }
285 
286 // --------------------------------------------------------
287 // --------------------------------------------------------
288 
289 // --------------------------------------------------------
290 // --------------------------------------------------------
291 
292 
294 {
295  QSize size = QLineEdit::minimumSizeHint();
296  size.setWidth(size.height() * 3);
297  return size;
298 }
299 
301 {
302  QSize size = QLineEdit::minimumSizeHint();
303  return size;
304 }
305 
306 // --------------------------------------------------------
307 // --------------------------------------------------------
308 
309 SliderGroupWidget::SliderGroupWidget(QWidget* parent, DoublePropertyBasePtr dataInterface, QGridLayout* gridLayout,
310  int row) :
311  ScalarInteractionWidget(parent, dataInterface)
312 {
313  this->enableLabel();
314  this->enableSlider();
315  this->enableEdit();
316 
317  this->build(gridLayout, row);
318 }
319 
320 // --------------------------------------------------------
321 // --------------------------------------------------------
322 
324  QGridLayout* gridLayout, int row) :
325  ScalarInteractionWidget(parent, dataInterface)
326 {
327  this->enableLabel();
328  this->enableSpinBox();
329 
330  this->build(gridLayout, row);
331 }
332 
333 // --------------------------------------------------------
334 
336  QGridLayout* gridLayout, int row) :
337  ScalarInteractionWidget(parent, dataInterface)
338 {
339  this->enableLabel();
340  this->enableSpinBox();
341  this->enableSlider();
342 
343  this->build(gridLayout, row);
344 }
345 // --------------------------------------------------------
347  QGridLayout* gridLayout, int row) :
348  ScalarInteractionWidget(parent, dataInterface)
349 {
350  this->enableLabel();
351  this->enableSpinBox();
352  this->enableDial();
353 
354  this->build(gridLayout, row);
355 }
356 
357 // --------------------------------------------------------
358 
360  DoublePropertyBasePtr dataInterface, QGridLayout* gridLayout, int row) :
361  ScalarInteractionWidget(parent, dataInterface)
362 {
363  this->enableLabel();
364  this->enableSpinBox();
365  this->enableInfiniteSlider();
366 
367  this->build(gridLayout, row);
368 }
369 
370 } // 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:70
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:53
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)
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
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:66
Custom widget for display of double-valued data.
boost::shared_ptr< class DoublePropertyBase > DoublePropertyBasePtr
double step() const
smallest reasonable increment
Definition: cxDoubleRange.h:74
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)
Interface for all classes following the modified/prepaint paradigm.
virtual QSize minimumSizeHint() const