diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2019-09-24 13:58:08 +0200 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2019-11-15 20:45:24 +0100 |
commit | 360df2cf74410b05d1cab0192f2d0ff5a39db59e (patch) | |
tree | 4a7a7c0b0666e30bb36390857d3905860b647aef | |
parent | 5abb976f23ef0f3cbb7b720e523c08d768c76c0e (diff) |
QComboBox: add property placeholderText
QComboBox had no option to tell the user that he must select an item -
there was no placeholder text like e.g. in QLineEdit. This feature is
widely used in html forms so we should support it also.
Therefore add a new property 'placeholderText' to specify a text which
should be shown when the current selected index is invalid.
[ChangeLog][QtWidgets][QComboBox] QComboBox got a new property
'placeholderText'
Change-Id: If6dac45c9f43455474e267907b0b0d893301c611
Fixes: QTBUG-1556
Fixes: QTBUG-2776
Fixes: QTBUG-77141
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r-- | src/widgets/widgets/qcombobox.cpp | 56 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox.h | 4 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox_p.h | 1 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp | 25 |
4 files changed, 80 insertions, 6 deletions
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 9a0e969e1c..2d21187317 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -368,6 +368,8 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const } if (minimumContentsLength > 0) sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.horizontalAdvance(QLatin1Char('X')) + (hasIcon ? iconSize.width() + 4 : 0))); + if (!placeholderText.isEmpty()) + sh.setWidth(qMax(sh.width(), fm.boundingRect(placeholderText).width())); // height @@ -1110,8 +1112,9 @@ void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int q->updateGeometry(); } - // set current index if combo was previously empty - if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid()) { + // set current index if combo was previously empty and there is no placeholderText + if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid() && + placeholderText.isEmpty()) { q->setCurrentIndex(0); // need to emit changed if model updated index "silently" } else if (currentIndex.row() != indexBeforeChange) { @@ -1214,10 +1217,9 @@ void QComboBox::initStyleOption(QStyleOptionComboBox *option) const } else { option->activeSubControls = d->hoverControl; } - if (d->currentIndex.isValid()) { - option->currentText = currentText(); + option->currentText = currentText(); + if (d->currentIndex.isValid()) option->currentIcon = d->itemIcon(d->currentIndex); - } option->iconSize = iconSize(); if (d->container && d->container->isVisible()) option->state |= QStyle::State_On; @@ -1772,6 +1774,45 @@ void QComboBox::setIconSize(const QSize &size) } /*! + \property QComboBox::placeholderText + \brief Sets a \a placeholderText text shown when no valid index is set + + The \a placeholderText will be shown when an invalid index is set. The + text is not accessible in the dropdown list. When this function is called + before items are added the placeholder text will be shown, otherwise you + have to call setCurrentIndex(-1) programmatically if you want to show the + placeholder text. + Set an empty placeholder text to reset the setting. + + When the QComboBox is editable, use QLineEdit::setPlaceholderText() + instead. + + \since 5.15 +*/ +void QComboBox::setPlaceholderText(const QString &placeholderText) +{ + Q_D(QComboBox); + if (placeholderText == d->placeholderText) + return; + + d->placeholderText = placeholderText; + if (currentIndex() == -1) { + if (d->placeholderText.isEmpty() && currentIndex() == -1) + setCurrentIndex(0); + else + update(); + } else { + updateGeometry(); + } +} + +QString QComboBox::placeholderText() const +{ + Q_D(const QComboBox); + return d->placeholderText; +} + +/*! \property QComboBox::editable \brief whether the combo box can be edited by the user @@ -2249,7 +2290,7 @@ QString QComboBox::currentText() const else if (d->currentIndex.isValid()) return d->itemText(d->currentIndex); else - return QString(); + return d->placeholderText; } /*! @@ -3079,6 +3120,9 @@ void QComboBox::paintEvent(QPaintEvent *) initStyleOption(&opt); painter.drawComplexControl(QStyle::CC_ComboBox, opt); + if (currentIndex() < 0) + opt.palette.setBrush(QPalette::ButtonText, opt.palette.brush(QPalette::ButtonText).color().lighter()); + // draw the icon and text painter.drawControl(QStyle::CE_ComboBoxLabel, opt); } diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index 286772c091..4f89d7f542 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -71,6 +71,7 @@ class Q_WIDGETS_EXPORT QComboBox : public QWidget Q_PROPERTY(SizeAdjustPolicy sizeAdjustPolicy READ sizeAdjustPolicy WRITE setSizeAdjustPolicy) Q_PROPERTY(int minimumContentsLength READ minimumContentsLength WRITE setMinimumContentsLength) Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) + Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText) #if QT_CONFIG(completer) #if QT_DEPRECATED_SINCE(5, 13) @@ -148,6 +149,9 @@ public: QSize iconSize() const; void setIconSize(const QSize &size); + void setPlaceholderText(const QString &placeholderText); + QString placeholderText() const; + bool isEditable() const; void setEditable(bool editable); void setLineEdit(QLineEdit *edit); diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index 5967776a61..00211d70aa 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -417,6 +417,7 @@ public: int maxVisibleItems; int maxCount; int modelColumn; + QString placeholderText; bool inserting; mutable QSize minimumSizeHint; mutable QSize sizeHint; diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index eed4fe3539..cab13092cb 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -397,6 +397,31 @@ void tst_QComboBox::getSetCheck() QCOMPARE(4, obj1.currentIndex()); // Valid obj1.setCurrentIndex(INT_MAX); QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1 + + obj1.setIconSize(QSize(64, 32)); + QCOMPARE(obj1.iconSize(), QSize(64, 32)); + obj1.setIconSize(QSize()); + const int iconWidth = obj1.style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, &obj1); + QCOMPARE(obj1.iconSize(), QSize(iconWidth, iconWidth)); + + const QString placeholderText("Please select"); + obj1.setCurrentIndex(1); + obj1.setPlaceholderText(placeholderText); + QCOMPARE(obj1.placeholderText(), placeholderText); + QCOMPARE(obj1.currentText(), "2"); + QCOMPARE(obj1.currentIndex(), 1); + obj1.setPlaceholderText(QString()); // should not change anything + QCOMPARE(obj1.placeholderText(), QString()); + QCOMPARE(obj1.currentText(), "2"); + + obj1.clear(); + obj1.setPlaceholderText(placeholderText); + obj1.addItems({"1", "2", "3", "4", "5"}); + QCOMPARE(obj1.currentText(), placeholderText); + QCOMPARE(obj1.currentIndex(), -1); + obj1.setPlaceholderText(QString()); // should not change anything + QCOMPARE(obj1.currentText(), "1"); + QCOMPARE(obj1.currentIndex(), 0); } typedef QList<QVariant> VariantList; |