1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qcombobox.h"
44 #ifndef QT_NO_COMBOBOX
45 #include <qstylepainter.h>
46 #include <qlineedit.h>
47 #include <qapplication.h>
48 #include <qdesktopwidget.h>
49 #include <qlistview.h>
50 #include <qtableview.h>
51 #include <qitemdelegate.h>
56 #include <qscrollbar.h>
57 #include <qtreeview.h>
58 #include <qheaderview.h>
60 #include <private/qapplication_p.h>
61 #include <private/qcombobox_p.h>
62 #include <private/qabstractitemmodel_p.h>
63 #include <private/qabstractscrollarea_p.h>
64 #include <private/qsoftkeymanager_p.h>
67 #include <private/qt_x11_p.h>
69 #if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS) && !defined(QT_NO_STYLE_MAC)
70 #include <private/qcore_mac_p.h>
72 #include <private/qt_cocoa_helpers_mac_p.h>
75 # include <private/qeffects_p.h>
77 #ifndef QT_NO_ACCESSIBILITY
78 #include "qaccessible.h"
83 QComboBoxPrivate::QComboBoxPrivate()
88 insertPolicy(QComboBox::InsertAtBottom),
89 sizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow),
90 minimumContentsLength(0),
93 duplicatesEnabled(false),
99 arrowState(QStyle::State_None),
100 hoverControl(QStyle::SC_None),
101 autoCompletionCaseSensitivity(Qt::CaseInsensitive),
102 indexBeforeChange(-1)
103 #ifndef QT_NO_COMPLETER
109 QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewItem &option,
110 const QModelIndex &index) const
112 QStyleOptionMenuItem menuOption;
114 QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu"));
115 QVariant value = index.data(Qt::ForegroundRole);
116 if (value.canConvert<QBrush>()) {
117 resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value));
118 resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value));
119 resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
121 menuOption.palette = resolvedpalette;
122 menuOption.state = QStyle::State_None;
123 if (mCombo->window()->isActiveWindow())
124 menuOption.state = QStyle::State_Active;
125 if ((option.state & QStyle::State_Enabled) && (index.model()->flags(index) & Qt::ItemIsEnabled))
126 menuOption.state |= QStyle::State_Enabled;
128 menuOption.palette.setCurrentColorGroup(QPalette::Disabled);
129 if (option.state & QStyle::State_Selected)
130 menuOption.state |= QStyle::State_Selected;
131 menuOption.checkType = QStyleOptionMenuItem::NonExclusive;
132 menuOption.checked = mCombo->currentIndex() == index.row();
133 if (QComboBoxDelegate::isSeparator(index))
134 menuOption.menuItemType = QStyleOptionMenuItem::Separator;
136 menuOption.menuItemType = QStyleOptionMenuItem::Normal;
138 QVariant variant = index.model()->data(index, Qt::DecorationRole);
139 switch (variant.type()) {
141 menuOption.icon = qvariant_cast<QIcon>(variant);
143 case QVariant::Color: {
144 static QPixmap pixmap(option.decorationSize);
145 pixmap.fill(qvariant_cast<QColor>(variant));
146 menuOption.icon = pixmap;
149 menuOption.icon = qvariant_cast<QPixmap>(variant);
152 if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) {
153 menuOption.palette.setBrush(QPalette::All, QPalette::Background,
154 qvariant_cast<QBrush>(index.data(Qt::BackgroundRole)));
156 menuOption.text = index.model()->data(index, Qt::DisplayRole).toString()
157 .replace(QLatin1Char('&'), QLatin1String("&&"));
158 menuOption.tabWidth = 0;
159 menuOption.maxIconWidth = option.decorationSize.width() + 4;
160 menuOption.menuRect = option.rect;
161 menuOption.rect = option.rect;
163 // Make sure fonts set on the combo box also overrides the font for the popup menu.
164 if (mCombo->testAttribute(Qt::WA_SetFont)
165 || mCombo->testAttribute(Qt::WA_MacSmallSize)
166 || mCombo->testAttribute(Qt::WA_MacMiniSize)
167 || mCombo->font() != qt_app_fonts_hash()->value("QComboBox", QFont()))
168 menuOption.font = mCombo->font();
170 menuOption.font = qt_app_fonts_hash()->value("QComboMenuItem", mCombo->font());
172 menuOption.fontMetrics = QFontMetrics(menuOption.font);
177 #ifdef QT_KEYPAD_NAVIGATION
178 void QComboBoxPrivate::_q_completerActivated()
181 if ( QApplication::keypadNavigationEnabled()
184 && q->completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ) {
185 q->setEditFocus(false);
190 void QComboBoxPrivate::updateArrow(QStyle::StateFlag state)
193 if (arrowState == state)
196 QStyleOptionComboBox opt;
197 q->initStyleOption(&opt);
198 q->update(q->style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, q));
201 void QComboBoxPrivate::_q_modelReset()
205 lineEdit->setText(QString());
206 updateLineEditGeometry();
208 if (currentIndex.row() != indexBeforeChange)
209 _q_emitCurrentIndexChanged(currentIndex);
213 void QComboBoxPrivate::_q_modelDestroyed()
215 model = QAbstractItemModelPrivate::staticEmptyModel();
219 //Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
220 QRect QComboBoxPrivate::popupGeometry(int screen) const
223 return QApplication::desktop()->screenGeometry(screen);
224 #elif defined Q_WS_X11
225 if (X11->desktopEnvironment == DE_KDE)
226 return QApplication::desktop()->screenGeometry(screen);
228 return QApplication::desktop()->availableGeometry(screen);
230 return QApplication::desktop()->availableGeometry(screen);
234 bool QComboBoxPrivate::updateHoverControl(const QPoint &pos)
238 QRect lastHoverRect = hoverRect;
239 QStyle::SubControl lastHoverControl = hoverControl;
240 bool doesHover = q->testAttribute(Qt::WA_Hover);
241 if (lastHoverControl != newHoverControl(pos) && doesHover) {
242 q->update(lastHoverRect);
243 q->update(hoverRect);
249 QStyle::SubControl QComboBoxPrivate::newHoverControl(const QPoint &pos)
252 QStyleOptionComboBox opt;
253 q->initStyleOption(&opt);
254 opt.subControls = QStyle::SC_All;
255 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, pos, q);
256 hoverRect = (hoverControl != QStyle::SC_None)
257 ? q->style()->subControlRect(QStyle::CC_ComboBox, &opt, hoverControl, q)
263 Computes a size hint based on the maximum width
264 for the items in the combobox.
266 int QComboBoxPrivate::computeWidthHint() const
268 Q_Q(const QComboBox);
271 const int count = q->count();
272 const int iconWidth = q->iconSize().width() + 4;
273 const QFontMetrics &fontMetrics = q->fontMetrics();
275 for (int i = 0; i < count; ++i) {
276 const int textWidth = fontMetrics.width(q->itemText(i));
277 if (q->itemIcon(i).isNull())
278 width = (qMax(width, textWidth));
280 width = (qMax(width, textWidth + iconWidth));
283 QStyleOptionComboBox opt;
284 q->initStyleOption(&opt);
286 tmp = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, tmp, q);
290 QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
292 Q_Q(const QComboBox);
294 bool hasIcon = sizeAdjustPolicy == QComboBox::AdjustToMinimumContentsLengthWithIcon ? true : false;
295 int count = q->count();
296 QSize iconSize = q->iconSize();
297 const QFontMetrics &fm = q->fontMetrics();
300 if (&sh == &sizeHint || minimumContentsLength == 0) {
301 switch (sizeAdjustPolicy) {
302 case QComboBox::AdjustToContents:
303 case QComboBox::AdjustToContentsOnFirstShow:
305 sh.rwidth() = 7 * fm.width(QLatin1Char('x'));
307 for (int i = 0; i < count; ++i) {
308 if (!q->itemIcon(i).isNull()) {
310 sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width() + iconSize.width() + 4));
312 sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width()));
317 case QComboBox::AdjustToMinimumContentsLength:
318 for (int i = 0; i < count && !hasIcon; ++i)
319 hasIcon = !q->itemIcon(i).isNull();
324 for (int i = 0; i < count && !hasIcon; ++i)
325 hasIcon = !q->itemIcon(i).isNull();
327 if (minimumContentsLength > 0)
328 sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.width(QLatin1Char('X')) + (hasIcon ? iconSize.width() + 4 : 0)));
332 sh.setHeight(qMax(qCeil(QFontMetricsF(fm).height()), 14) + 2);
334 sh.setHeight(qMax(sh.height(), iconSize.height() + 2));
337 // add style and strut values
338 QStyleOptionComboBox opt;
339 q->initStyleOption(&opt);
340 sh = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, q);
342 return sh.expandedTo(QApplication::globalStrut());
345 void QComboBoxPrivate::adjustComboBoxSize()
347 viewContainer()->adjustSizeTimer.start(20, container);
350 void QComboBoxPrivate::updateLayoutDirection()
352 Q_Q(const QComboBox);
353 QStyleOptionComboBox opt;
354 q->initStyleOption(&opt);
355 Qt::LayoutDirection dir = Qt::LayoutDirection(
356 q->style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, q));
358 lineEdit->setLayoutDirection(dir);
360 container->setLayoutDirection(dir);
364 void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent)
366 if (timerEvent->timerId() == adjustSizeTimer.timerId()) {
367 adjustSizeTimer.stop();
368 if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) {
369 combo->updateGeometry();
376 void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e)
378 QStyleOptionComboBox opt = comboStyleOption();
379 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) {
381 myOpt.initFrom(this);
382 QStyleHintReturnMask mask;
383 if (combo->style()->styleHint(QStyle::SH_Menu_Mask, &myOpt, this, &mask)) {
384 setMask(mask.region);
389 QFrame::resizeEvent(e);
392 void QComboBoxPrivateContainer::leaveEvent(QEvent *)
394 // On Mac using the Mac style we want to clear the selection
395 // when the mouse moves outside the popup.
397 QStyleOptionComboBox opt = comboStyleOption();
398 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo))
399 view->clearSelection();
403 QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent)
404 : QFrame(parent, Qt::Popup), combo(parent), view(0), top(0), bottom(0)
406 // we need the combobox and itemview
410 setAttribute(Qt::WA_WindowPropagation);
411 setAttribute(Qt::WA_X11NetWmWindowTypeCombo);
414 blockMouseReleaseTimer.setSingleShot(true);
416 // we need a vertical layout
417 QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
418 layout->setSpacing(0);
419 layout->setMargin(0);
422 setItemView(itemView);
424 // add scroller arrows if style needs them
425 QStyleOptionComboBox opt = comboStyleOption();
426 const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
428 top = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepSub, this);
429 bottom = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepAdd, this);
436 setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
439 layout->insertWidget(0, top);
440 connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
443 layout->addWidget(bottom);
444 connect(bottom, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
447 // Some styles (Mac) have a margin at the top and bottom of the popup.
448 layout->insertSpacing(0, 0);
449 layout->addSpacing(0);
450 updateTopBottomMargin();
453 void QComboBoxPrivateContainer::scrollItemView(int action)
455 #ifndef QT_NO_SCROLLBAR
456 if (view->verticalScrollBar())
457 view->verticalScrollBar()->triggerAction(static_cast<QAbstractSlider::SliderAction>(action));
462 Hides or shows the scrollers when we emulate a popupmenu
464 void QComboBoxPrivateContainer::updateScrollers()
466 #ifndef QT_NO_SCROLLBAR
470 if (isVisible() == false)
473 QStyleOptionComboBox opt = comboStyleOption();
474 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo) &&
475 view->verticalScrollBar()->minimum() < view->verticalScrollBar()->maximum()) {
477 bool needTop = view->verticalScrollBar()->value()
478 > (view->verticalScrollBar()->minimum() + spacing());
479 bool needBottom = view->verticalScrollBar()->value()
480 < (view->verticalScrollBar()->maximum() - spacing()*2);
493 #endif // QT_NO_SCROLLBAR
497 Cleans up when the view is destroyed.
499 void QComboBoxPrivateContainer::viewDestroyed()
502 setItemView(new QComboBoxListView());
506 Returns the item view used for the combobox popup.
508 QAbstractItemView *QComboBoxPrivateContainer::itemView() const
514 Sets the item view to be used for the combobox popup.
516 void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
522 view->removeEventFilter(this);
523 view->viewport()->removeEventFilter(this);
524 #ifndef QT_NO_SCROLLBAR
525 disconnect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
526 this, SLOT(updateScrollers()));
527 disconnect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
528 this, SLOT(updateScrollers()));
530 disconnect(view, SIGNAL(destroyed()),
531 this, SLOT(viewDestroyed()));
537 // setup the item view
539 view->setParent(this);
540 view->setAttribute(Qt::WA_MacShowFocusRect, false);
541 qobject_cast<QBoxLayout*>(layout())->insertWidget(top ? 2 : 0, view);
542 view->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
543 view->installEventFilter(this);
544 view->viewport()->installEventFilter(this);
545 view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
546 QStyleOptionComboBox opt = comboStyleOption();
547 const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
548 #ifndef QT_NO_SCROLLBAR
550 view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
552 if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
554 view->setMouseTracking(true);
556 view->setSelectionMode(QAbstractItemView::SingleSelection);
557 view->setFrameStyle(QFrame::NoFrame);
558 view->setLineWidth(0);
559 view->setEditTriggers(QAbstractItemView::NoEditTriggers);
560 #ifndef QT_NO_SCROLLBAR
561 connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
562 this, SLOT(updateScrollers()));
563 connect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
564 this, SLOT(updateScrollers()));
566 connect(view, SIGNAL(destroyed()),
567 this, SLOT(viewDestroyed()));
569 #ifdef QT_SOFTKEYS_ENABLED
570 selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, itemView);
571 cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, itemView);
572 addAction(selectAction);
573 addAction(cancelAction);
578 Returns the spacing between the items in the view.
580 int QComboBoxPrivateContainer::spacing() const
582 QListView *lview = qobject_cast<QListView*>(view);
584 return lview->spacing();
585 #ifndef QT_NO_TABLEVIEW
586 QTableView *tview = qobject_cast<QTableView*>(view);
588 return tview->showGrid() ? 1 : 0;
593 void QComboBoxPrivateContainer::updateTopBottomMargin()
595 if (!layout() || layout()->count() < 1)
598 QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout());
602 const QStyleOptionComboBox opt = comboStyleOption();
603 const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
604 const int margin = usePopup ? combo->style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, combo) : 0;
606 QSpacerItem *topSpacer = boxLayout->itemAt(0)->spacerItem();
608 topSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
610 QSpacerItem *bottomSpacer = boxLayout->itemAt(boxLayout->count() - 1)->spacerItem();
611 if (bottomSpacer && bottomSpacer != topSpacer)
612 bottomSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
614 boxLayout->invalidate();
617 void QComboBoxPrivateContainer::changeEvent(QEvent *e)
619 if (e->type() == QEvent::StyleChange) {
620 QStyleOptionComboBox opt = comboStyleOption();
621 view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
622 combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo));
623 setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
624 #ifdef QT_SOFTKEYS_ENABLED
625 } else if (e->type() == QEvent::LanguageChange) {
626 selectAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::SelectSoftKey));
627 cancelAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::CancelSoftKey));
631 QWidget::changeEvent(e);
635 bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
638 case QEvent::ShortcutOverride:
639 switch (static_cast<QKeyEvent*>(e)->key()) {
642 #ifdef QT_KEYPAD_NAVIGATION
645 if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
647 emit itemSelected(view->currentIndex());
651 if (!(static_cast<QKeyEvent*>(e)->modifiers() & Qt::AltModifier))
662 case QEvent::MouseMove:
664 QMouseEvent *m = static_cast<QMouseEvent *>(e);
665 QWidget *widget = static_cast<QWidget *>(o);
666 QPoint vector = widget->mapToGlobal(m->pos()) - initialClickPosition;
667 if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive())
668 blockMouseReleaseTimer.stop();
669 QModelIndex indexUnderMouse = view->indexAt(m->pos());
670 if (indexUnderMouse.isValid()
671 && !QComboBoxDelegate::isSeparator(indexUnderMouse)) {
672 view->setCurrentIndex(indexUnderMouse);
676 case QEvent::MouseButtonRelease: {
677 QMouseEvent *m = static_cast<QMouseEvent *>(e);
678 if (isVisible() && view->rect().contains(m->pos()) && view->currentIndex().isValid()
679 && !blockMouseReleaseTimer.isActive()
680 && (view->currentIndex().flags() & Qt::ItemIsEnabled)
681 && (view->currentIndex().flags() & Qt::ItemIsSelectable)) {
683 emit itemSelected(view->currentIndex());
691 return QFrame::eventFilter(o, e);
694 void QComboBoxPrivateContainer::showEvent(QShowEvent *)
699 void QComboBoxPrivateContainer::hideEvent(QHideEvent *)
703 #ifndef QT_NO_GRAPHICSVIEW
704 // QGraphicsScenePrivate::removePopup closes the combo box popup, it hides it non-explicitly.
705 // Hiding/showing the QComboBox after this will unexpectedly show the popup as well.
706 // Re-hiding the popup container makes sure it is explicitly hidden.
707 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget())
712 void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
715 QStyleOptionComboBox opt = comboStyleOption();
716 opt.subControls = QStyle::SC_All;
717 opt.activeSubControls = QStyle::SC_ComboBoxArrow;
718 QStyle::SubControl sc = combo->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt,
719 combo->mapFromGlobal(e->globalPos()),
721 if ((combo->isEditable() && sc == QStyle::SC_ComboBoxArrow)
722 || (!combo->isEditable() && sc != QStyle::SC_None))
723 setAttribute(Qt::WA_NoMouseReplay);
727 void QComboBoxPrivateContainer::mouseReleaseEvent(QMouseEvent *e)
730 if (!blockMouseReleaseTimer.isActive()){
736 QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
738 // ### This should use QComboBox's initStyleOption(), but it's protected
739 // perhaps, we could cheat by having the QCombo private instead?
740 QStyleOptionComboBox opt;
742 opt.subControls = QStyle::SC_All;
743 opt.activeSubControls = QStyle::SC_None;
744 opt.editable = combo->isEditable();
749 \enum QComboBox::InsertPolicy
751 This enum specifies what the QComboBox should do when a new string is
754 \value NoInsert The string will not be inserted into the combobox.
755 \value InsertAtTop The string will be inserted as the first item in the combobox.
756 \value InsertAtCurrent The current item will be \e replaced by the string.
757 \value InsertAtBottom The string will be inserted after the last item in the combobox.
758 \value InsertAfterCurrent The string is inserted after the current item in the combobox.
759 \value InsertBeforeCurrent The string is inserted before the current item in the combobox.
760 \value InsertAlphabetically The string is inserted in the alphabetic order in the combobox.
761 \omitvalue NoInsertion
765 \omitvalue AfterCurrent
766 \omitvalue BeforeCurrent
770 \enum QComboBox::SizeAdjustPolicy
772 This enum specifies how the size hint of the QComboBox should
773 adjust when new content is added or content changes.
775 \value AdjustToContents The combobox will always adjust to the contents
776 \value AdjustToContentsOnFirstShow The combobox will adjust to its contents the first time it is shown.
777 \value AdjustToMinimumContentsLength Use AdjustToContents or AdjustToContentsOnFirstShow instead.
778 \value AdjustToMinimumContentsLengthWithIcon The combobox will adjust to \l minimumContentsLength plus space for an icon. For performance reasons use this policy on large models.
782 \fn void QComboBox::activated(int index)
784 This signal is sent when the user chooses an item in the combobox.
785 The item's \a index is passed. Note that this signal is sent even
786 when the choice is not changed. If you need to know when the
787 choice actually changes, use signal currentIndexChanged().
792 \fn void QComboBox::activated(const QString &text)
794 This signal is sent when the user chooses an item in the combobox.
795 The item's \a text is passed. Note that this signal is sent even
796 when the choice is not changed. If you need to know when the
797 choice actually changes, use signal currentIndexChanged().
802 \fn void QComboBox::highlighted(int index)
804 This signal is sent when an item in the combobox popup list is
805 highlighted by the user. The item's \a index is passed.
809 \fn void QComboBox::highlighted(const QString &text)
811 This signal is sent when an item in the combobox popup list is
812 highlighted by the user. The item's \a text is passed.
816 \fn void QComboBox::currentIndexChanged(int index)
819 This signal is sent whenever the currentIndex in the combobox
820 changes either through user interaction or programmatically. The
821 item's \a index is passed or -1 if the combobox becomes empty or the
822 currentIndex was reset.
826 \fn void QComboBox::currentIndexChanged(const QString &text)
829 This signal is sent whenever the currentIndex in the combobox
830 changes either through user interaction or programmatically. The
831 item's \a text is passed.
835 Constructs a combobox with the given \a parent, using the default
836 model QStandardItemModel.
838 QComboBox::QComboBox(QWidget *parent)
839 : QWidget(*new QComboBoxPrivate(), parent, 0)
848 QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent)
849 : QWidget(dd, parent, 0)
858 \brief The QComboBox widget is a combined button and popup list.
860 \ingroup basicwidgets
863 A QComboBox provides a means of presenting a list of options to the user
864 in a way that takes up the minimum amount of screen space.
866 A combobox is a selection widget that displays the current item,
867 and can pop up a list of selectable items. A combobox may be editable,
868 allowing the user to modify each item in the list.
870 Comboboxes can contain pixmaps as well as strings; the
871 insertItem() and setItemText() functions are suitably overloaded.
872 For editable comboboxes, the function clearEditText() is provided,
873 to clear the displayed string without changing the combobox's
876 There are two signals emitted if the current item of a combobox
877 changes, currentIndexChanged() and activated().
878 currentIndexChanged() is always emitted regardless if the change
879 was done programmatically or by user interaction, while
880 activated() is only emitted when the change is caused by user
881 interaction. The highlighted() signal is emitted when the user
882 highlights an item in the combobox popup list. All three signals
883 exist in two versions, one with a QString argument and one with an
884 \c int argument. If the user selects or highlights a pixmap, only
885 the \c int signals are emitted. Whenever the text of an editable
886 combobox is changed the editTextChanged() signal is emitted.
888 When the user enters a new string in an editable combobox, the
889 widget may or may not insert it, and it can insert it in several
890 locations. The default policy is is \l AtBottom but you can change
891 this using setInsertPolicy().
893 It is possible to constrain the input to an editable combobox
894 using QValidator; see setValidator(). By default, any input is
897 A combobox can be populated using the insert functions,
898 insertItem() and insertItems() for example. Items can be
899 changed with setItemText(). An item can be removed with
900 removeItem() and all items can be removed with clear(). The text
901 of the current item is returned by currentText(), and the text of
902 a numbered item is returned with text(). The current item can be
903 set with setCurrentIndex(). The number of items in the combobox is
904 returned by count(); the maximum number of items can be set with
905 setMaxCount(). You can allow editing using setEditable(). For
906 editable comboboxes you can set auto-completion using
907 setCompleter() and whether or not the user can add duplicates
908 is set with setDuplicatesEnabled().
910 QComboBox uses the \l{Model/View Programming}{model/view
911 framework} for its popup list and to store its items. By default
912 a QStandardItemModel stores the items and a QListView subclass
913 displays the popuplist. You can access the model and view directly
914 (with model() and view()), but QComboBox also provides functions
915 to set and get item data (e.g., setItemData() and itemText()). You
916 can also set a new model and view (with setModel() and setView()).
917 For the text and icon in the combobox label, the data in the model
918 that has the Qt::DisplayRole and Qt::DecorationRole is used. Note
919 that you cannot alter the \l{QAbstractItemView::}{SelectionMode}
920 of the view(), e.g., by using
921 \l{QAbstractItemView::}{setSelectionMode()}.
923 \image qstyle-comboboxes.png Comboboxes in the different built-in styles.
925 \sa QLineEdit, QSpinBox, QRadioButton, QButtonGroup,
926 {fowler}{GUI Design Handbook: Combo Box, Drop-Down List Box}
929 void QComboBoxPrivate::init()
932 q->setFocusPolicy(Qt::WheelFocus);
933 q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed,
934 QSizePolicy::ComboBox));
935 setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
936 q->setModel(new QStandardItemModel(0, 1, q));
937 if (!q->isEditable())
938 q->setAttribute(Qt::WA_InputMethodEnabled, false);
940 q->setAttribute(Qt::WA_InputMethodEnabled);
943 QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
949 container = new QComboBoxPrivateContainer(new QComboBoxListView(q), q);
950 container->itemView()->setModel(model);
951 container->itemView()->setTextElideMode(Qt::ElideMiddle);
952 updateDelegate(true);
953 updateLayoutDirection();
954 updateViewContainerPaletteAndOpacity();
955 QObject::connect(container, SIGNAL(itemSelected(QModelIndex)),
956 q, SLOT(_q_itemSelected(QModelIndex)));
957 QObject::connect(container->itemView()->selectionModel(),
958 SIGNAL(currentChanged(QModelIndex,QModelIndex)),
959 q, SLOT(_q_emitHighlighted(QModelIndex)));
960 QObject::connect(container, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
965 void QComboBoxPrivate::_q_resetButton()
967 updateArrow(QStyle::State_None);
970 void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
973 if (inserting || topLeft.parent() != root)
976 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
978 adjustComboBoxSize();
982 if (currentIndex.row() >= topLeft.row() && currentIndex.row() <= bottomRight.row()) {
984 lineEdit->setText(q->itemText(currentIndex.row()));
985 updateLineEditGeometry();
989 #ifndef QT_NO_ACCESSIBILITY
990 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, q, 0));
994 void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end)
997 if (inserting || parent != root)
1000 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
1002 adjustComboBoxSize();
1003 q->updateGeometry();
1006 // set current index if combo was previously empty
1007 if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid()) {
1008 q->setCurrentIndex(0);
1009 // need to emit changed if model updated index "silently"
1010 } else if (currentIndex.row() != indexBeforeChange) {
1012 _q_emitCurrentIndexChanged(currentIndex);
1016 void QComboBoxPrivate::_q_updateIndexBeforeChange()
1018 indexBeforeChange = currentIndex.row();
1021 void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
1027 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
1029 adjustComboBoxSize();
1030 q->updateGeometry();
1033 // model has changed the currentIndex
1034 if (currentIndex.row() != indexBeforeChange) {
1035 if (!currentIndex.isValid() && q->count()) {
1036 q->setCurrentIndex(qMin(q->count() - 1, qMax(indexBeforeChange, 0)));
1040 lineEdit->setText(q->itemText(currentIndex.row()));
1041 updateLineEditGeometry();
1044 _q_emitCurrentIndexChanged(currentIndex);
1049 void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
1054 QStyleOptionComboBox opt;
1055 q->initStyleOption(&opt);
1057 if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1059 menu.ensurePolished();
1060 container->setPalette(menu.palette());
1061 container->setWindowOpacity(menu.windowOpacity());
1065 container->setPalette(q->palette());
1066 container->setWindowOpacity(1.0);
1069 lineEdit->setPalette(q->palette());
1073 Initialize \a option with the values from this QComboBox. This method
1074 is useful for subclasses when they need a QStyleOptionComboBox, but don't want
1075 to fill in all the information themselves.
1077 \sa QStyleOption::initFrom()
1079 void QComboBox::initStyleOption(QStyleOptionComboBox *option) const
1084 Q_D(const QComboBox);
1085 option->initFrom(this);
1086 option->editable = isEditable();
1087 option->frame = d->frame;
1088 if (hasFocus() && !option->editable)
1089 option->state |= QStyle::State_Selected;
1090 option->subControls = QStyle::SC_All;
1091 if (d->arrowState == QStyle::State_Sunken) {
1092 option->activeSubControls = QStyle::SC_ComboBoxArrow;
1093 option->state |= d->arrowState;
1095 option->activeSubControls = d->hoverControl;
1097 if (d->currentIndex.isValid()) {
1098 option->currentText = currentText();
1099 option->currentIcon = d->itemIcon(d->currentIndex);
1101 option->iconSize = iconSize();
1102 if (d->container && d->container->isVisible())
1103 option->state |= QStyle::State_On;
1106 void QComboBoxPrivate::updateLineEditGeometry()
1112 QStyleOptionComboBox opt;
1113 q->initStyleOption(&opt);
1114 QRect editRect = q->style()->subControlRect(QStyle::CC_ComboBox, &opt,
1115 QStyle::SC_ComboBoxEditField, q);
1116 if (!q->itemIcon(q->currentIndex()).isNull()) {
1117 QRect comboRect(editRect);
1118 editRect.setWidth(editRect.width() - q->iconSize().width() - 4);
1119 editRect = QStyle::alignedRect(q->layoutDirection(), Qt::AlignRight,
1120 editRect.size(), comboRect);
1122 lineEdit->setGeometry(editRect);
1125 Qt::MatchFlags QComboBoxPrivate::matchFlags() const
1127 // Base how duplicates are determined on the autocompletion case sensitivity
1128 Qt::MatchFlags flags = Qt::MatchFixedString;
1129 #ifndef QT_NO_COMPLETER
1130 if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive)
1132 flags |= Qt::MatchCaseSensitive;
1137 void QComboBoxPrivate::_q_editingFinished()
1140 if (lineEdit && !lineEdit->text().isEmpty()) {
1141 //here we just check if the current item was entered
1142 const int index = q_func()->findText(lineEdit->text(), matchFlags());
1143 if (index != -1 && itemText(currentIndex) != lineEdit->text()) {
1144 q->setCurrentIndex(index);
1145 emitActivated(currentIndex);
1151 void QComboBoxPrivate::_q_returnPressed()
1154 if (lineEdit && !lineEdit->text().isEmpty()) {
1155 if (q->count() >= maxCount && !(this->insertPolicy == QComboBox::InsertAtCurrent))
1157 lineEdit->deselect();
1158 lineEdit->end(false);
1159 QString text = lineEdit->text();
1160 // check for duplicates (if not enabled) and quit
1162 if (!duplicatesEnabled) {
1163 index = q->findText(text, matchFlags());
1165 q->setCurrentIndex(index);
1166 emitActivated(currentIndex);
1170 switch (insertPolicy) {
1171 case QComboBox::InsertAtTop:
1174 case QComboBox::InsertAtBottom:
1177 case QComboBox::InsertAtCurrent:
1178 case QComboBox::InsertAfterCurrent:
1179 case QComboBox::InsertBeforeCurrent:
1180 if (!q->count() || !currentIndex.isValid())
1182 else if (insertPolicy == QComboBox::InsertAtCurrent)
1183 q->setItemText(q->currentIndex(), text);
1184 else if (insertPolicy == QComboBox::InsertAfterCurrent)
1185 index = q->currentIndex() + 1;
1186 else if (insertPolicy == QComboBox::InsertBeforeCurrent)
1187 index = q->currentIndex();
1189 case QComboBox::InsertAlphabetically:
1191 for (int i=0; i< q->count(); i++, index++ ) {
1192 if (text.toLower() < q->itemText(i).toLower())
1196 case QComboBox::NoInsert:
1201 q->insertItem(index, text);
1202 q->setCurrentIndex(index);
1203 emitActivated(currentIndex);
1208 void QComboBoxPrivate::_q_itemSelected(const QModelIndex &item)
1211 if (item != currentIndex) {
1212 setCurrentIndex(item);
1213 } else if (lineEdit) {
1214 lineEdit->selectAll();
1215 lineEdit->setText(q->itemText(currentIndex.row()));
1217 emitActivated(currentIndex);
1220 void QComboBoxPrivate::emitActivated(const QModelIndex &index)
1223 if (!index.isValid())
1225 QString text(itemText(index));
1226 emit q->activated(index.row());
1227 emit q->activated(text);
1230 void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
1233 if (!index.isValid())
1235 QString text(itemText(index));
1236 emit q->highlighted(index.row());
1237 emit q->highlighted(text);
1240 void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
1243 emit q->currentIndexChanged(index.row());
1244 emit q->currentIndexChanged(itemText(index));
1245 #ifndef QT_NO_ACCESSIBILITY
1246 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, q, 0));
1250 QString QComboBoxPrivate::itemText(const QModelIndex &index) const
1252 return index.isValid() ? model->data(index, itemRole()).toString() : QString();
1255 int QComboBoxPrivate::itemRole() const
1257 return q_func()->isEditable() ? Qt::EditRole : Qt::DisplayRole;
1261 Destroys the combobox.
1263 QComboBox::~QComboBox()
1265 // ### check delegateparent and delete delegate if us?
1269 disconnect(d->model, SIGNAL(destroyed()),
1270 this, SLOT(_q_modelDestroyed()));
1272 ; // objects can't throw in destructor
1277 \property QComboBox::maxVisibleItems
1278 \brief the maximum allowed size on screen of the combo box, measured in items
1280 By default, this property has a value of 10.
1282 \note This property is ignored for non-editable comboboxes in styles that returns
1283 true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
1285 int QComboBox::maxVisibleItems() const
1287 Q_D(const QComboBox);
1288 return d->maxVisibleItems;
1291 void QComboBox::setMaxVisibleItems(int maxItems)
1295 qWarning("QComboBox::setMaxVisibleItems: "
1296 "Invalid max visible items (%d) must be >= 0", maxItems);
1299 d->maxVisibleItems = maxItems;
1303 \property QComboBox::count
1304 \brief the number of items in the combobox
1306 By default, for an empty combo box, this property has a value of 0.
1308 int QComboBox::count() const
1310 Q_D(const QComboBox);
1311 return d->model->rowCount(d->root);
1315 \property QComboBox::maxCount
1316 \brief the maximum number of items allowed in the combobox
1318 \note If you set the maximum number to be less then the current
1319 amount of items in the combobox, the extra items will be
1320 truncated. This also applies if you have set an external model on
1323 By default, this property's value is derived from the highest
1324 signed integer available (typically 2147483647).
1326 void QComboBox::setMaxCount(int max)
1330 qWarning("QComboBox::setMaxCount: Invalid count (%d) must be >= 0", max);
1335 d->model->removeRows(max, count() - max, d->root);
1340 int QComboBox::maxCount() const
1342 Q_D(const QComboBox);
1346 #ifndef QT_NO_COMPLETER
1349 \property QComboBox::autoCompletion
1350 \brief whether the combobox provides auto-completion for editable items
1354 Use setCompleter() instead.
1356 By default, this property is true.
1364 Use setCompleter() instead.
1366 bool QComboBox::autoCompletion() const
1368 Q_D(const QComboBox);
1369 return d->autoCompletion;
1375 Use setCompleter() instead.
1377 void QComboBox::setAutoCompletion(bool enable)
1381 #ifdef QT_KEYPAD_NAVIGATION
1382 if (QApplication::keypadNavigationEnabled() && !enable && isEditable())
1383 qWarning("QComboBox::setAutoCompletion: auto completion is mandatory when combo box editable");
1386 d->autoCompletion = enable;
1390 if (d->lineEdit->completer())
1392 d->completer = new QCompleter(d->model, d->lineEdit);
1393 d->completer->setCaseSensitivity(d->autoCompletionCaseSensitivity);
1394 d->completer->setCompletionMode(QCompleter::InlineCompletion);
1395 d->completer->setCompletionColumn(d->modelColumn);
1396 d->lineEdit->setCompleter(d->completer);
1397 d->completer->setWidget(this);
1399 d->lineEdit->setCompleter(0);
1404 \property QComboBox::autoCompletionCaseSensitivity
1405 \brief whether string comparisons are case-sensitive or case-insensitive for auto-completion
1408 By default, this property is Qt::CaseInsensitive.
1410 Use setCompleter() instead. Case sensitivity of the auto completion can be
1411 changed using QCompleter::setCaseSensitivity().
1419 Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1421 Qt::CaseSensitivity QComboBox::autoCompletionCaseSensitivity() const
1423 Q_D(const QComboBox);
1424 return d->autoCompletionCaseSensitivity;
1430 Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1432 void QComboBox::setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity)
1435 d->autoCompletionCaseSensitivity = sensitivity;
1436 if (d->lineEdit && d->lineEdit->completer())
1437 d->lineEdit->completer()->setCaseSensitivity(sensitivity);
1440 #endif // QT_NO_COMPLETER
1443 \property QComboBox::duplicatesEnabled
1444 \brief whether the user can enter duplicate items into the combobox
1446 Note that it is always possible to programmatically insert duplicate items into the
1449 By default, this property is false (duplicates are not allowed).
1451 bool QComboBox::duplicatesEnabled() const
1453 Q_D(const QComboBox);
1454 return d->duplicatesEnabled;
1457 void QComboBox::setDuplicatesEnabled(bool enable)
1460 d->duplicatesEnabled = enable;
1463 /*! \fn int QComboBox::findText(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const
1465 Returns the index of the item containing the given \a text; otherwise
1468 The \a flags specify how the items in the combobox are searched.
1472 Returns the index of the item containing the given \a data for the
1473 given \a role; otherwise returns -1.
1475 The \a flags specify how the items in the combobox are searched.
1477 int QComboBox::findData(const QVariant &data, int role, Qt::MatchFlags flags) const
1479 Q_D(const QComboBox);
1480 QModelIndexList result;
1481 QModelIndex start = d->model->index(0, d->modelColumn, d->root);
1482 result = d->model->match(start, role, data, 1, flags);
1483 if (result.isEmpty())
1485 return result.first().row();
1489 \property QComboBox::insertPolicy
1490 \brief the policy used to determine where user-inserted items should
1491 appear in the combobox
1493 The default value is \l AtBottom, indicating that new items will appear
1494 at the bottom of the list of items.
1499 QComboBox::InsertPolicy QComboBox::insertPolicy() const
1501 Q_D(const QComboBox);
1502 return d->insertPolicy;
1505 void QComboBox::setInsertPolicy(InsertPolicy policy)
1508 d->insertPolicy = policy;
1512 \property QComboBox::sizeAdjustPolicy
1513 \brief the policy describing how the size of the combobox changes
1514 when the content changes
1516 The default value is \l AdjustToContentsOnFirstShow.
1518 \sa SizeAdjustPolicy
1521 QComboBox::SizeAdjustPolicy QComboBox::sizeAdjustPolicy() const
1523 Q_D(const QComboBox);
1524 return d->sizeAdjustPolicy;
1527 void QComboBox::setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy policy)
1530 if (policy == d->sizeAdjustPolicy)
1533 d->sizeAdjustPolicy = policy;
1534 d->sizeHint = QSize();
1535 d->adjustComboBoxSize();
1540 \property QComboBox::minimumContentsLength
1541 \brief the minimum number of characters that should fit into the combobox.
1543 The default value is 0.
1545 If this property is set to a positive value, the
1546 minimumSizeHint() and sizeHint() take it into account.
1548 \sa sizeAdjustPolicy
1550 int QComboBox::minimumContentsLength() const
1552 Q_D(const QComboBox);
1553 return d->minimumContentsLength;
1556 void QComboBox::setMinimumContentsLength(int characters)
1559 if (characters == d->minimumContentsLength || characters < 0)
1562 d->minimumContentsLength = characters;
1564 if (d->sizeAdjustPolicy == AdjustToContents
1565 || d->sizeAdjustPolicy == AdjustToMinimumContentsLength
1566 || d->sizeAdjustPolicy == AdjustToMinimumContentsLengthWithIcon) {
1567 d->sizeHint = QSize();
1568 d->adjustComboBoxSize();
1574 \property QComboBox::iconSize
1575 \brief the size of the icons shown in the combobox.
1577 Unless explicitly set this returns the default value of the
1578 current style. This size is the maximum size that icons can have;
1579 icons of smaller size are not scaled up.
1582 QSize QComboBox::iconSize() const
1584 Q_D(const QComboBox);
1585 if (d->iconSize.isValid())
1588 int iconWidth = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
1589 return QSize(iconWidth, iconWidth);
1592 void QComboBox::setIconSize(const QSize &size)
1595 if (size == d->iconSize)
1598 view()->setIconSize(size);
1600 d->sizeHint = QSize();
1605 \property QComboBox::editable
1606 \brief whether the combo box can be edited by the user
1608 By default, this property is false.
1610 bool QComboBox::isEditable() const
1612 Q_D(const QComboBox);
1613 return d->lineEdit != 0;
1617 update the default delegate
1618 depending on the style's SH_ComboBox_Popup hint, we use a different default delegate.
1620 but we do not change the delegate is the combobox use a custom delegate,
1621 unless \a force is set to true.
1623 void QComboBoxPrivate::updateDelegate(bool force)
1626 QStyleOptionComboBox opt;
1627 q->initStyleOption(&opt);
1628 if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1629 if (force || qobject_cast<QComboBoxDelegate *>(q->itemDelegate()))
1630 q->setItemDelegate(new QComboMenuDelegate(q->view(), q));
1632 if (force || qobject_cast<QComboMenuDelegate *>(q->itemDelegate()))
1633 q->setItemDelegate(new QComboBoxDelegate(q->view(), q));
1637 QIcon QComboBoxPrivate::itemIcon(const QModelIndex &index) const
1639 QVariant decoration = model->data(index, Qt::DecorationRole);
1640 if (decoration.type() == QVariant::Pixmap)
1641 return QIcon(qvariant_cast<QPixmap>(decoration));
1643 return qvariant_cast<QIcon>(decoration);
1646 void QComboBox::setEditable(bool editable)
1649 if (isEditable() == editable)
1652 d->updateDelegate();
1654 QStyleOptionComboBox opt;
1655 initStyleOption(&opt);
1657 if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1658 d->viewContainer()->updateScrollers();
1659 view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
1661 QLineEdit *le = new QLineEdit(this);
1664 if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1665 d->viewContainer()->updateScrollers();
1666 view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1668 setAttribute(Qt::WA_InputMethodEnabled, false);
1669 d->lineEdit->hide();
1670 d->lineEdit->deleteLater();
1674 d->viewContainer()->updateTopBottomMargin();
1675 if (!testAttribute(Qt::WA_Resized))
1680 Sets the line \a edit to use instead of the current line edit widget.
1682 The combo box takes ownership of the line edit.
1684 void QComboBox::setLineEdit(QLineEdit *edit)
1688 qWarning("QComboBox::setLineEdit: cannot set a 0 line edit");
1692 if (edit == d->lineEdit)
1695 edit->setText(currentText());
1699 if (d->lineEdit->parent() != this)
1700 d->lineEdit->setParent(this);
1701 connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed()));
1702 connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished()));
1703 connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString)));
1704 d->lineEdit->setFrame(false);
1705 d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
1706 d->lineEdit->setFocusProxy(this);
1707 d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
1708 #ifndef QT_NO_COMPLETER
1709 setAutoCompletion(d->autoCompletion);
1712 #ifdef QT_KEYPAD_NAVIGATION
1713 #ifndef QT_NO_COMPLETER
1714 if (QApplication::keypadNavigationEnabled()) {
1715 // Editable combo boxes will have a completer that is set to UnfilteredPopupCompletion.
1716 // This means that when the user enters edit mode they are immediately presented with a
1717 // list of possible completions.
1718 setAutoCompletion(true);
1720 d->completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
1721 connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated()));
1727 setAttribute(Qt::WA_InputMethodEnabled);
1728 d->updateLayoutDirection();
1729 d->updateLineEditGeometry();
1731 d->lineEdit->show();
1737 Returns the line edit used to edit items in the combobox, or 0 if there
1740 Only editable combo boxes have a line edit.
1742 QLineEdit *QComboBox::lineEdit() const
1744 Q_D(const QComboBox);
1748 #ifndef QT_NO_VALIDATOR
1750 \fn void QComboBox::setValidator(const QValidator *validator)
1752 Sets the \a validator to use instead of the current validator.
1755 void QComboBox::setValidator(const QValidator *v)
1759 d->lineEdit->setValidator(v);
1763 Returns the validator that is used to constrain text input for the
1768 const QValidator *QComboBox::validator() const
1770 Q_D(const QComboBox);
1771 return d->lineEdit ? d->lineEdit->validator() : 0;
1773 #endif // QT_NO_VALIDATOR
1775 #ifndef QT_NO_COMPLETER
1778 \fn void QComboBox::setCompleter(QCompleter *completer)
1781 Sets the \a completer to use instead of the current completer.
1782 If \a completer is 0, auto completion is disabled.
1784 By default, for an editable combo box, a QCompleter that
1785 performs case insensitive inline completion is automatically created.
1787 void QComboBox::setCompleter(QCompleter *c)
1792 d->lineEdit->setCompleter(c);
1800 Returns the completer that is used to auto complete text input for the
1805 QCompleter *QComboBox::completer() const
1807 Q_D(const QComboBox);
1808 return d->lineEdit ? d->lineEdit->completer() : 0;
1811 #endif // QT_NO_COMPLETER
1814 Returns the item delegate used by the popup list view.
1816 \sa setItemDelegate()
1818 QAbstractItemDelegate *QComboBox::itemDelegate() const
1820 return view()->itemDelegate();
1824 Sets the item \a delegate for the popup list view.
1825 The combobox takes ownership of the delegate.
1827 \warning You should not share the same instance of a delegate between comboboxes,
1828 widget mappers or views. Doing so can cause incorrect or unintuitive editing behavior
1829 since each view connected to a given delegate may receive the
1830 \l{QAbstractItemDelegate::}{closeEditor()} signal, and attempt to access, modify or
1831 close an editor that has already been closed.
1835 void QComboBox::setItemDelegate(QAbstractItemDelegate *delegate)
1838 qWarning("QComboBox::setItemDelegate: cannot set a 0 delegate");
1841 delete view()->itemDelegate();
1842 view()->setItemDelegate(delegate);
1846 Returns the model used by the combobox.
1849 QAbstractItemModel *QComboBox::model() const
1851 Q_D(const QComboBox);
1852 if (d->model == QAbstractItemModelPrivate::staticEmptyModel()) {
1853 QComboBox *that = const_cast<QComboBox*>(this);
1854 that->setModel(new QStandardItemModel(0, 1, that));
1860 Sets the model to be \a model. \a model must not be 0.
1861 If you want to clear the contents of a model, call clear().
1865 void QComboBox::setModel(QAbstractItemModel *model)
1870 qWarning("QComboBox::setModel: cannot set a 0 model");
1874 #ifndef QT_NO_COMPLETER
1875 if (d->lineEdit && d->lineEdit->completer()
1876 && d->lineEdit->completer() == d->completer)
1877 d->lineEdit->completer()->setModel(model);
1880 disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1881 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1882 disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
1883 this, SLOT(_q_updateIndexBeforeChange()));
1884 disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
1885 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
1886 disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
1887 this, SLOT(_q_updateIndexBeforeChange()));
1888 disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
1889 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
1890 disconnect(d->model, SIGNAL(destroyed()),
1891 this, SLOT(_q_modelDestroyed()));
1892 disconnect(d->model, SIGNAL(modelAboutToBeReset()),
1893 this, SLOT(_q_updateIndexBeforeChange()));
1894 disconnect(d->model, SIGNAL(modelReset()),
1895 this, SLOT(_q_modelReset()));
1896 if (d->model->QObject::parent() == this)
1902 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1903 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1904 connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
1905 this, SLOT(_q_updateIndexBeforeChange()));
1906 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
1907 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
1908 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
1909 this, SLOT(_q_updateIndexBeforeChange()));
1910 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
1911 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
1912 connect(model, SIGNAL(destroyed()),
1913 this, SLOT(_q_modelDestroyed()));
1914 connect(model, SIGNAL(modelAboutToBeReset()),
1915 this, SLOT(_q_updateIndexBeforeChange()));
1916 connect(model, SIGNAL(modelReset()),
1917 this, SLOT(_q_modelReset()));
1920 d->container->itemView()->setModel(model);
1922 bool currentReset = false;
1925 for (int pos=0; pos < count(); pos++) {
1926 if (d->model->index(pos, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled) {
1927 setCurrentIndex(pos);
1928 currentReset = true;
1935 setCurrentIndex(-1);
1941 Returns the root model item index for the items in the combobox.
1943 \sa setRootModelIndex()
1946 QModelIndex QComboBox::rootModelIndex() const
1948 Q_D(const QComboBox);
1949 return QModelIndex(d->root);
1953 Sets the root model item \a index for the items in the combobox.
1955 \sa rootModelIndex()
1957 void QComboBox::setRootModelIndex(const QModelIndex &index)
1960 d->root = QPersistentModelIndex(index);
1961 view()->setRootIndex(index);
1966 \property QComboBox::currentIndex
1967 \brief the index of the current item in the combobox.
1969 The current index can change when inserting or removing items.
1971 By default, for an empty combo box or a combo box in which no current
1972 item is set, this property has a value of -1.
1974 int QComboBox::currentIndex() const
1976 Q_D(const QComboBox);
1977 return d->currentIndex.row();
1980 void QComboBox::setCurrentIndex(int index)
1983 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
1984 d->setCurrentIndex(mi);
1987 void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
1991 QModelIndex normalized;
1992 if (mi.column() != modelColumn)
1993 normalized = model->index(mi.row(), modelColumn, mi.parent());
1994 if (!normalized.isValid())
1995 normalized = mi; // Fallback to passed index.
1997 bool indexChanged = (normalized != currentIndex);
1999 currentIndex = QPersistentModelIndex(normalized);
2001 QString newText = q->itemText(normalized.row());
2002 if (lineEdit->text() != newText)
2003 lineEdit->setText(newText);
2004 updateLineEditGeometry();
2008 _q_emitCurrentIndexChanged(currentIndex);
2013 \property QComboBox::currentText
2014 \brief the text of the current item
2016 By default, for an empty combo box or a combo box in which no current
2017 item is set, this property contains an empty string.
2019 QString QComboBox::currentText() const
2021 Q_D(const QComboBox);
2023 return d->lineEdit->text();
2024 else if (d->currentIndex.isValid())
2025 return d->itemText(d->currentIndex);
2031 Returns the text for the given \a index in the combobox.
2033 QString QComboBox::itemText(int index) const
2035 Q_D(const QComboBox);
2036 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2037 return d->itemText(mi);
2041 Returns the icon for the given \a index in the combobox.
2043 QIcon QComboBox::itemIcon(int index) const
2045 Q_D(const QComboBox);
2046 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2047 return d->itemIcon(mi);
2051 Returns the data for the given \a role in the given \a index in the
2052 combobox, or QVariant::Invalid if there is no data for this role.
2054 QVariant QComboBox::itemData(int index, int role) const
2056 Q_D(const QComboBox);
2057 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2058 return d->model->data(mi, role);
2062 \fn void QComboBox::insertItem(int index, const QString &text, const QVariant &userData)
2064 Inserts the \a text and \a userData (stored in the Qt::UserRole)
2065 into the combobox at the given \a index.
2067 If the index is equal to or higher than the total number of items,
2068 the new item is appended to the list of existing items. If the
2069 index is zero or negative, the new item is prepended to the list
2077 Inserts the \a icon, \a text and \a userData (stored in the
2078 Qt::UserRole) into the combobox at the given \a index.
2080 If the index is equal to or higher than the total number of items,
2081 the new item is appended to the list of existing items. If the
2082 index is zero or negative, the new item is prepended to the list
2087 void QComboBox::insertItem(int index, const QIcon &icon, const QString &text, const QVariant &userData)
2090 int itemCount = count();
2091 index = qBound(0, index, itemCount);
2092 if (index >= d->maxCount)
2095 // For the common case where we are using the built in QStandardItemModel
2096 // construct a QStandardItem, reducing the number of expensive signals from the model
2097 if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(d->model)) {
2098 QStandardItem *item = new QStandardItem(text);
2099 if (!icon.isNull()) item->setData(icon, Qt::DecorationRole);
2100 if (userData.isValid()) item->setData(userData, Qt::UserRole);
2101 m->insertRow(index, item);
2104 d->inserting = true;
2105 if (d->model->insertRows(index, 1, d->root)) {
2106 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2107 if (icon.isNull() && !userData.isValid()) {
2108 d->model->setData(item, text, Qt::EditRole);
2110 QMap<int, QVariant> values;
2111 if (!text.isNull()) values.insert(Qt::EditRole, text);
2112 if (!icon.isNull()) values.insert(Qt::DecorationRole, icon);
2113 if (userData.isValid()) values.insert(Qt::UserRole, userData);
2114 if (!values.isEmpty()) d->model->setItemData(item, values);
2116 d->inserting = false;
2117 d->_q_rowsInserted(d->root, index, index);
2120 d->inserting = false;
2124 if (itemCount > d->maxCount)
2125 d->model->removeRows(itemCount - 1, itemCount - d->maxCount, d->root);
2129 Inserts the strings from the \a list into the combobox as separate items,
2130 starting at the \a index specified.
2132 If the index is equal to or higher than the total number of items, the new items
2133 are appended to the list of existing items. If the index is zero or negative, the
2134 new items are prepended to the list of existing items.
2138 void QComboBox::insertItems(int index, const QStringList &list)
2143 index = qBound(0, index, count());
2144 int insertCount = qMin(d->maxCount - index, list.count());
2145 if (insertCount <= 0)
2147 // For the common case where we are using the built in QStandardItemModel
2148 // construct a QStandardItem, reducing the number of expensive signals from the model
2149 if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(d->model)) {
2150 QList<QStandardItem *> items;
2151 QStandardItem *hiddenRoot = m->invisibleRootItem();
2152 for (int i = 0; i < insertCount; ++i)
2153 items.append(new QStandardItem(list.at(i)));
2154 hiddenRoot->insertRows(index, items);
2156 d->inserting = true;
2157 if (d->model->insertRows(index, insertCount, d->root)) {
2159 for (int i = 0; i < insertCount; ++i) {
2160 item = d->model->index(i+index, d->modelColumn, d->root);
2161 d->model->setData(item, list.at(i), Qt::EditRole);
2163 d->inserting = false;
2164 d->_q_rowsInserted(d->root, index, index + insertCount - 1);
2166 d->inserting = false;
2171 if (mc > d->maxCount)
2172 d->model->removeRows(d->maxCount, mc - d->maxCount, d->root);
2178 Inserts a separator item into the combobox at the given \a index.
2180 If the index is equal to or higher than the total number of items, the new item
2181 is appended to the list of existing items. If the index is zero or negative, the
2182 new item is prepended to the list of existing items.
2186 void QComboBox::insertSeparator(int index)
2189 int itemCount = count();
2190 index = qBound(0, index, itemCount);
2191 if (index >= d->maxCount)
2193 insertItem(index, QIcon(), QString());
2194 QComboBoxDelegate::setSeparator(d->model, d->model->index(index, 0, d->root));
2198 Removes the item at the given \a index from the combobox.
2199 This will update the current index if the index is removed.
2201 This function does nothing if \a index is out of range.
2203 void QComboBox::removeItem(int index)
2206 if (index < 0 || index >= count())
2208 d->model->removeRows(index, 1, d->root);
2212 Sets the \a text for the item on the given \a index in the combobox.
2214 void QComboBox::setItemText(int index, const QString &text)
2216 Q_D(const QComboBox);
2217 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2218 if (item.isValid()) {
2219 d->model->setData(item, text, Qt::EditRole);
2224 Sets the \a icon for the item on the given \a index in the combobox.
2226 void QComboBox::setItemIcon(int index, const QIcon &icon)
2228 Q_D(const QComboBox);
2229 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2230 if (item.isValid()) {
2231 d->model->setData(item, icon, Qt::DecorationRole);
2236 Sets the data \a role for the item on the given \a index in the combobox
2237 to the specified \a value.
2239 void QComboBox::setItemData(int index, const QVariant &value, int role)
2241 Q_D(const QComboBox);
2242 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2243 if (item.isValid()) {
2244 d->model->setData(item, value, role);
2249 Returns the list view used for the combobox popup.
2251 QAbstractItemView *QComboBox::view() const
2253 Q_D(const QComboBox);
2254 return const_cast<QComboBoxPrivate*>(d)->viewContainer()->itemView();
2258 Sets the view to be used in the combobox popup to the given \a
2259 itemView. The combobox takes ownership of the view.
2261 Note: If you want to use the convenience views (like QListWidget,
2262 QTableWidget or QTreeWidget), make sure to call setModel() on the
2263 combobox with the convenience widgets model before calling this
2266 void QComboBox::setView(QAbstractItemView *itemView)
2270 qWarning("QComboBox::setView: cannot set a 0 view");
2274 if (itemView->model() != d->model)
2275 itemView->setModel(d->model);
2276 d->viewContainer()->setItemView(itemView);
2282 QSize QComboBox::minimumSizeHint() const
2284 Q_D(const QComboBox);
2285 return d->recomputeSizeHint(d->minimumSizeHint);
2291 This implementation caches the size hint to avoid resizing when
2292 the contents change dynamically. To invalidate the cached value
2293 change the \l sizeAdjustPolicy.
2295 QSize QComboBox::sizeHint() const
2297 Q_D(const QComboBox);
2298 return d->recomputeSizeHint(d->sizeHint);
2302 Displays the list of items in the combobox. If the list is empty
2303 then the no items will be shown.
2305 If you reimplement this function to show a custom pop-up, make
2306 sure you call hidePopup() to reset the internal state.
2310 void QComboBox::showPopup()
2316 #ifdef QT_KEYPAD_NAVIGATION
2317 #ifndef QT_NO_COMPLETER
2318 if (QApplication::keypadNavigationEnabled() && d->completer) {
2319 // editable combo box is line edit plus completer
2321 d->completer->complete(); // show popup
2327 QStyle * const style = this->style();
2329 // set current item and select it
2330 view()->selectionModel()->setCurrentIndex(d->currentIndex,
2331 QItemSelectionModel::ClearAndSelect);
2332 QComboBoxPrivateContainer* container = d->viewContainer();
2333 QStyleOptionComboBox opt;
2334 initStyleOption(&opt);
2335 QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt,
2336 QStyle::SC_ComboBoxListBoxPopup, this));
2337 QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this));
2339 QPoint below = mapToGlobal(listRect.bottomLeft());
2340 int belowHeight = screen.bottom() - below.y();
2341 QPoint above = mapToGlobal(listRect.topLeft());
2342 int aboveHeight = above.y() - screen.y();
2343 bool boundToScreen = !window()->testAttribute(Qt::WA_DontShowOnScreen);
2345 const bool usePopup = style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this);
2349 QStack<QModelIndex> toCheck;
2350 toCheck.push(view()->rootIndex());
2351 #ifndef QT_NO_TREEVIEW
2352 QTreeView *treeView = qobject_cast<QTreeView*>(view());
2353 if (treeView && treeView->header() && !treeView->header()->isHidden())
2354 listHeight += treeView->header()->height();
2356 while (!toCheck.isEmpty()) {
2357 QModelIndex parent = toCheck.pop();
2358 for (int i = 0; i < d->model->rowCount(parent); ++i) {
2359 QModelIndex idx = d->model->index(i, d->modelColumn, parent);
2362 listHeight += view()->visualRect(idx).height() + container->spacing();
2363 #ifndef QT_NO_TREEVIEW
2364 if (d->model->hasChildren(idx) && treeView && treeView->isExpanded(idx))
2368 if (!usePopup && count >= d->maxVisibleItems) {
2374 listRect.setHeight(listHeight);
2378 // add the spacing for the grid on the top and the bottom;
2379 int heightMargin = 2*container->spacing();
2381 // add the frame of the container
2382 int marginTop, marginBottom;
2383 container->getContentsMargins(0, &marginTop, 0, &marginBottom);
2384 heightMargin += marginTop + marginBottom;
2386 //add the frame of the view
2387 view()->getContentsMargins(0, &marginTop, 0, &marginBottom);
2388 marginTop += static_cast<QAbstractScrollAreaPrivate *>(QObjectPrivate::get(view()))->top;
2389 marginBottom += static_cast<QAbstractScrollAreaPrivate *>(QObjectPrivate::get(view()))->bottom;
2390 heightMargin += marginTop + marginBottom;
2392 listRect.setHeight(listRect.height() + heightMargin);
2395 // Add space for margin at top and bottom if the style wants it.
2397 listRect.setHeight(listRect.height() + style->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) * 2);
2399 // Make sure the popup is wide enough to display its contents.
2401 const int diff = d->computeWidthHint() - width();
2403 listRect.setWidth(listRect.width() + diff);
2406 //we need to activate the layout to make sure the min/maximum size are set when the widget was not yet show
2407 container->layout()->activate();
2408 //takes account of the minimum/maximum size of the container
2409 listRect.setSize( listRect.size().expandedTo(container->minimumSize())
2410 .boundedTo(container->maximumSize()));
2412 // make sure the widget fits on screen
2413 if (boundToScreen) {
2414 if (listRect.width() > screen.width() )
2415 listRect.setWidth(screen.width());
2416 if (mapToGlobal(listRect.bottomRight()).x() > screen.right()) {
2417 below.setX(screen.x() + screen.width() - listRect.width());
2418 above.setX(screen.x() + screen.width() - listRect.width());
2420 if (mapToGlobal(listRect.topLeft()).x() < screen.x() ) {
2421 below.setX(screen.x());
2422 above.setX(screen.x());
2427 // Position horizontally.
2428 listRect.moveLeft(above.x());
2430 // Position vertically so the curently selected item lines up
2431 // with the combo box.
2432 const QRect currentItemRect = view()->visualRect(view()->currentIndex());
2433 const int offset = listRect.top() - currentItemRect.top();
2434 listRect.moveTop(above.y() + offset - listRect.top());
2436 // Clamp the listRect height and vertical position so we don't expand outside the
2437 // available screen geometry.This may override the vertical position, but it is more
2438 // important to show as much as possible of the popup.
2439 const int height = !boundToScreen ? listRect.height() : qMin(listRect.height(), screen.height());
2440 listRect.setHeight(height);
2442 if (boundToScreen) {
2443 if (listRect.top() < screen.top())
2444 listRect.moveTop(screen.top());
2445 if (listRect.bottom() > screen.bottom())
2446 listRect.moveBottom(screen.bottom());
2448 } else if (!boundToScreen || listRect.height() <= belowHeight) {
2449 listRect.moveTopLeft(below);
2450 } else if (listRect.height() <= aboveHeight) {
2451 listRect.moveBottomLeft(above);
2452 } else if (belowHeight >= aboveHeight) {
2453 listRect.setHeight(belowHeight);
2454 listRect.moveTopLeft(below);
2456 listRect.setHeight(aboveHeight);
2457 listRect.moveBottomLeft(above);
2461 qApp->inputMethod()->reset();
2464 QScrollBar *sb = view()->horizontalScrollBar();
2465 Qt::ScrollBarPolicy policy = view()->horizontalScrollBarPolicy();
2466 bool needHorizontalScrollBar = (policy == Qt::ScrollBarAsNeeded || policy == Qt::ScrollBarAlwaysOn)
2467 && sb->minimum() < sb->maximum();
2468 if (needHorizontalScrollBar) {
2469 listRect.adjust(0, 0, 0, sb->height());
2471 container->setGeometry(listRect);
2474 const bool updatesEnabled = container->updatesEnabled();
2477 #if defined(Q_WS_WIN) && !defined(QT_NO_EFFECTS)
2478 bool scrollDown = (listRect.topLeft() == below);
2479 if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo)
2480 && !style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && !window()->testAttribute(Qt::WA_DontShowOnScreen))
2481 qScrollEffect(container, scrollDown ? QEffects::DownScroll : QEffects::UpScroll, 150);
2484 // Don't disable updates on Mac OS X. Windows are displayed immediately on this platform,
2485 // which means that the window will be visible before the call to container->show() returns.
2486 // If updates are disabled at this point we'll miss our chance at painting the popup
2487 // menu before it's shown, causing flicker since the window then displays the standard gray
2490 container->setUpdatesEnabled(false);
2495 container->updateScrollers();
2498 view()->scrollTo(view()->currentIndex(),
2499 style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)
2500 ? QAbstractItemView::PositionAtCenter
2501 : QAbstractItemView::EnsureVisible);
2504 container->setUpdatesEnabled(updatesEnabled);
2507 container->update();
2508 #ifdef QT_KEYPAD_NAVIGATION
2509 if (QApplication::keypadNavigationEnabled())
2510 view()->setEditFocus(true);
2515 Hides the list of items in the combobox if it is currently visible
2516 and resets the internal state, so that if the custom pop-up was
2517 shown inside the reimplemented showPopup(), then you also need to
2518 reimplement the hidePopup() function to hide your custom pop-up
2519 and call the base class implementation to reset the internal state
2520 whenever your custom pop-up widget is hidden.
2524 void QComboBox::hidePopup()
2527 if (d->container && d->container->isVisible()) {
2528 #if !defined(QT_NO_EFFECTS)
2529 d->model->blockSignals(true);
2530 d->container->itemView()->blockSignals(true);
2531 d->container->blockSignals(true);
2532 // Flash selected/triggered item (if any).
2533 if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) {
2534 QItemSelectionModel *selectionModel = view() ? view()->selectionModel() : 0;
2535 if (selectionModel && selectionModel->hasSelection()) {
2536 QEventLoop eventLoop;
2537 const QItemSelection selection = selectionModel->selection();
2539 // Deselect item and wait 60 ms.
2540 selectionModel->select(selection, QItemSelectionModel::Toggle);
2541 QTimer::singleShot(60, &eventLoop, SLOT(quit()));
2544 // Select item and wait 20 ms.
2545 selectionModel->select(selection, QItemSelectionModel::Toggle);
2546 QTimer::singleShot(20, &eventLoop, SLOT(quit()));
2552 bool needFade = style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
2554 #if defined(Q_WS_MAC)
2555 macWindowFade(qt_mac_window_for(d->container));
2557 // Other platform implementations welcome :-)
2559 d->model->blockSignals(false);
2560 d->container->itemView()->blockSignals(false);
2561 d->container->blockSignals(false);
2564 #endif // QT_NO_EFFECTS
2565 // Fade should implicitly hide as well ;-)
2566 d->container->hide();
2568 #ifdef QT_KEYPAD_NAVIGATION
2569 if (QApplication::keypadNavigationEnabled() && isEditable() && hasFocus())
2572 d->_q_resetButton();
2576 Clears the combobox, removing all items.
2578 Note: If you have set an external model on the combobox this model
2579 will still be cleared when calling this function.
2581 void QComboBox::clear()
2584 d->model->removeRows(0, d->model->rowCount(d->root), d->root);
2585 #ifndef QT_NO_ACCESSIBILITY
2586 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
2591 \fn void QComboBox::clearValidator()
2593 Use setValidator(0) instead.
2597 Clears the contents of the line edit used for editing in the combobox.
2599 void QComboBox::clearEditText()
2603 d->lineEdit->clear();
2604 #ifndef QT_NO_ACCESSIBILITY
2605 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
2610 Sets the \a text in the combobox's text edit.
2612 void QComboBox::setEditText(const QString &text)
2616 d->lineEdit->setText(text);
2617 #ifndef QT_NO_ACCESSIBILITY
2618 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
2625 void QComboBox::focusInEvent(QFocusEvent *e)
2630 d->lineEdit->event(e);
2631 #ifndef QT_NO_COMPLETER
2632 if (d->lineEdit->completer())
2633 d->lineEdit->completer()->setWidget(this);
2641 void QComboBox::focusOutEvent(QFocusEvent *e)
2646 d->lineEdit->event(e);
2650 void QComboBox::changeEvent(QEvent *e)
2653 switch (e->type()) {
2654 case QEvent::StyleChange:
2655 d->updateDelegate();
2657 case QEvent::MacSizeChange:
2659 d->sizeHint = QSize(); // invalidate size hint
2660 d->minimumSizeHint = QSize();
2661 d->updateLayoutDirection();
2663 d->updateLineEditGeometry();
2664 d->setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
2666 // ### need to update scrollers etc. as well here
2668 case QEvent::EnabledChange:
2672 case QEvent::PaletteChange: {
2673 d->updateViewContainerPaletteAndOpacity();
2676 case QEvent::FontChange:
2677 d->sizeHint = QSize(); // invalidate size hint
2678 d->viewContainer()->setFont(font());
2680 d->updateLineEditGeometry();
2685 QWidget::changeEvent(e);
2691 void QComboBox::resizeEvent(QResizeEvent *)
2694 d->updateLineEditGeometry();
2700 void QComboBox::paintEvent(QPaintEvent *)
2702 QStylePainter painter(this);
2703 painter.setPen(palette().color(QPalette::Text));
2705 // draw the combobox frame, focusrect and selected etc.
2706 QStyleOptionComboBox opt;
2707 initStyleOption(&opt);
2708 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
2710 // draw the icon and text
2711 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
2717 void QComboBox::showEvent(QShowEvent *e)
2720 if (!d->shownOnce && d->sizeAdjustPolicy == QComboBox::AdjustToContentsOnFirstShow) {
2721 d->sizeHint = QSize();
2724 d->shownOnce = true;
2725 QWidget::showEvent(e);
2731 void QComboBox::hideEvent(QHideEvent *)
2739 bool QComboBox::event(QEvent *event)
2742 switch(event->type()) {
2743 case QEvent::LayoutDirectionChange:
2744 case QEvent::ApplicationLayoutDirectionChange:
2745 d->updateLayoutDirection();
2746 d->updateLineEditGeometry();
2748 case QEvent::HoverEnter:
2749 case QEvent::HoverLeave:
2750 case QEvent::HoverMove:
2751 if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
2752 d->updateHoverControl(he->pos());
2754 case QEvent::ShortcutOverride:
2756 return d->lineEdit->event(event);
2758 #ifdef QT_KEYPAD_NAVIGATION
2759 case QEvent::EnterEditFocus:
2761 setEditFocus(false); // We never want edit focus if we are not editable
2763 d->lineEdit->event(event); //so cursor starts
2765 case QEvent::LeaveEditFocus:
2767 d->lineEdit->event(event); //so cursor stops
2773 return QWidget::event(event);
2779 void QComboBox::mousePressEvent(QMouseEvent *e)
2782 QStyleOptionComboBox opt;
2783 initStyleOption(&opt);
2784 QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(),
2786 if (e->button() == Qt::LeftButton && (sc == QStyle::SC_ComboBoxArrow || !isEditable())
2787 && !d->viewContainer()->isVisible()) {
2788 if (sc == QStyle::SC_ComboBoxArrow)
2789 d->updateArrow(QStyle::State_Sunken);
2790 #ifdef QT_KEYPAD_NAVIGATION
2791 //if the container already exists, then d->viewContainer() is safe to call
2794 // We've restricted the next couple of lines, because by not calling
2795 // viewContainer(), we avoid creating the QComboBoxPrivateContainer.
2796 d->viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval());
2797 d->viewContainer()->initialClickPosition = mapToGlobal(e->pos());
2798 #ifdef QT_KEYPAD_NAVIGATION
2803 #ifdef QT_KEYPAD_NAVIGATION
2804 if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && d->lineEdit) {
2805 d->lineEdit->event(e); //so lineedit can move cursor, etc
2809 QWidget::mousePressEvent(e);
2816 void QComboBox::mouseReleaseEvent(QMouseEvent *e)
2820 d->updateArrow(QStyle::State_None);
2826 void QComboBox::keyPressEvent(QKeyEvent *e)
2830 #ifndef QT_NO_COMPLETER
2832 && d->lineEdit->completer()
2833 && d->lineEdit->completer()->popup()
2834 && d->lineEdit->completer()->popup()->isVisible()) {
2835 // provide same autocompletion support as line edit
2836 d->lineEdit->event(e);
2841 enum Move { NoMove=0 , MoveUp , MoveDown , MoveFirst , MoveLast};
2844 int newIndex = currentIndex();
2847 if (e->modifiers() & Qt::ControlModifier)
2848 break; // pass to line edit for auto completion
2849 case Qt::Key_PageUp:
2850 #ifdef QT_KEYPAD_NAVIGATION
2851 if (QApplication::keypadNavigationEnabled())
2858 if (e->modifiers() & Qt::AltModifier) {
2861 } else if (e->modifiers() & Qt::ControlModifier)
2862 break; // pass to line edit for auto completion
2864 case Qt::Key_PageDown:
2865 #ifdef QT_KEYPAD_NAVIGATION
2866 if (QApplication::keypadNavigationEnabled())
2881 if (!e->modifiers()) {
2892 case Qt::Key_Return:
2893 case Qt::Key_Escape:
2897 #ifdef QT_KEYPAD_NAVIGATION
2898 case Qt::Key_Select:
2899 if (QApplication::keypadNavigationEnabled()
2900 && (!hasEditFocus() || !d->lineEdit)) {
2907 if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
2911 if (QApplication::keypadNavigationEnabled()) {
2912 if (!hasEditFocus() || !d->lineEdit)
2915 e->ignore(); // let the surounding dialog have it
2921 if (!e->text().isEmpty())
2922 d->keyboardSearchString(e->text());
2928 if (move != NoMove) {
2935 while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2942 while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2950 if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2951 setCurrentIndex(newIndex);
2952 d->emitActivated(d->currentIndex);
2954 } else if (d->lineEdit) {
2955 d->lineEdit->event(e);
2963 void QComboBox::keyReleaseEvent(QKeyEvent *e)
2967 d->lineEdit->event(e);
2973 #ifndef QT_NO_WHEELEVENT
2974 void QComboBox::wheelEvent(QWheelEvent *e)
2977 if (!d->viewContainer()->isVisible()) {
2978 int newIndex = currentIndex();
2980 if (e->delta() > 0) {
2982 while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2986 while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2990 if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2991 setCurrentIndex(newIndex);
2992 d->emitActivated(d->currentIndex);
2999 #ifndef QT_NO_CONTEXTMENU
3003 void QComboBox::contextMenuEvent(QContextMenuEvent *e)
3007 Qt::ContextMenuPolicy p = d->lineEdit->contextMenuPolicy();
3008 d->lineEdit->setContextMenuPolicy(Qt::DefaultContextMenu);
3009 d->lineEdit->event(e);
3010 d->lineEdit->setContextMenuPolicy(p);
3013 #endif // QT_NO_CONTEXTMENU
3015 void QComboBoxPrivate::keyboardSearchString(const QString &text)
3017 // use keyboardSearch from the listView so we do not duplicate code
3018 QAbstractItemView *view = viewContainer()->itemView();
3019 view->setCurrentIndex(currentIndex);
3020 int currentRow = view->currentIndex().row();
3021 view->keyboardSearch(text);
3022 if (currentRow != view->currentIndex().row()) {
3023 setCurrentIndex(view->currentIndex());
3024 emitActivated(currentIndex);
3028 void QComboBoxPrivate::modelChanged()
3032 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
3034 adjustComboBoxSize();
3035 q->updateGeometry();
3042 void QComboBox::inputMethodEvent(QInputMethodEvent *e)
3046 d->lineEdit->event(e);
3048 if (!e->commitString().isEmpty())
3049 d->keyboardSearchString(e->commitString());
3058 QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query) const
3060 Q_D(const QComboBox);
3062 return d->lineEdit->inputMethodQuery(query);
3063 return QWidget::inputMethodQuery(query);
3067 \fn bool QComboBox::editable() const
3069 Use isEditable() instead.
3073 \fn void QComboBox::insertItem(const QPixmap &pixmap, int index)
3075 Use an insertItem() function that takes a QIcon instead, for
3076 example, insertItem(index, QIcon(pixmap)).
3080 \fn void QComboBox::insertItem(const QPixmap &pixmap, const QString &text, int index)
3082 Use an insertItem() function that takes a QIcon instead, for
3083 example, insertItem(index, QIcon(pixmap), text).
3089 \fn void QComboBox::changeItem(const QString &text, int index)
3091 Use setItemText() instead.
3095 \fn void QComboBox::changeItem(const QPixmap &pixmap, int index)
3097 Use setItemIcon() instead, for example,
3098 setItemIcon(index, QIcon(pixmap)).
3102 \fn void QComboBox::changeItem(const QPixmap &pixmap, const QString &text, int index)
3104 Use setItem() instead, for example, setItem(index, QIcon(pixmap),text).
3108 \fn void QComboBox::addItem(const QString &text, const QVariant &userData)
3110 Adds an item to the combobox with the given \a text, and
3111 containing the specified \a userData (stored in the Qt::UserRole).
3112 The item is appended to the list of existing items.
3116 \fn void QComboBox::addItem(const QIcon &icon, const QString &text,
3117 const QVariant &userData)
3119 Adds an item to the combobox with the given \a icon and \a text,
3120 and containing the specified \a userData (stored in the
3121 Qt::UserRole). The item is appended to the list of existing items.
3125 \fn void QComboBox::addItems(const QStringList &texts)
3127 Adds each of the strings in the given \a texts to the combobox. Each item
3128 is appended to the list of existing items in turn.
3132 \fn void QComboBox::editTextChanged(const QString &text)
3134 This signal is emitted when the text in the combobox's line edit
3135 widget is changed. The new text is specified by \a text.
3139 \property QComboBox::frame
3140 \brief whether the combo box draws itself with a frame
3143 If enabled (the default) the combo box draws itself inside a
3144 frame, otherwise the combo box draws itself without any frame.
3146 bool QComboBox::hasFrame() const
3148 Q_D(const QComboBox);
3153 void QComboBox::setFrame(bool enable)
3162 \property QComboBox::modelColumn
3163 \brief the column in the model that is visible.
3165 If set prior to populating the combo box, the pop-up view will
3166 not be affected and will show the first column (using this property's
3169 By default, this property has a value of 0.
3171 int QComboBox::modelColumn() const
3173 Q_D(const QComboBox);
3174 return d->modelColumn;
3177 void QComboBox::setModelColumn(int visibleColumn)
3180 d->modelColumn = visibleColumn;
3181 QListView *lv = qobject_cast<QListView *>(d->viewContainer()->itemView());
3183 lv->setModelColumn(visibleColumn);
3184 #ifndef QT_NO_COMPLETER
3185 if (d->lineEdit && d->lineEdit->completer()
3186 && d->lineEdit->completer() == d->completer)
3187 d->lineEdit->completer()->setCompletionColumn(visibleColumn);
3189 setCurrentIndex(currentIndex()); //update the text to the text of the new column;
3193 \fn int QComboBox::currentItem() const
3195 Use currentIndex() instead.
3199 \fn void QComboBox::setCurrentItem(int)
3201 Use setCurrentIndex(int) instead.
3205 \fn void QComboBox::popup()
3207 Use showPopup() instead.
3211 \fn void QComboBox::textChanged(const QString &text)
3213 Use the editTextChanged(const QString &text) signal instead.
3218 #include "moc_qcombobox.cpp"
3220 #endif // QT_NO_COMBOBOX