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