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