d6af8d6044946e0360fe35181c8e2adb467dc0eb
[profile/ivi/qtbase.git] / src / widgets / widgets / qcombobox.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
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 <qlineedit.h>
47 #include <qapplication.h>
48 #include <qdesktopwidget.h>
49 #include <qlistview.h>
50 #include <qtableview.h>
51 #include <qitemdelegate.h>
52 #include <qmap.h>
53 #include <qmenu.h>
54 #include <qevent.h>
55 #include <qlayout.h>
56 #include <qscrollbar.h>
57 #include <qtreeview.h>
58 #include <qheaderview.h>
59 #include <qmath.h>
60 #include <private/qapplication_p.h>
61 #include <private/qcombobox_p.h>
62 #include <private/qabstractitemmodel_p.h>
63 #include <private/qabstractscrollarea_p.h>
64 #include <private/qsoftkeymanager_p.h>
65 #include <qdebug.h>
66 #ifdef Q_WS_X11
67 #include <private/qt_x11_p.h>
68 #endif
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 #ifdef Q_WS_WIN
223     return QApplication::desktop()->screenGeometry(screen);
224 #elif defined Q_WS_X11
225     if (X11->desktopEnvironment == DE_KDE)
226         return QApplication::desktop()->screenGeometry(screen);
227     else
228         return QApplication::desktop()->availableGeometry(screen);
229 #else
230         return QApplication::desktop()->availableGeometry(screen);
231 #endif
232 }
233
234 bool QComboBoxPrivate::updateHoverControl(const QPoint &pos)
235 {
236
237     Q_Q(QComboBox);
238     QRect lastHoverRect = hoverRect;
239     QStyle::SubControl lastHoverControl = hoverControl;
240     bool doesHover = q->testAttribute(Qt::WA_Hover);
241     if (lastHoverControl != newHoverControl(pos) && doesHover) {
242         q->update(lastHoverRect);
243         q->update(hoverRect);
244         return true;
245     }
246     return !doesHover;
247 }
248
249 QStyle::SubControl QComboBoxPrivate::newHoverControl(const QPoint &pos)
250 {
251     Q_Q(QComboBox);
252     QStyleOptionComboBox opt;
253     q->initStyleOption(&opt);
254     opt.subControls = QStyle::SC_All;
255     hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, pos, q);
256     hoverRect = (hoverControl != QStyle::SC_None)
257                    ? q->style()->subControlRect(QStyle::CC_ComboBox, &opt, hoverControl, q)
258                    : QRect();
259     return hoverControl;
260 }
261
262 /*
263     Computes a size hint based on the maximum width
264     for the items in the combobox.
265 */
266 int QComboBoxPrivate::computeWidthHint() const
267 {
268     Q_Q(const QComboBox);
269
270     int width = 0;
271     const int count = q->count();
272     const int iconWidth = q->iconSize().width() + 4;
273     const QFontMetrics &fontMetrics = q->fontMetrics();
274
275     for (int i = 0; i < count; ++i) {
276         const int textWidth = fontMetrics.width(q->itemText(i));
277         if (q->itemIcon(i).isNull())
278             width = (qMax(width, textWidth));
279         else
280             width = (qMax(width, textWidth + iconWidth));
281     }
282
283     QStyleOptionComboBox opt;
284     q->initStyleOption(&opt);
285     QSize tmp(width, 0);
286     tmp = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, tmp, q);
287     return tmp.width();
288 }
289
290 QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
291 {
292     Q_Q(const QComboBox);
293     if (!sh.isValid()) {
294         bool hasIcon = sizeAdjustPolicy == QComboBox::AdjustToMinimumContentsLengthWithIcon ? true : false;
295         int count = q->count();
296         QSize iconSize = q->iconSize();
297         const QFontMetrics &fm = q->fontMetrics();
298
299         // text width
300         if (&sh == &sizeHint || minimumContentsLength == 0) {
301             switch (sizeAdjustPolicy) {
302             case QComboBox::AdjustToContents:
303             case QComboBox::AdjustToContentsOnFirstShow:
304                 if (count == 0) {
305                     sh.rwidth() = 7 * fm.width(QLatin1Char('x'));
306                 } else {
307                     for (int i = 0; i < count; ++i) {
308                         if (!q->itemIcon(i).isNull()) {
309                             hasIcon = true;
310                             sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width() + iconSize.width() + 4));
311                         } else {
312                             sh.setWidth(qMax(sh.width(), fm.boundingRect(q->itemText(i)).width()));
313                         }
314                     }
315                 }
316                 break;
317             case QComboBox::AdjustToMinimumContentsLength:
318                 for (int i = 0; i < count && !hasIcon; ++i)
319                     hasIcon = !q->itemIcon(i).isNull();
320             default:
321                 ;
322             }
323         } else {
324             for (int i = 0; i < count && !hasIcon; ++i)
325                 hasIcon = !q->itemIcon(i).isNull();
326         }
327         if (minimumContentsLength > 0)
328             sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.width(QLatin1Char('X')) + (hasIcon ? iconSize.width() + 4 : 0)));
329
330
331         // height
332         sh.setHeight(qMax(qCeil(QFontMetricsF(fm).height()), 14) + 2);
333         if (hasIcon) {
334             sh.setHeight(qMax(sh.height(), iconSize.height() + 2));
335         }
336
337         // add style and strut values
338         QStyleOptionComboBox opt;
339         q->initStyleOption(&opt);
340         sh = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, q);
341     }
342     return sh.expandedTo(QApplication::globalStrut());
343 }
344
345 void QComboBoxPrivate::adjustComboBoxSize()
346 {
347     viewContainer()->adjustSizeTimer.start(20, container);
348 }
349
350 void QComboBoxPrivate::updateLayoutDirection()
351 {
352     Q_Q(const QComboBox);
353     QStyleOptionComboBox opt;
354     q->initStyleOption(&opt);
355     Qt::LayoutDirection dir = Qt::LayoutDirection(
356         q->style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, q));
357     if (lineEdit)
358         lineEdit->setLayoutDirection(dir);
359     if (container)
360         container->setLayoutDirection(dir);
361 }
362
363
364 void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent)
365 {
366     if (timerEvent->timerId() == adjustSizeTimer.timerId()) {
367         adjustSizeTimer.stop();
368         if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) {
369             combo->updateGeometry();
370             combo->adjustSize();
371             combo->update();
372         }
373     }
374 }
375
376 void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e)
377 {
378     QStyleOptionComboBox opt = comboStyleOption();
379     if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) {
380         QStyleOption myOpt;
381         myOpt.initFrom(this);
382         QStyleHintReturnMask mask;
383         if (combo->style()->styleHint(QStyle::SH_Menu_Mask, &myOpt, this, &mask)) {
384             setMask(mask.region);
385         }
386     } else {
387         clearMask();
388     }
389     QFrame::resizeEvent(e);
390 }
391
392 void QComboBoxPrivateContainer::leaveEvent(QEvent *)
393 {
394 // On Mac using the Mac style we want to clear the selection
395 // when the mouse moves outside the popup.
396 #ifdef Q_WS_MAC
397     QStyleOptionComboBox opt = comboStyleOption();
398     if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo))
399           view->clearSelection();
400 #endif
401 }
402
403 QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent)
404     : QFrame(parent, Qt::Popup), combo(parent), view(0), top(0), bottom(0)
405 {
406     // we need the combobox and itemview
407     Q_ASSERT(parent);
408     Q_ASSERT(itemView);
409
410     setAttribute(Qt::WA_WindowPropagation);
411     setAttribute(Qt::WA_X11NetWmWindowTypeCombo);
412
413     // setup container
414     blockMouseReleaseTimer.setSingleShot(true);
415
416     // we need a vertical layout
417     QBoxLayout *layout =  new QBoxLayout(QBoxLayout::TopToBottom, this);
418     layout->setSpacing(0);
419     layout->setMargin(0);
420
421     // set item view
422     setItemView(itemView);
423
424     // add scroller arrows if style needs them
425     QStyleOptionComboBox opt = comboStyleOption();
426     const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
427     if (usePopup) {
428         top = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepSub, this);
429         bottom = new QComboBoxPrivateScroller(QAbstractSlider::SliderSingleStepAdd, this);
430         top->hide();
431         bottom->hide();
432     } else {
433         setLineWidth(1);
434     }
435
436     setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
437
438     if (top) {
439         layout->insertWidget(0, top);
440         connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
441     }
442     if (bottom) {
443         layout->addWidget(bottom);
444         connect(bottom, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
445     }
446
447     // Some styles (Mac) have a margin at the top and bottom of the popup.
448     layout->insertSpacing(0, 0);
449     layout->addSpacing(0);
450     updateTopBottomMargin();
451 }
452
453 void QComboBoxPrivateContainer::scrollItemView(int action)
454 {
455 #ifndef QT_NO_SCROLLBAR
456     if (view->verticalScrollBar())
457         view->verticalScrollBar()->triggerAction(static_cast<QAbstractSlider::SliderAction>(action));
458 #endif
459 }
460
461 /*
462     Hides or shows the scrollers when we emulate a popupmenu
463 */
464 void QComboBoxPrivateContainer::updateScrollers()
465 {
466 #ifndef QT_NO_SCROLLBAR
467     if (!top || !bottom)
468         return;
469
470     if (isVisible() == false)
471         return;
472
473     QStyleOptionComboBox opt = comboStyleOption();
474     if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo) &&
475         view->verticalScrollBar()->minimum() < view->verticalScrollBar()->maximum()) {
476
477         bool needTop = view->verticalScrollBar()->value()
478                        > (view->verticalScrollBar()->minimum() + spacing());
479         bool needBottom = view->verticalScrollBar()->value()
480                           < (view->verticalScrollBar()->maximum() - spacing()*2);
481         if (needTop)
482             top->show();
483         else
484             top->hide();
485         if (needBottom)
486             bottom->show();
487         else
488             bottom->hide();
489     } else {
490         top->hide();
491         bottom->hide();
492     }
493 #endif // QT_NO_SCROLLBAR
494 }
495
496 /*
497     Cleans up when the view is destroyed.
498 */
499 void QComboBoxPrivateContainer::viewDestroyed()
500 {
501     view = 0;
502     setItemView(new QComboBoxListView());
503 }
504
505 /*
506     Returns the item view used for the combobox popup.
507 */
508 QAbstractItemView *QComboBoxPrivateContainer::itemView() const
509 {
510     return view;
511 }
512
513 /*!
514     Sets the item view to be used for the combobox popup.
515 */
516 void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
517 {
518     Q_ASSERT(itemView);
519
520     // clean up old one
521     if (view) {
522         view->removeEventFilter(this);
523         view->viewport()->removeEventFilter(this);
524 #ifndef QT_NO_SCROLLBAR
525         disconnect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
526                    this, SLOT(updateScrollers()));
527         disconnect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
528                    this, SLOT(updateScrollers()));
529 #endif
530         disconnect(view, SIGNAL(destroyed()),
531                    this, SLOT(viewDestroyed()));
532
533         delete view;
534         view = 0;
535     }
536
537     // setup the item view
538     view = itemView;
539     view->setParent(this);
540     view->setAttribute(Qt::WA_MacShowFocusRect, false);
541     qobject_cast<QBoxLayout*>(layout())->insertWidget(top ? 2 : 0, view);
542     view->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
543     view->installEventFilter(this);
544     view->viewport()->installEventFilter(this);
545     view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
546     QStyleOptionComboBox opt = comboStyleOption();
547     const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
548 #ifndef QT_NO_SCROLLBAR
549     if (usePopup)
550         view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
551 #endif
552     if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
553         usePopup) {
554         view->setMouseTracking(true);
555     }
556     view->setSelectionMode(QAbstractItemView::SingleSelection);
557     view->setFrameStyle(QFrame::NoFrame);
558     view->setLineWidth(0);
559     view->setEditTriggers(QAbstractItemView::NoEditTriggers);
560 #ifndef QT_NO_SCROLLBAR
561     connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
562             this, SLOT(updateScrollers()));
563     connect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
564             this, SLOT(updateScrollers()));
565 #endif
566     connect(view, SIGNAL(destroyed()),
567             this, SLOT(viewDestroyed()));
568
569 #ifdef QT_SOFTKEYS_ENABLED
570     selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, itemView);
571     cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, itemView);
572     addAction(selectAction);
573     addAction(cancelAction);
574 #endif
575 }
576
577 /*!
578     Returns the spacing between the items in the view.
579 */
580 int QComboBoxPrivateContainer::spacing() const
581 {
582     QListView *lview = qobject_cast<QListView*>(view);
583     if (lview)
584         return lview->spacing();
585 #ifndef QT_NO_TABLEVIEW
586     QTableView *tview = qobject_cast<QTableView*>(view);
587     if (tview)
588         return tview->showGrid() ? 1 : 0;
589 #endif
590     return 0;
591 }
592
593 void QComboBoxPrivateContainer::updateTopBottomMargin()
594 {
595     if (!layout() || layout()->count() < 1)
596         return;
597
598     QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout());
599     if (!boxLayout)
600         return;
601
602     const QStyleOptionComboBox opt = comboStyleOption();
603     const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
604     const int margin = usePopup ? combo->style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, combo) : 0;
605
606     QSpacerItem *topSpacer = boxLayout->itemAt(0)->spacerItem();
607     if (topSpacer)
608         topSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
609
610     QSpacerItem *bottomSpacer = boxLayout->itemAt(boxLayout->count() - 1)->spacerItem();
611     if (bottomSpacer && bottomSpacer != topSpacer)
612         bottomSpacer->changeSize(0, margin, QSizePolicy::Minimum, QSizePolicy::Fixed);
613
614     boxLayout->invalidate();
615 }
616
617 void QComboBoxPrivateContainer::changeEvent(QEvent *e)
618 {
619     if (e->type() == QEvent::StyleChange) {
620         QStyleOptionComboBox opt = comboStyleOption();
621         view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
622                                combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo));
623         setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
624 #ifdef QT_SOFTKEYS_ENABLED
625     } else if (e->type() == QEvent::LanguageChange) {
626         selectAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::SelectSoftKey));
627         cancelAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::CancelSoftKey));
628 #endif
629     }
630
631     QWidget::changeEvent(e);
632 }
633
634
635 bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
636 {
637     switch (e->type()) {
638     case QEvent::ShortcutOverride:
639         switch (static_cast<QKeyEvent*>(e)->key()) {
640         case Qt::Key_Enter:
641         case Qt::Key_Return:
642 #ifdef QT_KEYPAD_NAVIGATION
643         case Qt::Key_Select:
644 #endif
645             if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
646                 combo->hidePopup();
647                 emit itemSelected(view->currentIndex());
648             }
649             return true;
650         case Qt::Key_Down:
651             if (!(static_cast<QKeyEvent*>(e)->modifiers() & Qt::AltModifier))
652                 break;
653             // fall through
654         case Qt::Key_F4:
655         case Qt::Key_Escape:
656             combo->hidePopup();
657             return true;
658         default:
659             break;
660         }
661     break;
662     case QEvent::MouseMove:
663         if (isVisible()) {
664             QMouseEvent *m = static_cast<QMouseEvent *>(e);
665             QWidget *widget = static_cast<QWidget *>(o);
666             QPoint vector = widget->mapToGlobal(m->pos()) - initialClickPosition;
667             if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive())
668                 blockMouseReleaseTimer.stop();
669             QModelIndex indexUnderMouse = view->indexAt(m->pos());
670             if (indexUnderMouse.isValid()
671                      && !QComboBoxDelegate::isSeparator(indexUnderMouse)) {
672                 view->setCurrentIndex(indexUnderMouse);
673             }
674         }
675         break;
676     case QEvent::MouseButtonRelease: {
677         QMouseEvent *m = static_cast<QMouseEvent *>(e);
678         if (isVisible() && view->rect().contains(m->pos()) && view->currentIndex().isValid()
679             && !blockMouseReleaseTimer.isActive()
680             && (view->currentIndex().flags() & Qt::ItemIsEnabled)
681             && (view->currentIndex().flags() & Qt::ItemIsSelectable)) {
682             combo->hidePopup();
683             emit itemSelected(view->currentIndex());
684             return true;
685         }
686         break;
687     }
688     default:
689         break;
690     }
691     return QFrame::eventFilter(o, e);
692 }
693
694 void QComboBoxPrivateContainer::showEvent(QShowEvent *)
695 {
696     combo->update();
697 }
698
699 void QComboBoxPrivateContainer::hideEvent(QHideEvent *)
700 {
701     emit resetButton();
702     combo->update();
703 #ifndef QT_NO_GRAPHICSVIEW
704     // QGraphicsScenePrivate::removePopup closes the combo box popup, it hides it non-explicitly.
705     // Hiding/showing the QComboBox after this will unexpectedly show the popup as well.
706     // Re-hiding the popup container makes sure it is explicitly hidden.
707     if (QGraphicsProxyWidget *proxy = graphicsProxyWidget())
708         proxy->hide();
709 #endif
710 }
711
712 void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
713 {
714
715     QStyleOptionComboBox opt = comboStyleOption();
716     opt.subControls = QStyle::SC_All;
717     opt.activeSubControls = QStyle::SC_ComboBoxArrow;
718     QStyle::SubControl sc = combo->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt,
719                                                            combo->mapFromGlobal(e->globalPos()),
720                                                            combo);
721     if ((combo->isEditable() && sc == QStyle::SC_ComboBoxArrow)
722         || (!combo->isEditable() && sc != QStyle::SC_None))
723         setAttribute(Qt::WA_NoMouseReplay);
724     combo->hidePopup();
725 }
726
727 void QComboBoxPrivateContainer::mouseReleaseEvent(QMouseEvent *e)
728 {
729     Q_UNUSED(e);
730     if (!blockMouseReleaseTimer.isActive()){
731         combo->hidePopup();
732         emit resetButton();
733     }
734 }
735
736 QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
737 {
738     // ### This should use QComboBox's initStyleOption(), but it's protected
739     // perhaps, we could cheat by having the QCombo private instead?
740     QStyleOptionComboBox opt;
741     opt.initFrom(combo);
742     opt.subControls = QStyle::SC_All;
743     opt.activeSubControls = QStyle::SC_None;
744     opt.editable = combo->isEditable();
745     return opt;
746 }
747
748 /*!
749     \enum QComboBox::InsertPolicy
750
751     This enum specifies what the QComboBox should do when a new string is
752     entered by the user.
753
754     \value NoInsert             The string will not be inserted into the combobox.
755     \value InsertAtTop          The string will be inserted as the first item in the combobox.
756     \value InsertAtCurrent      The current item will be \e replaced by the string.
757     \value InsertAtBottom       The string will be inserted after the last item in the combobox.
758     \value InsertAfterCurrent   The string is inserted after the current item in the combobox.
759     \value InsertBeforeCurrent  The string is inserted before the current item in the combobox.
760     \value InsertAlphabetically The string is inserted in the alphabetic order in the combobox.
761     \omitvalue NoInsertion
762     \omitvalue AtTop
763     \omitvalue AtCurrent
764     \omitvalue AtBottom
765     \omitvalue AfterCurrent
766     \omitvalue BeforeCurrent
767 */
768
769 /*!
770     \enum QComboBox::SizeAdjustPolicy
771
772     This enum specifies how the size hint of the QComboBox should
773     adjust when new content is added or content changes.
774
775     \value AdjustToContents              The combobox will always adjust to the contents
776     \value AdjustToContentsOnFirstShow   The combobox will adjust to its contents the first time it is shown.
777     \value AdjustToMinimumContentsLength Use AdjustToContents or AdjustToContentsOnFirstShow instead.
778     \value AdjustToMinimumContentsLengthWithIcon The combobox will adjust to \l minimumContentsLength plus space for an icon. For performance reasons use this policy on large models.
779 */
780
781 /*!
782     \fn void QComboBox::activated(int index)
783
784     This signal is sent when the user chooses an item in the combobox.
785     The item's \a index is passed. Note that this signal is sent even
786     when the choice is not changed. If you need to know when the
787     choice actually changes, use signal currentIndexChanged().
788
789 */
790
791 /*!
792     \fn void QComboBox::activated(const QString &text)
793
794     This signal is sent when the user chooses an item in the combobox.
795     The item's \a text is passed. Note that this signal is sent even
796     when the choice is not changed. If you need to know when the
797     choice actually changes, use signal currentIndexChanged().
798
799 */
800
801 /*!
802     \fn void QComboBox::highlighted(int index)
803
804     This signal is sent when an item in the combobox popup list is
805     highlighted by the user. The item's \a index is passed.
806 */
807
808 /*!
809     \fn void QComboBox::highlighted(const QString &text)
810
811     This signal is sent when an item in the combobox popup list is
812     highlighted by the user. The item's \a text is passed.
813 */
814
815 /*!
816     \fn void QComboBox::currentIndexChanged(int index)
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 index is passed or -1 if the combobox becomes empty or the
822     currentIndex was reset.
823 */
824
825 /*!
826     \fn void QComboBox::currentIndexChanged(const QString &text)
827     \since 4.1
828
829     This signal is sent whenever the currentIndex in the combobox
830     changes either through user interaction or programmatically.  The
831     item's \a text is passed.
832 */
833
834 /*!
835     Constructs a combobox with the given \a parent, using the default
836     model QStandardItemModel.
837 */
838 QComboBox::QComboBox(QWidget *parent)
839     : QWidget(*new QComboBoxPrivate(), parent, 0)
840 {
841     Q_D(QComboBox);
842     d->init();
843 }
844
845 /*!
846   \internal
847 */
848 QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent)
849     : QWidget(dd, parent, 0)
850 {
851     Q_D(QComboBox);
852     d->init();
853 }
854
855
856 /*!
857     \class QComboBox
858     \brief The QComboBox widget is a combined button and popup list.
859
860     \ingroup basicwidgets
861     \inmodule QtWidgets
862
863     A QComboBox provides a means of presenting a list of options to the user
864     in a way that takes up the minimum amount of screen space.
865
866     A combobox is a selection widget that displays the current item,
867     and can pop up a list of selectable items. A combobox may be editable,
868     allowing the user to modify each item in the list.
869
870     Comboboxes can contain pixmaps as well as strings; the
871     insertItem() and setItemText() functions are suitably overloaded.
872     For editable comboboxes, the function clearEditText() is provided,
873     to clear the displayed string without changing the combobox's
874     contents.
875
876     There are two signals emitted if the current item of a combobox
877     changes, currentIndexChanged() and activated().
878     currentIndexChanged() is always emitted regardless if the change
879     was done programmatically or by user interaction, while
880     activated() is only emitted when the change is caused by user
881     interaction. The highlighted() signal is emitted when the user
882     highlights an item in the combobox popup list. All three signals
883     exist in two versions, one with a QString argument and one with an
884     \c int argument. If the user selects or highlights a pixmap, only
885     the \c int signals are emitted. Whenever the text of an editable
886     combobox is changed the editTextChanged() signal is emitted.
887
888     When the user enters a new string in an editable combobox, the
889     widget may or may not insert it, and it can insert it in several
890     locations. The default policy is is \l AtBottom but you can change
891     this using setInsertPolicy().
892
893     It is possible to constrain the input to an editable combobox
894     using QValidator; see setValidator(). By default, any input is
895     accepted.
896
897     A combobox can be populated using the insert functions,
898     insertItem() and insertItems() for example. Items can be
899     changed with setItemText(). An item can be removed with
900     removeItem() and all items can be removed with clear(). The text
901     of the current item is returned by currentText(), and the text of
902     a numbered item is returned with text(). The current item can be
903     set with setCurrentIndex(). The number of items in the combobox is
904     returned by count(); the maximum number of items can be set with
905     setMaxCount(). You can allow editing using setEditable(). For
906     editable comboboxes you can set auto-completion using
907     setCompleter() and whether or not the user can add duplicates
908     is set with setDuplicatesEnabled().
909
910     QComboBox uses the \l{Model/View Programming}{model/view
911     framework} for its popup list and to store its items.  By default
912     a QStandardItemModel stores the items and a QListView subclass
913     displays the popuplist. You can access the model and view directly
914     (with model() and view()), but QComboBox also provides functions
915     to set and get item data (e.g., setItemData() and itemText()). You
916     can also set a new model and view (with setModel() and setView()).
917     For the text and icon in the combobox label, the data in the model
918     that has the Qt::DisplayRole and Qt::DecorationRole is used.  Note
919     that you cannot alter the \l{QAbstractItemView::}{SelectionMode}
920     of the view(), e.g., by using
921     \l{QAbstractItemView::}{setSelectionMode()}.
922
923     \image qstyle-comboboxes.png Comboboxes in the different built-in styles.
924
925     \sa QLineEdit, QSpinBox, QRadioButton, QButtonGroup,
926         {fowler}{GUI Design Handbook: Combo Box, Drop-Down List Box}
927 */
928
929 void QComboBoxPrivate::init()
930 {
931     Q_Q(QComboBox);
932     q->setFocusPolicy(Qt::WheelFocus);
933     q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed,
934                                  QSizePolicy::ComboBox));
935     setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
936     q->setModel(new QStandardItemModel(0, 1, q));
937     if (!q->isEditable())
938         q->setAttribute(Qt::WA_InputMethodEnabled, false);
939     else
940         q->setAttribute(Qt::WA_InputMethodEnabled);
941 }
942
943 QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
944 {
945     if (container)
946         return container;
947
948     Q_Q(QComboBox);
949     container = new QComboBoxPrivateContainer(new QComboBoxListView(q), q);
950     container->itemView()->setModel(model);
951     container->itemView()->setTextElideMode(Qt::ElideMiddle);
952     updateDelegate(true);
953     updateLayoutDirection();
954     updateViewContainerPaletteAndOpacity();
955     QObject::connect(container, SIGNAL(itemSelected(QModelIndex)),
956                      q, SLOT(_q_itemSelected(QModelIndex)));
957     QObject::connect(container->itemView()->selectionModel(),
958                      SIGNAL(currentChanged(QModelIndex,QModelIndex)),
959                      q, SLOT(_q_emitHighlighted(QModelIndex)));
960     QObject::connect(container, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
961     return container;
962 }
963
964
965 void QComboBoxPrivate::_q_resetButton()
966 {
967     updateArrow(QStyle::State_None);
968 }
969
970 void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
971 {
972     Q_Q(QComboBox);
973     if (inserting || topLeft.parent() != root)
974         return;
975
976     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
977         sizeHint = QSize();
978         adjustComboBoxSize();
979         q->updateGeometry();
980     }
981
982     if (currentIndex.row() >= topLeft.row() && currentIndex.row() <= bottomRight.row()) {
983         if (lineEdit) {
984             lineEdit->setText(q->itemText(currentIndex.row()));
985             updateLineEditGeometry();
986         }
987         q->update();
988     }
989 #ifndef QT_NO_ACCESSIBILITY
990         QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, q, 0));
991 #endif
992 }
993
994 void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end)
995 {
996     Q_Q(QComboBox);
997     if (inserting || parent != root)
998         return;
999
1000     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
1001         sizeHint = QSize();
1002         adjustComboBoxSize();
1003         q->updateGeometry();
1004     }
1005
1006     // set current index if combo was previously empty
1007     if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid()) {
1008         q->setCurrentIndex(0);
1009         // need to emit changed if model updated index "silently"
1010     } else if (currentIndex.row() != indexBeforeChange) {
1011         q->update();
1012         _q_emitCurrentIndexChanged(currentIndex);
1013     }
1014 }
1015
1016 void QComboBoxPrivate::_q_updateIndexBeforeChange()
1017 {
1018     indexBeforeChange = currentIndex.row();
1019 }
1020
1021 void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
1022 {
1023     Q_Q(QComboBox);
1024     if (parent != root)
1025         return;
1026
1027     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
1028         sizeHint = QSize();
1029         adjustComboBoxSize();
1030         q->updateGeometry();
1031     }
1032
1033     // model has changed the currentIndex
1034     if (currentIndex.row() != indexBeforeChange) {
1035         if (!currentIndex.isValid() && q->count()) {
1036             q->setCurrentIndex(qMin(q->count() - 1, qMax(indexBeforeChange, 0)));
1037             return;
1038         }
1039         if (lineEdit) {
1040             lineEdit->setText(q->itemText(currentIndex.row()));
1041             updateLineEditGeometry();
1042         }
1043         q->update();
1044         _q_emitCurrentIndexChanged(currentIndex);
1045     }
1046 }
1047
1048
1049 void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
1050 {
1051     if (!container)
1052         return;
1053     Q_Q(QComboBox);
1054     QStyleOptionComboBox opt;
1055     q->initStyleOption(&opt);
1056 #ifndef QT_NO_MENU
1057     if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1058         QMenu menu;
1059         menu.ensurePolished();
1060         container->setPalette(menu.palette());
1061         container->setWindowOpacity(menu.windowOpacity());
1062     } else
1063 #endif
1064     {
1065         container->setPalette(q->palette());
1066         container->setWindowOpacity(1.0);
1067     }
1068     if (lineEdit)
1069         lineEdit->setPalette(q->palette());
1070 }
1071
1072 /*!
1073     Initialize \a option with the values from this QComboBox. This method
1074     is useful for subclasses when they need a QStyleOptionComboBox, but don't want
1075     to fill in all the information themselves.
1076
1077     \sa QStyleOption::initFrom()
1078 */
1079 void QComboBox::initStyleOption(QStyleOptionComboBox *option) const
1080 {
1081     if (!option)
1082         return;
1083
1084     Q_D(const QComboBox);
1085     option->initFrom(this);
1086     option->editable = isEditable();
1087     option->frame = d->frame;
1088     if (hasFocus() && !option->editable)
1089         option->state |= QStyle::State_Selected;
1090     option->subControls = QStyle::SC_All;
1091     if (d->arrowState == QStyle::State_Sunken) {
1092         option->activeSubControls = QStyle::SC_ComboBoxArrow;
1093         option->state |= d->arrowState;
1094     } else {
1095         option->activeSubControls = d->hoverControl;
1096     }
1097     if (d->currentIndex.isValid()) {
1098         option->currentText = currentText();
1099         option->currentIcon = d->itemIcon(d->currentIndex);
1100     }
1101     option->iconSize = iconSize();
1102     if (d->container && d->container->isVisible())
1103         option->state |= QStyle::State_On;
1104 }
1105
1106 void QComboBoxPrivate::updateLineEditGeometry()
1107 {
1108     if (!lineEdit)
1109         return;
1110
1111     Q_Q(QComboBox);
1112     QStyleOptionComboBox opt;
1113     q->initStyleOption(&opt);
1114     QRect editRect = q->style()->subControlRect(QStyle::CC_ComboBox, &opt,
1115                                                 QStyle::SC_ComboBoxEditField, q);
1116     if (!q->itemIcon(q->currentIndex()).isNull()) {
1117         QRect comboRect(editRect);
1118         editRect.setWidth(editRect.width() - q->iconSize().width() - 4);
1119         editRect = QStyle::alignedRect(q->layoutDirection(), Qt::AlignRight,
1120                                        editRect.size(), comboRect);
1121     }
1122     lineEdit->setGeometry(editRect);
1123 }
1124
1125 Qt::MatchFlags QComboBoxPrivate::matchFlags() const
1126 {
1127     // Base how duplicates are determined on the autocompletion case sensitivity
1128     Qt::MatchFlags flags = Qt::MatchFixedString;
1129 #ifndef QT_NO_COMPLETER
1130     if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive)
1131 #endif
1132         flags |= Qt::MatchCaseSensitive;
1133     return flags;
1134 }
1135
1136
1137 void QComboBoxPrivate::_q_editingFinished()
1138 {
1139     Q_Q(QComboBox);
1140     if (lineEdit && !lineEdit->text().isEmpty()) {
1141         //here we just check if the current item was entered
1142         const int index = q_func()->findText(lineEdit->text(), matchFlags());
1143         if (index != -1 && itemText(currentIndex) != lineEdit->text()) {
1144             q->setCurrentIndex(index);
1145             emitActivated(currentIndex);
1146         }
1147     }
1148
1149 }
1150
1151 void QComboBoxPrivate::_q_returnPressed()
1152 {
1153     Q_Q(QComboBox);
1154     if (lineEdit && !lineEdit->text().isEmpty()) {
1155         if (q->count() >= maxCount && !(this->insertPolicy == QComboBox::InsertAtCurrent))
1156             return;
1157         lineEdit->deselect();
1158         lineEdit->end(false);
1159         QString text = lineEdit->text();
1160         // check for duplicates (if not enabled) and quit
1161         int index = -1;
1162         if (!duplicatesEnabled) {
1163             index = q->findText(text, matchFlags());
1164             if (index != -1) {
1165                 q->setCurrentIndex(index);
1166                 emitActivated(currentIndex);
1167                 return;
1168             }
1169         }
1170         switch (insertPolicy) {
1171         case QComboBox::InsertAtTop:
1172             index = 0;
1173             break;
1174         case QComboBox::InsertAtBottom:
1175             index = q->count();
1176             break;
1177         case QComboBox::InsertAtCurrent:
1178         case QComboBox::InsertAfterCurrent:
1179         case QComboBox::InsertBeforeCurrent:
1180             if (!q->count() || !currentIndex.isValid())
1181                 index = 0;
1182             else if (insertPolicy == QComboBox::InsertAtCurrent)
1183                 q->setItemText(q->currentIndex(), text);
1184             else if (insertPolicy == QComboBox::InsertAfterCurrent)
1185                 index = q->currentIndex() + 1;
1186             else if (insertPolicy == QComboBox::InsertBeforeCurrent)
1187                 index = q->currentIndex();
1188             break;
1189         case QComboBox::InsertAlphabetically:
1190             index = 0;
1191             for (int i=0; i< q->count(); i++, index++ ) {
1192                 if (text.toLower() < q->itemText(i).toLower())
1193                     break;
1194             }
1195             break;
1196         case QComboBox::NoInsert:
1197         default:
1198             break;
1199         }
1200         if (index >= 0) {
1201             q->insertItem(index, text);
1202             q->setCurrentIndex(index);
1203             emitActivated(currentIndex);
1204         }
1205     }
1206 }
1207
1208 void QComboBoxPrivate::_q_itemSelected(const QModelIndex &item)
1209 {
1210     Q_Q(QComboBox);
1211     if (item != currentIndex) {
1212         setCurrentIndex(item);
1213     } else if (lineEdit) {
1214         lineEdit->selectAll();
1215         lineEdit->setText(q->itemText(currentIndex.row()));
1216     }
1217     emitActivated(currentIndex);
1218 }
1219
1220 void QComboBoxPrivate::emitActivated(const QModelIndex &index)
1221 {
1222     Q_Q(QComboBox);
1223     if (!index.isValid())
1224         return;
1225     QString text(itemText(index));
1226     emit q->activated(index.row());
1227     emit q->activated(text);
1228 }
1229
1230 void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
1231 {
1232     Q_Q(QComboBox);
1233     if (!index.isValid())
1234         return;
1235     QString text(itemText(index));
1236     emit q->highlighted(index.row());
1237     emit q->highlighted(text);
1238 }
1239
1240 void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
1241 {
1242     Q_Q(QComboBox);
1243     emit q->currentIndexChanged(index.row());
1244     emit q->currentIndexChanged(itemText(index));
1245 #ifndef QT_NO_ACCESSIBILITY
1246         QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, q, 0));
1247 #endif
1248 }
1249
1250 QString QComboBoxPrivate::itemText(const QModelIndex &index) const
1251 {
1252     return index.isValid() ? model->data(index, itemRole()).toString() : QString();
1253 }
1254
1255 int QComboBoxPrivate::itemRole() const
1256 {
1257     return q_func()->isEditable() ? Qt::EditRole : Qt::DisplayRole;
1258 }
1259
1260 /*!
1261     Destroys the combobox.
1262 */
1263 QComboBox::~QComboBox()
1264 {
1265     // ### check delegateparent and delete delegate if us?
1266     Q_D(QComboBox);
1267
1268     QT_TRY {
1269         disconnect(d->model, SIGNAL(destroyed()),
1270                 this, SLOT(_q_modelDestroyed()));
1271     } QT_CATCH(...) {
1272         ; // objects can't throw in destructor
1273     }
1274 }
1275
1276 /*!
1277     \property QComboBox::maxVisibleItems
1278     \brief the maximum allowed size on screen of the combo box, measured in items
1279
1280     By default, this property has a value of 10.
1281
1282     \note This property is ignored for non-editable comboboxes in styles that returns
1283     true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
1284 */
1285 int QComboBox::maxVisibleItems() const
1286 {
1287     Q_D(const QComboBox);
1288     return d->maxVisibleItems;
1289 }
1290
1291 void QComboBox::setMaxVisibleItems(int maxItems)
1292 {
1293     Q_D(QComboBox);
1294     if (maxItems < 0) {
1295         qWarning("QComboBox::setMaxVisibleItems: "
1296                  "Invalid max visible items (%d) must be >= 0", maxItems);
1297         return;
1298     }
1299     d->maxVisibleItems = maxItems;
1300 }
1301
1302 /*!
1303     \property QComboBox::count
1304     \brief the number of items in the combobox
1305
1306     By default, for an empty combo box, this property has a value of 0.
1307 */
1308 int QComboBox::count() const
1309 {
1310     Q_D(const QComboBox);
1311     return d->model->rowCount(d->root);
1312 }
1313
1314 /*!
1315     \property QComboBox::maxCount
1316     \brief the maximum number of items allowed in the combobox
1317
1318     \note If you set the maximum number to be less then the current
1319     amount of items in the combobox, the extra items will be
1320     truncated. This also applies if you have set an external model on
1321     the combobox.
1322
1323     By default, this property's value is derived from the highest
1324     signed integer available (typically 2147483647).
1325 */
1326 void QComboBox::setMaxCount(int max)
1327 {
1328     Q_D(QComboBox);
1329     if (max < 0) {
1330         qWarning("QComboBox::setMaxCount: Invalid count (%d) must be >= 0", max);
1331         return;
1332     }
1333
1334     if (max < count())
1335         d->model->removeRows(max, count() - max, d->root);
1336
1337     d->maxCount = max;
1338 }
1339
1340 int QComboBox::maxCount() const
1341 {
1342     Q_D(const QComboBox);
1343     return d->maxCount;
1344 }
1345
1346 #ifndef QT_NO_COMPLETER
1347
1348 /*!
1349     \property QComboBox::autoCompletion
1350     \brief whether the combobox provides auto-completion for editable items
1351     \since 4.1
1352     \obsolete
1353
1354     Use setCompleter() instead.
1355
1356     By default, this property is true.
1357
1358     \sa editable
1359 */
1360
1361 /*!
1362     \obsolete
1363
1364     Use setCompleter() instead.
1365 */
1366 bool QComboBox::autoCompletion() const
1367 {
1368     Q_D(const QComboBox);
1369     return d->autoCompletion;
1370 }
1371
1372 /*!
1373     \obsolete
1374
1375     Use setCompleter() instead.
1376 */
1377 void QComboBox::setAutoCompletion(bool enable)
1378 {
1379     Q_D(QComboBox);
1380
1381 #ifdef QT_KEYPAD_NAVIGATION
1382     if (QApplication::keypadNavigationEnabled() && !enable && isEditable())
1383         qWarning("QComboBox::setAutoCompletion: auto completion is mandatory when combo box editable");
1384 #endif
1385
1386     d->autoCompletion = enable;
1387     if (!d->lineEdit)
1388         return;
1389     if (enable) {
1390         if (d->lineEdit->completer())
1391             return;
1392         d->completer = new QCompleter(d->model, d->lineEdit);
1393         d->completer->setCaseSensitivity(d->autoCompletionCaseSensitivity);
1394         d->completer->setCompletionMode(QCompleter::InlineCompletion);
1395         d->completer->setCompletionColumn(d->modelColumn);
1396         d->lineEdit->setCompleter(d->completer);
1397         d->completer->setWidget(this);
1398     } else {
1399         d->lineEdit->setCompleter(0);
1400     }
1401 }
1402
1403 /*!
1404     \property QComboBox::autoCompletionCaseSensitivity
1405     \brief whether string comparisons are case-sensitive or case-insensitive for auto-completion
1406     \obsolete
1407
1408     By default, this property is Qt::CaseInsensitive.
1409
1410     Use setCompleter() instead. Case sensitivity of the auto completion can be
1411     changed using QCompleter::setCaseSensitivity().
1412
1413     \sa autoCompletion
1414 */
1415
1416 /*!
1417     \obsolete
1418
1419     Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1420 */
1421 Qt::CaseSensitivity QComboBox::autoCompletionCaseSensitivity() const
1422 {
1423     Q_D(const QComboBox);
1424     return d->autoCompletionCaseSensitivity;
1425 }
1426
1427 /*!
1428     \obsolete
1429
1430     Use setCompleter() and QCompleter::setCaseSensitivity() instead.
1431 */
1432 void QComboBox::setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity)
1433 {
1434     Q_D(QComboBox);
1435     d->autoCompletionCaseSensitivity = sensitivity;
1436     if (d->lineEdit && d->lineEdit->completer())
1437         d->lineEdit->completer()->setCaseSensitivity(sensitivity);
1438 }
1439
1440 #endif // QT_NO_COMPLETER
1441
1442 /*!
1443     \property QComboBox::duplicatesEnabled
1444     \brief whether the user can enter duplicate items into the combobox
1445
1446     Note that it is always possible to programmatically insert duplicate items into the
1447     combobox.
1448
1449     By default, this property is false (duplicates are not allowed).
1450 */
1451 bool QComboBox::duplicatesEnabled() const
1452 {
1453     Q_D(const QComboBox);
1454     return d->duplicatesEnabled;
1455 }
1456
1457 void QComboBox::setDuplicatesEnabled(bool enable)
1458 {
1459     Q_D(QComboBox);
1460     d->duplicatesEnabled = enable;
1461 }
1462
1463 /*!  \fn int QComboBox::findText(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const
1464
1465   Returns the index of the item containing the given \a text; otherwise
1466   returns -1.
1467
1468   The \a flags specify how the items in the combobox are searched.
1469 */
1470
1471 /*!
1472   Returns the index of the item containing the given \a data for the
1473   given \a role; otherwise returns -1.
1474
1475   The \a flags specify how the items in the combobox are searched.
1476 */
1477 int QComboBox::findData(const QVariant &data, int role, Qt::MatchFlags flags) const
1478 {
1479     Q_D(const QComboBox);
1480     QModelIndexList result;
1481     QModelIndex start = d->model->index(0, d->modelColumn, d->root);
1482     result = d->model->match(start, role, data, 1, flags);
1483     if (result.isEmpty())
1484         return -1;
1485     return result.first().row();
1486 }
1487
1488 /*!
1489     \property QComboBox::insertPolicy
1490     \brief the policy used to determine where user-inserted items should
1491     appear in the combobox
1492
1493     The default value is \l AtBottom, indicating that new items will appear
1494     at the bottom of the list of items.
1495
1496     \sa InsertPolicy
1497 */
1498
1499 QComboBox::InsertPolicy QComboBox::insertPolicy() const
1500 {
1501     Q_D(const QComboBox);
1502     return d->insertPolicy;
1503 }
1504
1505 void QComboBox::setInsertPolicy(InsertPolicy policy)
1506 {
1507     Q_D(QComboBox);
1508     d->insertPolicy = policy;
1509 }
1510
1511 /*!
1512     \property QComboBox::sizeAdjustPolicy
1513     \brief the policy describing how the size of the combobox changes
1514     when the content changes
1515
1516     The default value is \l AdjustToContentsOnFirstShow.
1517
1518     \sa SizeAdjustPolicy
1519 */
1520
1521 QComboBox::SizeAdjustPolicy QComboBox::sizeAdjustPolicy() const
1522 {
1523     Q_D(const QComboBox);
1524     return d->sizeAdjustPolicy;
1525 }
1526
1527 void QComboBox::setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy policy)
1528 {
1529     Q_D(QComboBox);
1530     if (policy == d->sizeAdjustPolicy)
1531         return;
1532
1533     d->sizeAdjustPolicy = policy;
1534     d->sizeHint = QSize();
1535     d->adjustComboBoxSize();
1536     updateGeometry();
1537 }
1538
1539 /*!
1540     \property QComboBox::minimumContentsLength
1541     \brief the minimum number of characters that should fit into the combobox.
1542
1543     The default value is 0.
1544
1545     If this property is set to a positive value, the
1546     minimumSizeHint() and sizeHint() take it into account.
1547
1548     \sa sizeAdjustPolicy
1549 */
1550 int QComboBox::minimumContentsLength() const
1551 {
1552     Q_D(const QComboBox);
1553     return d->minimumContentsLength;
1554 }
1555
1556 void QComboBox::setMinimumContentsLength(int characters)
1557 {
1558     Q_D(QComboBox);
1559     if (characters == d->minimumContentsLength || characters < 0)
1560         return;
1561
1562     d->minimumContentsLength = characters;
1563
1564     if (d->sizeAdjustPolicy == AdjustToContents
1565             || d->sizeAdjustPolicy == AdjustToMinimumContentsLength
1566             || d->sizeAdjustPolicy == AdjustToMinimumContentsLengthWithIcon) {
1567         d->sizeHint = QSize();
1568         d->adjustComboBoxSize();
1569         updateGeometry();
1570     }
1571 }
1572
1573 /*!
1574     \property QComboBox::iconSize
1575     \brief the size of the icons shown in the combobox.
1576
1577     Unless explicitly set this returns the default value of the
1578     current style.  This size is the maximum size that icons can have;
1579     icons of smaller size are not scaled up.
1580 */
1581
1582 QSize QComboBox::iconSize() const
1583 {
1584     Q_D(const QComboBox);
1585     if (d->iconSize.isValid())
1586         return d->iconSize;
1587
1588     int iconWidth = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
1589     return QSize(iconWidth, iconWidth);
1590 }
1591
1592 void QComboBox::setIconSize(const QSize &size)
1593 {
1594     Q_D(QComboBox);
1595     if (size == d->iconSize)
1596         return;
1597
1598     view()->setIconSize(size);
1599     d->iconSize = size;
1600     d->sizeHint = QSize();
1601     updateGeometry();
1602 }
1603
1604 /*!
1605     \property QComboBox::editable
1606     \brief whether the combo box can be edited by the user
1607
1608     By default, this property is false.
1609 */
1610 bool QComboBox::isEditable() const
1611 {
1612     Q_D(const QComboBox);
1613     return d->lineEdit != 0;
1614 }
1615
1616 /*! \internal
1617     update the default delegate
1618     depending on the style's SH_ComboBox_Popup hint, we use a different default delegate.
1619
1620     but we do not change the delegate is the combobox use a custom delegate,
1621     unless \a force is set to true.
1622  */
1623 void QComboBoxPrivate::updateDelegate(bool force)
1624 {
1625     Q_Q(QComboBox);
1626     QStyleOptionComboBox opt;
1627     q->initStyleOption(&opt);
1628     if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
1629         if (force || qobject_cast<QComboBoxDelegate *>(q->itemDelegate()))
1630             q->setItemDelegate(new QComboMenuDelegate(q->view(), q));
1631     } else {
1632         if (force || qobject_cast<QComboMenuDelegate *>(q->itemDelegate()))
1633             q->setItemDelegate(new QComboBoxDelegate(q->view(), q));
1634     }
1635 }
1636
1637 QIcon QComboBoxPrivate::itemIcon(const QModelIndex &index) const
1638 {
1639     QVariant decoration = model->data(index, Qt::DecorationRole);
1640     if (decoration.type() == QVariant::Pixmap)
1641         return QIcon(qvariant_cast<QPixmap>(decoration));
1642     else
1643         return qvariant_cast<QIcon>(decoration);
1644 }
1645
1646 void QComboBox::setEditable(bool editable)
1647 {
1648     Q_D(QComboBox);
1649     if (isEditable() == editable)
1650         return;
1651
1652     d->updateDelegate();
1653
1654     QStyleOptionComboBox opt;
1655     initStyleOption(&opt);
1656     if (editable) {
1657         if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1658             d->viewContainer()->updateScrollers();
1659             view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
1660         }
1661         QLineEdit *le = new QLineEdit(this);
1662         setLineEdit(le);
1663     } else {
1664         if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
1665             d->viewContainer()->updateScrollers();
1666             view()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1667         }
1668         setAttribute(Qt::WA_InputMethodEnabled, false);
1669         d->lineEdit->hide();
1670         d->lineEdit->deleteLater();
1671         d->lineEdit = 0;
1672     }
1673
1674     d->viewContainer()->updateTopBottomMargin();
1675     if (!testAttribute(Qt::WA_Resized))
1676         adjustSize();
1677 }
1678
1679 /*!
1680     Sets the line \a edit to use instead of the current line edit widget.
1681
1682     The combo box takes ownership of the line edit.
1683 */
1684 void QComboBox::setLineEdit(QLineEdit *edit)
1685 {
1686     Q_D(QComboBox);
1687     if (!edit) {
1688         qWarning("QComboBox::setLineEdit: cannot set a 0 line edit");
1689         return;
1690     }
1691
1692     if (edit == d->lineEdit)
1693         return;
1694
1695     edit->setText(currentText());
1696     delete d->lineEdit;
1697
1698     d->lineEdit = edit;
1699     if (d->lineEdit->parent() != this)
1700         d->lineEdit->setParent(this);
1701     connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed()));
1702     connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished()));
1703     connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString)));
1704     d->lineEdit->setFrame(false);
1705     d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
1706     d->lineEdit->setFocusProxy(this);
1707     d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
1708 #ifndef QT_NO_COMPLETER
1709     setAutoCompletion(d->autoCompletion);
1710 #endif
1711
1712 #ifdef QT_KEYPAD_NAVIGATION
1713 #ifndef QT_NO_COMPLETER
1714     if (QApplication::keypadNavigationEnabled()) {
1715         // Editable combo boxes will have a completer that is set to UnfilteredPopupCompletion.
1716         // This means that when the user enters edit mode they are immediately presented with a
1717         // list of possible completions.
1718         setAutoCompletion(true);
1719         if (d->completer) {
1720             d->completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
1721             connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated()));
1722         }
1723     }
1724 #endif
1725 #endif
1726
1727     setAttribute(Qt::WA_InputMethodEnabled);
1728     d->updateLayoutDirection();
1729     d->updateLineEditGeometry();
1730     if (isVisible())
1731         d->lineEdit->show();
1732
1733     update();
1734 }
1735
1736 /*!
1737     Returns the line edit used to edit items in the combobox, or 0 if there
1738     is no line edit.
1739
1740     Only editable combo boxes have a line edit.
1741 */
1742 QLineEdit *QComboBox::lineEdit() const
1743 {
1744     Q_D(const QComboBox);
1745     return d->lineEdit;
1746 }
1747
1748 #ifndef QT_NO_VALIDATOR
1749 /*!
1750     \fn void QComboBox::setValidator(const QValidator *validator)
1751
1752     Sets the \a validator to use instead of the current validator.
1753 */
1754
1755 void QComboBox::setValidator(const QValidator *v)
1756 {
1757     Q_D(QComboBox);
1758     if (d->lineEdit)
1759         d->lineEdit->setValidator(v);
1760 }
1761
1762 /*!
1763     Returns the validator that is used to constrain text input for the
1764     combobox.
1765
1766     \sa editable
1767 */
1768 const QValidator *QComboBox::validator() const
1769 {
1770     Q_D(const QComboBox);
1771     return d->lineEdit ? d->lineEdit->validator() : 0;
1772 }
1773 #endif // QT_NO_VALIDATOR
1774
1775 #ifndef QT_NO_COMPLETER
1776
1777 /*!
1778     \fn void QComboBox::setCompleter(QCompleter *completer)
1779     \since 4.2
1780
1781     Sets the \a completer to use instead of the current completer.
1782     If \a completer is 0, auto completion is disabled.
1783
1784     By default, for an editable combo box, a QCompleter that
1785     performs case insensitive inline completion is automatically created.
1786 */
1787 void QComboBox::setCompleter(QCompleter *c)
1788 {
1789     Q_D(QComboBox);
1790     if (!d->lineEdit)
1791         return;
1792     d->lineEdit->setCompleter(c);
1793     if (c)
1794         c->setWidget(this);
1795 }
1796
1797 /*!
1798     \since 4.2
1799
1800     Returns the completer that is used to auto complete text input for the
1801     combobox.
1802
1803     \sa editable
1804 */
1805 QCompleter *QComboBox::completer() const
1806 {
1807     Q_D(const QComboBox);
1808     return d->lineEdit ? d->lineEdit->completer() : 0;
1809 }
1810
1811 #endif // QT_NO_COMPLETER
1812
1813 /*!
1814     Returns the item delegate used by the popup list view.
1815
1816     \sa setItemDelegate()
1817 */
1818 QAbstractItemDelegate *QComboBox::itemDelegate() const
1819 {
1820     return view()->itemDelegate();
1821 }
1822
1823 /*!
1824     Sets the item \a delegate for the popup list view.
1825     The combobox takes ownership of the delegate.
1826
1827     \warning You should not share the same instance of a delegate between comboboxes,
1828     widget mappers or views. Doing so can cause incorrect or unintuitive editing behavior
1829     since each view connected to a given delegate may receive the
1830     \l{QAbstractItemDelegate::}{closeEditor()} signal, and attempt to access, modify or
1831     close an editor that has already been closed.
1832
1833     \sa itemDelegate()
1834 */
1835 void QComboBox::setItemDelegate(QAbstractItemDelegate *delegate)
1836 {
1837     if (!delegate) {
1838         qWarning("QComboBox::setItemDelegate: cannot set a 0 delegate");
1839         return;
1840     }
1841     delete view()->itemDelegate();
1842     view()->setItemDelegate(delegate);
1843 }
1844
1845 /*!
1846     Returns the model used by the combobox.
1847 */
1848
1849 QAbstractItemModel *QComboBox::model() const
1850 {
1851     Q_D(const QComboBox);
1852     if (d->model == QAbstractItemModelPrivate::staticEmptyModel()) {
1853         QComboBox *that = const_cast<QComboBox*>(this);
1854         that->setModel(new QStandardItemModel(0, 1, that));
1855     }
1856     return d->model;
1857 }
1858
1859 /*!
1860     Sets the model to be \a model. \a model must not be 0.
1861     If you want to clear the contents of a model, call clear().
1862
1863     \sa clear()
1864 */
1865 void QComboBox::setModel(QAbstractItemModel *model)
1866 {
1867     Q_D(QComboBox);
1868
1869     if (!model) {
1870         qWarning("QComboBox::setModel: cannot set a 0 model");
1871         return;
1872     }
1873
1874 #ifndef QT_NO_COMPLETER
1875     if (d->lineEdit && d->lineEdit->completer()
1876         && d->lineEdit->completer() == d->completer)
1877         d->lineEdit->completer()->setModel(model);
1878 #endif
1879     if (d->model) {
1880         disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1881                    this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1882         disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
1883                    this, SLOT(_q_updateIndexBeforeChange()));
1884         disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
1885                    this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
1886         disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
1887                    this, SLOT(_q_updateIndexBeforeChange()));
1888         disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
1889                    this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
1890         disconnect(d->model, SIGNAL(destroyed()),
1891                    this, SLOT(_q_modelDestroyed()));
1892         disconnect(d->model, SIGNAL(modelAboutToBeReset()),
1893                    this, SLOT(_q_updateIndexBeforeChange()));
1894         disconnect(d->model, SIGNAL(modelReset()),
1895                    this, SLOT(_q_modelReset()));
1896         if (d->model->QObject::parent() == this)
1897             delete d->model;
1898     }
1899
1900     d->model = model;
1901
1902     connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1903             this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1904     connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
1905             this, SLOT(_q_updateIndexBeforeChange()));
1906     connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
1907             this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
1908     connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
1909             this, SLOT(_q_updateIndexBeforeChange()));
1910     connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
1911             this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
1912     connect(model, SIGNAL(destroyed()),
1913             this, SLOT(_q_modelDestroyed()));
1914     connect(model, SIGNAL(modelAboutToBeReset()),
1915             this, SLOT(_q_updateIndexBeforeChange()));
1916     connect(model, SIGNAL(modelReset()),
1917             this, SLOT(_q_modelReset()));
1918
1919     if (d->container)
1920         d->container->itemView()->setModel(model);
1921
1922     bool currentReset = false;
1923
1924     if (count()) {
1925         for (int pos=0; pos < count(); pos++) {
1926             if (d->model->index(pos, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled) {
1927                 setCurrentIndex(pos);
1928                 currentReset = true;
1929                 break;
1930             }
1931         }
1932     }
1933
1934     if (!currentReset)
1935         setCurrentIndex(-1);
1936
1937     d->modelChanged();
1938 }
1939
1940 /*!
1941     Returns the root model item index for the items in the combobox.
1942
1943     \sa setRootModelIndex()
1944 */
1945
1946 QModelIndex QComboBox::rootModelIndex() const
1947 {
1948     Q_D(const QComboBox);
1949     return QModelIndex(d->root);
1950 }
1951
1952 /*!
1953     Sets the root model item \a index for the items in the combobox.
1954
1955     \sa rootModelIndex()
1956 */
1957 void QComboBox::setRootModelIndex(const QModelIndex &index)
1958 {
1959     Q_D(QComboBox);
1960     d->root = QPersistentModelIndex(index);
1961     view()->setRootIndex(index);
1962     update();
1963 }
1964
1965 /*!
1966     \property QComboBox::currentIndex
1967     \brief the index of the current item in the combobox.
1968
1969     The current index can change when inserting or removing items.
1970
1971     By default, for an empty combo box or a combo box in which no current
1972     item is set, this property has a value of -1.
1973 */
1974 int QComboBox::currentIndex() const
1975 {
1976     Q_D(const QComboBox);
1977     return d->currentIndex.row();
1978 }
1979
1980 void QComboBox::setCurrentIndex(int index)
1981 {
1982     Q_D(QComboBox);
1983     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
1984     d->setCurrentIndex(mi);
1985 }
1986
1987 void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
1988 {
1989     Q_Q(QComboBox);
1990
1991     QModelIndex normalized;
1992     if (mi.column() != modelColumn)
1993         normalized = model->index(mi.row(), modelColumn, mi.parent());
1994     if (!normalized.isValid())
1995         normalized = mi;    // Fallback to passed index.
1996
1997     bool indexChanged = (normalized != currentIndex);
1998     if (indexChanged)
1999         currentIndex = QPersistentModelIndex(normalized);
2000     if (lineEdit) {
2001         QString newText = q->itemText(normalized.row());
2002         if (lineEdit->text() != newText)
2003             lineEdit->setText(newText);
2004         updateLineEditGeometry();
2005     }
2006     if (indexChanged) {
2007         q->update();
2008         _q_emitCurrentIndexChanged(currentIndex);
2009     }
2010 }
2011
2012 /*!
2013     \property QComboBox::currentText
2014     \brief the text of the current item
2015
2016     By default, for an empty combo box or a combo box in which no current
2017     item is set, this property contains an empty string.
2018 */
2019 QString QComboBox::currentText() const
2020 {
2021     Q_D(const QComboBox);
2022     if (d->lineEdit)
2023         return d->lineEdit->text();
2024     else if (d->currentIndex.isValid())
2025         return d->itemText(d->currentIndex);
2026     else
2027         return QString();
2028 }
2029
2030 /*!
2031     Returns the text for the given \a index in the combobox.
2032 */
2033 QString QComboBox::itemText(int index) const
2034 {
2035     Q_D(const QComboBox);
2036     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2037     return d->itemText(mi);
2038 }
2039
2040 /*!
2041     Returns the icon for the given \a index in the combobox.
2042 */
2043 QIcon QComboBox::itemIcon(int index) const
2044 {
2045     Q_D(const QComboBox);
2046     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2047     return d->itemIcon(mi);
2048 }
2049
2050 /*!
2051    Returns the data for the given \a role in the given \a index in the
2052    combobox, or QVariant::Invalid if there is no data for this role.
2053 */
2054 QVariant QComboBox::itemData(int index, int role) const
2055 {
2056     Q_D(const QComboBox);
2057     QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
2058     return d->model->data(mi, role);
2059 }
2060
2061 /*!
2062   \fn void QComboBox::insertItem(int index, const QString &text, const QVariant &userData)
2063
2064     Inserts the \a text and \a userData (stored in the Qt::UserRole)
2065     into the combobox at the given \a index.
2066
2067     If the index is equal to or higher than the total number of items,
2068     the new item is appended to the list of existing items. If the
2069     index is zero or negative, the new item is prepended to the list
2070     of existing items.
2071
2072   \sa insertItems()
2073 */
2074
2075 /*!
2076
2077     Inserts the \a icon, \a text and \a userData (stored in the
2078     Qt::UserRole) into the combobox at the given \a index.
2079
2080     If the index is equal to or higher than the total number of items,
2081     the new item is appended to the list of existing items. If the
2082     index is zero or negative, the new item is prepended to the list
2083     of existing items.
2084
2085     \sa insertItems()
2086 */
2087 void QComboBox::insertItem(int index, const QIcon &icon, const QString &text, const QVariant &userData)
2088 {
2089     Q_D(QComboBox);
2090     int itemCount = count();
2091     index = qBound(0, index, itemCount);
2092     if (index >= d->maxCount)
2093         return;
2094
2095     // For the common case where we are using the built in QStandardItemModel
2096     // construct a QStandardItem, reducing the number of expensive signals from the model
2097     if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(d->model)) {
2098         QStandardItem *item = new QStandardItem(text);
2099         if (!icon.isNull()) item->setData(icon, Qt::DecorationRole);
2100         if (userData.isValid()) item->setData(userData, Qt::UserRole);
2101         m->insertRow(index, item);
2102         ++itemCount;
2103     } else {
2104         d->inserting = true;
2105         if (d->model->insertRows(index, 1, d->root)) {
2106             QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2107             if (icon.isNull() && !userData.isValid()) {
2108                 d->model->setData(item, text, Qt::EditRole);
2109             } else {
2110                 QMap<int, QVariant> values;
2111                 if (!text.isNull()) values.insert(Qt::EditRole, text);
2112                 if (!icon.isNull()) values.insert(Qt::DecorationRole, icon);
2113                 if (userData.isValid()) values.insert(Qt::UserRole, userData);
2114                 if (!values.isEmpty()) d->model->setItemData(item, values);
2115             }
2116             d->inserting = false;
2117             d->_q_rowsInserted(d->root, index, index);
2118             ++itemCount;
2119         } else {
2120             d->inserting = false;
2121         }
2122     }
2123
2124     if (itemCount > d->maxCount)
2125         d->model->removeRows(itemCount - 1, itemCount - d->maxCount, d->root);
2126 }
2127
2128 /*!
2129     Inserts the strings from the \a list into the combobox as separate items,
2130     starting at the \a index specified.
2131
2132     If the index is equal to or higher than the total number of items, the new items
2133     are appended to the list of existing items. If the index is zero or negative, the
2134     new items are prepended to the list of existing items.
2135
2136     \sa insertItem()
2137     */
2138 void QComboBox::insertItems(int index, const QStringList &list)
2139 {
2140     Q_D(QComboBox);
2141     if (list.isEmpty())
2142         return;
2143     index = qBound(0, index, count());
2144     int insertCount = qMin(d->maxCount - index, list.count());
2145     if (insertCount <= 0)
2146         return;
2147     // For the common case where we are using the built in QStandardItemModel
2148     // construct a QStandardItem, reducing the number of expensive signals from the model
2149     if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(d->model)) {
2150         QList<QStandardItem *> items;
2151         QStandardItem *hiddenRoot = m->invisibleRootItem();
2152         for (int i = 0; i < insertCount; ++i)
2153             items.append(new QStandardItem(list.at(i)));
2154         hiddenRoot->insertRows(index, items);
2155     } else {
2156         d->inserting = true;
2157         if (d->model->insertRows(index, insertCount, d->root)) {
2158             QModelIndex item;
2159             for (int i = 0; i < insertCount; ++i) {
2160                 item = d->model->index(i+index, d->modelColumn, d->root);
2161                 d->model->setData(item, list.at(i), Qt::EditRole);
2162             }
2163             d->inserting = false;
2164             d->_q_rowsInserted(d->root, index, index + insertCount - 1);
2165         } else {
2166             d->inserting = false;
2167         }
2168     }
2169
2170     int mc = count();
2171     if (mc > d->maxCount)
2172         d->model->removeRows(d->maxCount, mc - d->maxCount, d->root);
2173 }
2174
2175 /*!
2176     \since 4.4
2177
2178     Inserts a separator item into the combobox at the given \a index.
2179
2180     If the index is equal to or higher than the total number of items, the new item
2181     is appended to the list of existing items. If the index is zero or negative, the
2182     new item is prepended to the list of existing items.
2183
2184     \sa insertItem()
2185 */
2186 void QComboBox::insertSeparator(int index)
2187 {
2188     Q_D(QComboBox);
2189     int itemCount = count();
2190     index = qBound(0, index, itemCount);
2191     if (index >= d->maxCount)
2192         return;
2193     insertItem(index, QIcon(), QString());
2194     QComboBoxDelegate::setSeparator(d->model, d->model->index(index, 0, d->root));
2195 }
2196
2197 /*!
2198     Removes the item at the given \a index from the combobox.
2199     This will update the current index if the index is removed.
2200
2201     This function does nothing if \a index is out of range.
2202 */
2203 void QComboBox::removeItem(int index)
2204 {
2205     Q_D(QComboBox);
2206     if (index < 0 || index >= count())
2207         return;
2208     d->model->removeRows(index, 1, d->root);
2209 }
2210
2211 /*!
2212     Sets the \a text for the item on the given \a index in the combobox.
2213 */
2214 void QComboBox::setItemText(int index, const QString &text)
2215 {
2216     Q_D(const QComboBox);
2217     QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2218     if (item.isValid()) {
2219         d->model->setData(item, text, Qt::EditRole);
2220     }
2221 }
2222
2223 /*!
2224     Sets the \a icon for the item on the given \a index in the combobox.
2225 */
2226 void QComboBox::setItemIcon(int index, const QIcon &icon)
2227 {
2228     Q_D(const QComboBox);
2229     QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2230     if (item.isValid()) {
2231         d->model->setData(item, icon, Qt::DecorationRole);
2232     }
2233 }
2234
2235 /*!
2236     Sets the data \a role for the item on the given \a index in the combobox
2237     to the specified \a value.
2238 */
2239 void QComboBox::setItemData(int index, const QVariant &value, int role)
2240 {
2241     Q_D(const QComboBox);
2242     QModelIndex item = d->model->index(index, d->modelColumn, d->root);
2243     if (item.isValid()) {
2244         d->model->setData(item, value, role);
2245     }
2246 }
2247
2248 /*!
2249     Returns the list view used for the combobox popup.
2250 */
2251 QAbstractItemView *QComboBox::view() const
2252 {
2253     Q_D(const QComboBox);
2254     return const_cast<QComboBoxPrivate*>(d)->viewContainer()->itemView();
2255 }
2256
2257 /*!
2258   Sets the view to be used in the combobox popup to the given \a
2259   itemView. The combobox takes ownership of the view.
2260
2261   Note: If you want to use the convenience views (like QListWidget,
2262   QTableWidget or QTreeWidget), make sure to call setModel() on the
2263   combobox with the convenience widgets model before calling this
2264   function.
2265 */
2266 void QComboBox::setView(QAbstractItemView *itemView)
2267 {
2268     Q_D(QComboBox);
2269     if (!itemView) {
2270         qWarning("QComboBox::setView: cannot set a 0 view");
2271         return;
2272     }
2273
2274     if (itemView->model() != d->model)
2275         itemView->setModel(d->model);
2276     d->viewContainer()->setItemView(itemView);
2277 }
2278
2279 /*!
2280     \reimp
2281 */
2282 QSize QComboBox::minimumSizeHint() const
2283 {
2284     Q_D(const QComboBox);
2285     return d->recomputeSizeHint(d->minimumSizeHint);
2286 }
2287
2288 /*!
2289     \reimp
2290
2291     This implementation caches the size hint to avoid resizing when
2292     the contents change dynamically. To invalidate the cached value
2293     change the \l sizeAdjustPolicy.
2294 */
2295 QSize QComboBox::sizeHint() const
2296 {
2297     Q_D(const QComboBox);
2298     return d->recomputeSizeHint(d->sizeHint);
2299 }
2300
2301 /*!
2302     Displays the list of items in the combobox. If the list is empty
2303     then the no items will be shown.
2304
2305     If you reimplement this function to show a custom pop-up, make
2306     sure you call hidePopup() to reset the internal state.
2307
2308     \sa hidePopup()
2309 */
2310 void QComboBox::showPopup()
2311 {
2312     Q_D(QComboBox);
2313     if (count() <= 0)
2314         return;
2315
2316 #ifdef QT_KEYPAD_NAVIGATION
2317 #ifndef QT_NO_COMPLETER
2318     if (QApplication::keypadNavigationEnabled() && d->completer) {
2319         // editable combo box is line edit plus completer
2320         setEditFocus(true);
2321         d->completer->complete(); // show popup
2322         return;
2323     }
2324 #endif
2325 #endif
2326
2327     QStyle * const style = this->style();
2328
2329     // set current item and select it
2330     view()->selectionModel()->setCurrentIndex(d->currentIndex,
2331                                               QItemSelectionModel::ClearAndSelect);
2332     QComboBoxPrivateContainer* container = d->viewContainer();
2333     QStyleOptionComboBox opt;
2334     initStyleOption(&opt);
2335     QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt,
2336                                          QStyle::SC_ComboBoxListBoxPopup, this));
2337     QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this));
2338
2339     QPoint below = mapToGlobal(listRect.bottomLeft());
2340     int belowHeight = screen.bottom() - below.y();
2341     QPoint above = mapToGlobal(listRect.topLeft());
2342     int aboveHeight = above.y() - screen.y();
2343     bool boundToScreen = !window()->testAttribute(Qt::WA_DontShowOnScreen);
2344
2345     const bool usePopup = style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this);
2346     {
2347         int listHeight = 0;
2348         int count = 0;
2349         QStack<QModelIndex> toCheck;
2350         toCheck.push(view()->rootIndex());
2351 #ifndef QT_NO_TREEVIEW
2352         QTreeView *treeView = qobject_cast<QTreeView*>(view());
2353         if (treeView && treeView->header() && !treeView->header()->isHidden())
2354             listHeight += treeView->header()->height();
2355 #endif
2356         while (!toCheck.isEmpty()) {
2357             QModelIndex parent = toCheck.pop();
2358             for (int i = 0; i < d->model->rowCount(parent); ++i) {
2359                 QModelIndex idx = d->model->index(i, d->modelColumn, parent);
2360                 if (!idx.isValid())
2361                     continue;
2362                 listHeight += view()->visualRect(idx).height() + container->spacing();
2363 #ifndef QT_NO_TREEVIEW
2364                 if (d->model->hasChildren(idx) && treeView && treeView->isExpanded(idx))
2365                     toCheck.push(idx);
2366 #endif
2367                 ++count;
2368                 if (!usePopup && count >= d->maxVisibleItems) {
2369                     toCheck.clear();
2370                     break;
2371                 }
2372             }
2373         }
2374         listRect.setHeight(listHeight);
2375     }
2376
2377     {
2378         // add the spacing for the grid on the top and the bottom;
2379         int heightMargin = 2*container->spacing();
2380
2381         // add the frame of the container
2382         int marginTop, marginBottom;
2383         container->getContentsMargins(0, &marginTop, 0, &marginBottom);
2384         heightMargin += marginTop + marginBottom;
2385
2386         //add the frame of the view
2387         view()->getContentsMargins(0, &marginTop, 0, &marginBottom);
2388         marginTop += static_cast<QAbstractScrollAreaPrivate *>(QObjectPrivate::get(view()))->top;
2389         marginBottom += static_cast<QAbstractScrollAreaPrivate *>(QObjectPrivate::get(view()))->bottom;
2390         heightMargin += marginTop + marginBottom;
2391
2392         listRect.setHeight(listRect.height() + heightMargin);
2393     }
2394
2395     // Add space for margin at top and bottom if the style wants it.
2396     if (usePopup)
2397         listRect.setHeight(listRect.height() + style->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) * 2);
2398
2399     // Make sure the popup is wide enough to display its contents.
2400     if (usePopup) {
2401         const int diff = d->computeWidthHint() - width();
2402         if (diff > 0)
2403             listRect.setWidth(listRect.width() + diff);
2404     }
2405
2406     //we need to activate the layout to make sure the min/maximum size are set when the widget was not yet show
2407     container->layout()->activate();
2408     //takes account of the minimum/maximum size of the container
2409     listRect.setSize( listRect.size().expandedTo(container->minimumSize())
2410                       .boundedTo(container->maximumSize()));
2411
2412     // make sure the widget fits on screen
2413     if (boundToScreen) {
2414         if (listRect.width() > screen.width() )
2415             listRect.setWidth(screen.width());
2416         if (mapToGlobal(listRect.bottomRight()).x() > screen.right()) {
2417             below.setX(screen.x() + screen.width() - listRect.width());
2418             above.setX(screen.x() + screen.width() - listRect.width());
2419         }
2420         if (mapToGlobal(listRect.topLeft()).x() < screen.x() ) {
2421             below.setX(screen.x());
2422             above.setX(screen.x());
2423         }
2424     }
2425
2426     if (usePopup) {
2427         // Position horizontally.
2428         listRect.moveLeft(above.x());
2429
2430         // Position vertically so the curently selected item lines up
2431         // with the combo box.
2432         const QRect currentItemRect = view()->visualRect(view()->currentIndex());
2433         const int offset = listRect.top() - currentItemRect.top();
2434         listRect.moveTop(above.y() + offset - listRect.top());
2435
2436         // Clamp the listRect height and vertical position so we don't expand outside the
2437         // available screen geometry.This may override the vertical position, but it is more
2438         // important to show as much as possible of the popup.
2439         const int height = !boundToScreen ? listRect.height() : qMin(listRect.height(), screen.height());
2440         listRect.setHeight(height);
2441
2442         if (boundToScreen) {
2443             if (listRect.top() < screen.top())
2444                 listRect.moveTop(screen.top());
2445             if (listRect.bottom() > screen.bottom())
2446                 listRect.moveBottom(screen.bottom());
2447         }
2448     } else if (!boundToScreen || listRect.height() <= belowHeight) {
2449         listRect.moveTopLeft(below);
2450     } else if (listRect.height() <= aboveHeight) {
2451         listRect.moveBottomLeft(above);
2452     } else if (belowHeight >= aboveHeight) {
2453         listRect.setHeight(belowHeight);
2454         listRect.moveTopLeft(below);
2455     } else {
2456         listRect.setHeight(aboveHeight);
2457         listRect.moveBottomLeft(above);
2458     }
2459
2460     if (qApp) {
2461         qApp->inputMethod()->reset();
2462     }
2463
2464     QScrollBar *sb = view()->horizontalScrollBar();
2465     Qt::ScrollBarPolicy policy = view()->horizontalScrollBarPolicy();
2466     bool needHorizontalScrollBar = (policy == Qt::ScrollBarAsNeeded || policy == Qt::ScrollBarAlwaysOn)
2467                                    && sb->minimum() < sb->maximum();
2468     if (needHorizontalScrollBar) {
2469         listRect.adjust(0, 0, 0, sb->height());
2470     }
2471     container->setGeometry(listRect);
2472
2473 #ifndef Q_WS_MAC
2474     const bool updatesEnabled = container->updatesEnabled();
2475 #endif
2476
2477 #if defined(Q_WS_WIN) && !defined(QT_NO_EFFECTS)
2478     bool scrollDown = (listRect.topLeft() == below);
2479     if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo)
2480         && !style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && !window()->testAttribute(Qt::WA_DontShowOnScreen))
2481         qScrollEffect(container, scrollDown ? QEffects::DownScroll : QEffects::UpScroll, 150);
2482 #endif
2483
2484 // Don't disable updates on Mac OS X. Windows are displayed immediately on this platform,
2485 // which means that the window will be visible before the call to container->show() returns.
2486 // If updates are disabled at this point we'll miss our chance at painting the popup
2487 // menu before it's shown, causing flicker since the window then displays the standard gray
2488 // background.
2489 #ifndef Q_WS_MAC
2490     container->setUpdatesEnabled(false);
2491 #endif
2492
2493     container->raise();
2494     container->show();
2495     container->updateScrollers();
2496     view()->setFocus();
2497
2498     view()->scrollTo(view()->currentIndex(),
2499                      style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)
2500                              ? QAbstractItemView::PositionAtCenter
2501                              : QAbstractItemView::EnsureVisible);
2502
2503 #ifndef Q_WS_MAC
2504     container->setUpdatesEnabled(updatesEnabled);
2505 #endif
2506
2507     container->update();
2508 #ifdef QT_KEYPAD_NAVIGATION
2509     if (QApplication::keypadNavigationEnabled())
2510         view()->setEditFocus(true);
2511 #endif
2512 }
2513
2514 /*!
2515     Hides the list of items in the combobox if it is currently visible
2516     and resets the internal state, so that if the custom pop-up was
2517     shown inside the reimplemented showPopup(), then you also need to
2518     reimplement the hidePopup() function to hide your custom pop-up
2519     and call the base class implementation to reset the internal state
2520     whenever your custom pop-up widget is hidden.
2521
2522     \sa showPopup()
2523 */
2524 void QComboBox::hidePopup()
2525 {
2526     Q_D(QComboBox);
2527     if (d->container && d->container->isVisible()) {
2528 #if !defined(QT_NO_EFFECTS)
2529         d->model->blockSignals(true);
2530         d->container->itemView()->blockSignals(true);
2531         d->container->blockSignals(true);
2532         // Flash selected/triggered item (if any).
2533         if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) {
2534             QItemSelectionModel *selectionModel = view() ? view()->selectionModel() : 0;
2535             if (selectionModel && selectionModel->hasSelection()) {
2536                 QEventLoop eventLoop;
2537                 const QItemSelection selection = selectionModel->selection();
2538
2539                 // Deselect item and wait 60 ms.
2540                 selectionModel->select(selection, QItemSelectionModel::Toggle);
2541                 QTimer::singleShot(60, &eventLoop, SLOT(quit()));
2542                 eventLoop.exec();
2543
2544                 // Select item and wait 20 ms.
2545                 selectionModel->select(selection, QItemSelectionModel::Toggle);
2546                 QTimer::singleShot(20, &eventLoop, SLOT(quit()));
2547                 eventLoop.exec();
2548             }
2549         }
2550
2551         // Fade out.
2552         bool needFade = style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
2553         if (needFade) {
2554 #if defined(Q_WS_MAC)
2555             macWindowFade(qt_mac_window_for(d->container));
2556 #endif // Q_WS_MAC
2557             // Other platform implementations welcome :-)
2558         }
2559         d->model->blockSignals(false);
2560         d->container->itemView()->blockSignals(false);
2561         d->container->blockSignals(false);
2562
2563         if (!needFade)
2564 #endif // QT_NO_EFFECTS
2565             // Fade should implicitly hide as well ;-)
2566             d->container->hide();
2567     }
2568 #ifdef QT_KEYPAD_NAVIGATION
2569     if (QApplication::keypadNavigationEnabled() && isEditable() && hasFocus())
2570         setEditFocus(true);
2571 #endif
2572     d->_q_resetButton();
2573 }
2574
2575 /*!
2576     Clears the combobox, removing all items.
2577
2578     Note: If you have set an external model on the combobox this model
2579     will still be cleared when calling this function.
2580 */
2581 void QComboBox::clear()
2582 {
2583     Q_D(QComboBox);
2584     d->model->removeRows(0, d->model->rowCount(d->root), d->root);
2585 #ifndef QT_NO_ACCESSIBILITY
2586         QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
2587 #endif
2588 }
2589
2590 /*!
2591     \fn void QComboBox::clearValidator()
2592
2593     Use setValidator(0) instead.
2594 */
2595
2596 /*!
2597     Clears the contents of the line edit used for editing in the combobox.
2598 */
2599 void QComboBox::clearEditText()
2600 {
2601     Q_D(QComboBox);
2602     if (d->lineEdit)
2603         d->lineEdit->clear();
2604 #ifndef QT_NO_ACCESSIBILITY
2605         QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
2606 #endif
2607 }
2608
2609 /*!
2610     Sets the \a text in the combobox's text edit.
2611 */
2612 void QComboBox::setEditText(const QString &text)
2613 {
2614     Q_D(QComboBox);
2615     if (d->lineEdit)
2616         d->lineEdit->setText(text);
2617 #ifndef QT_NO_ACCESSIBILITY
2618         QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
2619 #endif
2620 }
2621
2622 /*!
2623     \reimp
2624 */
2625 void QComboBox::focusInEvent(QFocusEvent *e)
2626 {
2627     Q_D(QComboBox);
2628     update();
2629     if (d->lineEdit) {
2630         d->lineEdit->event(e);
2631 #ifndef QT_NO_COMPLETER
2632         if (d->lineEdit->completer())
2633             d->lineEdit->completer()->setWidget(this);
2634 #endif
2635     }
2636 }
2637
2638 /*!
2639     \reimp
2640 */
2641 void QComboBox::focusOutEvent(QFocusEvent *e)
2642 {
2643     Q_D(QComboBox);
2644     update();
2645     if (d->lineEdit)
2646         d->lineEdit->event(e);
2647 }
2648
2649 /*! \reimp */
2650 void QComboBox::changeEvent(QEvent *e)
2651 {
2652     Q_D(QComboBox);
2653     switch (e->type()) {
2654     case QEvent::StyleChange:
2655         d->updateDelegate();
2656 #ifdef Q_WS_MAC
2657     case QEvent::MacSizeChange:
2658 #endif
2659         d->sizeHint = QSize(); // invalidate size hint
2660         d->minimumSizeHint = QSize();
2661         d->updateLayoutDirection();
2662         if (d->lineEdit)
2663             d->updateLineEditGeometry();
2664         d->setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
2665
2666         // ### need to update scrollers etc. as well here
2667         break;
2668     case QEvent::EnabledChange:
2669         if (!isEnabled())
2670             hidePopup();
2671         break;
2672     case QEvent::PaletteChange: {
2673         d->updateViewContainerPaletteAndOpacity();
2674         break;
2675     }
2676     case QEvent::FontChange:
2677         d->sizeHint = QSize(); // invalidate size hint
2678         d->viewContainer()->setFont(font());
2679         if (d->lineEdit)
2680             d->updateLineEditGeometry();
2681         break;
2682     default:
2683         break;
2684     }
2685     QWidget::changeEvent(e);
2686 }
2687
2688 /*!
2689     \reimp
2690 */
2691 void QComboBox::resizeEvent(QResizeEvent *)
2692 {
2693     Q_D(QComboBox);
2694     d->updateLineEditGeometry();
2695 }
2696
2697 /*!
2698     \reimp
2699 */
2700 void QComboBox::paintEvent(QPaintEvent *)
2701 {
2702     QStylePainter painter(this);
2703     painter.setPen(palette().color(QPalette::Text));
2704
2705     // draw the combobox frame, focusrect and selected etc.
2706     QStyleOptionComboBox opt;
2707     initStyleOption(&opt);
2708     painter.drawComplexControl(QStyle::CC_ComboBox, opt);
2709
2710     // draw the icon and text
2711     painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
2712 }
2713
2714 /*!
2715     \reimp
2716 */
2717 void QComboBox::showEvent(QShowEvent *e)
2718 {
2719     Q_D(QComboBox);
2720     if (!d->shownOnce && d->sizeAdjustPolicy == QComboBox::AdjustToContentsOnFirstShow) {
2721         d->sizeHint = QSize();
2722         updateGeometry();
2723     }
2724     d->shownOnce = true;
2725     QWidget::showEvent(e);
2726 }
2727
2728 /*!
2729     \reimp
2730 */
2731 void QComboBox::hideEvent(QHideEvent *)
2732 {
2733     hidePopup();
2734 }
2735
2736 /*!
2737     \reimp
2738 */
2739 bool QComboBox::event(QEvent *event)
2740 {
2741     Q_D(QComboBox);
2742     switch(event->type()) {
2743     case QEvent::LayoutDirectionChange:
2744     case QEvent::ApplicationLayoutDirectionChange:
2745         d->updateLayoutDirection();
2746         d->updateLineEditGeometry();
2747         break;
2748     case QEvent::HoverEnter:
2749     case QEvent::HoverLeave:
2750     case QEvent::HoverMove:
2751     if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
2752         d->updateHoverControl(he->pos());
2753         break;
2754     case QEvent::ShortcutOverride:
2755         if (d->lineEdit)
2756             return d->lineEdit->event(event);
2757         break;
2758 #ifdef QT_KEYPAD_NAVIGATION
2759     case QEvent::EnterEditFocus:
2760         if (!d->lineEdit)
2761             setEditFocus(false); // We never want edit focus if we are not editable
2762         else
2763             d->lineEdit->event(event);  //so cursor starts
2764         break;
2765     case QEvent::LeaveEditFocus:
2766         if (d->lineEdit)
2767             d->lineEdit->event(event);  //so cursor stops
2768         break;
2769 #endif
2770     default:
2771         break;
2772     }
2773     return QWidget::event(event);
2774 }
2775
2776 /*!
2777     \reimp
2778 */
2779 void QComboBox::mousePressEvent(QMouseEvent *e)
2780 {
2781     Q_D(QComboBox);
2782     QStyleOptionComboBox opt;
2783     initStyleOption(&opt);
2784     QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(),
2785                                                            this);
2786     if (e->button() == Qt::LeftButton && (sc == QStyle::SC_ComboBoxArrow || !isEditable())
2787         && !d->viewContainer()->isVisible()) {
2788         if (sc == QStyle::SC_ComboBoxArrow)
2789             d->updateArrow(QStyle::State_Sunken);
2790 #ifdef QT_KEYPAD_NAVIGATION
2791         //if the container already exists, then d->viewContainer() is safe to call
2792         if (d->container) {
2793 #endif
2794             // We've restricted the next couple of lines, because by not calling
2795             // viewContainer(), we avoid creating the QComboBoxPrivateContainer.
2796             d->viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval());
2797             d->viewContainer()->initialClickPosition = mapToGlobal(e->pos());
2798 #ifdef QT_KEYPAD_NAVIGATION
2799         }
2800 #endif
2801         showPopup();
2802     } else {
2803 #ifdef QT_KEYPAD_NAVIGATION
2804         if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && d->lineEdit) {
2805             d->lineEdit->event(e);  //so lineedit can move cursor, etc
2806             return;
2807         }
2808 #endif
2809         QWidget::mousePressEvent(e);
2810     }
2811 }
2812
2813 /*!
2814     \reimp
2815 */
2816 void QComboBox::mouseReleaseEvent(QMouseEvent *e)
2817 {
2818     Q_D(QComboBox);
2819     Q_UNUSED(e);
2820     d->updateArrow(QStyle::State_None);
2821 }
2822
2823 /*!
2824     \reimp
2825 */
2826 void QComboBox::keyPressEvent(QKeyEvent *e)
2827 {
2828     Q_D(QComboBox);
2829
2830 #ifndef QT_NO_COMPLETER
2831     if (d->lineEdit
2832         && d->lineEdit->completer()
2833         && d->lineEdit->completer()->popup()
2834         && d->lineEdit->completer()->popup()->isVisible()) {
2835         // provide same autocompletion support as line edit
2836         d->lineEdit->event(e);
2837         return;
2838     }
2839 #endif
2840
2841     enum Move { NoMove=0 , MoveUp , MoveDown , MoveFirst , MoveLast};
2842
2843     Move move = NoMove;
2844     int newIndex = currentIndex();
2845     switch (e->key()) {
2846     case Qt::Key_Up:
2847         if (e->modifiers() & Qt::ControlModifier)
2848             break; // pass to line edit for auto completion
2849     case Qt::Key_PageUp:
2850 #ifdef QT_KEYPAD_NAVIGATION
2851         if (QApplication::keypadNavigationEnabled())
2852             e->ignore();
2853         else
2854 #endif
2855         move = MoveUp;
2856         break;
2857     case Qt::Key_Down:
2858         if (e->modifiers() & Qt::AltModifier) {
2859             showPopup();
2860             return;
2861         } else if (e->modifiers() & Qt::ControlModifier)
2862             break; // pass to line edit for auto completion
2863         // fall through
2864     case Qt::Key_PageDown:
2865 #ifdef QT_KEYPAD_NAVIGATION
2866         if (QApplication::keypadNavigationEnabled())
2867             e->ignore();
2868         else
2869 #endif
2870         move = MoveDown;
2871         break;
2872     case Qt::Key_Home:
2873         if (!d->lineEdit)
2874             move = MoveFirst;
2875         break;
2876     case Qt::Key_End:
2877         if (!d->lineEdit)
2878             move = MoveLast;
2879         break;
2880     case Qt::Key_F4:
2881         if (!e->modifiers()) {
2882             showPopup();
2883             return;
2884         }
2885         break;
2886     case Qt::Key_Space:
2887         if (!d->lineEdit) {
2888             showPopup();
2889             return;
2890         }
2891     case Qt::Key_Enter:
2892     case Qt::Key_Return:
2893     case Qt::Key_Escape:
2894         if (!d->lineEdit)
2895             e->ignore();
2896         break;
2897 #ifdef QT_KEYPAD_NAVIGATION
2898     case Qt::Key_Select:
2899         if (QApplication::keypadNavigationEnabled()
2900                 && (!hasEditFocus() || !d->lineEdit)) {
2901             showPopup();
2902             return;
2903         }
2904         break;
2905     case Qt::Key_Left:
2906     case Qt::Key_Right:
2907         if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
2908             e->ignore();
2909         break;
2910     case Qt::Key_Back:
2911         if (QApplication::keypadNavigationEnabled()) {
2912             if (!hasEditFocus() || !d->lineEdit)
2913                 e->ignore();
2914         } else {
2915             e->ignore(); // let the surounding dialog have it
2916         }
2917         break;
2918 #endif
2919     default:
2920         if (!d->lineEdit) {
2921             if (!e->text().isEmpty())
2922                 d->keyboardSearchString(e->text());
2923             else
2924                 e->ignore();
2925         }
2926     }
2927
2928     if (move != NoMove) {
2929         e->accept();
2930         switch (move) {
2931         case MoveFirst:
2932             newIndex = -1;
2933         case MoveDown:
2934             newIndex++;
2935             while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2936                 newIndex++;
2937             break;
2938         case MoveLast:
2939             newIndex = count();
2940         case MoveUp:
2941             newIndex--;
2942             while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2943                 newIndex--;
2944             break;
2945         default:
2946             e->ignore();
2947             break;
2948         }
2949
2950         if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2951             setCurrentIndex(newIndex);
2952             d->emitActivated(d->currentIndex);
2953         }
2954     } else if (d->lineEdit) {
2955         d->lineEdit->event(e);
2956     }
2957 }
2958
2959
2960 /*!
2961     \reimp
2962 */
2963 void QComboBox::keyReleaseEvent(QKeyEvent *e)
2964 {
2965     Q_D(QComboBox);
2966     if (d->lineEdit)
2967         d->lineEdit->event(e);
2968 }
2969
2970 /*!
2971     \reimp
2972 */
2973 #ifndef QT_NO_WHEELEVENT
2974 void QComboBox::wheelEvent(QWheelEvent *e)
2975 {
2976     Q_D(QComboBox);
2977     if (!d->viewContainer()->isVisible()) {
2978         int newIndex = currentIndex();
2979
2980         if (e->delta() > 0) {
2981             newIndex--;
2982             while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2983                 newIndex--;
2984         } else {
2985             newIndex++;
2986             while ((newIndex < count()) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))
2987                 newIndex++;
2988         }
2989
2990         if (newIndex >= 0 && newIndex < count() && newIndex != currentIndex()) {
2991             setCurrentIndex(newIndex);
2992             d->emitActivated(d->currentIndex);
2993         }
2994         e->accept();
2995     }
2996 }
2997 #endif
2998
2999 #ifndef QT_NO_CONTEXTMENU
3000 /*!
3001     \reimp
3002 */
3003 void QComboBox::contextMenuEvent(QContextMenuEvent *e)
3004 {
3005     Q_D(QComboBox);
3006     if (d->lineEdit) {
3007         Qt::ContextMenuPolicy p = d->lineEdit->contextMenuPolicy();
3008         d->lineEdit->setContextMenuPolicy(Qt::DefaultContextMenu);
3009         d->lineEdit->event(e);
3010         d->lineEdit->setContextMenuPolicy(p);
3011     }
3012 }
3013 #endif // QT_NO_CONTEXTMENU
3014
3015 void QComboBoxPrivate::keyboardSearchString(const QString &text)
3016 {
3017     // use keyboardSearch from the listView so we do not duplicate code
3018     QAbstractItemView *view = viewContainer()->itemView();
3019     view->setCurrentIndex(currentIndex);
3020     int currentRow = view->currentIndex().row();
3021     view->keyboardSearch(text);
3022     if (currentRow != view->currentIndex().row()) {
3023         setCurrentIndex(view->currentIndex());
3024         emitActivated(currentIndex);
3025     }
3026 }
3027
3028 void QComboBoxPrivate::modelChanged()
3029 {
3030     Q_Q(QComboBox);
3031
3032     if (sizeAdjustPolicy == QComboBox::AdjustToContents) {
3033         sizeHint = QSize();
3034         adjustComboBoxSize();
3035         q->updateGeometry();
3036     }
3037 }
3038
3039 /*!
3040     \reimp
3041 */
3042 void QComboBox::inputMethodEvent(QInputMethodEvent *e)
3043 {
3044     Q_D(QComboBox);
3045     if (d->lineEdit) {
3046         d->lineEdit->event(e);
3047     } else {
3048         if (!e->commitString().isEmpty())
3049             d->keyboardSearchString(e->commitString());
3050         else
3051             e->ignore();
3052     }
3053 }
3054
3055 /*!
3056     \reimp
3057 */
3058 QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query) const
3059 {
3060     Q_D(const QComboBox);
3061     if (d->lineEdit)
3062         return d->lineEdit->inputMethodQuery(query);
3063     return QWidget::inputMethodQuery(query);
3064 }
3065
3066 /*!
3067     \fn bool QComboBox::editable() const
3068
3069     Use isEditable() instead.
3070 */
3071
3072 /*!
3073     \fn void QComboBox::insertItem(const QPixmap &pixmap, int index)
3074
3075     Use an insertItem() function that takes a QIcon instead, for
3076     example, insertItem(index, QIcon(pixmap)).
3077 */
3078
3079 /*!
3080     \fn void QComboBox::insertItem(const QPixmap &pixmap, const QString &text, int index)
3081
3082     Use an insertItem() function that takes a QIcon instead, for
3083     example, insertItem(index, QIcon(pixmap), text).
3084
3085     \sa insertItems()
3086 */
3087
3088 /*!
3089     \fn void QComboBox::changeItem(const QString &text, int index)
3090
3091     Use setItemText() instead.
3092 */
3093
3094 /*!
3095     \fn void QComboBox::changeItem(const QPixmap &pixmap, int index)
3096
3097     Use setItemIcon() instead, for example,
3098     setItemIcon(index, QIcon(pixmap)).
3099 */
3100
3101 /*!
3102     \fn void QComboBox::changeItem(const QPixmap &pixmap, const QString &text, int index)
3103
3104     Use setItem() instead, for example, setItem(index, QIcon(pixmap),text).
3105 */
3106
3107 /*!
3108     \fn void QComboBox::addItem(const QString &text, const QVariant &userData)
3109
3110     Adds an item to the combobox with the given \a text, and
3111     containing the specified \a userData (stored in the Qt::UserRole).
3112     The item is appended to the list of existing items.
3113 */
3114
3115 /*!
3116     \fn void QComboBox::addItem(const QIcon &icon, const QString &text,
3117                                 const QVariant &userData)
3118
3119     Adds an item to the combobox with the given \a icon and \a text,
3120     and containing the specified \a userData (stored in the
3121     Qt::UserRole). The item is appended to the list of existing items.
3122 */
3123
3124 /*!
3125     \fn void QComboBox::addItems(const QStringList &texts)
3126
3127     Adds each of the strings in the given \a texts to the combobox. Each item
3128     is appended to the list of existing items in turn.
3129 */
3130
3131 /*!
3132     \fn void QComboBox::editTextChanged(const QString &text)
3133
3134     This signal is emitted when the text in the combobox's line edit
3135     widget is changed. The new text is specified by \a text.
3136 */
3137
3138 /*!
3139     \property QComboBox::frame
3140     \brief whether the combo box draws itself with a frame
3141
3142
3143     If enabled (the default) the combo box draws itself inside a
3144     frame, otherwise the combo box draws itself without any frame.
3145 */
3146 bool QComboBox::hasFrame() const
3147 {
3148     Q_D(const QComboBox);
3149     return d->frame;
3150 }
3151
3152
3153 void QComboBox::setFrame(bool enable)
3154 {
3155     Q_D(QComboBox);
3156     d->frame = enable;
3157     update();
3158     updateGeometry();
3159 }
3160
3161 /*!
3162     \property QComboBox::modelColumn
3163     \brief the column in the model that is visible.
3164
3165     If set prior to populating the combo box, the pop-up view will
3166     not be affected and will show the first column (using this property's
3167     default value).
3168
3169     By default, this property has a value of 0.
3170 */
3171 int QComboBox::modelColumn() const
3172 {
3173     Q_D(const QComboBox);
3174     return d->modelColumn;
3175 }
3176
3177 void QComboBox::setModelColumn(int visibleColumn)
3178 {
3179     Q_D(QComboBox);
3180     d->modelColumn = visibleColumn;
3181     QListView *lv = qobject_cast<QListView *>(d->viewContainer()->itemView());
3182     if (lv)
3183         lv->setModelColumn(visibleColumn);
3184 #ifndef QT_NO_COMPLETER
3185     if (d->lineEdit && d->lineEdit->completer()
3186         && d->lineEdit->completer() == d->completer)
3187         d->lineEdit->completer()->setCompletionColumn(visibleColumn);
3188 #endif
3189     setCurrentIndex(currentIndex()); //update the text to the text of the new column;
3190 }
3191
3192 /*!
3193     \fn int QComboBox::currentItem() const
3194
3195     Use currentIndex() instead.
3196 */
3197
3198 /*!
3199     \fn void QComboBox::setCurrentItem(int)
3200
3201     Use setCurrentIndex(int) instead.
3202 */
3203
3204 /*!
3205     \fn void QComboBox::popup()
3206
3207     Use showPopup() instead.
3208 */
3209
3210 /*!
3211     \fn void QComboBox::textChanged(const QString &text)
3212
3213     Use the editTextChanged(const QString &text) signal instead.
3214 */
3215
3216 QT_END_NAMESPACE
3217
3218 #include "moc_qcombobox.cpp"
3219
3220 #endif // QT_NO_COMBOBOX