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