Просмотр исходного кода

Update displayed value when value proxy is modified

Julien Finet лет назад: 11
Родитель
Сommit
bc38808d0a

+ 44 - 0
Libs/Core/Testing/Cpp/ctkLinearValueProxyTest.cpp

@@ -50,6 +50,9 @@ private Q_SLOTS:
 
   void testSetProxyValueNullCoeff();
   void testSetProxyValueNullCoeff_data();
+
+  void testProxyModified();
+  void testProxyModified_data();
 };
 
 // ----------------------------------------------------------------------------
@@ -460,6 +463,47 @@ void ctkLinearValueProxyTester::testSetProxyValueNullCoeff_data()
     << std::numeric_limits<double>::quiet_NaN();
 }
 
+
+// ----------------------------------------------------------------------------
+void ctkLinearValueProxyTester::testProxyModified()
+{
+  ctkLinearValueProxy proxy;
+  proxy.setCoefficient(5.0);
+  proxy.setOffset(5.0);
+
+  QSignalSpy proxyAboutToBeModifiedSpy(&proxy, SIGNAL(proxyAboutToBeModified()));
+  QSignalSpy proxyModifiedSpy(&proxy, SIGNAL(proxyModified()));
+
+  QFETCH(bool, changeCoefficient);
+  QFETCH(double, coefficientOrOffset);
+  if (changeCoefficient)
+    {
+    proxy.setCoefficient(coefficientOrOffset);
+    }
+  else
+    {
+    proxy.setOffset(coefficientOrOffset);
+    }
+  QFETCH(int, expectedSignalCount);
+  ctkTest::COMPARE(proxyAboutToBeModifiedSpy.count(), expectedSignalCount);
+  ctkTest::COMPARE(proxyModifiedSpy.count(), expectedSignalCount);
+}
+
+// ----------------------------------------------------------------------------
+void ctkLinearValueProxyTester::testProxyModified_data()
+{
+  QTest::addColumn<double>("coefficientOrOffset");
+  QTest::addColumn<bool>("changeCoefficient");
+  QTest::addColumn<int>("expectedSignalCount");
+
+  QTest::newRow("change coefficient") << 10.0 << true << 1;
+  QTest::newRow("same coefficient") << 5.0 << true << 0;
+  QTest::newRow("null coefficient") << 0.0 << true << 1;
+  QTest::newRow("change offset") << 10.0 << false << 1;
+  QTest::newRow("same offset") << 5.0 << false << 0;
+  QTest::newRow("null offset") << 0.0 << false << 1;
+}
+
 // ----------------------------------------------------------------------------
 CTK_TEST_MAIN(ctkLinearValueProxyTest)
 #include "moc_ctkLinearValueProxyTest.cpp"

+ 4 - 2
Libs/Core/ctkLinearValueProxy.cpp

@@ -107,9 +107,10 @@ void ctkLinearValueProxy::setCoefficient(double newCoeff)
     {
     return;
     }
-
+  emit proxyAboutToBeModified();
   d->Coefficient = newCoeff;
   this->updateProxyValue();
+  emit proxyModified();
 }
 
 // --------------------------------------------------------------------------
@@ -120,7 +121,8 @@ void ctkLinearValueProxy::setOffset(double newOffset)
     {
     return;
     }
-
+  emit proxyAboutToBeModified();
   d->Offset = newOffset;
   this->updateProxyValue();
+  emit proxyModified();
 }

+ 3 - 0
Libs/Core/ctkValueProxy.h

@@ -78,6 +78,9 @@ Q_SIGNALS:
   void valueChanged(double);
   void proxyValueChanged(double);
 
+  void proxyAboutToBeModified();
+  void proxyModified();
+
 protected:
   QScopedPointer<ctkValueProxyPrivate> d_ptr;
 

+ 0 - 4
Libs/Testing/ctkTest.h

@@ -123,10 +123,6 @@ inline void COMPARE(double v1, double v2)
     QVERIFY(v1 == std::numeric_limits<double>::infinity());
     }
   // QCOMPARE doesn't like to compare zeroes
-  else if (v2 == 0.0)
-    {
-    QCOMPARE(v1 + 1.0, 1.0);
-    }
   else
     {
     QCOMPARE(v1, v2);

+ 3 - 0
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -26,6 +26,7 @@ set(TEST_SOURCES
   ctkCoordinatesWidgetValueProxyTest.cpp
   ctkCrosshairLabelTest1.cpp
   ctkDirectoryButtonTest1.cpp
+  ctkDoubleRangeSliderTest.cpp
   ctkDoubleRangeSliderTest1.cpp
   ctkDoubleRangeSliderTest2.cpp
   ctkDoubleRangeSliderValueProxyTest.cpp
@@ -188,6 +189,7 @@ QT4_WRAP_CPP(Tests_MOC_CPP ${Tests_MOC_SRCS})
 QT4_GENERATE_MOCS(
   ctkCoordinatesWidgetTest.cpp
   ctkCoordinatesWidgetValueProxyTest.cpp
+  ctkDoubleRangeSliderTest.cpp
   ctkDoubleRangeSliderValueProxyTest.cpp
   ctkDoubleSliderTest.cpp
   ctkDoubleSliderValueProxyTest.cpp
@@ -247,6 +249,7 @@ SIMPLE_TEST( ctkCoordinatesWidgetValueProxyTest )
 SIMPLE_TEST( ctkCrosshairLabelTest1 )
 SIMPLE_TEST( ctkDateRangeWidgetTest1 )
 SIMPLE_TEST( ctkDirectoryButtonTest1 )
+SIMPLE_TEST( ctkDoubleRangeSliderTest )
 SIMPLE_TEST( ctkDoubleRangeSliderTest1 )
 SIMPLE_TEST( ctkDoubleRangeSliderTest2 )
 SIMPLE_TEST( ctkDoubleRangeSliderValueProxyTest )

+ 127 - 0
Libs/Widgets/Testing/Cpp/ctkDoubleRangeSliderTest.cpp

@@ -0,0 +1,127 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QApplication>
+#include <QTest>
+
+// CTK includes
+#include "ctkDoubleRangeSlider.h"
+#include "ctkTest.h"
+
+//-----------------------------------------------------------------------------
+class ctkDoubleRangeSliderTester: public QObject
+{
+  Q_OBJECT
+private slots:
+  void testUI();
+
+  void testRange();
+  void testRange_data();
+
+  void testSingleStep();
+  void testSingleStep_data();
+};
+
+// ----------------------------------------------------------------------------
+void ctkDoubleRangeSliderTester::testUI()
+{
+  ctkDoubleRangeSlider slider;
+  slider.show();
+  QTest::qWaitForWindowShown(&slider);
+  // qApp->exec();
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleRangeSliderTester::testRange()
+{
+  ctkDoubleRangeSlider slider;
+
+  QFETCH(double, minimum);
+  QFETCH(double, maximum);
+  slider.setRange(minimum, maximum);
+
+  QFETCH(double, expectedMinimum);
+  QFETCH(double, expectedMaximum);
+  QFETCH(double, expectedMinimumValue);
+  QFETCH(double, expectedMaximumValue);
+
+  QCOMPARE(slider.minimum(), expectedMinimum);
+  QCOMPARE(slider.maximum(), expectedMaximum);
+  QCOMPARE(slider.minimumValue(), expectedMinimumValue);
+  QCOMPARE(slider.maximumValue(), expectedMaximumValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleRangeSliderTester::testRange_data()
+{
+  QTest::addColumn<double>("minimum");
+  QTest::addColumn<double>("maximum");
+  QTest::addColumn<double>("expectedMinimum");
+  QTest::addColumn<double>("expectedMaximum");
+  QTest::addColumn<double>("expectedMinimumValue");
+  QTest::addColumn<double>("expectedMaximumValue");
+
+  QTest::newRow("[20.123,20.1234]") << 20.123 << 20.1234
+                                    << 20.123 << 20.1234 << 20.123 << 20.1234;
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleRangeSliderTester::testSingleStep()
+{
+  ctkDoubleRangeSlider slider;
+  slider.setValues(25., 75.);
+
+  QFETCH(double, minimum);
+  QFETCH(double, maximum);
+  slider.setRange(minimum, maximum);
+
+  QFETCH(double, singleStep);
+  slider.setSingleStep(singleStep);
+
+  QFETCH(double, expectedMinimumValue);
+  QFETCH(double, expectedMaximumValue);
+  QCOMPARE(slider.minimumValue(), expectedMinimumValue);
+  QCOMPARE(slider.maximumValue(), expectedMaximumValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleRangeSliderTester::testSingleStep_data()
+{
+  QTest::addColumn<double>("minimum");
+  QTest::addColumn<double>("maximum");
+  QTest::addColumn<double>("singleStep");
+  QTest::addColumn<double>("expectedMinimumValue");
+  QTest::addColumn<double>("expectedMaximumValue");
+
+  QTest::newRow("1.") << 0. << 100. << 1. << 25. << 75.;
+  QTest::newRow("100.") << 0. << 100. << 100. << 25. << 75.;
+  QTest::newRow("0.1") << 0. << 100. << 0.1 << 25. << 75.;
+  QTest::newRow("min") << 0. << 100. << std::numeric_limits<double>::min() << 25. << 75.;
+  QTest::newRow("max") << 0. << 100. << std::numeric_limits<double>::max() << 25. << 75.;
+  QTest::newRow("-max") << 0. << 100. << -std::numeric_limits<double>::max() << 25. << 75.;
+  QTest::newRow("-inf") << 0. << 100. << -std::numeric_limits<double>::infinity() << 25. << 75.;
+  QTest::newRow("inf") << 0. << 100. << std::numeric_limits<double>::infinity() << 25. << 75.;
+  QTest::newRow("NaN") << 0. << 100. << std::numeric_limits<double>::quiet_NaN() << 25. << 75.;
+}
+
+// ----------------------------------------------------------------------------
+CTK_TEST_MAIN(ctkDoubleRangeSliderTest)
+#include "moc_ctkDoubleRangeSliderTest.cpp"

+ 74 - 286
Libs/Widgets/Testing/Cpp/ctkDoubleRangeSliderValueProxyTest.cpp

@@ -40,7 +40,7 @@ void getSpyReport(QSignalSpy& spy, double expectedValue)
   QCOMPARE(spy.count(), 1);
 
   QList<QVariant> arguments = spy.takeFirst(); // take the first signal
-  ctkTest::COMPARE(arguments.at(0).toDouble(), expectedValue);
+  QCOMPARE(arguments.at(0).toDouble(), expectedValue);
 }
 
 //-----------------------------------------------------------------------------
@@ -124,7 +124,7 @@ void ctkDoubleRangeSliderValueProxyTester::testSetValues()
   slider.setValueProxy(&proxy);
 
   // Spy
-  CustomSpy valuesSpy();
+  CustomSpy valuesSpy;
   QObject::connect(&slider, SIGNAL(valuesChanged(double, double)),
                    &valuesSpy, SLOT(onValuesChanged(double, double)));
 
@@ -136,8 +136,8 @@ void ctkDoubleRangeSliderValueProxyTester::testSetValues()
   QFETCH(double, expectedMin);
   QFETCH(double, expectedMax);
   valuesSpy.getSpyReport(expectedMin, expectedMax);
-  ctkTest::COMPARE(slider.minimumValue(), expectedMin);
-  ctkTest::COMPARE(slider.maximumValue(), expectedMax);
+  QCOMPARE(slider.minimumValue(), expectedMin);
+  QCOMPARE(slider.maximumValue(), expectedMax);
 }
 
 //-----------------------------------------------------------------------------
@@ -154,190 +154,55 @@ void ctkDoubleRangeSliderValueProxyTester::testSetValues_data()
   // Offset
   QTest::newRow("Offset only") << 1.0 << 42.19176 << 0.1 << 0.1 << 0.2 << 0.2;
 
-  QTest::newRow("Offset only: max+offset < min+offset < -200") << 1.0 << -42.19
-    << -160.0 << -157.81
-    << -190.9 << -157.81;
-  QTest::newRow("Offset only: max+offset < -200 < min+offset") << 1.0 << -42.19
-    << -0.1 << -157.81
-    << -160.9 << -0.1;
-  QTest::newRow("Offset only: -200 < max+offset < min+offset") << 1.0 << 42.19
-    << -0.1 << -130.9
-    << -130.9 << -0.1;
-
-  QTest::newRow("Offset only: 200 < max+offset < min+offset") << 1.0 << 42.19
-    << 160.0 << 157.81
-    << 190.9 << 157.81;
-  QTest::newRow("Offset only: max+offset < 200 < min+offset") << 1.0 << 42.19
-    << 160.9 << -0.9
-    << -0.9 << 157.81;
-  QTest::newRow("Offset only: max+offset < min+offset < 200") << 1.0 << 42.19
-    << 130.6 << -13.9
-    << -13.9 << 130.6;
-
-  QTest::newRow("Offset only: 200 < max = max_double = min = max_double")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::max() << 157.81
-    << std::numeric_limits<double>::max() << 157.81;
-  QTest::newRow("Offset only: max = -max_double < -200 < 200 < min = max_double")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::max() << -242.19
-    << -std::numeric_limits<double>::max() << 157.81;
-  QTest::newRow("Offset only: max = -max_double = min = -max_double < -200")
-    << 1.0 << 42.19
-    << - std::numeric_limits<double>::max() << -242.19
-    << - std::numeric_limits<double>::max() << -242.19;
-
-  QTest::newRow("Offset only: 200 < max = infinity = min = infinity")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::infinity() << 157.81
-    << std::numeric_limits<double>::infinity() << 157.81;
-  QTest::newRow("Offset only: max = -infinity < -200 < 200 < min = infinity")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::infinity() << -242.19
-    << -std::numeric_limits<double>::infinity() << 157.81;
-  QTest::newRow("Offset only: max = -infinity = min = -infinity < -200")
-    << 1.0 << 42.19
-    << - std::numeric_limits<double>::infinity() << -242.19
-    << - std::numeric_limits<double>::infinity() << -242.19;
-
-  QTest::newRow("Offset only: max = min = NaN")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::quiet_NaN() << -242.19
-    << std::numeric_limits<double>::quiet_NaN() << -242.19;
-  QTest::newRow("Offset only: max = NaN && min > 200")
-    << 1.0 << 42.19
-    << 630.0 << -242.19
-    << std::numeric_limits<double>::quiet_NaN() << 157.81;
-  QTest::newRow("Offset only: min = NaN && max < -200")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::quiet_NaN() << -242.19
-    << -794348.12 << -242.19;
+  QTest::newRow("Offset only: max+offset < min+offset < -200")
+    << 1. << -42.19 << -160. << -190.9 << -190.9 << -160.;
+  QTest::newRow("Offset only: max+offset < -200 < min+offset")
+    << 1. << -42.19 << -0.1 << -160.9 << -160.9 << -0.1;
+  QTest::newRow("Offset only: -200 < max+offset < min+offset")
+    << 1. << 42.19 << -0.1 << -130.9 << -130.9 << -0.1;
+
+  QTest::newRow("Offset only: 200 < max+offset < min+offset")
+    << 1. << 42.19 << 160. << 160. << 190.9 << 190.9;
+  QTest::newRow("Offset only: max+offset < 200 < min+offset")
+    << 1. << 42.19 << 160.9 << -0.9 << -0.9 << 160.9;
+  QTest::newRow("Offset only: max+offset < min+offset < 200")
+    << 1. << 42.19 << 130.6 << -13.9 << -13.9 << 130.6;
 
   //---------------------------------------------------------------------------
   // Coefficient
   QTest::newRow("Coeff only") << 5.0 << 0.0 << 0.1 << 0.1 << 0.2 << 0.2;
 
-  QTest::newRow("Coeff only: max*coeff < min*coeff < -200") << 5.0 << 0.0
-    << -160.0 << -40.0
-    << -190.9 << -40.0;
-  QTest::newRow("Coeff only: max*coeff < -200 < min*coeff") << 5.0 << 0.0
-    << -0.1 << -40.0
-    << -160.9 << -0.1;
-  QTest::newRow("Coeff only: -200 < max*coeff < min*coeff") << 5.0 << 0.0
-    << -0.1 << -20.9
-    << -20.9 << -0.1;
-
-  QTest::newRow("Coeff only: 200 < max*coeff < min*coeff") << 5.0 << 0.0
-    << 160.0 << 40.0
-    << 190.9 << 40.0;
-  QTest::newRow("Coeff only: max*coeff < 200 < min*coeff") << 5.0 << 0.0
-    << 160.9 << -0.9
-    << -0.9 << 40.00;
-  QTest::newRow("Coeff only: max*coeff < min*coeff < 200") << 5.0 << 0.0
-    << 13.6 << -13.9
-    << -13.9 << 13.6;
-
-  QTest::newRow("Coeff only: 200 < max = max_double = min = max_double")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::max() << 40.0
-    << std::numeric_limits<double>::max() << 40.0;
-  QTest::newRow("Coeff only: max = -max_double < -200 < 200 < min = max_double")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::max() << -40.0
-    << - std::numeric_limits<double>::max() << 40.0;
-  QTest::newRow("Coeff only: max = -max_double = min = -max_double < -200")
-    << 5.0 << 0.0
-    << -std::numeric_limits<double>::max() << -40.0
-    << -std::numeric_limits<double>::max() << -40.0;
-
-  QTest::newRow("Coeff only: 200 < max = infinity = min = infinity")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::infinity() << 40.0
-    << std::numeric_limits<double>::infinity() << 40.0;
-  QTest::newRow("Coeff only: max = -infinity < -200 < 200 < min = infinity")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::infinity() << -40.0
-    << -std::numeric_limits<double>::infinity() << 40.0;
-  QTest::newRow("Coeff only: max = -infinity = min = -infinity < -200")
-    << 5.0 << 0.0
-    << - std::numeric_limits<double>::infinity() << -40.0
-    << - std::numeric_limits<double>::infinity() << -40.0;
-
-  QTest::newRow("Coeff only: max = min = NaN")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::quiet_NaN() << -40.0
-    << std::numeric_limits<double>::quiet_NaN() << -40.0;
-  QTest::newRow("Coeff only: max = NaN && min > 200")
-    << 5.0 << 0.0
-    << 630.0 << -40.0
-    << std::numeric_limits<double>::quiet_NaN() << 40.0;
-  QTest::newRow("Coeff only: min = NaN && max < -200")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::quiet_NaN() << -40.0
-    << -794348.12 << -40.0;
+  QTest::newRow("Coeff only: max*coeff < min*coeff < -200")
+    << 5. << 0. << -160. << -190.9 << -190.9 << -160.;
+  QTest::newRow("Coeff only: max*coeff < -200 < min*coeff")
+    << 5. << 0. << -0.1 << -160.9 << -160.9 << -0.1;
+  QTest::newRow("Coeff only: -200 < max*coeff < min*coeff")
+    << 5. << 0. << -0.1 << -20.9 << -20.9 << -0.1;
+
+  QTest::newRow("Coeff only: 200 < max*coeff < min*coeff")
+    << 5. << 0. << 160. << 160. << 190.9 << 190.9;
+  QTest::newRow("Coeff only: max*coeff < 200 < min*coeff")
+    << 5. << 0. << 160.9 << -0.9 << -0.9 << 160.9;
+  QTest::newRow("Coeff only: max*coeff < min*coeff < 200")
+    << 5. << 0. << 13.6 << -13.9 << -13.9 << 13.6;
 
   //---------------------------------------------------------------------------
   // Linear
   QTest::newRow("Linear") << 5.0 << 12.0 << 0.1 << 0.1 << 0.2 << 0.2;
 
-  QTest::newRow("Linear:f(max) < f(min) < -200") << 5.0 << 12.0
-    << -160.0 << -42.4
-    << -190.9 << -42.4;
-  QTest::newRow("Linear: f(max) < -200 < f(min)") << 5.0 << 12.0
-    << -0.1 << -42.4
-    << -160.9 << -0.1;
-  QTest::newRow("Linear: -200 < f(max) < f(min)") << 5.0 << 12.0
-    << -0.1 << -20.9
-    << -20.9 << -0.1;
-
-  QTest::newRow("Linear: 200 < f(max) < f(min)") << 5.0 << 12.0
-    << 160.0 << 37.6
-    << 190.9 << 37.6;
-  QTest::newRow("Linear: f(max) < 200 < f(min)") << 5.0 << 12.0
-    << 160.9 << -0.9
-    << -0.9 << 37.6;
-  QTest::newRow("Linear: f(max) < f(min) < 200") << 5.0 << 12.0
-    << 13.6 << -13.9
-    << -13.9 << 13.6;
-
-  QTest::newRow("Linear: 200 < max = max_double = min = max_double")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::max() << 37.6
-    << std::numeric_limits<double>::max() << 37.6;
-  QTest::newRow("Linear: max = -max_double < -200 < 200 < min = max_double")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::max() << -42.4
-    << - std::numeric_limits<double>::max() << 37.6;
-  QTest::newRow("Linear: max = -max_double = min = -max_double < -200")
-    << 5.0 << 12.0
-    << -std::numeric_limits<double>::max() << -42.4
-    << -std::numeric_limits<double>::max() << -42.4;
-
-  QTest::newRow("Linear: 200 < max = infinity = min = infinity")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::infinity() << 37.6
-    << std::numeric_limits<double>::infinity() << 37.6;
-  QTest::newRow("Linear: max = -infinity < -200 < 200 < min = infinity")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::infinity() << -42.4
-    << -std::numeric_limits<double>::infinity() << 37.6;
-  QTest::newRow("Linear: max = -infinity = min = -infinity < -200")
-    << 5.0 << 12.0
-    << - std::numeric_limits<double>::infinity() << -42.4
-    << - std::numeric_limits<double>::infinity() << -42.4;
-
-  QTest::newRow("Linear: max = min = NaN")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::quiet_NaN() << -42.4
-    << std::numeric_limits<double>::quiet_NaN() << -42.4;
-  QTest::newRow("Linear: max = NaN && f(min) > 200")
-    << 5.0 << 12.0
-    << 630.0 << -42.4
-    << std::numeric_limits<double>::quiet_NaN() << 37.6;
-  QTest::newRow("Linear: min = NaN && f(max) < -200")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::quiet_NaN() << -42.4
-    << -794348.12 << -42.4;
+  QTest::newRow("Linear:f(max) < f(min) < -200")
+    << 5. << 12. << -160. << -190.9 << -190.9 << -160.;
+  QTest::newRow("Linear: f(max) < -200 < f(min)")
+    << 5. << 12. << -0.1 << -160.9 << -160.9 << -0.1;
+  QTest::newRow("Linear: -200 < f(max) < f(min)")
+    << 5. << 12. << -0.1 << -20.9 << -20.9 << -0.1;
+
+  QTest::newRow("Linear: 200 < f(max) < f(min)")
+    << 5. << 12. << 160.0 << 160.0 << 190.9 << 190.9;
+  QTest::newRow("Linear: f(max) < 200 < f(min)")
+    << 5. << 12. << 160.9 << -0.9 << -0.9 << 160.9;
+  QTest::newRow("Linear: f(max) < f(min) < 200")
+    << 5. << 12. << 13.6 << -13.9 << -13.9 << 13.6;
 }
 
 //-----------------------------------------------------------------------------
@@ -366,7 +231,7 @@ void ctkDoubleRangeSliderValueProxyTester::testSetMinValue()
 
   QFETCH(double, expectedValue);
   getSpyReport(valueSpy, expectedValue);
-  ctkTest::COMPARE(slider.minimumValue(), expectedValue);
+  QCOMPARE(slider.minimumValue(), expectedValue);
 }
 
 //-----------------------------------------------------------------------------
@@ -411,87 +276,54 @@ void ctkDoubleRangeSliderValueProxyTester::testSetValueCommonData()
   QTest::newRow("Offset only") << 1.0 << 42.19176 << 0.1 << 0.1;
 
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19 << -510.0 << -242.19;
+    << 1. << 42.19 << -510. << -200.;
   QTest::newRow("Offset only: less than min but ok with offset")
-    << 1.0 << 42.19 << -230.0 << -230.0;
+    << 1. << 42.19 << -230. << -200.;
   QTest::newRow("Offset only: less than min with offset")
-    << 1.0 << -42.19 << -190.0 << -157.81;
+    << 1. << -42.19 << -190. << -190.;
 
   QTest::newRow("Offset only: more than max with offset")
-    << 1.0 << 42.19 << 160.0 << 157.81;
+    << 1. << 42.19 << 160. << 160.;
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.19 << 65010.0 << 242.19;
+    << 1. << -42.19 << 65010.0 << 200.;
   QTest::newRow("Offset only: less than max but ok with offset")
-    << 1.0 << -42.19 << 229.1 << 229.1;
-
-  QTest::newRow("Offset only: max")
-    << 1.0 << 42.19 << std::numeric_limits<double>::max() << 157.81;
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::max() << -242.19;
-  QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19 << std::numeric_limits<double>::infinity() << 157.81;
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::infinity() << -242.19;
-  QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN() << -242.19;
+    << 1. << -42.19 << 229.1 << 200.;
 
   //---------------------------------------------------------------------------
   // Coefficient
   QTest::newRow("Coeff only") << 5.0 << 0.0 << 0.1 << 0.1;
 
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -510.0 << -40.0;
+    << 5. << 0. << -510. << -200.;
   QTest::newRow("Coeff only: less than min but ok with coeff")
-    << 0.5 << 0.0 << -230.0 << -230.0;
+    << 0.5 << 0. << -230. << -200.;
   QTest::newRow("Coeff only: less than min with coeff")
-    << 5.0 << 0.0 << -190.0 << -40.0;
+    << 5.0 << 0. << -190. << -190.;
 
   QTest::newRow("Coeff only: more than max with coeff")
-    << 5.0 << 0.0 << 160.0 << 40.0;
+    << 5. << 0. << 160. << 160.;
   QTest::newRow("Coeff only: more than max")
-    << 5.0 << 0.0 << 65010.0 << 40.0;
+    << 5. << 0. << 65010. << 200.;
   QTest::newRow("Offset only: less than max but ok with coeff")
-    << 0.5 << 0.0 << 229.2 << 229.2;
-
-  QTest::newRow("Coeff only: max")
-    << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0;
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -40.0;
-  QTest::newRow("Coeff only: infinity")
-    << 5.0 << 0.0 << std::numeric_limits<double>::infinity() << 40.0;
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity() << -40.0;
-  QTest::newRow("Coeff only: Nan")
-    << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN() << -40.0;
+    << 0.5 << 0. << 229.2 << 200.;
 
   //---------------------------------------------------------------------------
   // Linear
   QTest::newRow("Linear") << 5.0 << 0.0 << 0.1 << 0.1;
 
   QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -510.0 << -42.4;
+    << 5. << 12. << -510.0 << -200.;
   QTest::newRow("Linear: less than min but ok with function")
-    << 0.5 << 12.0 << -230.0 << -230.0;
+    << 0.5 << 12. << -230.0 << -200.;
   QTest::newRow("Linear: less than min with function")
-    << 5.0 << 12.0 << -61.5 << -42.4;
+    << 5. << 12. << -61.5 << -61.5;
 
   QTest::newRow("Linear: more than max with function")
-    << 5.0 << 12.0 << 160.0 << 37.6;
+    << 5. << 12. << 160. << 160.;
   QTest::newRow("Linear: more than max")
-    << 5.0 << 12.0 << 65010.0 << 37.6;
-  QTest::newRow("Offset only: less than max but ok with function")
-    << 0.5 << 12.0 << 229.2 << 229.2;
-
-  QTest::newRow("Linear: max")
-    << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6;
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -42.4;
-  QTest::newRow("Linear: infinity")
-    << 5.0 << 12.0 << std::numeric_limits<double>::infinity() << 37.6;
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity() << -42.4;
-  QTest::newRow("Linear: Nan")
-    << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN() << -42.4;
+    << 5. << 12. << 65010. << 200.;
+  QTest::newRow("Linear: less than max but ok with function")
+    << 0.5 << 12. << 229.2 << 200.;
 }
 
 //-----------------------------------------------------------------------------
@@ -530,8 +362,7 @@ void ctkDoubleRangeSliderValueProxyTester::testSetMaxPosition()
 {
   // Setup
   ctkDoubleRangeSlider slider;
-  slider.setMinimum(-200);
-  slider.setMaximum(200);
+  slider.setRange(-200., 200.);
   slider.setSingleStep(0.01);
   slider.setMaximumValue(-32.6);
 
@@ -567,73 +398,30 @@ void ctkDoubleRangeSliderValueProxyTester::testSetPositionCommonData()
 
   //---------------------------------------------------------------------------
   // Offset
-  QTest::newRow("Offset only") << 1.0 << 42.19 << 0.1 << -42.09 << 0.1;
-
+  QTest::newRow("Offset only") << 1. << 42.19 << 0.1 << 0.1 << 0.1;
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19 << -510.0 << -242.19 << -200.0;
+    << 1. << 42.19 << -510. << -200. << -200.;
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.19 << 65010.0 << 242.19 << 200.0;
-
-  QTest::newRow("Offset only: max")
-    << 1.0 << 42.19 << std::numeric_limits<double>::max()
-    << 157.81 << 200.0;
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::max()
-    << -242.19 << -200.0;
-  QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19 << std::numeric_limits<double>::infinity()
-    << 157.81 << 200.0;
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::infinity()
-    << -242.19 << -200.0;
-  QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN()
-    << -242.19 << -200.0;
+    << 1. << -42.19 << 65010. << 200. << 200.;
+
 
   //---------------------------------------------------------------------------
   // Coefficient
-  QTest::newRow("Coeff only") << 5.0 << 0.0 << 5.0 << 1.0 << 5.0;
-
+  QTest::newRow("Coeff only") << 5. << 0. << 5. << 5. << 5.;
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -1010.0 << -40.0 << -200.0;
+    << 5. << 0. << -1010. << -200. << -200.;
   QTest::newRow("Coeff only: more than max")
-    << 5.0 << 0.0 << 65010.0 << 40.0 << 200.0;
-
-  QTest::newRow("Coeff only: max")
-    << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0 << 200.0;
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -40.0 << -200.0;
-  QTest::newRow("Coeff only: infinity")
-    << 5.0 << 0.0 << std::numeric_limits<double>::infinity() << 40.0 << 200.0;
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity()
-    << -40.0 << -200.0;
-  QTest::newRow("Coeff only: Nan")
-    << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN()
-    << -40.0 << -200.0;
+    << 5. << 0. << 65010. << 200. << 200.;
 
   //---------------------------------------------------------------------------
   // Linear
-  QTest::newRow("Linear") << 5.0 << 12.0 << 42.0 << 6.0 << 42.0;
+  QTest::newRow("Linear") << 5. << 12. << 42. << 42. << 42.;
 
   QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -5010.0 << -42.4 << -200.0;
+    << 5. << 12. << -5010. << -200. << -200.;
 
   QTest::newRow("Linear: more than max")
-    << 5.0 << 12.0 << 65010.0 << 37.6 << 200.0;
-
-  QTest::newRow("Linear: max")
-    << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6 << 200.0;
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -42.4 << -200.0;
-  QTest::newRow("Linear: infinity")
-    << 5.0 << 12.0 << std::numeric_limits<double>::infinity() << 37.6 << 200.0;
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity()
-    << -42.4 << -200.0;
-  QTest::newRow("Linear: Nan")
-    << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN()
-    << -42.4 << -200.0;
+    << 5. << 12. << 65010. << 200. << 200.;
 }
 
 // ----------------------------------------------------------------------------

+ 33 - 108
Libs/Widgets/Testing/Cpp/ctkDoubleSliderValueProxyTest.cpp

@@ -63,8 +63,7 @@ void ctkDoubleSliderValueProxyTester::testSetValue()
 {
   // Setup
   ctkDoubleSlider slider;
-  slider.setMinimum(-200);
-  slider.setMaximum(200);
+  slider.setRange(-200., 200.);
   slider.setSingleStep(0.01);
   slider.setValue(-32.6);
 
@@ -100,90 +99,58 @@ void ctkDoubleSliderValueProxyTester::testSetValue_data()
   QTest::newRow("Offset only") << 1.0 << 42.19176 << 0.1 << 0.1;
 
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19 << -510.0 << -242.19;
+    << 1. << 42.19 << -510. << -200.;
   QTest::newRow("Offset only: less than min but ok with offset")
-    << 1.0 << 42.19 << -230.0 << -230.0;
+    << 1. << 42.19 << -230. << -200.;
   QTest::newRow("Offset only: less than min with offset")
-    << 1.0 << -42.19 << -190.0 << -157.81;
+    << 1. << -42.19 << -190. << -190.;
 
   QTest::newRow("Offset only: more than max with offset")
-    << 1.0 << 42.19 << 160.0 << 157.81;
+    << 1. << 42.19 << 160. << 160.;
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.19 << 65010.0 << 242.19;
+    << 1. << -42.19 << 65010.0 << 200.;
   QTest::newRow("Offset only: less than max but ok with offset")
-    << 1.0 << -42.19 << 229.1 << 229.1;
-
-  QTest::newRow("Offset only: max")
-    << 1.0 << 42.19 << std::numeric_limits<double>::max() << 157.81;
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::max() << -242.19;
-  QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19 << std::numeric_limits<double>::infinity() << 157.81;
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::infinity() << -242.19;
-  QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN() << -242.19;
+    << 1. << -42.19 << 229.1 << 200.;
+
 
   // coeff // offset // value // expectedValue
   //---------------------------------------------------------------------------
   // Coefficient
-  QTest::newRow("Coeff only") << 5.0 << 0.0 << 0.1 << 0.1;
+  QTest::newRow("Coeff only") << 5. << 0. << 0.1 << 0.1;
 
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -510.0 << -40.0;
+    << 5. << 0. << -510. << -200.;
   QTest::newRow("Coeff only: less than min but ok with coeff")
-    << 0.5 << 0.0 << -230.0 << -230.0;
+    << 0.5 << 0. << -230. << -200.;
   QTest::newRow("Coeff only: less than min with coeff")
-    << 5.0 << 0.0 << -190.0 << -40.0;
+    << 5. << 0. << -190. << -190.;
 
   QTest::newRow("Coeff only: more than max with coeff")
-    << 5.0 << 0.0 << 160.0 << 40.0;
+    << 5. << 0. << 160. << 160.;
   QTest::newRow("Coeff only: more than max")
-    << 5.0 << 0.0 << 65010.0 << 40.0;
+    << 5. << 0. << 65010. << 200.;
   QTest::newRow("Offset only: less than max but ok with coeff")
-    << 0.5 << 0.0 << 229.2 << 229.2;
-
-  QTest::newRow("Coeff only: max")
-    << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0;
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -40.0;
-  QTest::newRow("Coeff only: infinity")
-    << 5.0 << 0.0 << std::numeric_limits<double>::infinity() << 40.0;
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity() << -40.0;
-  QTest::newRow("Coeff only: Nan")
-    << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN() << -40.0;
+    << 0.5 << 0. << 229.2 << 200.;
 
 
   // coeff // offset // value // expectedValue
   //---------------------------------------------------------------------------
   // Linear
-  QTest::newRow("Linear") << 5.0 << 0.0 << 0.1 << 0.1;
+  QTest::newRow("Linear") << 5. << 0. << 0.1 << 0.1;
 
   QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -510.0 << -42.4;
+    << 5.0 << 12.0 << -510. << -200.;
   QTest::newRow("Linear: less than min but ok with function")
-    << 0.5 << 12.0 << -230.0 << -230.0;
+    << 0.5 << 12.0 << -230. << -200.;
   QTest::newRow("Linear: less than min with function")
-    << 5.0 << 12.0 << -61.5 << -42.4;
+    << 5.0 << 12.0 << -61.5 << -61.5;
 
   QTest::newRow("Linear: more than max with function")
-    << 5.0 << 12.0 << 160.0 << 37.6;
+    << 5.0 << 12.0 << 160. << 160.;
   QTest::newRow("Linear: more than max")
-    << 5.0 << 12.0 << 65010.0 << 37.6;
+    << 5.0 << 12.0 << 65010. << 200.;
   QTest::newRow("Offset only: less than max but ok with function")
-    << 0.5 << 12.0 << 229.2 << 229.2;
-
-  QTest::newRow("Linear: max")
-    << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6;
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -42.4;
-  QTest::newRow("Linear: infinity")
-    << 5.0 << 12.0 << std::numeric_limits<double>::infinity() << 37.6;
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity() << -42.4;
-  QTest::newRow("Linear: Nan")
-    << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN() << -42.4;
+    << 0.5 << 12.0 << 229.2 << 200.;
 }
 
 //-----------------------------------------------------------------------------
@@ -191,8 +158,7 @@ void ctkDoubleSliderValueProxyTester::testSetSliderPosition()
 {
   // Setup
   ctkDoubleSlider slider;
-  slider.setMinimum(-200);
-  slider.setMaximum(200);
+  slider.setRange(-200., 200.);
   slider.setSingleStep(0.01);
   slider.setValue(-32.6);
 
@@ -228,73 +194,32 @@ void ctkDoubleSliderValueProxyTester::testSetSliderPosition_data()
 
   //---------------------------------------------------------------------------
   // Offset
-  QTest::newRow("Offset only") << 1.0 << 42.19 << 0.1 << -42.09 << 0.1;
+  QTest::newRow("Offset only") << 1. << 42.19 << 0.1 << 0.1 << 0.1;
 
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19 << -510.0 << -242.19 << -200.0;
+    << 1. << 42.19 << -510. << -200. << -200.;
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.19 << 65010.0 << 242.19 << 200.0;
-
-  QTest::newRow("Offset only: max")
-    << 1.0 << 42.19 << std::numeric_limits<double>::max()
-    << 157.81 << 200.0;
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::max()
-    << -242.19 << -200.0;
-  QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19 << std::numeric_limits<double>::infinity()
-    << 157.81 << 200.0;
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::infinity()
-    << -242.19 << -200.0;
-  QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN()
-    << -242.19 << -200.0;
+    << 1. << -42.19 << 65010. << 200. << 200.;
 
   //---------------------------------------------------------------------------
   // Coefficient
-  QTest::newRow("Coeff only") << 5.0 << 0.0 << 5.0 << 1.0 << 5.0;
+  QTest::newRow("Coeff only") << 5. << 0. << 5. << 5. << 5.;
 
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -1010.0 << -40.0 << -200.0;
+    << 5. << 0. << -1010. << -200. << -200.;
   QTest::newRow("Coeff only: more than max")
-    << 5.0 << 0.0 << 65010.0 << 40.0 << 200.0;
-
-  QTest::newRow("Coeff only: max")
-    << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0 << 200.0;
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -40.0 << -200.0;
-  QTest::newRow("Coeff only: infinity")
-    << 5.0 << 0.0 << std::numeric_limits<double>::infinity() << 40.0 << 200.0;
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity()
-    << -40.0 << -200.0;
-  QTest::newRow("Coeff only: Nan")
-    << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN()
-    << -40.0 << -200.0;
+    << 5. << 0. << 65010. << 200. << 200.;
 
   //---------------------------------------------------------------------------
   // Linear
-  QTest::newRow("Linear") << 5.0 << 12.0 << 42.0 << 6.0 << 42.0;
+  QTest::newRow("Linear") << 5. << 12. << 42. << 42. << 42.;
 
   QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -5010.0 << -42.4 << -200.0;
+    << 5. << 12. << -5010. << -200. << -200.;
 
   QTest::newRow("Linear: more than max")
-    << 5.0 << 12.0 << 65010.0 << 37.6 << 200.0;
-
-  QTest::newRow("Linear: max")
-    << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6 << 200.0;
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -42.4 << -200.0;
-  QTest::newRow("Linear: infinity")
-    << 5.0 << 12.0 << std::numeric_limits<double>::infinity() << 37.6 << 200.0;
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity()
-    << -42.4 << -200.0;
-  QTest::newRow("Linear: Nan")
-    << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN()
-    << -42.4 << -200.0;
+    << 5. << 12. << 65010. << 200. << 200.;
+
 }
 
 // ----------------------------------------------------------------------------

+ 74 - 143
Libs/Widgets/Testing/Cpp/ctkDoubleSpinBoxValueProxyTest.cpp

@@ -66,6 +66,9 @@ private slots:
 
   void testSetDisplayedValue();
   void testSetDisplayedValue_data();
+
+  void testSetCoefficient();
+  void testSetCoefficient_data();
 };
 
 //-----------------------------------------------------------------------------
@@ -73,8 +76,7 @@ void ctkDoubleSpinBoxValueProxyTester::testSetValue()
 {
   // Setup
   ctkDoubleSpinBox spinBox;
-  spinBox.setMinimum(-200);
-  spinBox.setMaximum(200);
+  spinBox.setRange(-200., 200.);
   spinBox.setValue(-32.6);
 
   QFETCH(double, coefficient);
@@ -113,101 +115,44 @@ void ctkDoubleSpinBoxValueProxyTester::testSetValue_data()
   QTest::newRow("Offset only") << 1.0 << 42.19176 << 0.1 << 0.1 << "0.10";
 
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19176 << -510.0 << -242.19 << "-242.19";
-  QTest::newRow("Offset only: less than min but ok with offset")
-    << 1.0 << 42.19176 << -230.0 << -230.0 << "-230.00";
+    << 1.0 << -42.19176 << -220.0 << -200. << "-200.00";
   QTest::newRow("Offset only: less than min with offset")
-    << 1.0 << -42.1976 << -190.0 << -157.8 << "-157.80";
+    << 1.0 << -42.1976 << -190.0 << -190. << "-190.00";
+  QTest::newRow("Offset only: more than min")
+    << 1.0 << 42.1976 << -190.0 << -190. << "-190.00";
+  QTest::newRow("Offset only: more than min with offset")
+    << 1.0 << 42.19176 << -220.0 << -200. << "-200.00";
 
-  QTest::newRow("Offset only: more than max with offset")
-    << 1.0 << 42.19176 << 160.0 << 157.81 << "157.81";
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.1976 << 65010.0 << 242.2 << "242.20";
-  QTest::newRow("Offset only: less than max but ok with offset")
-    << 1.0 << -42.1976 << 229.1 << 229.1 << "229.10";
-
-  QTest::newRow("Offset only: max")
-    << 1.0 << 42.19176 << std::numeric_limits<double>::max()
-    << 157.81 << "157.81";
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19176 << -std::numeric_limits<double>::max()
-    << -242.19 << "-242.19";
-  QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19176 << std::numeric_limits<double>::infinity()
-    << 157.81 << "157.81";
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19176 << -std::numeric_limits<double>::infinity()
-    << -242.19 << "-242.19";
-  QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19176 << std::numeric_limits<double>::quiet_NaN()
-    << 157.81 << "157.81";
-
-  // coeff // offset // value // expectedValue // expectedStringValue
+    << 1.0 << 42.1976 << 220.0 << 200. << "200.00";
+  QTest::newRow("Offset only: more than max with offset")
+    << 1.0 << 42.19176 << 190.0 << 190. << "190.00";
+  QTest::newRow("Offset only: less than max")
+    << 1.0 << -42.1976 << 190.0 << 190. << "190.00";
+  QTest::newRow("Offset only: less than max with offset")
+    << 1.0 << -42.19176 << 220.0 << 200. << "200.00";
+
   //---------------------------------------------------------------------------
   // Coefficient
   QTest::newRow("Coeff only") << 5.0 << 0.0 << 0.1 << 0.1 << "0.10";
 
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -510.0 << -40.0 << "-40.00";
-  QTest::newRow("Coeff only: less than min but ok with coeff")
-    << 0.5 << 0.0 << -230.0 << -230.0 << "-230.00";
-  QTest::newRow("Coeff only: less than min with coeff")
-    << 5.0 << 0.0 << -190.0 << -40.0 << "-40.00";
-
-  QTest::newRow("Coeff only: more than max with coeff")
-    << 5.0 << 0.0 << 160.0 << 40.0 << "40.00";
-  QTest::newRow("Coeff only: more than max")
-    << 5.0 << 0.0 << 65010.0 << 40.0 << "40.00";
-  QTest::newRow("Offset only: less than max but ok with coeff")
-    << 0.5 << 0.0 << 229.2 << 229.2 << "229.20";
-
-  QTest::newRow("Coeff only: max")
-    << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0 << "40.00";
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -40.0 << "-40.00";
-  QTest::newRow("Coeff only: infinity")
-    << 5.0 << 0.0 << std::numeric_limits<double>::infinity()
-    << 40.0 << "40.00";
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity()
-    << -40.0 << "-40.00";
-  QTest::newRow("Coeff only: Nan")
-    << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN()
-    << 40.0 << "40.00";
-
-
-  // coeff // offset // value // expectedValue // expectedStringValue
-  //---------------------------------------------------------------------------
-  // Linear
-  QTest::newRow("Linear") << 5.0 << 0.0 << 0.1 << 0.1 << "0.10";
+    << 5.0 << 0. << -220.0 << -200. << "-200.00";
+  QTest::newRow("Coeff only: less than min with offset")
+    << 5.0 << 0. << -190.0 << -190. << "-190.00";
+  QTest::newRow("Coeff only: more than min")
+    << 0.5 << 0. << -190.0 << -190. << "-190.00";
+  QTest::newRow("Coeff only: more than min with offset")
+    << 0.5 << 0. << -220.0 << -200. << "-200.00";
 
-  QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -510.0 << -42.4 << "-42.40";
-  QTest::newRow("Linear: less than min but ok with function")
-    << 0.5 << 12.0 << -230.0 << -230.0 << "-230.00";
-  QTest::newRow("Linear: less than min with function")
-    << 5.0 << 12.0 << -61.5 << -42.4 << "-42.40";
-
-  QTest::newRow("Linear: more than max with function")
-    << 5.0 << 12.0 << 160.0 << 37.6 << "37.60";
-  QTest::newRow("Linear: more than max")
-    << 5.0 << 12.0 << 65010.0 << 37.6 << "37.60";
-  QTest::newRow("Offset only: less than max but ok with function")
-    << 0.5 << 12.0 << 229.2 << 229.2 << "229.20";
-
-  QTest::newRow("Linear: max")
-    << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6 << "37.60";
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -42.4 << "-42.40";
-  QTest::newRow("Linear: infinity")
-    << 5.0 << 12.0 << std::numeric_limits<double>::infinity()
-    << 37.6 << "37.60";
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity()
-    << -42.4 << "-42.40";
-  QTest::newRow("Linear: Nan")
-    << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN()
-    << 37.6 << "37.60";
+  QTest::newRow("Coeff only: more than max")
+    << 5. << 0. << 220.0 << 200. << "200.00";
+  QTest::newRow("Coeff only: more than max with offset")
+    << 5. << 0. << 190.0 << 190. << "190.00";
+  QTest::newRow("Coeff only: less than max")
+    << 0.5 << 0. << 190.0 << 190. << "190.00";
+  QTest::newRow("Coeff only: less than max with offset")
+    << 0.5 << 0. << 220.0 << 200. << "200.00";
 }
 
 //-----------------------------------------------------------------------------
@@ -259,25 +204,9 @@ void ctkDoubleSpinBoxValueProxyTester::testSetDisplayedValue_data()
     << 1.0 << 42.19176 << 0.1 << -42.09 << "-42.09" << 0.1;
 
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19176 << -510.0 << -242.19 << "-242.19" << -200.0;
+    << 1.0 << 42.19176 << -510.0 << -200. << "-200.00" << -157.81;
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.1976 << 65010.0 << 242.2 << "242.20" << 200.0;
-
-  QTest::newRow("Offset only: max")
-    << 1.0 << 42.19176 << std::numeric_limits<double>::max()
-    << 157.81 << "157.81" << 200.0;
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19176 << -std::numeric_limits<double>::max()
-    << -242.19 << "-242.19" << -200.0;
-  QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19176 << std::numeric_limits<double>::infinity()
-    << 157.81 << "157.81" << 200.0;
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19176 << -std::numeric_limits<double>::infinity()
-    << -242.19 << "-242.19" << -200.0;
-  QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19176 << std::numeric_limits<double>::quiet_NaN()
-    << 157.81 << "157.81" << 200.0;
+    << 1.0 << -42.1976 << 65010.0 << 200. << "200.00" << 157.8;
 
   //---------------------------------------------------------------------------
   // Coefficient
@@ -285,51 +214,53 @@ void ctkDoubleSpinBoxValueProxyTester::testSetDisplayedValue_data()
     << 5.0 << 0.0 << 5.0 << 1.0 << "1.00" << 5.0;
 
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -1010.0 << -40.0 << "-40.00" << -200.0;
+    << 5.0 << 0.0 << -1010.0 << -200. << "-200.00" << -1000.;
   QTest::newRow("Coeff only: more than max")
-    << 5.0 << 0.0 << 65010.0 << 40.0 << "40.00" << 200.0;
-
-  QTest::newRow("Coeff only: max")
-    << 5.0 << 0.0 << std::numeric_limits<double>::max()
-    << 40.0 << "40.00" << 200.0;
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max()
-    << -40.0 << "-40.00" << -200.0;
-  QTest::newRow("Coeff only: infinity")
-    << 5.0 << 0.0 << std::numeric_limits<double>::infinity()
-    << 40.0 << "40.00" << 200.0;
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity()
-    << -40.0 << "-40.00" << -200.0;
-  QTest::newRow("Coeff only: Nan")
-    << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN()
-    << 40.0 << "40.00" << 200.0;
+    << 5.0 << 0.0 << 65010.0 << 200.0 << "200.00" << 1000.0;
 
   //---------------------------------------------------------------------------
   // Linear
   QTest::newRow("Linear") << 5.0 << 12.0 << 42.0 << 6.0 << "6.00" << 42.0;
 
   QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -5010.0 << -42.4 << "-42.40" << -200.0;
-
+    << 5.0 << 12.0 << -5010.0 << -200. << "-200.00" << -988.;
   QTest::newRow("Linear: more than max")
-    << 5.0 << 12.0 << 65010.0 << 37.6 << "37.60" << 200.0;
-
-  QTest::newRow("Linear: max")
-    << 5.0 << 12.0 << std::numeric_limits<double>::max()
-    << 37.6 << "37.60" << 200.0;
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max()
-    << -42.4 << "-42.40" << -200.0;
-  QTest::newRow("Linear: infinity")
-    << 5.0 << 12.0 << std::numeric_limits<double>::infinity()
-    << 37.6 << "37.60" << 200.0;
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity()
-    << -42.4 << "-42.40" << -200.0;
-  QTest::newRow("Linear: Nan")
-    << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN()
-    << 37.6 << "37.60" << 200.0;
+    << 5.0 << 12.0 << 65010.0 << 200.00 << "200.00" << 1012.;
+}
+
+//-----------------------------------------------------------------------------
+void ctkDoubleSpinBoxValueProxyTester::testSetCoefficient()
+{
+  ctkDoubleSpinBox spinBox;
+  spinBox.setRange(-10000., 10000.);
+  spinBox.setValue(10.);
+
+  ctkLinearValueProxy proxy;
+  proxy.setCoefficient(10.);
+  spinBox.setValueProxy(&proxy);
+
+  ctkTest::COMPARE(spinBox.value(), 10.);
+  ctkTest::COMPARE(spinBox.displayedValue(), 100.);
+
+  QFETCH(double, newCoefficient);
+  proxy.setCoefficient(newCoefficient);
+
+  QFETCH(double, expectedDisplayedValue);
+  ctkTest::COMPARE(spinBox.value(), 10.);
+  ctkTest::COMPARE(spinBox.displayedValue(), expectedDisplayedValue);
+}
+
+//-----------------------------------------------------------------------------
+void ctkDoubleSpinBoxValueProxyTester::testSetCoefficient_data()
+{
+  QTest::addColumn<double>("newCoefficient");
+  QTest::addColumn<double>("expectedDisplayedValue");
+
+  QTest::newRow("100") << 100.0 << 1000.;
+  QTest::newRow("10") << 10.0 << 100.;
+  QTest::newRow("1") << 1.0 << 10.;
+  QTest::newRow("0.10") << 0.1 << 1.;
+  QTest::newRow("-10") << -10.0 << -100.;
 }
 
 // ----------------------------------------------------------------------------

+ 154 - 180
Libs/Widgets/Testing/Cpp/ctkRangeWidgetValueProxyTest.cpp

@@ -23,8 +23,9 @@
 #include <QTest>
 
 // CTK includes
-#include "ctkRangeWidget.h"
+#include "ctkDoubleSpinBox.h"
 #include "ctkLinearValueProxy.h"
+#include "ctkRangeWidget.h"
 #include "ctkTest.h"
 #include "ctkValueProxy.h"
 
@@ -82,14 +83,17 @@ class ctkRangeWidgetValueProxyTester: public QObject
   Q_OBJECT
 private slots:
 
+  void testSetValues();
+  void testSetValues_data();
+
   void testSetMinValue();
   void testSetMinValue_data();
 
   void testSetMaxValue();
   void testSetMaxValue_data();
 
-  void testSetValues();
-  void testSetValues_data();
+  void testSetCoefficient();
+  void testSetCoefficient_data();
 
 private:
   void testSetValueCommonData();
@@ -101,11 +105,9 @@ void ctkRangeWidgetValueProxyTester::testSetValues()
 {
   // Setup
   ctkRangeWidget ranger;
-  ranger.setMinimum(-200);
-  ranger.setMaximum(200);
+  ranger.setRange(-200., 200.);
   ranger.setSingleStep(0.01);
-  ranger.setMinimumValue(-32.6);
-  ranger.setMaximumValue(32.6);
+  ranger.setValues(-32.6, 32.6);
 
   QFETCH(double, coefficient);
   QFETCH(double, offset);
@@ -142,194 +144,126 @@ void ctkRangeWidgetValueProxyTester::testSetValues_data()
   QTest::addColumn<double>("max");
   QTest::addColumn<double>("expectedMax");
 
+  const double max = std::numeric_limits<double>::max();
+  const double inf = std::numeric_limits<double>::infinity();
+  const double NaN = std::numeric_limits<double>::quiet_NaN();
+
   //---------------------------------------------------------------------------
   // Offset
   QTest::newRow("Offset only") << 1.0 << 49.19 << 0.1 << 0.1 << 0.2 << 0.2;
 
-  QTest::newRow("Offset only: max+offset < min+offset < -200") << 1.0 << -42.19
-    << -160.0 << -157.81
-    << -190.9 << -157.81;
-  QTest::newRow("Offset only: max+offset < -200 < min+offset") << 1.0 << -42.19
-    << -0.1 << -157.81
-    << -160.9 << -0.1;
-  QTest::newRow("Offset only: -200 < max+offset < min+offset") << 1.0 << 42.19
-    << -0.1 << -130.9
-    << -130.9 << -0.1;
-
-  QTest::newRow("Offset only: 200 < max+offset < min+offset") << 1.0 << 42.19
-    << 160.0 << 157.81
-    << 190.9 << 157.81;
-  QTest::newRow("Offset only: max+offset < 200 < min+offset") << 1.0 << 42.19
-    << 160.9 << -0.9
-    << -0.9 << 157.81;
-  QTest::newRow("Offset only: max+offset < min+offset < 200") << 1.0 << 42.19
-    << 130.6 << -13.9
-    << -13.9 << 130.6;
+  QTest::newRow("Offset only: max+offset < min+offset < -200")
+    << 1.0 << -42.19 << -160.0 << -157.81 << -190.9 << -157.81;
+  QTest::newRow("Offset only: max+offset < -200 < min+offset")
+    << 1.0 << -42.19 << -0.1 << -157.81 << -160.9 << -0.1;
+  QTest::newRow("Offset only: -200 < max+offset < min+offset")
+    << 1.0 << 42.19<< -0.1 << -130.9 << -130.9 << -0.1;
+
+  QTest::newRow("Offset only: 200 < max+offset < min+offset")
+    << 1.0 << 42.19 << 160.0 << 157.81 << 190.9 << 157.81;
+  QTest::newRow("Offset only: max+offset < 200 < min+offset")
+    << 1.0 << 42.19 << 160.9 << -0.9 << -0.9 << 157.81;
+  QTest::newRow("Offset only: max+offset < min+offset < 200")
+    << 1.0 << 42.19 << 130.6 << -13.9 << -13.9 << 130.6;
 
   QTest::newRow("Offset only: 200 < max = max_double = min = max_double")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::max() << 157.81
-    << std::numeric_limits<double>::max() << 157.81;
+    << 1.0 << 42.19 << max << 157.81 << max << 157.81;
   QTest::newRow("Offset only: max = -max_double < -200 < 200 < min = max_double")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::max() << -242.19
-    << -std::numeric_limits<double>::max() << 157.81;
+    << 1.0 << 42.19 << max << -242.19 << -max << 157.81;
   QTest::newRow("Offset only: max = -max_double = min = -max_double < -200")
-    << 1.0 << 42.19
-    << - std::numeric_limits<double>::max() << -242.19
-    << - std::numeric_limits<double>::max() << -242.19;
+    << 1.0 << 42.19 << -max << -242.19 << -max << -242.19;
 
   QTest::newRow("Offset only: 200 < max = infinity = min = infinity")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::infinity() << 157.81
-    << std::numeric_limits<double>::infinity() << 157.81;
+    << 1.0 << 42.19 << inf << 157.81 << inf << 157.81;
   QTest::newRow("Offset only: max = -infinity < -200 < 200 < min = infinity")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::infinity() << -242.19
-    << -std::numeric_limits<double>::infinity() << 157.81;
+    << 1.0 << 42.19 << inf << -242.19 << -inf << 157.81;
   QTest::newRow("Offset only: max = -infinity = min = -infinity < -200")
-    << 1.0 << 42.19
-    << - std::numeric_limits<double>::infinity() << -242.19
-    << - std::numeric_limits<double>::infinity() << -242.19;
+    << 1.0 << 42.19 << - inf << -242.19 << - inf << -242.19;
 
   QTest::newRow("Offset only: max = min = NaN")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::quiet_NaN() << 157.81
-    << std::numeric_limits<double>::quiet_NaN() << 157.81;
+    << 1.0 << 42.19 << NaN << 157.81 << NaN << 157.81;
   QTest::newRow("Offset only: max = NaN && min > 200")
-    << 1.0 << 42.19
-    << 630.0 << 157.81
-    << std::numeric_limits<double>::quiet_NaN() << 157.81;
+    << 1.0 << 42.19 << 630.0 << 157.81 << NaN << 157.81;
   QTest::newRow("Offset only: min = NaN && max < -200")
-    << 1.0 << 42.19
-    << std::numeric_limits<double>::quiet_NaN() << -74.79
-    << -794348.12 << -74.79;
+    << 1.0 << 42.19 << NaN << -32.6 << -794348.12 << -32.6;
 
   //---------------------------------------------------------------------------
   // Coefficient
   QTest::newRow("Coeff only") << 5.0 << 0.0 << 0.1 << 0.1 << 0.2 << 0.2;
 
-  QTest::newRow("Coeff only: max*coeff < min*coeff < -200") << 5.0 << 0.0
-    << -160.0 << -40.0
-    << -190.9 << -40.0;
-  QTest::newRow("Coeff only: max*coeff < -200 < min*coeff") << 5.0 << 0.0
-    << -0.1 << -40.0
-    << -160.9 << -0.1;
-  QTest::newRow("Coeff only: -200 < max*coeff < min*coeff") << 5.0 << 0.0
-    << -0.1 << -20.9
-    << -20.9 << -0.1;
-
-  QTest::newRow("Coeff only: 200 < max*coeff < min*coeff") << 5.0 << 0.0
-    << 160.0 << 40.0
-    << 190.9 << 40.0;
-  QTest::newRow("Coeff only: max*coeff < 200 < min*coeff") << 5.0 << 0.0
-    << 160.9 << -0.9
-    << -0.9 << 40.00;
-  QTest::newRow("Coeff only: max*coeff < min*coeff < 200") << 5.0 << 0.0
-    << 13.6 << -13.9
-    << -13.9 << 13.6;
+  QTest::newRow("Coeff only: max*coeff < min*coeff < -200")
+    << 5.0 << 0.0 << -160.0 << -40.0 << -190.9 << -40.0;
+  QTest::newRow("Coeff only: max*coeff < -200 < min*coeff")
+    << 5.0 << 0.0 << -0.1 << -40.0 << -160.9 << -0.1;
+  QTest::newRow("Coeff only: -200 < max*coeff < min*coeff")
+    << 5.0 << 0.0 << -0.1 << -20.9 << -20.9 << -0.1;
+
+  QTest::newRow("Coeff only: 200 < max*coeff < min*coeff")
+    << 5.0 << 0.0 << 160.0 << 40.0 << 190.9 << 40.0;
+  QTest::newRow("Coeff only: max*coeff < 200 < min*coeff")
+    << 5.0 << 0.0 << 160.9 << -0.9 << -0.9 << 40.00;
+  QTest::newRow("Coeff only: max*coeff < min*coeff < 200")
+    << 5.0 << 0.0 << 13.6 << -13.9 << -13.9 << 13.6;
 
   QTest::newRow("Coeff only: 200 < max = max_double = min = max_double")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::max() << 40.0
-    << std::numeric_limits<double>::max() << 40.0;
+    << 5.0 << 0.0 << max << 40.0 << max << 40.0;
   QTest::newRow("Coeff only: max = -max_double < -200 < 200 < min = max_double")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::max() << -40.0
-    << - std::numeric_limits<double>::max() << 40.0;
+    << 5.0 << 0.0 << max << -40.0 << - max << 40.0;
   QTest::newRow("Coeff only: max = -max_double = min = -max_double < -200")
-    << 5.0 << 0.0
-    << -std::numeric_limits<double>::max() << -40.0
-    << -std::numeric_limits<double>::max() << -40.0;
+    << 5.0 << 0.0 << -max << -40.0 << -max << -40.0;
 
   QTest::newRow("Coeff only: 200 < max = infinity = min = infinity")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::infinity() << 40.0
-    << std::numeric_limits<double>::infinity() << 40.0;
+    << 5.0 << 0.0 << inf << 40.0 << inf << 40.0;
   QTest::newRow("Coeff only: max = -infinity < -200 < 200 < min = infinity")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::infinity() << -40.0
-    << -std::numeric_limits<double>::infinity() << 40.0;
+    << 5.0 << 0.0 << inf << -40.0 << -inf << 40.0;
   QTest::newRow("Coeff only: max = -infinity = min = -infinity < -200")
-    << 5.0 << 0.0
-    << - std::numeric_limits<double>::infinity() << -40.0
-    << - std::numeric_limits<double>::infinity() << -40.0;
+    << 5.0 << 0.0 << - inf << -40.0 << - inf << -40.0;
 
   QTest::newRow("Coeff only: max = min = NaN")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::quiet_NaN() << 40.0
-    << std::numeric_limits<double>::quiet_NaN() << 40.0;
+    << 5.0 << 0.0 << NaN << 40.0 << NaN << 40.0;
   QTest::newRow("Coeff only: max = NaN && min > 200")
-    << 5.0 << 0.0
-    << 630.0 << 40.0
-    << std::numeric_limits<double>::quiet_NaN() << 40.0;
+    << 5.0 << 0.0 << 630.0 << 40.0 << NaN << 40.0;
   QTest::newRow("Coeff only: min = NaN && max < -200")
-    << 5.0 << 0.0
-    << std::numeric_limits<double>::quiet_NaN() << -6.52
-    << -794348.12 << -6.52;
+    << 5.0 << 0.0 << NaN << -32.6 << -794348.12 << -32.6;
 
   //---------------------------------------------------------------------------
   // Linear
   QTest::newRow("Linear") << 5.0 << 12.0 << 0.1 << 0.1 << 0.2 << 0.2;
 
-  QTest::newRow("Linear:f(max) < f(min) < -200") << 5.0 << 12.0
-    << -160.0 << -42.4
-    << -190.9 << -42.4;
-  QTest::newRow("Linear: f(max) < -200 < f(min)") << 5.0 << 12.0
-    << -0.1 << -42.4
-    << -160.9 << -0.1;
-  QTest::newRow("Linear: -200 < f(max) < f(min)") << 5.0 << 12.0
-    << -0.1 << -20.9
-    << -20.9 << -0.1;
-
-  QTest::newRow("Linear: 200 < f(max) < f(min)") << 5.0 << 12.0
-    << 160.0 << 37.6
-    << 190.9 << 37.6;
-  QTest::newRow("Linear: f(max) < 200 < f(min)") << 5.0 << 12.0
-    << 160.9 << -0.9
-    << -0.9 << 37.6;
-  QTest::newRow("Linear: f(max) < f(min) < 200") << 5.0 << 12.0
-    << 13.6 << -13.9
-    << -13.9 << 13.6;
+  QTest::newRow("Linear:f(max) < f(min) < -200")
+    << 5.0 << 12.0 << -160.0 << -42.4 << -190.9 << -42.4;
+  QTest::newRow("Linear: f(max) < -200 < f(min)")
+    << 5.0 << 12.0 << -0.1 << -42.4 << -160.9 << -0.1;
+  QTest::newRow("Linear: -200 < f(max) < f(min)")
+    << 5.0 << 12.0 << -0.1 << -20.9 << -20.9 << -0.1;
+
+  QTest::newRow("Linear: 200 < f(max) < f(min)")
+    << 5.0 << 12.0 << 160.0 << 37.6 << 190.9 << 37.6;
+  QTest::newRow("Linear: f(max) < 200 < f(min)")
+    << 5.0 << 12.0 << 160.9 << -0.9 << -0.9 << 37.6;
+  QTest::newRow("Linear: f(max) < f(min) < 200")
+    << 5.0 << 12.0 << 13.6 << -13.9 << -13.9 << 13.6;
 
   QTest::newRow("Linear: 200 < max = max_double = min = max_double")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::max() << 37.6
-    << std::numeric_limits<double>::max() << 37.6;
+    << 5.0 << 12.0 << max << 37.6 << max << 37.6;
   QTest::newRow("Linear: max = -max_double < -200 < 200 < min = max_double")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::max() << -42.4
-    << - std::numeric_limits<double>::max() << 37.6;
+    << 5.0 << 12.0 << max << -42.4 << - max << 37.6;
   QTest::newRow("Linear: max = -max_double = min = -max_double < -200")
-    << 5.0 << 12.0
-    << -std::numeric_limits<double>::max() << -42.4
-    << -std::numeric_limits<double>::max() << -42.4;
+    << 5.0 << 12.0 << -max << -42.4 << -max << -42.4;
 
   QTest::newRow("Linear: 200 < max = infinity = min = infinity")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::infinity() << 37.6
-    << std::numeric_limits<double>::infinity() << 37.6;
+    << 5.0 << 12.0 << inf << 37.6 << inf << 37.6;
   QTest::newRow("Linear: max = -infinity < -200 < 200 < min = infinity")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::infinity() << -42.4
-    << -std::numeric_limits<double>::infinity() << 37.6;
+    << 5.0 << 12.0 << inf << -42.4 << -inf << 37.6;
   QTest::newRow("Linear: max = -infinity = min = -infinity < -200")
-    << 5.0 << 12.0
-    << - std::numeric_limits<double>::infinity() << -42.4
-    << - std::numeric_limits<double>::infinity() << -42.4;
+    << 5.0 << 12.0 << - inf << -42.4 << - inf << -42.4;
 
   QTest::newRow("Linear: max = min = NaN")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::quiet_NaN() << 37.6
-    << std::numeric_limits<double>::quiet_NaN() << 37.6;
+    << 5.0 << 12.0 << NaN << 37.6 << NaN << 37.6;
   QTest::newRow("Linear: max = NaN && f(min) > 200")
-    << 5.0 << 12.0
-    << 630.0 << 37.6
-    << std::numeric_limits<double>::quiet_NaN() << 37.6;
+    << 5.0 << 12.0 << 630.0 << 37.6 << NaN << 37.6;
   QTest::newRow("Linear: min = NaN && f(max) < -200")
-    << 5.0 << 12.0
-    << std::numeric_limits<double>::quiet_NaN() << -8.92
-    << -794348.12 << -8.92;
+    << 5.0 << 12.0 << NaN << -32.6 << -794348.12 << -32.6;
 }
 
 //-----------------------------------------------------------------------------
@@ -337,8 +271,7 @@ void ctkRangeWidgetValueProxyTester::testSetMinValue()
 {
   // Setup
   ctkRangeWidget ranger;
-  ranger.setMinimum(-200);
-  ranger.setMaximum(200);
+  ranger.setRange(-200., 200.);
   ranger.setSingleStep(0.01);
   ranger.setMinimumValue(-32.6);
 
@@ -382,22 +315,20 @@ void ctkRangeWidgetValueProxyTester::testSetMinValue_data()
     << 1.0 << -42.19 << -190.0 << -157.81;
 
   QTest::newRow("Offset only: more than max with offset")
-    << 1.0 << 42.19 << 160.0 << 157.81;
+    << 1.0 << 42.19 << 160.0 << 99.;
   QTest::newRow("Offset only: more than max")
-    << 1.0 << -42.19 << 65010.0 << 242.19;
-  QTest::newRow("Offset only: less than max but ok with offset")
-    << 1.0 << -42.19 << 229.1 << 229.1;
+    << 1.0 << -42.19 << 65010.0 << 99.;
 
   QTest::newRow("Offset only: max")
-    << 1.0 << 42.19 << std::numeric_limits<double>::max() << 157.81;
+    << 1.0 << 42.19 << std::numeric_limits<double>::max() << 99.;
   QTest::newRow("Offset only:  min")
     << 1.0 << 42.19 << -std::numeric_limits<double>::max() << -242.19;
   QTest::newRow("Offset only: infinity")
-    << 1.0 << 42.19 << std::numeric_limits<double>::infinity() << 157.81;
+    << 1.0 << 42.19 << std::numeric_limits<double>::infinity() << 99.;
   QTest::newRow("Offset only:  - infinity")
     << 1.0 << 42.19 << -std::numeric_limits<double>::infinity() << -242.19;
   QTest::newRow("Offset only: Nan")
-    << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN() << 157.81;
+    << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN() << 99.;
 
   //---------------------------------------------------------------------------
   // Coefficient
@@ -414,8 +345,8 @@ void ctkRangeWidgetValueProxyTester::testSetMinValue_data()
     << 5.0 << 0.0 << 160.0 << 40.0;
   QTest::newRow("Coeff only: more than max")
     << 5.0 << 0.0 << 65010.0 << 40.0;
-  QTest::newRow("Offset only: less than max but ok with coeff")
-    << 0.5 << 0.0 << 229.2 << 229.2;
+  QTest::newRow("Coeff only: less than max but ok with coeff")
+    << 0.5 << 0.0 << 229.2 << 99.;
 
   QTest::newRow("Coeff only: max")
     << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0;
@@ -443,8 +374,8 @@ void ctkRangeWidgetValueProxyTester::testSetMinValue_data()
     << 5.0 << 12.0 << 160.0 << 37.6;
   QTest::newRow("Linear: more than max")
     << 5.0 << 12.0 << 65010.0 << 37.6;
-  QTest::newRow("Offset only: less than max but ok with function")
-    << 0.5 << 12.0 << 229.2 << 229.2;
+  QTest::newRow("Linear: less than max but ok with function")
+    << 0.5 << 12.0 << 229.2 << 99.;
 
   QTest::newRow("Linear: max")
     << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6;
@@ -501,11 +432,11 @@ void ctkRangeWidgetValueProxyTester::testSetMaxValue_data()
   QTest::newRow("Offset only") << 1.0 << 42.19 << 0.1 << 0.1;
 
   QTest::newRow("Offset only: less than min")
-    << 1.0 << 42.19 << -510.0 << -32.6 - 42.19;
+    << 1.0 << 42.19 << -510.0 << -32.6;
   QTest::newRow("Offset only: less than min but ok with offset")
-    << 1.0 << 42.19 << -230.0 << -32.6 - 42.19;
+    << 1.0 << 42.19 << -230.0 << -32.6;
   QTest::newRow("Offset only: less than min with offset")
-    << 1.0 << -42.19 << -190.0 << 9.59;
+    << 1.0 << -42.19 << -190.0 << -32.6;
 
   QTest::newRow("Offset only: more than max with offset")
     << 1.0 << 42.19 << 160.0 << 157.81;
@@ -516,12 +447,12 @@ void ctkRangeWidgetValueProxyTester::testSetMaxValue_data()
 
   QTest::newRow("Offset only: max")
     << 1.0 << 42.19 << std::numeric_limits<double>::max() << 157.81;
-  QTest::newRow("Offset only:  min")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::max() << -74.79;
+  QTest::newRow("Offset only: min")
+    << 1.0 << 42.19 << -std::numeric_limits<double>::max() << -32.6;
   QTest::newRow("Offset only: infinity")
     << 1.0 << 42.19 << std::numeric_limits<double>::infinity() << 157.81;
-  QTest::newRow("Offset only:  - infinity")
-    << 1.0 << 42.19 << -std::numeric_limits<double>::infinity() << -74.79;
+  QTest::newRow("Offset only: -infinity")
+    << 1.0 << 42.19 << -std::numeric_limits<double>::infinity() << -32.6;
   QTest::newRow("Offset only: Nan")
     << 1.0 << 42.19 << std::numeric_limits<double>::quiet_NaN() << 157.81;
 
@@ -530,11 +461,11 @@ void ctkRangeWidgetValueProxyTester::testSetMaxValue_data()
   QTest::newRow("Coeff only") << 5.0 << 0.0 << 0.1 << 0.1;
 
   QTest::newRow("Coeff only: less than min")
-    << 5.0 << 0.0 << -510.0 << -6.52;
+    << 5.0 << 0.0 << -510.0 << -32.6;
   QTest::newRow("Coeff only: less than min but ok with coeff")
-    << 0.5 << 0.0 << -230.0 << -65.2;
+    << 0.5 << 0.0 << -230.0 << -32.6;;
   QTest::newRow("Coeff only: less than min with coeff")
-    << 5.0 << 0.0 << -190.0 << -6.52;
+    << 5.0 << 0.0 << -190.0 << -32.6;
 
   QTest::newRow("Coeff only: more than max with coeff")
     << 5.0 << 0.0 << 160.0 << 40.0;
@@ -545,12 +476,12 @@ void ctkRangeWidgetValueProxyTester::testSetMaxValue_data()
 
   QTest::newRow("Coeff only: max")
     << 5.0 << 0.0 << std::numeric_limits<double>::max() << 40.0;
-  QTest::newRow("Coeff only:  min")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -6.52;
+  QTest::newRow("Coeff only: min")
+    << 5.0 << 0.0 << -std::numeric_limits<double>::max() << -32.6;
   QTest::newRow("Coeff only: infinity")
     << 5.0 << 0.0 << std::numeric_limits<double>::infinity() << 40.0;
-  QTest::newRow("Coeff only:  - infinity")
-    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity() << -6.52;
+  QTest::newRow("Coeff only: -infinity")
+    << 5.0 << 0.0 << -std::numeric_limits<double>::infinity() << -32.6;
   QTest::newRow("Coeff only: Nan")
     << 5.0 << 0.0 << std::numeric_limits<double>::quiet_NaN() << 40.0;
 
@@ -559,31 +490,74 @@ void ctkRangeWidgetValueProxyTester::testSetMaxValue_data()
   QTest::newRow("Linear") << 5.0 << 0.0 << 0.1 << 0.1;
 
   QTest::newRow("Linear: less than min")
-    << 5.0 << 12.0 << -510.0 << -8.92;
+    << 5.0 << 12.0 << -510.0 << -32.6;
   QTest::newRow("Linear: less than min but ok with function")
-    << 0.5 << 12.0 << -230.0 << -89.2;
+    << 0.5 << 12.0 << -230.0 << -32.6;
   QTest::newRow("Linear: less than min with function")
-    << 5.0 << 12.0 << -61.5 << -8.92;
+    << 5.0 << 12.0 << -61.5 << -32.6;
 
   QTest::newRow("Linear: more than max with function")
     << 5.0 << 12.0 << 160.0 << 37.6;
   QTest::newRow("Linear: more than max")
     << 5.0 << 12.0 << 65010.0 << 37.6;
-  QTest::newRow("Offset only: less than max but ok with function")
+  QTest::newRow("Linear: less than max but ok with function")
     << 0.5 << 12.0 << 229.2 << 229.2;
 
   QTest::newRow("Linear: max")
     << 5.0 << 12.0 << std::numeric_limits<double>::max() << 37.6;
-  QTest::newRow("Linear:  min")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -8.92;
+  QTest::newRow("Linear: min")
+    << 5.0 << 12.0 << -std::numeric_limits<double>::max() << -32.6;
   QTest::newRow("Linear: infinity")
     << 5.0 << 12.0 << std::numeric_limits<double>::infinity() << 37.6;
-  QTest::newRow("Linear:  - infinity")
-    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity() << -8.92;
+  QTest::newRow("Linear: -infinity")
+    << 5.0 << 12.0 << -std::numeric_limits<double>::infinity() << -32.6;
   QTest::newRow("Linear: Nan")
     << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN() << 37.6;
 }
 
+//-----------------------------------------------------------------------------
+void ctkRangeWidgetValueProxyTester::testSetCoefficient()
+{
+  ctkRangeWidget rangeWidget;
+  rangeWidget.setRange(-10000., 10000.);
+  rangeWidget.setValues(10., 50.);
+
+  ctkLinearValueProxy proxy;
+  proxy.setCoefficient(10.);
+  rangeWidget.setValueProxy(&proxy);
+
+  ctkTest::COMPARE(rangeWidget.minimumValue(), 10.);
+  ctkTest::COMPARE(rangeWidget.maximumValue(), 50.);
+  ctkTest::COMPARE(rangeWidget.minimumSpinBox()->displayedValue(), 100.);
+  ctkTest::COMPARE(rangeWidget.maximumSpinBox()->displayedValue(), 500.);
+
+  QFETCH(double, newCoefficient);
+  proxy.setCoefficient(newCoefficient);
+
+  QFETCH(double, expectedMinimumDisplayedValue);
+  QFETCH(double, expectedMaximumDisplayedValue);
+  ctkTest::COMPARE(rangeWidget.minimumValue(), 10.);
+  ctkTest::COMPARE(rangeWidget.maximumValue(), 50.);
+  ctkTest::COMPARE(rangeWidget.minimumSpinBox()->displayedValue(),
+                   expectedMinimumDisplayedValue);
+  ctkTest::COMPARE(rangeWidget.maximumSpinBox()->displayedValue(),
+                   expectedMaximumDisplayedValue);
+}
+
+//-----------------------------------------------------------------------------
+void ctkRangeWidgetValueProxyTester::testSetCoefficient_data()
+{
+  QTest::addColumn<double>("newCoefficient");
+  QTest::addColumn<double>("expectedMinimumDisplayedValue");
+  QTest::addColumn<double>("expectedMaximumDisplayedValue");
+
+  QTest::newRow("100") << 100.0 << 1000. << 5000.;
+  QTest::newRow("10") << 10.0 << 100. << 500.;
+  QTest::newRow("1") << 1.0 << 10. << 50.;
+  QTest::newRow("0.10") << 0.1 << 1. << 5.;
+  QTest::newRow("-10") << -10.0 << -500. << -100.;
+}
+
 // ----------------------------------------------------------------------------
 CTK_TEST_MAIN(ctkRangeWidgetValueProxyTest)
 #include "moc_ctkRangeWidgetValueProxyTest.cpp"

+ 40 - 0
Libs/Widgets/Testing/Cpp/ctkSliderWidgetValueProxyTest.cpp

@@ -55,6 +55,9 @@ private slots:
 
   void testSetValue();
   void testSetValue_data();
+
+  void testSetCoefficient();
+  void testSetCoefficient_data();
 };
 
 //-----------------------------------------------------------------------------
@@ -183,6 +186,43 @@ void ctkSliderWidgetValueProxyTester::testSetValue_data()
     << 5.0 << 12.0 << std::numeric_limits<double>::quiet_NaN() << 37.6;
 }
 
+
+//-----------------------------------------------------------------------------
+void ctkSliderWidgetValueProxyTester::testSetCoefficient()
+{
+  ctkSliderWidget sliderWidget;
+  sliderWidget.setRange(-10000., 10000.);
+  sliderWidget.setValue(10.);
+
+  ctkLinearValueProxy proxy;
+  proxy.setCoefficient(10.);
+  sliderWidget.setValueProxy(&proxy);
+
+  QCOMPARE(sliderWidget.value(), 10.);
+  QCOMPARE(sliderWidget.spinBox()->displayedValue(), 100.);
+
+  QFETCH(double, newCoefficient);
+  proxy.setCoefficient(newCoefficient);
+
+  QFETCH(double, expectedDisplayedValue);
+  QCOMPARE(sliderWidget.value(), 10.);
+  QCOMPARE(sliderWidget.spinBox()->displayedValue(),
+                   expectedDisplayedValue);
+}
+
+//-----------------------------------------------------------------------------
+void ctkSliderWidgetValueProxyTester::testSetCoefficient_data()
+{
+  QTest::addColumn<double>("newCoefficient");
+  QTest::addColumn<double>("expectedDisplayedValue");
+
+  QTest::newRow("100") << 100.0 << 1000.;
+  QTest::newRow("10") << 10.0 << 100.;
+  QTest::newRow("1") << 1.0 << 10.;
+  QTest::newRow("0.10") << 0.1 << 1.;
+  QTest::newRow("-10") << -10.0 << -100.;
+}
+
 // ----------------------------------------------------------------------------
 CTK_TEST_MAIN(ctkSliderWidgetValueProxyTest)
 #include "moc_ctkSliderWidgetValueProxyTest.cpp"

+ 58 - 15
Libs/Widgets/ctkDoubleRangeSlider.cpp

@@ -487,7 +487,8 @@ void ctkDoubleRangeSlider::setValues(double newMinVal, double newMaxVal)
 double ctkDoubleRangeSlider::singleStep()const
 {
   Q_D(const ctkDoubleRangeSlider);
-  return d->SingleStep;
+  double step = d->SingleStep;
+  return step;
 }
 
 // --------------------------------------------------------------------------
@@ -496,13 +497,12 @@ void ctkDoubleRangeSlider::setSingleStep(double newStep)
   Q_D(ctkDoubleRangeSlider);
   if (!this->isValidStep(newStep))
     {
-    qWarning() << "Single step " << newStep << "is out of bounds.";
+    qWarning() << "ctkDoubleRangeSlider::setSingleStep("<< newStep <<")"
+               << "is outside of valid bounds.";
     return;
     }
-
   d->SingleStep = newStep;
-  // The following can fire A LOT of signals that shouldn't be 
-  // fired.
+  // The following can fire A LOT of signals that shouldn't be fired.
   bool oldBlockSignals = this->blockSignals(true);
   d->updateMinOffset(d->MinValue);
   d->updateMaxOffset(d->MaxValue);
@@ -510,7 +510,7 @@ void ctkDoubleRangeSlider::setSingleStep(double newStep)
   double _minvalue = d->MinValue;
   double _maxvalue = d->MaxValue;
   // calling setMinimum or setMaximum can change the values MinimumValue
-  // and MaximumValue, this is why we re-set them later.  
+  // and MaximumValue, this is why we re-set them later.
   this->setMinimum(d->Minimum);
   this->setMaximum(d->Maximum);
   this->setMinimumValue(_minvalue);
@@ -523,25 +523,36 @@ void ctkDoubleRangeSlider::setSingleStep(double newStep)
 // --------------------------------------------------------------------------
 bool ctkDoubleRangeSlider::isValidStep(double step)const
 {
-  const double minStep( qMax(this->maximum() / std::numeric_limits<int>::max(),
-                                   std::numeric_limits<double>::epsilon()) );
-  const double maxStep( qMin(this->maximum() - this->minimum(),
-                                   static_cast<double>(std::numeric_limits<int>::max())) );
-  return step > minStep && step < maxStep;
+  Q_D(const ctkDoubleRangeSlider);
+  const double minStep = qMax(d->Maximum / std::numeric_limits<double>::max(),
+                              std::numeric_limits<double>::epsilon());
+  const double maxStep = qMin(d->Maximum - d->Minimum,
+                              static_cast<double>(std::numeric_limits<int>::max()));
+  return (step >= minStep) && (step <= maxStep);
 }
 
 // --------------------------------------------------------------------------
 double ctkDoubleRangeSlider::tickInterval()const
 {
   Q_D(const ctkDoubleRangeSlider);
-  return d->SingleStep * d->Slider->tickInterval();
+  double interval = d->SingleStep * d->Slider->tickInterval();
+  if (d->Proxy)
+    {
+    interval = d->Proxy.data()->valueFromProxyValue(interval);
+    }
+  return interval;
 }
 
 // --------------------------------------------------------------------------
-void ctkDoubleRangeSlider::setTickInterval(double newTickInterval)
+void ctkDoubleRangeSlider::setTickInterval(double newInterval)
 {
   Q_D(ctkDoubleRangeSlider);
-  d->Slider->setTickInterval(d->toInt(newTickInterval));
+  if (d->Proxy)
+    {
+    newInterval = d->Proxy.data()->proxyValueFromValue(newInterval);
+    }
+  int newIntInterval = d->toInt(newInterval);
+  d->Slider->setTickInterval(newIntInterval);
 }
 
 // --------------------------------------------------------------------------
@@ -706,12 +717,29 @@ void ctkDoubleRangeSlider::setSlider(ctkRangeSlider* newslider)
 void ctkDoubleRangeSlider::setValueProxy(ctkValueProxy* proxy)
 {
   Q_D(ctkDoubleRangeSlider);
-  if (d->Proxy.data() == proxy)
+  if (proxy == d->Proxy.data())
     {
     return;
     }
 
+  this->onValueProxyAboutToBeModified();
+
+  if (d->Proxy.data())
+    {
+    disconnect(d->Proxy.data(), 0, this, 0);
+    }
+
   d->Proxy = proxy;
+
+  if (d->Proxy)
+    {
+    connect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
+            this, SLOT(onValueProxyAboutToBeModified()));
+    connect(d->Proxy.data(), SIGNAL(proxyModified()),
+            this, SLOT(onValueProxyModified()));
+    }
+
+  this->onValueProxyModified();
 }
 
 //----------------------------------------------------------------------------
@@ -720,3 +748,18 @@ ctkValueProxy* ctkDoubleRangeSlider::valueProxy() const
   Q_D(const ctkDoubleRangeSlider);
   return d->Proxy.data();
 }
+
+//-----------------------------------------------------------------------------
+void ctkDoubleRangeSlider::onValueProxyAboutToBeModified()
+{
+  Q_D(ctkDoubleRangeSlider);
+  d->InputMinValue = this->minimumValue();
+  d->InputMaxValue = this->maximumValue();
+}
+
+//-----------------------------------------------------------------------------
+void ctkDoubleRangeSlider::onValueProxyModified()
+{
+  Q_D(ctkDoubleRangeSlider);
+  this->setValues(d->InputMinValue, d->InputMaxValue);
+}

+ 7 - 5
Libs/Widgets/ctkDoubleRangeSlider.h

@@ -76,12 +76,11 @@ public:
   void setSingleStep(double ss);
   double singleStep()const;
 
-  /// This utility function checks whether singleStep is
-  /// valid or not. To be valid, single step should not be too
-  /// small or too large. The singleStep property is used to convert
-  /// the slider value from int to double, therefore the boundary.
+  /// Return true if the step can be handled by the slider, false otherwise.
+  /// An invalid step is a step that can't be used to convert from double
+  /// to int (too large or too small).
   /// \sa singleStep
-  bool isValidStep(double singleStep)const;
+  bool isValidStep(double step)const;
 
   /// 
   /// This property holds the interval between tickmarks.
@@ -261,6 +260,9 @@ protected Q_SLOTS:
   void onPositionsChanged(int min, int max);
   void onRangeChanged(int min, int max);
 
+  void onValueProxyAboutToBeModified();
+  void onValueProxyModified();
+
 protected:
   ctkRangeSlider* slider()const;
   /// Subclasses can change the internal slider

+ 93 - 23
Libs/Widgets/ctkDoubleSlider.cpp

@@ -76,6 +76,7 @@ public:
   double      SingleStep;
   double      PageStep;
   double      Value;
+  /// Converts input value with displayed value
   QWeakPointer<ctkValueProxy> Proxy;
 };
 
@@ -190,24 +191,33 @@ ctkDoubleSlider::~ctkDoubleSlider()
 // --------------------------------------------------------------------------
 void ctkDoubleSlider::setMinimum(double min)
 {
-  Q_D(ctkDoubleSlider);
-  this->setRange(min, qMax(min, d->Maximum));
+  this->setRange(min, this->maximum());
 }
 
 // --------------------------------------------------------------------------
 void ctkDoubleSlider::setMaximum(double max)
 {
-  Q_D(ctkDoubleSlider);
-  this->setRange(qMin(d->Minimum, max), max);
+  this->setRange(this->minimum(), max);
 }
 
 // --------------------------------------------------------------------------
-void ctkDoubleSlider::setRange(double min, double max)
+void ctkDoubleSlider::setRange(double newMin, double newMax)
 {
   Q_D(ctkDoubleSlider);
-  d->Minimum = min;
-  d->Maximum = max;
-  
+  if (d->Proxy)
+    {
+    newMin = d->Proxy.data()->proxyValueFromValue(newMin);
+    newMax = d->Proxy.data()->proxyValueFromValue(newMax);
+    }
+
+  if (newMin > newMax)
+    {
+    qSwap(newMin, newMax);
+    }
+
+  d->Minimum = newMin;
+  d->Maximum = newMax;
+
   if (d->Minimum >= d->Value)
     {
     d->updateOffset(d->Minimum);
@@ -217,7 +227,7 @@ void ctkDoubleSlider::setRange(double min, double max)
     d->updateOffset(d->Maximum);
     }
   d->SettingRange = true;
-  d->Slider->setRange(d->toInt(min), d->toInt(max));
+  d->Slider->setRange(d->toInt(newMin), d->toInt(newMax));
   d->SettingRange = false;
   emit this->rangeChanged(d->Minimum, d->Maximum);
   /// In case QSlider::setRange(...) didn't notify the value
@@ -229,28 +239,49 @@ void ctkDoubleSlider::setRange(double min, double max)
 double ctkDoubleSlider::minimum()const
 {
   Q_D(const ctkDoubleSlider);
-  return d->Minimum;
+  double min = d->Minimum;
+  if (d->Proxy)
+    {
+    min = d->Proxy.data()->valueFromProxyValue(min);
+    }
+  return min;
 }
 
 // --------------------------------------------------------------------------
 double ctkDoubleSlider::maximum()const
 {
   Q_D(const ctkDoubleSlider);
-  return d->Maximum;
+  double max = d->Maximum;
+  if (d->Proxy)
+    {
+    max = d->Proxy.data()->valueFromProxyValue(max);
+    }
+  return max;
 }
 
 // --------------------------------------------------------------------------
 double ctkDoubleSlider::sliderPosition()const
 {
   Q_D(const ctkDoubleSlider);
-  return d->safeFromInt(d->Slider->sliderPosition());
+  int intPosition = d->Slider->sliderPosition();
+  double position = d->safeFromInt(intPosition);
+  if (d->Proxy)
+    {
+    position = d->Proxy.data()->valueFromProxyValue(position);
+    }
+  return position;
 }
 
 // --------------------------------------------------------------------------
-void ctkDoubleSlider::setSliderPosition(double newSliderPosition)
+void ctkDoubleSlider::setSliderPosition(double newPosition)
 {
   Q_D(ctkDoubleSlider);
-  d->Slider->setSliderPosition(d->toInt(newSliderPosition));
+  if (d->Proxy)
+    {
+    newPosition = d->Proxy.data()->proxyValueFromValue(newPosition);
+    }
+  int newIntPosition = d->toInt(newPosition);
+  d->Slider->setSliderPosition(newIntPosition);
 }
 
 // --------------------------------------------------------------------------
@@ -300,7 +331,8 @@ void ctkDoubleSlider::setValue(double newValue)
 double ctkDoubleSlider::singleStep()const
 {
   Q_D(const ctkDoubleSlider);
-  return d->SingleStep;
+  double step = d->SingleStep;
+  return step;
 }
 
 // --------------------------------------------------------------------------
@@ -309,7 +341,8 @@ void ctkDoubleSlider::setSingleStep(double newStep)
   Q_D(ctkDoubleSlider);
   if (!this->isValidStep(newStep))
     {
-    qWarning() << "Single step " << newStep << "is out of bounds.";
+    qWarning() << "ctkDoubleSlider::setSingleStep("<< newStep <<")"
+               << "is outside of valid bounds.";
     return;
     }
   d->SingleStep = newStep;
@@ -326,11 +359,12 @@ void ctkDoubleSlider::setSingleStep(double newStep)
 // --------------------------------------------------------------------------
 bool ctkDoubleSlider::isValidStep(double step)const
 {
-  const double minStep( qMax(this->maximum() / std::numeric_limits<int>::max(),
-                                   std::numeric_limits<double>::epsilon()) );
-  const double maxStep( qMin(this->maximum() - this->minimum(),
-                                   static_cast<double>(std::numeric_limits<int>::max())) );
-  return step > minStep && step < maxStep;
+  Q_D(const ctkDoubleSlider);
+  const double minStep = qMax(d->Maximum / std::numeric_limits<double>::max(),
+                              std::numeric_limits<double>::epsilon());
+  const double maxStep = qMin(d->Maximum - d->Minimum,
+                              static_cast<double>(std::numeric_limits<int>::max()));
+  return step >= minStep && step <= maxStep;
 }
 
 // --------------------------------------------------------------------------
@@ -345,7 +379,8 @@ void ctkDoubleSlider::setPageStep(double newStep)
 {
   Q_D(ctkDoubleSlider);
   d->PageStep = newStep;
-  d->Slider->setPageStep(d->toInt(d->PageStep));
+  int intPageStep = d->toInt(d->PageStep);
+  d->Slider->setPageStep(intPageStep);
 }
 
 // --------------------------------------------------------------------------
@@ -536,12 +571,29 @@ bool ctkDoubleSlider::eventFilter(QObject* watched, QEvent* event)
 void ctkDoubleSlider::setValueProxy(ctkValueProxy* proxy)
 {
   Q_D(ctkDoubleSlider);
-  if (d->Proxy.data() == proxy)
+  if (proxy == d->Proxy.data())
     {
     return;
     }
 
+  this->onValueProxyAboutToBeModified();
+
+  if (d->Proxy.data())
+    {
+    disconnect(d->Proxy.data(), 0, this, 0);
+    }
+
   d->Proxy = proxy;
+
+  if (d->Proxy)
+    {
+    connect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
+            this, SLOT(onValueProxyAboutToBeModified()));
+    connect(d->Proxy.data(), SIGNAL(proxyModified()),
+            this, SLOT(onValueProxyModified()));
+    }
+
+  this->onValueProxyModified();
 }
 
 //----------------------------------------------------------------------------
@@ -551,3 +603,21 @@ ctkValueProxy* ctkDoubleSlider::valueProxy() const
   return d->Proxy.data();
 }
 
+// --------------------------------------------------------------------------
+void ctkDoubleSlider::onValueProxyAboutToBeModified()
+{
+  Q_D(ctkDoubleSlider);
+  d->Slider->setProperty("inputValue", this->value());
+  d->Slider->setProperty("inputMinimum", this->minimum());
+  d->Slider->setProperty("inputMaximum", this->maximum());
+}
+
+// --------------------------------------------------------------------------
+void ctkDoubleSlider::onValueProxyModified()
+{
+  Q_D(ctkDoubleSlider);
+  this->setRange(d->Slider->property("inputMinimum").toDouble(),
+                 d->Slider->property("inputMaximum").toDouble());
+  this->setValue(d->Slider->property("inputValue").toDouble());
+}
+

+ 7 - 6
Libs/Widgets/ctkDoubleSlider.h

@@ -104,16 +104,15 @@ public:
   /// The smaller of two natural steps that an abstract sliders provides and
   /// typically corresponds to the user pressing an arrow key
   /// Default value is 1.
-  /// \sa isValidStep
+  /// \sa isValidStep()
   void setSingleStep(double step);
   double singleStep()const;
 
-  /// This utility function checks whether singleStep is
-  /// valid or not. To be valid, single step should not be too
-  /// small or too large. The singleStep property is used to convert
-  /// the slider value from int to double, therefore the boundary.
+  /// Return true if the step can be handled by the slider, false otherwise.
+  /// An invalid step is a step that can't be used to convert from double
+  /// to int (too large or too small).
   /// \sa singleStep
-  bool isValidStep(double singleStep)const;
+  bool isValidStep(double step)const;
 
   /// 
   /// This property holds the page step.
@@ -257,6 +256,8 @@ protected Q_SLOTS:
   void onValueChanged(int value);
   void onSliderMoved(int position);
   void onRangeChanged(int min, int max);
+  void onValueProxyAboutToBeModified();
+  void onValueProxyModified();
 
 protected:
   QScopedPointer<ctkDoubleSliderPrivate> d_ptr;

+ 84 - 16
Libs/Widgets/ctkDoubleSpinBox.cpp

@@ -25,6 +25,7 @@
 #include "ctkPimpl.h"
 
 // Qt includes
+#include <QDebug>
 #include <QEvent>
 #include <QHBoxLayout>
 #include <QKeyEvent>
@@ -663,6 +664,24 @@ void ctkDoubleSpinBoxPrivate::onValueChanged()
 }
 
 //-----------------------------------------------------------------------------
+void ctkDoubleSpinBoxPrivate::onValueProxyAboutToBeModified()
+{
+  Q_Q(ctkDoubleSpinBox);
+  this->SpinBox->setProperty("inputValue", q->value());
+  this->SpinBox->setProperty("inputMinimum", q->minimum());
+  this->SpinBox->setProperty("inputMaximum", q->maximum());
+}
+
+//-----------------------------------------------------------------------------
+void ctkDoubleSpinBoxPrivate::onValueProxyModified()
+{
+  Q_Q(ctkDoubleSpinBox);
+  q->setRange(this->SpinBox->property("inputMinimum").toDouble(),
+              this->SpinBox->property("inputMaximum").toDouble());
+  q->setValue(this->SpinBox->property("inputValue").toDouble());
+}
+
+//-----------------------------------------------------------------------------
 // ctkDoubleSpinBox
 //-----------------------------------------------------------------------------
 ctkDoubleSpinBox::ctkDoubleSpinBox(QWidget* newParent)
@@ -815,73 +834,102 @@ void ctkDoubleSpinBox::setSuffix(const QString &suffix)
 double ctkDoubleSpinBox::singleStep() const
 {
   Q_D(const ctkDoubleSpinBox);
-  return d->SpinBox->singleStep();
+  double step = d->SpinBox->singleStep();
+  return step;
 }
 
 //-----------------------------------------------------------------------------
-void ctkDoubleSpinBox::setSingleStep(double step)
+void ctkDoubleSpinBox::setSingleStep(double newStep)
 {
   Q_D(ctkDoubleSpinBox);
   if (d->Mode == ctkDoubleSpinBox::SetIfDifferent
-    && d->compare(step, this->singleStep()))
+    && d->compare(newStep, this->singleStep()))
     {
     return;
     }
 
-  d->SpinBox->setSingleStep(step);
+  d->SpinBox->setSingleStep(newStep);
 }
 
 //-----------------------------------------------------------------------------
 double ctkDoubleSpinBox::minimum() const
 {
   Q_D(const ctkDoubleSpinBox);
-  return d->SpinBox->minimum();
+  double min = d->SpinBox->minimum();
+  if (d->Proxy)
+    {
+    min = d->Proxy.data()->valueFromProxyValue(min);
+    }
+  return min;
 }
 
 //-----------------------------------------------------------------------------
-void ctkDoubleSpinBox::setMinimum(double min)
+void ctkDoubleSpinBox::setMinimum(double newMin)
 {
   Q_D(ctkDoubleSpinBox);
+  if (d->Proxy)
+    {
+    newMin = d->Proxy.data()->proxyValueFromValue(newMin);
+    }
   if (d->Mode == ctkDoubleSpinBox::SetIfDifferent
-    && d->compare(min, this->minimum()))
+      && d->compare(newMin, d->SpinBox->minimum()))
     {
     return;
     }
 
-  d->SpinBox->setMinimum(min);
+  d->SpinBox->setMinimum(newMin);
 }
 
 //-----------------------------------------------------------------------------
 double ctkDoubleSpinBox::maximum() const
 {
   Q_D(const ctkDoubleSpinBox);
-  return d->SpinBox->maximum();
+  double max = d->SpinBox->maximum();
+  if (d->Proxy)
+    {
+    max = d->Proxy.data()->valueFromProxyValue(max);
+    }
+  return max;
 }
 
 //-----------------------------------------------------------------------------
-void ctkDoubleSpinBox::setMaximum(double max)
+void ctkDoubleSpinBox::setMaximum(double newMax)
 {
   Q_D(ctkDoubleSpinBox);
+  if (d->Proxy)
+    {
+    newMax = d->Proxy.data()->proxyValueFromValue(newMax);
+    }
   if (d->Mode == ctkDoubleSpinBox::SetIfDifferent
-    && d->compare(max, this->maximum()))
+    && d->compare(newMax, d->SpinBox->maximum()))
     {
     return;
     }
 
-  d->SpinBox->setMaximum(max);
+  d->SpinBox->setMaximum(newMax);
 }
 
 //-----------------------------------------------------------------------------
-void ctkDoubleSpinBox::setRange(double min, double max)
+void ctkDoubleSpinBox::setRange(double newMin, double newMax)
 {
   Q_D(ctkDoubleSpinBox);
+  if (d->Proxy)
+    {
+    newMin = d->Proxy.data()->proxyValueFromValue(newMin);
+    newMax = d->Proxy.data()->proxyValueFromValue(newMax);
+    }
+  if (newMin > newMax)
+    {
+    qSwap(newMin, newMax);
+    }
   if (d->Mode == ctkDoubleSpinBox::SetIfDifferent
-    && d->compare(max, this->maximum()) && d->compare(min, this->minimum()))
+      && d->compare(newMax, d->SpinBox->maximum())
+      && d->compare(newMin, d->SpinBox->minimum()))
     {
     return;
     }
 
-  d->SpinBox->setRange(min, max);
+  d->SpinBox->setRange(newMin, newMax);
 }
 
 //-----------------------------------------------------------------------------
@@ -1056,12 +1104,32 @@ bool ctkDoubleSpinBox::invertedControls() const
 void ctkDoubleSpinBox::setValueProxy(ctkValueProxy* proxy)
 {
   Q_D(ctkDoubleSpinBox);
-  if (d->Proxy.data() == proxy)
+  if (proxy == d->Proxy.data())
     {
     return;
     }
 
+  d->onValueProxyAboutToBeModified();
+
+  if (d->Proxy)
+    {
+    disconnect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
+               d, SLOT(onValueProxyAboutToBeModified()));
+    disconnect(d->Proxy.data(), SIGNAL(proxyModified()),
+               d, SLOT(onValueProxyModified()));
+    }
+
   d->Proxy = proxy;
+
+  if (d->Proxy)
+    {
+    connect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
+            d, SLOT(onValueProxyAboutToBeModified()));
+    connect(d->Proxy.data(), SIGNAL(proxyModified()),
+            d, SLOT(onValueProxyModified()));
+    }
+
+  d->onValueProxyModified();
 }
 
 //----------------------------------------------------------------------------

+ 3 - 0
Libs/Widgets/ctkDoubleSpinBox_p.h

@@ -127,4 +127,7 @@ public:
 public Q_SLOTS:
   void editorTextChanged(const QString& text);
   void onValueChanged();
+
+  void onValueProxyAboutToBeModified();
+  void onValueProxyModified();
 };

+ 75 - 18
Libs/Widgets/ctkRangeWidget.cpp

@@ -238,17 +238,17 @@ ctkRangeWidget::~ctkRangeWidget()
 // --------------------------------------------------------------------------
 double ctkRangeWidget::minimum()const
 {
-  Q_D(const ctkRangeWidget);
-  Q_ASSERT(d->equal(d->MinimumSpinBox->minimum(),d->Slider->minimum()));
-  return d->Slider->minimum();
+  double minimumMaximum[2];
+  this->range(minimumMaximum);
+  return minimumMaximum[0];
 }
 
 // --------------------------------------------------------------------------
 double ctkRangeWidget::maximum()const
 {
-  Q_D(const ctkRangeWidget);
-  Q_ASSERT(d->equal(d->MaximumSpinBox->maximum(), d->Slider->maximum()));
-  return d->Slider->maximum();
+  double minimumMaximum[2];
+  this->range(minimumMaximum);
+  return minimumMaximum[1];
 }
 
 // --------------------------------------------------------------------------
@@ -259,6 +259,15 @@ void ctkRangeWidget::range(double* range)const
   Q_ASSERT(d->equal(d->MaximumSpinBox->maximum(), d->Slider->maximum()));
   range[0] = d->Slider->minimum();
   range[1] = d->Slider->maximum();
+  if (d->Proxy)
+    {
+    range[0] = d->Proxy.data()->valueFromProxyValue(range[0]);
+    range[1] = d->Proxy.data()->valueFromProxyValue(range[1]);
+    if (range[0] > range[1])
+      {
+      qSwap(range[0], range[1]);
+      }
+    }
 }
 
 // --------------------------------------------------------------------------
@@ -371,8 +380,8 @@ void ctkRangeWidget::values(double &minValue, double &maxValue)const
 
   if (d->Proxy)
     {
-    minValue = d->Proxy.data()->valueFromProxyValue(minValue);
-    maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
+    //minValue = d->Proxy.data()->valueFromProxyValue(minValue);
+    //maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
     }
 }
 
@@ -382,13 +391,17 @@ double ctkRangeWidget::minimumValue()const
   Q_D(const ctkRangeWidget);
   Q_ASSERT(d->equal(d->Slider->minimumValue(), d->MinimumSpinBox->value()));
 
-  double val =
+  double minValue =
     d->Changing ? d->MinimumValueBeforeChange : d->Slider->minimumValue();
+  double maxValue =
+    d->Changing ? d->MaximumValueBeforeChange : d->Slider->maximumValue();
   if (d->Proxy)
     {
-    val = d->Proxy.data()->valueFromProxyValue(val);
+    /// The proxy can invert the signs (e.g. linear coef < 0.)
+    //minValue = d->Proxy.data()->valueFromProxyValue(minValue);
+    //maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
     }
-  return val;
+  return qMin(minValue, maxValue);
 }
 
 // --------------------------------------------------------------------------
@@ -397,13 +410,16 @@ double ctkRangeWidget::maximumValue()const
   Q_D(const ctkRangeWidget);
   Q_ASSERT(d->equal(d->Slider->maximumValue(), d->MaximumSpinBox->value()));
 
-  double val =
+  double minValue =
+    d->Changing ? d->MinimumValueBeforeChange : d->Slider->minimumValue();
+  double maxValue =
     d->Changing ? d->MaximumValueBeforeChange : d->Slider->maximumValue();
   if (d->Proxy)
     {
-    val = d->Proxy.data()->valueFromProxyValue(val);
+    //minValue = d->Proxy.data()->valueFromProxyValue(minValue);
+    //maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
     }
-  return val;
+  return qMax(minValue, maxValue);
 }
 
 // --------------------------------------------------------------------------
@@ -412,7 +428,7 @@ void ctkRangeWidget::setMinimumValue(double _value)
   Q_D(ctkRangeWidget);
   if (d->Proxy)
     {
-    _value = d->Proxy.data()->proxyValueFromValue(_value);
+    //_value = d->Proxy.data()->proxyValueFromValue(_value);
     }
 
   // disable the tracking temporally to emit the
@@ -432,7 +448,7 @@ void ctkRangeWidget::setMaximumValue(double _value)
   Q_D(ctkRangeWidget);
   if (d->Proxy)
     {
-    _value = d->Proxy.data()->proxyValueFromValue(_value);
+    //_value = d->Proxy.data()->proxyValueFromValue(_value);
     }
 
   // disable the tracking temporally to emit the
@@ -628,7 +644,8 @@ void ctkRangeWidget::setSingleStep(double step)
   Q_D(ctkRangeWidget);
   if (!d->Slider->isValidStep(step))
     {
-    qWarning() << "Single step" << step << "is out of bounds.";
+    qWarning() << "ctkRangeWidget::setSingleStep(" << step << ")"
+               << "is outside valid bounds";
     return;
     }
   d->MinimumSpinBox->setSingleStep(step);
@@ -839,12 +856,32 @@ ctkDoubleSpinBox* ctkRangeWidget::maximumSpinBox()const
 void ctkRangeWidget::setValueProxy(ctkValueProxy* proxy)
 {
   Q_D(ctkRangeWidget);
-  if (d->Proxy.data() == proxy)
+  if (proxy == d->Proxy.data())
     {
     return;
     }
 
+  this->onValueProxyAboutToBeModified();
+
+  if (d->Proxy)
+    {
+    disconnect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
+               this, SLOT(onValueProxyAboutToBeModified()));
+    disconnect(d->Proxy.data(), SIGNAL(proxyModified()),
+               this, SLOT(onValueProxyModified()));
+    }
+
   d->Proxy = proxy;
+
+  if (d->Proxy)
+    {
+    connect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
+            this, SLOT(onValueProxyAboutToBeModified()));
+    connect(d->Proxy.data(), SIGNAL(proxyModified()),
+            this, SLOT(onValueProxyModified()));
+    }
+
+  this->onValueProxyModified();
 }
 
 //----------------------------------------------------------------------------
@@ -853,3 +890,23 @@ ctkValueProxy* ctkRangeWidget::valueProxy() const
   Q_D(const ctkRangeWidget);
   return d->Proxy.data();
 }
+
+//-----------------------------------------------------------------------------
+void ctkRangeWidget::onValueProxyAboutToBeModified()
+{
+  Q_D(ctkRangeWidget);
+  d->Slider->setProperty("inputMinimumValue", this->minimumValue());
+  d->Slider->setProperty("inputMaximumValue", this->maximumValue());
+  d->Slider->setProperty("inputMinimum", this->minimum());
+  d->Slider->setProperty("inputMaximum", this->maximum());
+}
+
+//-----------------------------------------------------------------------------
+void ctkRangeWidget::onValueProxyModified()
+{
+  Q_D(ctkRangeWidget);
+  this->setRange(d->Slider->property("inputMinimum").toDouble(),
+                 d->Slider->property("inputMaximum").toDouble());
+  this->setValues(d->Slider->property("inputMinimumValue").toDouble(),
+                  d->Slider->property("inputMaximumValue").toDouble());
+}

+ 3 - 0
Libs/Widgets/ctkRangeWidget.h

@@ -231,6 +231,9 @@ protected Q_SLOTS:
   void setMaximumToMinimumSpinBox(double maximum);
   void onSliderRangeChanged(double min, double max);
 
+  void onValueProxyAboutToBeModified();
+  void onValueProxyModified();
+
 protected:
   virtual bool eventFilter(QObject *obj, QEvent *event);