Procházet zdrojové kódy

ctkDoubleSlider::setRange wasn't bounding the value

In ctkDoubleSlider::setRange():
In some cases (where calling d->Slider->setRange(...) wasn't changing the
QSlider value), d->Value was keeping a value that was outside of the
new range.
Indeed, in the case (-1, -0.5, 1) (min, value, max) the QSlider have the
following values [-1, 0, 1]. Changing the range to [0., 1.] is changing the
QSlider range to [0, 1] which doesn't change the value (0).
Julien Finet před 14 roky
rodič
revize
1218234a71

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

@@ -26,6 +26,7 @@ SET(TEST_SOURCES
   ctkDoubleRangeSliderTest1.cpp
   ctkDoubleRangeSliderTest2.cpp
   ctkDoubleSliderTest1.cpp
+  ctkDoubleSliderTest2.cpp
   ctkDynamicSpacerTest1.cpp
   ctkDynamicSpacerTest2.cpp
   ctkErrorLogWidgetTest1.cpp
@@ -143,6 +144,7 @@ SIMPLE_TEST( ctkDirectoryButtonTest1 )
 SIMPLE_TEST( ctkDoubleRangeSliderTest1 )
 SIMPLE_TEST( ctkDoubleRangeSliderTest2 )
 SIMPLE_TEST( ctkDoubleSliderTest1 )
+SIMPLE_TEST( ctkDoubleSliderTest2 )
 SIMPLE_TEST( ctkDynamicSpacerTest1 )
 SIMPLE_TEST( ctkDynamicSpacerTest2 )
 SIMPLE_TEST( ctkErrorLogWidgetTest1 )

+ 4 - 2
Libs/Widgets/Testing/Cpp/ctkDoubleSliderTest1.cpp

@@ -46,7 +46,8 @@ int ctkDoubleSliderTest1(int argc, char * argv [] )
   std::cout << "Test setMinimum(5.21)" << std::endl;
   slider.setMinimum(5.21);
   if (!qFuzzyCompare(slider.minimum(), 5.21) ||
-      !qFuzzyCompare(slider.value(),18.54))
+      !qFuzzyCompare(slider.value(),18.54) ||
+      !qFuzzyCompare(slider.sliderPosition(), 18.54))
     {
     std::cerr << "ctkDoubleSlider::setMinimum failed." << slider.value() << std::endl;
     return EXIT_FAILURE;
@@ -54,7 +55,8 @@ int ctkDoubleSliderTest1(int argc, char * argv [] )
   std::cout << "Test setMaximum(1340.2)" << std::endl;
   slider.setMaximum(1340.2);
   if (!qFuzzyCompare(slider.maximum(), 1340.2) ||
-      !qFuzzyCompare(slider.value(), 18.54))
+      !qFuzzyCompare(slider.value(), 18.54) ||
+      !qFuzzyCompare(slider.sliderPosition(), 18.54))
     {
     std::cerr << "ctkDoubleSlider::setMinimum failed." << slider.value() << std::endl;
     return EXIT_FAILURE;

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

@@ -0,0 +1,60 @@
+/*=========================================================================
+
+  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();
+}
+

+ 11 - 25
Libs/Widgets/ctkDoubleSlider.cpp

@@ -159,30 +159,14 @@ ctkDoubleSlider::~ctkDoubleSlider()
 void ctkDoubleSlider::setMinimum(double min)
 {
   Q_D(ctkDoubleSlider);
-  d->Minimum = min;
-  if (d->Minimum >= d->Value)
-    {
-    d->updateOffset(d->Minimum);
-    }
-  d->SettingRange = true;
-  d->Slider->setMinimum(d->toInt(min));
-  d->SettingRange = false;
-  emit this->rangeChanged(d->Minimum, d->Maximum);
+  this->setRange(min, qMax(min, d->Maximum));
 }
 
 // --------------------------------------------------------------------------
 void ctkDoubleSlider::setMaximum(double max)
 {
   Q_D(ctkDoubleSlider);
-  d->Maximum = max;
-  if (d->Maximum <= d->Value)
-    {
-    d->updateOffset(d->Maximum);
-    }
-  d->SettingRange = true;
-  d->Slider->setMaximum(d->toInt(max));
-  d->SettingRange = false;
-  emit this->rangeChanged(d->Minimum, d->Maximum);
+  this->setRange(qMin(d->Minimum, max), max);
 }
 
 // --------------------------------------------------------------------------
@@ -204,6 +188,9 @@ void ctkDoubleSlider::setRange(double min, double max)
   d->Slider->setRange(d->toInt(min), d->toInt(max));
   d->SettingRange = false;
   emit this->rangeChanged(d->Minimum, d->Maximum);
+  /// In case QSlider::setRange(...) didn't notify the value
+  /// has changed.
+  this->setValue(d->Value);
 }
 
 // --------------------------------------------------------------------------
@@ -279,15 +266,14 @@ void ctkDoubleSlider::setSingleStep(double newStep)
 {
   Q_D(ctkDoubleSlider);
   d->SingleStep = newStep;
+  d->updateOffset(d->Value);
   // update the new values of the QSlider
-  double _value = d->Value;
-  d->updateOffset(_value);
-  bool oldBlockSignals = this->blockSignals(true);
-  this->setRange(d->Minimum, d->Maximum);
-  d->Slider->setValue(d->toInt(_value));
-  d->Value = _value;
+  bool oldBlockSignals = d->Slider->blockSignals(true);
+  d->Slider->setRange(d->toInt(d->Minimum), d->toInt(d->Maximum));
+  d->Slider->setValue(d->toInt(d->Value));
   d->Slider->setPageStep(d->toInt(d->PageStep));
-  this->blockSignals(oldBlockSignals);
+  d->Slider->blockSignals(oldBlockSignals);
+  Q_ASSERT(d->Value == d->safeFromInt(d->Slider->value()));
 }
 
 // --------------------------------------------------------------------------