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 test suite 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 <QtTest/QtTest>
43
44 #include "qcombobox.h"
45 #include <private/qcombobox_p.h>
46
47 #include <qfontcombobox.h>
48 #include <qdesktopwidget.h>
49 #include <qapplication.h>
50 #include <qpushbutton.h>
51 #include <qdialog.h>
52 #include <qevent.h>
53 #include <qlineedit.h>
54 #include <qlistview.h>
55 #include <qheaderview.h>
56 #include <qlistwidget.h>
57 #include <qtreewidget.h>
58 #include <qtablewidget.h>
59 #include <qscrollbar.h>
60 #include <qboxlayout.h>
61 #ifdef Q_WS_MAC
62 #include <qmacstyle_mac.h>
63 #elif defined Q_WS_X11
64 #include <private/qt_x11_p.h>
65 #endif
66
67 #include <qstandarditemmodel.h>
68 #include <qstringlistmodel.h>
69 #include <qcombobox.h>
70 #include <qpushbutton.h>
71 #include <qdialog.h>
72 #include <qstringlist.h>
73 #include <qvalidator.h>
74 #include <qcompleter.h>
75 #ifndef QT_NO_STYLE_CLEANLOOKS
76 #include <qcleanlooksstyle.h>
77 #endif
78 #include <qabstractitemview.h>
79 #include "../../shared/util.h"
80 #include <qstyleditemdelegate.h>
81 #ifndef QT_NO_STYLE_WINDOWS
82 #include <qwindowsstyle.h>
83 #endif
84
85 //TESTED_CLASS=
86 //TESTED_FILES=
87
88 class tst_QComboBox : public QObject
89 {
90 Q_OBJECT
91
92 public:
93 tst_QComboBox();
94 ~tst_QComboBox();
95
96 public slots:
97 void initTestCase();
98 void cleanupTestCase();
99 void init();
100 void cleanup();
101
102 private slots:
103 void getSetCheck();
104 void ensureReturnIsIgnored();
105 void setEditable();
106 void setPalette();
107 void sizeAdjustPolicy();
108 void clear();
109 void insertPolicy_data();
110 void insertPolicy();
111 void virtualAutocompletion();
112 void autoCompletionCaseSensitivity();
113 void hide();
114 void currentIndex_data();
115 void currentIndex();
116 void insertItems_data();
117 void insertItems();
118 void insertItem_data();
119 void insertItem();
120 void insertOnCurrentIndex();
121 void textpixmapdata_data();
122 void textpixmapdata();
123 void editTextChanged();
124 void setModel();
125 void modelDeleted();
126 void setMaxCount();
127 void setCurrentIndex();
128 void convenienceViews();
129 void findText_data();
130 void findText();
131 void flaggedItems_data();
132 void flaggedItems();
133 void pixmapIcon();
134 void mouseWheel_data();
135 void mouseWheel();
136 void layoutDirection();
137 void itemListPosition();
138 void separatorItem_data();
139 void separatorItem();
140 void task190351_layout();
141 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();
149 void noScrollbar();
150 void setItemDelegate();
151 void task253944_itemDelegateIsReset();
152 void subControlRectsWithOffset_data();
153 void subControlRectsWithOffset();
154 void task260974_menuItemRectangleForComboBoxPopup();
155 void removeItem();
156 void resetModel();
157 void keyBoardNavigationWithMouse();
158 void task_QTBUG_1071_changingFocusEmitsActivated();
159 void maxVisibleItems();
160 void task_QTBUG_10491_currentIndexAndModelColumn();
161
162 private:
163 QComboBox *testWidget;
164 QWidget *parent;
165 QPushButton* ok;
166 };
167
168 class MyAbstractItemDelegate : public QAbstractItemDelegate
169 {
170 public:
MyAbstractItemDelegate()171 MyAbstractItemDelegate() : QAbstractItemDelegate() {};
paint(QPainter *,const QStyleOptionViewItem &,const QModelIndex &) const172 void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
sizeHint(const QStyleOptionViewItem &,const QModelIndex &) const173 QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
174 };
175
176 class MyAbstractItemModel: public QAbstractItemModel
177 {
178 public:
MyAbstractItemModel()179 MyAbstractItemModel() : QAbstractItemModel() {};
index(int,int,const QModelIndex &) const180 QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); }
parent(const QModelIndex &) const181 QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
rowCount(const QModelIndex &) const182 int rowCount(const QModelIndex &) const { return 0; }
columnCount(const QModelIndex &) const183 int columnCount(const QModelIndex &) const { return 0; }
hasChildren(const QModelIndex &) const184 bool hasChildren(const QModelIndex &) const { return false; }
data(const QModelIndex &,int) const185 QVariant data(const QModelIndex &, int) const { return QVariant(); }
setData(const QModelIndex &,const QVariant &,int)186 bool setData(const QModelIndex &, const QVariant &, int) { return false; }
insertRows(int,int,const QModelIndex &)187 bool insertRows(int, int, const QModelIndex &) { return false; }
insertColumns(int,int,const QModelIndex &)188 bool insertColumns(int, int, const QModelIndex &) { return false; }
setPersistent(const QModelIndex &,const QModelIndex &)189 void setPersistent(const QModelIndex &, const QModelIndex &) {}
removeRows(int,int,const QModelIndex &)190 bool removeRows (int, int, const QModelIndex &) { return false; }
removeColumns(int,int,const QModelIndex &)191 bool removeColumns(int, int, const QModelIndex &) { return false; }
reset()192 void reset() {}
193 };
194
195 class MyAbstractItemView : public QAbstractItemView
196 {
197 public:
MyAbstractItemView()198 MyAbstractItemView() : QAbstractItemView() {}
visualRect(const QModelIndex &) const199 QRect visualRect(const QModelIndex &) const { return QRect(); }
scrollTo(const QModelIndex &,ScrollHint)200 void scrollTo(const QModelIndex &, ScrollHint) {}
indexAt(const QPoint &) const201 QModelIndex indexAt(const QPoint &) const { return QModelIndex(); }
202 protected:
moveCursor(CursorAction,Qt::KeyboardModifiers)203 QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers) { return QModelIndex(); }
horizontalOffset() const204 int horizontalOffset() const { return 0; }
verticalOffset() const205 int verticalOffset() const { return 0; }
isIndexHidden(const QModelIndex &) const206 bool isIndexHidden(const QModelIndex &) const { return false; }
setSelection(const QRect &,QItemSelectionModel::SelectionFlags)207 void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) {}
visualRegionForSelection(const QItemSelection &) const208 QRegion visualRegionForSelection(const QItemSelection &) const { return QRegion(); }
209 };
210
211 // Testing get/set functions
getSetCheck()212 void tst_QComboBox::getSetCheck()
213 {
214 QComboBox obj1;
215 // int QComboBox::maxVisibleItems()
216 // void QComboBox::setMaxVisibleItems(int)
217 obj1.setMaxVisibleItems(100);
218 QCOMPARE(100, obj1.maxVisibleItems());
219 obj1.setMaxVisibleItems(0);
220 QCOMPARE(obj1.maxVisibleItems(), 0);
221 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxVisibleItems: "
222 "Invalid max visible items (-2147483648) must be >= 0");
223 obj1.setMaxVisibleItems(INT_MIN);
224 QCOMPARE(obj1.maxVisibleItems(), 0); // Cannot be set to something negative => old value
225 obj1.setMaxVisibleItems(INT_MAX);
226 QCOMPARE(INT_MAX, obj1.maxVisibleItems());
227
228 // int QComboBox::maxCount()
229 // void QComboBox::setMaxCount(int)
230 obj1.setMaxCount(0);
231 QCOMPARE(0, obj1.maxCount());
232 #ifndef QT_DEBUG
233 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxCount: Invalid count (-2147483648) must be >= 0");
234 obj1.setMaxCount(INT_MIN);
235 QCOMPARE(0, obj1.maxCount()); // Setting a value below 0 makes no sense, and shouldn't be allowed
236 #endif
237 obj1.setMaxCount(INT_MAX);
238 QCOMPARE(INT_MAX, obj1.maxCount());
239
240 // bool QComboBox::autoCompletion()
241 // void QComboBox::setAutoCompletion(bool)
242 obj1.setAutoCompletion(false);
243 QCOMPARE(false, obj1.autoCompletion());
244 obj1.setAutoCompletion(true);
245 QCOMPARE(true, obj1.autoCompletion());
246
247 // bool QComboBox::duplicatesEnabled()
248 // void QComboBox::setDuplicatesEnabled(bool)
249 obj1.setDuplicatesEnabled(false);
250 QCOMPARE(false, obj1.duplicatesEnabled());
251 obj1.setDuplicatesEnabled(true);
252 QCOMPARE(true, obj1.duplicatesEnabled());
253
254 // InsertPolicy QComboBox::insertPolicy()
255 // void QComboBox::setInsertPolicy(InsertPolicy)
256 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::NoInsert));
257 QCOMPARE(QComboBox::InsertPolicy(QComboBox::NoInsert), obj1.insertPolicy());
258 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtTop));
259 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtTop), obj1.insertPolicy());
260 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtCurrent));
261 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtCurrent), obj1.insertPolicy());
262 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtBottom));
263 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtBottom), obj1.insertPolicy());
264 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAfterCurrent));
265 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAfterCurrent), obj1.insertPolicy());
266 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertBeforeCurrent));
267 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertBeforeCurrent), obj1.insertPolicy());
268 obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAlphabetically));
269 QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAlphabetically), obj1.insertPolicy());
270
271 // SizeAdjustPolicy QComboBox::sizeAdjustPolicy()
272 // void QComboBox::setSizeAdjustPolicy(SizeAdjustPolicy)
273 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents));
274 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents), obj1.sizeAdjustPolicy());
275 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow));
276 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow), obj1.sizeAdjustPolicy());
277 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength));
278 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength), obj1.sizeAdjustPolicy());
279 obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon));
280 QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon), obj1.sizeAdjustPolicy());
281
282 // int QComboBox::minimumContentsLength()
283 // void QComboBox::setMinimumContentsLength(int)
284 obj1.setMinimumContentsLength(0);
285 QCOMPARE(0, obj1.minimumContentsLength());
286 obj1.setMinimumContentsLength(100);
287 QCOMPARE(100, obj1.minimumContentsLength());
288 obj1.setMinimumContentsLength(INT_MIN);
289 QCOMPARE(100, obj1.minimumContentsLength()); // Cannot be set to something negative => old value
290 obj1.setMinimumContentsLength(INT_MAX);
291 QCOMPARE(INT_MAX, obj1.minimumContentsLength());
292
293 // QLineEdit * QComboBox::lineEdit()
294 // void QComboBox::setLineEdit(QLineEdit *)
295 QLineEdit *var8 = new QLineEdit(0);
296 obj1.setLineEdit(var8);
297 QCOMPARE(var8, obj1.lineEdit());
298 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setLineEdit: cannot set a 0 line edit");
299 obj1.setLineEdit((QLineEdit *)0);
300 QCOMPARE(var8, obj1.lineEdit());
301 // delete var8; // No delete, since QComboBox takes ownership
302
303 // const QValidator * QComboBox::validator()
304 // void QComboBox::setValidator(const QValidator *)
305 QIntValidator *var9 = new QIntValidator(0);
306 obj1.setValidator(var9);
307 QCOMPARE(obj1.validator(), (const QValidator *)var9);
308 obj1.setValidator((QValidator *)0);
309 QCOMPARE(obj1.validator(), (const QValidator *)0);
310 delete var9;
311
312 // QAbstractItemDelegate * QComboBox::itemDelegate()
313 // void QComboBox::setItemDelegate(QAbstractItemDelegate *)
314 MyAbstractItemDelegate *var10 = new MyAbstractItemDelegate;
315 obj1.setItemDelegate(var10);
316 QCOMPARE(obj1.itemDelegate(), (QAbstractItemDelegate *)var10);
317 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setItemDelegate: cannot set a 0 delegate");
318 obj1.setItemDelegate((QAbstractItemDelegate *)0);
319 QCOMPARE(obj1.itemDelegate(), (QAbstractItemDelegate *)var10);
320 // delete var10; // No delete, since QComboBox takes ownership
321
322 // QAbstractItemModel * QComboBox::model()
323 // void QComboBox::setModel(QAbstractItemModel *)
324 MyAbstractItemModel *var11 = new MyAbstractItemModel;
325 obj1.setModel(var11);
326 QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
327 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setModel: cannot set a 0 model");
328 obj1.setModel((QAbstractItemModel *)0);
329 QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
330 delete var11;
331 obj1.model();
332
333 // int QComboBox::modelColumn()
334 // void QComboBox::setModelColumn(int)
335 obj1.setModelColumn(0);
336 QCOMPARE(0, obj1.modelColumn());
337 obj1.setModelColumn(INT_MIN);
338 // QCOMPARE(0, obj1.modelColumn()); // Cannot be set to something negative => column 0
339 obj1.setModelColumn(INT_MAX);
340 QCOMPARE(INT_MAX, obj1.modelColumn());
341 obj1.setModelColumn(0); // back to normal
342
343 // QAbstractItemView * QComboBox::view()
344 // void QComboBox::setView(QAbstractItemView *)
345 MyAbstractItemView *var13 = new MyAbstractItemView;
346 obj1.setView(var13);
347 QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
348 QTest::ignoreMessage(QtWarningMsg, "QComboBox::setView: cannot set a 0 view");
349 obj1.setView((QAbstractItemView *)0);
350 QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
351 delete var13;
352
353 // int QComboBox::currentIndex()
354 // void QComboBox::setCurrentIndex(int)
355 obj1.setEditable(false);
356 obj1.setCurrentIndex(0);
357 QCOMPARE(-1, obj1.currentIndex());
358 obj1.setCurrentIndex(INT_MIN);
359 QCOMPARE(-1, obj1.currentIndex());
360 obj1.setCurrentIndex(INT_MAX);
361 QCOMPARE(-1, obj1.currentIndex());
362 obj1.addItems(QStringList() << "1" << "2" << "3" << "4" << "5");
363 obj1.setCurrentIndex(0);
364 QCOMPARE(0, obj1.currentIndex()); // Valid
365 obj1.setCurrentIndex(INT_MIN);
366 QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
367 obj1.setCurrentIndex(4);
368 QCOMPARE(4, obj1.currentIndex()); // Valid
369 obj1.setCurrentIndex(INT_MAX);
370 QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
371 }
372
373 typedef QList<QVariant> VariantList;
374 typedef QList<QIcon> IconList;
375
376 Q_DECLARE_METATYPE(VariantList)
Q_DECLARE_METATYPE(IconList)377 Q_DECLARE_METATYPE(IconList)
378 Q_DECLARE_METATYPE(QComboBox::InsertPolicy)
379
380 tst_QComboBox::tst_QComboBox()
381 {
382 qRegisterMetaType<QModelIndex>("QModelIndex");
383 parent = 0;
384 }
385
~tst_QComboBox()386 tst_QComboBox::~tst_QComboBox()
387 {
388 }
389
390
initTestCase()391 void tst_QComboBox::initTestCase()
392 {
393 // Create the test class
394 parent = new QWidget(0, Qt::Window);
395 parent->setObjectName("parent");
396 parent->resize(400, 400);
397 testWidget = new QComboBox(parent);
398 testWidget->setObjectName("testObject");
399 testWidget->setGeometry(0, 0, 100, 100);
400 parent->show();
401 }
402
cleanupTestCase()403 void tst_QComboBox::cleanupTestCase()
404 {
405 delete parent;
406 parent = 0;
407 }
408
409
init()410 void tst_QComboBox::init()
411 {
412 // all tests starts with a clean non-editable combobox
413 testWidget->setEditable(false);
414 testWidget->clear();
415 #ifdef Q_OS_WINCE //disable magic for WindowsCE
416 qApp->setAutoMaximizeThreshold(-1);
417 #endif
418 }
419
cleanup()420 void tst_QComboBox::cleanup()
421 {
422 //nothing
423 }
424
425
setEditable()426 void tst_QComboBox::setEditable()
427 {
428 // make sure we have no lineedit
429 QVERIFY(!testWidget->lineEdit());
430 // test setEditable(true)
431 testWidget->setEditable(true);
432 QVERIFY(testWidget->lineEdit());
433 testWidget->addItem("foo");
434 QCOMPARE(testWidget->lineEdit()->text(), QString("foo"));
435 // test setEditable(false)
436
437 QLineEdit *lineEdit = testWidget->lineEdit();
438 // line edit is visible when combobox is editable
439 QVERIFY(lineEdit->isVisible());
440 testWidget->setEditable(false);
441 QVERIFY(!testWidget->lineEdit());
442 // line edit should have been explicitly hidden when editable was turned off
443 QVERIFY(!lineEdit->isVisible());
444 }
445
446
setPalette()447 void tst_QComboBox::setPalette()
448 {
449 #ifdef Q_WS_MAC
450 if (qobject_cast<QMacStyle *>(testWidget->style())) {
451 QSKIP("This test doesn't make sense for pixmap-based styles", SkipAll);
452 }
453 #endif
454 QPalette pal = testWidget->palette();
455 pal.setColor(QPalette::Base, Qt::red);
456 testWidget->setPalette(pal);
457 testWidget->setEditable(!testWidget->isEditable());
458
459 pal.setColor(QPalette::Base, Qt::blue);
460 testWidget->setPalette(pal);
461
462 const QObjectList comboChildren = testWidget->children();
463 for (int i = 0; i < comboChildren.size(); ++i) {
464 QObject *o = comboChildren.at(i);
465 if (o->isWidgetType()) {
466 QVERIFY(((QWidget*)o)->palette() == pal);
467 }
468 }
469
470 testWidget->setEditable(true);
471 pal.setColor(QPalette::Base, Qt::red);
472 //Setting it on the lineedit should be separate form the combo
473 testWidget->lineEdit()->setPalette(pal);
474 QVERIFY(testWidget->palette() != pal);
475 QVERIFY(testWidget->lineEdit()->palette() == pal);
476 pal.setColor(QPalette::Base, Qt::green);
477 //Setting it on the combo directly should override lineedit
478 testWidget->setPalette(pal);
479 QVERIFY(testWidget->palette() == pal);
480 QVERIFY(testWidget->lineEdit()->palette() == pal);
481 }
482
sizeAdjustPolicy()483 void tst_QComboBox::sizeAdjustPolicy()
484 {
485 // test that adding new items will not change the sizehint for AdjustToContentsOnFirstShow
486 QVERIFY(!testWidget->count());
487 QVERIFY(testWidget->sizeAdjustPolicy() == QComboBox::AdjustToContentsOnFirstShow);
488 QVERIFY(testWidget->isVisible());
489 QSize firstShow = testWidget->sizeHint();
490 testWidget->addItem("normal item");
491 QCOMPARE(testWidget->sizeHint(), firstShow);
492
493 // check that with minimumContentsLength/AdjustToMinimumContentsLength sizehint changes
494 testWidget->setMinimumContentsLength(30);
495 QCOMPARE(testWidget->sizeHint(), firstShow);
496 testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
497 QSize minimumContentsLength = testWidget->sizeHint();
498 QVERIFY(minimumContentsLength.width() > firstShow.width());
499 testWidget->setMinimumContentsLength(60);
500 QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
501
502 // check that with minimumContentsLength/AdjustToMinimumContentsLengthWithIcon sizehint changes
503 testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
504 testWidget->setMinimumContentsLength(30);
505 minimumContentsLength = testWidget->sizeHint();
506 QVERIFY(minimumContentsLength.width() > firstShow.width());
507 testWidget->setMinimumContentsLength(60);
508 QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
509 minimumContentsLength = testWidget->sizeHint();
510 testWidget->setIconSize(QSize(128,128));
511 QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
512
513 // check AdjustToContents changes with content
514 testWidget->setSizeAdjustPolicy(QComboBox::AdjustToContents);
515 QSize content = testWidget->sizeHint();
516 testWidget->addItem("small");
517 QCOMPARE(testWidget->sizeHint(), content);
518 testWidget->addItem("looooooooooooooooooooooong item");
519 // minimumContentsLength() > sizeof("looooooooooooooooooooooong item"), so the sizeHint()
520 // stays the same
521 QCOMPARE(testWidget->sizeHint(), content);
522 // over 60 characters (cf. setMinimumContentsLength() call above)
523 testWidget->addItem("loooooooooooooooooooooooooooooooooooooooooooooo"
524 "ooooooooooooooooooooooooooooooooooooooooooooooo"
525 "ooooooooooooooooooooooooooooong item");
526 QVERIFY(testWidget->sizeHint().width() > content.width());
527
528 // check AdjustToContents also shrinks when item changes
529 content = testWidget->sizeHint();
530 for (int i=0; i<testWidget->count(); ++i)
531 testWidget->setItemText(i, "XXXXXXXXXX");
532 QVERIFY(testWidget->sizeHint().width() < content.width());
533
534 // check AdjustToContents shrinks when items are removed
535 content = testWidget->sizeHint();
536 while (testWidget->count())
537 testWidget->removeItem(0);
538 QCOMPARE(testWidget->sizeHint(), content);
539 testWidget->setMinimumContentsLength(0);
540 QVERIFY(testWidget->sizeHint().width() < content.width());
541 }
542
clear()543 void tst_QComboBox::clear()
544 {
545 // first non editable combobox
546 testWidget->addItem("foo");
547 testWidget->addItem("bar");
548 QVERIFY(testWidget->count() > 0);
549 QCOMPARE(testWidget->currentIndex(), 0);
550
551 testWidget->clear();
552 QCOMPARE(testWidget->count(), 0);
553 QCOMPARE(testWidget->currentIndex(), -1);
554 QVERIFY(testWidget->currentText().isEmpty());
555
556 // then editable combobox
557 testWidget->clear();
558 testWidget->setEditable(true);
559 testWidget->addItem("foo");
560 testWidget->addItem("bar");
561 QVERIFY(testWidget->count() > 0);
562 QCOMPARE(testWidget->currentIndex(), 0);
563 QVERIFY(testWidget->lineEdit());
564 QVERIFY(!testWidget->lineEdit()->text().isEmpty());
565 testWidget->clear();
566 QCOMPARE(testWidget->count(), 0);
567 QCOMPARE(testWidget->currentIndex(), -1);
568 QVERIFY(testWidget->currentText().isEmpty());
569 QVERIFY(testWidget->lineEdit()->text().isEmpty());
570 }
571
insertPolicy_data()572 void tst_QComboBox::insertPolicy_data()
573 {
574 QTest::addColumn<QStringList>("initialEntries");
575 QTest::addColumn<QComboBox::InsertPolicy>("insertPolicy");
576 QTest::addColumn<int>("currentIndex");
577 QTest::addColumn<QString>("userInput");
578 QTest::addColumn<QStringList>("result");
579
580 /* Each insertPolicy should test at least:
581 no initial entries
582 one initial entry
583 five initial entries, current is first item
584 five initial entries, current is third item
585 five initial entries, current is last item
586 */
587
588 /* QComboBox::NoInsert - the string will not be inserted into the combobox.
589 QComboBox::InsertAtTop - insert the string as the first item in the combobox.
590 QComboBox::InsertAtCurrent - replace the previously selected item with the string the user has entered.
591 QComboBox::InsertAtBottom - insert the string as the last item in the combobox.
592 QComboBox::InsertAfterCurrent - insert the string after the previously selected item.
593 QComboBox::InsertBeforeCurrent - insert the string before the previously selected item.
594 QComboBox::InsertAlphabetically - insert the string at the alphabetic position.
595 */
596 QStringList initial;
597 QStringList oneEntry("One");
598 QStringList fiveEntries;
599 fiveEntries << "One" << "Two" << "Three" << "Four" << "Five";
600 QString input("insert");
601
602 {
603 QTest::newRow("NoInsert-NoInitial") << initial << QComboBox::NoInsert << 0 << input << initial;
604 QTest::newRow("NoInsert-OneInitial") << oneEntry << QComboBox::NoInsert << 0 << input << oneEntry;
605 QTest::newRow("NoInsert-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::NoInsert << 0 << input << fiveEntries;
606 QTest::newRow("NoInsert-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::NoInsert << 2 << input << fiveEntries;
607 QTest::newRow("NoInsert-FiveInitial-LastCurrent") << fiveEntries << QComboBox::NoInsert << 4 << input << fiveEntries;
608 }
609
610 {
611 QStringList initialAtTop("insert");
612 QStringList oneAtTop;
613 oneAtTop << "insert" << "One";
614 QStringList fiveAtTop;
615 fiveAtTop << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
616
617 QTest::newRow("AtTop-NoInitial") << initial << QComboBox::InsertAtTop << 0 << input << initialAtTop;
618 QTest::newRow("AtTop-OneInitial") << oneEntry << QComboBox::InsertAtTop << 0 << input << oneAtTop;
619 QTest::newRow("AtTop-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtTop << 0 << input << fiveAtTop;
620 QTest::newRow("AtTop-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtTop << 2 << input << fiveAtTop;
621 QTest::newRow("AtTop-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtTop << 4 << input << fiveAtTop;
622 }
623
624 {
625 QStringList initialAtCurrent("insert");
626 QStringList oneAtCurrent("insert");
627 QStringList fiveAtCurrentFirst;
628 fiveAtCurrentFirst << "insert" << "Two" << "Three" << "Four" << "Five";
629 QStringList fiveAtCurrentThird;
630 fiveAtCurrentThird << "One" << "Two" << "insert" << "Four" << "Five";
631 QStringList fiveAtCurrentLast;
632 fiveAtCurrentLast << "One" << "Two" << "Three" << "Four" << "insert";
633
634 QTest::newRow("AtCurrent-NoInitial") << initial << QComboBox::InsertAtCurrent << 0 << input << initialAtCurrent;
635 QTest::newRow("AtCurrent-OneInitial") << oneEntry << QComboBox::InsertAtCurrent << 0 << input << oneAtCurrent;
636 QTest::newRow("AtCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 0 << input << fiveAtCurrentFirst;
637 QTest::newRow("AtCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 2 << input << fiveAtCurrentThird;
638 QTest::newRow("AtCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 4 << input << fiveAtCurrentLast;
639 }
640
641 {
642 QStringList initialAtBottom("insert");
643 QStringList oneAtBottom;
644 oneAtBottom << "One" << "insert";
645 QStringList fiveAtBottom;
646 fiveAtBottom << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
647
648 QTest::newRow("AtBottom-NoInitial") << initial << QComboBox::InsertAtBottom << 0 << input << initialAtBottom;
649 QTest::newRow("AtBottom-OneInitial") << oneEntry << QComboBox::InsertAtBottom << 0 << input << oneAtBottom;
650 QTest::newRow("AtBottom-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtBottom << 0 << input << fiveAtBottom;
651 QTest::newRow("AtBottom-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtBottom << 2 << input << fiveAtBottom;
652 QTest::newRow("AtBottom-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtBottom << 4 << input << fiveAtBottom;
653 }
654
655 {
656 QStringList initialAfterCurrent("insert");
657 QStringList oneAfterCurrent;
658 oneAfterCurrent << "One" << "insert";
659 QStringList fiveAfterCurrentFirst;
660 fiveAfterCurrentFirst << "One" << "insert" << "Two" << "Three" << "Four" << "Five";
661 QStringList fiveAfterCurrentThird;
662 fiveAfterCurrentThird << "One" << "Two" << "Three" << "insert" << "Four" << "Five";
663 QStringList fiveAfterCurrentLast;
664 fiveAfterCurrentLast << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
665
666 QTest::newRow("AfterCurrent-NoInitial") << initial << QComboBox::InsertAfterCurrent << 0 << input << initialAfterCurrent;
667 QTest::newRow("AfterCurrent-OneInitial") << oneEntry << QComboBox::InsertAfterCurrent << 0 << input << oneAfterCurrent;
668 QTest::newRow("AfterCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 0 << input << fiveAfterCurrentFirst;
669 QTest::newRow("AfterCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 2 << input << fiveAfterCurrentThird;
670 QTest::newRow("AfterCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 4 << input << fiveAfterCurrentLast;
671 }
672
673 {
674 QStringList initialBeforeCurrent("insert");
675 QStringList oneBeforeCurrent;
676 oneBeforeCurrent << "insert" << "One";
677 QStringList fiveBeforeCurrentFirst;
678 fiveBeforeCurrentFirst << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
679 QStringList fiveBeforeCurrentThird;
680 fiveBeforeCurrentThird << "One" << "Two" << "insert" << "Three" << "Four" << "Five";
681 QStringList fiveBeforeCurrentLast;
682 fiveBeforeCurrentLast << "One" << "Two" << "Three" << "Four" << "insert" << "Five";
683
684 QTest::newRow("BeforeCurrent-NoInitial") << initial << QComboBox::InsertBeforeCurrent << 0 << input << initialBeforeCurrent;
685 QTest::newRow("BeforeCurrent-OneInitial") << oneEntry << QComboBox::InsertBeforeCurrent << 0 << input << oneBeforeCurrent;
686 QTest::newRow("BeforeCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 0 << input << fiveBeforeCurrentFirst;
687 QTest::newRow("BeforeCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 2 << input << fiveBeforeCurrentThird;
688 QTest::newRow("BeforeCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 4 << input << fiveBeforeCurrentLast;
689 }
690
691 {
692 oneEntry.clear();
693 oneEntry << "foobar";
694 fiveEntries.clear();
695 fiveEntries << "bar" << "foo" << "initial" << "Item" << "stamp";
696
697 QStringList initialAlphabetically("insert");
698 QStringList oneAlphabetically;
699 oneAlphabetically << "foobar" << "insert";
700 QStringList fiveAlphabetically;
701 fiveAlphabetically << "bar" << "foo" << "initial" << "insert" << "Item" << "stamp";
702
703 QTest::newRow("Alphabetically-NoInitial") << initial << QComboBox::InsertAlphabetically << 0 << input << initialAlphabetically;
704 QTest::newRow("Alphabetically-OneInitial") << oneEntry << QComboBox::InsertAlphabetically << 0 << input << oneAlphabetically;
705 QTest::newRow("Alphabetically-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 0 << input << fiveAlphabetically;
706 QTest::newRow("Alphabetically-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 2 << input << fiveAlphabetically;
707 QTest::newRow("Alphabetically-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 4 << input << fiveAlphabetically;
708 }
709 }
710
insertPolicy()711 void tst_QComboBox::insertPolicy()
712 {
713 QFETCH(QStringList, initialEntries);
714 QFETCH(QComboBox::InsertPolicy, insertPolicy);
715 QFETCH(int, currentIndex);
716 QFETCH(QString, userInput);
717 QFETCH(QStringList, result);
718
719 testWidget->clear();
720 testWidget->setInsertPolicy(insertPolicy);
721 testWidget->addItems(initialEntries);
722 testWidget->setEditable(true);
723 if (initialEntries.count() > 0)
724 testWidget->setCurrentIndex(currentIndex);
725
726 // clear
727 QTest::mouseDClick(testWidget->lineEdit(), Qt::LeftButton);
728 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Delete);
729
730 QTest::keyClicks(testWidget->lineEdit(), userInput);
731 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Return);
732
733 // First check that there is the right number of entries, or
734 // we may unwittingly pass
735 QVERIFY((int)result.count() == testWidget->count());
736
737 // No need to compare if there are no strings to compare
738 if (result.count() > 0) {
739 for (int i=0; i<testWidget->count(); ++i) {
740 QCOMPARE(testWidget->itemText(i), result.at(i));
741 }
742 }
743 }
744
745
virtualAutocompletion()746 void tst_QComboBox::virtualAutocompletion()
747 {
748 testWidget->clear();
749 testWidget->setAutoCompletion(true);
750 testWidget->addItem("Foo");
751 testWidget->addItem("Bar");
752 testWidget->addItem("Boat");
753 testWidget->addItem("Boost");
754 testWidget->clearEditText();
755
756 // We need to set the keyboard input interval to a higher value
757 // as the processEvent() call takes too much time, so it restarts
758 // the keyboard search then
759 #if defined(QT_ARCH_ARM) || defined(QT_ARCH_MIPS) || defined(QT_ARCH_SYMBIAN)
760 int oldInterval = QApplication::keyboardInputInterval();
761 QApplication::setKeyboardInputInterval(1500);
762 #endif
763
764 // NOTE:
765 // Cannot use keyClick for this test, as it simulates keyclicks too well
766 // The virtual keyboards we're trying to catch here, do not perform that
767 // well, and send a keypress & keyrelease right after each other.
768 // This provokes the actual error, as there's no events in between to do
769 // the text completion.
770 QKeyEvent kp1(QEvent::KeyPress, Qt::Key_B, 0, "b");
771 QKeyEvent kr1(QEvent::KeyRelease, Qt::Key_B, 0, "b");
772 QApplication::sendEvent(testWidget, &kp1);
773 QApplication::sendEvent(testWidget, &kr1);
774
775 qApp->processEvents(); // Process events to trigger autocompletion
776 QTRY_VERIFY(testWidget->currentIndex() == 1);
777
778 #ifdef QTEST_RUNNING_USING_VALGRIND
779 QSKIP("App running with valgrind are not fast enough", SkipAll);
780 #endif
781
782 QKeyEvent kp2(QEvent::KeyPress, Qt::Key_O, 0, "o");
783 QKeyEvent kr2(QEvent::KeyRelease, Qt::Key_O, 0, "o");
784
785 QApplication::sendEvent(testWidget, &kp2);
786 QApplication::sendEvent(testWidget, &kr2);
787
788 qApp->processEvents(); // Process events to trigger autocompletion
789 QTRY_COMPARE(testWidget->currentIndex(), 2);
790
791 QApplication::sendEvent(testWidget, &kp2);
792 QApplication::sendEvent(testWidget, &kr2);
793 qApp->processEvents(); // Process events to trigger autocompletion
794 QTRY_COMPARE(testWidget->currentIndex(), 3);
795 #if defined(QT_ARCH_ARM) || defined(QT_ARCH_MIPS) || defined(QT_ARCH_SYMBIAN)
796 QApplication::setKeyboardInputInterval(oldInterval);
797 #endif
798 }
799
autoCompletionCaseSensitivity()800 void tst_QComboBox::autoCompletionCaseSensitivity()
801 {
802 //we have put the focus because the completer
803 //is only used when the widget actually has the focus
804 testWidget->setFocus();
805 qApp->setActiveWindow(testWidget);
806 QTRY_COMPARE(qApp->focusWidget(), (QWidget *)testWidget);
807
808 testWidget->clear();
809 testWidget->setAutoCompletion(true);
810 testWidget->addItem("Cow");
811 testWidget->addItem("irrelevant1");
812 testWidget->addItem("aww");
813 testWidget->addItem("A*");
814 testWidget->addItem("irrelevant2");
815 testWidget->addItem("aBCDEF");
816 testWidget->addItem("irrelevant3");
817 testWidget->addItem("abcdef");
818 testWidget->addItem("abCdef");
819 testWidget->setEditable(true);
820
821 // case insensitive
822 testWidget->clearEditText();
823 QSignalSpy spyReturn(testWidget, SIGNAL(activated(int)));
824 testWidget->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
825 QVERIFY(testWidget->autoCompletionCaseSensitivity() == Qt::CaseInsensitive);
826
827 QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
828 qApp->processEvents();
829 QCOMPARE(testWidget->currentText(), QString("aww"));
830 QCOMPARE(spyReturn.count(), 0);
831
832 QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
833 qApp->processEvents();
834 // autocompletions preserve userkey-case from 4.2
835 QCOMPARE(testWidget->currentText(), QString("abCDEF"));
836 QCOMPARE(spyReturn.count(), 0);
837
838 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
839 qApp->processEvents();
840 QCOMPARE(testWidget->currentText(), QString("aBCDEF")); // case restored to item's case
841 QCOMPARE(spyReturn.count(), 1);
842
843 testWidget->clearEditText();
844 QTest::keyClick(testWidget->lineEdit(), 'c');
845 QCOMPARE(testWidget->currentText(), QString("cow"));
846 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
847 QCOMPARE(testWidget->currentText(), QString("Cow")); // case restored to item's case
848
849 testWidget->clearEditText();
850 QTest::keyClick(testWidget->lineEdit(), 'a');
851 QTest::keyClick(testWidget->lineEdit(), '*');
852 QCOMPARE(testWidget->currentText(), QString("a*"));
853 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
854 QCOMPARE(testWidget->currentText(), QString("A*"));
855
856 // case sensitive
857 testWidget->clearEditText();
858 testWidget->setAutoCompletionCaseSensitivity(Qt::CaseSensitive);
859 QVERIFY(testWidget->autoCompletionCaseSensitivity() == Qt::CaseSensitive);
860 QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
861 qApp->processEvents();
862 QCOMPARE(testWidget->currentText(), QString("aww"));
863 QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
864 qApp->processEvents();
865 QCOMPARE(testWidget->currentText(), QString("abcdef"));
866
867 testWidget->setCurrentIndex(0); // to reset the completion's "start"
868 testWidget->clearEditText();
869 QTest::keyClick(testWidget->lineEdit(), 'a');
870 QTest::keyClick(testWidget->lineEdit(), 'b');
871 QCOMPARE(testWidget->currentText(), QString("abcdef"));
872 QTest::keyClick(testWidget->lineEdit(), 'C');
873 qApp->processEvents();
874 QCOMPARE(testWidget->currentText(), QString("abCdef"));
875 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
876 qApp->processEvents();
877 QCOMPARE(testWidget->currentText(), QString("abCdef")); // case restored to item's case
878
879 testWidget->clearEditText();
880 QTest::keyClick(testWidget->lineEdit(), 'c');
881 QCOMPARE(testWidget->currentText(), QString("c"));
882 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Backspace);
883 QTest::keyClick(testWidget->lineEdit(), 'C');
884 QCOMPARE(testWidget->currentText(), QString("Cow"));
885 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
886 QCOMPARE(testWidget->currentText(), QString("Cow"));
887
888 testWidget->clearEditText();
889 QTest::keyClick(testWidget->lineEdit(), 'a');
890 QTest::keyClick(testWidget->lineEdit(), '*');
891 QCOMPARE(testWidget->currentText(), QString("a*"));
892 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
893 QCOMPARE(testWidget->currentText(), QString("a*")); // A* not matched
894 }
895
hide()896 void tst_QComboBox::hide()
897 {
898 testWidget->addItem("foo");
899 testWidget->showPopup();
900 //allow combobox effect to complete
901 QTRY_VERIFY(testWidget->view());
902 QTRY_VERIFY(testWidget->view()->isVisible());
903 testWidget->hidePopup();
904 //allow combobox effect to complete
905 QTRY_VERIFY(!testWidget->view()->isVisible());
906 testWidget->hide();
907 QVERIFY(!testWidget->isVisible());
908 }
909
910
911
currentIndex_data()912 void tst_QComboBox::currentIndex_data()
913 {
914 QTest::addColumn<QStringList>("initialItems");
915 QTest::addColumn<int>("setCurrentIndex");
916 QTest::addColumn<int>("removeIndex");
917 QTest::addColumn<int>("insertIndex");
918 QTest::addColumn<QString>("insertText");
919 QTest::addColumn<int>("expectedCurrentIndex");
920 QTest::addColumn<QString>("expectedCurrentText");
921 QTest::addColumn<int>("expectedSignalCount");
922
923 QStringList initialItems;
924 int setCurrentIndex;
925 int removeIndex;
926 int insertIndex;
927 QString insertText;
928 int expectedCurrentIndex;
929 QString expectedCurrentText;
930 int expectedSignalCount;
931
932 {
933 initialItems.clear();
934 initialItems << "foo" << "bar";
935 setCurrentIndex = -2;
936 removeIndex = -1;
937 insertIndex = -1;
938 insertText = "";
939 expectedCurrentIndex = 0;
940 expectedCurrentText = "foo";
941 expectedSignalCount = 1;
942 QTest::newRow("first added item is set to current if there is no current")
943 << initialItems << setCurrentIndex << removeIndex
944 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
945 << expectedSignalCount;
946 }
947 {
948 initialItems.clear();
949 initialItems << "foo" << "bar";
950 setCurrentIndex = 1;
951 removeIndex = -1;
952 insertIndex = -1;
953 insertText = "";
954 expectedCurrentIndex = 1;
955 expectedCurrentText = "bar";
956 expectedSignalCount = 2;
957 QTest::newRow("check that setting the index works")
958 << initialItems << setCurrentIndex << removeIndex
959 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
960 << expectedSignalCount;
961
962 }
963 {
964 initialItems.clear();
965 initialItems << "foo" << "bar";
966 setCurrentIndex = -1; // will invalidate the currentIndex
967 removeIndex = -1;
968 insertIndex = -1;
969 insertText = "";
970 expectedCurrentIndex = -1;
971 expectedCurrentText = "";
972 expectedSignalCount = 2;
973 QTest::newRow("check that isetting the index to -1 works")
974 << initialItems << setCurrentIndex << removeIndex
975 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
976 << expectedSignalCount;
977
978 }
979 {
980 initialItems.clear();
981 initialItems << "foo";
982 setCurrentIndex = 0;
983 removeIndex = 0;
984 insertIndex = -1;
985 insertText = "";
986 expectedCurrentIndex = -1;
987 expectedCurrentText = "";
988 expectedSignalCount = 2;
989 QTest::newRow("check that current index is invalid when removing the only item")
990 << initialItems << setCurrentIndex << removeIndex
991 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
992 << expectedSignalCount;
993 }
994 {
995 initialItems.clear();
996 initialItems << "foo" << "bar";
997 setCurrentIndex = 1;
998 removeIndex = 0;
999 insertIndex = -1;
1000 insertText = "";
1001 expectedCurrentIndex = 0;
1002 expectedCurrentText = "bar";
1003 expectedSignalCount = 3;
1004 QTest::newRow("check that the current index follows the item when removing an item above")
1005 << initialItems << setCurrentIndex << removeIndex
1006 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1007 << expectedSignalCount;
1008
1009 }
1010 {
1011 initialItems.clear();
1012 initialItems << "foo" << "bar" << "baz";
1013 setCurrentIndex = 1;
1014 removeIndex = 1;
1015 insertIndex = -1;
1016 insertText = "";
1017 expectedCurrentIndex = 1;
1018 expectedCurrentText = "baz";
1019 expectedSignalCount = 3;
1020 QTest::newRow("check that the current index uses the next item if current is removed")
1021 << initialItems << setCurrentIndex << removeIndex
1022 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1023 << expectedSignalCount;
1024 }
1025 {
1026 initialItems.clear();
1027 initialItems << "foo" << "bar" << "baz";
1028 setCurrentIndex = 2;
1029 removeIndex = 2;
1030 insertIndex = -1;
1031 insertText = "";
1032 expectedCurrentIndex = 1;
1033 expectedCurrentText = "bar";
1034 expectedSignalCount = 3;
1035 QTest::newRow("check that the current index is moved to the one before if current is removed")
1036 << initialItems << setCurrentIndex << removeIndex
1037 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1038 << expectedSignalCount;
1039 }
1040 {
1041 initialItems.clear();
1042 initialItems << "foo" << "bar" << "baz";
1043 setCurrentIndex = 1;
1044 removeIndex = 2;
1045 insertIndex = -1;
1046 insertText = "";
1047 expectedCurrentIndex = 1;
1048 expectedCurrentText = "bar";
1049 expectedSignalCount = 2;
1050 QTest::newRow("check that the current index is unchanged if you remove an item after")
1051 << initialItems << setCurrentIndex << removeIndex
1052 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1053 << expectedSignalCount;
1054 }
1055 {
1056 initialItems.clear();
1057 initialItems << "foo" << "bar";
1058 setCurrentIndex = 1;
1059 removeIndex = -1;
1060 insertIndex = 0;
1061 insertText = "baz";
1062 expectedCurrentIndex = 2;
1063 expectedCurrentText = "bar";
1064 expectedSignalCount = 3;
1065 QTest::newRow("check that the current index follows the item if you insert before current")
1066 << initialItems << setCurrentIndex << removeIndex
1067 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1068 << expectedSignalCount;
1069 }
1070 {
1071 initialItems.clear();
1072 initialItems << "foo";
1073 setCurrentIndex = 0;
1074 removeIndex = -1;
1075 insertIndex = 0;
1076 insertText = "bar";
1077 expectedCurrentIndex = 1;
1078 expectedCurrentText = "foo";
1079 expectedSignalCount = 2;
1080 QTest::newRow("check that the current index follows the item if you insert on the current")
1081 << initialItems << setCurrentIndex << removeIndex
1082 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1083 << expectedSignalCount;
1084 }
1085 {
1086 initialItems.clear();
1087 initialItems << "foo";
1088 setCurrentIndex = 0;
1089 removeIndex = -1;
1090 insertIndex = 1;
1091 insertText = "bar";
1092 expectedCurrentIndex = 0;
1093 expectedCurrentText = "foo";
1094 expectedSignalCount = 1;
1095 QTest::newRow("check that the current index stays the same if you insert after the current")
1096 << initialItems << setCurrentIndex << removeIndex
1097 << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1098 << expectedSignalCount;
1099 }
1100 }
1101
currentIndex()1102 void tst_QComboBox::currentIndex()
1103 {
1104 QFETCH(QStringList, initialItems);
1105 QFETCH(int, setCurrentIndex);
1106 QFETCH(int, removeIndex);
1107 QFETCH(int, insertIndex);
1108 QFETCH(QString, insertText);
1109 QFETCH(int, expectedCurrentIndex);
1110 QFETCH(QString, expectedCurrentText);
1111 QFETCH(int, expectedSignalCount);
1112
1113 // test both editable/non-editable combobox
1114 for (int edit = 0; edit < 2; ++edit) {
1115 testWidget->clear();
1116 testWidget->setEditable(edit ? true : false);
1117 if (edit)
1118 QVERIFY(testWidget->lineEdit());
1119
1120 // verify it is empty, has no current index and no current text
1121 QCOMPARE(testWidget->count(), 0);
1122 QCOMPARE(testWidget->currentIndex(), -1);
1123 QVERIFY(testWidget->currentText().isEmpty());
1124
1125 // spy on currentIndexChanged
1126 QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int)));
1127 QSignalSpy indexChangedString(testWidget, SIGNAL(currentIndexChanged(const QString&)));
1128
1129 // stuff items into it
1130 foreach(QString text, initialItems) {
1131 testWidget->addItem(text);
1132 }
1133 QCOMPARE(testWidget->count(), initialItems.count());
1134
1135 // set current index, remove and/or insert
1136 if (setCurrentIndex >= -1) {
1137 testWidget->setCurrentIndex(setCurrentIndex);
1138 QCOMPARE(testWidget->currentIndex(), setCurrentIndex);
1139 }
1140
1141 if (removeIndex >= 0)
1142 testWidget->removeItem(removeIndex);
1143 if (insertIndex >= 0)
1144 testWidget->insertItem(insertIndex, insertText);
1145
1146 // compare with expected index and text
1147 QCOMPARE(testWidget->currentIndex(), expectedCurrentIndex);
1148 QCOMPARE(testWidget->currentText(), expectedCurrentText);
1149
1150 // check that signal count is correct
1151 QCOMPARE(indexChangedInt.count(), expectedSignalCount);
1152 QCOMPARE(indexChangedString.count(), expectedSignalCount);
1153
1154 // compare with last sent signal values
1155 if (indexChangedInt.count())
1156 QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(),
1157 testWidget->currentIndex());
1158 if (indexChangedString.count())
1159 QCOMPARE(indexChangedString.at(indexChangedString.count() - 1).at(0).toString(),
1160 testWidget->currentText());
1161
1162 if (edit) {
1163 testWidget->setCurrentIndex(-1);
1164 testWidget->setInsertPolicy(QComboBox::InsertAtBottom);
1165 QTest::keyPress(testWidget, 'a');
1166 QTest::keyPress(testWidget, 'b');
1167 QCOMPARE(testWidget->currentText(), QString("ab"));
1168 QCOMPARE(testWidget->currentIndex(), -1);
1169 int numItems = testWidget->count();
1170 QTest::keyPress(testWidget, Qt::Key_Return);
1171 QCOMPARE(testWidget->count(), numItems + 1);
1172 QCOMPARE(testWidget->currentIndex(), numItems);
1173 testWidget->setCurrentIndex(-1);
1174 QTest::keyPress(testWidget, 'a');
1175 QTest::keyPress(testWidget, 'b');
1176 QCOMPARE(testWidget->currentIndex(), -1);
1177 }
1178 }
1179 }
1180
insertItems_data()1181 void tst_QComboBox::insertItems_data()
1182 {
1183 QTest::addColumn<QStringList>("initialItems");
1184 QTest::addColumn<QStringList>("insertedItems");
1185 QTest::addColumn<int>("insertIndex");
1186 QTest::addColumn<int>("expectedIndex");
1187
1188 QStringList initialItems;
1189 QStringList insertedItems;
1190
1191 initialItems << "foo" << "bar";
1192 insertedItems << "mongo";
1193
1194 QTest::newRow("prepend") << initialItems << insertedItems << 0 << 0;
1195 QTest::newRow("prepend with negative value") << initialItems << insertedItems << -1 << 0;
1196 QTest::newRow("append") << initialItems << insertedItems << initialItems.count() << initialItems.count();
1197 QTest::newRow("append with too high value") << initialItems << insertedItems << 999 << initialItems.count();
1198 QTest::newRow("insert") << initialItems << insertedItems << 1 << 1;
1199 }
1200
insertItems()1201 void tst_QComboBox::insertItems()
1202 {
1203 QFETCH(QStringList, initialItems);
1204 QFETCH(QStringList, insertedItems);
1205 QFETCH(int, insertIndex);
1206 QFETCH(int, expectedIndex);
1207
1208 testWidget->insertItems(0, initialItems);
1209 QCOMPARE(testWidget->count(), initialItems.count());
1210
1211 testWidget->insertItems(insertIndex, insertedItems);
1212
1213 QCOMPARE(testWidget->count(), initialItems.count() + insertedItems.count());
1214 for (int i=0; i<insertedItems.count(); ++i)
1215 QCOMPARE(testWidget->itemText(expectedIndex + i), insertedItems.at(i));
1216 }
1217
insertItem_data()1218 void tst_QComboBox::insertItem_data()
1219 {
1220 QTest::addColumn<QStringList>("initialItems");
1221 QTest::addColumn<int>("insertIndex");
1222 QTest::addColumn<QString>("itemLabel");
1223 QTest::addColumn<int>("expectedIndex");
1224 QTest::addColumn<bool>("testQt3Support");
1225 QTest::addColumn<bool>("editable");
1226
1227 QStringList initialItems;
1228 initialItems << "foo" << "bar";
1229 for(int e = 0 ; e<2 ; e++) {
1230 bool editable = (e==0);
1231 QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0 << false << editable;
1232 QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0 << false << editable;
1233 QTest::newRow("Insert beyond count") << initialItems << 3 << "inserted" << 2 << false << editable;
1234 QTest::newRow("Insert at count") << initialItems << 2 << "inserted" << 2 << false << editable;
1235 QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1 << false << editable;
1236 #if defined(QT3_SUPPORT)
1237 QTest::newRow("Qt3Support: Insert less then 0") << initialItems << -1 << "inserted" << 2 << true << editable;
1238 #endif
1239 }
1240 }
1241
insertItem()1242 void tst_QComboBox::insertItem()
1243 {
1244 QFETCH(QStringList, initialItems);
1245 QFETCH(int, insertIndex);
1246 QFETCH(QString, itemLabel);
1247 QFETCH(int, expectedIndex);
1248 QFETCH(bool, testQt3Support);
1249 QFETCH(bool, editable);
1250
1251 testWidget->insertItems(0, initialItems);
1252 QCOMPARE(testWidget->count(), initialItems.count());
1253
1254 testWidget->setEditable(true);
1255 if (editable)
1256 testWidget->setEditText("FOO");
1257 #if defined (QT3_SUPPORT)
1258 if (testQt3Support)
1259 testWidget->insertItem(itemLabel, insertIndex);
1260 else
1261 testWidget->insertItem(insertIndex, itemLabel);
1262 #else
1263 Q_UNUSED(testQt3Support);
1264 testWidget->insertItem(insertIndex, itemLabel);
1265 #endif
1266
1267
1268 QCOMPARE(testWidget->count(), initialItems.count() + 1);
1269 QCOMPARE(testWidget->itemText(expectedIndex), itemLabel);
1270
1271 if (editable)
1272 QCOMPARE(testWidget->currentText(), QString("FOO"));
1273 }
1274
insertOnCurrentIndex()1275 void tst_QComboBox::insertOnCurrentIndex()
1276 {
1277 testWidget->setEditable(true);
1278 testWidget->addItem("first item");
1279 testWidget->setCurrentIndex(0);
1280 testWidget->insertItem(0, "second item");
1281 QCOMPARE(testWidget->lineEdit()->text(), QString::fromAscii("first item"));
1282 }
1283
textpixmapdata_data()1284 void tst_QComboBox::textpixmapdata_data()
1285 {
1286 QTest::addColumn<QStringList>("text");
1287 QTest::addColumn<IconList>("icons");
1288 QTest::addColumn<VariantList>("variant");
1289
1290 QStringList text;
1291 IconList icon;
1292 VariantList variant;
1293
1294 {
1295 text.clear(); icon.clear(); variant.clear();
1296 text << "foo" << "bar";
1297 icon << QIcon() << QIcon();
1298 variant << QVariant() << QVariant();
1299 QTest::newRow("just text") << text << icon << variant;
1300 }
1301 {
1302 text.clear(); icon.clear(); variant.clear();
1303 text << QString() << QString();
1304 icon << QIcon(QPixmap("qtlogo.png")) << QIcon(QPixmap("qtlogoinverted.png"));
1305 variant << QVariant() << QVariant();
1306 QTest::newRow("just icons") << text << icon << variant;
1307 }
1308 {
1309 text.clear(); icon.clear(); variant.clear();
1310 text << QString() << QString();
1311 icon << QIcon() << QIcon();
1312 variant << 12 << "bingo";
1313 QTest::newRow("just user data") << text << icon << variant;
1314 }
1315 {
1316 text.clear(); icon.clear(); variant.clear();
1317 text << "foo" << "bar";
1318 icon << QIcon(QPixmap("qtlogo.png")) << QIcon(QPixmap("qtlogoinverted.png"));
1319 variant << 12 << "bingo";
1320 QTest::newRow("text, icons and user data") << text << icon << variant;
1321 }
1322 }
1323
textpixmapdata()1324 void tst_QComboBox::textpixmapdata()
1325 {
1326 QFETCH(QStringList, text);
1327 QFETCH(IconList, icons);
1328 QFETCH(VariantList, variant);
1329
1330 QVERIFY(text.count() == icons.count() && text.count() == variant.count());
1331
1332 for (int i = 0; i<text.count(); ++i) {
1333 testWidget->insertItem(i, text.at(i));
1334 testWidget->setItemIcon(i, icons.at(i));
1335 testWidget->setItemData(i, variant.at(i), Qt::UserRole);
1336 }
1337
1338 QCOMPARE(testWidget->count(), text.count());
1339
1340 for (int i = 0; i<text.count(); ++i) {
1341 QIcon icon = testWidget->itemIcon(i);
1342 QVERIFY(icon.serialNumber() == icons.at(i).serialNumber());
1343 QPixmap original = icons.at(i).pixmap(1024);
1344 QPixmap pixmap = icon.pixmap(1024);
1345 QVERIFY(pixmap.toImage() == original.toImage());
1346 }
1347
1348 for (int i = 0; i<text.count(); ++i) {
1349 QCOMPARE(testWidget->itemText(i), text.at(i));
1350 // ### we should test icons/pixmap as well, but I need to fix the api mismatch first
1351 QCOMPARE(testWidget->itemData(i, Qt::UserRole), variant.at(i));
1352 }
1353 }
1354
setCurrentIndex()1355 void tst_QComboBox::setCurrentIndex()
1356 {
1357 QCOMPARE(testWidget->count(), 0);
1358 testWidget->addItem("foo");
1359 testWidget->addItem("bar");
1360 QCOMPARE(testWidget->count(), 2);
1361
1362 QCOMPARE(testWidget->currentIndex(), 0);
1363 testWidget->setCurrentIndex(0);
1364 QCOMPARE(testWidget->currentText(), QString("foo"));
1365
1366 testWidget->setCurrentIndex(1);
1367 QCOMPARE(testWidget->currentText(), QString("bar"));
1368
1369 testWidget->setCurrentIndex(0);
1370 QCOMPARE(testWidget->currentText(), QString("foo"));
1371 }
1372
editTextChanged()1373 void tst_QComboBox::editTextChanged()
1374 {
1375 QCOMPARE(testWidget->count(), 0);
1376 testWidget->addItem("foo");
1377 testWidget->addItem("bar");
1378 QCOMPARE(testWidget->count(), 2);
1379
1380 // first we test non editable
1381 testWidget->setEditable(false);
1382 QCOMPARE(testWidget->isEditable(), false);
1383
1384 QSignalSpy spy(testWidget, SIGNAL(editTextChanged(QString)));
1385
1386 // no signal should be sent when current is set to the same
1387 QCOMPARE(testWidget->currentIndex(), 0);
1388 testWidget->setCurrentIndex(0);
1389 QCOMPARE(testWidget->currentIndex(), 0);
1390 QCOMPARE(spy.count(), 0);
1391
1392 // no signal should be sent when changing to other index because we are not editable
1393 QCOMPARE(testWidget->currentIndex(), 0);
1394 testWidget->setCurrentIndex(1);
1395 QCOMPARE(testWidget->currentIndex(), 1);
1396 QCOMPARE(spy.count(), 0);
1397
1398 // now set to editable and reset current index
1399 testWidget->setEditable(true);
1400 QCOMPARE(testWidget->isEditable(), true);
1401 testWidget->setCurrentIndex(0);
1402
1403 // no signal should be sent when current is set to the same
1404 spy.clear();
1405 QCOMPARE(testWidget->currentIndex(), 0);
1406 testWidget->setCurrentIndex(0);
1407 QCOMPARE(testWidget->currentIndex(), 0);
1408 QCOMPARE(spy.count(), 0);
1409
1410 // signal should be sent when changing to other index
1411 QCOMPARE(testWidget->currentIndex(), 0);
1412 testWidget->setCurrentIndex(1);
1413 QCOMPARE(testWidget->currentIndex(), 1);
1414 QCOMPARE(spy.count(), 1);
1415 QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("bar"));
1416
1417
1418 // insert some keys and notice they are all signaled
1419 spy.clear();
1420 QTest::keyClicks(testWidget, "bingo");
1421 QCOMPARE(spy.count(), 5);
1422 QCOMPARE(qvariant_cast<QString>(spy.at(4).at(0)), QString("barbingo"));
1423 }
1424
setModel()1425 void tst_QComboBox::setModel()
1426 {
1427 QComboBox box;
1428 QCOMPARE(box.currentIndex(), -1);
1429 box.addItems((QStringList() << "foo" << "bar"));
1430 QCOMPARE(box.currentIndex(), 0);
1431 box.setCurrentIndex(1);
1432 QCOMPARE(box.currentIndex(), 1);
1433
1434 // check that currentIndex is set to invalid
1435 QAbstractItemModel *oldModel = box.model();
1436 box.setModel(new QStandardItemModel(&box));
1437 QCOMPARE(box.currentIndex(), -1);
1438 QVERIFY(box.model() != oldModel);
1439
1440 // check that currentIndex is set to first item
1441 oldModel = box.model();
1442 box.setModel(new QStandardItemModel(2,1, &box));
1443 QCOMPARE(box.currentIndex(), 0);
1444 QVERIFY(box.model() != oldModel);
1445 }
1446
modelDeleted()1447 void tst_QComboBox::modelDeleted()
1448 {
1449 QComboBox box;
1450 QStandardItemModel *model = new QStandardItemModel;
1451 box.setModel(model);
1452 QCOMPARE(box.model(), static_cast<QAbstractItemModel *>(model));
1453 delete model;
1454 QVERIFY(box.model());
1455 QCOMPARE(box.findText("bubu"), -1);
1456
1457 delete box.model();
1458 QVERIFY(box.model());
1459 delete box.model();
1460 QVERIFY(box.model());
1461 }
1462
setMaxCount()1463 void tst_QComboBox::setMaxCount()
1464 {
1465 QStringList items;
1466 items << "1" << "2" << "3" << "4" << "5";
1467
1468 QComboBox box;
1469 box.addItems(items);
1470 QCOMPARE(box.count(), 5);
1471
1472 box.setMaxCount(4);
1473 QCOMPARE(box.count(), 4);
1474 QCOMPARE(box.itemText(0), QString("1"));
1475 QCOMPARE(box.itemText(1), QString("2"));
1476 QCOMPARE(box.itemText(2), QString("3"));
1477 QCOMPARE(box.itemText(3), QString("4"));
1478
1479 // appending should do nothing
1480 box.addItem("foo");
1481 QCOMPARE(box.count(), 4);
1482 QCOMPARE(box.findText("foo"), -1);
1483
1484 // inserting one item at top should remove the last
1485 box.insertItem(0, "0");
1486 QCOMPARE(box.count(), 4);
1487 QCOMPARE(box.itemText(0), QString("0"));
1488 QCOMPARE(box.itemText(1), QString("1"));
1489 QCOMPARE(box.itemText(2), QString("2"));
1490 QCOMPARE(box.itemText(3), QString("3"));
1491
1492 // insert 5 items in a box with maxCount 4
1493 box.insertItems(0, items);
1494 QCOMPARE(box.count(), 4);
1495 QCOMPARE(box.itemText(0), QString("1"));
1496 QCOMPARE(box.itemText(1), QString("2"));
1497 QCOMPARE(box.itemText(2), QString("3"));
1498 QCOMPARE(box.itemText(3), QString("4"));
1499
1500 // insert 5 items at pos 2. Make sure only two get inserted
1501 QSignalSpy spy(box.model(), SIGNAL(rowsInserted(QModelIndex,int,int)));
1502 box.insertItems(2, items);
1503 QCOMPARE(spy.count(), 1);
1504 QCOMPARE(spy.at(0).at(1).toInt(), 2);
1505 QCOMPARE(spy.at(0).at(2).toInt(), 3);
1506
1507 QCOMPARE(box.count(), 4);
1508 QCOMPARE(box.itemText(0), QString("1"));
1509 QCOMPARE(box.itemText(1), QString("2"));
1510 QCOMPARE(box.itemText(2), QString("1"));
1511 QCOMPARE(box.itemText(3), QString("2"));
1512
1513 box.insertItems(0, QStringList());
1514 QCOMPARE(box.count(), 4);
1515
1516 box.setMaxCount(0);
1517 QCOMPARE(box.count(), 0);
1518 box.addItem("foo");
1519 QCOMPARE(box.count(), 0);
1520 box.addItems(items);
1521 QCOMPARE(box.count(), 0);
1522 }
1523
convenienceViews()1524 void tst_QComboBox::convenienceViews()
1525 {
1526 // QListWidget
1527 QComboBox listCombo;
1528 QListWidget *list = new QListWidget();
1529 listCombo.setModel(list->model());
1530 listCombo.setView(list);
1531 // add items
1532 list->addItem("list0");
1533 listCombo.addItem("list1");
1534 QCOMPARE(listCombo.count(), 2);
1535 QCOMPARE(listCombo.itemText(0), QString("list0"));
1536 QCOMPARE(listCombo.itemText(1), QString("list1"));
1537
1538 // QTreeWidget
1539 QComboBox treeCombo;
1540 QTreeWidget *tree = new QTreeWidget();
1541 tree->setColumnCount(1);
1542 tree->header()->hide();
1543 treeCombo.setModel(tree->model());
1544 treeCombo.setView(tree);
1545 // add items
1546 tree->addTopLevelItem(new QTreeWidgetItem(QStringList("tree0")));
1547 treeCombo.addItem("tree1");
1548 QCOMPARE(treeCombo.count(), 2);
1549 QCOMPARE(treeCombo.itemText(0), QString("tree0"));
1550 QCOMPARE(treeCombo.itemText(1), QString("tree1"));
1551
1552 // QTableWidget
1553 QComboBox tableCombo;
1554 QTableWidget *table = new QTableWidget(0,1);
1555 table->verticalHeader()->hide();
1556 table->horizontalHeader()->hide();
1557 tableCombo.setModel(table->model());
1558 tableCombo.setView(table);
1559 // add items
1560 table->setRowCount(table->rowCount() + 1);
1561 table->setItem(0, table->rowCount() - 1, new QTableWidgetItem("table0"));
1562 tableCombo.addItem("table1");
1563 QCOMPARE(tableCombo.count(), 2);
1564 QCOMPARE(tableCombo.itemText(0), QString("table0"));
1565 QCOMPARE(tableCombo.itemText(1), QString("table1"));
1566 }
1567
1568 class ReturnClass : public QWidget
1569 {
1570 Q_OBJECT
1571 public:
ReturnClass(QWidget * parent=0)1572 ReturnClass(QWidget *parent = 0)
1573 : QWidget(parent), received(false)
1574 {
1575 QComboBox *box = new QComboBox(this);
1576 box->setEditable(true);
1577 edit = box->lineEdit();
1578 box->setGeometry(rect());
1579 }
1580
keyPressEvent(QKeyEvent * e)1581 void keyPressEvent(QKeyEvent *e)
1582 {
1583 received = (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter);
1584 }
1585
1586 QLineEdit *edit;
1587
1588 bool received;
1589
1590 };
1591
1592
1593
ensureReturnIsIgnored()1594 void tst_QComboBox::ensureReturnIsIgnored()
1595 {
1596 ReturnClass r;
1597 r.show();
1598
1599 QTest::keyClick(r.edit, Qt::Key_Return);
1600 QVERIFY(r.received);
1601 r.received = false;
1602 QTest::keyClick(r.edit, Qt::Key_Enter);
1603 QVERIFY(r.received);
1604 }
1605
1606
findText_data()1607 void tst_QComboBox::findText_data()
1608 {
1609 QTest::addColumn<QStringList>("items");
1610 QTest::addColumn<int>("matchflags");
1611 QTest::addColumn<QString>("search");
1612 QTest::addColumn<int>("result");
1613
1614 QStringList list;
1615 list << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "one";
1616 QTest::newRow("CaseSensitive_1") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1617 << QString("Two") << 1;
1618 QTest::newRow("CaseSensitive_2") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1619 << QString("two") << -1;
1620 QTest::newRow("CaseSensitive_3") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1621 << QString("One") << 0;
1622 QTest::newRow("CaseSensitive_4") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1623 << QString("one") << 6;
1624 QTest::newRow("CaseInsensitive_1") << list << (int)(Qt::MatchExactly) << QString("Two") << 1;
1625 QTest::newRow("CaseInsensitive_2") << list << (int)(Qt::MatchExactly) << QString("two") << -1;
1626 QTest::newRow("CaseInsensitive_3") << list << (int)(Qt::MatchExactly) << QString("One") << 0;
1627 QTest::newRow("CaseInsensitive_4") << list << (int)(Qt::MatchExactly) << QString("one") << 6;
1628 }
findText()1629 void tst_QComboBox::findText()
1630 {
1631 QFETCH(QStringList, items);
1632 QFETCH(int, matchflags);
1633 QFETCH(QString, search);
1634 QFETCH(int, result);
1635
1636 testWidget->clear();
1637 testWidget->addItems(items);
1638
1639 QCOMPARE(testWidget->findText(search, (Qt::MatchFlags)matchflags), result);
1640 }
1641
1642 typedef QList<int> IntList;
1643 typedef QList<Qt::Key> KeyList;
1644 Q_DECLARE_METATYPE(IntList)
Q_DECLARE_METATYPE(KeyList)1645 Q_DECLARE_METATYPE(KeyList)
1646
1647 void tst_QComboBox::flaggedItems_data()
1648 {
1649 QTest::addColumn<QStringList>("itemList");
1650 QTest::addColumn<IntList>("deselectFlagList");
1651 QTest::addColumn<IntList>("disableFlagList");
1652 QTest::addColumn<KeyList>("keyMovementList");
1653 QTest::addColumn<bool>("editable");
1654 QTest::addColumn<int>("expectedIndex");
1655
1656 for (int editable=0;editable<2;editable++) {
1657 QString testCase = editable ? "editable:" : "non-editable:";
1658 QStringList itemList;
1659 itemList << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "Seven" << "Eight";
1660 IntList deselectFlagList;
1661 IntList disableFlagList;
1662 KeyList keyMovementList;
1663
1664 keyMovementList << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down;
1665 QTest::newRow(testCase.toAscii() + "normal") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1666
1667 deselectFlagList.clear();
1668 disableFlagList.clear();
1669 deselectFlagList << 1 << 3;
1670 QTest::newRow(testCase.toAscii() + "non-selectable") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1671
1672 deselectFlagList.clear();
1673 disableFlagList.clear();
1674 disableFlagList << 2;
1675 QTest::newRow(testCase.toAscii() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 5;
1676
1677 deselectFlagList.clear();
1678 disableFlagList.clear();
1679 deselectFlagList << 1 << 3;
1680 disableFlagList << 2 << 3;
1681 QTest::newRow(testCase.toAscii() + "mixed") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 6;
1682 deselectFlagList.clear();
1683 disableFlagList.clear();
1684 disableFlagList << 0 << 1 << 2 << 3 << 4 << 5 << 6;
1685 QTest::newRow(testCase.toAscii() + "nearly-empty") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
1686
1687 deselectFlagList.clear();
1688 disableFlagList.clear();
1689 disableFlagList << 0 << 1 << 2 << 3 << 5 << 6 << 7;
1690 keyMovementList.clear();
1691 QTest::newRow(testCase.toAscii() + "only one enabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1692
1693 if (!editable) {
1694 deselectFlagList.clear();
1695 disableFlagList.clear();
1696 keyMovementList.clear();
1697 disableFlagList << 0 << 2 << 3;
1698 keyMovementList << Qt::Key_Down << Qt::Key_Home;
1699 QTest::newRow(testCase.toAscii() + "home-disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 1;
1700
1701 keyMovementList.clear();
1702 keyMovementList << Qt::Key_End;
1703 QTest::newRow(testCase.toAscii() + "end-key") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
1704
1705 disableFlagList.clear();
1706 disableFlagList << 1 ;
1707 keyMovementList << Qt::Key_T;
1708 QTest::newRow(testCase.toAscii() + "keyboard-search") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1709
1710 itemList << "nine" << "ten";
1711 keyMovementList << Qt::Key_T;
1712 QTest::newRow(testCase.toAscii() + "search same start letter") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 9;
1713
1714 keyMovementList.clear();
1715 keyMovementList << Qt::Key_T << Qt::Key_H;
1716 QTest::newRow(testCase.toAscii() + "keyboard search item") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1717
1718 disableFlagList.clear();
1719 disableFlagList << 1 << 3 << 5 << 7 << 9;
1720 keyMovementList.clear();
1721 keyMovementList << Qt::Key_End << Qt::Key_Up << Qt::Key_Up << Qt::Key_PageDown << Qt::Key_PageUp << Qt::Key_PageUp << Qt::Key_Down;
1722 QTest::newRow(testCase.toAscii() + "all key combinations") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1723 } else {
1724 deselectFlagList.clear();
1725 disableFlagList.clear();
1726 disableFlagList << 1;
1727 keyMovementList.clear();
1728 keyMovementList << Qt::Key_T << Qt::Key_Enter;
1729 QTest::newRow(testCase.toAscii() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1730 QTest::newRow(testCase.toAscii() + "broken autocompletion") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1731 }
1732 }
1733 }
1734
flaggedItems()1735 void tst_QComboBox::flaggedItems()
1736 {
1737 QFETCH(QStringList, itemList);
1738 QFETCH(IntList, deselectFlagList);
1739 QFETCH(IntList, disableFlagList);
1740 QFETCH(KeyList, keyMovementList);
1741 QFETCH(bool, editable);
1742 QFETCH(int, expectedIndex);
1743
1744 QComboBox comboBox;
1745 QListWidget listWidget;
1746 listWidget.addItems(itemList);
1747
1748 comboBox.setEditable(editable);
1749 foreach (int index, deselectFlagList)
1750 listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsSelectable);
1751
1752 foreach (int index, disableFlagList)
1753 listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
1754
1755 comboBox.setModel(listWidget.model());
1756 comboBox.setView(&listWidget);
1757 comboBox.show();
1758 QApplication::setActiveWindow(&comboBox);
1759 comboBox.activateWindow();
1760 comboBox.setFocus();
1761 QTRY_VERIFY(comboBox.isVisible());
1762 QTRY_VERIFY(comboBox.hasFocus());
1763
1764 if (editable)
1765 comboBox.lineEdit()->selectAll();
1766
1767 QSignalSpy indexChangedInt(&comboBox, SIGNAL(currentIndexChanged(int)));
1768 for (int i = 0; i < keyMovementList.count(); ++i) {
1769 Qt::Key key = keyMovementList[i];
1770 QTest::keyClick(&comboBox, key);
1771 if (indexChangedInt.count() != i + 1) {
1772 QTest::qWait(400);
1773 }
1774 }
1775
1776 QCOMPARE(comboBox.currentIndex() , expectedIndex);
1777 }
1778
pixmapIcon()1779 void tst_QComboBox::pixmapIcon()
1780 {
1781 QComboBox box;
1782 QStandardItemModel *model = new QStandardItemModel(2, 1, &box);
1783
1784 QPixmap pix(10, 10);
1785 pix.fill(Qt::red);
1786 model->setData(model->index(0, 0), "Element 1");
1787 model->setData(model->index(0, 0), pix, Qt::DecorationRole);
1788
1789 QIcon icon(pix);
1790 model->setData(model->index(1, 0), "Element 2");
1791 model->setData(model->index(1, 0), icon, Qt::DecorationRole);
1792
1793 box.setModel(model);
1794
1795 QCOMPARE( box.itemIcon(0).isNull(), false );
1796 QCOMPARE( box.itemIcon(1).isNull(), false );
1797 }
1798
1799 // defined to be 120 by the wheel mouse vendors according to the docs
1800 #define WHEEL_DELTA 120
1801
mouseWheel_data()1802 void tst_QComboBox::mouseWheel_data()
1803 {
1804 QTest::addColumn<IntList>("disabledItems");
1805 QTest::addColumn<int>("startIndex");
1806 QTest::addColumn<int>("wheelDirection");
1807 QTest::addColumn<int>("expectedIndex");
1808
1809 IntList disabled;
1810 disabled << 0 << 1 << 2 << 4;
1811 int start = 3;
1812 int wheel = 1;
1813 int expected = 3;
1814 QTest::newRow("upper locked") << disabled << start << wheel << expected;
1815
1816 wheel = -1;
1817 expected = 5;
1818 QTest::newRow("jump over") << disabled << start << wheel << expected;
1819
1820 disabled.clear();
1821 disabled << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9;
1822 start = 0;
1823 wheel = -1;
1824 expected = 0;
1825 QTest::newRow("single Item enabled") << disabled << start << wheel << expected;
1826 }
1827
mouseWheel()1828 void tst_QComboBox::mouseWheel()
1829 {
1830 QFETCH(IntList, disabledItems);
1831 QFETCH(int, startIndex);
1832 QFETCH(int, wheelDirection);
1833 QFETCH(int, expectedIndex);
1834
1835 QCoreApplication *applicationInstance = QCoreApplication::instance();
1836 QVERIFY(applicationInstance != 0);
1837
1838 QComboBox box;
1839 QStringList list;
1840 list << "one" << "two" << "three" << "four" << "five" << "six" << "seven" << "eight" << "nine" << "ten";
1841
1842 QListWidget listWidget;
1843 listWidget.addItems(list);
1844
1845 foreach (int index, disabledItems)
1846 listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
1847
1848 box.setModel(listWidget.model());
1849 box.setView(&listWidget);
1850 for (int i=0; i < 2; ++i) {
1851 box.setEditable(i==0?false:true);
1852 box.setCurrentIndex(startIndex);
1853
1854 QWheelEvent event = QWheelEvent(box.rect().bottomRight() , WHEEL_DELTA * wheelDirection, Qt::NoButton, Qt::NoModifier);
1855 QVERIFY(applicationInstance->sendEvent(&box,&event));
1856
1857 QCOMPARE(box.currentIndex(), expectedIndex);
1858 }
1859 }
1860
layoutDirection()1861 void tst_QComboBox::layoutDirection()
1862 {
1863 QComboBox box;
1864 Qt::LayoutDirection dir;
1865 QLineEdit *lineEdit;
1866
1867 // RTL
1868 box.setLayoutDirection(Qt::RightToLeft);
1869 QStyleOptionComboBox opt;
1870 opt.direction = Qt::RightToLeft;
1871 dir = (Qt::LayoutDirection)box.style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, &box);
1872
1873 QCOMPARE(box.view()->layoutDirection(), dir);
1874 box.setEditable(true);
1875 QCOMPARE(box.lineEdit()->layoutDirection(), dir);
1876 lineEdit = new QLineEdit;
1877 QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
1878 box.setLineEdit(lineEdit);
1879 QCOMPARE(lineEdit->layoutDirection(), dir);
1880
1881 // LTR
1882 box.setLayoutDirection(Qt::LeftToRight);
1883 qApp->setLayoutDirection(Qt::RightToLeft);
1884
1885 opt.direction = Qt::LeftToRight;
1886 dir = (Qt::LayoutDirection)box.style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, &box);
1887
1888 QCOMPARE(box.view()->layoutDirection(), dir);
1889 box.setEditable(true);
1890 QCOMPARE(box.lineEdit()->layoutDirection(), dir);
1891 lineEdit = new QLineEdit;
1892 QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
1893 box.setLineEdit(lineEdit);
1894 QCOMPARE(lineEdit->layoutDirection(), dir);
1895
1896 }
1897
itemListPosition()1898 void tst_QComboBox::itemListPosition()
1899 {
1900 //tests that the list is not out of the screen boundaries
1901
1902 //put the QApplication layout back
1903 QApplication::setLayoutDirection(Qt::LeftToRight);
1904
1905 //we test QFontComboBox because it has the specific behaviour to set a fixed size
1906 //to the list view
1907 QWidget topLevel;
1908 QFontComboBox combo(&topLevel);
1909
1910 //the code to get the avaialbe screen space is copied from QComboBox code
1911 const int scrNumber = QApplication::desktop()->screenNumber(&combo);
1912 QRect screen;
1913 #ifdef Q_WS_WIN
1914 screen = QApplication::desktop()->screenGeometry(scrNumber);
1915 #elif defined Q_WS_X11
1916 if (X11->desktopEnvironment == DE_KDE)
1917 screen = QApplication::desktop()->screenGeometry(scrNumber);
1918 else
1919 screen = QApplication::desktop()->availableGeometry(scrNumber);
1920 #else
1921 screen = QApplication::desktop()->availableGeometry(scrNumber);
1922 #endif
1923
1924 combo.move(screen.width()-combo.sizeHint().width(), 0); //puts the combo to the top-right corner
1925
1926 topLevel.show();
1927 //wait because the window manager can move the window if there is a right panel
1928 QTRY_VERIFY(combo.isVisible());
1929 combo.showPopup();
1930 QTRY_VERIFY(combo.view());
1931 QTRY_VERIFY(combo.view()->isVisible());
1932
1933 #if defined(Q_WS_S60)
1934 // Assuming that QtS60 style is used, here. But other ones would certainly also fail
1935 QEXPECT_FAIL("", "QtS60Style does not yet position the combobox popup correctly", Continue);
1936 #endif
1937 QVERIFY( combo.view()->window()->x() + combo.view()->window()->width() <= screen.x() + screen.width() );
1938
1939 }
1940
separatorItem_data()1941 void tst_QComboBox::separatorItem_data()
1942 {
1943 QTest::addColumn<QStringList>("items");
1944 QTest::addColumn<IntList>("separators");
1945
1946 QTest::newRow("test") << (QStringList() << "one" << "two" << "three" << "other...")
1947 << (IntList() << 4);
1948 }
1949
separatorItem()1950 void tst_QComboBox::separatorItem()
1951 {
1952 QFETCH(QStringList, items);
1953 QFETCH(IntList, separators);
1954
1955 QComboBox box;
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());
1963 ++s;
1964 } else {
1965 QCOMPARE(box.itemText(i), items.at(i - s));
1966 }
1967 }
1968 }
1969
task190351_layout()1970 void tst_QComboBox::task190351_layout()
1971 {
1972 #ifndef QT_NO_STYLE_CLEANLOOKS
1973 const QString oldStyle = QApplication::style()->objectName();
1974 QApplication::setStyle(new QCleanlooksStyle);
1975
1976 QComboBox listCombo;
1977 QListWidget *list = new QListWidget();
1978 listCombo.setModel(list->model());
1979 listCombo.setView(list);
1980 for(int i = 1; i < 150; i++)
1981 list->addItem(QLatin1String("list") + QString::number(i));
1982
1983 listCombo.show();
1984 QTest::qWaitForWindowShown(&listCombo);
1985 QTRY_VERIFY(listCombo.isVisible());
1986 listCombo.setCurrentIndex(70);
1987 listCombo.showPopup();
1988 QTRY_VERIFY(listCombo.view());
1989 QTest::qWaitForWindowShown(listCombo.view());
1990 QTRY_VERIFY(listCombo.view()->isVisible());
1991 QApplication::processEvents();
1992
1993 #ifdef QT_BUILD_INTERNAL
1994 QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&listCombo);
1995 QVERIFY(container);
1996 QCOMPARE(static_cast<QAbstractItemView *>(list), qFindChild<QAbstractItemView *>(container));
1997 QWidget *top = qFindChild<QComboBoxPrivateScroller *>(container);
1998 QVERIFY(top);
1999 QVERIFY(top->isVisible());
2000 QCOMPARE(top->mapToGlobal(QPoint(0, top->height())).y(), list->mapToGlobal(QPoint()).y());
2001 #endif
2002
2003 QApplication::setStyle(oldStyle);
2004 #else
2005 QSKIP("Qt configured without cleanlooks style", SkipAll);
2006 #endif
2007 }
2008
2009 class task166349_ComboBox : public QComboBox
2010 {
2011 Q_OBJECT
2012 public:
task166349_ComboBox(QWidget * parent=0)2013 task166349_ComboBox(QWidget *parent = 0) : QComboBox(parent)
2014 {
2015 QStringList list;
2016 list << "one" << "two";
2017 connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
2018 addItems(list);
2019 }
2020 public slots:
onCurrentIndexChanged(int index)2021 void onCurrentIndexChanged(int index)
2022 {
2023 setEditable(index % 2 == 1);
2024 }
2025 };
2026
task166349_setEditableOnReturn()2027 void tst_QComboBox::task166349_setEditableOnReturn()
2028 {
2029 task166349_ComboBox comboBox;
2030 QTest::keyClick(&comboBox, Qt::Key_Down);
2031 QTest::keyClick(&comboBox, Qt::Key_1);
2032 QTest::keyClick(&comboBox, Qt::Key_Enter);
2033 QCOMPARE(QLatin1String("two1"), comboBox.itemText(comboBox.count() - 1));
2034 }
2035
task191329_size()2036 void tst_QComboBox::task191329_size()
2037 {
2038 #ifndef QT_NO_STYLE_CLEANLOOKS
2039 const QString oldStyle = QApplication::style()->objectName();
2040 QApplication::setStyle(new QCleanlooksStyle);
2041
2042 QComboBox tableCombo;
2043 int rows;
2044 if (QApplication::desktop()->screenGeometry().height() < 480)
2045 rows = 8;
2046 else
2047 rows = 15;
2048
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);
2054 }
2055 }
2056 QTableView *table = new QTableView();
2057 table->verticalHeader()->hide();
2058 table->horizontalHeader()->hide();
2059 tableCombo.setView(table);
2060 tableCombo.setModel(&model);
2061
2062 tableCombo.show();
2063 QTRY_VERIFY(tableCombo.isVisible());
2064 tableCombo.showPopup();
2065 QTRY_VERIFY(tableCombo.view());
2066 QTRY_VERIFY(tableCombo.view()->isVisible());
2067
2068 #ifdef QT_BUILD_INTERNAL
2069 QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&tableCombo);
2070 QVERIFY(container);
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());
2075 }
2076 #endif
2077
2078 QApplication::setStyle(oldStyle);
2079 #else
2080 QSKIP("Qt configured without cleanlooks style", SkipAll);
2081 #endif
2082 }
2083
task190205_setModelAdjustToContents()2084 void tst_QComboBox::task190205_setModelAdjustToContents()
2085 {
2086 QStringList initialContent;
2087 QStringList finalContent;
2088 initialContent << "foo" << "bar";
2089 finalContent << "bar" << "foooooooobar";
2090
2091 QComboBox box;
2092 box.setSizeAdjustPolicy(QComboBox::AdjustToContents);
2093 box.addItems(initialContent);
2094 box.show();
2095
2096 //wait needed in order to get the combo initial size
2097 QTRY_VERIFY(box.isVisible());
2098
2099 box.setModel(new QStringListModel(finalContent));
2100
2101 QComboBox correctBox;
2102 correctBox.addItems(finalContent);
2103 correctBox.show();
2104
2105 QCoreApplication::processEvents();
2106 #ifdef Q_WS_X11
2107 qt_x11_wait_for_window_manager(&box);
2108 qt_x11_wait_for_window_manager(&correctBox);
2109 #endif
2110
2111 // box should be resized to the same size as correctBox
2112 QTRY_COMPARE(box.size(), correctBox.size());
2113 }
2114
task248169_popupWithMinimalSize()2115 void tst_QComboBox::task248169_popupWithMinimalSize()
2116 {
2117 QStringList initialContent;
2118 initialContent << "foo" << "bar" << "foobar";
2119
2120 QComboBox comboBox;
2121 comboBox.addItems(initialContent);
2122 QDesktopWidget desktop;
2123 QRect desktopSize = desktop.availableGeometry();
2124 comboBox.view()->setMinimumWidth(desktopSize.width() / 2);
2125
2126 comboBox.setGeometry(desktopSize.width() - (desktopSize.width() / 4), (desktopSize.width() / 4), (desktopSize.width() / 2), (desktopSize.width() / 4));
2127
2128 comboBox.show();
2129 QTest::qWaitForWindowShown(&comboBox);
2130 QTRY_VERIFY(comboBox.isVisible());
2131 comboBox.showPopup();
2132 QTRY_VERIFY(comboBox.view());
2133 QTest::qWaitForWindowShown(comboBox.view());
2134 QTRY_VERIFY(comboBox.view()->isVisible());
2135
2136 #ifdef QT_BUILD_INTERNAL
2137 QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&comboBox);
2138 QVERIFY(container);
2139 QTRY_VERIFY(desktop.screenGeometry(container).contains(container->geometry()));
2140 #endif
2141 }
2142
task247863_keyBoardSelection()2143 void tst_QComboBox::task247863_keyBoardSelection()
2144 {
2145 QComboBox combo;
2146 combo.setEditable(false);
2147 combo.addItem( QLatin1String("111"));
2148 combo.addItem( QLatin1String("222"));
2149 combo.show();
2150 QApplication::setActiveWindow(&combo);
2151 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2152
2153 QSignalSpy spy(&combo, SIGNAL(activated(const QString &)));
2154 qApp->setEffectEnabled(Qt::UI_AnimateCombo, false);
2155 QTest::keyClick(&combo, Qt::Key_Space);
2156 qApp->setEffectEnabled(Qt::UI_AnimateCombo, true);
2157 QTest::keyClick(0, Qt::Key_Down);
2158 QTest::keyClick(0, Qt::Key_Enter);
2159 QCOMPARE(combo.currentText(), QLatin1String("222"));
2160 QCOMPARE(spy.count(), 1);
2161 }
2162
task220195_keyBoardSelection2()2163 void tst_QComboBox::task220195_keyBoardSelection2()
2164 {
2165 QComboBox combo;
2166 combo.setEditable(false);
2167 combo.addItem( QLatin1String("foo1"));
2168 combo.addItem( QLatin1String("foo2"));
2169 combo.addItem( QLatin1String("foo3"));
2170 combo.show();
2171 QApplication::setActiveWindow(&combo);
2172 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2173
2174 combo.setCurrentIndex(-1);
2175 QVERIFY(combo.currentText().isNull());
2176
2177 QTest::keyClick(&combo, 'f');
2178 QCOMPARE(combo.currentText(), QLatin1String("foo1"));
2179 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2180 QTest::keyClick(&combo, 'f');
2181 QCOMPARE(combo.currentText(), QLatin1String("foo2"));
2182 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2183 QTest::keyClick(&combo, 'f');
2184 QCOMPARE(combo.currentText(), QLatin1String("foo3"));
2185 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2186 QTest::keyClick(&combo, 'f');
2187 QCOMPARE(combo.currentText(), QLatin1String("foo1"));
2188 QTest::qWait(QApplication::keyboardInputInterval() + 30);
2189
2190 combo.setCurrentIndex(1);
2191 QCOMPARE(combo.currentText(), QLatin1String("foo2"));
2192 QTest::keyClick(&combo, 'f');
2193 QCOMPARE(combo.currentText(), QLatin1String("foo3"));
2194 }
2195
2196
setModelColumn()2197 void tst_QComboBox::setModelColumn()
2198 {
2199 QStandardItemModel model(5,3);
2200 model.setItem(0,0, new QStandardItem("0"));
2201 model.setItem(1,0, new QStandardItem("1"));
2202 model.setItem(2,0, new QStandardItem("2"));
2203 model.setItem(3,0, new QStandardItem("3"));
2204 model.setItem(4,0, new QStandardItem("4"));
2205 model.setItem(0,1, new QStandardItem("zero"));
2206 model.setItem(1,1, new QStandardItem("un"));
2207 model.setItem(2,1, new QStandardItem("deux"));
2208 model.setItem(3,1, new QStandardItem("trois"));
2209 model.setItem(4,1, new QStandardItem("quatre"));
2210 model.setItem(0,2, new QStandardItem("a"));
2211 model.setItem(1,2, new QStandardItem("b"));
2212 model.setItem(2,2, new QStandardItem("c"));
2213 model.setItem(3,2, new QStandardItem("d"));
2214 model.setItem(4,2, new QStandardItem("e"));
2215
2216 QComboBox box;
2217 box.setModel(&model);
2218 QCOMPARE(box.currentText(), QString("0"));
2219 box.setModelColumn(1);
2220 QCOMPARE(box.currentText(), QString("zero"));
2221 }
2222
noScrollbar_data()2223 void tst_QComboBox::noScrollbar_data()
2224 {
2225 QTest::addColumn<QString>("stylesheet");
2226
2227 QTest::newRow("normal") << QString();
2228 QTest::newRow("border") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue;}");
2229 QTest::newRow("margin") << QString::fromLatin1("QAbstractItemView { margin: 12px 15px 13px 10px; }");
2230 QTest::newRow("padding") << QString::fromLatin1("QAbstractItemView { padding: 12px 15px 13px 10px;}");
2231 QTest::newRow("everything") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue; "
2232 " padding: 12px 15px 13px 10px; margin: 12px 15px 13px 10px; }");
2233 QTest::newRow("everything and more") << QString::fromLatin1("QAbstractItemView { border: 1px 3px 5px 1px solid blue; "
2234 " padding: 2px 5px 3px 1px; margin: 2px 5px 3px 1px; } "
2235 " QAbstractItemView::item { border: 2px solid green; "
2236 " padding: 1px 1px 2px 2px; margin: 1px; } " );
2237 }
2238
noScrollbar()2239 void tst_QComboBox::noScrollbar()
2240 {
2241 QStringList initialContent;
2242 initialContent << "foo" << "bar" << "foobar" << "moo";
2243 QFETCH(QString, stylesheet);
2244 QString oldCss = qApp->styleSheet();
2245 qApp->setStyleSheet(stylesheet);
2246
2247 {
2248 QWidget topLevel;
2249 QComboBox comboBox(&topLevel);
2250 comboBox.addItems(initialContent);
2251 topLevel.show();
2252 comboBox.resize(200, comboBox.height());
2253 QTRY_VERIFY(comboBox.isVisible());
2254 comboBox.showPopup();
2255 QTRY_VERIFY(comboBox.view());
2256 QTRY_VERIFY(comboBox.view()->isVisible());
2257
2258 QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
2259 QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
2260 }
2261
2262 {
2263 QTableWidget *table = new QTableWidget(2,2);
2264 QComboBox comboBox;
2265 comboBox.setModel(table->model());
2266 comboBox.setView(table);
2267 comboBox.show();
2268 QTRY_VERIFY(comboBox.isVisible());
2269 comboBox.resize(200, comboBox.height());
2270 comboBox.showPopup();
2271 QTRY_VERIFY(comboBox.view());
2272 QTRY_VERIFY(comboBox.view()->isVisible());
2273
2274 QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
2275 QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
2276 }
2277
2278 qApp->setStyleSheet(oldCss);
2279 }
2280
setItemDelegate()2281 void tst_QComboBox::setItemDelegate()
2282 {
2283 QComboBox comboBox;
2284 QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
2285 comboBox.setItemDelegate(itemDelegate);
2286 // the cast is a workaround for the XLC and Metrowerks compilers
2287 QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2288 }
2289
task253944_itemDelegateIsReset()2290 void tst_QComboBox::task253944_itemDelegateIsReset()
2291 {
2292 QComboBox comboBox;
2293 QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
2294 comboBox.setItemDelegate(itemDelegate);
2295
2296 // the casts are workarounds for the XLC and Metrowerks compilers
2297
2298 comboBox.setEditable(true);
2299 QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2300
2301 comboBox.setStyleSheet("QComboBox { border: 1px solid gray; }");
2302 QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2303 }
2304
2305
subControlRectsWithOffset_data()2306 void tst_QComboBox::subControlRectsWithOffset_data()
2307 {
2308 QTest::addColumn<bool>("editable");
2309
2310 QTest::newRow("editable = true") << true;
2311 QTest::newRow("editable = false") << false;
2312 }
2313
subControlRectsWithOffset()2314 void tst_QComboBox::subControlRectsWithOffset()
2315 {
2316 // The sub control rect relative position should not depends
2317 // on the position of the combobox
2318
2319 class FriendlyCombo : public QComboBox {
2320 public:
2321 void styleOption(QStyleOptionComboBox *optCombo) {
2322 initStyleOption(optCombo);
2323 }
2324 } combo;
2325 QStyleOptionComboBox optCombo;
2326 combo.styleOption(&optCombo);
2327
2328
2329 const QRect rectAtOrigin(0, 0, 80, 30);
2330 const QPoint offset(25, 50);
2331 const QRect rectWithOffset = rectAtOrigin.translated(offset);
2332
2333 QStyle *style = combo.style();
2334
2335 QFETCH(bool, editable);
2336 optCombo.editable = editable;
2337
2338 optCombo.rect = rectAtOrigin;
2339 QRect editFieldRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
2340 QRect arrowRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
2341 QRect listboxRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
2342
2343 optCombo.rect = rectWithOffset;
2344 QRect editFieldRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
2345 QRect arrowRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
2346 QRect listboxRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
2347
2348 QCOMPARE(editFieldRect, editFieldRectWithOffset.translated(-offset));
2349 QCOMPARE(arrowRect, arrowRectWithOffset.translated(-offset));
2350 QCOMPARE(listboxRect, listboxRectWithOffset.translated(-offset));
2351
2352 }
2353
task260974_menuItemRectangleForComboBoxPopup()2354 void tst_QComboBox::task260974_menuItemRectangleForComboBoxPopup()
2355 {
2356 #ifdef QT_NO_STYLE_WINDOWS
2357 QSKIP("test depends on windows style", QTest::SkipAll);
2358 #else
2359 class TestStyle: public QWindowsStyle
2360 {
2361 public:
2362 int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *ret) const
2363 {
2364 if (hint == SH_ComboBox_Popup) return 1;
2365 else return QCommonStyle::styleHint(hint, option, widget, ret);
2366 }
2367
2368 void drawControl(ControlElement element, const QStyleOption *option, QPainter *, const QWidget *) const
2369 {
2370 if (element == CE_MenuItem)
2371 discoveredRect = option->rect;
2372 }
2373
2374 mutable QRect discoveredRect;
2375 } style;
2376
2377
2378 {
2379 QComboBox comboBox;
2380 comboBox.setStyle(&style);
2381 comboBox.addItem("Item 1");
2382
2383 comboBox.show();
2384 QTRY_VERIFY(comboBox.isVisible());
2385 comboBox.showPopup();
2386 QTRY_VERIFY(comboBox.view());
2387 QTRY_VERIFY(comboBox.view()->isVisible());
2388
2389 QTRY_VERIFY(style.discoveredRect.width() <= comboBox.width());
2390 }
2391 #endif
2392 }
2393
removeItem()2394 void tst_QComboBox::removeItem()
2395 {
2396 QComboBox cb;
2397 cb.removeItem(-1);
2398 cb.removeItem(1);
2399 cb.removeItem(0);
2400 QCOMPARE(cb.count(), 0);
2401
2402 cb.addItem("foo");
2403 cb.removeItem(-1);
2404 QCOMPARE(cb.count(), 1);
2405 cb.removeItem(1);
2406 QCOMPARE(cb.count(), 1);
2407 cb.removeItem(0);
2408 QCOMPARE(cb.count(), 0);
2409 }
2410
resetModel()2411 void tst_QComboBox::resetModel()
2412 {
2413 class StringListModel : public QStringListModel
2414 {
2415 public:
2416 StringListModel(const QStringList &list) : QStringListModel(list)
2417 {
2418 }
2419
2420 void reset()
2421 {
2422 QStringListModel::reset();
2423 }
2424 };
2425 QComboBox cb;
2426 StringListModel model( QStringList() << "1" << "2");
2427 QSignalSpy spy(&cb, SIGNAL(currentIndexChanged(int)));
2428 QCOMPARE(spy.count(), 0);
2429 QCOMPARE(cb.currentIndex(), -1); //no selection
2430
2431 cb.setModel(&model);
2432
2433 QCOMPARE(spy.count(), 1);
2434 QCOMPARE(cb.currentIndex(), 0); //first item selected
2435
2436 model.reset();
2437 QCOMPARE(spy.count(), 2);
2438 QCOMPARE(cb.currentIndex(), -1); //no selection
2439
2440 }
2441
keyBoardNavigationWithMouse()2442 void tst_QComboBox::keyBoardNavigationWithMouse()
2443 {
2444 QComboBox combo;
2445 combo.setEditable(false);
2446 for (int i = 0; i < 80; i++)
2447 combo.addItem( QString::number(i));
2448 combo.show();
2449 QApplication::setActiveWindow(&combo);
2450 QTest::qWaitForWindowShown(&combo);
2451 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2452
2453 QCOMPARE(combo.currentText(), QLatin1String("0"));
2454
2455 combo.setFocus();
2456 QTRY_VERIFY(combo.hasFocus());
2457
2458 QTest::keyClick(testWidget->lineEdit(), Qt::Key_Space);
2459 QTest::qWait(30);
2460 QTRY_VERIFY(combo.view());
2461 QTRY_VERIFY(combo.view()->isVisible());
2462 QTest::qWait(130);
2463
2464 QCOMPARE(combo.currentText(), QLatin1String("0"));
2465
2466 #ifdef Q_OS_WINCE
2467 QSKIP("When calling cursor function, Windows CE responds with: This function is not supported on this system.", SkipAll);
2468 #endif
2469
2470 QCursor::setPos(combo.view()->mapToGlobal(combo.view()->rect().center()));
2471 QTest::qWait(200);
2472
2473 #define GET_SELECTION(SEL) \
2474 QCOMPARE(combo.view()->selectionModel()->selection().count(), 1); \
2475 QCOMPARE(combo.view()->selectionModel()->selection().indexes().count(), 1); \
2476 SEL = combo.view()->selectionModel()->selection().indexes().first().row()
2477
2478 int selection;
2479 GET_SELECTION(selection);
2480
2481 //since we moved the mouse is in the middle it should even be around 5;
2482 QVERIFY(selection > 3);
2483
2484 static const int final = 40;
2485 for (int i = selection + 1; i <= final; i++)
2486 {
2487 QTest::keyClick(combo.view(), Qt::Key_Down);
2488 QTest::qWait(20);
2489 GET_SELECTION(selection);
2490 QCOMPARE(selection, i);
2491 }
2492
2493 QTest::keyClick(combo.view(), Qt::Key_Enter);
2494 QTRY_COMPARE(combo.currentText(), QString::number(final));
2495 }
2496
task_QTBUG_1071_changingFocusEmitsActivated()2497 void tst_QComboBox::task_QTBUG_1071_changingFocusEmitsActivated()
2498 {
2499 QWidget w;
2500 QVBoxLayout layout(&w);
2501 QComboBox cb;
2502 cb.setEditable(true);
2503 QSignalSpy spy(&cb, SIGNAL(activated(int)));
2504 cb.addItem("0");
2505 cb.addItem("1");
2506 cb.addItem("2");
2507 QLineEdit edit;
2508 layout.addWidget(&cb);
2509 layout.addWidget(&edit);
2510
2511 w.show();
2512 QApplication::setActiveWindow(&w);
2513 QTest::qWaitForWindowShown(&w);
2514 cb.clearEditText();
2515 cb.setFocus();
2516 QApplication::processEvents();
2517 QTRY_VERIFY(cb.hasFocus());
2518 QTest::keyClick(0, '1');
2519 QCOMPARE(spy.count(), 0);
2520 edit.setFocus();
2521 QTRY_VERIFY(edit.hasFocus());
2522 QTRY_COMPARE(spy.count(), 1);
2523 }
2524
maxVisibleItems()2525 void tst_QComboBox::maxVisibleItems()
2526 {
2527 QComboBox comboBox;
2528 QCOMPARE(comboBox.maxVisibleItems(), 10); //default value.
2529
2530 QStringList content;
2531 for(int i = 1; i < 50; i++)
2532 content += QString::number(i);
2533
2534 comboBox.addItems(content);
2535 comboBox.show();
2536 comboBox.resize(200, comboBox.height());
2537 QTRY_VERIFY(comboBox.isVisible());
2538
2539 comboBox.setMaxVisibleItems(5);
2540 QCOMPARE(comboBox.maxVisibleItems(), 5);
2541
2542 comboBox.showPopup();
2543 QTRY_VERIFY(comboBox.view());
2544 QTRY_VERIFY(comboBox.view()->isVisible());
2545
2546 QAbstractItemView *v = comboBox.view();
2547 int itemHeight = v->visualRect(v->model()->index(0,0)).height();
2548 QListView *lv = qobject_cast<QListView*>(v);
2549 if (lv)
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());
2555 }
2556
task_QTBUG_10491_currentIndexAndModelColumn()2557 void tst_QComboBox::task_QTBUG_10491_currentIndexAndModelColumn()
2558 {
2559 QComboBox comboBox;
2560
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)));
2567 }
2568 comboBox.setModel(&model);
2569 comboBox.setModelColumn(0);
2570
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()));
2574 }
2575
2576 QTEST_MAIN(tst_QComboBox)
2577 #include "tst_qcombobox.moc"
2578