QComboBox: mention insert policy in context of editable property
[profile/ivi/qtbase.git] / src / widgets / widgets / qcombobox.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
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.
16 **
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.
24 **
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.
28 **
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.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qcombobox.h"
43
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>
53 #include <qmap.h>
54 #include <qmenu.h>
55 #include <qevent.h>
56 #include <qlayout.h>
57 #include <qscrollbar.h>
58 #include <qtreeview.h>
59 #include <qheaderview.h>
60 #include <qmath.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>
68 #include <qdebug.h>
69 #if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS) && !defined(QT_NO_STYLE_MAC)
70 #include <private/qcore_mac_p.h>
71 #include <QMacStyle>
72 #include <private/qt_cocoa_helpers_mac_p.h>
73 #endif
74 #ifndef QT_NO_EFFECTS
75 # include <private/qeffects_p.h>
76 #endif
77 #ifndef QT_NO_ACCESSIBILITY
78 #include "qaccessible.h"
79 #endif
80
81 QT_BEGIN_NAMESPACE
82
83 QComboBoxPrivate::QComboBoxPrivate()
84     : QWidgetPrivate(),
85       model(0),
86       lineEdit(0),
87       container(0),
88       insertPolicy(QComboBox::InsertAtBottom),
89       sizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow),
90       minimumContentsLength(0),
91       shownOnce(false),
92       autoCompletion(true),
93       duplicatesEnabled(false),
94       frame(true),
95       maxVisibleItems(10),
96       maxCount(INT_MAX),
97       modelColumn(0),
98       inserting(false),
99       arrowState(QStyle::State_None),
100       hoverControl(QStyle::SC_None),
101       autoCompletionCaseSensitivity(Qt::CaseInsensitive),
102       indexBeforeChange(-1)
103 #ifndef QT_NO_COMPLETER
104       , completer(0)
105 #endif
106 {
107 }
108
109 QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewItem &option,
110                                                         const QModelIndex &index) const
111 {
112     QStyleOptionMenuItem menuOption;
113
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));
120     }
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;
127     else
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;
135     else
136         menuOption.menuItemType = QStyleOptionMenuItem::Normal;
137
138     QVariant variant = index.model()->data(index, Qt::DecorationRole);
139     switch (variant.type()) {
140     case QVariant::Icon:
141         menuOption.icon = qvariant_cast<QIcon>(variant);
142         break;
143     case QVariant::Color: {
144         static QPixmap pixmap(option.decorationSize);
145         pixmap.fill(qvariant_cast<QColor>(variant));
146         menuOption.icon = pixmap;
147         break; }
148     default:
149         menuOption.icon = qvariant_cast<QPixmap>(variant);
150         break;
151     }
152     if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) {
153         menuOption.palette.setBrush(QPalette::All, QPalette::Background,
154                                     qvariant_cast<QBrush>(index.data(Qt::BackgroundRole)));
155     }
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;
162
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();
169     else
170         menuOption.font = qt_app_fonts_hash()->value("QComboMenuItem", mCombo->font());
171
172     menuOption.fontMetrics = QFontMetrics(menuOption.font);
173
174     return menuOption;
175 }
176
177 #ifdef QT_KEYPAD_NAVIGATION
178 void QComboBoxPrivate::_q_completerActivated()
179 {
180     Q_Q(QComboBox);
181     if ( QApplication::keypadNavigationEnabled()
182          && q->isEditable()
183          && q->completer()
184          && q->completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ) {
185         q->setEditFocus(false);
186     }
187 }
188 #endif
189
190 void QComboBoxPrivate::updateArrow(QStyle::StateFlag state)
191 {
192     Q_Q(QComboBox);
193     if (arrowState == state)
194         return;
195     arrowState = state;
196     QStyleOptionComboBox opt;
197     q->initStyleOption(&opt);
198     q->update(q->style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, q));
199 }
200
201 void QComboBoxPrivate::_q_modelReset()
202 {
203     Q_Q(QComboBox);
204     if (lineEdit) {
205         lineEdit->setText(QString());
206         updateLineEditGeometry();
207     }
208     if (currentIndex.row() != indexBeforeChange)
209         _q_emitCurrentIndexChanged(currentIndex);
210     q->update();
211 }
212
213 void QComboBoxPrivate::_q_modelDestroyed()
214 {
215     model = QAbstractItemModelPrivate::staticEmptyModel();
216 }
217
218
219 //Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
220 QRect QComboBoxPrivate::popupGeometry(int screen) const
221 {
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);
228 }
229
230 bool QComboBoxPrivate::updateHoverControl(const QPoint &pos)
231 {
232
233     Q_Q(QComboBox);
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);
240         return true;
241     }
242     return !doesHover;
243 }
244
245 QStyle::SubControl QComboBoxPrivate::newHoverControl(const QPoint &pos)
246 {
247     Q_Q(QComboBox);
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)
254                    : QRect();
255     return hoverControl;
256 }
257
258 /*
259     Computes a size hint based on the maximum width
260     for the items in the combobox.
261 */
262 int QComboBoxPrivate::computeWidthHint() const
263 {
264     Q_Q(const QComboBox);
265
266     int width = 0;
267     const int count = q->count();
268     const int iconWidth = q->iconSize().width() + 4;
269     const QFontMetrics &fontMetrics = q->fontMetrics();
270
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));
275         else
276             width = (qMax(width, textWidth + iconWidth));
277     }
278
279     QStyleOptionComboBox opt;
280     q->initStyleOption(&opt);
281     QSize tmp(width, 0);
282     tmp = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, tmp, q);
283     return tmp.width();
284 }
285
286 QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
287 {
288     Q_Q(const QComboBox);
289     if (!sh.isValid()) {
290         bool hasIcon = sizeAdjustPolicy == QComboBox::AdjustToMinimumContentsLengthWithIcon ? true : false;
291         int count = q->count();
292         QSize iconSize = q->iconSize();
293         const QFontMetrics &fm = q->fontMetrics();
294
295         // text width
296         if (&sh == &sizeHint || minimumContentsLength == 0) {
297             switch (sizeAdjustPolicy) {
298             case QComboBox::AdjustToContents:
299             case QComboBox::AdjustToContentsOnFirstShow:
300                 if (count == 0) {
301                     sh.rwidth() = 7 * fm.width(QLatin1Char('x'));
302                 } else {
303                     for (int i = 0; i < count; ++i) {
304                         if (!q->itemIcon(i).isNull()) {
305                             hasIcon = true;
306                             sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width() + iconSize.width() + 4));
307                         } else {
308                             sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width()));
309                         }
310                     }
311                 }
312                 break;
313             case QComboBox::AdjustToMinimumContentsLength:
314                 for (int i = 0; i < count && !hasIcon; ++i)
315                     hasIcon = !q->itemIcon(i).isNull();
316             default:
317                 ;
318             }
319         } else {
320             for (int i = 0; i < count && !hasIcon; ++i)
321                 hasIcon = !q->itemIcon(i).isNull();
322         }
323         if (minimumContentsLength > 0)
324             sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.width(QLatin1Char('X')) + (hasIcon ? iconSize.width() + 4 : 0)));
325
326
327         // height
328         sh.setHeight(qMax(qCeil(QFontMetricsF(fm).height()), 14) + 2);
329         if (hasIcon) {
330             sh.setHeight(qMax(sh.height(), iconSize.height() + 2));
331         }
332
333         // add style and strut values
334         QStyleOptionComboBox opt;
335         q->initStyleOption(&opt);
336         sh = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, q);
337     }
338     return sh.expandedTo(QApplication::globalStrut());
339 }
340
341 void QComboBoxPrivate::adjustComboBoxSize()
342 {
343     viewContainer()->adjustSizeTimer.start(20, container);
344 }
345
346 void QComboBoxPrivate::updateLayoutDirection()
347 {
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));
353     if (lineEdit)
354         lineEdit->setLayoutDirection(dir);
355     if (container)
356         container->setLayoutDirection(dir);
357 }
358
359
360 void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent)
361 {
362     if (timerEvent->timerId() == adjustSizeTimer.timerId()) {
363         adjustSizeTimer.stop();
364         if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) {
365             combo->updateGeometry();
366             combo->adjustSize();
367             combo->update();
368         }
369     }
370 }
371
372 void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e)
373 {
374     QStyleOptionComboBox opt = comboStyleOption();
375     if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) {
376         QStyleOption myOpt;
377         myOpt.initFrom(this);
378         QStyleHintReturnMask mask;
379         if (combo->style()->styleHint(QStyle::SH_Menu_Mask, &myOpt, this, &mask)) {
380             setMask(mask.region);
381         }
382     } else {
383         clearMask();
384     }
385     QFrame::resizeEvent(e);
386 }
387
388 void QComboBoxPrivateContainer::leaveEvent(QEvent *)
389 {
390 // On Mac using the Mac style we want to clear the selection
391 // when the mouse moves outside the popup.
392 #ifdef Q_WS_MAC
393     QStyleOptionComboBox opt = comboStyleOption();
394     if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo))
395           view->clearSelection();
396 #endif
397 }
398
399 QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent)
400     : QFrame(parent, Qt::Popup), combo(parent), view(0), top(0), bottom(0)
401 {
402     // we need the combobox and itemview
403     Q_ASSERT(parent);
404     Q_ASSERT(itemView);
405
406     setAttribute(Qt::WA_WindowPropagation);
407     setAttribute(Qt::WA_X11NetWmWindowTypeCombo);
408
409     // setup container
410     blockMouseReleaseTimer.setSingleShot(true);
411
412     // we need a vertical layout
413     QBoxLayout *layout =  new QBoxLayout(QBoxLayout::TopToBottom, this);
414     layout->setSpacing(0);
415     layout->setMargin(0);
416
417     // set item view
418     setItemView(itemView);
419
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);
423     if (usePopup) {
424         top = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepSub, this);
425         bottom = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepAdd, this);
426         top->hide();
427         bottom->hide();
428     } else {
429         setLineWidth(1);
430     }
431
432     setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
433
434     if (top) {
435         layout->insertWidget(0, top);
436         connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
437     }
438     if (bottom) {
439         layout->addWidget(bottom);
440         connect(bottom, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
441     }
442
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();
447 }
448
449 void QComboBoxPrivateContainer::scrollItemView(int action)
450 {
451 #ifndef QT_NO_SCROLLBAR
452     if (view->verticalScrollBar())
453         view->verticalScrollBar()->triggerAction(static_cast<QAbstractSlider::SliderAction>(action));
454 #endif
455 }
456
457 /*
458     Hides or shows the scrollers when we emulate a popupmenu
459 */
460 void QComboBoxPrivateContainer::updateScrollers()
461 {
462 #ifndef QT_NO_SCROLLBAR
463     if (!top || !bottom)
464         return;
465
466     if (isVisible() == false)
467         return;
468
469     QStyleOptionComboBox opt = comboStyleOption();
470     if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo) &&
471         view->verticalScrollBar()->minimum() < view->verticalScrollBar()->maximum()) {
472
473         bool needTop = view->verticalScrollBar()->value()
474                        > (view->verticalScrollBar()->minimum() + spacing());
475         bool needBottom = view->verticalScrollBar()->value()
476                           < (view->verticalScrollBar()->maximum() - spacing()*2);
477         if (needTop)
478             top->show();
479         else
480             top->hide();
481         if (needBottom)
482             bottom->show();
483         else
484             bottom->hide();
485     } else {
486         top->hide();
487         bottom->hide();
488     }
489 #endif // QT_NO_SCROLLBAR
490 }
491
492 /*
493     Cleans up when the view is destroyed.
494 */
495 void QComboBoxPrivateContainer::viewDestroyed()
496 {
497     view = 0;
498     setItemView(new QComboBoxListView());
499 }
500
501 /*
502     Returns the item view used for the combobox popup.
503 */
504 QAbstractItemView *QComboBoxPrivateContainer::itemView() const
505 {
506     return view;
507 }
508
509 /*!
510     Sets the item view to be used for the combobox popup.
511 */
512 void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
513 {
514     Q_ASSERT(itemView);
515
516     // clean up old one
517     if (view) {
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()));
525 #endif
526         disconnect(view, SIGNAL(destroyed()),
527                    this, SLOT(viewDestroyed()));
528
529         delete view;
530         view = 0;
531     }
532
533     // setup the item view
534     view = itemView;
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
545     if (usePopup)
546         view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
547 #endif
548     if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
549         usePopup) {
550         view->setMouseTracking(true);
551     }
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()));
561 #endif
562     connect(view, SIGNAL(destroyed()),
563             this, SLOT(viewDestroyed()));
564
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);
570 #endif
571 }
572
573 /*!
574     Returns the spacing between the items in the view.
575 */
576 int QComboBoxPrivateContainer::spacing() const
577 {
578     QListView *lview = qobject_cast<QListView*>(view);
579     if (lview)
580         return lview->spacing();
581 #ifndef QT_NO_TABLEVIEW
582     QTableView *tview = qobject_cast<QTableView*>(view);
583     if (tview)
584         return tview->showGrid() ? 1 : 0;
585 #endif
586     return 0;
587 }
588
589 void QComboBoxPrivateContainer::updateTopBottomMargin()
590 {
591     if (!layout() || layout()->count() < 1)
592         return;
593
594     QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout());
595     if (!boxLayout)
596         return;
597
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;
601
602     QSpacerItem *topSpacer = boxLayout->itemAt(0)->spacerItem();
603     if (topSpacer)
604         topSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
605
606     QSpacerItem *bottomSpacer = boxLayout->itemAt(boxLayout->count() - 1)->spacerItem();
607     if (bottomSpacer && bottomSpacer != topSpacer)
608         bottomSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
609
610     boxLayout->invalidate();
611 }
612
613 void QComboBoxPrivateContainer::changeEvent(QEvent *e)
614 {
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));
624 #endif
625     }
626
627     QWidget::changeEvent(e);
628 }
629
630
631 bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
632 {
633     switch (e->type()) {
634     case QEvent::ShortcutOverride:
635         switch (static_cast<QKeyEvent*>(e)->key()) {
636         case Qt::Key_Enter:
637         case Qt::Key_Return:
638 #ifdef QT_KEYPAD_NAVIGATION
639         case Qt::Key_Select:
640 #endif
641             if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
642                 combo->hidePopup();
643                 emit itemSelected(view->currentIndex());
644             }
645             return true;
646         case Qt::Key_Down:
647             if (!(static_cast<QKeyEvent*>(e)->modifiers() & Qt::AltModifier))
648                 break;
649             // fall through
650         case Qt::Key_F4:
651         case Qt::Key_Escape:
652             combo->hidePopup();
653             return true;
654         default:
655             break;
656         }
657     break;
658     case QEvent::MouseMove:
659         if (isVisible()) {
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);
669             }
670         }
671         break;
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)) {
678             combo->hidePopup();
679             emit itemSelected(view->currentIndex());
680             return true;
681         }
682         break;
683     }
684     default:
685         break;
686     }
687     return QFrame::eventFilter(o, e);
688 }
689
690 void QComboBoxPrivateContainer::showEvent(QShowEvent *)
691 {
692     combo->update();
693 }
694
695 void QComboBoxPrivateContainer::hideEvent(QHideEvent *)
696 {
697     emit resetButton();
698     combo->update();
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())
704         proxy->hide();
705 #endif
706 }
707
708 void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
709 {
710
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()),
716                                                            combo);
717     if ((combo->isEditable() && sc == QStyle::SC_ComboBoxArrow)
718         || (!combo->isEditable() && sc != QStyle::SC_None))
719         setAttribute(Qt::WA_NoMouseReplay);
720     combo->hidePopup();
721 }
722
723 void QComboBoxPrivateContainer::mouseReleaseEvent(QMouseEvent *e)
724 {
725     Q_UNUSED(e);
726     if (!blockMouseReleaseTimer.isActive()){
727         combo->hidePopup();
728         emit resetButton();
729     }
730 }
731
732 QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
733 {
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;
737     opt.initFrom(combo);
738     opt.subControls = QStyle::SC_All;
739     opt.activeSubControls = QStyle::SC_None;
740     opt.editable = combo->isEditable();
741     return opt;
742 }
743
744 /*!
745     \enum QComboBox::InsertPolicy
746
747     This enum specifies what the QComboBox should do when a new string is
748     entered by the user.
749
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.
757 */
758
759 /*!
760     \enum QComboBox::SizeAdjustPolicy
761
762     This enum specifies how the size hint of the QComboBox should
763     adjust when new content is added or content changes.
764
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.
769 */
770
771 /*!
772     \fn void QComboBox::activated(int index)
773
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().
778
779 */
780
781 /*!
782     \fn void QComboBox::activated(const QString &text)
783
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().
788
789 */
790
791 /*!
792     \fn void QComboBox::highlighted(int index)
793
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.
796 */
797
798 /*!
799     \fn void QComboBox::highlighted(const QString &text)
800
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.
803 */
804
805 /*!
806     \fn void QComboBox::currentIndexChanged(int index)
807     \since 4.1
808
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.
813 */
814
815 /*!
816     \fn void QComboBox::currentIndexChanged(const QString &text)
817     \since 4.1
818
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.
822 */
823
824 /*!
825     Constructs a combobox with the given \a parent, using the default
826     model QStandardItemModel.
827 */
828 QComboBox::QComboBox(QWidget *parent)
829     : QWidget(*new QComboBoxPrivate(), parent, 0)
830 {
831     Q_D(QComboBox);
832     d->init();
833 }
834
835 /*!
836   \internal
837 */
838 QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent)
839     : QWidget(dd, parent, 0)
840 {
841     Q_D(QComboBox);
842     d->init();
843 }
844
845
846 /*!
847     \class QComboBox
848     \brief The QComboBox widget is a combined button and popup list.
849
850     \ingroup basicwidgets
851     \inmodule QtWidgets
852
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.
855
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.
859
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
864     contents.
865
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.
877
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().
882
883     It is possible to constrain the input to an editable combobox
884     using QValidator; see setValidator(). By default, any input is
885     accepted.
886
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().
899
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()}.
912
913     \image qstyle-comboboxes.png Comboboxes in the different built-in styles.
914
915     \sa QLineEdit, QSpinBox, QRadioButton, QButtonGroup,
916         {fowler}{GUI Design Handbook: Combo Box, Drop-Down List Box}
917 */
918
919 void QComboBoxPrivate::init()
920 {
921     Q_Q(QComboBox);
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);
929     else
930         q->setAttribute(Qt::WA_InputMethodEnabled);
931 }
932
933 QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
934 {
935     if (container)
936         return container;
937
938     Q_Q(QComboBox);
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()));
951     return container;
952 }
953
954
955 void QComboBoxPrivate::_q_resetButton()
956 {
957     updateArrow(QStyle::State_None);
958 }
959
960 void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
961 {
962     Q_Q(QComboBox);
963     if (inserting || topLeft.parent() != root)
964         return;
965
966     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
967         sizeHint = QSize();
968         adjustComboBoxSize();
969         q->updateGeometry();
970     }
971
972     if (currentIndex.row() >= topLeft.row() && currentIndex.row() <= bottomRight.row()) {
973         if (lineEdit) {
974             lineEdit->setText(q->itemText(currentIndex.row()));
975             updateLineEditGeometry();
976         }
977         q->update();
978     }
979 #ifndef QT_NO_ACCESSIBILITY
980         QAccessibleEvent event(q, QAccessible::NameChanged);
981         QAccessible::updateAccessibility(&event);
982 #endif
983 }
984
985 void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end)
986 {
987     Q_Q(QComboBox);
988     if (inserting || parent != root)
989         return;
990
991     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
992         sizeHint = QSize();
993         adjustComboBoxSize();
994         q->updateGeometry();
995     }
996
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) {
1002         q->update();
1003         _q_emitCurrentIndexChanged(currentIndex);
1004     }
1005 }
1006
1007 void QComboBoxPrivate::_q_updateIndexBeforeChange()
1008 {
1009     indexBeforeChange = currentIndex.row();
1010 }
1011
1012 void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
1013 {
1014     Q_Q(QComboBox);
1015     if (parent != root)
1016         return;
1017
1018     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
1019         sizeHint = QSize();
1020         adjustComboBoxSize();
1021         q->updateGeometry();
1022     }
1023
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)));
1028             return;
1029         }
1030         if (lineEdit) {
1031             lineEdit->setText(q->itemText(currentIndex.row()));
1032             updateLineEditGeometry();
1033         }
1034         q->update();
1035         _q_emitCurrentIndexChanged(currentIndex);
1036     }
1037 }
1038
1039
1040 void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
1041 {
1042     if (!container)
1043         return;
1044     Q_Q(QComboBox);
1045     QStyleOptionComboBox opt;
1046     q->initStyleOption(&opt);
1047 #ifndef QT_NO_MENU
1048     if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1049         QMenu menu;
1050         menu.ensurePolished();
1051         container->setPalette(menu.palette());
1052         container->setWindowOpacity(menu.windowOpacity());
1053     } else
1054 #endif
1055     {
1056         container->setPalette(q->palette());
1057         container->setWindowOpacity(1.0);
1058     }
1059     if (lineEdit)
1060         lineEdit->setPalette(q->palette());
1061 }
1062
1063 /*!
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.
1067
1068     \sa QStyleOption::initFrom()
1069 */
1070 void QComboBox::initStyleOption(QStyleOptionComboBox *option) const
1071 {
1072     if (!option)
1073         return;
1074
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;
1085     } else {
1086         option->activeSubControls = d->hoverControl;
1087     }
1088     if (d->currentIndex.isValid()) {
1089         option->currentText = currentText();
1090         option->currentIcon = d->itemIcon(d->currentIndex);
1091     }
1092     option->iconSize = iconSize();
1093     if (d->container && d->container->isVisible())
1094         option->state |= QStyle::State_On;
1095 }
1096
1097 void QComboBoxPrivate::updateLineEditGeometry()
1098 {
1099     if (!lineEdit)
1100         return;
1101
1102     Q_Q(QComboBox);
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);
1112     }
1113     lineEdit->setGeometry(editRect);
1114 }
1115
1116 Qt::MatchFlags QComboBoxPrivate::matchFlags() const
1117 {
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)
1122 #endif
1123         flags |= Qt::MatchCaseSensitive;
1124     return flags;
1125 }
1126
1127
1128 void QComboBoxPrivate::_q_editingFinished()
1129 {
1130     Q_Q(QComboBox);
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);
1137         }
1138     }
1139
1140 }
1141
1142 void QComboBoxPrivate::_q_returnPressed()
1143 {
1144     Q_Q(QComboBox);
1145     if (lineEdit && !lineEdit->text().isEmpty()) {
1146         if (q->count() >= maxCount && !(this->insertPolicy == QComboBox::InsertAtCurrent))
1147             return;
1148         lineEdit->deselect();
1149         lineEdit->end(false);
1150         QString text = lineEdit->text();
1151         // check for duplicates (if not enabled) and quit
1152         int index = -1;
1153         if (!duplicatesEnabled) {
1154             index = q->findText(text, matchFlags());
1155             if (index != -1) {
1156                 q->setCurrentIndex(index);
1157                 emitActivated(currentIndex);
1158                 return;
1159             }
1160         }
1161         switch (insertPolicy) {
1162         case QComboBox::InsertAtTop:
1163             index = 0;
1164             break;
1165         case QComboBox::InsertAtBottom:
1166             index = q->count();
1167             break;
1168         case QComboBox::InsertAtCurrent:
1169         case QComboBox::InsertAfterCurrent:
1170         case QComboBox::InsertBeforeCurrent:
1171             if (!q->count() || !currentIndex.isValid())
1172                 index = 0;
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();
1179             break;
1180         case QComboBox::InsertAlphabetically:
1181             index = 0;
1182             for (int i=0; i< q->count(); i++, index++ ) {
1183                 if (text.toLower() < q->itemText(i).toLower())
1184                     break;
1185             }
1186             break;
1187         case QComboBox::NoInsert:
1188         default:
1189             break;
1190         }
1191         if (index >= 0) {
1192             q->insertItem(index, text);
1193             q->setCurrentIndex(index);
1194             emitActivated(currentIndex);
1195         }
1196     }
1197 }
1198
1199 void QComboBoxPrivate::_q_itemSelected(const QModelIndex &item)
1200 {
1201     Q_Q(QComboBox);
1202     if (item != currentIndex) {
1203         setCurrentIndex(item);
1204     } else if (lineEdit) {
1205         lineEdit->selectAll();
1206         lineEdit->setText(q->itemText(currentIndex.row()));
1207     }
1208     emitActivated(currentIndex);
1209 }
1210
1211 void QComboBoxPrivate::emitActivated(const QModelIndex &index)
1212 {
1213     Q_Q(QComboBox);
1214     if (!index.isValid())
1215         return;
1216     QString text(itemText(index));
1217     emit q->activated(index.row());
1218     emit q->activated(text);
1219 }
1220
1221 void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
1222 {
1223     Q_Q(QComboBox);
1224     if (!index.isValid())
1225         return;
1226     QString text(itemText(index));
1227     emit q->highlighted(index.row());
1228     emit q->highlighted(text);
1229 }
1230
1231 void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
1232 {
1233     Q_Q(QComboBox);
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);
1239 #endif
1240 }
1241
1242 QString QComboBoxPrivate::itemText(const QModelIndex &index) const
1243 {
1244     return index.isValid() ? model->data(index, itemRole()).toString() : QString();
1245 }
1246
1247 int QComboBoxPrivate::itemRole() const
1248 {
1249     return q_func()->isEditable() ? Qt::EditRole : Qt::DisplayRole;
1250 }
1251
1252 /*!
1253     Destroys the combobox.
1254 */
1255 QComboBox::~QComboBox()
1256 {
1257     // ### check delegateparent and delete delegate if us?
1258     Q_D(QComboBox);
1259
1260     QT_TRY {
1261         disconnect(d->model, SIGNAL(destroyed()),
1262                 this, SLOT(_q_modelDestroyed()));
1263     } QT_CATCH(...) {
1264         ; // objects can't throw in destructor
1265     }
1266 }
1267
1268 /*!
1269     \property QComboBox::maxVisibleItems
1270     \brief the maximum allowed size on screen of the combo box, measured in items
1271
1272     By default, this property has a value of 10.
1273
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.
1276 */
1277 int QComboBox::maxVisibleItems() const
1278 {
1279     Q_D(const QComboBox);
1280     return d->maxVisibleItems;
1281 }
1282
1283 void QComboBox::setMaxVisibleItems(int maxItems)
1284 {
1285     Q_D(QComboBox);
1286     if (maxItems < 0) {
1287         qWarning("QComboBox::setMaxVisibleItems: "
1288                  "Invalid max visible items (%d) must be >= 0", maxItems);
1289         return;
1290     }
1291     d->maxVisibleItems = maxItems;
1292 }
1293
1294 /*!
1295     \property QComboBox::count
1296     \brief the number of items in the combobox
1297
1298     By default, for an empty combo box, this property has a value of 0.
1299 */
1300 int QComboBox::count() const
1301 {
1302     Q_D(const QComboBox);
1303     return d->model->rowCount(d->root);
1304 }
1305
1306 /*!
1307     \property QComboBox::maxCount
1308     \brief the maximum number of items allowed in the combobox
1309
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
1313     the combobox.
1314
1315     By default, this property's value is derived from the highest
1316     signed integer available (typically 2147483647).
1317 */
1318 void QComboBox::setMaxCount(int max)
1319 {
1320     Q_D(QComboBox);
1321     if (max < 0) {
1322         qWarning("QComboBox::setMaxCount: Invalid count (%d) must be >= 0", max);
1323         return;
1324     }
1325
1326     if (max < count())
1327         d->model->removeRows(max, count() - max, d->root);
1328
1329     d->maxCount = max;
1330 }
1331
1332 int QComboBox::maxCount() const
1333 {
1334     Q_D(const QComboBox);
1335     return d->maxCount;
1336 }
1337
1338 #ifndef QT_NO_COMPLETER
1339
1340 /*!
1341     \property QComboBox::autoCompletion
1342     \brief whether the combobox provides auto-completion for editable items
1343     \since 4.1
1344     \obsolete
1345
1346     Use setCompleter() instead.
1347
1348     By default, this property is true.
1349
1350     \sa editable
1351 */
1352
1353 /*!
1354     \obsolete
1355
1356     Use setCompleter() instead.
1357 */
1358 bool QComboBox::autoCompletion() const
1359 {
1360     Q_D(const QComboBox);
1361     return d->autoCompletion;
1362 }
1363
1364 /*!
1365     \obsolete
1366
1367     Use setCompleter() instead.
1368 */
1369 void QComboBox::setAutoCompletion(bool enable)
1370 {
1371     Q_D(QComboBox);
1372
1373 #ifdef QT_KEYPAD_NAVIGATION
1374     if (QApplication::keypadNavigationEnabled() && !enable && isEditable())
1375         qWarning("QComboBox::setAutoCompletion: auto completion is mandatory when combo box editable");
1376 #endif
1377
1378     d->autoCompletion = enable;
1379     if (!d->lineEdit)
1380         return;
1381     if (enable) {
1382         if (d->lineEdit->completer())
1383             return;
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);
1390     } else {
1391         d->lineEdit->setCompleter(0);
1392     }
1393 }
1394
1395 /*!
1396     \property QComboBox::autoCompletionCaseSensitivity
1397     \brief whether string comparisons are case-sensitive or case-insensitive for auto-completion
1398     \obsolete
1399
1400     By default, this property is Qt::CaseInsensitive.
1401
1402     Use setCompleter() instead. Case sensitivity of the auto completion can be
1403     changed using QCompleter::setCaseSensitivity().
1404
1405     \sa autoCompletion
1406 */
1407
1408 /*!
1409     \obsolete
1410
1411     Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1412 */
1413 Qt::CaseSensitivity QComboBox::autoCompletionCaseSensitivity() const
1414 {
1415     Q_D(const QComboBox);
1416     return d->autoCompletionCaseSensitivity;
1417 }
1418
1419 /*!
1420     \obsolete
1421
1422     Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1423 */
1424 void QComboBox::setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity)
1425 {
1426     Q_D(QComboBox);
1427     d->autoCompletionCaseSensitivity = sensitivity;
1428     if (d->lineEdit && d->lineEdit->completer())
1429         d->lineEdit->completer()->setCaseSensitivity(sensitivity);
1430 }
1431
1432 #endif // QT_NO_COMPLETER
1433
1434 /*!
1435     \property QComboBox::duplicatesEnabled
1436     \brief whether the user can enter duplicate items into the combobox
1437
1438     Note that it is always possible to programmatically insert duplicate items into the
1439     combobox.
1440
1441     By default, this property is false (duplicates are not allowed).
1442 */
1443 bool QComboBox::duplicatesEnabled() const
1444 {
1445     Q_D(const QComboBox);
1446     return d->duplicatesEnabled;
1447 }
1448
1449 void QComboBox::setDuplicatesEnabled(bool enable)
1450 {
1451     Q_D(QComboBox);
1452     d->duplicatesEnabled = enable;
1453 }
1454
1455 /*!  \fn int QComboBox::findText(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const
1456
1457   Returns the index of the item containing the given \a text; otherwise
1458   returns -1.
1459
1460   The \a flags specify how the items in the combobox are searched.
1461 */
1462
1463 /*!
1464   Returns the index of the item containing the given \a data for the
1465   given \a role; otherwise returns -1.
1466
1467   The \a flags specify how the items in the combobox are searched.
1468 */
1469 int QComboBox::findData(const QVariant &data, int role, Qt::MatchFlags flags) const
1470 {
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())
1476         return -1;
1477     return result.first().row();
1478 }
1479
1480 /*!
1481     \property QComboBox::insertPolicy
1482     \brief the policy used to determine where user-inserted items should
1483     appear in the combobox
1484
1485     The default value is \l InsertAtBottom, indicating that new items will appear
1486     at the bottom of the list of items.
1487
1488     \sa InsertPolicy
1489 */
1490
1491 QComboBox::InsertPolicy QComboBox::insertPolicy() const
1492 {
1493     Q_D(const QComboBox);
1494     return d->insertPolicy;
1495 }
1496
1497 void QComboBox::setInsertPolicy(InsertPolicy policy)
1498 {
1499     Q_D(QComboBox);
1500     d->insertPolicy = policy;
1501 }
1502
1503 /*!
1504     \property QComboBox::sizeAdjustPolicy
1505     \brief the policy describing how the size of the combobox changes
1506     when the content changes
1507
1508     The default value is \l AdjustToContentsOnFirstShow.
1509
1510     \sa SizeAdjustPolicy
1511 */
1512
1513 QComboBox::SizeAdjustPolicy QComboBox::sizeAdjustPolicy() const
1514 {
1515     Q_D(const QComboBox);
1516     return d->sizeAdjustPolicy;
1517 }
1518
1519 void QComboBox::setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy policy)
1520 {
1521     Q_D(QComboBox);
1522     if (policy == d->sizeAdjustPolicy)
1523         return;
1524
1525     d->sizeAdjustPolicy = policy;
1526     d->sizeHint = QSize();
1527     d->adjustComboBoxSize();
1528     updateGeometry();
1529 }
1530
1531 /*!
1532     \property QComboBox::minimumContentsLength
1533     \brief the minimum number of characters that should fit into the combobox.
1534
1535     The default value is 0.
1536
1537     If this property is set to a positive value, the
1538     minimumSizeHint() and sizeHint() take it into account.
1539
1540     \sa sizeAdjustPolicy
1541 */
1542 int QComboBox::minimumContentsLength() const
1543 {
1544     Q_D(const QComboBox);
1545     return d->minimumContentsLength;
1546 }
1547
1548 void QComboBox::setMinimumContentsLength(int characters)
1549 {
1550     Q_D(QComboBox);
1551     if (characters == d->minimumContentsLength || characters < 0)
1552         return;
1553
1554     d->minimumContentsLength = characters;
1555
1556     if (d->sizeAdjustPolicy == AdjustToContents
1557             || d->sizeAdjustPolicy == AdjustToMinimumContentsLength
1558             || d->sizeAdjustPolicy == AdjustToMinimumContentsLengthWithIcon) {
1559         d->sizeHint = QSize();
1560         d->adjustComboBoxSize();
1561         updateGeometry();
1562     }
1563 }
1564
1565 /*!
1566     \property QComboBox::iconSize
1567     \brief the size of the icons shown in the combobox.
1568
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.
1572 */
1573
1574 QSize QComboBox::iconSize() const
1575 {
1576     Q_D(const QComboBox);
1577     if (d->iconSize.isValid())
1578         return d->iconSize;
1579
1580     int iconWidth = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
1581     return QSize(iconWidth, iconWidth);
1582 }
1583
1584 void QComboBox::setIconSize(const QSize &size)
1585 {
1586     Q_D(QComboBox);
1587     if (size == d->iconSize)
1588         return;
1589
1590     view()->setIconSize(size);
1591     d->iconSize = size;
1592     d->sizeHint = QSize();
1593     updateGeometry();
1594 }
1595
1596 /*!
1597     \property QComboBox::editable
1598     \brief whether the combo box can be edited by the user
1599
1600     By default, this property is false. The effect of editing depends
1601     on the insert policy.
1602
1603     \sa InsertPolicy
1604 */
1605 bool QComboBox::isEditable() const
1606 {
1607     Q_D(const QComboBox);
1608     return d->lineEdit != 0;
1609 }
1610
1611 /*! \internal
1612     update the default delegate
1613     depending on the style's SH_ComboBox_Popup hint, we use a different default delegate.
1614
1615     but we do not change the delegate is the combobox use a custom delegate,
1616     unless \a force is set to true.
1617  */
1618 void QComboBoxPrivate::updateDelegate(bool force)
1619 {
1620     Q_Q(QComboBox);
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));
1626     } else {
1627         if (force || qobject_cast<QComboMenuDelegate *>(q->itemDelegate()))
1628             q->setItemDelegate(new QComboBoxDelegate(q->view(), q));
1629     }
1630 }
1631
1632 QIcon QComboBoxPrivate::itemIcon(const QModelIndex &index) const
1633 {
1634     QVariant decoration = model->data(index, Qt::DecorationRole);
1635     if (decoration.type() == QVariant::Pixmap)
1636         return QIcon(qvariant_cast<QPixmap>(decoration));
1637     else
1638         return qvariant_cast<QIcon>(decoration);
1639 }
1640
1641 void QComboBox::setEditable(bool editable)
1642 {
1643     Q_D(QComboBox);
1644     if (isEditable() == editable)
1645         return;
1646
1647     d->updateDelegate();
1648
1649     QStyleOptionComboBox opt;
1650     initStyleOption(&opt);
1651     if (editable) {
1652         if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1653             d->viewContainer()->updateScrollers();
1654             view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
1655         }
1656         QLineEdit *le = new QLineEdit(this);
1657         setLineEdit(le);
1658     } else {
1659         if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1660             d->viewContainer()->updateScrollers();
1661             view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1662         }
1663         setAttribute(Qt::WA_InputMethodEnabled, false);
1664         d->lineEdit->hide();
1665         d->lineEdit->deleteLater();
1666         d->lineEdit = 0;
1667     }
1668
1669     d->viewContainer()->updateTopBottomMargin();
1670     if (!testAttribute(Qt::WA_Resized))
1671         adjustSize();
1672 }
1673
1674 /*!
1675     Sets the line \a edit to use instead of the current line edit widget.
1676
1677     The combo box takes ownership of the line edit.
1678 */
1679 void QComboBox::setLineEdit(QLineEdit *edit)
1680 {
1681     Q_D(QComboBox);
1682     if (!edit) {
1683         qWarning("QComboBox::setLineEdit: cannot set a 0 line edit");
1684         return;
1685     }
1686
1687     if (edit == d->lineEdit)
1688         return;
1689
1690     edit->setText(currentText());
1691     delete d->lineEdit;
1692
1693     d->lineEdit = edit;
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);
1705 #endif
1706
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);
1714         if (d->completer) {
1715             d->completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
1716             connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated()));
1717         }
1718     }
1719 #endif
1720 #endif
1721
1722     setAttribute(Qt::WA_InputMethodEnabled);
1723     d->updateLayoutDirection();
1724     d->updateLineEditGeometry();
1725     if (isVisible())
1726         d->lineEdit->show();
1727
1728     update();
1729 }
1730
1731 /*!
1732     Returns the line edit used to edit items in the combobox, or 0 if there
1733     is no line edit.
1734
1735     Only editable combo boxes have a line edit.
1736 */
1737 QLineEdit *QComboBox::lineEdit() const
1738 {
1739     Q_D(const QComboBox);
1740     return d->lineEdit;
1741 }
1742
1743 #ifndef QT_NO_VALIDATOR
1744 /*!
1745     \fn void QComboBox::setValidator(const QValidator *validator)
1746
1747     Sets the \a validator to use instead of the current validator.
1748 */
1749
1750 void QComboBox::setValidator(const QValidator *v)
1751 {
1752     Q_D(QComboBox);
1753     if (d->lineEdit)
1754         d->lineEdit->setValidator(v);
1755 }
1756
1757 /*!
1758     Returns the validator that is used to constrain text input for the
1759     combobox.
1760
1761     \sa editable
1762 */
1763 const QValidator *QComboBox::validator() const
1764 {
1765     Q_D(const QComboBox);
1766     return d->lineEdit ? d->lineEdit->validator() : 0;
1767 }
1768 #endif // QT_NO_VALIDATOR
1769
1770 #ifndef QT_NO_COMPLETER
1771
1772 /*!
1773     \fn void QComboBox::setCompleter(QCompleter *completer)
1774     \since 4.2
1775
1776     Sets the \a completer to use instead of the current completer.
1777     If \a completer is 0, auto completion is disabled.
1778
1779     By default, for an editable combo box, a QCompleter that
1780     performs case insensitive inline completion is automatically created.
1781 */
1782 void QComboBox::setCompleter(QCompleter *c)
1783 {
1784     Q_D(QComboBox);
1785     if (!d->lineEdit)
1786         return;
1787     d->lineEdit->setCompleter(c);
1788     if (c)
1789         c->setWidget(this);
1790 }
1791
1792 /*!
1793     \since 4.2
1794
1795     Returns the completer that is used to auto complete text input for the
1796     combobox.
1797
1798     \sa editable
1799 */
1800 QCompleter *QComboBox::completer() const
1801 {
1802     Q_D(const QComboBox);
1803     return d->lineEdit ? d->lineEdit->completer() : 0;
1804 }
1805
1806 #endif // QT_NO_COMPLETER
1807
1808 /*!
1809     Returns the item delegate used by the popup list view.
1810
1811     \sa setItemDelegate()
1812 */
1813 QAbstractItemDelegate *QComboBox::itemDelegate() const
1814 {
1815     return view()->itemDelegate();
1816 }
1817
1818 /*!
1819     Sets the item \a delegate for the popup list view.
1820     The combobox takes ownership of the delegate.
1821
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.
1827
1828     \sa itemDelegate()
1829 */
1830 void QComboBox::setItemDelegate(QAbstractItemDelegate *delegate)
1831 {
1832     if (!delegate) {
1833         qWarning("QComboBox::setItemDelegate: cannot set a 0 delegate");
1834         return;
1835     }
1836     delete view()->itemDelegate();
1837     view()->setItemDelegate(delegate);
1838 }
1839
1840 /*!
1841     Returns the model used by the combobox.
1842 */
1843
1844 QAbstractItemModel *QComboBox::model() const
1845 {
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));
1850     }
1851     return d->model;
1852 }
1853
1854 /*!
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().
1857
1858     \sa clear()
1859 */
1860 void QComboBox::setModel(QAbstractItemModel *model)
1861 {
1862     Q_D(QComboBox);
1863
1864     if (!model) {
1865         qWarning("QComboBox::setModel: cannot set a 0 model");
1866         return;
1867     }
1868
1869 #ifndef QT_NO_COMPLETER
1870     if (d->lineEdit && d->lineEdit->completer()
1871         && d->lineEdit->completer() == d->completer)
1872         d->lineEdit->completer()->setModel(model);
1873 #endif
1874     if (d->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)
1892             delete d->model;
1893     }
1894
1895     d->model = model;
1896
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()));
1913
1914     if (d->container) {
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);
1919     }
1920
1921     bool currentReset = false;
1922
1923     if (count()) {
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;
1928                 break;
1929             }
1930         }
1931     }
1932
1933     if (!currentReset)
1934         setCurrentIndex(-1);
1935
1936     d->modelChanged();
1937 }
1938
1939 /*!
1940     Returns the root model item index for the items in the combobox.
1941
1942     \sa setRootModelIndex()
1943 */
1944
1945 QModelIndex QComboBox::rootModelIndex() const
1946 {
1947     Q_D(const QComboBox);
1948     return QModelIndex(d->root);
1949 }
1950
1951 /*!
1952     Sets the root model item \a index for the items in the combobox.
1953
1954     \sa rootModelIndex()
1955 */
1956 void QComboBox::setRootModelIndex(const QModelIndex &index)
1957 {
1958     Q_D(QComboBox);
1959     d->root = QPersistentModelIndex(index);
1960     view()->setRootIndex(index);
1961     update();
1962 }
1963
1964 /*!
1965     \property QComboBox::currentIndex
1966     \brief the index of the current item in the combobox.
1967
1968     The current index can change when inserting or removing items.
1969
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.
1972 */
1973 int QComboBox::currentIndex() const
1974 {
1975     Q_D(const QComboBox);
1976     return d->currentIndex.row();
1977 }
1978
1979 void QComboBox::setCurrentIndex(int index)
1980 {
1981     Q_D(QComboBox);
1982     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
1983     d->setCurrentIndex(mi);
1984 }
1985
1986 void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
1987 {
1988     Q_Q(QComboBox);
1989
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.
1995
1996     bool indexChanged = (normalized != currentIndex);
1997     if (indexChanged)
1998         currentIndex = QPersistentModelIndex(normalized);
1999     if (lineEdit) {
2000         QString newText = q->itemText(normalized.row());
2001         if (lineEdit->text() != newText)
2002             lineEdit->setText(newText);
2003         updateLineEditGeometry();
2004     }
2005     if (indexChanged) {
2006         q->update();
2007         _q_emitCurrentIndexChanged(currentIndex);
2008     }
2009 }
2010
2011 /*!
2012     \property QComboBox::currentText
2013     \brief the current text
2014
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.
2018
2019     \sa editable
2020 */
2021 QString QComboBox::currentText() const
2022 {
2023     Q_D(const QComboBox);
2024     if (d->lineEdit)
2025         return d->lineEdit->text();
2026     else if (d->currentIndex.isValid())
2027         return d->itemText(d->currentIndex);
2028     else
2029         return QString();
2030 }
2031
2032 /*!
2033     Returns the text for the given \a index in the combobox.
2034 */
2035 QString QComboBox::itemText(int index) const
2036 {
2037     Q_D(const QComboBox);
2038     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2039     return d->itemText(mi);
2040 }
2041
2042 /*!
2043     Returns the icon for the given \a index in the combobox.
2044 */
2045 QIcon QComboBox::itemIcon(int index) const
2046 {
2047     Q_D(const QComboBox);
2048     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2049     return d->itemIcon(mi);
2050 }
2051
2052 /*!
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.
2055 */
2056 QVariant QComboBox::itemData(int index, int role) const
2057 {
2058     Q_D(const QComboBox);
2059     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2060     return d->model->data(mi, role);
2061 }
2062
2063 /*!
2064   \fn void QComboBox::insertItem(int index, const QString &text, const QVariant &userData)
2065
2066     Inserts the \a text and \a userData (stored in the Qt::UserRole)
2067     into the combobox at the given \a index.
2068
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
2072     of existing items.
2073
2074   \sa insertItems()
2075 */
2076
2077 /*!
2078
2079     Inserts the \a icon, \a text and \a userData (stored in the
2080     Qt::UserRole) into the combobox at the given \a index.
2081
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
2085     of existing items.
2086
2087     \sa insertItems()
2088 */
2089 void QComboBox::insertItem(int index, const QIcon &icon, const QString &text, const QVariant &userData)
2090 {
2091     Q_D(QComboBox);
2092     int itemCount = count();
2093     index = qBound(0, index, itemCount);
2094     if (index >= d->maxCount)
2095         return;
2096
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);
2104         ++itemCount;
2105     } else {
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);
2111             } else {
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);
2117             }
2118             d->inserting = false;
2119             d->_q_rowsInserted(d->root, index, index);
2120             ++itemCount;
2121         } else {
2122             d->inserting = false;
2123         }
2124     }
2125
2126     if (itemCount > d->maxCount)
2127         d->model->removeRows(itemCount - 1, itemCount - d->maxCount, d->root);
2128 }
2129
2130 /*!
2131     Inserts the strings from the \a list into the combobox as separate items,
2132     starting at the \a index specified.
2133
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.
2137
2138     \sa insertItem()
2139     */
2140 void QComboBox::insertItems(int index, const QStringList &list)
2141 {
2142     Q_D(QComboBox);
2143     if (list.isEmpty())
2144         return;
2145     index = qBound(0, index, count());
2146     int insertCount = qMin(d->maxCount - index, list.count());
2147     if (insertCount <= 0)
2148         return;
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);
2157     } else {
2158         d->inserting = true;
2159         if (d->model->insertRows(index, insertCount, d->root)) {
2160             QModelIndex item;
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);
2164             }
2165             d->inserting = false;
2166             d->_q_rowsInserted(d->root, index, index + insertCount - 1);
2167         } else {
2168             d->inserting = false;
2169         }
2170     }
2171
2172     int mc = count();
2173     if (mc > d->maxCount)
2174         d->model->removeRows(d->maxCount, mc - d->maxCount, d->root);
2175 }
2176
2177 /*!
2178     \since 4.4
2179
2180     Inserts a separator item into the combobox at the given \a index.
2181
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.
2185
2186     \sa insertItem()
2187 */
2188 void QComboBox::insertSeparator(int index)
2189 {
2190     Q_D(QComboBox);
2191     int itemCount = count();
2192     index = qBound(0, index, itemCount);
2193     if (index >= d->maxCount)
2194         return;
2195     insertItem(index, QIcon(), QString());
2196     QComboBoxDelegate::setSeparator(d->model, d->model->index(index, 0, d->root));
2197 }
2198
2199 /*!
2200     Removes the item at the given \a index from the combobox.
2201     This will update the current index if the index is removed.
2202
2203     This function does nothing if \a index is out of range.
2204 */
2205 void QComboBox::removeItem(int index)
2206 {
2207     Q_D(QComboBox);
2208     if (index < 0 || index >= count())
2209         return;
2210     d->model->removeRows(index, 1, d->root);
2211 }
2212
2213 /*!
2214     Sets the \a text for the item on the given \a index in the combobox.
2215 */
2216 void QComboBox::setItemText(int index, const QString &text)
2217 {
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);
2222     }
2223 }
2224
2225 /*!
2226     Sets the \a icon for the item on the given \a index in the combobox.
2227 */
2228 void QComboBox::setItemIcon(int index, const QIcon &icon)
2229 {
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);
2234     }
2235 }
2236
2237 /*!
2238     Sets the data \a role for the item on the given \a index in the combobox
2239     to the specified \a value.
2240 */
2241 void QComboBox::setItemData(int index, const QVariant &value, int role)
2242 {
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);
2247     }
2248 }
2249
2250 /*!
2251     Returns the list view used for the combobox popup.
2252 */
2253 QAbstractItemView *QComboBox::view() const
2254 {
2255     Q_D(const QComboBox);
2256     return const_cast<QComboBoxPrivate*>(d)->viewContainer()->itemView();
2257 }
2258
2259 /*!
2260   Sets the view to be used in the combobox popup to the given \a
2261   itemView. The combobox takes ownership of the view.
2262
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
2266   function.
2267 */
2268 void QComboBox::setView(QAbstractItemView *itemView)
2269 {
2270     Q_D(QComboBox);
2271     if (!itemView) {
2272         qWarning("QComboBox::setView: cannot set a 0 view");
2273         return;
2274     }
2275
2276     if (itemView->model() != d->model)
2277         itemView->setModel(d->model);
2278     d->viewContainer()->setItemView(itemView);
2279 }
2280
2281 /*!
2282     \reimp
2283 */
2284 QSize QComboBox::minimumSizeHint() const
2285 {
2286     Q_D(const QComboBox);
2287     return d->recomputeSizeHint(d->minimumSizeHint);
2288 }
2289
2290 /*!
2291     \reimp
2292
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.
2296 */
2297 QSize QComboBox::sizeHint() const
2298 {
2299     Q_D(const QComboBox);
2300     return d->recomputeSizeHint(d->sizeHint);
2301 }
2302
2303 /*!
2304     Displays the list of items in the combobox. If the list is empty
2305     then the no items will be shown.
2306
2307     If you reimplement this function to show a custom pop-up, make
2308     sure you call hidePopup() to reset the internal state.
2309
2310     \sa hidePopup()
2311 */
2312 void QComboBox::showPopup()
2313 {
2314     Q_D(QComboBox);
2315     if (count() <= 0)
2316         return;
2317
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
2322         setEditFocus(true);
2323         d->completer->complete(); // show popup
2324         return;
2325     }
2326 #endif
2327 #endif
2328
2329     QStyle * const style = this->style();
2330
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));
2340
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);
2346
2347     const bool usePopup = style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this);
2348     {
2349         int listHeight = 0;
2350         int count = 0;
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();
2357 #endif
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);
2362                 if (!idx.isValid())
2363                     continue;
2364                 listHeight += view()->visualRect(idx).height() + container->spacing();
2365 #ifndef QT_NO_TREEVIEW
2366                 if (d->model->hasChildren(idx) && treeView && treeView->isExpanded(idx))
2367                     toCheck.push(idx);
2368 #endif
2369                 ++count;
2370                 if (!usePopup && count >= d->maxVisibleItems) {
2371                     toCheck.clear();
2372                     break;
2373                 }
2374             }
2375         }
2376         listRect.setHeight(listHeight);
2377     }
2378
2379     {
2380         // add the spacing for the grid on the top and the bottom;
2381         int heightMargin = 2*container->spacing();
2382
2383         // add the frame of the container
2384         int marginTop, marginBottom;
2385         container->getContentsMargins(0, &marginTop, 0, &marginBottom);
2386         heightMargin += marginTop + marginBottom;
2387
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;
2393
2394         listRect.setHeight(listRect.height() + heightMargin);
2395     }
2396
2397     // Add space for margin at top and bottom if the style wants it.
2398     if (usePopup)
2399         listRect.setHeight(listRect.height() + style->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) * 2);
2400
2401     // Make sure the popup is wide enough to display its contents.
2402     if (usePopup) {
2403         const int diff = d->computeWidthHint() - width();
2404         if (diff > 0)
2405             listRect.setWidth(listRect.width() + diff);
2406     }
2407
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()));
2413
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());
2421         }
2422         if (mapToGlobal(listRect.topLeft()).x() < screen.x() ) {
2423             below.setX(screen.x());
2424             above.setX(screen.x());
2425         }
2426     }
2427
2428     if (usePopup) {
2429         // Position horizontally.
2430         listRect.moveLeft(above.x());
2431
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());
2437
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);
2443
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());
2449         }
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);
2457     } else {
2458         listRect.setHeight(aboveHeight);
2459         listRect.moveBottomLeft(above);
2460     }
2461
2462     if (qApp) {
2463         qApp->inputMethod()->reset();
2464     }
2465
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());
2472     }
2473     container->setGeometry(listRect);
2474
2475 #ifndef Q_OS_MAC
2476     const bool updatesEnabled = container->updatesEnabled();
2477 #endif
2478
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);
2484 #endif
2485
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
2490 // background.
2491 #ifndef Q_OS_MAC
2492     container->setUpdatesEnabled(false);
2493 #endif
2494
2495     container->raise();
2496     container->show();
2497     container->updateScrollers();
2498     view()->setFocus();
2499
2500     view()->scrollTo(view()->currentIndex(),
2501                      style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)
2502                              ? QAbstractItemView::PositionAtCenter
2503                              : QAbstractItemView::EnsureVisible);
2504
2505 #ifndef Q_OS_MAC
2506     container->setUpdatesEnabled(updatesEnabled);
2507 #endif
2508
2509     container->update();
2510 #ifdef QT_KEYPAD_NAVIGATION
2511     if (QApplication::keypadNavigationEnabled())
2512         view()->setEditFocus(true);
2513 #endif
2514 }
2515
2516 /*!
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.
2523
2524     \sa showPopup()
2525 */
2526 void QComboBox::hidePopup()
2527 {
2528     Q_D(QComboBox);
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();
2540
2541                 // Deselect item and wait 60 ms.
2542                 selectionModel->select(selection, QItemSelectionModel::Toggle);
2543                 QTimer::singleShot(60, &eventLoop, SLOT(quit()));
2544                 eventLoop.exec();
2545
2546                 // Select item and wait 20 ms.
2547                 selectionModel->select(selection, QItemSelectionModel::Toggle);
2548                 QTimer::singleShot(20, &eventLoop, SLOT(quit()));
2549                 eventLoop.exec();
2550             }
2551         }
2552
2553         // Fade out.
2554         bool needFade = style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
2555         bool didFade = false;
2556         if (needFade) {
2557 #if defined(Q_OS_MAC)
2558             QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface();
2559             int at = platformNativeInterface->metaObject()->indexOfMethod("fadeWindow()");
2560             if (at != -1) {
2561                 QMetaMethod windowFade = platformNativeInterface->metaObject()->method(at);
2562                 windowFade.invoke(platformNativeInterface, Q_ARG(QWindow *, d->container->windowHandle()));
2563                 didFade = true;
2564             }
2565
2566 #endif // Q_OS_MAC
2567             // Other platform implementations welcome :-)
2568         }
2569         d->model->blockSignals(false);
2570         d->container->itemView()->blockSignals(false);
2571         d->container->blockSignals(false);
2572
2573         if (!didFade)
2574 #endif // QT_NO_EFFECTS
2575             // Fade should implicitly hide as well ;-)
2576             d->container->hide();
2577     }
2578 #ifdef QT_KEYPAD_NAVIGATION
2579     if (QApplication::keypadNavigationEnabled() && isEditable() && hasFocus())
2580         setEditFocus(true);
2581 #endif
2582     d->_q_resetButton();
2583 }
2584
2585 /*!
2586     Clears the combobox, removing all items.
2587
2588     Note: If you have set an external model on the combobox this model
2589     will still be cleared when calling this function.
2590 */
2591 void QComboBox::clear()
2592 {
2593     Q_D(QComboBox);
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);
2598 #endif
2599 }
2600
2601 /*!
2602     Clears the contents of the line edit used for editing in the combobox.
2603 */
2604 void QComboBox::clearEditText()
2605 {
2606     Q_D(QComboBox);
2607     if (d->lineEdit)
2608         d->lineEdit->clear();
2609 #ifndef QT_NO_ACCESSIBILITY
2610         QAccessibleEvent event(this, QAccessible::NameChanged);
2611         QAccessible::updateAccessibility(&event);
2612 #endif
2613 }
2614
2615 /*!
2616     Sets the \a text in the combobox's text edit.
2617 */
2618 void QComboBox::setEditText(const QString &text)
2619 {
2620     Q_D(QComboBox);
2621     if (d->lineEdit)
2622         d->lineEdit->setText(text);
2623 #ifndef QT_NO_ACCESSIBILITY
2624         QAccessibleEvent event(this, QAccessible::NameChanged);
2625         QAccessible::updateAccessibility(&event);
2626 #endif
2627 }
2628
2629 /*!
2630     \reimp
2631 */
2632 void QComboBox::focusInEvent(QFocusEvent *e)
2633 {
2634     Q_D(QComboBox);
2635     update();
2636     if (d->lineEdit) {
2637         d->lineEdit->event(e);
2638 #ifndef QT_NO_COMPLETER
2639         if (d->lineEdit->completer())
2640             d->lineEdit->completer()->setWidget(this);
2641 #endif
2642     }
2643 }
2644
2645 /*!
2646     \reimp
2647 */
2648 void QComboBox::focusOutEvent(QFocusEvent *e)
2649 {
2650     Q_D(QComboBox);
2651     update();
2652     if (d->lineEdit)
2653         d->lineEdit->event(e);
2654 }
2655
2656 /*! \reimp */
2657 void QComboBox::changeEvent(QEvent *e)
2658 {
2659     Q_D(QComboBox);
2660     switch (e->type()) {
2661     case QEvent::StyleChange:
2662         d->updateDelegate();
2663 #ifdef Q_WS_MAC
2664     case QEvent::MacSizeChange:
2665 #endif
2666         d->sizeHint = QSize(); // invalidate size hint
2667         d->minimumSizeHint = QSize();
2668         d->updateLayoutDirection();
2669         if (d->lineEdit)
2670             d->updateLineEditGeometry();
2671         d->setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
2672
2673         // ### need to update scrollers etc. as well here
2674         break;
2675     case QEvent::EnabledChange:
2676         if (!isEnabled())
2677             hidePopup();
2678         break;
2679     case QEvent::PaletteChange: {
2680         d->updateViewContainerPaletteAndOpacity();
2681         break;
2682     }
2683     case QEvent::FontChange:
2684         d->sizeHint = QSize(); // invalidate size hint
2685         d->viewContainer()->setFont(font());
2686         if (d->lineEdit)
2687             d->updateLineEditGeometry();
2688         break;
2689     default:
2690         break;
2691     }
2692     QWidget::changeEvent(e);
2693 }
2694
2695 /*!
2696     \reimp
2697 */
2698 void QComboBox::resizeEvent(QResizeEvent *)
2699 {
2700     Q_D(QComboBox);
2701     d->updateLineEditGeometry();
2702 }
2703
2704 /*!
2705     \reimp
2706 */
2707 void QComboBox::paintEvent(QPaintEvent *)
2708 {
2709     QStylePainter painter(this);
2710     painter.setPen(palette().color(QPalette::Text));
2711
2712     // draw the combobox frame, focusrect and selected etc.
2713     QStyleOptionComboBox opt;
2714     initStyleOption(&opt);
2715     painter.drawComplexControl(QStyle::CC_ComboBox, opt);
2716
2717     // draw the icon and text
2718     painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
2719 }
2720
2721 /*!
2722     \reimp
2723 */
2724 void QComboBox::showEvent(QShowEvent *e)
2725 {
2726     Q_D(QComboBox);
2727     if (!d->shownOnce && d->sizeAdjustPolicy == QComboBox::AdjustToContentsOnFirstShow) {
2728         d->sizeHint = QSize();
2729         updateGeometry();
2730     }
2731     d->shownOnce = true;
2732     QWidget::showEvent(e);
2733 }
2734
2735 /*!
2736     \reimp
2737 */
2738 void QComboBox::hideEvent(QHideEvent *)
2739 {
2740     hidePopup();
2741 }
2742
2743 /*!
2744     \reimp
2745 */
2746 bool QComboBox::event(QEvent *event)
2747 {
2748     Q_D(QComboBox);
2749     switch(event->type()) {
2750     case QEvent::LayoutDirectionChange:
2751     case QEvent::ApplicationLayoutDirectionChange:
2752         d->updateLayoutDirection();
2753         d->updateLineEditGeometry();
2754         break;
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());
2760         break;
2761     case QEvent::ShortcutOverride:
2762         if (d->lineEdit)
2763             return d->lineEdit->event(event);
2764         break;
2765 #ifdef QT_KEYPAD_NAVIGATION
2766     case QEvent::EnterEditFocus:
2767         if (!d->lineEdit)
2768             setEditFocus(false); // We never want edit focus if we are not editable
2769         else
2770             d->lineEdit->event(event);  //so cursor starts
2771         break;
2772     case QEvent::LeaveEditFocus:
2773         if (d->lineEdit)
2774             d->lineEdit->event(event);  //so cursor stops
2775         break;
2776 #endif
2777     default:
2778         break;
2779     }
2780     return QWidget::event(event);
2781 }
2782
2783 /*!
2784     \reimp
2785 */
2786 void QComboBox::mousePressEvent(QMouseEvent *e)
2787 {
2788     Q_D(QComboBox);
2789     QStyleOptionComboBox opt;
2790     initStyleOption(&opt);
2791     QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(),
2792                                                            this);
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
2799         if (d->container) {
2800 #endif
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
2806         }
2807 #endif
2808         showPopup();
2809     } else {
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
2813             return;
2814         }
2815 #endif
2816         QWidget::mousePressEvent(e);
2817     }
2818 }
2819
2820 /*!
2821     \reimp
2822 */
2823 void QComboBox::mouseReleaseEvent(QMouseEvent *e)
2824 {
2825     Q_D(QComboBox);
2826     Q_UNUSED(e);
2827     d->updateArrow(QStyle::State_None);
2828 }
2829
2830 /*!
2831     \reimp
2832 */
2833 void QComboBox::keyPressEvent(QKeyEvent *e)
2834 {
2835     Q_D(QComboBox);
2836
2837 #ifndef QT_NO_COMPLETER
2838     if (d->lineEdit
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);
2844         return;
2845     }
2846 #endif
2847
2848     enum Move { NoMove=0 , MoveUp , MoveDown , MoveFirst , MoveLast};
2849
2850     Move move = NoMove;
2851     int newIndex = currentIndex();
2852     switch (e->key()) {
2853     case Qt::Key_Up:
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())
2859             e->ignore();
2860         else
2861 #endif
2862         move = MoveUp;
2863         break;
2864     case Qt::Key_Down:
2865         if (e->modifiers() & Qt::AltModifier) {
2866             showPopup();
2867             return;
2868         } else if (e->modifiers() & Qt::ControlModifier)
2869             break; // pass to line edit for auto completion
2870         // fall through
2871     case Qt::Key_PageDown:
2872 #ifdef QT_KEYPAD_NAVIGATION
2873         if (QApplication::keypadNavigationEnabled())
2874             e->ignore();
2875         else
2876 #endif
2877         move = MoveDown;
2878         break;
2879     case Qt::Key_Home:
2880         if (!d->lineEdit)
2881             move = MoveFirst;
2882         break;
2883     case Qt::Key_End:
2884         if (!d->lineEdit)
2885             move = MoveLast;
2886         break;
2887     case Qt::Key_F4:
2888         if (!e->modifiers()) {
2889             showPopup();
2890             return;
2891         }
2892         break;
2893     case Qt::Key_Space:
2894         if (!d->lineEdit) {
2895             showPopup();
2896             return;
2897         }
2898     case Qt::Key_Enter:
2899     case Qt::Key_Return:
2900     case Qt::Key_Escape:
2901         if (!d->lineEdit)
2902             e->ignore();
2903         break;
2904 #ifdef QT_KEYPAD_NAVIGATION
2905     case Qt::Key_Select:
2906         if (QApplication::keypadNavigationEnabled()
2907                 && (!hasEditFocus() || !d->lineEdit)) {
2908             showPopup();
2909             return;
2910         }
2911         break;
2912     case Qt::Key_Left:
2913     case Qt::Key_Right:
2914         if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
2915             e->ignore();
2916         break;
2917     case Qt::Key_Back:
2918         if (QApplication::keypadNavigationEnabled()) {
2919             if (!hasEditFocus() || !d->lineEdit)
2920                 e->ignore();
2921         } else {
2922             e->ignore(); // let the surounding dialog have it
2923         }
2924         break;
2925 #endif
2926     default:
2927         if (!d->lineEdit) {
2928             if (!e->text().isEmpty())
2929                 d->keyboardSearchString(e->text());
2930             else
2931                 e->ignore();
2932         }
2933     }
2934
2935     if (move != NoMove) {
2936         e->accept();
2937         switch (move) {
2938         case MoveFirst:
2939             newIndex = -1;
2940         case MoveDown:
2941             newIndex++;
2942             while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2943                 newIndex++;
2944             break;
2945         case MoveLast:
2946             newIndex = count();
2947         case MoveUp:
2948             newIndex--;
2949             while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2950                 newIndex--;
2951             break;
2952         default:
2953             e->ignore();
2954             break;
2955         }
2956
2957         if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2958             setCurrentIndex(newIndex);
2959             d->emitActivated(d->currentIndex);
2960         }
2961     } else if (d->lineEdit) {
2962         d->lineEdit->event(e);
2963     }
2964 }
2965
2966
2967 /*!
2968     \reimp
2969 */
2970 void QComboBox::keyReleaseEvent(QKeyEvent *e)
2971 {
2972     Q_D(QComboBox);
2973     if (d->lineEdit)
2974         d->lineEdit->event(e);
2975 }
2976
2977 /*!
2978     \reimp
2979 */
2980 #ifndef QT_NO_WHEELEVENT
2981 void QComboBox::wheelEvent(QWheelEvent *e)
2982 {
2983     Q_D(QComboBox);
2984     if (!d->viewContainer()->isVisible()) {
2985         int newIndex = currentIndex();
2986
2987         if (e->delta() > 0) {
2988             newIndex--;
2989             while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2990                 newIndex--;
2991         } else {
2992             newIndex++;
2993             while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2994                 newIndex++;
2995         }
2996
2997         if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2998             setCurrentIndex(newIndex);
2999             d->emitActivated(d->currentIndex);
3000         }
3001         e->accept();
3002     }
3003 }
3004 #endif
3005
3006 #ifndef QT_NO_CONTEXTMENU
3007 /*!
3008     \reimp
3009 */
3010 void QComboBox::contextMenuEvent(QContextMenuEvent *e)
3011 {
3012     Q_D(QComboBox);
3013     if (d->lineEdit) {
3014         Qt::ContextMenuPolicy p = d->lineEdit->contextMenuPolicy();
3015         d->lineEdit->setContextMenuPolicy(Qt::DefaultContextMenu);
3016         d->lineEdit->event(e);
3017         d->lineEdit->setContextMenuPolicy(p);
3018     }
3019 }
3020 #endif // QT_NO_CONTEXTMENU
3021
3022 void QComboBoxPrivate::keyboardSearchString(const QString &text)
3023 {
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);
3032     }
3033 }
3034
3035 void QComboBoxPrivate::modelChanged()
3036 {
3037     Q_Q(QComboBox);
3038
3039     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
3040         sizeHint = QSize();
3041         adjustComboBoxSize();
3042         q->updateGeometry();
3043     }
3044 }
3045
3046 /*!
3047     \reimp
3048 */
3049 void QComboBox::inputMethodEvent(QInputMethodEvent *e)
3050 {
3051     Q_D(QComboBox);
3052     if (d->lineEdit) {
3053         d->lineEdit->event(e);
3054     } else {
3055         if (!e->commitString().isEmpty())
3056             d->keyboardSearchString(e->commitString());
3057         else
3058             e->ignore();
3059     }
3060 }
3061
3062 /*!
3063     \reimp
3064 */
3065 QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query) const
3066 {
3067     Q_D(const QComboBox);
3068     if (d->lineEdit)
3069         return d->lineEdit->inputMethodQuery(query);
3070     return QWidget::inputMethodQuery(query);
3071 }
3072
3073 /*!
3074     \fn void QComboBox::addItem(const QString &text, const QVariant &userData)
3075
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.
3079 */
3080
3081 /*!
3082     \fn void QComboBox::addItem(const QIcon &icon, const QString &text,
3083                                 const QVariant &userData)
3084
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.
3088 */
3089
3090 /*!
3091     \fn void QComboBox::addItems(const QStringList &texts)
3092
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.
3095 */
3096
3097 /*!
3098     \fn void QComboBox::editTextChanged(const QString &text)
3099
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.
3102 */
3103
3104 /*!
3105     \property QComboBox::frame
3106     \brief whether the combo box draws itself with a frame
3107
3108
3109     If enabled (the default) the combo box draws itself inside a
3110     frame, otherwise the combo box draws itself without any frame.
3111 */
3112 bool QComboBox::hasFrame() const
3113 {
3114     Q_D(const QComboBox);
3115     return d->frame;
3116 }
3117
3118
3119 void QComboBox::setFrame(bool enable)
3120 {
3121     Q_D(QComboBox);
3122     d->frame = enable;
3123     update();
3124     updateGeometry();
3125 }
3126
3127 /*!
3128     \property QComboBox::modelColumn
3129     \brief the column in the model that is visible.
3130
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
3133     default value).
3134
3135     By default, this property has a value of 0.
3136 */
3137 int QComboBox::modelColumn() const
3138 {
3139     Q_D(const QComboBox);
3140     return d->modelColumn;
3141 }
3142
3143 void QComboBox::setModelColumn(int visibleColumn)
3144 {
3145     Q_D(QComboBox);
3146     d->modelColumn = visibleColumn;
3147     QListView *lv = qobject_cast<QListView *>(d->viewContainer()->itemView());
3148     if (lv)
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);
3154 #endif
3155     setCurrentIndex(currentIndex()); //update the text to the text of the new column;
3156 }
3157
3158 QT_END_NAMESPACE
3159
3160 #include "moc_qcombobox.cpp"
3161
3162 #endif // QT_NO_COMBOBOX