Browse Source

#237 Added SizeAdjustPolicy property to control the resizing behavior.

Sascha Zelzer 12 years ago
parent
commit
9854d31270
2 changed files with 160 additions and 55 deletions
  1. 129 51
      Libs/Widgets/ctkPathLineEdit.cpp
  2. 31 4
      Libs/Widgets/ctkPathLineEdit.h

+ 129 - 51
Libs/Widgets/ctkPathLineEdit.cpp

@@ -31,6 +31,7 @@
 #include <QSettings>
 #include <QStyleOptionComboBox>
 #include <QToolButton>
+#include <QApplication>
 
 // CTK includes
 #include "ctkPathLineEdit.h"
@@ -47,9 +48,11 @@ protected:
 public:
   ctkPathLineEditPrivate(ctkPathLineEdit& object);
   void init();
-  QSize sizeHint(const QString& text)const;
+  QSize recomputeSizeHint(QSize& sh)const;
   void updateFilter();
 
+  void adjustPathLineEditSize();
+
   void createPathLineEditWidget(bool useComboBox);
   QString settingKey()const;
 
@@ -73,6 +76,11 @@ public:
 
   static QString        sCurrentDirectory;   //!< Content the last value of the current directory
   static int            sMaxHistory;     //!< Size of the history, if the history is full and a new value is added, the oldest value is dropped
+
+  ctkPathLineEdit::SizeAdjustPolicy SizeAdjustPolicy;
+
+  mutable QSize SizeHint;
+  mutable QSize MinimumSizeHint;
 };
 
 QString ctkPathLineEditPrivate::sCurrentDirectory = "";
@@ -80,14 +88,15 @@ int ctkPathLineEditPrivate::sMaxHistory = 5;
 
 //-----------------------------------------------------------------------------
 ctkPathLineEditPrivate::ctkPathLineEditPrivate(ctkPathLineEdit& object)
-  :q_ptr(&object)
+  : q_ptr(&object)
+  , LineEdit(0)
+  , ComboBox(0)
+  , BrowseButton(0)
+  , MinimumContentsLength(0)
+  , Filters(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Readable)
+  , HasValidInput(false)
+  , SizeAdjustPolicy(ctkPathLineEdit::AdjustToContentsOnFirstShow)
 {
-  this->LineEdit = 0;
-  this->ComboBox = 0;
-  this->BrowseButton = 0;
-  this->MinimumContentsLength = 17;
-  this->HasValidInput = false;
-  this->Filters = QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Readable;
 }
 
 //-----------------------------------------------------------------------------
@@ -158,42 +167,75 @@ void ctkPathLineEditPrivate::createPathLineEditWidget(bool useComboBox)
 }
 
 //------------------------------------------------------------------------------
-QSize ctkPathLineEditPrivate::sizeHint(const QString& text)const
+QSize ctkPathLineEditPrivate::recomputeSizeHint(QSize& sh)const
 {
   Q_Q(const ctkPathLineEdit);
-  int frame = 0;
-  if (this->ComboBox)
+  if (!sh.isValid())
     {
-    QStyleOptionComboBox option;
-    int arrowWidth = this->ComboBox->style()->subControlRect(
-      QStyle::CC_ComboBox, &option, QStyle::SC_ComboBoxArrow, this->ComboBox).width()
-      + (this->ComboBox->hasFrame() ? 2 : 0);
-    frame = 2 * (this->ComboBox->hasFrame() ? 3 : 0)
-      + arrowWidth
-      + 1; // for mac style, not sure why
+    int frame = 0;
+    if (this->ComboBox)
+    {
+      QStyleOptionComboBox option;
+      int arrowWidth = this->ComboBox->style()->subControlRect(
+            QStyle::CC_ComboBox, &option, QStyle::SC_ComboBoxArrow, this->ComboBox).width()
+          + (this->ComboBox->hasFrame() ? 2 : 0);
+      frame = 2 * (this->ComboBox->hasFrame() ? 3 : 0)
+          + arrowWidth
+          + 1; // for mac style, not sure why
     }
-  else
+    else
     {
-    QStyleOptionFrame option;
-    int frameWidth = this->LineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, q);
-    int horizontalMargin = 2; // QLineEditPrivate::horizontalMargin
-    // See QLineEdit::sizeHint
-    frame = 2 * frameWidth
-      + this->LineEdit->textMargins().left()
-      + this->LineEdit->textMargins().right()
-      + this->LineEdit->contentsMargins().left()
-      + this->LineEdit->contentsMargins().right()
-      + 2 * horizontalMargin;
+      QStyleOptionFrame option;
+      int frameWidth = this->LineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, q);
+      int horizontalMargin = 2; // QLineEditPrivate::horizontalMargin
+      // See QLineEdit::sizeHint
+      frame = 2 * frameWidth
+          + this->LineEdit->textMargins().left()
+          + this->LineEdit->textMargins().right()
+          + this->LineEdit->contentsMargins().left()
+          + this->LineEdit->contentsMargins().right()
+          + 2 * horizontalMargin;
     }
-  int browseWidth = 0;
-  if (q->showBrowseButton())
+    int browseWidth = 0;
+    if (q->showBrowseButton())
     {
-    browseWidth = this->BrowseButton->minimumSizeHint().width();
+      browseWidth = this->BrowseButton->minimumSizeHint().width();
     }
-  int textWidth = this->LineEdit->fontMetrics().width(text);
-  int height = (this->ComboBox ? this->ComboBox->minimumSizeHint() :
-                this->LineEdit->minimumSizeHint()).height();
-  return QSize(frame + textWidth + browseWidth, height);
+
+    // text width
+    int textWidth = 0;
+    if (&sh == &SizeHint || MinimumContentsLength == 0)
+      {
+      switch (SizeAdjustPolicy)
+        {
+        case ctkPathLineEdit::AdjustToContents:
+        case ctkPathLineEdit::AdjustToContentsOnFirstShow:
+          if (this->LineEdit->text().isEmpty())
+            {
+            textWidth = 7 * this->LineEdit->fontMetrics().width(QLatin1Char('x'));
+            }
+          else
+            {
+            textWidth = this->LineEdit->fontMetrics().boundingRect(this->LineEdit->text()).width() + 8;
+            }
+          break;
+        case QComboBox::AdjustToMinimumContentsLength:
+        default:
+          ;
+        }
+      }
+
+    if (MinimumContentsLength > 0)
+      {
+      textWidth = qMax(textWidth, MinimumContentsLength * this->LineEdit->fontMetrics().width(QLatin1Char('X')));
+      }
+
+    int height = (this->ComboBox ? this->ComboBox->minimumSizeHint() :
+                                   this->LineEdit->minimumSizeHint()).height();
+    sh.rwidth() = frame + textWidth + browseWidth;
+    sh.rheight() = height;
+  }
+  return sh.expandedTo(QApplication::globalStrut());
 }
 
 //-----------------------------------------------------------------------------
@@ -215,6 +257,18 @@ void ctkPathLineEditPrivate::updateFilter()
 }
 
 //-----------------------------------------------------------------------------
+void ctkPathLineEditPrivate::adjustPathLineEditSize()
+{
+  Q_Q(ctkPathLineEdit);
+  if (q->sizeAdjustPolicy() == ctkPathLineEdit::AdjustToContents)
+    {
+    q->updateGeometry();
+    q->adjustSize();
+    q->update();
+    }
+}
+
+//-----------------------------------------------------------------------------
 QString ctkPathLineEditPrivate::settingKey()const
 {
   Q_Q(const ctkPathLineEdit);
@@ -509,7 +563,13 @@ void ctkPathLineEdit::updateHasValidInput()
     {
     emit validInputChanged(d->HasValidInput);
     }
-  this->updateGeometry();
+
+  if (d->SizeAdjustPolicy == AdjustToContents)
+    {
+    d->SizeHint = QSize();
+    d->adjustPathLineEditSize();
+    this->updateGeometry();
+    }
 }
 
 //------------------------------------------------------------------------------
@@ -556,6 +616,26 @@ void ctkPathLineEdit::setShowHistoryButton(bool visible)
 }
 
 //------------------------------------------------------------------------------
+ctkPathLineEdit::SizeAdjustPolicy ctkPathLineEdit::sizeAdjustPolicy() const
+{
+  Q_D(const ctkPathLineEdit);
+  return d->SizeAdjustPolicy;
+}
+
+//------------------------------------------------------------------------------
+void ctkPathLineEdit::setSizeAdjustPolicy(ctkPathLineEdit::SizeAdjustPolicy policy)
+{
+  Q_D(ctkPathLineEdit);
+  if (policy == d->SizeAdjustPolicy)
+    return;
+
+  d->SizeAdjustPolicy = policy;
+  d->SizeHint = QSize();
+  d->adjustPathLineEditSize();
+  updateGeometry();
+}
+
+//------------------------------------------------------------------------------
 int ctkPathLineEdit::minimumContentsLength()const
 {
   Q_D(const ctkPathLineEdit);
@@ -566,31 +646,29 @@ int ctkPathLineEdit::minimumContentsLength()const
 void ctkPathLineEdit::setMinimumContentsLength(int length)
 {
   Q_D(ctkPathLineEdit);
+  if (d->MinimumContentsLength == length || length < 0) return;
+
   d->MinimumContentsLength = length;
-  this->updateGeometry();
+
+  if (d->SizeAdjustPolicy == AdjustToContents ||
+      d->SizeAdjustPolicy == AdjustToMinimumContentsLength)
+  {
+    d->SizeHint = QSize();
+    d->adjustPathLineEditSize();
+    this->updateGeometry();
+  }
 }
 
 //------------------------------------------------------------------------------
 QSize ctkPathLineEdit::minimumSizeHint()const
 {
   Q_D(const ctkPathLineEdit);
-  QString fileName = QString('/') + QFileInfo(this->currentPath()).fileName();
-  if (fileName.size() < d->MinimumContentsLength)
-    {
-    fileName = QString("x").repeated(d->MinimumContentsLength);
-    }
-  QSize hint = d->sizeHint(fileName);
-  return hint;
+  return d->recomputeSizeHint(d->MinimumSizeHint);
 }
 
 //------------------------------------------------------------------------------
 QSize ctkPathLineEdit::sizeHint()const
 {
   Q_D(const ctkPathLineEdit);
-  QString path = this->currentPath();
-  if (path.size() < d->MinimumContentsLength)
-    {
-    path = QString("x").repeated(d->MinimumContentsLength);
-    }
-  return d->sizeHint(path);
+  return d->recomputeSizeHint(d->SizeHint);
 }

+ 31 - 4
Libs/Widgets/ctkPathLineEdit.h

@@ -74,7 +74,7 @@ class CTK_WIDGETS_EXPORT ctkPathLineEdit: public QWidget
   Q_PROPERTY(QFileDialog::Options options READ options WRITE setOptions)
 #else
   Q_PROPERTY(Options options READ options WRITE setOptions)
-  Q_FLAGS(Option Options);
+  Q_FLAGS(Option Options)
 #endif
 
   /// This property controls the key used to search the settings for recorded
@@ -91,17 +91,23 @@ class CTK_WIDGETS_EXPORT ctkPathLineEdit: public QWidget
   /// not. Clicking on the button calls opens a dialog to select the current path.
   /// True by default
   /// \sa browse()
-  Q_PROPERTY(bool showBrowseButton READ showBrowseButton WRITE setShowBrowseButton);
+  Q_PROPERTY(bool showBrowseButton READ showBrowseButton WRITE setShowBrowseButton)
 
   /// This property controls whether the history button (arrow button that opens
   /// the history menu) is visible or not.
   /// True by default.
   /// \sa retrieveHistory(), addCurrentPathToHistory(), settingKey
-  Q_PROPERTY(bool showHistoryButton READ showHistoryButton WRITE setShowHistoryButton);
+  Q_PROPERTY(bool showHistoryButton READ showHistoryButton WRITE setShowHistoryButton)
+
+  /// This property holds the policy describing how the size of the path line edit widget
+  /// changes when the content changes.
+  /// The default value is AdjustToContentsOnFirstShow.
+  Q_PROPERTY(SizeAdjustPolicy sizeAdjustPolicy READ sizeAdjustPolicy WRITE setSizeAdjustPolicy)
 
   /// This property holds the minimum number of characters that should fit into
   /// the path line edit.
-  /// The default value is 17.
+  /// The default value is 0.
+  /// If this property is set to a positive value, the minimumSizeHint() and sizeHint() take it into account.
   Q_PROPERTY(int minimumContentsLength READ minimumContentsLength WRITE setMinimumContentsLength)
 
 public:
@@ -143,6 +149,17 @@ public:
   Q_DECLARE_FLAGS(Options, Option)
 #endif
 
+  enum SizeAdjustPolicy
+  {
+    /// The path line edit will always adjust to the contents.
+    AdjustToContents,
+    /// The path line edit will adjust to its contents the first time it is shown.
+    AdjustToContentsOnFirstShow,
+    /// The combobox will adjust to minimumContentsLength. For performance reasons
+    /// use this policy on large models.
+    AdjustToMinimumContentsLength
+  };
+
   /** Default constructor
   */
   ctkPathLineEdit(QWidget *parent = 0);
@@ -192,6 +209,16 @@ public:
   bool showHistoryButton()const;
   void setShowHistoryButton(bool visible);
 
+  /// the policy describing how the size of the combobox changes
+  /// when the content changes
+  ///
+  /// The default value is \c AdjustToContentsOnFirstShow.
+  ///
+  /// \sa SizeAdjustPolicy
+  SizeAdjustPolicy sizeAdjustPolicy() const;
+
+  void setSizeAdjustPolicy(SizeAdjustPolicy policy);
+
   int minimumContentsLength()const;
   void setMinimumContentsLength(int lenght);