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