1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qcombobox.h"
44 #ifndef QT_NO_COMBOBOX
45 #include <qstylepainter.h>
46 #include <qpa/qplatformtheme.h>
47 #include <qlineedit.h>
48 #include <qapplication.h>
49 #include <qdesktopwidget.h>
50 #include <qlistview.h>
51 #include <qtableview.h>
52 #include <qitemdelegate.h>
57 #include <qscrollbar.h>
58 #include <qtreeview.h>
59 #include <qheaderview.h>
61 #include <qmetaobject.h>
62 #include <private/qguiapplication_p.h>
63 #include <private/qapplication_p.h>
64 #include <private/qcombobox_p.h>
65 #include <private/qabstractitemmodel_p.h>
66 #include <private/qabstractscrollarea_p.h>
67 #include <private/qsoftkeymanager_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
222 bool useFullScreenForPopupMenu = false;
223 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
224 useFullScreenForPopupMenu = theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool();
225 return useFullScreenForPopupMenu ?
226 QApplication::desktop()->screenGeometry(screen) :
227 QApplication::desktop()->availableGeometry(screen);
230 bool QComboBoxPrivate::updateHoverControl(const QPoint &pos)
234 QRect lastHoverRect = hoverRect;
235 QStyle::SubControl lastHoverControl = hoverControl;
236 bool doesHover = q->testAttribute(Qt::WA_Hover);
237 if (lastHoverControl != newHoverControl(pos) && doesHover) {
238 q->update(lastHoverRect);
239 q->update(hoverRect);
245 QStyle::SubControl QComboBoxPrivate::newHoverControl(const QPoint &pos)
248 QStyleOptionComboBox opt;
249 q->initStyleOption(&opt);
250 opt.subControls = QStyle::SC_All;
251 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, pos, q);
252 hoverRect = (hoverControl != QStyle::SC_None)
253 ? q->style()->subControlRect(QStyle::CC_ComboBox, &opt, hoverControl, q)
259 Computes a size hint based on the maximum width
260 for the items in the combobox.
262 int QComboBoxPrivate::computeWidthHint() const
264 Q_Q(const QComboBox);
267 const int count = q->count();
268 const int iconWidth = q->iconSize().width() + 4;
269 const QFontMetrics &fontMetrics = q->fontMetrics();
271 for (int i = 0; i < count; ++i) {
272 const int textWidth = fontMetrics.width(q->itemText(i));
273 if (q->itemIcon(i).isNull())
274 width = (qMax(width, textWidth));
276 width = (qMax(width, textWidth + iconWidth));
279 QStyleOptionComboBox opt;
280 q->initStyleOption(&opt);
282 tmp = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, tmp, q);
286 QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
288 Q_Q(const QComboBox);
290 bool hasIcon = sizeAdjustPolicy == QComboBox::AdjustToMinimumContentsLengthWithIcon ? true : false;
291 int count = q->count();
292 QSize iconSize = q->iconSize();
293 const QFontMetrics &fm = q->fontMetrics();
296 if (&sh == &sizeHint || minimumContentsLength == 0) {
297 switch (sizeAdjustPolicy) {
298 case QComboBox::AdjustToContents:
299 case QComboBox::AdjustToContentsOnFirstShow:
301 sh.rwidth() = 7 * fm.width(QLatin1Char('x'));
303 for (int i = 0; i < count; ++i) {
304 if (!q->itemIcon(i).isNull()) {
306 sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width() + iconSize.width() + 4));
308 sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width()));
313 case QComboBox::AdjustToMinimumContentsLength:
314 for (int i = 0; i < count && !hasIcon; ++i)
315 hasIcon = !q->itemIcon(i).isNull();
320 for (int i = 0; i < count && !hasIcon; ++i)
321 hasIcon = !q->itemIcon(i).isNull();
323 if (minimumContentsLength > 0)
324 sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.width(QLatin1Char('X')) + (hasIcon ? iconSize.width() + 4 : 0)));
328 sh.setHeight(qMax(qCeil(QFontMetricsF(fm).height()), 14) + 2);
330 sh.setHeight(qMax(sh.height(), iconSize.height() + 2));
333 // add style and strut values
334 QStyleOptionComboBox opt;
335 q->initStyleOption(&opt);
336 sh = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, q);
338 return sh.expandedTo(QApplication::globalStrut());
341 void QComboBoxPrivate::adjustComboBoxSize()
343 viewContainer()->adjustSizeTimer.start(20, container);
346 void QComboBoxPrivate::updateLayoutDirection()
348 Q_Q(const QComboBox);
349 QStyleOptionComboBox opt;
350 q->initStyleOption(&opt);
351 Qt::LayoutDirection dir = Qt::LayoutDirection(
352 q->style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, q));
354 lineEdit->setLayoutDirection(dir);
356 container->setLayoutDirection(dir);
360 void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent)
362 if (timerEvent->timerId() == adjustSizeTimer.timerId()) {
363 adjustSizeTimer.stop();
364 if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) {
365 combo->updateGeometry();
372 void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e)
374 QStyleOptionComboBox opt = comboStyleOption();
375 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) {
377 myOpt.initFrom(this);
378 QStyleHintReturnMask mask;
379 if (combo->style()->styleHint(QStyle::SH_Menu_Mask, &myOpt, this, &mask)) {
380 setMask(mask.region);
385 QFrame::resizeEvent(e);
388 void QComboBoxPrivateContainer::leaveEvent(QEvent *)
390 // On Mac using the Mac style we want to clear the selection
391 // when the mouse moves outside the popup.
393 QStyleOptionComboBox opt = comboStyleOption();
394 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo))
395 view->clearSelection();
399 QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent)
400 : QFrame(parent, Qt::Popup), combo(parent), view(0), top(0), bottom(0)
402 // we need the combobox and itemview
406 setAttribute(Qt::WA_WindowPropagation);
407 setAttribute(Qt::WA_X11NetWmWindowTypeCombo);
410 blockMouseReleaseTimer.setSingleShot(true);
412 // we need a vertical layout
413 QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
414 layout->setSpacing(0);
415 layout->setMargin(0);
418 setItemView(itemView);
420 // add scroller arrows if style needs them
421 QStyleOptionComboBox opt = comboStyleOption();
422 const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
424 top = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepSub, this);
425 bottom = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepAdd, this);
432 setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
435 layout->insertWidget(0, top);
436 connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
439 layout->addWidget(bottom);
440 connect(bottom, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
443 // Some styles (Mac) have a margin at the top and bottom of the popup.
444 layout->insertSpacing(0, 0);
445 layout->addSpacing(0);
446 updateTopBottomMargin();
449 void QComboBoxPrivateContainer::scrollItemView(int action)
451 #ifndef QT_NO_SCROLLBAR
452 if (view->verticalScrollBar())
453 view->verticalScrollBar()->triggerAction(static_cast<QAbstractSlider::SliderAction>(action));
458 Hides or shows the scrollers when we emulate a popupmenu
460 void QComboBoxPrivateContainer::updateScrollers()
462 #ifndef QT_NO_SCROLLBAR
466 if (isVisible() == false)
469 QStyleOptionComboBox opt = comboStyleOption();
470 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo) &&
471 view->verticalScrollBar()->minimum() < view->verticalScrollBar()->maximum()) {
473 bool needTop = view->verticalScrollBar()->value()
474 > (view->verticalScrollBar()->minimum() + spacing());
475 bool needBottom = view->verticalScrollBar()->value()
476 < (view->verticalScrollBar()->maximum() - spacing()*2);
489 #endif // QT_NO_SCROLLBAR
493 Cleans up when the view is destroyed.
495 void QComboBoxPrivateContainer::viewDestroyed()
498 setItemView(new QComboBoxListView());
502 Returns the item view used for the combobox popup.
504 QAbstractItemView *QComboBoxPrivateContainer::itemView() const
510 Sets the item view to be used for the combobox popup.
512 void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
518 view->removeEventFilter(this);
519 view->viewport()->removeEventFilter(this);
520 #ifndef QT_NO_SCROLLBAR
521 disconnect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
522 this, SLOT(updateScrollers()));
523 disconnect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
524 this, SLOT(updateScrollers()));
526 disconnect(view, SIGNAL(destroyed()),
527 this, SLOT(viewDestroyed()));
533 // setup the item view
535 view->setParent(this);
536 view->setAttribute(Qt::WA_MacShowFocusRect, false);
537 qobject_cast<QBoxLayout*>(layout())->insertWidget(top ? 2 : 0, view);
538 view->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
539 view->installEventFilter(this);
540 view->viewport()->installEventFilter(this);
541 view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
542 QStyleOptionComboBox opt = comboStyleOption();
543 const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
544 #ifndef QT_NO_SCROLLBAR
546 view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
548 if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
550 view->setMouseTracking(true);
552 view->setSelectionMode(QAbstractItemView::SingleSelection);
553 view->setFrameStyle(QFrame::NoFrame);
554 view->setLineWidth(0);
555 view->setEditTriggers(QAbstractItemView::NoEditTriggers);
556 #ifndef QT_NO_SCROLLBAR
557 connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
558 this, SLOT(updateScrollers()));
559 connect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
560 this, SLOT(updateScrollers()));
562 connect(view, SIGNAL(destroyed()),
563 this, SLOT(viewDestroyed()));
565 #ifdef QT_SOFTKEYS_ENABLED
566 selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, itemView);
567 cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, itemView);
568 addAction(selectAction);
569 addAction(cancelAction);
574 Returns the spacing between the items in the view.
576 int QComboBoxPrivateContainer::spacing() const
578 QListView *lview = qobject_cast<QListView*>(view);
580 return lview->spacing();
581 #ifndef QT_NO_TABLEVIEW
582 QTableView *tview = qobject_cast<QTableView*>(view);
584 return tview->showGrid() ? 1 : 0;
589 void QComboBoxPrivateContainer::updateTopBottomMargin()
591 if (!layout() || layout()->count() < 1)
594 QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout());
598 const QStyleOptionComboBox opt = comboStyleOption();
599 const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
600 const int margin = usePopup ? combo->style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, combo) : 0;
602 QSpacerItem *topSpacer = boxLayout->itemAt(0)->spacerItem();
604 topSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
606 QSpacerItem *bottomSpacer = boxLayout->itemAt(boxLayout->count() - 1)->spacerItem();
607 if (bottomSpacer && bottomSpacer != topSpacer)
608 bottomSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
610 boxLayout->invalidate();
613 void QComboBoxPrivateContainer::changeEvent(QEvent *e)
615 if (e->type() == QEvent::StyleChange) {
616 QStyleOptionComboBox opt = comboStyleOption();
617 view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
618 combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo));
619 setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
620 #ifdef QT_SOFTKEYS_ENABLED
621 } else if (e->type() == QEvent::LanguageChange) {
622 selectAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::SelectSoftKey));
623 cancelAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::CancelSoftKey));
627 QWidget::changeEvent(e);
631 bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
634 case QEvent::ShortcutOverride:
635 switch (static_cast<QKeyEvent*>(e)->key()) {
638 #ifdef QT_KEYPAD_NAVIGATION
641 if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
643 emit itemSelected(view->currentIndex());
647 if (!(static_cast<QKeyEvent*>(e)->modifiers() & Qt::AltModifier))
658 case QEvent::MouseMove:
660 QMouseEvent *m = static_cast<QMouseEvent *>(e);
661 QWidget *widget = static_cast<QWidget *>(o);
662 QPoint vector = widget->mapToGlobal(m->pos()) - initialClickPosition;
663 if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive())
664 blockMouseReleaseTimer.stop();
665 QModelIndex indexUnderMouse = view->indexAt(m->pos());
666 if (indexUnderMouse.isValid()
667 && !QComboBoxDelegate::isSeparator(indexUnderMouse)) {
668 view->setCurrentIndex(indexUnderMouse);
672 case QEvent::MouseButtonRelease: {
673 QMouseEvent *m = static_cast<QMouseEvent *>(e);
674 if (isVisible() && view->rect().contains(m->pos()) && view->currentIndex().isValid()
675 && !blockMouseReleaseTimer.isActive()
676 && (view->currentIndex().flags() & Qt::ItemIsEnabled)
677 && (view->currentIndex().flags() & Qt::ItemIsSelectable)) {
679 emit itemSelected(view->currentIndex());
687 return QFrame::eventFilter(o, e);
690 void QComboBoxPrivateContainer::showEvent(QShowEvent *)
695 void QComboBoxPrivateContainer::hideEvent(QHideEvent *)
699 #ifndef QT_NO_GRAPHICSVIEW
700 // QGraphicsScenePrivate::removePopup closes the combo box popup, it hides it non-explicitly.
701 // Hiding/showing the QComboBox after this will unexpectedly show the popup as well.
702 // Re-hiding the popup container makes sure it is explicitly hidden.
703 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget())
708 void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
711 QStyleOptionComboBox opt = comboStyleOption();
712 opt.subControls = QStyle::SC_All;
713 opt.activeSubControls = QStyle::SC_ComboBoxArrow;
714 QStyle::SubControl sc = combo->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt,
715 combo->mapFromGlobal(e->globalPos()),
717 if ((combo->isEditable() && sc == QStyle::SC_ComboBoxArrow)
718 || (!combo->isEditable() && sc != QStyle::SC_None))
719 setAttribute(Qt::WA_NoMouseReplay);
723 void QComboBoxPrivateContainer::mouseReleaseEvent(QMouseEvent *e)
726 if (!blockMouseReleaseTimer.isActive()){
732 QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
734 // ### This should use QComboBox's initStyleOption(), but it's protected
735 // perhaps, we could cheat by having the QCombo private instead?
736 QStyleOptionComboBox opt;
738 opt.subControls = QStyle::SC_All;
739 opt.activeSubControls = QStyle::SC_None;
740 opt.editable = combo->isEditable();
745 \enum QComboBox::InsertPolicy
747 This enum specifies what the QComboBox should do when a new string is
750 \value NoInsert The string will not be inserted into the combobox.
751 \value InsertAtTop The string will be inserted as the first item in the combobox.
752 \value InsertAtCurrent The current item will be \e replaced by the string.
753 \value InsertAtBottom The string will be inserted after the last item in the combobox.
754 \value InsertAfterCurrent The string is inserted after the current item in the combobox.
755 \value InsertBeforeCurrent The string is inserted before the current item in the combobox.
756 \value InsertAlphabetically The string is inserted in the alphabetic order in the combobox.
760 \enum QComboBox::SizeAdjustPolicy
762 This enum specifies how the size hint of the QComboBox should
763 adjust when new content is added or content changes.
765 \value AdjustToContents The combobox will always adjust to the contents
766 \value AdjustToContentsOnFirstShow The combobox will adjust to its contents the first time it is shown.
767 \value AdjustToMinimumContentsLength Use AdjustToContents or AdjustToContentsOnFirstShow instead.
768 \value AdjustToMinimumContentsLengthWithIcon The combobox will adjust to \l minimumContentsLength plus space for an icon. For performance reasons use this policy on large models.
772 \fn void QComboBox::activated(int index)
774 This signal is sent when the user chooses an item in the combobox.
775 The item's \a index is passed. Note that this signal is sent even
776 when the choice is not changed. If you need to know when the
777 choice actually changes, use signal currentIndexChanged().
782 \fn void QComboBox::activated(const QString &text)
784 This signal is sent when the user chooses an item in the combobox.
785 The item's \a text 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::highlighted(int index)
794 This signal is sent when an item in the combobox popup list is
795 highlighted by the user. The item's \a index is passed.
799 \fn void QComboBox::highlighted(const QString &text)
801 This signal is sent when an item in the combobox popup list is
802 highlighted by the user. The item's \a text is passed.
806 \fn void QComboBox::currentIndexChanged(int index)
809 This signal is sent whenever the currentIndex in the combobox
810 changes either through user interaction or programmatically. The
811 item's \a index is passed or -1 if the combobox becomes empty or the
812 currentIndex was reset.
816 \fn void QComboBox::currentIndexChanged(const QString &text)
819 This signal is sent whenever the currentIndex in the combobox
820 changes either through user interaction or programmatically. The
821 item's \a text is passed.
825 Constructs a combobox with the given \a parent, using the default
826 model QStandardItemModel.
828 QComboBox::QComboBox(QWidget *parent)
829 : QWidget(*new QComboBoxPrivate(), parent, 0)
838 QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent)
839 : QWidget(dd, parent, 0)
848 \brief The QComboBox widget is a combined button and popup list.
850 \ingroup basicwidgets
853 A QComboBox provides a means of presenting a list of options to the user
854 in a way that takes up the minimum amount of screen space.
856 A combobox is a selection widget that displays the current item,
857 and can pop up a list of selectable items. A combobox may be editable,
858 allowing the user to modify each item in the list.
860 Comboboxes can contain pixmaps as well as strings; the
861 insertItem() and setItemText() functions are suitably overloaded.
862 For editable comboboxes, the function clearEditText() is provided,
863 to clear the displayed string without changing the combobox's
866 There are two signals emitted if the current item of a combobox
867 changes, currentIndexChanged() and activated().
868 currentIndexChanged() is always emitted regardless if the change
869 was done programmatically or by user interaction, while
870 activated() is only emitted when the change is caused by user
871 interaction. The highlighted() signal is emitted when the user
872 highlights an item in the combobox popup list. All three signals
873 exist in two versions, one with a QString argument and one with an
874 \c int argument. If the user selects or highlights a pixmap, only
875 the \c int signals are emitted. Whenever the text of an editable
876 combobox is changed the editTextChanged() signal is emitted.
878 When the user enters a new string in an editable combobox, the
879 widget may or may not insert it, and it can insert it in several
880 locations. The default policy is \l InsertAtBottom but you can change
881 this using setInsertPolicy().
883 It is possible to constrain the input to an editable combobox
884 using QValidator; see setValidator(). By default, any input is
887 A combobox can be populated using the insert functions,
888 insertItem() and insertItems() for example. Items can be
889 changed with setItemText(). An item can be removed with
890 removeItem() and all items can be removed with clear(). The text
891 of the current item is returned by currentText(), and the text of
892 a numbered item is returned with text(). The current item can be
893 set with setCurrentIndex(). The number of items in the combobox is
894 returned by count(); the maximum number of items can be set with
895 setMaxCount(). You can allow editing using setEditable(). For
896 editable comboboxes you can set auto-completion using
897 setCompleter() and whether or not the user can add duplicates
898 is set with setDuplicatesEnabled().
900 QComboBox uses the \l{Model/View Programming}{model/view
901 framework} for its popup list and to store its items. By default
902 a QStandardItemModel stores the items and a QListView subclass
903 displays the popuplist. You can access the model and view directly
904 (with model() and view()), but QComboBox also provides functions
905 to set and get item data (e.g., setItemData() and itemText()). You
906 can also set a new model and view (with setModel() and setView()).
907 For the text and icon in the combobox label, the data in the model
908 that has the Qt::DisplayRole and Qt::DecorationRole is used. Note
909 that you cannot alter the \l{QAbstractItemView::}{SelectionMode}
910 of the view(), e.g., by using
911 \l{QAbstractItemView::}{setSelectionMode()}.
913 \image qstyle-comboboxes.png Comboboxes in the different built-in styles.
915 \sa QLineEdit, QSpinBox, QRadioButton, QButtonGroup,
916 {fowler}{GUI Design Handbook: Combo Box, Drop-Down List Box}
919 void QComboBoxPrivate::init()
922 q->setFocusPolicy(Qt::WheelFocus);
923 q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed,
924 QSizePolicy::ComboBox));
925 setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
926 q->setModel(new QStandardItemModel(0, 1, q));
927 if (!q->isEditable())
928 q->setAttribute(Qt::WA_InputMethodEnabled, false);
930 q->setAttribute(Qt::WA_InputMethodEnabled);
933 QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
939 container = new QComboBoxPrivateContainer(new QComboBoxListView(q), q);
940 container->itemView()->setModel(model);
941 container->itemView()->setTextElideMode(Qt::ElideMiddle);
942 updateDelegate(true);
943 updateLayoutDirection();
944 updateViewContainerPaletteAndOpacity();
945 QObject::connect(container, SIGNAL(itemSelected(QModelIndex)),
946 q, SLOT(_q_itemSelected(QModelIndex)));
947 QObject::connect(container->itemView()->selectionModel(),
948 SIGNAL(currentChanged(QModelIndex,QModelIndex)),
949 q, SLOT(_q_emitHighlighted(QModelIndex)));
950 QObject::connect(container, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
955 void QComboBoxPrivate::_q_resetButton()
957 updateArrow(QStyle::State_None);
960 void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
963 if (inserting || topLeft.parent() != root)
966 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
968 adjustComboBoxSize();
972 if (currentIndex.row() >= topLeft.row() && currentIndex.row() <= bottomRight.row()) {
974 lineEdit->setText(q->itemText(currentIndex.row()));
975 updateLineEditGeometry();
979 #ifndef QT_NO_ACCESSIBILITY
980 QAccessibleEvent event(q, QAccessible::NameChanged);
981 QAccessible::updateAccessibility(&event);
985 void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end)
988 if (inserting || parent != root)
991 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
993 adjustComboBoxSize();
997 // set current index if combo was previously empty
998 if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid()) {
999 q->setCurrentIndex(0);
1000 // need to emit changed if model updated index "silently"
1001 } else if (currentIndex.row() != indexBeforeChange) {
1003 _q_emitCurrentIndexChanged(currentIndex);
1007 void QComboBoxPrivate::_q_updateIndexBeforeChange()
1009 indexBeforeChange = currentIndex.row();
1012 void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
1018 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
1020 adjustComboBoxSize();
1021 q->updateGeometry();
1024 // model has changed the currentIndex
1025 if (currentIndex.row() != indexBeforeChange) {
1026 if (!currentIndex.isValid() && q->count()) {
1027 q->setCurrentIndex(qMin(q->count() - 1, qMax(indexBeforeChange, 0)));
1031 lineEdit->setText(q->itemText(currentIndex.row()));
1032 updateLineEditGeometry();
1035 _q_emitCurrentIndexChanged(currentIndex);
1040 void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
1045 QStyleOptionComboBox opt;
1046 q->initStyleOption(&opt);
1048 if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1050 menu.ensurePolished();
1051 container->setPalette(menu.palette());
1052 container->setWindowOpacity(menu.windowOpacity());
1056 container->setPalette(q->palette());
1057 container->setWindowOpacity(1.0);
1060 lineEdit->setPalette(q->palette());
1064 Initialize \a option with the values from this QComboBox. This method
1065 is useful for subclasses when they need a QStyleOptionComboBox, but don't want
1066 to fill in all the information themselves.
1068 \sa QStyleOption::initFrom()
1070 void QComboBox::initStyleOption(QStyleOptionComboBox *option) const
1075 Q_D(const QComboBox);
1076 option->initFrom(this);
1077 option->editable = isEditable();
1078 option->frame = d->frame;
1079 if (hasFocus() && !option->editable)
1080 option->state |= QStyle::State_Selected;
1081 option->subControls = QStyle::SC_All;
1082 if (d->arrowState == QStyle::State_Sunken) {
1083 option->activeSubControls = QStyle::SC_ComboBoxArrow;
1084 option->state |= d->arrowState;
1086 option->activeSubControls = d->hoverControl;
1088 if (d->currentIndex.isValid()) {
1089 option->currentText = currentText();
1090 option->currentIcon = d->itemIcon(d->currentIndex);
1092 option->iconSize = iconSize();
1093 if (d->container && d->container->isVisible())
1094 option->state |= QStyle::State_On;
1097 void QComboBoxPrivate::updateLineEditGeometry()
1103 QStyleOptionComboBox opt;
1104 q->initStyleOption(&opt);
1105 QRect editRect = q->style()->subControlRect(QStyle::CC_ComboBox, &opt,
1106 QStyle::SC_ComboBoxEditField, q);
1107 if (!q->itemIcon(q->currentIndex()).isNull()) {
1108 QRect comboRect(editRect);
1109 editRect.setWidth(editRect.width() - q->iconSize().width() - 4);
1110 editRect = QStyle::alignedRect(q->layoutDirection(), Qt::AlignRight,
1111 editRect.size(), comboRect);
1113 lineEdit->setGeometry(editRect);
1116 Qt::MatchFlags QComboBoxPrivate::matchFlags() const
1118 // Base how duplicates are determined on the autocompletion case sensitivity
1119 Qt::MatchFlags flags = Qt::MatchFixedString;
1120 #ifndef QT_NO_COMPLETER
1121 if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive)
1123 flags |= Qt::MatchCaseSensitive;
1128 void QComboBoxPrivate::_q_editingFinished()
1131 if (lineEdit && !lineEdit->text().isEmpty()) {
1132 //here we just check if the current item was entered
1133 const int index = q_func()->findText(lineEdit->text(), matchFlags());
1134 if (index != -1 && itemText(currentIndex) != lineEdit->text()) {
1135 q->setCurrentIndex(index);
1136 emitActivated(currentIndex);
1142 void QComboBoxPrivate::_q_returnPressed()
1145 if (lineEdit && !lineEdit->text().isEmpty()) {
1146 if (q->count() >= maxCount && !(this->insertPolicy == QComboBox::InsertAtCurrent))
1148 lineEdit->deselect();
1149 lineEdit->end(false);
1150 QString text = lineEdit->text();
1151 // check for duplicates (if not enabled) and quit
1153 if (!duplicatesEnabled) {
1154 index = q->findText(text, matchFlags());
1156 q->setCurrentIndex(index);
1157 emitActivated(currentIndex);
1161 switch (insertPolicy) {
1162 case QComboBox::InsertAtTop:
1165 case QComboBox::InsertAtBottom:
1168 case QComboBox::InsertAtCurrent:
1169 case QComboBox::InsertAfterCurrent:
1170 case QComboBox::InsertBeforeCurrent:
1171 if (!q->count() || !currentIndex.isValid())
1173 else if (insertPolicy == QComboBox::InsertAtCurrent)
1174 q->setItemText(q->currentIndex(), text);
1175 else if (insertPolicy == QComboBox::InsertAfterCurrent)
1176 index = q->currentIndex() + 1;
1177 else if (insertPolicy == QComboBox::InsertBeforeCurrent)
1178 index = q->currentIndex();
1180 case QComboBox::InsertAlphabetically:
1182 for (int i=0; i< q->count(); i++, index++ ) {
1183 if (text.toLower() < q->itemText(i).toLower())
1187 case QComboBox::NoInsert:
1192 q->insertItem(index, text);
1193 q->setCurrentIndex(index);
1194 emitActivated(currentIndex);
1199 void QComboBoxPrivate::_q_itemSelected(const QModelIndex &item)
1202 if (item != currentIndex) {
1203 setCurrentIndex(item);
1204 } else if (lineEdit) {
1205 lineEdit->selectAll();
1206 lineEdit->setText(q->itemText(currentIndex.row()));
1208 emitActivated(currentIndex);
1211 void QComboBoxPrivate::emitActivated(const QModelIndex &index)
1214 if (!index.isValid())
1216 QString text(itemText(index));
1217 emit q->activated(index.row());
1218 emit q->activated(text);
1221 void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
1224 if (!index.isValid())
1226 QString text(itemText(index));
1227 emit q->highlighted(index.row());
1228 emit q->highlighted(text);
1231 void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
1234 emit q->currentIndexChanged(index.row());
1235 emit q->currentIndexChanged(itemText(index));
1236 #ifndef QT_NO_ACCESSIBILITY
1237 QAccessibleEvent event(q, QAccessible::NameChanged);
1238 QAccessible::updateAccessibility(&event);
1242 QString QComboBoxPrivate::itemText(const QModelIndex &index) const
1244 return index.isValid() ? model->data(index, itemRole()).toString() : QString();
1247 int QComboBoxPrivate::itemRole() const
1249 return q_func()->isEditable() ? Qt::EditRole : Qt::DisplayRole;
1253 Destroys the combobox.
1255 QComboBox::~QComboBox()
1257 // ### check delegateparent and delete delegate if us?
1261 disconnect(d->model, SIGNAL(destroyed()),
1262 this, SLOT(_q_modelDestroyed()));
1264 ; // objects can't throw in destructor
1269 \property QComboBox::maxVisibleItems
1270 \brief the maximum allowed size on screen of the combo box, measured in items
1272 By default, this property has a value of 10.
1274 \note This property is ignored for non-editable comboboxes in styles that returns
1275 true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
1277 int QComboBox::maxVisibleItems() const
1279 Q_D(const QComboBox);
1280 return d->maxVisibleItems;
1283 void QComboBox::setMaxVisibleItems(int maxItems)
1287 qWarning("QComboBox::setMaxVisibleItems: "
1288 "Invalid max visible items (%d) must be >= 0", maxItems);
1291 d->maxVisibleItems = maxItems;
1295 \property QComboBox::count
1296 \brief the number of items in the combobox
1298 By default, for an empty combo box, this property has a value of 0.
1300 int QComboBox::count() const
1302 Q_D(const QComboBox);
1303 return d->model->rowCount(d->root);
1307 \property QComboBox::maxCount
1308 \brief the maximum number of items allowed in the combobox
1310 \note If you set the maximum number to be less then the current
1311 amount of items in the combobox, the extra items will be
1312 truncated. This also applies if you have set an external model on
1315 By default, this property's value is derived from the highest
1316 signed integer available (typically 2147483647).
1318 void QComboBox::setMaxCount(int max)
1322 qWarning("QComboBox::setMaxCount: Invalid count (%d) must be >= 0", max);
1327 d->model->removeRows(max, count() - max, d->root);
1332 int QComboBox::maxCount() const
1334 Q_D(const QComboBox);
1338 #ifndef QT_NO_COMPLETER
1341 \property QComboBox::autoCompletion
1342 \brief whether the combobox provides auto-completion for editable items
1346 Use setCompleter() instead.
1348 By default, this property is true.
1356 Use setCompleter() instead.
1358 bool QComboBox::autoCompletion() const
1360 Q_D(const QComboBox);
1361 return d->autoCompletion;
1367 Use setCompleter() instead.
1369 void QComboBox::setAutoCompletion(bool enable)
1373 #ifdef QT_KEYPAD_NAVIGATION
1374 if (QApplication::keypadNavigationEnabled() && !enable && isEditable())
1375 qWarning("QComboBox::setAutoCompletion: auto completion is mandatory when combo box editable");
1378 d->autoCompletion = enable;
1382 if (d->lineEdit->completer())
1384 d->completer = new QCompleter(d->model, d->lineEdit);
1385 d->completer->setCaseSensitivity(d->autoCompletionCaseSensitivity);
1386 d->completer->setCompletionMode(QCompleter::InlineCompletion);
1387 d->completer->setCompletionColumn(d->modelColumn);
1388 d->lineEdit->setCompleter(d->completer);
1389 d->completer->setWidget(this);
1391 d->lineEdit->setCompleter(0);
1396 \property QComboBox::autoCompletionCaseSensitivity
1397 \brief whether string comparisons are case-sensitive or case-insensitive for auto-completion
1400 By default, this property is Qt::CaseInsensitive.
1402 Use setCompleter() instead. Case sensitivity of the auto completion can be
1403 changed using QCompleter::setCaseSensitivity().
1411 Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1413 Qt::CaseSensitivity QComboBox::autoCompletionCaseSensitivity() const
1415 Q_D(const QComboBox);
1416 return d->autoCompletionCaseSensitivity;
1422 Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1424 void QComboBox::setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity)
1427 d->autoCompletionCaseSensitivity = sensitivity;
1428 if (d->lineEdit && d->lineEdit->completer())
1429 d->lineEdit->completer()->setCaseSensitivity(sensitivity);
1432 #endif // QT_NO_COMPLETER
1435 \property QComboBox::duplicatesEnabled
1436 \brief whether the user can enter duplicate items into the combobox
1438 Note that it is always possible to programmatically insert duplicate items into the
1441 By default, this property is false (duplicates are not allowed).
1443 bool QComboBox::duplicatesEnabled() const
1445 Q_D(const QComboBox);
1446 return d->duplicatesEnabled;
1449 void QComboBox::setDuplicatesEnabled(bool enable)
1452 d->duplicatesEnabled = enable;
1455 /*! \fn int QComboBox::findText(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const
1457 Returns the index of the item containing the given \a text; otherwise
1460 The \a flags specify how the items in the combobox are searched.
1464 Returns the index of the item containing the given \a data for the
1465 given \a role; otherwise returns -1.
1467 The \a flags specify how the items in the combobox are searched.
1469 int QComboBox::findData(const QVariant &data, int role, Qt::MatchFlags flags) const
1471 Q_D(const QComboBox);
1472 QModelIndexList result;
1473 QModelIndex start = d->model->index(0, d->modelColumn, d->root);
1474 result = d->model->match(start, role, data, 1, flags);
1475 if (result.isEmpty())
1477 return result.first().row();
1481 \property QComboBox::insertPolicy
1482 \brief the policy used to determine where user-inserted items should
1483 appear in the combobox
1485 The default value is \l InsertAtBottom, indicating that new items will appear
1486 at the bottom of the list of items.
1491 QComboBox::InsertPolicy QComboBox::insertPolicy() const
1493 Q_D(const QComboBox);
1494 return d->insertPolicy;
1497 void QComboBox::setInsertPolicy(InsertPolicy policy)
1500 d->insertPolicy = policy;
1504 \property QComboBox::sizeAdjustPolicy
1505 \brief the policy describing how the size of the combobox changes
1506 when the content changes
1508 The default value is \l AdjustToContentsOnFirstShow.
1510 \sa SizeAdjustPolicy
1513 QComboBox::SizeAdjustPolicy QComboBox::sizeAdjustPolicy() const
1515 Q_D(const QComboBox);
1516 return d->sizeAdjustPolicy;
1519 void QComboBox::setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy policy)
1522 if (policy == d->sizeAdjustPolicy)
1525 d->sizeAdjustPolicy = policy;
1526 d->sizeHint = QSize();
1527 d->adjustComboBoxSize();
1532 \property QComboBox::minimumContentsLength
1533 \brief the minimum number of characters that should fit into the combobox.
1535 The default value is 0.
1537 If this property is set to a positive value, the
1538 minimumSizeHint() and sizeHint() take it into account.
1540 \sa sizeAdjustPolicy
1542 int QComboBox::minimumContentsLength() const
1544 Q_D(const QComboBox);
1545 return d->minimumContentsLength;
1548 void QComboBox::setMinimumContentsLength(int characters)
1551 if (characters == d->minimumContentsLength || characters < 0)
1554 d->minimumContentsLength = characters;
1556 if (d->sizeAdjustPolicy == AdjustToContents
1557 || d->sizeAdjustPolicy == AdjustToMinimumContentsLength
1558 || d->sizeAdjustPolicy == AdjustToMinimumContentsLengthWithIcon) {
1559 d->sizeHint = QSize();
1560 d->adjustComboBoxSize();
1566 \property QComboBox::iconSize
1567 \brief the size of the icons shown in the combobox.
1569 Unless explicitly set this returns the default value of the
1570 current style. This size is the maximum size that icons can have;
1571 icons of smaller size are not scaled up.
1574 QSize QComboBox::iconSize() const
1576 Q_D(const QComboBox);
1577 if (d->iconSize.isValid())
1580 int iconWidth = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
1581 return QSize(iconWidth, iconWidth);
1584 void QComboBox::setIconSize(const QSize &size)
1587 if (size == d->iconSize)
1590 view()->setIconSize(size);
1592 d->sizeHint = QSize();
1597 \property QComboBox::editable
1598 \brief whether the combo box can be edited by the user
1600 By default, this property is false. The effect of editing depends
1601 on the insert policy.
1605 bool QComboBox::isEditable() const
1607 Q_D(const QComboBox);
1608 return d->lineEdit != 0;
1612 update the default delegate
1613 depending on the style's SH_ComboBox_Popup hint, we use a different default delegate.
1615 but we do not change the delegate is the combobox use a custom delegate,
1616 unless \a force is set to true.
1618 void QComboBoxPrivate::updateDelegate(bool force)
1621 QStyleOptionComboBox opt;
1622 q->initStyleOption(&opt);
1623 if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1624 if (force || qobject_cast<QComboBoxDelegate *>(q->itemDelegate()))
1625 q->setItemDelegate(new QComboMenuDelegate(q->view(), q));
1627 if (force || qobject_cast<QComboMenuDelegate *>(q->itemDelegate()))
1628 q->setItemDelegate(new QComboBoxDelegate(q->view(), q));
1632 QIcon QComboBoxPrivate::itemIcon(const QModelIndex &index) const
1634 QVariant decoration = model->data(index, Qt::DecorationRole);
1635 if (decoration.type() == QVariant::Pixmap)
1636 return QIcon(qvariant_cast<QPixmap>(decoration));
1638 return qvariant_cast<QIcon>(decoration);
1641 void QComboBox::setEditable(bool editable)
1644 if (isEditable() == editable)
1647 d->updateDelegate();
1649 QStyleOptionComboBox opt;
1650 initStyleOption(&opt);
1652 if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1653 d->viewContainer()->updateScrollers();
1654 view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
1656 QLineEdit *le = new QLineEdit(this);
1659 if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1660 d->viewContainer()->updateScrollers();
1661 view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1663 setAttribute(Qt::WA_InputMethodEnabled, false);
1664 d->lineEdit->hide();
1665 d->lineEdit->deleteLater();
1669 d->viewContainer()->updateTopBottomMargin();
1670 if (!testAttribute(Qt::WA_Resized))
1675 Sets the line \a edit to use instead of the current line edit widget.
1677 The combo box takes ownership of the line edit.
1679 void QComboBox::setLineEdit(QLineEdit *edit)
1683 qWarning("QComboBox::setLineEdit: cannot set a 0 line edit");
1687 if (edit == d->lineEdit)
1690 edit->setText(currentText());
1694 if (d->lineEdit->parent() != this)
1695 d->lineEdit->setParent(this);
1696 connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed()));
1697 connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished()));
1698 connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString)));
1699 d->lineEdit->setFrame(false);
1700 d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
1701 d->lineEdit->setFocusProxy(this);
1702 d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
1703 #ifndef QT_NO_COMPLETER
1704 setAutoCompletion(d->autoCompletion);
1707 #ifdef QT_KEYPAD_NAVIGATION
1708 #ifndef QT_NO_COMPLETER
1709 if (QApplication::keypadNavigationEnabled()) {
1710 // Editable combo boxes will have a completer that is set to UnfilteredPopupCompletion.
1711 // This means that when the user enters edit mode they are immediately presented with a
1712 // list of possible completions.
1713 setAutoCompletion(true);
1715 d->completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
1716 connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated()));
1722 setAttribute(Qt::WA_InputMethodEnabled);
1723 d->updateLayoutDirection();
1724 d->updateLineEditGeometry();
1726 d->lineEdit->show();
1732 Returns the line edit used to edit items in the combobox, or 0 if there
1735 Only editable combo boxes have a line edit.
1737 QLineEdit *QComboBox::lineEdit() const
1739 Q_D(const QComboBox);
1743 #ifndef QT_NO_VALIDATOR
1745 \fn void QComboBox::setValidator(const QValidator *validator)
1747 Sets the \a validator to use instead of the current validator.
1750 void QComboBox::setValidator(const QValidator *v)
1754 d->lineEdit->setValidator(v);
1758 Returns the validator that is used to constrain text input for the
1763 const QValidator *QComboBox::validator() const
1765 Q_D(const QComboBox);
1766 return d->lineEdit ? d->lineEdit->validator() : 0;
1768 #endif // QT_NO_VALIDATOR
1770 #ifndef QT_NO_COMPLETER
1773 \fn void QComboBox::setCompleter(QCompleter *completer)
1776 Sets the \a completer to use instead of the current completer.
1777 If \a completer is 0, auto completion is disabled.
1779 By default, for an editable combo box, a QCompleter that
1780 performs case insensitive inline completion is automatically created.
1782 void QComboBox::setCompleter(QCompleter *c)
1787 d->lineEdit->setCompleter(c);
1795 Returns the completer that is used to auto complete text input for the
1800 QCompleter *QComboBox::completer() const
1802 Q_D(const QComboBox);
1803 return d->lineEdit ? d->lineEdit->completer() : 0;
1806 #endif // QT_NO_COMPLETER
1809 Returns the item delegate used by the popup list view.
1811 \sa setItemDelegate()
1813 QAbstractItemDelegate *QComboBox::itemDelegate() const
1815 return view()->itemDelegate();
1819 Sets the item \a delegate for the popup list view.
1820 The combobox takes ownership of the delegate.
1822 \warning You should not share the same instance of a delegate between comboboxes,
1823 widget mappers or views. Doing so can cause incorrect or unintuitive editing behavior
1824 since each view connected to a given delegate may receive the
1825 \l{QAbstractItemDelegate::}{closeEditor()} signal, and attempt to access, modify or
1826 close an editor that has already been closed.
1830 void QComboBox::setItemDelegate(QAbstractItemDelegate *delegate)
1833 qWarning("QComboBox::setItemDelegate: cannot set a 0 delegate");
1836 delete view()->itemDelegate();
1837 view()->setItemDelegate(delegate);
1841 Returns the model used by the combobox.
1844 QAbstractItemModel *QComboBox::model() const
1846 Q_D(const QComboBox);
1847 if (d->model == QAbstractItemModelPrivate::staticEmptyModel()) {
1848 QComboBox *that = const_cast<QComboBox*>(this);
1849 that->setModel(new QStandardItemModel(0, 1, that));
1855 Sets the model to be \a model. \a model must not be 0.
1856 If you want to clear the contents of a model, call clear().
1860 void QComboBox::setModel(QAbstractItemModel *model)
1865 qWarning("QComboBox::setModel: cannot set a 0 model");
1869 #ifndef QT_NO_COMPLETER
1870 if (d->lineEdit && d->lineEdit->completer()
1871 && d->lineEdit->completer() == d->completer)
1872 d->lineEdit->completer()->setModel(model);
1875 disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1876 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1877 disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
1878 this, SLOT(_q_updateIndexBeforeChange()));
1879 disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
1880 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
1881 disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
1882 this, SLOT(_q_updateIndexBeforeChange()));
1883 disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
1884 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
1885 disconnect(d->model, SIGNAL(destroyed()),
1886 this, SLOT(_q_modelDestroyed()));
1887 disconnect(d->model, SIGNAL(modelAboutToBeReset()),
1888 this, SLOT(_q_updateIndexBeforeChange()));
1889 disconnect(d->model, SIGNAL(modelReset()),
1890 this, SLOT(_q_modelReset()));
1891 if (d->model->QObject::parent() == this)
1897 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1898 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1899 connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
1900 this, SLOT(_q_updateIndexBeforeChange()));
1901 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
1902 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
1903 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
1904 this, SLOT(_q_updateIndexBeforeChange()));
1905 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
1906 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
1907 connect(model, SIGNAL(destroyed()),
1908 this, SLOT(_q_modelDestroyed()));
1909 connect(model, SIGNAL(modelAboutToBeReset()),
1910 this, SLOT(_q_updateIndexBeforeChange()));
1911 connect(model, SIGNAL(modelReset()),
1912 this, SLOT(_q_modelReset()));
1915 d->container->itemView()->setModel(model);
1916 connect(d->container->itemView()->selectionModel(),
1917 SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1918 this, SLOT(_q_emitHighlighted(QModelIndex)), Qt::UniqueConnection);
1921 bool currentReset = false;
1924 for (int pos=0; pos < count(); pos++) {
1925 if (d->model->index(pos, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled) {
1926 setCurrentIndex(pos);
1927 currentReset = true;
1934 setCurrentIndex(-1);
1940 Returns the root model item index for the items in the combobox.
1942 \sa setRootModelIndex()
1945 QModelIndex QComboBox::rootModelIndex() const
1947 Q_D(const QComboBox);
1948 return QModelIndex(d->root);
1952 Sets the root model item \a index for the items in the combobox.
1954 \sa rootModelIndex()
1956 void QComboBox::setRootModelIndex(const QModelIndex &index)
1959 d->root = QPersistentModelIndex(index);
1960 view()->setRootIndex(index);
1965 \property QComboBox::currentIndex
1966 \brief the index of the current item in the combobox.
1968 The current index can change when inserting or removing items.
1970 By default, for an empty combo box or a combo box in which no current
1971 item is set, this property has a value of -1.
1973 int QComboBox::currentIndex() const
1975 Q_D(const QComboBox);
1976 return d->currentIndex.row();
1979 void QComboBox::setCurrentIndex(int index)
1982 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
1983 d->setCurrentIndex(mi);
1986 void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
1990 QModelIndex normalized;
1991 if (mi.column() != modelColumn)
1992 normalized = model->index(mi.row(), modelColumn, mi.parent());
1993 if (!normalized.isValid())
1994 normalized = mi; // Fallback to passed index.
1996 bool indexChanged = (normalized != currentIndex);
1998 currentIndex = QPersistentModelIndex(normalized);
2000 QString newText = q->itemText(normalized.row());
2001 if (lineEdit->text() != newText)
2002 lineEdit->setText(newText);
2003 updateLineEditGeometry();
2007 _q_emitCurrentIndexChanged(currentIndex);
2012 \property QComboBox::currentText
2013 \brief the current text
2015 If the combo box is editable, the current text is the value displayed
2016 by the line edit. Otherwise, it is the value of the current item or
2017 an empty string if the combo box is empty or no current item is set.
2021 QString QComboBox::currentText() const
2023 Q_D(const QComboBox);
2025 return d->lineEdit->text();
2026 else if (d->currentIndex.isValid())
2027 return d->itemText(d->currentIndex);
2033 Returns the text for the given \a index in the combobox.
2035 QString QComboBox::itemText(int index) const
2037 Q_D(const QComboBox);
2038 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2039 return d->itemText(mi);
2043 Returns the icon for the given \a index in the combobox.
2045 QIcon QComboBox::itemIcon(int index) const
2047 Q_D(const QComboBox);
2048 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2049 return d->itemIcon(mi);
2053 Returns the data for the given \a role in the given \a index in the
2054 combobox, or QVariant::Invalid if there is no data for this role.
2056 QVariant QComboBox::itemData(int index, int role) const
2058 Q_D(const QComboBox);
2059 QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2060 return d->model->data(mi, role);
2064 \fn void QComboBox::insertItem(int index, const QString &text, const QVariant &userData)
2066 Inserts the \a text and \a userData (stored in the Qt::UserRole)
2067 into the combobox at the given \a index.
2069 If the index is equal to or higher than the total number of items,
2070 the new item is appended to the list of existing items. If the
2071 index is zero or negative, the new item is prepended to the list
2079 Inserts the \a icon, \a text and \a userData (stored in the
2080 Qt::UserRole) into the combobox at the given \a index.
2082 If the index is equal to or higher than the total number of items,
2083 the new item is appended to the list of existing items. If the
2084 index is zero or negative, the new item is prepended to the list
2089 void QComboBox::insertItem(int index, const QIcon &icon, const QString &text, const QVariant &userData)
2092 int itemCount = count();
2093 index = qBound(0, index, itemCount);
2094 if (index >= d->maxCount)
2097 // For the common case where we are using the built in QStandardItemModel
2098 // construct a QStandardItem, reducing the number of expensive signals from the model
2099 if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(d->model)) {
2100 QStandardItem *item = new QStandardItem(text);
2101 if (!icon.isNull()) item->setData(icon, Qt::DecorationRole);
2102 if (userData.isValid()) item->setData(userData, Qt::UserRole);
2103 m->insertRow(index, item);
2106 d->inserting = true;
2107 if (d->model->insertRows(index, 1, d->root)) {
2108 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2109 if (icon.isNull() && !userData.isValid()) {
2110 d->model->setData(item, text, Qt::EditRole);
2112 QMap<int, QVariant> values;
2113 if (!text.isNull()) values.insert(Qt::EditRole, text);
2114 if (!icon.isNull()) values.insert(Qt::DecorationRole, icon);
2115 if (userData.isValid()) values.insert(Qt::UserRole, userData);
2116 if (!values.isEmpty()) d->model->setItemData(item, values);
2118 d->inserting = false;
2119 d->_q_rowsInserted(d->root, index, index);
2122 d->inserting = false;
2126 if (itemCount > d->maxCount)
2127 d->model->removeRows(itemCount - 1, itemCount - d->maxCount, d->root);
2131 Inserts the strings from the \a list into the combobox as separate items,
2132 starting at the \a index specified.
2134 If the index is equal to or higher than the total number of items, the new items
2135 are appended to the list of existing items. If the index is zero or negative, the
2136 new items are prepended to the list of existing items.
2140 void QComboBox::insertItems(int index, const QStringList &list)
2145 index = qBound(0, index, count());
2146 int insertCount = qMin(d->maxCount - index, list.count());
2147 if (insertCount <= 0)
2149 // For the common case where we are using the built in QStandardItemModel
2150 // construct a QStandardItem, reducing the number of expensive signals from the model
2151 if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(d->model)) {
2152 QList<QStandardItem *> items;
2153 QStandardItem *hiddenRoot = m->invisibleRootItem();
2154 for (int i = 0; i < insertCount; ++i)
2155 items.append(new QStandardItem(list.at(i)));
2156 hiddenRoot->insertRows(index, items);
2158 d->inserting = true;
2159 if (d->model->insertRows(index, insertCount, d->root)) {
2161 for (int i = 0; i < insertCount; ++i) {
2162 item = d->model->index(i+index, d->modelColumn, d->root);
2163 d->model->setData(item, list.at(i), Qt::EditRole);
2165 d->inserting = false;
2166 d->_q_rowsInserted(d->root, index, index + insertCount - 1);
2168 d->inserting = false;
2173 if (mc > d->maxCount)
2174 d->model->removeRows(d->maxCount, mc - d->maxCount, d->root);
2180 Inserts a separator item into the combobox at the given \a index.
2182 If the index is equal to or higher than the total number of items, the new item
2183 is appended to the list of existing items. If the index is zero or negative, the
2184 new item is prepended to the list of existing items.
2188 void QComboBox::insertSeparator(int index)
2191 int itemCount = count();
2192 index = qBound(0, index, itemCount);
2193 if (index >= d->maxCount)
2195 insertItem(index, QIcon(), QString());
2196 QComboBoxDelegate::setSeparator(d->model, d->model->index(index, 0, d->root));
2200 Removes the item at the given \a index from the combobox.
2201 This will update the current index if the index is removed.
2203 This function does nothing if \a index is out of range.
2205 void QComboBox::removeItem(int index)
2208 if (index < 0 || index >= count())
2210 d->model->removeRows(index, 1, d->root);
2214 Sets the \a text for the item on the given \a index in the combobox.
2216 void QComboBox::setItemText(int index, const QString &text)
2218 Q_D(const QComboBox);
2219 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2220 if (item.isValid()) {
2221 d->model->setData(item, text, Qt::EditRole);
2226 Sets the \a icon for the item on the given \a index in the combobox.
2228 void QComboBox::setItemIcon(int index, const QIcon &icon)
2230 Q_D(const QComboBox);
2231 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2232 if (item.isValid()) {
2233 d->model->setData(item, icon, Qt::DecorationRole);
2238 Sets the data \a role for the item on the given \a index in the combobox
2239 to the specified \a value.
2241 void QComboBox::setItemData(int index, const QVariant &value, int role)
2243 Q_D(const QComboBox);
2244 QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2245 if (item.isValid()) {
2246 d->model->setData(item, value, role);
2251 Returns the list view used for the combobox popup.
2253 QAbstractItemView *QComboBox::view() const
2255 Q_D(const QComboBox);
2256 return const_cast<QComboBoxPrivate*>(d)->viewContainer()->itemView();
2260 Sets the view to be used in the combobox popup to the given \a
2261 itemView. The combobox takes ownership of the view.
2263 Note: If you want to use the convenience views (like QListWidget,
2264 QTableWidget or QTreeWidget), make sure to call setModel() on the
2265 combobox with the convenience widgets model before calling this
2268 void QComboBox::setView(QAbstractItemView *itemView)
2272 qWarning("QComboBox::setView: cannot set a 0 view");
2276 if (itemView->model() != d->model)
2277 itemView->setModel(d->model);
2278 d->viewContainer()->setItemView(itemView);
2284 QSize QComboBox::minimumSizeHint() const
2286 Q_D(const QComboBox);
2287 return d->recomputeSizeHint(d->minimumSizeHint);
2293 This implementation caches the size hint to avoid resizing when
2294 the contents change dynamically. To invalidate the cached value
2295 change the \l sizeAdjustPolicy.
2297 QSize QComboBox::sizeHint() const
2299 Q_D(const QComboBox);
2300 return d->recomputeSizeHint(d->sizeHint);
2304 Displays the list of items in the combobox. If the list is empty
2305 then the no items will be shown.
2307 If you reimplement this function to show a custom pop-up, make
2308 sure you call hidePopup() to reset the internal state.
2312 void QComboBox::showPopup()
2318 #ifdef QT_KEYPAD_NAVIGATION
2319 #ifndef QT_NO_COMPLETER
2320 if (QApplication::keypadNavigationEnabled() && d->completer) {
2321 // editable combo box is line edit plus completer
2323 d->completer->complete(); // show popup
2329 QStyle * const style = this->style();
2331 // set current item and select it
2332 view()->selectionModel()->setCurrentIndex(d->currentIndex,
2333 QItemSelectionModel::ClearAndSelect);
2334 QComboBoxPrivateContainer* container = d->viewContainer();
2335 QStyleOptionComboBox opt;
2336 initStyleOption(&opt);
2337 QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt,
2338 QStyle::SC_ComboBoxListBoxPopup, this));
2339 QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this));
2341 QPoint below = mapToGlobal(listRect.bottomLeft());
2342 int belowHeight = screen.bottom() - below.y();
2343 QPoint above = mapToGlobal(listRect.topLeft());
2344 int aboveHeight = above.y() - screen.y();
2345 bool boundToScreen = !window()->testAttribute(Qt::WA_DontShowOnScreen);
2347 const bool usePopup = style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this);
2351 QStack<QModelIndex> toCheck;
2352 toCheck.push(view()->rootIndex());
2353 #ifndef QT_NO_TREEVIEW
2354 QTreeView *treeView = qobject_cast<QTreeView*>(view());
2355 if (treeView && treeView->header() && !treeView->header()->isHidden())
2356 listHeight += treeView->header()->height();
2358 while (!toCheck.isEmpty()) {
2359 QModelIndex parent = toCheck.pop();
2360 for (int i = 0; i < d->model->rowCount(parent); ++i) {
2361 QModelIndex idx = d->model->index(i, d->modelColumn, parent);
2364 listHeight += view()->visualRect(idx).height() + container->spacing();
2365 #ifndef QT_NO_TREEVIEW
2366 if (d->model->hasChildren(idx) && treeView && treeView->isExpanded(idx))
2370 if (!usePopup && count >= d->maxVisibleItems) {
2376 listRect.setHeight(listHeight);
2380 // add the spacing for the grid on the top and the bottom;
2381 int heightMargin = 2*container->spacing();
2383 // add the frame of the container
2384 int marginTop, marginBottom;
2385 container->getContentsMargins(0, &marginTop, 0, &marginBottom);
2386 heightMargin += marginTop + marginBottom;
2388 //add the frame of the view
2389 view()->getContentsMargins(0, &marginTop, 0, &marginBottom);
2390 marginTop += static_cast<QAbstractScrollAreaPrivate *>(QObjectPrivate::get(view()))->top;
2391 marginBottom += static_cast<QAbstractScrollAreaPrivate *>(QObjectPrivate::get(view()))->bottom;
2392 heightMargin += marginTop + marginBottom;
2394 listRect.setHeight(listRect.height() + heightMargin);
2397 // Add space for margin at top and bottom if the style wants it.
2399 listRect.setHeight(listRect.height() + style->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) * 2);
2401 // Make sure the popup is wide enough to display its contents.
2403 const int diff = d->computeWidthHint() - width();
2405 listRect.setWidth(listRect.width() + diff);
2408 //we need to activate the layout to make sure the min/maximum size are set when the widget was not yet show
2409 container->layout()->activate();
2410 //takes account of the minimum/maximum size of the container
2411 listRect.setSize( listRect.size().expandedTo(container->minimumSize())
2412 .boundedTo(container->maximumSize()));
2414 // make sure the widget fits on screen
2415 if (boundToScreen) {
2416 if (listRect.width() > screen.width() )
2417 listRect.setWidth(screen.width());
2418 if (mapToGlobal(listRect.bottomRight()).x() > screen.right()) {
2419 below.setX(screen.x() + screen.width() - listRect.width());
2420 above.setX(screen.x() + screen.width() - listRect.width());
2422 if (mapToGlobal(listRect.topLeft()).x() < screen.x() ) {
2423 below.setX(screen.x());
2424 above.setX(screen.x());
2429 // Position horizontally.
2430 listRect.moveLeft(above.x());
2432 // Position vertically so the curently selected item lines up
2433 // with the combo box.
2434 const QRect currentItemRect = view()->visualRect(view()->currentIndex());
2435 const int offset = listRect.top() - currentItemRect.top();
2436 listRect.moveTop(above.y() + offset - listRect.top());
2438 // Clamp the listRect height and vertical position so we don't expand outside the
2439 // available screen geometry.This may override the vertical position, but it is more
2440 // important to show as much as possible of the popup.
2441 const int height = !boundToScreen ? listRect.height() : qMin(listRect.height(), screen.height());
2442 listRect.setHeight(height);
2444 if (boundToScreen) {
2445 if (listRect.top() < screen.top())
2446 listRect.moveTop(screen.top());
2447 if (listRect.bottom() > screen.bottom())
2448 listRect.moveBottom(screen.bottom());
2450 } else if (!boundToScreen || listRect.height() <= belowHeight) {
2451 listRect.moveTopLeft(below);
2452 } else if (listRect.height() <= aboveHeight) {
2453 listRect.moveBottomLeft(above);
2454 } else if (belowHeight >= aboveHeight) {
2455 listRect.setHeight(belowHeight);
2456 listRect.moveTopLeft(below);
2458 listRect.setHeight(aboveHeight);
2459 listRect.moveBottomLeft(above);
2463 qApp->inputMethod()->reset();
2466 QScrollBar *sb = view()->horizontalScrollBar();
2467 Qt::ScrollBarPolicy policy = view()->horizontalScrollBarPolicy();
2468 bool needHorizontalScrollBar = (policy == Qt::ScrollBarAsNeeded || policy == Qt::ScrollBarAlwaysOn)
2469 && sb->minimum() < sb->maximum();
2470 if (needHorizontalScrollBar) {
2471 listRect.adjust(0, 0, 0, sb->height());
2473 container->setGeometry(listRect);
2476 const bool updatesEnabled = container->updatesEnabled();
2479 #if !defined(QT_NO_EFFECTS)
2480 bool scrollDown = (listRect.topLeft() == below);
2481 if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo)
2482 && !style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && !window()->testAttribute(Qt::WA_DontShowOnScreen))
2483 qScrollEffect(container, scrollDown ? QEffects::DownScroll : QEffects::UpScroll, 150);
2486 // Don't disable updates on Mac OS X. Windows are displayed immediately on this platform,
2487 // which means that the window will be visible before the call to container->show() returns.
2488 // If updates are disabled at this point we'll miss our chance at painting the popup
2489 // menu before it's shown, causing flicker since the window then displays the standard gray
2492 container->setUpdatesEnabled(false);
2497 container->updateScrollers();
2500 view()->scrollTo(view()->currentIndex(),
2501 style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)
2502 ? QAbstractItemView::PositionAtCenter
2503 : QAbstractItemView::EnsureVisible);
2506 container->setUpdatesEnabled(updatesEnabled);
2509 container->update();
2510 #ifdef QT_KEYPAD_NAVIGATION
2511 if (QApplication::keypadNavigationEnabled())
2512 view()->setEditFocus(true);
2517 Hides the list of items in the combobox if it is currently visible
2518 and resets the internal state, so that if the custom pop-up was
2519 shown inside the reimplemented showPopup(), then you also need to
2520 reimplement the hidePopup() function to hide your custom pop-up
2521 and call the base class implementation to reset the internal state
2522 whenever your custom pop-up widget is hidden.
2526 void QComboBox::hidePopup()
2529 if (d->container && d->container->isVisible()) {
2530 #if !defined(QT_NO_EFFECTS)
2531 d->model->blockSignals(true);
2532 d->container->itemView()->blockSignals(true);
2533 d->container->blockSignals(true);
2534 // Flash selected/triggered item (if any).
2535 if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) {
2536 QItemSelectionModel *selectionModel = view() ? view()->selectionModel() : 0;
2537 if (selectionModel && selectionModel->hasSelection()) {
2538 QEventLoop eventLoop;
2539 const QItemSelection selection = selectionModel->selection();
2541 // Deselect item and wait 60 ms.
2542 selectionModel->select(selection, QItemSelectionModel::Toggle);
2543 QTimer::singleShot(60, &eventLoop, SLOT(quit()));
2546 // Select item and wait 20 ms.
2547 selectionModel->select(selection, QItemSelectionModel::Toggle);
2548 QTimer::singleShot(20, &eventLoop, SLOT(quit()));
2554 bool needFade = style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
2555 bool didFade = false;
2557 #if defined(Q_OS_MAC)
2558 QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface();
2559 int at = platformNativeInterface->metaObject()->indexOfMethod("fadeWindow()");
2561 QMetaMethod windowFade = platformNativeInterface->metaObject()->method(at);
2562 windowFade.invoke(platformNativeInterface, Q_ARG(QWindow *, d->container->windowHandle()));
2567 // Other platform implementations welcome :-)
2569 d->model->blockSignals(false);
2570 d->container->itemView()->blockSignals(false);
2571 d->container->blockSignals(false);
2574 #endif // QT_NO_EFFECTS
2575 // Fade should implicitly hide as well ;-)
2576 d->container->hide();
2578 #ifdef QT_KEYPAD_NAVIGATION
2579 if (QApplication::keypadNavigationEnabled() && isEditable() && hasFocus())
2582 d->_q_resetButton();
2586 Clears the combobox, removing all items.
2588 Note: If you have set an external model on the combobox this model
2589 will still be cleared when calling this function.
2591 void QComboBox::clear()
2594 d->model->removeRows(0, d->model->rowCount(d->root), d->root);
2595 #ifndef QT_NO_ACCESSIBILITY
2596 QAccessibleEvent event(this, QAccessible::NameChanged);
2597 QAccessible::updateAccessibility(&event);
2602 Clears the contents of the line edit used for editing in the combobox.
2604 void QComboBox::clearEditText()
2608 d->lineEdit->clear();
2609 #ifndef QT_NO_ACCESSIBILITY
2610 QAccessibleEvent event(this, QAccessible::NameChanged);
2611 QAccessible::updateAccessibility(&event);
2616 Sets the \a text in the combobox's text edit.
2618 void QComboBox::setEditText(const QString &text)
2622 d->lineEdit->setText(text);
2623 #ifndef QT_NO_ACCESSIBILITY
2624 QAccessibleEvent event(this, QAccessible::NameChanged);
2625 QAccessible::updateAccessibility(&event);
2632 void QComboBox::focusInEvent(QFocusEvent *e)
2637 d->lineEdit->event(e);
2638 #ifndef QT_NO_COMPLETER
2639 if (d->lineEdit->completer())
2640 d->lineEdit->completer()->setWidget(this);
2648 void QComboBox::focusOutEvent(QFocusEvent *e)
2653 d->lineEdit->event(e);
2657 void QComboBox::changeEvent(QEvent *e)
2660 switch (e->type()) {
2661 case QEvent::StyleChange:
2662 d->updateDelegate();
2664 case QEvent::MacSizeChange:
2666 d->sizeHint = QSize(); // invalidate size hint
2667 d->minimumSizeHint = QSize();
2668 d->updateLayoutDirection();
2670 d->updateLineEditGeometry();
2671 d->setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
2673 // ### need to update scrollers etc. as well here
2675 case QEvent::EnabledChange:
2679 case QEvent::PaletteChange: {
2680 d->updateViewContainerPaletteAndOpacity();
2683 case QEvent::FontChange:
2684 d->sizeHint = QSize(); // invalidate size hint
2685 d->viewContainer()->setFont(font());
2687 d->updateLineEditGeometry();
2692 QWidget::changeEvent(e);
2698 void QComboBox::resizeEvent(QResizeEvent *)
2701 d->updateLineEditGeometry();
2707 void QComboBox::paintEvent(QPaintEvent *)
2709 QStylePainter painter(this);
2710 painter.setPen(palette().color(QPalette::Text));
2712 // draw the combobox frame, focusrect and selected etc.
2713 QStyleOptionComboBox opt;
2714 initStyleOption(&opt);
2715 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
2717 // draw the icon and text
2718 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
2724 void QComboBox::showEvent(QShowEvent *e)
2727 if (!d->shownOnce && d->sizeAdjustPolicy == QComboBox::AdjustToContentsOnFirstShow) {
2728 d->sizeHint = QSize();
2731 d->shownOnce = true;
2732 QWidget::showEvent(e);
2738 void QComboBox::hideEvent(QHideEvent *)
2746 bool QComboBox::event(QEvent *event)
2749 switch(event->type()) {
2750 case QEvent::LayoutDirectionChange:
2751 case QEvent::ApplicationLayoutDirectionChange:
2752 d->updateLayoutDirection();
2753 d->updateLineEditGeometry();
2755 case QEvent::HoverEnter:
2756 case QEvent::HoverLeave:
2757 case QEvent::HoverMove:
2758 if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
2759 d->updateHoverControl(he->pos());
2761 case QEvent::ShortcutOverride:
2763 return d->lineEdit->event(event);
2765 #ifdef QT_KEYPAD_NAVIGATION
2766 case QEvent::EnterEditFocus:
2768 setEditFocus(false); // We never want edit focus if we are not editable
2770 d->lineEdit->event(event); //so cursor starts
2772 case QEvent::LeaveEditFocus:
2774 d->lineEdit->event(event); //so cursor stops
2780 return QWidget::event(event);
2786 void QComboBox::mousePressEvent(QMouseEvent *e)
2789 QStyleOptionComboBox opt;
2790 initStyleOption(&opt);
2791 QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(),
2793 if (e->button() == Qt::LeftButton && (sc == QStyle::SC_ComboBoxArrow || !isEditable())
2794 && !d->viewContainer()->isVisible()) {
2795 if (sc == QStyle::SC_ComboBoxArrow)
2796 d->updateArrow(QStyle::State_Sunken);
2797 #ifdef QT_KEYPAD_NAVIGATION
2798 //if the container already exists, then d->viewContainer() is safe to call
2801 // We've restricted the next couple of lines, because by not calling
2802 // viewContainer(), we avoid creating the QComboBoxPrivateContainer.
2803 d->viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval());
2804 d->viewContainer()->initialClickPosition = mapToGlobal(e->pos());
2805 #ifdef QT_KEYPAD_NAVIGATION
2810 #ifdef QT_KEYPAD_NAVIGATION
2811 if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && d->lineEdit) {
2812 d->lineEdit->event(e); //so lineedit can move cursor, etc
2816 QWidget::mousePressEvent(e);
2823 void QComboBox::mouseReleaseEvent(QMouseEvent *e)
2827 d->updateArrow(QStyle::State_None);
2833 void QComboBox::keyPressEvent(QKeyEvent *e)
2837 #ifndef QT_NO_COMPLETER
2839 && d->lineEdit->completer()
2840 && d->lineEdit->completer()->popup()
2841 && d->lineEdit->completer()->popup()->isVisible()) {
2842 // provide same autocompletion support as line edit
2843 d->lineEdit->event(e);
2848 enum Move { NoMove=0 , MoveUp , MoveDown , MoveFirst , MoveLast};
2851 int newIndex = currentIndex();
2854 if (e->modifiers() & Qt::ControlModifier)
2855 break; // pass to line edit for auto completion
2856 case Qt::Key_PageUp:
2857 #ifdef QT_KEYPAD_NAVIGATION
2858 if (QApplication::keypadNavigationEnabled())
2865 if (e->modifiers() & Qt::AltModifier) {
2868 } else if (e->modifiers() & Qt::ControlModifier)
2869 break; // pass to line edit for auto completion
2871 case Qt::Key_PageDown:
2872 #ifdef QT_KEYPAD_NAVIGATION
2873 if (QApplication::keypadNavigationEnabled())
2888 if (!e->modifiers()) {
2899 case Qt::Key_Return:
2900 case Qt::Key_Escape:
2904 #ifdef QT_KEYPAD_NAVIGATION
2905 case Qt::Key_Select:
2906 if (QApplication::keypadNavigationEnabled()
2907 && (!hasEditFocus() || !d->lineEdit)) {
2914 if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
2918 if (QApplication::keypadNavigationEnabled()) {
2919 if (!hasEditFocus() || !d->lineEdit)
2922 e->ignore(); // let the surounding dialog have it
2928 if (!e->text().isEmpty())
2929 d->keyboardSearchString(e->text());
2935 if (move != NoMove) {
2942 while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2949 while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2957 if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2958 setCurrentIndex(newIndex);
2959 d->emitActivated(d->currentIndex);
2961 } else if (d->lineEdit) {
2962 d->lineEdit->event(e);
2970 void QComboBox::keyReleaseEvent(QKeyEvent *e)
2974 d->lineEdit->event(e);
2980 #ifndef QT_NO_WHEELEVENT
2981 void QComboBox::wheelEvent(QWheelEvent *e)
2984 if (!d->viewContainer()->isVisible()) {
2985 int newIndex = currentIndex();
2987 if (e->delta() > 0) {
2989 while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2993 while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2997 if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2998 setCurrentIndex(newIndex);
2999 d->emitActivated(d->currentIndex);
3006 #ifndef QT_NO_CONTEXTMENU
3010 void QComboBox::contextMenuEvent(QContextMenuEvent *e)
3014 Qt::ContextMenuPolicy p = d->lineEdit->contextMenuPolicy();
3015 d->lineEdit->setContextMenuPolicy(Qt::DefaultContextMenu);
3016 d->lineEdit->event(e);
3017 d->lineEdit->setContextMenuPolicy(p);
3020 #endif // QT_NO_CONTEXTMENU
3022 void QComboBoxPrivate::keyboardSearchString(const QString &text)
3024 // use keyboardSearch from the listView so we do not duplicate code
3025 QAbstractItemView *view = viewContainer()->itemView();
3026 view->setCurrentIndex(currentIndex);
3027 int currentRow = view->currentIndex().row();
3028 view->keyboardSearch(text);
3029 if (currentRow != view->currentIndex().row()) {
3030 setCurrentIndex(view->currentIndex());
3031 emitActivated(currentIndex);
3035 void QComboBoxPrivate::modelChanged()
3039 if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
3041 adjustComboBoxSize();
3042 q->updateGeometry();
3049 void QComboBox::inputMethodEvent(QInputMethodEvent *e)
3053 d->lineEdit->event(e);
3055 if (!e->commitString().isEmpty())
3056 d->keyboardSearchString(e->commitString());
3065 QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query) const
3067 Q_D(const QComboBox);
3069 return d->lineEdit->inputMethodQuery(query);
3070 return QWidget::inputMethodQuery(query);
3074 \fn void QComboBox::addItem(const QString &text, const QVariant &userData)
3076 Adds an item to the combobox with the given \a text, and
3077 containing the specified \a userData (stored in the Qt::UserRole).
3078 The item is appended to the list of existing items.
3082 \fn void QComboBox::addItem(const QIcon &icon, const QString &text,
3083 const QVariant &userData)
3085 Adds an item to the combobox with the given \a icon and \a text,
3086 and containing the specified \a userData (stored in the
3087 Qt::UserRole). The item is appended to the list of existing items.
3091 \fn void QComboBox::addItems(const QStringList &texts)
3093 Adds each of the strings in the given \a texts to the combobox. Each item
3094 is appended to the list of existing items in turn.
3098 \fn void QComboBox::editTextChanged(const QString &text)
3100 This signal is emitted when the text in the combobox's line edit
3101 widget is changed. The new text is specified by \a text.
3105 \property QComboBox::frame
3106 \brief whether the combo box draws itself with a frame
3109 If enabled (the default) the combo box draws itself inside a
3110 frame, otherwise the combo box draws itself without any frame.
3112 bool QComboBox::hasFrame() const
3114 Q_D(const QComboBox);
3119 void QComboBox::setFrame(bool enable)
3128 \property QComboBox::modelColumn
3129 \brief the column in the model that is visible.
3131 If set prior to populating the combo box, the pop-up view will
3132 not be affected and will show the first column (using this property's
3135 By default, this property has a value of 0.
3137 int QComboBox::modelColumn() const
3139 Q_D(const QComboBox);
3140 return d->modelColumn;
3143 void QComboBox::setModelColumn(int visibleColumn)
3146 d->modelColumn = visibleColumn;
3147 QListView *lv = qobject_cast<QListView *>(d->viewContainer()->itemView());
3149 lv->setModelColumn(visibleColumn);
3150 #ifndef QT_NO_COMPLETER
3151 if (d->lineEdit && d->lineEdit->completer()
3152 && d->lineEdit->completer() == d->completer)
3153 d->lineEdit->completer()->setCompletionColumn(visibleColumn);
3155 setCurrentIndex(currentIndex()); //update the text to the text of the new column;
3160 #include "moc_qcombobox.cpp"
3162 #endif // QT_NO_COMBOBOX