瀏覽代碼

Reject inf single step in ctkRangeWidget

Julien Finet 12 年之前
父節點
當前提交
6749d7f713

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

@@ -27,8 +27,8 @@ set(TEST_SOURCES
   ctkDirectoryButtonTest1.cpp
   ctkDoubleRangeSliderTest1.cpp
   ctkDoubleRangeSliderTest2.cpp
+  ctkDoubleSliderTest.cpp
   ctkDoubleSliderTest1.cpp
-  ctkDoubleSliderTest2.cpp
   ctkDoubleSpinBoxTest.cpp
   ctkDoubleSpinBoxTest1.cpp
   ctkDynamicSpacerTest1.cpp
@@ -181,6 +181,7 @@ set(Tests_MOC_CPP)
 QT4_WRAP_CPP(Tests_MOC_CPP ${Tests_MOC_SRCS})
 QT4_GENERATE_MOCS(
   ctkCoordinatesWidgetTest.cpp
+  ctkDoubleSliderTest.cpp
   ctkDoubleSpinBoxTest.cpp
   ctkFlatProxyModelTest.cpp
   ctkFontButtonTest.cpp
@@ -235,8 +236,8 @@ SIMPLE_TEST( ctkDateRangeWidgetTest1 )
 SIMPLE_TEST( ctkDirectoryButtonTest1 )
 SIMPLE_TEST( ctkDoubleRangeSliderTest1 )
 SIMPLE_TEST( ctkDoubleRangeSliderTest2 )
+SIMPLE_TEST( ctkDoubleSliderTest )
 SIMPLE_TEST( ctkDoubleSliderTest1 )
-SIMPLE_TEST( ctkDoubleSliderTest2 )
 SIMPLE_TEST( ctkDoubleSpinBoxTest )
 SIMPLE_TEST( ctkDoubleSpinBoxTest1 )
 SIMPLE_TEST( ctkDynamicSpacerTest1 )

+ 120 - 0
Libs/Widgets/Testing/Cpp/ctkDoubleSliderTest.cpp

@@ -0,0 +1,120 @@
+/*=========================================================================
+
+  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 "ctkDoubleSlider.h"
+#include "ctkTest.h"
+
+//-----------------------------------------------------------------------------
+class ctkDoubleSliderTester: public QObject
+{
+  Q_OBJECT
+private slots:
+  void testUI();
+
+  void testRange();
+  void testRange_data();
+
+  void testSingleStep();
+  void testSingleStep_data();
+};
+
+// ----------------------------------------------------------------------------
+void ctkDoubleSliderTester::testUI()
+{
+  ctkDoubleSlider slider;
+  slider.show();
+  QTest::qWaitForWindowShown(&slider);
+  // qApp->exec();
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleSliderTester::testRange()
+{
+  ctkDoubleSlider slider;
+
+  QFETCH(double, minimum);
+  QFETCH(double, maximum);
+  slider.setRange(minimum, maximum);
+
+  QFETCH(double, expectedMinimum);
+  QFETCH(double, expectedMaximum);
+  QFETCH(double, expectedValue);
+
+  QCOMPARE(slider.minimum(), expectedMinimum);
+  QCOMPARE(slider.maximum(), expectedMaximum);
+  QCOMPARE(slider.value(), expectedValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleSliderTester::testRange_data()
+{
+  QTest::addColumn<double>("minimum");
+  QTest::addColumn<double>("maximum");
+  QTest::addColumn<double>("expectedMinimum");
+  QTest::addColumn<double>("expectedMaximum");
+  QTest::addColumn<double>("expectedValue");
+
+  QTest::newRow("[20.123,20.1234]") << 20.123 << 20.1234 << 20.123 << 20.1234 << 20.123;
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleSliderTester::testSingleStep()
+{
+  ctkDoubleSlider slider;
+  slider.setValue(50.);
+
+  QFETCH(double, minimum);
+  QFETCH(double, maximum);
+  slider.setRange(minimum, maximum);
+
+  QFETCH(double, singleStep);
+  slider.setSingleStep(singleStep);
+
+  QFETCH(double, expectedValue);
+  QCOMPARE(slider.value(), expectedValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkDoubleSliderTester::testSingleStep_data()
+{
+  QTest::addColumn<double>("minimum");
+  QTest::addColumn<double>("maximum");
+  QTest::addColumn<double>("singleStep");
+  QTest::addColumn<double>("expectedValue");
+
+  QTest::newRow("1.") << 0. << 100. << 1. << 50.;
+  QTest::newRow("100.") << 0. << 100. << 100. << 50.;
+  QTest::newRow("0.1") << 0. << 100. << 0.1 << 50.;
+  QTest::newRow("min") << 0. << 100. << std::numeric_limits<double>::min() << 50.;
+  QTest::newRow("max") << 0. << 100. << std::numeric_limits<double>::max() << 50.;
+  QTest::newRow("-max") << 0. << 100. << -std::numeric_limits<double>::max() << 50.;
+  QTest::newRow("-inf") << 0. << 100. << -std::numeric_limits<double>::infinity() << 50.;
+  QTest::newRow("inf") << 0. << 100. << std::numeric_limits<double>::infinity() << 50.;
+  QTest::newRow("NaN") << 0. << 100. << std::numeric_limits<double>::quiet_NaN() << 50.;
+}
+
+// ----------------------------------------------------------------------------
+CTK_TEST_MAIN(ctkDoubleSliderTest)
+#include "moc_ctkDoubleSliderTest.cpp"

+ 0 - 60
Libs/Widgets/Testing/Cpp/ctkDoubleSliderTest2.cpp

@@ -1,60 +0,0 @@
-/*=========================================================================
-
-  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 <QString>
-#include <QTimer>
-
-// CTK includes
-#include "ctkDoubleSlider.h"
-
-// STD includes
-#include <cstdlib>
-#include <iostream>
-
-//-----------------------------------------------------------------------------
-int ctkDoubleSliderTest2(int argc, char * argv [] )
-{
-  QApplication app(argc, argv);
-
-  ctkDoubleSlider slider;
-  slider.setRange(-1., 1.);
-  slider.setValue(-0.5);
-  slider.setRange(0.,1.);
-  if (slider.value() != 0.)
-    {
-    std::cout << "ctkDoubleSlider::setRange() failed: " << slider.value() << std::endl;
-    return EXIT_FAILURE;
-    }
-  slider.setRange(2.0001, 2.0001);
-  if (slider.value() != 2.0001)
-    {
-    std::cout << "ctkDoubleSlider::setRange() failed: " << slider.value() << std::endl;
-    return EXIT_FAILURE;
-    }
-  slider.show();
-  if (argc < 2 || QString(argv[1]) != "-I" )
-    {
-    QTimer::singleShot(100, &app, SLOT(quit()));
-    }
-  return app.exec();
-}
-

+ 7 - 1
Libs/Widgets/Testing/Cpp/ctkDoubleSpinBoxTest.cpp

@@ -192,7 +192,13 @@ void ctkDoubleSpinBoxTester::testSetRange_data()
   QTest::newRow("[min,max]")
     << std::numeric_limits<double>::min()
     << std::numeric_limits<double>::max()
-    << 0. // \tbd Qt bug ?
+    << std::numeric_limits<double>::min()
+    << std::numeric_limits<double>::max()
+    << 25.;
+  QTest::newRow("[-max,max]")
+    << -std::numeric_limits<double>::max()
+    << std::numeric_limits<double>::max()
+    << -std::numeric_limits<double>::max()
     << std::numeric_limits<double>::max()
     << 25.;
   QTest::newRow("[-inf,inf]")

+ 35 - 0
Libs/Widgets/Testing/Cpp/ctkRangeWidgetTest.cpp

@@ -47,6 +47,10 @@ private slots:
 
   void testSetRange();
   void testSetRange_data();
+
+  void testSetRangeSetValues();
+  void testSetRangeSetValues_data();
+
 };
 
 // ----------------------------------------------------------------------------
@@ -267,6 +271,37 @@ void ctkRangeWidgetTester::testSetRange_data()
     << std::numeric_limits<double>::quiet_NaN();
 }
 
+//-----------------------------------------------------------------------------
+void ctkRangeWidgetTester::testSetRangeSetValues()
+{
+  ctkRangeWidget rangeWidget;
+  QFETCH(double, minimum);
+  QFETCH(double, maximum);
+  rangeWidget.setRange(minimum, maximum);
+
+  rangeWidget.setDecimals(0);
+  rangeWidget.setSingleStep(std::numeric_limits<double>::infinity());
+  QFETCH(double, lowerValue);
+  QFETCH(double, upperValue);
+  rangeWidget.setValues(lowerValue, upperValue);
+}
+
+
+//-----------------------------------------------------------------------------
+void ctkRangeWidgetTester::testSetRangeSetValues_data()
+{
+  QTest::addColumn<double>("minimum");
+  QTest::addColumn<double>("maximum");
+  QTest::addColumn<double>("lowerValue");
+  QTest::addColumn<double>("upperValue");
+
+  QTest::newRow("[-inf,inf,-inf,inf]")
+    << -std::numeric_limits<double>::infinity()
+    << std::numeric_limits<double>::infinity()
+    << -std::numeric_limits<double>::infinity()
+    << std::numeric_limits<double>::infinity();
+}
+
 // ----------------------------------------------------------------------------
 CTK_TEST_MAIN(ctkRangeWidgetTest)
 #include "moc_ctkRangeWidgetTest.cpp"

+ 1 - 1
Libs/Widgets/ctkDoubleSlider.h

@@ -43,7 +43,7 @@ class ctkDoubleSliderPrivate;
 class CTK_WIDGETS_EXPORT ctkDoubleSlider : public QWidget
 {
   Q_OBJECT
-  Q_PROPERTY(double value READ value WRITE setValue)
+  Q_PROPERTY(double value READ value WRITE setValue NOTIFY valueChanged USER true)
   Q_PROPERTY(double sliderPosition READ sliderPosition WRITE setSliderPosition)
   Q_PROPERTY(double singleStep READ singleStep WRITE setSingleStep)
   Q_PROPERTY(double pageStep READ pageStep WRITE setPageStep)

+ 31 - 4
Libs/Widgets/ctkRangeWidget.cpp

@@ -28,6 +28,7 @@
 
 // STD includes
 #include <cmath>
+#include <limits>
 
 //-----------------------------------------------------------------------------
 class ctkRangeWidgetPrivate: public Ui_ctkRangeWidget
@@ -300,6 +301,7 @@ void ctkRangeWidget::setMaximum(double max)
 void ctkRangeWidget::setRange(double min, double max)
 {
   Q_D(ctkRangeWidget);
+  qDebug() << "setRange" << min << max;
   
   double oldMin = d->MinimumSpinBox->minimum();
   double oldMax = d->MaximumSpinBox->maximum();
@@ -316,12 +318,15 @@ void ctkRangeWidget::setRange(double min, double max)
   d->SettingSliderRange = false;
   Q_ASSERT(d->equal(d->MinimumSpinBox->minimum(), d->Slider->minimum()));
   Q_ASSERT(d->equal(d->MaximumSpinBox->maximum(), d->Slider->maximum()));
+  Q_ASSERT(d->equal(d->Slider->minimumValue(), d->MinimumSpinBox->value()));
+  Q_ASSERT(d->equal(d->Slider->maximumValue(), d->MaximumSpinBox->value()));
   d->updateSpinBoxWidth();
   if (oldMin != d->MinimumSpinBox->minimum() ||
       oldMax != d->MaximumSpinBox->maximum())
     {
     emit rangeChanged(d->MinimumSpinBox->minimum(), d->MaximumSpinBox->maximum());
     }
+  qDebug() << "end setRange";
 }
 
 // --------------------------------------------------------------------------
@@ -385,6 +390,8 @@ double ctkRangeWidget::maximumValue()const
 void ctkRangeWidget::setMinimumValue(double _value)
 {
   Q_D(ctkRangeWidget);
+  qDebug() << "setMinimumValue" << _value;
+
   // disable the tracking temporally to emit the
   // signal valueChanged if changeValue() is called
   bool isChanging = d->Changing;
@@ -394,12 +401,14 @@ void ctkRangeWidget::setMinimumValue(double _value)
   Q_ASSERT(d->equal(d->Slider->minimumValue(), d->MinimumSpinBox->value()));
   // restore the prop
   d->Changing = isChanging;
+  qDebug() << "end setMinimumValue";
 }
 
 // --------------------------------------------------------------------------
 void ctkRangeWidget::setMaximumValue(double _value)
 {
   Q_D(ctkRangeWidget);
+  qDebug() << "setMaximumValue" << _value;
   // disable the tracking temporally to emit the
   // signal valueChanged if changeValue() is called
   bool isChanging = d->Changing;
@@ -409,12 +418,14 @@ void ctkRangeWidget::setMaximumValue(double _value)
   Q_ASSERT(d->equal(d->Slider->maximumValue(), d->MaximumSpinBox->value()));
   // restore the prop
   d->Changing = isChanging;
+  qDebug() << "end setMaximumValue";
 }
 
 // --------------------------------------------------------------------------
 void ctkRangeWidget::setValues(double newMinimumValue, double newMaximumValue)
 {
   Q_D(ctkRangeWidget);
+  qDebug() << "setValues" << newMinimumValue << newMaximumValue;
   if (newMinimumValue > newMaximumValue)
     {
     qSwap(newMinimumValue, newMaximumValue);
@@ -442,6 +453,7 @@ void ctkRangeWidget::setValues(double newMinimumValue, double newMaximumValue)
   Q_ASSERT(d->equal(d->Slider->maximumValue(), d->MaximumSpinBox->value()));
   // restore the prop
   d->Changing = isChanging;
+  qDebug() << "end setValues";
 }
 
 // --------------------------------------------------------------------------
@@ -575,8 +587,8 @@ bool ctkRangeWidget::eventFilter(QObject *obj, QEvent *event)
 double ctkRangeWidget::singleStep()const
 {
   Q_D(const ctkRangeWidget);
-  Q_ASSERT(d->equal(d->Slider->singleStep(), d->MinimumSpinBox->singleStep()) &&
-           d->equal(d->Slider->singleStep(), d->MaximumSpinBox->singleStep()));
+  Q_ASSERT(d->equal(d->Slider->singleStep(), d->MinimumSpinBox->singleStep()));
+  Q_ASSERT(d->equal(d->Slider->singleStep(), d->MaximumSpinBox->singleStep()));
   return d->Slider->singleStep();
 }
 
@@ -584,11 +596,26 @@ double ctkRangeWidget::singleStep()const
 void ctkRangeWidget::setSingleStep(double step)
 {
   Q_D(ctkRangeWidget);
+  const double minSingleStep( qMax(this->maximum() / std::numeric_limits<int>::max(),
+                                   std::numeric_limits<double>::epsilon()) );
+  const double maxSingleStep( qMin(this->maximum() - this->minimum(),
+                                   static_cast<double>(std::numeric_limits<int>::max())) );
+  if (step < minSingleStep || step > maxSingleStep)
+    {
+    qWarning() << "ctkRangeWidget single step is out of bounds";
+    return;
+    }
+  qDebug() << "setSingleStep" << step;
+  qDebug() << "min slider: " << d->Slider->minimumValue() << "max slider" << d->Slider->maximumValue();
+  qDebug() << "min spinbox: " << d->MinimumSpinBox->value() << "max spinBox" << d->MaximumSpinBox->value();
   d->MinimumSpinBox->setSingleStep(step);
   d->MaximumSpinBox->setSingleStep(step);
+  qDebug() << "min single step: " << d->MinimumSpinBox->singleStep();
   d->Slider->setSingleStep(d->MinimumSpinBox->singleStep());
-  Q_ASSERT(d->equal(d->Slider->singleStep(), d->MinimumSpinBox->singleStep()) &&
-           d->equal(d->Slider->singleStep(), d->MaximumSpinBox->singleStep()));
+  Q_ASSERT(d->equal(d->Slider->singleStep(), d->MinimumSpinBox->singleStep()));
+  Q_ASSERT(d->equal(d->Slider->singleStep(), d->MaximumSpinBox->singleStep()));
+  Q_ASSERT(d->equal(d->Slider->minimumValue(), d->MinimumSpinBox->value()));
+  Q_ASSERT(d->equal(d->Slider->maximumValue(), d->MaximumSpinBox->value()));
 }
 
 // --------------------------------------------------------------------------