Browse Source

BUG: ctkDoubleSpinBox: Fix SizeHintByValue support when using Qt5

See https://issues.slicer.org/view.php?id=4633

This commit implements minimumSizeHint (identically to sizeHint) to ensure
the widget can be resized based on its value.
Jean-Christophe Fillion-Robin 6 years ago
parent
commit
be5b29d023
2 changed files with 47 additions and 3 deletions
  1. 46 3
      Libs/Widgets/ctkDoubleSpinBox.cpp
  2. 1 0
      Libs/Widgets/ctkDoubleSpinBox_p.h

+ 46 - 3
Libs/Widgets/ctkDoubleSpinBox.cpp

@@ -313,6 +313,7 @@ void ctkDoubleSpinBoxPrivate::setValue(double value, int dec)
   if (this->SizeHintPolicy == ctkDoubleSpinBox::SizeHintByValue)
     {
     this->CachedSizeHint = QSize();
+    this->CachedMinimumSizeHint = QSize();
     q->updateGeometry();
     }
 }
@@ -986,6 +987,7 @@ void ctkDoubleSpinBox
     }
   d->SizeHintPolicy = newSizeHintPolicy;
   d->CachedSizeHint = QSize();
+  d->CachedMinimumSizeHint = QSize();
   this->updateGeometry();
 }
 
@@ -1085,9 +1087,50 @@ QSize ctkDoubleSpinBox::sizeHint() const
 //----------------------------------------------------------------------------
 QSize ctkDoubleSpinBox::minimumSizeHint() const
 {
-  // For some reasons, Superclass::minimumSizeHint() returns the spinbox
-  // sizeHint()
-  return this->spinBox()->minimumSizeHint();
+  Q_D(const ctkDoubleSpinBox);
+  if (d->SizeHintPolicy == ctkDoubleSpinBox::SizeHintByMinMax)
+    {
+    // For some reasons, Superclass::minimumSizeHint() returns the spinbox
+    // sizeHint()
+    return this->spinBox()->minimumSizeHint();
+    }
+  if (!d->CachedMinimumSizeHint.isEmpty())
+    {
+    return d->CachedMinimumSizeHint;
+    }
+
+  QSize newSizeHint;
+  newSizeHint.setHeight(this->lineEdit()->minimumSizeHint().height());
+
+  QString extraString = " "; // give some room
+  QString s = this->text() + extraString;
+  s.truncate(18);
+  int extraWidth = 2; // cursor width
+
+  this->ensurePolished(); // ensure we are using the right font
+  const QFontMetrics fm(this->fontMetrics());
+  newSizeHint.setWidth(fm.width(s + extraString) + extraWidth);
+
+  QStyleOptionSpinBox opt;
+  d->SpinBox->initStyleOptionSpinBox(&opt);
+
+  QSize extraSize(35, 6);
+  opt.rect.setSize(newSizeHint + extraSize);
+  extraSize += newSizeHint - this->style()->subControlRect(
+    QStyle::CC_SpinBox, &opt,
+    QStyle::SC_SpinBoxEditField, this).size();
+  // Converging size hint...
+  opt.rect.setSize(newSizeHint + extraSize);
+  extraSize += newSizeHint - this->style()->subControlRect(
+    QStyle::CC_SpinBox, &opt,
+    QStyle::SC_SpinBoxEditField, this).size();
+  newSizeHint += extraSize;
+
+  opt.rect = this->rect();
+  d->CachedMinimumSizeHint = this->style()->sizeFromContents(
+    QStyle::CT_SpinBox, &opt, newSizeHint, this)
+    .expandedTo(QApplication::globalStrut());
+  return d->CachedMinimumSizeHint;
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 0
Libs/Widgets/ctkDoubleSpinBox_p.h

@@ -98,6 +98,7 @@ public:
   mutable QValidator::State CachedState;
   mutable int CachedDecimals;
   mutable QSize CachedSizeHint;
+  mutable QSize CachedMinimumSizeHint;
   bool ForceInputValueUpdate;
 
   QPointer<ctkValueProxy> Proxy;