1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
44 #include "qcombobox.h"
45 #include <private/qcombobox_p.h>
46 #include <private/qguiapplication_p.h>
47 #include <qplatformtheme_qpa.h>
49 #include <qfontcombobox.h>
50 #include <qdesktopwidget.h>
51 #include <qapplication.h>
52 #include <qpushbutton.h>
55 #include <qlineedit.h>
56 #include <qlistview.h>
57 #include <qheaderview.h>
58 #include <qlistwidget.h>
59 #include <qtreewidget.h>
60 #include <qtablewidget.h>
61 #include <qscrollbar.h>
62 #include <qboxlayout.h>
64 #include <qmacstyle_mac.h>
65 #elif defined Q_WS_X11
66 #include <private/qt_x11_p.h>
69 #include <qstandarditemmodel.h>
70 #include <qstringlistmodel.h>
71 #include <qcombobox.h>
72 #include <qpushbutton.h>
74 #include <qstringlist.h>
75 #include <qvalidator.h>
76 #include <qcompleter.h>
77 #ifndef QT_NO_STYLE_CLEANLOOKS
78 #include <qcleanlooksstyle.h>
80 #include <qabstractitemview.h>
81 #include <qstyleditemdelegate.h>
82 #ifndef QT_NO_STYLE_WINDOWS
83 #include <qwindowsstyle.h>
86 class tst_QComboBox : public QObject
96 void cleanupTestCase();
102 void ensureReturnIsIgnored();
105 void sizeAdjustPolicy();
107 void insertPolicy_data();
109 void virtualAutocompletion();
110 void autoCompletionCaseSensitivity();
112 void currentIndex_data();
114 void insertItems_data();
116 void insertItem_data();
118 void insertOnCurrentIndex();
119 void textpixmapdata_data();
120 void textpixmapdata();
121 void editTextChanged();
125 void setCurrentIndex();
126 void convenienceViews();
127 void findText_data();
129 void flaggedItems_data();
132 void mouseWheel_data();
134 void layoutDirection();
135 void itemListPosition();
136 void separatorItem_data();
137 void separatorItem();
138 #ifndef QT_NO_STYLE_CLEANLOOKS
139 void task190351_layout();
140 void task191329_size();
142 void task166349_setEditableOnReturn();
143 void task190205_setModelAdjustToContents();
144 void task248169_popupWithMinimalSize();
145 void task247863_keyBoardSelection();
146 void task220195_keyBoardSelection2();
147 void setModelColumn();
148 void noScrollbar_data();
150 void setItemDelegate();
151 void task253944_itemDelegateIsReset();
152 void subControlRectsWithOffset_data();
153 void subControlRectsWithOffset();
154 #ifndef QT_NO_STYLE_WINDOWS
155 void task260974_menuItemRectangleForComboBoxPopup();
159 void keyBoardNavigationWithMouse();
160 void task_QTBUG_1071_changingFocusEmitsActivated();
161 void maxVisibleItems();
162 void task_QTBUG_10491_currentIndexAndModelColumn();
165 void onEditTextChanged( const QString &newString );
168 QComboBox *testWidget;
175 class MyAbstractItemDelegate : public QAbstractItemDelegate
178 MyAbstractItemDelegate() : QAbstractItemDelegate() {};
179 void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
180 QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
183 class MyAbstractItemModel: public QAbstractItemModel
186 MyAbstractItemModel() : QAbstractItemModel() {};
187 QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); }
188 QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
189 int rowCount(const QModelIndex &) const { return 0; }
190 int columnCount(const QModelIndex &) const { return 0; }
191 bool hasChildren(const QModelIndex &) const { return false; }
192 QVariant data(const QModelIndex &, int) const { return QVariant(); }
193 bool setData(const QModelIndex &, const QVariant &, int) { return false; }
194 bool insertRows(int, int, const QModelIndex &) { return false; }
195 bool insertColumns(int, int, const QModelIndex &) { return false; }
196 void setPersistent(const QModelIndex &, const QModelIndex &) {}
197 bool removeRows (int, int, const QModelIndex &) { return false; }
198 bool removeColumns(int, int, const QModelIndex &) { return false; }
202 class MyAbstractItemView : public QAbstractItemView
205 MyAbstractItemView() : QAbstractItemView() {}
206 QRect visualRect(const QModelIndex &) const { return QRect(); }
207 void scrollTo(const QModelIndex &, ScrollHint) {}
208 QModelIndex indexAt(const QPoint &) const { return QModelIndex(); }
210 QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers) { return QModelIndex(); }
211 int horizontalOffset() const { return 0; }
212 int verticalOffset() const { return 0; }
213 bool isIndexHidden(const QModelIndex &) const { return false; }
214 void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) {}
215 QRegion visualRegionForSelection(const QItemSelection &) const { return QRegion(); }
218 // Testing get/set functions
219 void tst_QComboBox::getSetCheck()
222 // int QComboBox::maxVisibleItems()
223 // void QComboBox::setMaxVisibleItems(int)
224 obj1.setMaxVisibleItems(100);
225 QCOMPARE(100, obj1.maxVisibleItems());
226 obj1.setMaxVisibleItems(0);
227 QCOMPARE(obj1.maxVisibleItems(), 0);
228 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxVisibleItems: "
229 "Invalid max visible items (-2147483648) must be >= 0");
230 obj1.setMaxVisibleItems(INT_MIN);
231 QCOMPARE(obj1.maxVisibleItems(), 0); // Cannot be set to something negative => old value
232 obj1.setMaxVisibleItems(INT_MAX);
233 QCOMPARE(INT_MAX, obj1.maxVisibleItems());
235 // int QComboBox::maxCount()
236 // void QComboBox::setMaxCount(int)
238 QCOMPARE(0, obj1.maxCount());
240 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxCount: Invalid count (-2147483648) must be >= 0");
241 obj1.setMaxCount(INT_MIN);
242 QCOMPARE(0, obj1.maxCount()); // Setting a value below 0 makes no sense, and shouldn't be allowed
244 obj1.setMaxCount(INT_MAX);
245 QCOMPARE(INT_MAX, obj1.maxCount());
247 // bool QComboBox::autoCompletion()
248 // void QComboBox::setAutoCompletion(bool)
249 obj1.setAutoCompletion(false);
250 QCOMPARE(false, obj1.autoCompletion());
251 obj1.setAutoCompletion(true);
252 QCOMPARE(true, obj1.autoCompletion());
254 // bool QComboBox::duplicatesEnabled()
255 // void QComboBox::setDuplicatesEnabled(bool)
256 obj1.setDuplicatesEnabled(false);
257 QCOMPARE(false, obj1.duplicatesEnabled());
258 obj1.setDuplicatesEnabled(true);
259 QCOMPARE(true, obj1.duplicatesEnabled());
261 // InsertPolicy QComboBox::insertPolicy()
262 // void QComboBox::setInsertPolicy(InsertPolicy)
263 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::NoInsert));
264 QCOMPARE(QComboBox::InsertPolicy(QComboBox::NoInsert), obj1.insertPolicy());
265 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtTop));
266 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtTop), obj1.insertPolicy());
267 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtCurrent));
268 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtCurrent), obj1.insertPolicy());
269 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtBottom));
270 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtBottom), obj1.insertPolicy());
271 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAfterCurrent));
272 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAfterCurrent), obj1.insertPolicy());
273 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertBeforeCurrent));
274 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertBeforeCurrent), obj1.insertPolicy());
275 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAlphabetically));
276 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAlphabetically), obj1.insertPolicy());
278 // SizeAdjustPolicy QComboBox::sizeAdjustPolicy()
279 // void QComboBox::setSizeAdjustPolicy(SizeAdjustPolicy)
280 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents));
281 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents), obj1.sizeAdjustPolicy());
282 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow));
283 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow), obj1.sizeAdjustPolicy());
284 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength));
285 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength), obj1.sizeAdjustPolicy());
286 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon));
287 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon), obj1.sizeAdjustPolicy());
289 // int QComboBox::minimumContentsLength()
290 // void QComboBox::setMinimumContentsLength(int)
291 obj1.setMinimumContentsLength(0);
292 QCOMPARE(0, obj1.minimumContentsLength());
293 obj1.setMinimumContentsLength(100);
294 QCOMPARE(100, obj1.minimumContentsLength());
295 obj1.setMinimumContentsLength(INT_MIN);
296 QCOMPARE(100, obj1.minimumContentsLength()); // Cannot be set to something negative => old value
297 obj1.setMinimumContentsLength(INT_MAX);
298 QCOMPARE(INT_MAX, obj1.minimumContentsLength());
300 // QLineEdit * QComboBox::lineEdit()
301 // void QComboBox::setLineEdit(QLineEdit *)
302 QLineEdit *var8 = new QLineEdit(0);
303 obj1.setLineEdit(var8);
304 QCOMPARE(var8, obj1.lineEdit());
305 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setLineEdit: cannot set a 0 line edit");
306 obj1.setLineEdit((QLineEdit *)0);
307 QCOMPARE(var8, obj1.lineEdit());
308 // delete var8; // No delete, since QComboBox takes ownership
310 // const QValidator * QComboBox::validator()
311 // void QComboBox::setValidator(const QValidator *)
312 QIntValidator *var9 = new QIntValidator(0);
313 obj1.setValidator(var9);
314 QCOMPARE(obj1.validator(), (const QValidator *)var9);
315 obj1.setValidator((QValidator *)0);
316 QCOMPARE(obj1.validator(), (const QValidator *)0);
319 // QAbstractItemDelegate * QComboBox::itemDelegate()
320 // void QComboBox::setItemDelegate(QAbstractItemDelegate *)
321 MyAbstractItemDelegate *var10 = new MyAbstractItemDelegate;
322 obj1.setItemDelegate(var10);
323 QCOMPARE(obj1.itemDelegate(), (QAbstractItemDelegate *)var10);
324 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setItemDelegate: cannot set a 0 delegate");
325 obj1.setItemDelegate((QAbstractItemDelegate *)0);
326 QCOMPARE(obj1.itemDelegate(), (QAbstractItemDelegate *)var10);
327 // delete var10; // No delete, since QComboBox takes ownership
329 // QAbstractItemModel * QComboBox::model()
330 // void QComboBox::setModel(QAbstractItemModel *)
331 MyAbstractItemModel *var11 = new MyAbstractItemModel;
332 obj1.setModel(var11);
333 QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
334 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setModel: cannot set a 0 model");
335 obj1.setModel((QAbstractItemModel *)0);
336 QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
340 // int QComboBox::modelColumn()
341 // void QComboBox::setModelColumn(int)
342 obj1.setModelColumn(0);
343 QCOMPARE(0, obj1.modelColumn());
344 obj1.setModelColumn(INT_MIN);
345 // QCOMPARE(0, obj1.modelColumn()); // Cannot be set to something negative => column 0
346 obj1.setModelColumn(INT_MAX);
347 QCOMPARE(INT_MAX, obj1.modelColumn());
348 obj1.setModelColumn(0); // back to normal
350 // QAbstractItemView * QComboBox::view()
351 // void QComboBox::setView(QAbstractItemView *)
352 MyAbstractItemView *var13 = new MyAbstractItemView;
354 QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
355 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setView: cannot set a 0 view");
356 obj1.setView((QAbstractItemView *)0);
357 QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
360 // int QComboBox::currentIndex()
361 // void QComboBox::setCurrentIndex(int)
362 obj1.setEditable(false);
363 obj1.setCurrentIndex(0);
364 QCOMPARE(-1, obj1.currentIndex());
365 obj1.setCurrentIndex(INT_MIN);
366 QCOMPARE(-1, obj1.currentIndex());
367 obj1.setCurrentIndex(INT_MAX);
368 QCOMPARE(-1, obj1.currentIndex());
369 obj1.addItems(QStringList() << "1" << "2" << "3" << "4" << "5");
370 obj1.setCurrentIndex(0);
371 QCOMPARE(0, obj1.currentIndex()); // Valid
372 obj1.setCurrentIndex(INT_MIN);
373 QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
374 obj1.setCurrentIndex(4);
375 QCOMPARE(4, obj1.currentIndex()); // Valid
376 obj1.setCurrentIndex(INT_MAX);
377 QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
380 typedef QList<QVariant> VariantList;
381 typedef QList<QIcon> IconList;
383 Q_DECLARE_METATYPE(VariantList)
384 Q_DECLARE_METATYPE(IconList)
385 Q_DECLARE_METATYPE(QComboBox::InsertPolicy)
387 tst_QComboBox::tst_QComboBox()
389 qRegisterMetaType<QModelIndex>("QModelIndex");
393 tst_QComboBox::~tst_QComboBox()
398 void tst_QComboBox::initTestCase()
400 // Create the test class
401 parent = new QWidget(0, Qt::Window);
402 parent->setObjectName("parent");
403 parent->resize(400, 400);
404 testWidget = new QComboBox(parent);
405 testWidget->setObjectName("testObject");
406 testWidget->setGeometry(0, 0, 100, 100);
409 connect(testWidget, SIGNAL(editTextChanged(const QString&)),
410 this, SLOT(onEditTextChanged(const QString&)));
414 void tst_QComboBox::cleanupTestCase()
421 void tst_QComboBox::init()
423 // all tests starts with a clean non-editable combobox
424 testWidget->setEditable(false);
426 #ifdef Q_OS_WINCE //disable magic for WindowsCE
427 qApp->setAutoMaximizeThreshold(-1);
431 void tst_QComboBox::cleanup()
437 void tst_QComboBox::setEditable()
439 // make sure we have no lineedit
440 QVERIFY(!testWidget->lineEdit());
441 // test setEditable(true)
442 testWidget->setEditable(true);
443 QVERIFY(testWidget->lineEdit());
444 testWidget->addItem("foo");
445 QCOMPARE(testWidget->lineEdit()->text(), QString("foo"));
446 // test setEditable(false)
448 QLineEdit *lineEdit = testWidget->lineEdit();
449 // line edit is visible when combobox is editable
450 QVERIFY(lineEdit->isVisible());
451 testWidget->setEditable(false);
452 QVERIFY(!testWidget->lineEdit());
453 // line edit should have been explicitly hidden when editable was turned off
454 QVERIFY(!lineEdit->isVisible());
458 void tst_QComboBox::setPalette()
461 if (qobject_cast<QMacStyle *>(testWidget->style())) {
462 QSKIP("This test doesn't make sense for pixmap-based styles");
465 QPalette pal = testWidget->palette();
466 pal.setColor(QPalette::Base, Qt::red);
467 testWidget->setPalette(pal);
468 testWidget->setEditable(!testWidget->isEditable());
470 pal.setColor(QPalette::Base, Qt::blue);
471 testWidget->setPalette(pal);
473 const QObjectList comboChildren = testWidget->children();
474 for (int i = 0; i < comboChildren.size(); ++i) {
475 QObject *o = comboChildren.at(i);
476 if (o->isWidgetType()) {
477 QVERIFY(((QWidget*)o)->palette() == pal);
481 testWidget->setEditable(true);
482 pal.setColor(QPalette::Base, Qt::red);
483 //Setting it on the lineedit should be separate form the combo
484 testWidget->lineEdit()->setPalette(pal);
485 QVERIFY(testWidget->palette() != pal);
486 QVERIFY(testWidget->lineEdit()->palette() == pal);
487 pal.setColor(QPalette::Base, Qt::green);
488 //Setting it on the combo directly should override lineedit
489 testWidget->setPalette(pal);
490 QVERIFY(testWidget->palette() == pal);
491 QVERIFY(testWidget->lineEdit()->palette() == pal);
494 void tst_QComboBox::sizeAdjustPolicy()
496 // test that adding new items will not change the sizehint for AdjustToContentsOnFirstShow
497 QVERIFY(!testWidget->count());
498 QVERIFY(testWidget->sizeAdjustPolicy() == QComboBox::AdjustToContentsOnFirstShow);
499 QVERIFY(testWidget->isVisible());
500 QSize firstShow = testWidget->sizeHint();
501 testWidget->addItem("normal item");
502 QCOMPARE(testWidget->sizeHint(), firstShow);
504 // check that with minimumContentsLength/AdjustToMinimumContentsLength sizehint changes
505 testWidget->setMinimumContentsLength(30);
506 QCOMPARE(testWidget->sizeHint(), firstShow);
507 testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
508 QSize minimumContentsLength = testWidget->sizeHint();
509 QVERIFY(minimumContentsLength.width() > firstShow.width());
510 testWidget->setMinimumContentsLength(60);
511 QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
513 // check that with minimumContentsLength/AdjustToMinimumContentsLengthWithIcon sizehint changes
514 testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
515 testWidget->setMinimumContentsLength(30);
516 minimumContentsLength = testWidget->sizeHint();
517 QVERIFY(minimumContentsLength.width() > firstShow.width());
518 testWidget->setMinimumContentsLength(60);
519 QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
520 minimumContentsLength = testWidget->sizeHint();
521 testWidget->setIconSize(QSize(128,128));
522 QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
524 // check AdjustToContents changes with content
525 testWidget->setSizeAdjustPolicy(QComboBox::AdjustToContents);
526 QSize content = testWidget->sizeHint();
527 testWidget->addItem("small");
528 QCOMPARE(testWidget->sizeHint(), content);
529 testWidget->addItem("looooooooooooooooooooooong item");
530 // minimumContentsLength() > sizeof("looooooooooooooooooooooong item"), so the sizeHint()
532 QCOMPARE(testWidget->sizeHint(), content);
533 // over 60 characters (cf. setMinimumContentsLength() call above)
534 testWidget->addItem("loooooooooooooooooooooooooooooooooooooooooooooo"
535 "ooooooooooooooooooooooooooooooooooooooooooooooo"
536 "ooooooooooooooooooooooooooooong item");
537 QVERIFY(testWidget->sizeHint().width() > content.width());
539 // check AdjustToContents also shrinks when item changes
540 content = testWidget->sizeHint();
541 for (int i=0; i<testWidget->count(); ++i)
542 testWidget->setItemText(i, "XXXXXXXXXX");
543 QVERIFY(testWidget->sizeHint().width() < content.width());
545 // check AdjustToContents shrinks when items are removed
546 content = testWidget->sizeHint();
547 while (testWidget->count())
548 testWidget->removeItem(0);
549 QCOMPARE(testWidget->sizeHint(), content);
550 testWidget->setMinimumContentsLength(0);
551 QVERIFY(testWidget->sizeHint().width() < content.width());
554 void tst_QComboBox::clear()
556 // first non editable combobox
557 testWidget->addItem("foo");
558 testWidget->addItem("bar");
559 QVERIFY(testWidget->count() > 0);
560 QCOMPARE(testWidget->currentIndex(), 0);
563 QCOMPARE(testWidget->count(), 0);
564 QCOMPARE(testWidget->currentIndex(), -1);
565 QVERIFY(testWidget->currentText().isEmpty());
567 // then editable combobox
569 testWidget->setEditable(true);
570 testWidget->addItem("foo");
571 testWidget->addItem("bar");
572 QVERIFY(testWidget->count() > 0);
573 QCOMPARE(testWidget->currentIndex(), 0);
574 QVERIFY(testWidget->lineEdit());
575 QVERIFY(!testWidget->lineEdit()->text().isEmpty());
577 QCOMPARE(testWidget->count(), 0);
578 QCOMPARE(testWidget->currentIndex(), -1);
579 QVERIFY(testWidget->currentText().isEmpty());
580 QVERIFY(testWidget->lineEdit()->text().isEmpty());
583 void tst_QComboBox::insertPolicy_data()
585 QTest::addColumn<QStringList>("initialEntries");
586 QTest::addColumn<QComboBox::InsertPolicy>("insertPolicy");
587 QTest::addColumn<int>("currentIndex");
588 QTest::addColumn<QString>("userInput");
589 QTest::addColumn<QStringList>("result");
591 /* Each insertPolicy should test at least:
594 five initial entries, current is first item
595 five initial entries, current is third item
596 five initial entries, current is last item
599 /* QComboBox::NoInsert - the string will not be inserted into the combobox.
600 QComboBox::InsertAtTop - insert the string as the first item in the combobox.
601 QComboBox::InsertAtCurrent - replace the previously selected item with the string the user has entered.
602 QComboBox::InsertAtBottom - insert the string as the last item in the combobox.
603 QComboBox::InsertAfterCurrent - insert the string after the previously selected item.
604 QComboBox::InsertBeforeCurrent - insert the string before the previously selected item.
605 QComboBox::InsertAlphabetically - insert the string at the alphabetic position.
608 QStringList oneEntry("One");
609 QStringList fiveEntries;
610 fiveEntries << "One" << "Two" << "Three" << "Four" << "Five";
611 QString input("insert");
614 QTest::newRow("NoInsert-NoInitial") << initial << QComboBox::NoInsert << 0 << input << initial;
615 QTest::newRow("NoInsert-OneInitial") << oneEntry << QComboBox::NoInsert << 0 << input << oneEntry;
616 QTest::newRow("NoInsert-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::NoInsert << 0 << input << fiveEntries;
617 QTest::newRow("NoInsert-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::NoInsert << 2 << input << fiveEntries;
618 QTest::newRow("NoInsert-FiveInitial-LastCurrent") << fiveEntries << QComboBox::NoInsert << 4 << input << fiveEntries;
622 QStringList initialAtTop("insert");
623 QStringList oneAtTop;
624 oneAtTop << "insert" << "One";
625 QStringList fiveAtTop;
626 fiveAtTop << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
628 QTest::newRow("AtTop-NoInitial") << initial << QComboBox::InsertAtTop << 0 << input << initialAtTop;
629 QTest::newRow("AtTop-OneInitial") << oneEntry << QComboBox::InsertAtTop << 0 << input << oneAtTop;
630 QTest::newRow("AtTop-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtTop << 0 << input << fiveAtTop;
631 QTest::newRow("AtTop-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtTop << 2 << input << fiveAtTop;
632 QTest::newRow("AtTop-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtTop << 4 << input << fiveAtTop;
636 QStringList initialAtCurrent("insert");
637 QStringList oneAtCurrent("insert");
638 QStringList fiveAtCurrentFirst;
639 fiveAtCurrentFirst << "insert" << "Two" << "Three" << "Four" << "Five";
640 QStringList fiveAtCurrentThird;
641 fiveAtCurrentThird << "One" << "Two" << "insert" << "Four" << "Five";
642 QStringList fiveAtCurrentLast;
643 fiveAtCurrentLast << "One" << "Two" << "Three" << "Four" << "insert";
645 QTest::newRow("AtCurrent-NoInitial") << initial << QComboBox::InsertAtCurrent << 0 << input << initialAtCurrent;
646 QTest::newRow("AtCurrent-OneInitial") << oneEntry << QComboBox::InsertAtCurrent << 0 << input << oneAtCurrent;
647 QTest::newRow("AtCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 0 << input << fiveAtCurrentFirst;
648 QTest::newRow("AtCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 2 << input << fiveAtCurrentThird;
649 QTest::newRow("AtCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 4 << input << fiveAtCurrentLast;
653 QStringList initialAtBottom("insert");
654 QStringList oneAtBottom;
655 oneAtBottom << "One" << "insert";
656 QStringList fiveAtBottom;
657 fiveAtBottom << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
659 QTest::newRow("AtBottom-NoInitial") << initial << QComboBox::InsertAtBottom << 0 << input << initialAtBottom;
660 QTest::newRow("AtBottom-OneInitial") << oneEntry << QComboBox::InsertAtBottom << 0 << input << oneAtBottom;
661 QTest::newRow("AtBottom-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtBottom << 0 << input << fiveAtBottom;
662 QTest::newRow("AtBottom-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtBottom << 2 << input << fiveAtBottom;
663 QTest::newRow("AtBottom-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtBottom << 4 << input << fiveAtBottom;
667 QStringList initialAfterCurrent("insert");
668 QStringList oneAfterCurrent;
669 oneAfterCurrent << "One" << "insert";
670 QStringList fiveAfterCurrentFirst;
671 fiveAfterCurrentFirst << "One" << "insert" << "Two" << "Three" << "Four" << "Five";
672 QStringList fiveAfterCurrentThird;
673 fiveAfterCurrentThird << "One" << "Two" << "Three" << "insert" << "Four" << "Five";
674 QStringList fiveAfterCurrentLast;
675 fiveAfterCurrentLast << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
677 QTest::newRow("AfterCurrent-NoInitial") << initial << QComboBox::InsertAfterCurrent << 0 << input << initialAfterCurrent;
678 QTest::newRow("AfterCurrent-OneInitial") << oneEntry << QComboBox::InsertAfterCurrent << 0 << input << oneAfterCurrent;
679 QTest::newRow("AfterCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 0 << input << fiveAfterCurrentFirst;
680 QTest::newRow("AfterCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 2 << input << fiveAfterCurrentThird;
681 QTest::newRow("AfterCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 4 << input << fiveAfterCurrentLast;
685 QStringList initialBeforeCurrent("insert");
686 QStringList oneBeforeCurrent;
687 oneBeforeCurrent << "insert" << "One";
688 QStringList fiveBeforeCurrentFirst;
689 fiveBeforeCurrentFirst << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
690 QStringList fiveBeforeCurrentThird;
691 fiveBeforeCurrentThird << "One" << "Two" << "insert" << "Three" << "Four" << "Five";
692 QStringList fiveBeforeCurrentLast;
693 fiveBeforeCurrentLast << "One" << "Two" << "Three" << "Four" << "insert" << "Five";
695 QTest::newRow("BeforeCurrent-NoInitial") << initial << QComboBox::InsertBeforeCurrent << 0 << input << initialBeforeCurrent;
696 QTest::newRow("BeforeCurrent-OneInitial") << oneEntry << QComboBox::InsertBeforeCurrent << 0 << input << oneBeforeCurrent;
697 QTest::newRow("BeforeCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 0 << input << fiveBeforeCurrentFirst;
698 QTest::newRow("BeforeCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 2 << input << fiveBeforeCurrentThird;
699 QTest::newRow("BeforeCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 4 << input << fiveBeforeCurrentLast;
704 oneEntry << "foobar";
706 fiveEntries << "bar" << "foo" << "initial" << "Item" << "stamp";
708 QStringList initialAlphabetically("insert");
709 QStringList oneAlphabetically;
710 oneAlphabetically << "foobar" << "insert";
711 QStringList fiveAlphabetically;
712 fiveAlphabetically << "bar" << "foo" << "initial" << "insert" << "Item" << "stamp";
714 QTest::newRow("Alphabetically-NoInitial") << initial << QComboBox::InsertAlphabetically << 0 << input << initialAlphabetically;
715 QTest::newRow("Alphabetically-OneInitial") << oneEntry << QComboBox::InsertAlphabetically << 0 << input << oneAlphabetically;
716 QTest::newRow("Alphabetically-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 0 << input << fiveAlphabetically;
717 QTest::newRow("Alphabetically-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 2 << input << fiveAlphabetically;
718 QTest::newRow("Alphabetically-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 4 << input << fiveAlphabetically;
722 void tst_QComboBox::insertPolicy()
724 QFETCH(QStringList, initialEntries);
725 QFETCH(QComboBox::InsertPolicy, insertPolicy);
726 QFETCH(int, currentIndex);
727 QFETCH(QString, userInput);
728 QFETCH(QStringList, result);
731 testWidget->setInsertPolicy(insertPolicy);
732 testWidget->addItems(initialEntries);
733 testWidget->setEditable(true);
734 if (initialEntries.count() > 0)
735 testWidget->setCurrentIndex(currentIndex);
738 QTest::mouseDClick(testWidget->lineEdit(), Qt::LeftButton);
739 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Delete);
741 QTest::keyClicks(testWidget->lineEdit(), userInput);
742 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Return);
744 // First check that there is the right number of entries, or
745 // we may unwittingly pass
746 QVERIFY((int)result.count() == testWidget->count());
748 // No need to compare if there are no strings to compare
749 if (result.count() > 0) {
750 for (int i=0; i<testWidget->count(); ++i) {
751 QCOMPARE(testWidget->itemText(i), result.at(i));
756 // Apps running with valgrind are not fast enough.
757 void tst_QComboBox::virtualAutocompletion()
760 testWidget->setAutoCompletion(true);
761 testWidget->addItem("Foo");
762 testWidget->addItem("Bar");
763 testWidget->addItem("Boat");
764 testWidget->addItem("Boost");
765 testWidget->clearEditText();
767 // We need to set the keyboard input interval to a higher value
768 // as the processEvent() call takes too much time, so it restarts
769 // the keyboard search then
770 #if defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS)
771 int oldInterval = QApplication::keyboardInputInterval();
772 QApplication::setKeyboardInputInterval(1500);
776 // Cannot use keyClick for this test, as it simulates keyclicks too well
777 // The virtual keyboards we're trying to catch here, do not perform that
778 // well, and send a keypress & keyrelease right after each other.
779 // This provokes the actual error, as there's no events in between to do
780 // the text completion.
781 QKeyEvent kp1(QEvent::KeyPress, Qt::Key_B, 0, "b");
782 QKeyEvent kr1(QEvent::KeyRelease, Qt::Key_B, 0, "b");
783 QApplication::sendEvent(testWidget, &kp1);
784 QApplication::sendEvent(testWidget, &kr1);
786 qApp->processEvents(); // Process events to trigger autocompletion
787 QTRY_VERIFY(testWidget->currentIndex() == 1);
789 QKeyEvent kp2(QEvent::KeyPress, Qt::Key_O, 0, "o");
790 QKeyEvent kr2(QEvent::KeyRelease, Qt::Key_O, 0, "o");
792 QApplication::sendEvent(testWidget, &kp2);
793 QApplication::sendEvent(testWidget, &kr2);
795 qApp->processEvents(); // Process events to trigger autocompletion
796 QTRY_COMPARE(testWidget->currentIndex(), 2);
798 QApplication::sendEvent(testWidget, &kp2);
799 QApplication::sendEvent(testWidget, &kr2);
800 qApp->processEvents(); // Process events to trigger autocompletion
801 QTRY_COMPARE(testWidget->currentIndex(), 3);
802 #if defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS)
803 QApplication::setKeyboardInputInterval(oldInterval);
807 void tst_QComboBox::autoCompletionCaseSensitivity()
809 //we have put the focus because the completer
810 //is only used when the widget actually has the focus
811 testWidget->setFocus();
812 qApp->setActiveWindow(testWidget);
813 QTRY_COMPARE(qApp->focusWidget(), (QWidget *)testWidget);
816 testWidget->setAutoCompletion(true);
817 testWidget->addItem("Cow");
818 testWidget->addItem("irrelevant1");
819 testWidget->addItem("aww");
820 testWidget->addItem("A*");
821 testWidget->addItem("irrelevant2");
822 testWidget->addItem("aBCDEF");
823 testWidget->addItem("irrelevant3");
824 testWidget->addItem("abcdef");
825 testWidget->addItem("abCdef");
826 testWidget->setEditable(true);
829 testWidget->clearEditText();
830 QSignalSpy spyReturn(testWidget, SIGNAL(activated(int)));
831 testWidget->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
832 QVERIFY(testWidget->autoCompletionCaseSensitivity() == Qt::CaseInsensitive);
834 QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
835 qApp->processEvents();
836 QCOMPARE(testWidget->currentText(), QString("aww"));
837 QCOMPARE(spyReturn.count(), 0);
839 QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
840 qApp->processEvents();
841 // autocompletions preserve userkey-case from 4.2
842 QCOMPARE(testWidget->currentText(), QString("abCDEF"));
843 QCOMPARE(spyReturn.count(), 0);
845 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
846 qApp->processEvents();
847 QCOMPARE(testWidget->currentText(), QString("aBCDEF")); // case restored to item's case
848 QCOMPARE(spyReturn.count(), 1);
850 testWidget->clearEditText();
851 QTest::keyClick(testWidget->lineEdit(), 'c');
852 QCOMPARE(testWidget->currentText(), QString("cow"));
853 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
854 QCOMPARE(testWidget->currentText(), QString("Cow")); // case restored to item's case
856 testWidget->clearEditText();
857 QTest::keyClick(testWidget->lineEdit(), 'a');
858 QTest::keyClick(testWidget->lineEdit(), '*');
859 QCOMPARE(testWidget->currentText(), QString("a*"));
860 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
861 QCOMPARE(testWidget->currentText(), QString("A*"));
864 testWidget->clearEditText();
865 testWidget->setAutoCompletionCaseSensitivity(Qt::CaseSensitive);
866 QVERIFY(testWidget->autoCompletionCaseSensitivity() == Qt::CaseSensitive);
867 QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
868 qApp->processEvents();
869 QCOMPARE(testWidget->currentText(), QString("aww"));
870 QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
871 qApp->processEvents();
872 QCOMPARE(testWidget->currentText(), QString("abcdef"));
874 testWidget->setCurrentIndex(0); // to reset the completion's "start"
875 testWidget->clearEditText();
876 QTest::keyClick(testWidget->lineEdit(), 'a');
877 QTest::keyClick(testWidget->lineEdit(), 'b');
878 QCOMPARE(testWidget->currentText(), QString("abcdef"));
879 QTest::keyClick(testWidget->lineEdit(), 'C');
880 qApp->processEvents();
881 QCOMPARE(testWidget->currentText(), QString("abCdef"));
882 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
883 qApp->processEvents();
884 QCOMPARE(testWidget->currentText(), QString("abCdef")); // case restored to item's case
886 testWidget->clearEditText();
887 QTest::keyClick(testWidget->lineEdit(), 'c');
888 QCOMPARE(testWidget->currentText(), QString("c"));
889 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Backspace);
890 QTest::keyClick(testWidget->lineEdit(), 'C');
891 QCOMPARE(testWidget->currentText(), QString("Cow"));
892 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
893 QCOMPARE(testWidget->currentText(), QString("Cow"));
895 testWidget->clearEditText();
896 QTest::keyClick(testWidget->lineEdit(), 'a');
897 QTest::keyClick(testWidget->lineEdit(), '*');
898 QCOMPARE(testWidget->currentText(), QString("a*"));
899 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
900 QCOMPARE(testWidget->currentText(), QString("a*")); // A* not matched
903 void tst_QComboBox::hide()
905 testWidget->addItem("foo");
906 testWidget->showPopup();
907 //allow combobox effect to complete
908 QTRY_VERIFY(testWidget->view());
909 QTRY_VERIFY(testWidget->view()->isVisible());
910 testWidget->hidePopup();
911 //allow combobox effect to complete
913 QEXPECT_FAIL("", "QTBUG-23678", Continue);
915 QTRY_VERIFY(!testWidget->view()->isVisible());
917 QVERIFY(!testWidget->isVisible());
922 void tst_QComboBox::currentIndex_data()
924 QTest::addColumn<QStringList>("initialItems");
925 QTest::addColumn<int>("setCurrentIndex");
926 QTest::addColumn<int>("removeIndex");
927 QTest::addColumn<int>("insertIndex");
928 QTest::addColumn<QString>("insertText");
929 QTest::addColumn<int>("expectedCurrentIndex");
930 QTest::addColumn<QString>("expectedCurrentText");
931 QTest::addColumn<int>("expectedSignalCount");
933 QStringList initialItems;
938 int expectedCurrentIndex;
939 QString expectedCurrentText;
940 int expectedSignalCount;
943 initialItems.clear();
944 initialItems << "foo" << "bar";
945 setCurrentIndex = -2;
949 expectedCurrentIndex = 0;
950 expectedCurrentText = "foo";
951 expectedSignalCount = 1;
952 QTest::newRow("first added item is set to current if there is no current")
953 << initialItems << setCurrentIndex << removeIndex
954 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
955 << expectedSignalCount;
958 initialItems.clear();
959 initialItems << "foo" << "bar";
964 expectedCurrentIndex = 1;
965 expectedCurrentText = "bar";
966 expectedSignalCount = 2;
967 QTest::newRow("check that setting the index works")
968 << initialItems << setCurrentIndex << removeIndex
969 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
970 << expectedSignalCount;
974 initialItems.clear();
975 initialItems << "foo" << "bar";
976 setCurrentIndex = -1; // will invalidate the currentIndex
980 expectedCurrentIndex = -1;
981 expectedCurrentText = "";
982 expectedSignalCount = 2;
983 QTest::newRow("check that isetting the index to -1 works")
984 << initialItems << setCurrentIndex << removeIndex
985 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
986 << expectedSignalCount;
990 initialItems.clear();
991 initialItems << "foo";
996 expectedCurrentIndex = -1;
997 expectedCurrentText = "";
998 expectedSignalCount = 2;
999 QTest::newRow("check that current index is invalid when removing the only item")
1000 << initialItems << setCurrentIndex << removeIndex
1001 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1002 << expectedSignalCount;
1005 initialItems.clear();
1006 initialItems << "foo" << "bar";
1007 setCurrentIndex = 1;
1011 expectedCurrentIndex = 0;
1012 expectedCurrentText = "bar";
1013 expectedSignalCount = 3;
1014 QTest::newRow("check that the current index follows the item when removing an item above")
1015 << initialItems << setCurrentIndex << removeIndex
1016 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1017 << expectedSignalCount;
1021 initialItems.clear();
1022 initialItems << "foo" << "bar" << "baz";
1023 setCurrentIndex = 1;
1027 expectedCurrentIndex = 1;
1028 expectedCurrentText = "baz";
1029 expectedSignalCount = 3;
1030 QTest::newRow("check that the current index uses the next item if current is removed")
1031 << initialItems << setCurrentIndex << removeIndex
1032 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1033 << expectedSignalCount;
1036 initialItems.clear();
1037 initialItems << "foo" << "bar" << "baz";
1038 setCurrentIndex = 2;
1042 expectedCurrentIndex = 1;
1043 expectedCurrentText = "bar";
1044 expectedSignalCount = 3;
1045 QTest::newRow("check that the current index is moved to the one before if current is removed")
1046 << initialItems << setCurrentIndex << removeIndex
1047 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1048 << expectedSignalCount;
1051 initialItems.clear();
1052 initialItems << "foo" << "bar" << "baz";
1053 setCurrentIndex = 1;
1057 expectedCurrentIndex = 1;
1058 expectedCurrentText = "bar";
1059 expectedSignalCount = 2;
1060 QTest::newRow("check that the current index is unchanged if you remove an item after")
1061 << initialItems << setCurrentIndex << removeIndex
1062 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1063 << expectedSignalCount;
1066 initialItems.clear();
1067 initialItems << "foo" << "bar";
1068 setCurrentIndex = 1;
1072 expectedCurrentIndex = 2;
1073 expectedCurrentText = "bar";
1074 expectedSignalCount = 3;
1075 QTest::newRow("check that the current index follows the item if you insert before current")
1076 << initialItems << setCurrentIndex << removeIndex
1077 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1078 << expectedSignalCount;
1081 initialItems.clear();
1082 initialItems << "foo";
1083 setCurrentIndex = 0;
1087 expectedCurrentIndex = 1;
1088 expectedCurrentText = "foo";
1089 expectedSignalCount = 2;
1090 QTest::newRow("check that the current index follows the item if you insert on the current")
1091 << initialItems << setCurrentIndex << removeIndex
1092 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1093 << expectedSignalCount;
1096 initialItems.clear();
1097 initialItems << "foo";
1098 setCurrentIndex = 0;
1102 expectedCurrentIndex = 0;
1103 expectedCurrentText = "foo";
1104 expectedSignalCount = 1;
1105 QTest::newRow("check that the current index stays the same if you insert after the current")
1106 << initialItems << setCurrentIndex << removeIndex
1107 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1108 << expectedSignalCount;
1112 void tst_QComboBox::currentIndex()
1114 QFETCH(QStringList, initialItems);
1115 QFETCH(int, setCurrentIndex);
1116 QFETCH(int, removeIndex);
1117 QFETCH(int, insertIndex);
1118 QFETCH(QString, insertText);
1119 QFETCH(int, expectedCurrentIndex);
1120 QFETCH(QString, expectedCurrentText);
1121 QFETCH(int, expectedSignalCount);
1123 // test both editable/non-editable combobox
1124 for (int edit = 0; edit < 2; ++edit) {
1125 testWidget->clear();
1126 testWidget->setEditable(edit ? true : false);
1128 QVERIFY(testWidget->lineEdit());
1130 // verify it is empty, has no current index and no current text
1131 QCOMPARE(testWidget->count(), 0);
1132 QCOMPARE(testWidget->currentIndex(), -1);
1133 QVERIFY(testWidget->currentText().isEmpty());
1135 // spy on currentIndexChanged
1136 QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int)));
1137 QSignalSpy indexChangedString(testWidget, SIGNAL(currentIndexChanged(const QString&)));
1139 // stuff items into it
1140 foreach(QString text, initialItems) {
1141 testWidget->addItem(text);
1143 QCOMPARE(testWidget->count(), initialItems.count());
1145 // set current index, remove and/or insert
1146 if (setCurrentIndex >= -1) {
1147 testWidget->setCurrentIndex(setCurrentIndex);
1148 QCOMPARE(testWidget->currentIndex(), setCurrentIndex);
1151 if (removeIndex >= 0)
1152 testWidget->removeItem(removeIndex);
1153 if (insertIndex >= 0)
1154 testWidget->insertItem(insertIndex, insertText);
1156 // compare with expected index and text
1157 QCOMPARE(testWidget->currentIndex(), expectedCurrentIndex);
1158 QCOMPARE(testWidget->currentText(), expectedCurrentText);
1160 // check that signal count is correct
1161 QCOMPARE(indexChangedInt.count(), expectedSignalCount);
1162 QCOMPARE(indexChangedString.count(), expectedSignalCount);
1164 // compare with last sent signal values
1165 if (indexChangedInt.count())
1166 QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(),
1167 testWidget->currentIndex());
1168 if (indexChangedString.count())
1169 QCOMPARE(indexChangedString.at(indexChangedString.count() - 1).at(0).toString(),
1170 testWidget->currentText());
1173 testWidget->setCurrentIndex(-1);
1174 testWidget->setInsertPolicy(QComboBox::InsertAtBottom);
1175 QTest::keyPress(testWidget, 'a');
1176 QTest::keyPress(testWidget, 'b');
1177 QCOMPARE(testWidget->currentText(), QString("ab"));
1178 QCOMPARE(testWidget->currentIndex(), -1);
1179 int numItems = testWidget->count();
1180 QTest::keyPress(testWidget, Qt::Key_Return);
1181 QCOMPARE(testWidget->count(), numItems + 1);
1182 QCOMPARE(testWidget->currentIndex(), numItems);
1183 testWidget->setCurrentIndex(-1);
1184 QTest::keyPress(testWidget, 'a');
1185 QTest::keyPress(testWidget, 'b');
1186 QCOMPARE(testWidget->currentIndex(), -1);
1191 void tst_QComboBox::insertItems_data()
1193 QTest::addColumn<QStringList>("initialItems");
1194 QTest::addColumn<QStringList>("insertedItems");
1195 QTest::addColumn<int>("insertIndex");
1196 QTest::addColumn<int>("expectedIndex");
1198 QStringList initialItems;
1199 QStringList insertedItems;
1201 initialItems << "foo" << "bar";
1202 insertedItems << "mongo";
1204 QTest::newRow("prepend") << initialItems << insertedItems << 0 << 0;
1205 QTest::newRow("prepend with negative value") << initialItems << insertedItems << -1 << 0;
1206 QTest::newRow("append") << initialItems << insertedItems << initialItems.count() << initialItems.count();
1207 QTest::newRow("append with too high value") << initialItems << insertedItems << 999 << initialItems.count();
1208 QTest::newRow("insert") << initialItems << insertedItems << 1 << 1;
1211 void tst_QComboBox::insertItems()
1213 QFETCH(QStringList, initialItems);
1214 QFETCH(QStringList, insertedItems);
1215 QFETCH(int, insertIndex);
1216 QFETCH(int, expectedIndex);
1218 testWidget->insertItems(0, initialItems);
1219 QCOMPARE(testWidget->count(), initialItems.count());
1221 testWidget->insertItems(insertIndex, insertedItems);
1223 QCOMPARE(testWidget->count(), initialItems.count() + insertedItems.count());
1224 for (int i=0; i<insertedItems.count(); ++i)
1225 QCOMPARE(testWidget->itemText(expectedIndex + i), insertedItems.at(i));
1228 void tst_QComboBox::insertItem_data()
1230 QTest::addColumn<QStringList>("initialItems");
1231 QTest::addColumn<int>("insertIndex");
1232 QTest::addColumn<QString>("itemLabel");
1233 QTest::addColumn<int>("expectedIndex");
1234 QTest::addColumn<bool>("editable");
1236 QStringList initialItems;
1237 initialItems << "foo" << "bar";
1238 for(int e = 0 ; e<2 ; e++) {
1239 bool editable = (e==0);
1240 QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0 << editable;
1241 QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0 << editable;
1242 QTest::newRow("Insert beyond count") << initialItems << 3 << "inserted" << 2 << editable;
1243 QTest::newRow("Insert at count") << initialItems << 2 << "inserted" << 2 << editable;
1244 QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1 << editable;
1248 void tst_QComboBox::insertItem()
1250 QFETCH(QStringList, initialItems);
1251 QFETCH(int, insertIndex);
1252 QFETCH(QString, itemLabel);
1253 QFETCH(int, expectedIndex);
1254 QFETCH(bool, editable);
1256 testWidget->insertItems(0, initialItems);
1257 QCOMPARE(testWidget->count(), initialItems.count());
1259 testWidget->setEditable(true);
1261 testWidget->setEditText("FOO");
1262 testWidget->insertItem(insertIndex, itemLabel);
1264 QCOMPARE(testWidget->count(), initialItems.count() + 1);
1265 QCOMPARE(testWidget->itemText(expectedIndex), itemLabel);
1268 QCOMPARE(testWidget->currentText(), QString("FOO"));
1271 void tst_QComboBox::insertOnCurrentIndex()
1273 testWidget->setEditable(true);
1274 testWidget->addItem("first item");
1275 testWidget->setCurrentIndex(0);
1276 testWidget->insertItem(0, "second item");
1277 QCOMPARE(testWidget->lineEdit()->text(), QString::fromAscii("first item"));
1280 void tst_QComboBox::textpixmapdata_data()
1282 QTest::addColumn<QStringList>("text");
1283 QTest::addColumn<IconList>("icons");
1284 QTest::addColumn<VariantList>("variant");
1288 VariantList variant;
1291 text.clear(); icon.clear(); variant.clear();
1292 text << "foo" << "bar";
1293 icon << QIcon() << QIcon();
1294 variant << QVariant() << QVariant();
1295 QTest::newRow("just text") << text << icon << variant;
1298 text.clear(); icon.clear(); variant.clear();
1299 text << QString() << QString();
1300 icon << QIcon(QPixmap("qtlogo.png")) << QIcon(QPixmap("qtlogoinverted.png"));
1301 variant << QVariant() << QVariant();
1302 QTest::newRow("just icons") << text << icon << variant;
1305 text.clear(); icon.clear(); variant.clear();
1306 text << QString() << QString();
1307 icon << QIcon() << QIcon();
1308 variant << 12 << "bingo";
1309 QTest::newRow("just user data") << text << icon << variant;
1312 text.clear(); icon.clear(); variant.clear();
1313 text << "foo" << "bar";
1314 icon << QIcon(QPixmap("qtlogo.png")) << QIcon(QPixmap("qtlogoinverted.png"));
1315 variant << 12 << "bingo";
1316 QTest::newRow("text, icons and user data") << text << icon << variant;
1320 void tst_QComboBox::textpixmapdata()
1322 QFETCH(QStringList, text);
1323 QFETCH(IconList, icons);
1324 QFETCH(VariantList, variant);
1326 QVERIFY(text.count() == icons.count() && text.count() == variant.count());
1328 for (int i = 0; i<text.count(); ++i) {
1329 testWidget->insertItem(i, text.at(i));
1330 testWidget->setItemIcon(i, icons.at(i));
1331 testWidget->setItemData(i, variant.at(i), Qt::UserRole);
1334 QCOMPARE(testWidget->count(), text.count());
1336 for (int i = 0; i<text.count(); ++i) {
1337 QIcon icon = testWidget->itemIcon(i);
1338 QVERIFY(icon.serialNumber() == icons.at(i).serialNumber());
1339 QPixmap original = icons.at(i).pixmap(1024);
1340 QPixmap pixmap = icon.pixmap(1024);
1341 QVERIFY(pixmap.toImage() == original.toImage());
1344 for (int i = 0; i<text.count(); ++i) {
1345 QCOMPARE(testWidget->itemText(i), text.at(i));
1346 // ### we should test icons/pixmap as well, but I need to fix the api mismatch first
1347 QCOMPARE(testWidget->itemData(i, Qt::UserRole), variant.at(i));
1351 void tst_QComboBox::setCurrentIndex()
1353 QCOMPARE(testWidget->count(), 0);
1354 testWidget->addItem("foo");
1355 testWidget->addItem("bar");
1356 QCOMPARE(testWidget->count(), 2);
1358 QCOMPARE(testWidget->currentIndex(), 0);
1359 testWidget->setCurrentIndex(0);
1360 QCOMPARE(testWidget->currentText(), QString("foo"));
1362 testWidget->setCurrentIndex(1);
1363 QCOMPARE(testWidget->currentText(), QString("bar"));
1365 testWidget->setCurrentIndex(0);
1366 QCOMPARE(testWidget->currentText(), QString("foo"));
1369 void tst_QComboBox::editTextChanged()
1371 QCOMPARE(testWidget->count(), 0);
1372 testWidget->addItem("foo");
1373 testWidget->addItem("bar");
1374 QCOMPARE(testWidget->count(), 2);
1376 // first we test non editable
1377 testWidget->setEditable(false);
1378 QCOMPARE(testWidget->isEditable(), false);
1380 // no signal should be sent when current is set to the same
1381 QCOMPARE(testWidget->currentIndex(), 0);
1384 testWidget->setCurrentIndex(0);
1385 QCOMPARE(testWidget->currentIndex(), 0);
1386 QCOMPARE(editTextCount, 0);
1387 QCOMPARE(editText.isEmpty(), true);
1389 // no signal should be sent when changing to other index because we are not editable
1390 QCOMPARE(testWidget->currentIndex(), 0);
1393 testWidget->setCurrentIndex(1);
1394 QCOMPARE(testWidget->currentIndex(), 1);
1395 QCOMPARE(editTextCount, 0);
1396 QCOMPARE(editText.isEmpty(), true);
1398 // now set to editable and reset current index
1399 testWidget->setEditable(true);
1400 QCOMPARE(testWidget->isEditable(), true);
1401 testWidget->setCurrentIndex(0);
1403 // no signal should be sent when current is set to the same
1404 QCOMPARE(testWidget->currentIndex(), 0);
1407 testWidget->setCurrentIndex(0);
1408 QCOMPARE(testWidget->currentIndex(), 0);
1409 QCOMPARE(editTextCount, 0);
1410 QCOMPARE(editText.isEmpty(), true);
1412 // signal should be sent when changing to other index
1413 QCOMPARE(testWidget->currentIndex(), 0);
1416 testWidget->setCurrentIndex(1);
1417 QCOMPARE(testWidget->currentIndex(), 1);
1418 QCOMPARE(editTextCount, 1);
1419 QCOMPARE(editText, QString("bar"));
1421 // insert some keys and notice they are all signaled
1424 QTest::keyClicks(testWidget, "bingo");
1425 QCOMPARE(editTextCount, 5);
1426 QCOMPARE(editText, QString("barbingo"));
1429 void tst_QComboBox::onEditTextChanged(const QString &text)
1435 void tst_QComboBox::setModel()
1438 QCOMPARE(box.currentIndex(), -1);
1439 box.addItems((QStringList() << "foo" << "bar"));
1440 QCOMPARE(box.currentIndex(), 0);
1441 box.setCurrentIndex(1);
1442 QCOMPARE(box.currentIndex(), 1);
1444 // check that currentIndex is set to invalid
1445 QAbstractItemModel *oldModel = box.model();
1446 box.setModel(new QStandardItemModel(&box));
1447 QCOMPARE(box.currentIndex(), -1);
1448 QVERIFY(box.model() != oldModel);
1450 // check that currentIndex is set to first item
1451 oldModel = box.model();
1452 box.setModel(new QStandardItemModel(2,1, &box));
1453 QCOMPARE(box.currentIndex(), 0);
1454 QVERIFY(box.model() != oldModel);
1457 void tst_QComboBox::modelDeleted()
1460 QStandardItemModel *model = new QStandardItemModel;
1461 box.setModel(model);
1462 QCOMPARE(box.model(), static_cast<QAbstractItemModel *>(model));
1464 QVERIFY(box.model());
1465 QCOMPARE(box.findText("bubu"), -1);
1468 QVERIFY(box.model());
1470 QVERIFY(box.model());
1473 void tst_QComboBox::setMaxCount()
1476 items << "1" << "2" << "3" << "4" << "5";
1479 box.addItems(items);
1480 QCOMPARE(box.count(), 5);
1483 QCOMPARE(box.count(), 4);
1484 QCOMPARE(box.itemText(0), QString("1"));
1485 QCOMPARE(box.itemText(1), QString("2"));
1486 QCOMPARE(box.itemText(2), QString("3"));
1487 QCOMPARE(box.itemText(3), QString("4"));
1489 // appending should do nothing
1491 QCOMPARE(box.count(), 4);
1492 QCOMPARE(box.findText("foo"), -1);
1494 // inserting one item at top should remove the last
1495 box.insertItem(0, "0");
1496 QCOMPARE(box.count(), 4);
1497 QCOMPARE(box.itemText(0), QString("0"));
1498 QCOMPARE(box.itemText(1), QString("1"));
1499 QCOMPARE(box.itemText(2), QString("2"));
1500 QCOMPARE(box.itemText(3), QString("3"));
1502 // insert 5 items in a box with maxCount 4
1503 box.insertItems(0, items);
1504 QCOMPARE(box.count(), 4);
1505 QCOMPARE(box.itemText(0), QString("1"));
1506 QCOMPARE(box.itemText(1), QString("2"));
1507 QCOMPARE(box.itemText(2), QString("3"));
1508 QCOMPARE(box.itemText(3), QString("4"));
1510 // insert 5 items at pos 2. Make sure only two get inserted
1511 QSignalSpy spy(box.model(), SIGNAL(rowsInserted(QModelIndex,int,int)));
1512 box.insertItems(2, items);
1513 QCOMPARE(spy.count(), 1);
1514 QCOMPARE(spy.at(0).at(1).toInt(), 2);
1515 QCOMPARE(spy.at(0).at(2).toInt(), 3);
1517 QCOMPARE(box.count(), 4);
1518 QCOMPARE(box.itemText(0), QString("1"));
1519 QCOMPARE(box.itemText(1), QString("2"));
1520 QCOMPARE(box.itemText(2), QString("1"));
1521 QCOMPARE(box.itemText(3), QString("2"));
1523 box.insertItems(0, QStringList());
1524 QCOMPARE(box.count(), 4);
1527 QCOMPARE(box.count(), 0);
1529 QCOMPARE(box.count(), 0);
1530 box.addItems(items);
1531 QCOMPARE(box.count(), 0);
1534 void tst_QComboBox::convenienceViews()
1537 QComboBox listCombo;
1538 QListWidget *list = new QListWidget();
1539 listCombo.setModel(list->model());
1540 listCombo.setView(list);
1542 list->addItem("list0");
1543 listCombo.addItem("list1");
1544 QCOMPARE(listCombo.count(), 2);
1545 QCOMPARE(listCombo.itemText(0), QString("list0"));
1546 QCOMPARE(listCombo.itemText(1), QString("list1"));
1549 QComboBox treeCombo;
1550 QTreeWidget *tree = new QTreeWidget();
1551 tree->setColumnCount(1);
1552 tree->header()->hide();
1553 treeCombo.setModel(tree->model());
1554 treeCombo.setView(tree);
1556 tree->addTopLevelItem(new QTreeWidgetItem(QStringList("tree0")));
1557 treeCombo.addItem("tree1");
1558 QCOMPARE(treeCombo.count(), 2);
1559 QCOMPARE(treeCombo.itemText(0), QString("tree0"));
1560 QCOMPARE(treeCombo.itemText(1), QString("tree1"));
1563 QComboBox tableCombo;
1564 QTableWidget *table = new QTableWidget(0,1);
1565 table->verticalHeader()->hide();
1566 table->horizontalHeader()->hide();
1567 tableCombo.setModel(table->model());
1568 tableCombo.setView(table);
1570 table->setRowCount(table->rowCount() + 1);
1571 table->setItem(0, table->rowCount() - 1, new QTableWidgetItem("table0"));
1572 tableCombo.addItem("table1");
1573 QCOMPARE(tableCombo.count(), 2);
1574 QCOMPARE(tableCombo.itemText(0), QString("table0"));
1575 QCOMPARE(tableCombo.itemText(1), QString("table1"));
1578 class ReturnClass : public QWidget
1582 ReturnClass(QWidget *parent = 0)
1583 : QWidget(parent), received(false)
1585 QComboBox *box = new QComboBox(this);
1586 box->setEditable(true);
1587 edit = box->lineEdit();
1588 box->setGeometry(rect());
1591 void keyPressEvent(QKeyEvent *e)
1593 received = (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter);
1604 void tst_QComboBox::ensureReturnIsIgnored()
1609 QTest::keyClick(r.edit, Qt::Key_Return);
1610 QVERIFY(r.received);
1612 QTest::keyClick(r.edit, Qt::Key_Enter);
1613 QVERIFY(r.received);
1617 void tst_QComboBox::findText_data()
1619 QTest::addColumn<QStringList>("items");
1620 QTest::addColumn<int>("matchflags");
1621 QTest::addColumn<QString>("search");
1622 QTest::addColumn<int>("result");
1625 list << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "one";
1626 QTest::newRow("CaseSensitive_1") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1627 << QString("Two") << 1;
1628 QTest::newRow("CaseSensitive_2") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1629 << QString("two") << -1;
1630 QTest::newRow("CaseSensitive_3") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1631 << QString("One") << 0;
1632 QTest::newRow("CaseSensitive_4") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1633 << QString("one") << 6;
1634 QTest::newRow("CaseInsensitive_1") << list << (int)(Qt::MatchExactly) << QString("Two") << 1;
1635 QTest::newRow("CaseInsensitive_2") << list << (int)(Qt::MatchExactly) << QString("two") << -1;
1636 QTest::newRow("CaseInsensitive_3") << list << (int)(Qt::MatchExactly) << QString("One") << 0;
1637 QTest::newRow("CaseInsensitive_4") << list << (int)(Qt::MatchExactly) << QString("one") << 6;
1639 void tst_QComboBox::findText()
1641 QFETCH(QStringList, items);
1642 QFETCH(int, matchflags);
1643 QFETCH(QString, search);
1644 QFETCH(int, result);
1646 testWidget->clear();
1647 testWidget->addItems(items);
1649 QCOMPARE(testWidget->findText(search, (Qt::MatchFlags)matchflags), result);
1652 typedef QList<int> IntList;
1653 typedef QList<Qt::Key> KeyList;
1654 Q_DECLARE_METATYPE(IntList)
1655 Q_DECLARE_METATYPE(KeyList)
1657 void tst_QComboBox::flaggedItems_data()
1659 QTest::addColumn<QStringList>("itemList");
1660 QTest::addColumn<IntList>("deselectFlagList");
1661 QTest::addColumn<IntList>("disableFlagList");
1662 QTest::addColumn<KeyList>("keyMovementList");
1663 QTest::addColumn<bool>("editable");
1664 QTest::addColumn<int>("expectedIndex");
1666 for (int editable=0;editable<2;editable++) {
1667 QString testCase = editable ? "editable:" : "non-editable:";
1668 QStringList itemList;
1669 itemList << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "Seven" << "Eight";
1670 IntList deselectFlagList;
1671 IntList disableFlagList;
1672 KeyList keyMovementList;
1674 keyMovementList << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down;
1675 QTest::newRow(testCase.toAscii() + "normal") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1677 deselectFlagList.clear();
1678 disableFlagList.clear();
1679 deselectFlagList << 1 << 3;
1680 QTest::newRow(testCase.toAscii() + "non-selectable") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1682 deselectFlagList.clear();
1683 disableFlagList.clear();
1684 disableFlagList << 2;
1685 QTest::newRow(testCase.toAscii() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 5;
1687 deselectFlagList.clear();
1688 disableFlagList.clear();
1689 deselectFlagList << 1 << 3;
1690 disableFlagList << 2 << 3;
1691 QTest::newRow(testCase.toAscii() + "mixed") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 6;
1692 deselectFlagList.clear();
1693 disableFlagList.clear();
1694 disableFlagList << 0 << 1 << 2 << 3 << 4 << 5 << 6;
1695 QTest::newRow(testCase.toAscii() + "nearly-empty") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
1697 deselectFlagList.clear();
1698 disableFlagList.clear();
1699 disableFlagList << 0 << 1 << 2 << 3 << 5 << 6 << 7;
1700 keyMovementList.clear();
1701 QTest::newRow(testCase.toAscii() + "only one enabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1704 deselectFlagList.clear();
1705 disableFlagList.clear();
1706 keyMovementList.clear();
1707 disableFlagList << 0 << 2 << 3;
1708 keyMovementList << Qt::Key_Down << Qt::Key_Home;
1709 QTest::newRow(testCase.toAscii() + "home-disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 1;
1711 keyMovementList.clear();
1712 keyMovementList << Qt::Key_End;
1713 QTest::newRow(testCase.toAscii() + "end-key") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
1715 disableFlagList.clear();
1716 disableFlagList << 1 ;
1717 keyMovementList << Qt::Key_T;
1718 QTest::newRow(testCase.toAscii() + "keyboard-search") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1720 itemList << "nine" << "ten";
1721 keyMovementList << Qt::Key_T;
1722 QTest::newRow(testCase.toAscii() + "search same start letter") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 9;
1724 keyMovementList.clear();
1725 keyMovementList << Qt::Key_T << Qt::Key_H;
1726 QTest::newRow(testCase.toAscii() + "keyboard search item") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1728 disableFlagList.clear();
1729 disableFlagList << 1 << 3 << 5 << 7 << 9;
1730 keyMovementList.clear();
1731 keyMovementList << Qt::Key_End << Qt::Key_Up << Qt::Key_Up << Qt::Key_PageDown << Qt::Key_PageUp << Qt::Key_PageUp << Qt::Key_Down;
1732 QTest::newRow(testCase.toAscii() + "all key combinations") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1734 deselectFlagList.clear();
1735 disableFlagList.clear();
1736 disableFlagList << 1;
1737 keyMovementList.clear();
1738 keyMovementList << Qt::Key_T << Qt::Key_Enter;
1739 QTest::newRow(testCase.toAscii() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1740 QTest::newRow(testCase.toAscii() + "broken autocompletion") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1745 void tst_QComboBox::flaggedItems()
1747 QFETCH(QStringList, itemList);
1748 QFETCH(IntList, deselectFlagList);
1749 QFETCH(IntList, disableFlagList);
1750 QFETCH(KeyList, keyMovementList);
1751 QFETCH(bool, editable);
1752 QFETCH(int, expectedIndex);
1755 QListWidget listWidget;
1756 listWidget.addItems(itemList);
1758 comboBox.setEditable(editable);
1759 foreach (int index, deselectFlagList)
1760 listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsSelectable);
1762 foreach (int index, disableFlagList)
1763 listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
1765 comboBox.setModel(listWidget.model());
1766 comboBox.setView(&listWidget);
1768 QApplication::setActiveWindow(&comboBox);
1769 comboBox.activateWindow();
1770 comboBox.setFocus();
1771 QTRY_VERIFY(comboBox.isVisible());
1772 QTRY_VERIFY(comboBox.hasFocus());
1775 comboBox.lineEdit()->selectAll();
1777 QSignalSpy indexChangedInt(&comboBox, SIGNAL(currentIndexChanged(int)));
1778 for (int i = 0; i < keyMovementList.count(); ++i) {
1779 Qt::Key key = keyMovementList[i];
1780 QTest::keyClick(&comboBox, key);
1781 if (indexChangedInt.count() != i + 1) {
1786 QCOMPARE(comboBox.currentIndex() , expectedIndex);
1789 void tst_QComboBox::pixmapIcon()
1792 QStandardItemModel *model = new QStandardItemModel(2, 1, &box);
1794 QPixmap pix(10, 10);
1796 model->setData(model->index(0, 0), "Element 1");
1797 model->setData(model->index(0, 0), pix, Qt::DecorationRole);
1800 model->setData(model->index(1, 0), "Element 2");
1801 model->setData(model->index(1, 0), icon, Qt::DecorationRole);
1803 box.setModel(model);
1805 QCOMPARE( box.itemIcon(0).isNull(), false );
1806 QCOMPARE( box.itemIcon(1).isNull(), false );
1809 // defined to be 120 by the wheel mouse vendors according to the docs
1810 #define WHEEL_DELTA 120
1812 void tst_QComboBox::mouseWheel_data()
1814 QTest::addColumn<IntList>("disabledItems");
1815 QTest::addColumn<int>("startIndex");
1816 QTest::addColumn<int>("wheelDirection");
1817 QTest::addColumn<int>("expectedIndex");
1820 disabled << 0 << 1 << 2 << 4;
1824 QTest::newRow("upper locked") << disabled << start << wheel << expected;
1828 QTest::newRow("jump over") << disabled << start << wheel << expected;
1831 disabled << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9;
1835 QTest::newRow("single Item enabled") << disabled << start << wheel << expected;
1838 void tst_QComboBox::mouseWheel()
1840 QFETCH(IntList, disabledItems);
1841 QFETCH(int, startIndex);
1842 QFETCH(int, wheelDirection);
1843 QFETCH(int, expectedIndex);
1845 QCoreApplication *applicationInstance = QCoreApplication::instance();
1846 QVERIFY(applicationInstance != 0);
1850 list << "one" << "two" << "three" << "four" << "five" << "six" << "seven" << "eight" << "nine" << "ten";
1852 QListWidget listWidget;
1853 listWidget.addItems(list);
1855 foreach (int index, disabledItems)
1856 listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
1858 box.setModel(listWidget.model());
1859 box.setView(&listWidget);
1860 for (int i=0; i < 2; ++i) {
1861 box.setEditable(i==0?false:true);
1862 box.setCurrentIndex(startIndex);
1864 QWheelEvent event = QWheelEvent(box.rect().bottomRight() , WHEEL_DELTA * wheelDirection, Qt::NoButton, Qt::NoModifier);
1865 QVERIFY(applicationInstance->sendEvent(&box,&event));
1867 QCOMPARE(box.currentIndex(), expectedIndex);
1871 void tst_QComboBox::layoutDirection()
1874 Qt::LayoutDirection dir;
1875 QLineEdit *lineEdit;
1878 box.setLayoutDirection(Qt::RightToLeft);
1879 QStyleOptionComboBox opt;
1880 opt.direction = Qt::RightToLeft;
1881 dir = (Qt::LayoutDirection)box.style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, &box);
1883 QCOMPARE(box.view()->layoutDirection(), dir);
1884 box.setEditable(true);
1885 QCOMPARE(box.lineEdit()->layoutDirection(), dir);
1886 lineEdit = new QLineEdit;
1887 QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
1888 box.setLineEdit(lineEdit);
1889 QCOMPARE(lineEdit->layoutDirection(), dir);
1892 box.setLayoutDirection(Qt::LeftToRight);
1893 qApp->setLayoutDirection(Qt::RightToLeft);
1895 opt.direction = Qt::LeftToRight;
1896 dir = (Qt::LayoutDirection)box.style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, &box);
1898 QCOMPARE(box.view()->layoutDirection(), dir);
1899 box.setEditable(true);
1900 QCOMPARE(box.lineEdit()->layoutDirection(), dir);
1901 lineEdit = new QLineEdit;
1902 QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
1903 box.setLineEdit(lineEdit);
1904 QCOMPARE(lineEdit->layoutDirection(), dir);
1908 void tst_QComboBox::itemListPosition()
1910 //tests that the list is not out of the screen boundaries
1912 //put the QApplication layout back
1913 QApplication::setLayoutDirection(Qt::LeftToRight);
1915 //we test QFontComboBox because it has the specific behaviour to set a fixed size
1918 QFontComboBox combo(&topLevel);
1920 //the code to get the available screen space is copied from QComboBox code
1921 const int scrNumber = QApplication::desktop()->screenNumber(&combo);
1923 bool useFullScreenForPopupMenu = false;
1924 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
1925 useFullScreenForPopupMenu = theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool();
1926 const QRect screen = useFullScreenForPopupMenu ?
1927 QApplication::desktop()->screenGeometry(scrNumber) :
1928 QApplication::desktop()->availableGeometry(scrNumber);
1930 combo.move(screen.width()-combo.sizeHint().width(), 0); //puts the combo to the top-right corner
1933 //wait because the window manager can move the window if there is a right panel
1934 QTRY_VERIFY(combo.isVisible());
1936 QTRY_VERIFY(combo.view());
1937 QTRY_VERIFY(combo.view()->isVisible());
1938 QVERIFY( combo.view()->window()->x() + combo.view()->window()->width() <= screen.x() + screen.width() );
1941 void tst_QComboBox::separatorItem_data()
1943 QTest::addColumn<QStringList>("items");
1944 QTest::addColumn<IntList>("separators");
1946 QTest::newRow("test") << (QStringList() << "one" << "two" << "three" << "other...")
1947 << (IntList() << 4);
1950 void tst_QComboBox::separatorItem()
1952 QFETCH(QStringList, items);
1953 QFETCH(IntList, separators);
1956 box.addItems(items);
1957 foreach(int index, separators)
1958 box.insertSeparator(index);
1959 QCOMPARE(box.count(), (items.count() + separators.count()));
1960 for (int i = 0, s = 0; i < box.count(); ++i) {
1961 if (i == separators.at(s)) {
1962 QCOMPARE(box.itemText(i), QString());
1965 QCOMPARE(box.itemText(i), items.at(i - s));
1970 // This test requires the Cleanlooks style
1971 #ifndef QT_NO_STYLE_CLEANLOOKS
1972 void tst_QComboBox::task190351_layout()
1974 const QString oldStyle = QApplication::style()->objectName();
1975 QApplication::setStyle(new QCleanlooksStyle);
1977 QComboBox listCombo;
1978 QListWidget *list = new QListWidget();
1979 listCombo.setModel(list->model());
1980 listCombo.setView(list);
1981 for(int i = 1; i < 150; i++)
1982 list->addItem(QLatin1String("list") + QString::number(i));
1985 QTest::qWaitForWindowShown(&listCombo);
1986 QTRY_VERIFY(listCombo.isVisible());
1987 listCombo.setCurrentIndex(70);
1988 listCombo.showPopup();
1989 QTRY_VERIFY(listCombo.view());
1990 QTest::qWaitForWindowShown(listCombo.view());
1991 QTRY_VERIFY(listCombo.view()->isVisible());
1992 QApplication::processEvents();
1994 #ifdef QT_BUILD_INTERNAL
1995 QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&listCombo);
1997 QCOMPARE(static_cast<QAbstractItemView *>(list), qFindChild<QAbstractItemView *>(container));
1998 QWidget *top = qFindChild<QComboBoxPrivateScroller *>(container);
2000 QVERIFY(top->isVisible());
2001 QCOMPARE(top->mapToGlobal(QPoint(0, top->height())).y(), list->mapToGlobal(QPoint()).y());
2004 QApplication::setStyle(oldStyle);
2008 class task166349_ComboBox : public QComboBox
2012 task166349_ComboBox(QWidget *parent = 0) : QComboBox(parent)
2015 list << "one" << "two";
2016 connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
2020 void onCurrentIndexChanged(int index)
2022 setEditable(index % 2 == 1);
2026 void tst_QComboBox::task166349_setEditableOnReturn()
2028 task166349_ComboBox comboBox;
2029 QTest::keyClick(&comboBox, Qt::Key_Down);
2030 QTest::keyClick(&comboBox, Qt::Key_1);
2031 QTest::keyClick(&comboBox, Qt::Key_Enter);
2032 QCOMPARE(QLatin1String("two1"), comboBox.itemText(comboBox.count() - 1));
2035 // This test requires the Cleanlooks style.
2036 #ifndef QT_NO_STYLE_CLEANLOOKS
2037 void tst_QComboBox::task191329_size()
2039 const QString oldStyle = QApplication::style()->objectName();
2040 QApplication::setStyle(new QCleanlooksStyle);
2042 QComboBox tableCombo;
2044 if (QApplication::desktop()->screenGeometry().height() < 480)
2049 QStandardItemModel model(rows, 2);
2050 for (int row = 0; row < model.rowCount(); ++row) {
2051 for (int column = 0; column < model.columnCount(); ++column) {
2052 QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
2053 model.setItem(row, column, item);
2056 QTableView *table = new QTableView();
2057 table->verticalHeader()->hide();
2058 table->horizontalHeader()->hide();
2059 tableCombo.setView(table);
2060 tableCombo.setModel(&model);
2063 QTRY_VERIFY(tableCombo.isVisible());
2064 tableCombo.showPopup();
2065 QTRY_VERIFY(tableCombo.view());
2066 QTRY_VERIFY(tableCombo.view()->isVisible());
2068 #ifdef QT_BUILD_INTERNAL
2069 QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&tableCombo);
2071 QCOMPARE(static_cast<QAbstractItemView *>(table), qFindChild<QAbstractItemView *>(container));
2072 foreach (QWidget *button, qFindChildren<QComboBoxPrivateScroller *>(container)) {
2073 //the popup should be large enough to contains everithing so the top and left button are hidden
2074 QVERIFY(!button->isVisible());
2078 QApplication::setStyle(oldStyle);
2082 void tst_QComboBox::task190205_setModelAdjustToContents()
2084 QStringList initialContent;
2085 QStringList finalContent;
2086 initialContent << "foo" << "bar";
2087 finalContent << "bar" << "foooooooobar";
2090 box.setSizeAdjustPolicy(QComboBox::AdjustToContents);
2091 box.addItems(initialContent);
2094 //wait needed in order to get the combo initial size
2095 QTRY_VERIFY(box.isVisible());
2097 box.setModel(new QStringListModel(finalContent));
2099 QComboBox correctBox;
2100 correctBox.addItems(finalContent);
2103 QCoreApplication::processEvents();
2105 qt_x11_wait_for_window_manager(&box);
2106 qt_x11_wait_for_window_manager(&correctBox);
2109 // box should be resized to the same size as correctBox
2110 QTRY_COMPARE(box.size(), correctBox.size());
2113 void tst_QComboBox::task248169_popupWithMinimalSize()
2115 QStringList initialContent;
2116 initialContent << "foo" << "bar" << "foobar";
2119 comboBox.addItems(initialContent);
2120 QDesktopWidget desktop;
2121 QRect desktopSize = desktop.availableGeometry();
2122 comboBox.view()->setMinimumWidth(desktopSize.width() / 2);
2124 comboBox.setGeometry(desktopSize.width() - (desktopSize.width() / 4), (desktopSize.width() / 4), (desktopSize.width() / 2), (desktopSize.width() / 4));
2127 QTest::qWaitForWindowShown(&comboBox);
2128 QTRY_VERIFY(comboBox.isVisible());
2129 comboBox.showPopup();
2130 QTRY_VERIFY(comboBox.view());
2131 QTest::qWaitForWindowShown(comboBox.view());
2132 QTRY_VERIFY(comboBox.view()->isVisible());
2134 #ifdef QT_BUILD_INTERNAL
2135 QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&comboBox);
2137 QTRY_VERIFY(desktop.screenGeometry(container).contains(container->geometry()));
2141 void tst_QComboBox::task247863_keyBoardSelection()
2144 combo.setEditable(false);
2145 combo.addItem( QLatin1String("111"));
2146 combo.addItem( QLatin1String("222"));
2148 QApplication::setActiveWindow(&combo);
2149 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2151 QSignalSpy spy(&combo, SIGNAL(activated(const QString &)));
2152 qApp->setEffectEnabled(Qt::UI_AnimateCombo, false);
2153 QTest::keyClick(&combo, Qt::Key_Space);
2154 qApp->setEffectEnabled(Qt::UI_AnimateCombo, true);
2155 QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down);
2156 QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter);
2157 QCOMPARE(combo.currentText(), QLatin1String("222"));
2158 QCOMPARE(spy.count(), 1);
2161 void tst_QComboBox::task220195_keyBoardSelection2()
2164 combo.setEditable(false);
2165 combo.addItem( QLatin1String("foo1"));
2166 combo.addItem( QLatin1String("foo2"));
2167 combo.addItem( QLatin1String("foo3"));
2169 QApplication::setActiveWindow(&combo);
2170 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2172 combo.setCurrentIndex(-1);
2173 QVERIFY(combo.currentText().isNull());
2175 QTest::keyClick(&combo, 'f');
2176 QCOMPARE(combo.currentText(), QLatin1String("foo1"));
2177 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2178 QTest::keyClick(&combo, 'f');
2179 QCOMPARE(combo.currentText(), QLatin1String("foo2"));
2180 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2181 QTest::keyClick(&combo, 'f');
2182 QCOMPARE(combo.currentText(), QLatin1String("foo3"));
2183 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2184 QTest::keyClick(&combo, 'f');
2185 QCOMPARE(combo.currentText(), QLatin1String("foo1"));
2186 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2188 combo.setCurrentIndex(1);
2189 QCOMPARE(combo.currentText(), QLatin1String("foo2"));
2190 QTest::keyClick(&combo, 'f');
2191 QCOMPARE(combo.currentText(), QLatin1String("foo3"));
2195 void tst_QComboBox::setModelColumn()
2197 QStandardItemModel model(5,3);
2198 model.setItem(0,0, new QStandardItem("0"));
2199 model.setItem(1,0, new QStandardItem("1"));
2200 model.setItem(2,0, new QStandardItem("2"));
2201 model.setItem(3,0, new QStandardItem("3"));
2202 model.setItem(4,0, new QStandardItem("4"));
2203 model.setItem(0,1, new QStandardItem("zero"));
2204 model.setItem(1,1, new QStandardItem("un"));
2205 model.setItem(2,1, new QStandardItem("deux"));
2206 model.setItem(3,1, new QStandardItem("trois"));
2207 model.setItem(4,1, new QStandardItem("quatre"));
2208 model.setItem(0,2, new QStandardItem("a"));
2209 model.setItem(1,2, new QStandardItem("b"));
2210 model.setItem(2,2, new QStandardItem("c"));
2211 model.setItem(3,2, new QStandardItem("d"));
2212 model.setItem(4,2, new QStandardItem("e"));
2215 box.setModel(&model);
2216 QCOMPARE(box.currentText(), QString("0"));
2217 box.setModelColumn(1);
2218 QCOMPARE(box.currentText(), QString("zero"));
2221 void tst_QComboBox::noScrollbar_data()
2223 QTest::addColumn<QString>("stylesheet");
2225 QTest::newRow("normal") << QString();
2226 QTest::newRow("border") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue;}");
2227 QTest::newRow("margin") << QString::fromLatin1("QAbstractItemView { margin: 12px 15px 13px 10px; }");
2228 QTest::newRow("padding") << QString::fromLatin1("QAbstractItemView { padding: 12px 15px 13px 10px;}");
2229 QTest::newRow("everything") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue; "
2230 " padding: 12px 15px 13px 10px; margin: 12px 15px 13px 10px; }");
2231 QTest::newRow("everything and more") << QString::fromLatin1("QAbstractItemView { border: 1px 3px 5px 1px solid blue; "
2232 " padding: 2px 5px 3px 1px; margin: 2px 5px 3px 1px; } "
2233 " QAbstractItemView::item { border: 2px solid green; "
2234 " padding: 1px 1px 2px 2px; margin: 1px; } " );
2237 void tst_QComboBox::noScrollbar()
2239 QStringList initialContent;
2240 initialContent << "foo" << "bar" << "foobar" << "moo";
2241 QFETCH(QString, stylesheet);
2242 QString oldCss = qApp->styleSheet();
2243 qApp->setStyleSheet(stylesheet);
2247 QComboBox comboBox(&topLevel);
2248 comboBox.addItems(initialContent);
2250 comboBox.resize(200, comboBox.height());
2251 QTRY_VERIFY(comboBox.isVisible());
2252 comboBox.showPopup();
2253 QTRY_VERIFY(comboBox.view());
2254 QTRY_VERIFY(comboBox.view()->isVisible());
2256 QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
2257 QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
2261 QTableWidget *table = new QTableWidget(2,2);
2263 comboBox.setModel(table->model());
2264 comboBox.setView(table);
2266 QTRY_VERIFY(comboBox.isVisible());
2267 comboBox.resize(200, comboBox.height());
2268 comboBox.showPopup();
2269 QTRY_VERIFY(comboBox.view());
2270 QTRY_VERIFY(comboBox.view()->isVisible());
2272 QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
2273 QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
2276 qApp->setStyleSheet(oldCss);
2279 void tst_QComboBox::setItemDelegate()
2282 QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
2283 comboBox.setItemDelegate(itemDelegate);
2284 // the cast is a workaround for the XLC and Metrowerks compilers
2285 QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2288 void tst_QComboBox::task253944_itemDelegateIsReset()
2291 QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
2292 comboBox.setItemDelegate(itemDelegate);
2294 // the casts are workarounds for the XLC and Metrowerks compilers
2296 comboBox.setEditable(true);
2297 QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2299 comboBox.setStyleSheet("QComboBox { border: 1px solid gray; }");
2300 QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2304 void tst_QComboBox::subControlRectsWithOffset_data()
2306 QTest::addColumn<bool>("editable");
2308 QTest::newRow("editable = true") << true;
2309 QTest::newRow("editable = false") << false;
2312 void tst_QComboBox::subControlRectsWithOffset()
2314 // The sub control rect relative position should not depends
2315 // on the position of the combobox
2317 class FriendlyCombo : public QComboBox {
2319 void styleOption(QStyleOptionComboBox *optCombo) {
2320 initStyleOption(optCombo);
2323 QStyleOptionComboBox optCombo;
2324 combo.styleOption(&optCombo);
2327 const QRect rectAtOrigin(0, 0, 80, 30);
2328 const QPoint offset(25, 50);
2329 const QRect rectWithOffset = rectAtOrigin.translated(offset);
2331 QStyle *style = combo.style();
2333 QFETCH(bool, editable);
2334 optCombo.editable = editable;
2336 optCombo.rect = rectAtOrigin;
2337 QRect editFieldRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
2338 QRect arrowRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
2339 QRect listboxRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
2341 optCombo.rect = rectWithOffset;
2342 QRect editFieldRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
2343 QRect arrowRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
2344 QRect listboxRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
2346 QCOMPARE(editFieldRect, editFieldRectWithOffset.translated(-offset));
2347 QCOMPARE(arrowRect, arrowRectWithOffset.translated(-offset));
2348 QCOMPARE(listboxRect, listboxRectWithOffset.translated(-offset));
2352 // This test depends on Windows style.
2353 #ifndef QT_NO_STYLE_WINDOWS
2354 void tst_QComboBox::task260974_menuItemRectangleForComboBoxPopup()
2356 class TestStyle: public QWindowsStyle
2359 int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *ret) const
2361 if (hint == SH_ComboBox_Popup) return 1;
2362 else return QCommonStyle::styleHint(hint, option, widget, ret);
2365 void drawControl(ControlElement element, const QStyleOption *option, QPainter *, const QWidget *) const
2367 if (element == CE_MenuItem)
2368 discoveredRect = option->rect;
2371 mutable QRect discoveredRect;
2377 comboBox.setStyle(&style);
2378 comboBox.addItem("Item 1");
2381 QTRY_VERIFY(comboBox.isVisible());
2382 comboBox.showPopup();
2383 QTRY_VERIFY(comboBox.view());
2384 QTRY_VERIFY(comboBox.view()->isVisible());
2386 QTRY_VERIFY(style.discoveredRect.width() <= comboBox.width());
2391 void tst_QComboBox::removeItem()
2397 QCOMPARE(cb.count(), 0);
2401 QCOMPARE(cb.count(), 1);
2403 QCOMPARE(cb.count(), 1);
2405 QCOMPARE(cb.count(), 0);
2408 void tst_QComboBox::resetModel()
2410 class StringListModel : public QStringListModel
2413 StringListModel(const QStringList &list) : QStringListModel(list)
2419 QStringListModel::reset();
2423 StringListModel model( QStringList() << "1" << "2");
2424 QSignalSpy spy(&cb, SIGNAL(currentIndexChanged(int)));
2425 QCOMPARE(spy.count(), 0);
2426 QCOMPARE(cb.currentIndex(), -1); //no selection
2428 cb.setModel(&model);
2430 QCOMPARE(spy.count(), 1);
2431 QCOMPARE(cb.currentIndex(), 0); //first item selected
2434 QCOMPARE(spy.count(), 2);
2435 QCOMPARE(cb.currentIndex(), -1); //no selection
2439 void tst_QComboBox::keyBoardNavigationWithMouse()
2442 combo.setEditable(false);
2443 for (int i = 0; i < 80; i++)
2444 combo.addItem( QString::number(i));
2446 QApplication::setActiveWindow(&combo);
2447 QTest::qWaitForWindowShown(&combo);
2448 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2450 QCOMPARE(combo.currentText(), QLatin1String("0"));
2453 QTRY_VERIFY(combo.hasFocus());
2455 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Space);
2457 QTRY_VERIFY(combo.view());
2458 QTRY_VERIFY(combo.view()->isVisible());
2461 QCOMPARE(combo.currentText(), QLatin1String("0"));
2463 // When calling cursor function, Windows CE responds with: This function is not supported on this system.
2465 // Force cursor movement to prevent QCursor::setPos() from returning prematurely on QPA:
2466 const QPoint target(combo.view()->mapToGlobal(combo.view()->rect().center()));
2467 QCursor::setPos(QPoint(target.x() + 1, target.y()));
2468 QCursor::setPos(target);
2472 #define GET_SELECTION(SEL) \
2473 QCOMPARE(combo.view()->selectionModel()->selection().count(), 1); \
2474 QCOMPARE(combo.view()->selectionModel()->selection().indexes().count(), 1); \
2475 SEL = combo.view()->selectionModel()->selection().indexes().first().row()
2478 GET_SELECTION(selection);
2480 //since we moved the mouse is in the middle it should even be around 5;
2481 QVERIFY(selection > 3);
2483 static const int final = 40;
2484 for (int i = selection + 1; i <= final; i++)
2486 QTest::keyClick(combo.view(), Qt::Key_Down);
2488 GET_SELECTION(selection);
2489 QCOMPARE(selection, i);
2492 QTest::keyClick(combo.view(), Qt::Key_Enter);
2493 QTRY_COMPARE(combo.currentText(), QString::number(final));
2497 void tst_QComboBox::task_QTBUG_1071_changingFocusEmitsActivated()
2500 QVBoxLayout layout(&w);
2502 cb.setEditable(true);
2503 QSignalSpy spy(&cb, SIGNAL(activated(int)));
2508 layout.addWidget(&cb);
2509 layout.addWidget(&edit);
2512 QApplication::setActiveWindow(&w);
2513 QTest::qWaitForWindowShown(&w);
2516 QApplication::processEvents();
2517 QTRY_VERIFY(cb.hasFocus());
2518 QTest::keyClick(static_cast<QWidget *>(0), '1');
2519 QCOMPARE(spy.count(), 0);
2521 QTRY_VERIFY(edit.hasFocus());
2522 QTRY_COMPARE(spy.count(), 1);
2525 void tst_QComboBox::maxVisibleItems()
2528 QCOMPARE(comboBox.maxVisibleItems(), 10); //default value.
2530 QStringList content;
2531 for(int i = 1; i < 50; i++)
2532 content += QString::number(i);
2534 comboBox.addItems(content);
2536 comboBox.resize(200, comboBox.height());
2537 QTRY_VERIFY(comboBox.isVisible());
2539 comboBox.setMaxVisibleItems(5);
2540 QCOMPARE(comboBox.maxVisibleItems(), 5);
2542 comboBox.showPopup();
2543 QTRY_VERIFY(comboBox.view());
2544 QTRY_VERIFY(comboBox.view()->isVisible());
2546 QAbstractItemView *v = comboBox.view();
2547 int itemHeight = v->visualRect(v->model()->index(0,0)).height();
2548 QListView *lv = qobject_cast<QListView*>(v);
2550 itemHeight += lv->spacing();
2551 QStyleOptionComboBox opt;
2552 opt.initFrom(&comboBox);
2553 if (!comboBox.style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
2554 QCOMPARE(v->viewport()->height(), itemHeight * comboBox.maxVisibleItems());
2557 void tst_QComboBox::task_QTBUG_10491_currentIndexAndModelColumn()
2561 QStandardItemModel model(4, 4, &comboBox);
2562 for (int i = 0; i < 4; i++){
2563 model.setItem(i, 0, new QStandardItem(QString("Employee Nr %1").arg(i)));
2564 model.setItem(i, 1, new QStandardItem(QString("Street Nr %1").arg(i)));
2565 model.setItem(i, 2, new QStandardItem(QString("Town Nr %1").arg(i)));
2566 model.setItem(i, 3, new QStandardItem(QString("Phone Nr %1").arg(i)));
2568 comboBox.setModel(&model);
2569 comboBox.setModelColumn(0);
2571 QComboBoxPrivate *d = static_cast<QComboBoxPrivate *>(QComboBoxPrivate::get(&comboBox));
2572 d->setCurrentIndex(model.index(2, 2));
2573 QCOMPARE(QModelIndex(d->currentIndex), model.index(2, comboBox.modelColumn()));
2576 QTEST_MAIN(tst_QComboBox)
2577 #include "tst_qcombobox.moc"