QtBase  v6.3.1
tst_qcombobox.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include <QTest>
30 #include <QSignalSpy>
31 #include <QSortFilterProxyModel>
32 
33 #include "qcombobox.h"
34 #include <private/qcombobox_p.h>
35 #include <private/qguiapplication_p.h>
36 #include <qpa/qplatformtheme.h>
37 
38 #include <qfontcombobox.h>
39 #include <qapplication.h>
40 #include <qpushbutton.h>
41 #include <qdialog.h>
42 #include <qevent.h>
43 #include <qlineedit.h>
44 #include <qlabel.h>
45 #include <qlistview.h>
46 #include <qheaderview.h>
47 #include <qlistwidget.h>
48 #include <qtreewidget.h>
49 #include <qtablewidget.h>
50 #include <qscrollbar.h>
51 #include <qboxlayout.h>
52 #include <qstackedwidget.h>
53 
54 #include <qstandarditemmodel.h>
55 #include <qstringlistmodel.h>
56 #include <qcombobox.h>
57 #include <qpushbutton.h>
58 #include <qdialog.h>
59 #include <qstringlist.h>
60 #include <qvalidator.h>
61 #include <qcompleter.h>
62 #include <qstylefactory.h>
63 #include <qabstractitemview.h>
64 #include <qstyleditemdelegate.h>
65 #include <qstandarditemmodel.h>
66 #include <qproxystyle.h>
67 #include <qfont.h>
68 
69 #include "../../../shared/platforminputcontext.h"
70 #include <private/qinputmethod_p.h>
71 
72 #include <QtTest/private/qtesthelpers_p.h>
73 
74 using namespace QTestPrivate;
75 
76 class tst_QComboBox : public QObject
77 {
78  Q_OBJECT
79 
80 public:
82 
83 private slots:
84  void initTestCase();
85  void cleanupTestCase();
86  void getSetCheck();
87  void ensureReturnIsIgnored();
88  void setEditable();
89  void setPalette();
90  void sizeAdjustPolicy();
91  void clear();
92  void insertPolicy_data();
93  void insertPolicy();
94  void virtualAutocompletion();
95  void autoCompletionCaseSensitivity();
96  void hide();
97  void currentIndex_data();
98  void currentIndex();
99  void insertItems_data();
100  void insertItems();
101  void insertItem_data();
102  void insertItem();
103  void insertOnCurrentIndex();
104  void textpixmapdata_data();
105  void textpixmapdata();
106  void currentTextChanged_data();
107  void currentTextChanged();
108  void editTextChanged();
109  void setModel();
110  void modelDeleted();
111  void setMaxCount();
112  void setCurrentIndex();
113  void setCurrentText_data();
114  void setCurrentText();
115  void convenienceViews();
116  void findText_data();
117  void findText();
118  void flaggedItems_data();
119  void flaggedItems();
120  void pixmapIcon();
121 #if QT_CONFIG(wheelevent)
122  void mouseWheel_data();
123  void mouseWheel();
124  void popupWheelHandling();
125 #endif // QT_CONFIG(wheelevent)
126  void layoutDirection();
127  void itemListPosition();
128  void separatorItem_data();
129  void separatorItem();
130 #ifndef QT_NO_STYLE_FUSION
131  void task190351_layout();
132  void task191329_size();
133 #endif
134  void task166349_setEditableOnReturn();
135  void task190205_setModelAdjustToContents();
136  void task248169_popupWithMinimalSize();
137  void task247863_keyBoardSelection();
138  void task220195_keyBoardSelection2();
139  void setModelColumn();
140  void noScrollbar_data();
141  void noScrollbar();
142  void setItemDelegate();
143  void task253944_itemDelegateIsReset();
144  void subControlRectsWithOffset_data();
145  void subControlRectsWithOffset();
146 #ifndef QT_NO_STYLE_WINDOWS
147  void task260974_menuItemRectangleForComboBoxPopup();
148 #endif
149  void removeItem();
150  void resetModel();
151  void keyBoardNavigationWithMouse();
152  void task_QTBUG_1071_changingFocusEmitsActivated();
153  void maxVisibleItems_data();
154  void maxVisibleItems();
155  void task_QTBUG_10491_currentIndexAndModelColumn();
156  void highlightedSignal();
157  void itemData();
158  void task_QTBUG_31146_popupCompletion();
159  void task_QTBUG_41288_completerChangesCurrentIndex();
160  void task_QTBUG_54191_slotOnEditTextChangedSetsComboBoxToReadOnly();
161  void keyboardSelection();
162  void setCustomModelAndView();
163  void updateDelegateOnEditableChange();
164  void respectChangedOwnershipOfItemView();
165  void task_QTBUG_39088_inputMethodHints();
166  void task_QTBUG_49831_scrollerNotActivated();
167  void task_QTBUG_56693_itemFontFromModel();
168  void inputMethodUpdate();
169  void task_QTBUG_52027_mapCompleterIndex();
170  void checkMenuItemPosWhenStyleSheetIsSet();
171  void checkEmbeddedLineEditWhenStyleSheetIsSet();
172  void propagateStyleChanges();
173 
174 private:
175  PlatformInputContext m_platformInputContext;
176 };
177 
179 {
180 public:
182  void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override {}
183  QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override { return QSize(); }
184 };
185 
187 {
188 public:
190  QModelIndex index(int, int, const QModelIndex &) const override { return QModelIndex(); }
191  QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); }
192  int rowCount(const QModelIndex &) const override { return 0; }
193  int columnCount(const QModelIndex &) const override { return 0; }
194  bool hasChildren(const QModelIndex &) const override { return false; }
195  QVariant data(const QModelIndex &, int) const override { return QVariant(); }
196  bool setData(const QModelIndex &, const QVariant &, int) override { return false; }
197  bool insertRows(int, int, const QModelIndex &) override { return false; }
198  bool insertColumns(int, int, const QModelIndex &) override { return false; }
199  void setPersistent(const QModelIndex &, const QModelIndex &) {}
200  bool removeRows (int, int, const QModelIndex &) override { return false; }
201  bool removeColumns(int, int, const QModelIndex &) override { return false; }
202  void reset() {}
203 };
204 
206 {
207 public:
209  QRect visualRect(const QModelIndex &) const override { return QRect(); }
210  void scrollTo(const QModelIndex &, ScrollHint) override {}
211  QModelIndex indexAt(const QPoint &) const override { return QModelIndex(); }
212 protected:
213  QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers) override { return QModelIndex(); }
214  int horizontalOffset() const override { return 0; }
215  int verticalOffset() const override { return 0; }
216  bool isIndexHidden(const QModelIndex &) const override { return false; }
217  void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) override {}
218  QRegion visualRegionForSelection(const QItemSelection &) const override { return QRegion(); }
219 };
220 
221 void tst_QComboBox::initTestCase()
222 {
223  QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
224  inputMethodPrivate->testContext = &m_platformInputContext;
225 }
226 
227 void tst_QComboBox::cleanupTestCase()
228 {
229  QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
230  inputMethodPrivate->testContext = 0;
231 }
232 
233 // Testing get/set functions
234 void tst_QComboBox::getSetCheck()
235 {
236  QComboBox obj1;
237  // int QComboBox::maxVisibleItems()
238  // void QComboBox::setMaxVisibleItems(int)
239  obj1.setMaxVisibleItems(100);
240  QCOMPARE(100, obj1.maxVisibleItems());
241  obj1.setMaxVisibleItems(0);
242  QCOMPARE(obj1.maxVisibleItems(), 0);
243  QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxVisibleItems: "
244  "Invalid max visible items (-2147483648) must be >= 0");
245  obj1.setMaxVisibleItems(INT_MIN);
246  QCOMPARE(obj1.maxVisibleItems(), 0); // Cannot be set to something negative => old value
247  obj1.setMaxVisibleItems(INT_MAX);
248  QCOMPARE(INT_MAX, obj1.maxVisibleItems());
249 
250  // int QComboBox::maxCount()
251  // void QComboBox::setMaxCount(int)
252  obj1.setMaxCount(0);
253  QCOMPARE(0, obj1.maxCount());
254 #ifndef QT_DEBUG
255  QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxCount: Invalid count (-2147483648) must be >= 0");
256  obj1.setMaxCount(INT_MIN);
257  QCOMPARE(0, obj1.maxCount()); // Setting a value below 0 makes no sense, and shouldn't be allowed
258 #endif
259  obj1.setMaxCount(INT_MAX);
260  QCOMPARE(INT_MAX, obj1.maxCount());
261 
262  // QCompleter *QComboBox::completer()
263  // void QComboBox::setCompleter(QCompleter *)
264  obj1.setCompleter(nullptr);
265  QCOMPARE(nullptr, obj1.completer());
267  obj1.setCompleter(&completer);
268  QVERIFY(obj1.completer() == nullptr); // no QLineEdit is set
269 
270  // bool QComboBox::duplicatesEnabled()
271  // void QComboBox::setDuplicatesEnabled(bool)
272  obj1.setDuplicatesEnabled(false);
273  QCOMPARE(false, obj1.duplicatesEnabled());
274  obj1.setDuplicatesEnabled(true);
275  QCOMPARE(true, obj1.duplicatesEnabled());
276 
277  // InsertPolicy QComboBox::insertPolicy()
278  // void QComboBox::setInsertPolicy(InsertPolicy)
279  obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::NoInsert));
281  obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtTop));
285  obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtBottom));
293 
294  // SizeAdjustPolicy QComboBox::sizeAdjustPolicy()
295  // void QComboBox::setSizeAdjustPolicy(SizeAdjustPolicy)
296  obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents));
302 
303  // int QComboBox::minimumContentsLength()
304  // void QComboBox::setMinimumContentsLength(int)
305  obj1.setMinimumContentsLength(0);
306  QCOMPARE(0, obj1.minimumContentsLength());
307  obj1.setMinimumContentsLength(100);
308  QCOMPARE(100, obj1.minimumContentsLength());
309  obj1.setMinimumContentsLength(INT_MIN);
310  QCOMPARE(100, obj1.minimumContentsLength()); // Cannot be set to something negative => old value
311  obj1.setMinimumContentsLength(INT_MAX);
312  QCOMPARE(INT_MAX, obj1.minimumContentsLength());
313 
314  // QLineEdit * QComboBox::lineEdit()
315  // void QComboBox::setLineEdit(QLineEdit *)
316  QLineEdit *var8 = new QLineEdit(0);
317  obj1.setLineEdit(var8);
318  QCOMPARE(var8, obj1.lineEdit());
319  QTest::ignoreMessage(QtWarningMsg, "QComboBox::setLineEdit: cannot set a 0 line edit");
320  obj1.setLineEdit((QLineEdit *)0);
321  QCOMPARE(var8, obj1.lineEdit());
322  // delete var8; // No delete, since QComboBox takes ownership
323 
324  // After setting a line edit, completer() should not return nullptr anymore
325  QVERIFY(obj1.completer() != nullptr);
326 
327  // const QValidator * QComboBox::validator()
328  // void QComboBox::setValidator(const QValidator *)
329  QIntValidator *var9 = new QIntValidator(0);
330  obj1.setValidator(var9);
331  QCOMPARE(obj1.validator(), (const QValidator *)var9);
332  obj1.setValidator((QValidator *)0);
333  QCOMPARE(obj1.validator(), nullptr);
334  delete var9;
335 
336  // QAbstractItemDelegate * QComboBox::itemDelegate()
337  // void QComboBox::setItemDelegate(QAbstractItemDelegate *)
339  obj1.setItemDelegate(var10);
340  QCOMPARE(obj1.itemDelegate(), var10);
341  QTest::ignoreMessage(QtWarningMsg, "QComboBox::setItemDelegate: cannot set a 0 delegate");
342  obj1.setItemDelegate((QAbstractItemDelegate *)0);
343  QCOMPARE(obj1.itemDelegate(), var10);
344  // delete var10; // No delete, since QComboBox takes ownership
345 
346  // QAbstractItemModel * QComboBox::model()
347  // void QComboBox::setModel(QAbstractItemModel *)
349  obj1.setModel(var11);
350  QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
351  QTest::ignoreMessage(QtWarningMsg, "QComboBox::setModel: cannot set a 0 model");
352  obj1.setModel((QAbstractItemModel *)0);
353  QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
354  delete var11;
355  obj1.model();
356 
357  // int QComboBox::modelColumn()
358  // void QComboBox::setModelColumn(int)
359  obj1.setModelColumn(0);
360  QCOMPARE(0, obj1.modelColumn());
361  obj1.setModelColumn(INT_MIN);
362 // QCOMPARE(0, obj1.modelColumn()); // Cannot be set to something negative => column 0
363  obj1.setModelColumn(INT_MAX);
364  QCOMPARE(INT_MAX, obj1.modelColumn());
365  obj1.setModelColumn(0); // back to normal
366 
367  // QAbstractItemView * QComboBox::view()
368  // void QComboBox::setView(QAbstractItemView *)
370  obj1.setView(var13);
371  QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
372  QTest::ignoreMessage(QtWarningMsg, "QComboBox::setView: cannot set a 0 view");
373  obj1.setView((QAbstractItemView *)0);
374  QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
375  delete var13;
376 
377  // int QComboBox::currentIndex()
378  // void QComboBox::setCurrentIndex(int)
379  obj1.setEditable(false);
380  obj1.setCurrentIndex(0);
381  QCOMPARE(-1, obj1.currentIndex());
382  obj1.setCurrentIndex(INT_MIN);
383  QCOMPARE(-1, obj1.currentIndex());
384  obj1.setCurrentIndex(INT_MAX);
385  QCOMPARE(-1, obj1.currentIndex());
386  obj1.addItems(QStringList() << "1" << "2" << "3" << "4" << "5");
387  obj1.setCurrentIndex(0);
388  QCOMPARE(0, obj1.currentIndex()); // Valid
389  obj1.setCurrentIndex(INT_MIN);
390  QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
391  obj1.setCurrentIndex(4);
392  QCOMPARE(4, obj1.currentIndex()); // Valid
393  obj1.setCurrentIndex(INT_MAX);
394  QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
395 
396  obj1.setIconSize(QSize(64, 32));
397  QCOMPARE(obj1.iconSize(), QSize(64, 32));
398  obj1.setIconSize(QSize());
399  const int iconWidth = obj1.style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, &obj1);
400  QCOMPARE(obj1.iconSize(), QSize(iconWidth, iconWidth));
401 
402  const QString placeholderText("Please select");
403  obj1.setCurrentIndex(1);
404  obj1.setPlaceholderText(placeholderText);
405  QCOMPARE(obj1.placeholderText(), placeholderText);
406  QCOMPARE(obj1.currentText(), "2");
407  QCOMPARE(obj1.currentIndex(), 1);
408  obj1.setPlaceholderText(QString()); // should not change anything
409  QCOMPARE(obj1.placeholderText(), QString());
410  QCOMPARE(obj1.currentText(), "2");
411 
412  obj1.clear();
413  obj1.setPlaceholderText(placeholderText);
414  obj1.addItems({"1", "2", "3", "4", "5"});
415  QCOMPARE(obj1.currentText(), QString());
416  QCOMPARE(obj1.currentIndex(), -1);
417  obj1.setPlaceholderText(QString()); // should not change anything
418  QCOMPARE(obj1.currentText(), "1");
419  QCOMPARE(obj1.currentIndex(), 0);
420 }
421 
424 
426 
427 class TestWidget : public QWidget
428 {
429 public:
430  TestWidget() : QWidget(0, Qt::Window), m_comboBox(new QComboBox(this))
431  {
432  setObjectName("parent");
433  move(200, 200);
434  resize(400, 400);
435  m_comboBox->setGeometry(0, 0, 100, 100);
436  m_comboBox->setObjectName("testObject");
437  m_comboBox->setEditable(false);
438  }
439 
440  QComboBox *comboBox() const { return m_comboBox; }
441 
442 private:
443  QComboBox *m_comboBox;
444 
445 
446 };
447 
448 void tst_QComboBox::setEditable()
449 {
450  TestWidget topLevel;
451  topLevel.show();
453  QComboBox *testWidget = topLevel.comboBox();
454  // make sure we have no lineedit
455  QVERIFY(!testWidget->lineEdit());
456  // test setEditable(true)
457  testWidget->setEditable(true);
458  QVERIFY(testWidget->lineEdit());
459  testWidget->addItem("foo");
460  QCOMPARE(testWidget->lineEdit()->text(), QString("foo"));
461  // test setEditable(false)
462 
463  QLineEdit *lineEdit = testWidget->lineEdit();
464  // line edit is visible when combobox is editable
466  testWidget->setEditable(false);
467  QVERIFY(!testWidget->lineEdit());
468  // line edit should have been explicitly hidden when editable was turned off
470 }
471 
472 
473 void tst_QComboBox::setPalette()
474 {
475 #ifdef Q_OS_MAC
476  if (QApplication::style()->inherits("QMacStyle")) {
477  QSKIP("This test doesn't make sense for pixmap-based styles");
478  }
479 #endif
480  TestWidget topLevel;
481  topLevel.show();
483  QComboBox *testWidget = topLevel.comboBox();
484  QPalette pal = testWidget->palette();
485  pal.setColor(QPalette::Base, Qt::red);
486  testWidget->setPalette(pal);
487  testWidget->setEditable(!testWidget->isEditable());
488 
489  pal.setColor(QPalette::Base, Qt::blue);
490  testWidget->setPalette(pal);
491 
492  const QObjectList comboChildren = testWidget->children();
493  for (int i = 0; i < comboChildren.size(); ++i) {
494  QObject *o = comboChildren.at(i);
495  if (o->isWidgetType()) {
496  QCOMPARE(((QWidget*)o)->palette(), pal);
497  }
498  }
499 
500  testWidget->setEditable(true);
501  pal.setColor(QPalette::Base, Qt::red);
502  //Setting it on the lineedit should be separate form the combo
503  testWidget->lineEdit()->setPalette(pal);
504  QVERIFY(testWidget->palette() != pal);
505  QCOMPARE(testWidget->lineEdit()->palette(), pal);
506  pal.setColor(QPalette::Base, Qt::green);
507  //Setting it on the combo directly should override lineedit
508  testWidget->setPalette(pal);
509  QCOMPARE(testWidget->palette(), pal);
510  QCOMPARE(testWidget->lineEdit()->palette(), pal);
511 }
512 
513 void tst_QComboBox::sizeAdjustPolicy()
514 {
515  TestWidget topLevel;
516  topLevel.show();
518  QComboBox *testWidget = topLevel.comboBox();
519  // test that adding new items will not change the sizehint for AdjustToContentsOnFirstShow
520  QVERIFY(!testWidget->count());
521  QCOMPARE(testWidget->sizeAdjustPolicy(), QComboBox::AdjustToContentsOnFirstShow);
522  QVERIFY(testWidget->isVisible());
523  QSize firstShow = testWidget->sizeHint();
524  testWidget->addItem("normal item");
525  QCOMPARE(testWidget->sizeHint(), firstShow);
526 
527  // check that with minimumContentsLength/AdjustToMinimumContentsLengthWithIcon sizehint changes
528  testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
529  testWidget->setMinimumContentsLength(30);
530  QSize minimumContentsLength = testWidget->sizeHint();
531  QVERIFY(minimumContentsLength.width() > firstShow.width());
532  testWidget->setMinimumContentsLength(60);
533  QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
534  minimumContentsLength = testWidget->sizeHint();
535  testWidget->setIconSize(QSize(128,128));
536  QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
537 
538  // check AdjustToContents changes with content
539  testWidget->setSizeAdjustPolicy(QComboBox::AdjustToContents);
540  QSize content = testWidget->sizeHint();
541  testWidget->addItem("small");
542  QCOMPARE(testWidget->sizeHint(), content);
543  testWidget->addItem("looooooooooooooooooooooong item");
544  // minimumContentsLength() > sizeof("looooooooooooooooooooooong item"), so the sizeHint()
545  // stays the same
546  QCOMPARE(testWidget->sizeHint(), content);
547  // over 60 characters (cf. setMinimumContentsLength() call above)
548  testWidget->addItem("loooooooooooooooooooooooooooooooooooooooooooooo"
549  "ooooooooooooooooooooooooooooooooooooooooooooooo"
550  "ooooooooooooooooooooooooooooong item");
551  QVERIFY(testWidget->sizeHint().width() > content.width());
552 
553  // check AdjustToContents also shrinks when item changes
554  content = testWidget->sizeHint();
555  for (int i=0; i<testWidget->count(); ++i)
556  testWidget->setItemText(i, "XXXXXXXXXX");
557  QVERIFY(testWidget->sizeHint().width() < content.width());
558 
559  // check AdjustToContents shrinks when items are removed
560  content = testWidget->sizeHint();
561  while (testWidget->count())
562  testWidget->removeItem(0);
563  QCOMPARE(testWidget->sizeHint(), content);
564  testWidget->setMinimumContentsLength(0);
565  QVERIFY(testWidget->sizeHint().width() < content.width());
566 
567  // check AdjustToContents changes when model changes
568  content = testWidget->sizeHint();
569  QStandardItemModel *model = new QStandardItemModel(2, 1, testWidget);
570  testWidget->setModel(model);
571  QVERIFY(testWidget->sizeHint().width() < content.width());
572 
573  // check AdjustToContents changes when a row is inserted into the model
574  content = testWidget->sizeHint();
575  QStandardItem *item = new QStandardItem(QStringLiteral("This is an item"));
576  model->appendRow(item);
577  QVERIFY(testWidget->sizeHint().width() > content.width());
578 
579  // check AdjustToContents changes when model is reset
580  content = testWidget->sizeHint();
581  model->clear();
582  QVERIFY(testWidget->sizeHint().width() < content.width());
583 }
584 
585 void tst_QComboBox::clear()
586 {
587  TestWidget topLevel;
588  topLevel.show();
590  QComboBox *testWidget = topLevel.comboBox();
591  // first non editable combobox
592  testWidget->addItem("foo");
593  testWidget->addItem("bar");
594  QVERIFY(testWidget->count() > 0);
595  QCOMPARE(testWidget->currentIndex(), 0);
596 
597  testWidget->clear();
598  QCOMPARE(testWidget->count(), 0);
599  QCOMPARE(testWidget->currentIndex(), -1);
600  QVERIFY(testWidget->currentText().isEmpty());
601 
602  // then editable combobox
603  testWidget->clear();
604  testWidget->setEditable(true);
605  testWidget->addItem("foo");
606  testWidget->addItem("bar");
607  QVERIFY(testWidget->count() > 0);
608  QCOMPARE(testWidget->currentIndex(), 0);
609  QVERIFY(testWidget->lineEdit());
610  QVERIFY(!testWidget->lineEdit()->text().isEmpty());
611  testWidget->clear();
612  QCOMPARE(testWidget->count(), 0);
613  QCOMPARE(testWidget->currentIndex(), -1);
614  QVERIFY(testWidget->currentText().isEmpty());
615  QVERIFY(testWidget->lineEdit()->text().isEmpty());
616 }
617 
618 void tst_QComboBox::insertPolicy_data()
619 {
620  QTest::addColumn<QStringList>("initialEntries");
621  QTest::addColumn<QComboBox::InsertPolicy>("insertPolicy");
622  QTest::addColumn<int>("currentIndex");
623  QTest::addColumn<QString>("userInput");
624  QTest::addColumn<QStringList>("result");
625 
626  /* Each insertPolicy should test at least:
627  no initial entries
628  one initial entry
629  five initial entries, current is first item
630  five initial entries, current is third item
631  five initial entries, current is last item
632  */
633 
634  /* QComboBox::NoInsert - the string will not be inserted into the combobox.
635  QComboBox::InsertAtTop - insert the string as the first item in the combobox.
636  QComboBox::InsertAtCurrent - replace the previously selected item with the string the user has entered.
637  QComboBox::InsertAtBottom - insert the string as the last item in the combobox.
638  QComboBox::InsertAfterCurrent - insert the string after the previously selected item.
639  QComboBox::InsertBeforeCurrent - insert the string before the previously selected item.
640  QComboBox::InsertAlphabetically - insert the string at the alphabetic position.
641  */
642  QStringList initial;
643  QStringList oneEntry("One");
644  QStringList fiveEntries;
645  fiveEntries << "One" << "Two" << "Three" << "Four" << "Five";
646  QString input("insert");
647 
648  {
649  QTest::newRow("NoInsert-NoInitial") << initial << QComboBox::NoInsert << 0 << input << initial;
650  QTest::newRow("NoInsert-OneInitial") << oneEntry << QComboBox::NoInsert << 0 << input << oneEntry;
651  QTest::newRow("NoInsert-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::NoInsert << 0 << input << fiveEntries;
652  QTest::newRow("NoInsert-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::NoInsert << 2 << input << fiveEntries;
653  QTest::newRow("NoInsert-FiveInitial-LastCurrent") << fiveEntries << QComboBox::NoInsert << 4 << input << fiveEntries;
654  }
655 
656  {
657  QStringList initialAtTop("insert");
658  QStringList oneAtTop;
659  oneAtTop << "insert" << "One";
660  QStringList fiveAtTop;
661  fiveAtTop << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
662 
663  QTest::newRow("AtTop-NoInitial") << initial << QComboBox::InsertAtTop << 0 << input << initialAtTop;
664  QTest::newRow("AtTop-OneInitial") << oneEntry << QComboBox::InsertAtTop << 0 << input << oneAtTop;
665  QTest::newRow("AtTop-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtTop << 0 << input << fiveAtTop;
666  QTest::newRow("AtTop-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtTop << 2 << input << fiveAtTop;
667  QTest::newRow("AtTop-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtTop << 4 << input << fiveAtTop;
668  }
669 
670  {
671  QStringList initialAtCurrent("insert");
672  QStringList oneAtCurrent("insert");
673  QStringList fiveAtCurrentFirst;
674  fiveAtCurrentFirst << "insert" << "Two" << "Three" << "Four" << "Five";
675  QStringList fiveAtCurrentThird;
676  fiveAtCurrentThird << "One" << "Two" << "insert" << "Four" << "Five";
677  QStringList fiveAtCurrentLast;
678  fiveAtCurrentLast << "One" << "Two" << "Three" << "Four" << "insert";
679 
680  QTest::newRow("AtCurrent-NoInitial") << initial << QComboBox::InsertAtCurrent << 0 << input << initialAtCurrent;
681  QTest::newRow("AtCurrent-OneInitial") << oneEntry << QComboBox::InsertAtCurrent << 0 << input << oneAtCurrent;
682  QTest::newRow("AtCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 0 << input << fiveAtCurrentFirst;
683  QTest::newRow("AtCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 2 << input << fiveAtCurrentThird;
684  QTest::newRow("AtCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 4 << input << fiveAtCurrentLast;
685  }
686 
687  {
688  QStringList initialAtBottom("insert");
689  QStringList oneAtBottom;
690  oneAtBottom << "One" << "insert";
691  QStringList fiveAtBottom;
692  fiveAtBottom << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
693 
694  QTest::newRow("AtBottom-NoInitial") << initial << QComboBox::InsertAtBottom << 0 << input << initialAtBottom;
695  QTest::newRow("AtBottom-OneInitial") << oneEntry << QComboBox::InsertAtBottom << 0 << input << oneAtBottom;
696  QTest::newRow("AtBottom-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtBottom << 0 << input << fiveAtBottom;
697  QTest::newRow("AtBottom-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtBottom << 2 << input << fiveAtBottom;
698  QTest::newRow("AtBottom-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtBottom << 4 << input << fiveAtBottom;
699  }
700 
701  {
702  QStringList initialAfterCurrent("insert");
703  QStringList oneAfterCurrent;
704  oneAfterCurrent << "One" << "insert";
705  QStringList fiveAfterCurrentFirst;
706  fiveAfterCurrentFirst << "One" << "insert" << "Two" << "Three" << "Four" << "Five";
707  QStringList fiveAfterCurrentThird;
708  fiveAfterCurrentThird << "One" << "Two" << "Three" << "insert" << "Four" << "Five";
709  QStringList fiveAfterCurrentLast;
710  fiveAfterCurrentLast << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
711 
712  QTest::newRow("AfterCurrent-NoInitial") << initial << QComboBox::InsertAfterCurrent << 0 << input << initialAfterCurrent;
713  QTest::newRow("AfterCurrent-OneInitial") << oneEntry << QComboBox::InsertAfterCurrent << 0 << input << oneAfterCurrent;
714  QTest::newRow("AfterCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 0 << input << fiveAfterCurrentFirst;
715  QTest::newRow("AfterCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 2 << input << fiveAfterCurrentThird;
716  QTest::newRow("AfterCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 4 << input << fiveAfterCurrentLast;
717  }
718 
719  {
720  QStringList initialBeforeCurrent("insert");
721  QStringList oneBeforeCurrent;
722  oneBeforeCurrent << "insert" << "One";
723  QStringList fiveBeforeCurrentFirst;
724  fiveBeforeCurrentFirst << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
725  QStringList fiveBeforeCurrentThird;
726  fiveBeforeCurrentThird << "One" << "Two" << "insert" << "Three" << "Four" << "Five";
727  QStringList fiveBeforeCurrentLast;
728  fiveBeforeCurrentLast << "One" << "Two" << "Three" << "Four" << "insert" << "Five";
729 
730  QTest::newRow("BeforeCurrent-NoInitial") << initial << QComboBox::InsertBeforeCurrent << 0 << input << initialBeforeCurrent;
731  QTest::newRow("BeforeCurrent-OneInitial") << oneEntry << QComboBox::InsertBeforeCurrent << 0 << input << oneBeforeCurrent;
732  QTest::newRow("BeforeCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 0 << input << fiveBeforeCurrentFirst;
733  QTest::newRow("BeforeCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 2 << input << fiveBeforeCurrentThird;
734  QTest::newRow("BeforeCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 4 << input << fiveBeforeCurrentLast;
735  }
736 
737  {
738  oneEntry.clear();
739  oneEntry << "foobar";
740  fiveEntries.clear();
741  fiveEntries << "bar" << "foo" << "initial" << "Item" << "stamp";
742 
743  QStringList initialAlphabetically("insert");
744  QStringList oneAlphabetically;
745  oneAlphabetically << "foobar" << "insert";
746  QStringList fiveAlphabetically;
747  fiveAlphabetically << "bar" << "foo" << "initial" << "insert" << "Item" << "stamp";
748 
749  QTest::newRow("Alphabetically-NoInitial") << initial << QComboBox::InsertAlphabetically << 0 << input << initialAlphabetically;
750  QTest::newRow("Alphabetically-OneInitial") << oneEntry << QComboBox::InsertAlphabetically << 0 << input << oneAlphabetically;
751  QTest::newRow("Alphabetically-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 0 << input << fiveAlphabetically;
752  QTest::newRow("Alphabetically-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 2 << input << fiveAlphabetically;
753  QTest::newRow("Alphabetically-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 4 << input << fiveAlphabetically;
754  }
755 }
756 
757 void tst_QComboBox::insertPolicy()
758 {
759  QFETCH(QStringList, initialEntries);
760  QFETCH(QComboBox::InsertPolicy, insertPolicy);
761  QFETCH(int, currentIndex);
762  QFETCH(QString, userInput);
764 
765  TestWidget topLevel;
766  topLevel.show();
768  QComboBox *testWidget = topLevel.comboBox();
769  testWidget->clear();
770  testWidget->setInsertPolicy(insertPolicy);
771  testWidget->addItems(initialEntries);
772  testWidget->setEditable(true);
773  if (initialEntries.count() > 0)
774  testWidget->setCurrentIndex(currentIndex);
775 
776  // clear
777  QTest::mouseDClick(testWidget->lineEdit(), Qt::LeftButton);
778  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Delete);
779 
780  QTest::keyClicks(testWidget->lineEdit(), userInput);
781  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Return);
782 
783  // First check that there is the right number of entries, or
784  // we may unwittingly pass
785  QCOMPARE((int)result.count(), testWidget->count());
786 
787  // No need to compare if there are no strings to compare
788  if (result.count() > 0) {
789  for (int i=0; i<testWidget->count(); ++i) {
790  QCOMPARE(testWidget->itemText(i), result.at(i));
791  }
792  }
793 }
794 
795 // Apps running with valgrind are not fast enough.
796 void tst_QComboBox::virtualAutocompletion()
797 {
798  TestWidget topLevel;
799  topLevel.show();
801  QComboBox *testWidget = topLevel.comboBox();
802  testWidget->clear();
803  testWidget->addItem("Foo");
804  testWidget->addItem("Bar");
805  testWidget->addItem("Boat");
806  testWidget->addItem("Boost");
807  testWidget->clearEditText();
808 
809  // We need to set the keyboard input interval to a higher value
810  // as the processEvent() call takes too much time, so it restarts
811  // the keyboard search then
812 #if defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS)
813  int oldInterval = QApplication::keyboardInputInterval();
815 #endif
816 
817  // NOTE:
818  // Cannot use keyClick for this test, as it simulates keyclicks too well
819  // The virtual keyboards we're trying to catch here, do not perform that
820  // well, and send a keypress & keyrelease right after each other.
821  // This provokes the actual error, as there's no events in between to do
822  // the text completion.
823  QKeyEvent kp1(QEvent::KeyPress, Qt::Key_B, {}, "b");
824  QKeyEvent kr1(QEvent::KeyRelease, Qt::Key_B, {}, "b");
825  QApplication::sendEvent(testWidget, &kp1);
826  QApplication::sendEvent(testWidget, &kr1);
827 
828  qApp->processEvents(); // Process events to trigger autocompletion
829  QTRY_COMPARE(testWidget->currentIndex(), 1);
830 
831  QKeyEvent kp2(QEvent::KeyPress, Qt::Key_O, {}, "o");
832  QKeyEvent kr2(QEvent::KeyRelease, Qt::Key_O, {}, "o");
833 
834  QApplication::sendEvent(testWidget, &kp2);
835  QApplication::sendEvent(testWidget, &kr2);
836 
837  qApp->processEvents(); // Process events to trigger autocompletion
838  QTRY_COMPARE(testWidget->currentIndex(), 2);
839 
840  QApplication::sendEvent(testWidget, &kp2);
841  QApplication::sendEvent(testWidget, &kr2);
842  qApp->processEvents(); // Process events to trigger autocompletion
843  QTRY_COMPARE(testWidget->currentIndex(), 3);
844 #if defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS)
846 #endif
847 }
848 
849 void tst_QComboBox::autoCompletionCaseSensitivity()
850 {
852  QSKIP("Wayland: This fails. Figure out why.");
853 
854  //we have put the focus because the completer
855  //is only used when the widget actually has the focus
856  TestWidget topLevel;
857  topLevel.show();
858  QComboBox *testWidget = topLevel.comboBox();
859  qApp->setActiveWindow(&topLevel);
860  testWidget->setFocus();
862  QCOMPARE(qApp->focusWidget(), (QWidget *)testWidget);
863 
864  testWidget->clear();
865  testWidget->addItem("Cow");
866  testWidget->addItem("irrelevant1");
867  testWidget->addItem("aww");
868  testWidget->addItem("A*");
869  testWidget->addItem("irrelevant2");
870  testWidget->addItem("aBCDEF");
871  testWidget->addItem("irrelevant3");
872  testWidget->addItem("abcdef");
873  testWidget->addItem("abCdef");
874  testWidget->setEditable(true);
875 
876  // case insensitive
877  testWidget->clearEditText();
878  QSignalSpy spyReturn(testWidget, SIGNAL(activated(int)));
879  testWidget->completer()->setCaseSensitivity(Qt::CaseInsensitive);
880  QCOMPARE(testWidget->completer()->caseSensitivity(), Qt::CaseInsensitive);
881 
882  QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
883  qApp->processEvents();
884  QCOMPARE(testWidget->currentText(), QString("aww"));
885  QCOMPARE(spyReturn.count(), 0);
886 
887  QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
888  qApp->processEvents();
889  // autocompletions preserve userkey-case from 4.2
890  QCOMPARE(testWidget->currentText(), QString("abCDEF"));
891  QCOMPARE(spyReturn.count(), 0);
892 
893  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
894  qApp->processEvents();
895  QCOMPARE(testWidget->currentText(), QString("aBCDEF")); // case restored to item's case
896  QCOMPARE(spyReturn.count(), 1);
897 
898  testWidget->clearEditText();
899  QTest::keyClick(testWidget->lineEdit(), 'c');
900  QCOMPARE(testWidget->currentText(), QString("cow"));
901  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
902  QCOMPARE(testWidget->currentText(), QString("Cow")); // case restored to item's case
903 
904  testWidget->clearEditText();
905  QTest::keyClick(testWidget->lineEdit(), 'a');
906  QTest::keyClick(testWidget->lineEdit(), '*');
907  QCOMPARE(testWidget->currentText(), QString("a*"));
908  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
909  QCOMPARE(testWidget->currentText(), QString("A*"));
910 
911  // case sensitive
912  testWidget->clearEditText();
913  testWidget->completer()->setCaseSensitivity(Qt::CaseSensitive);
914  QCOMPARE(testWidget->completer()->caseSensitivity(), Qt::CaseSensitive);
915  QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
916  qApp->processEvents();
917  QCOMPARE(testWidget->currentText(), QString("aww"));
918  QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
919  qApp->processEvents();
920  QCOMPARE(testWidget->currentText(), QString("abcdef"));
921 
922  testWidget->setCurrentIndex(0); // to reset the completion's "start"
923  testWidget->clearEditText();
924  QTest::keyClick(testWidget->lineEdit(), 'a');
925  QTest::keyClick(testWidget->lineEdit(), 'b');
926  QCOMPARE(testWidget->currentText(), QString("abcdef"));
927  QTest::keyClick(testWidget->lineEdit(), 'C');
928  qApp->processEvents();
929  QCOMPARE(testWidget->currentText(), QString("abCdef"));
930  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
931  qApp->processEvents();
932  QCOMPARE(testWidget->currentText(), QString("abCdef")); // case restored to item's case
933 
934  testWidget->clearEditText();
935  QTest::keyClick(testWidget->lineEdit(), 'c');
936  QCOMPARE(testWidget->currentText(), QString("c"));
937  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Backspace);
938  QTest::keyClick(testWidget->lineEdit(), 'C');
939  QCOMPARE(testWidget->currentText(), QString("Cow"));
940  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
941  QCOMPARE(testWidget->currentText(), QString("Cow"));
942 
943  testWidget->clearEditText();
944  QTest::keyClick(testWidget->lineEdit(), 'a');
945  QTest::keyClick(testWidget->lineEdit(), '*');
946  QCOMPARE(testWidget->currentText(), QString("a*"));
947  QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
948  QCOMPARE(testWidget->currentText(), QString("a*")); // A* not matched
949 }
950 
951 void tst_QComboBox::hide()
952 {
953  TestWidget topLevel;
954  topLevel.show();
956  QComboBox *testWidget = topLevel.comboBox();
957  testWidget->addItem("foo");
958  testWidget->showPopup();
959  //allow combobox effect to complete
960  QTRY_VERIFY(testWidget->view());
961  QTRY_VERIFY(testWidget->view()->isVisible());
962  testWidget->hidePopup();
963  //allow combobox effect to complete
964  QTRY_VERIFY(!testWidget->view()->isVisible());
965  testWidget->hide();
966  QVERIFY(!testWidget->isVisible());
967 }
968 
969 
970 
971 void tst_QComboBox::currentIndex_data()
972 {
973  QTest::addColumn<QStringList>("initialItems");
974  QTest::addColumn<int>("setCurrentIndex");
975  QTest::addColumn<int>("removeIndex");
976  QTest::addColumn<int>("insertIndex");
977  QTest::addColumn<QString>("insertText");
978  QTest::addColumn<int>("expectedCurrentIndex");
979  QTest::addColumn<QString>("expectedCurrentText");
980  QTest::addColumn<int>("expectedSignalCount");
981 
982  QStringList initialItems;
983  int setCurrentIndex;
984  int removeIndex;
985  int insertIndex;
986  QString insertText;
987  int expectedCurrentIndex;
988  QString expectedCurrentText;
989  int expectedSignalCount;
990 
991  {
992  initialItems.clear();
993  initialItems << "foo" << "bar";
994  setCurrentIndex = -2;
995  removeIndex = -1;
996  insertIndex = -1;
997  insertText = "";
998  expectedCurrentIndex = 0;
999  expectedCurrentText = "foo";
1000  expectedSignalCount = 1;
1001  QTest::newRow("first added item is set to current if there is no current")
1002  << initialItems << setCurrentIndex << removeIndex
1003  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1004  << expectedSignalCount;
1005  }
1006  {
1007  initialItems.clear();
1008  initialItems << "foo" << "bar";
1009  setCurrentIndex = 1;
1010  removeIndex = -1;
1011  insertIndex = -1;
1012  insertText = "";
1013  expectedCurrentIndex = 1;
1014  expectedCurrentText = "bar";
1015  expectedSignalCount = 2;
1016  QTest::newRow("check that setting the index works")
1017  << initialItems << setCurrentIndex << removeIndex
1018  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1019  << expectedSignalCount;
1020 
1021  }
1022  {
1023  initialItems.clear();
1024  initialItems << "foo" << "bar";
1025  setCurrentIndex = -1; // will invalidate the currentIndex
1026  removeIndex = -1;
1027  insertIndex = -1;
1028  insertText = "";
1029  expectedCurrentIndex = -1;
1030  expectedCurrentText = "";
1031  expectedSignalCount = 2;
1032  QTest::newRow("check that isetting the index to -1 works")
1033  << initialItems << setCurrentIndex << removeIndex
1034  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1035  << expectedSignalCount;
1036 
1037  }
1038  {
1039  initialItems.clear();
1040  initialItems << "foo";
1041  setCurrentIndex = 0;
1042  removeIndex = 0;
1043  insertIndex = -1;
1044  insertText = "";
1045  expectedCurrentIndex = -1;
1046  expectedCurrentText = "";
1047  expectedSignalCount = 2;
1048  QTest::newRow("check that current index is invalid when removing the only item")
1049  << initialItems << setCurrentIndex << removeIndex
1050  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1051  << expectedSignalCount;
1052  }
1053  {
1054  initialItems.clear();
1055  initialItems << "foo" << "bar";
1056  setCurrentIndex = 1;
1057  removeIndex = 0;
1058  insertIndex = -1;
1059  insertText = "";
1060  expectedCurrentIndex = 0;
1061  expectedCurrentText = "bar";
1062  expectedSignalCount = 3;
1063  QTest::newRow("check that the current index follows the item when removing an item above")
1064  << initialItems << setCurrentIndex << removeIndex
1065  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1066  << expectedSignalCount;
1067 
1068  }
1069  {
1070  initialItems.clear();
1071  initialItems << "foo" << "bar" << "baz";
1072  setCurrentIndex = 1;
1073  removeIndex = 1;
1074  insertIndex = -1;
1075  insertText = "";
1076  expectedCurrentIndex = 1;
1077  expectedCurrentText = "baz";
1078  expectedSignalCount = 3;
1079  QTest::newRow("check that the current index uses the next item if current is removed")
1080  << initialItems << setCurrentIndex << removeIndex
1081  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1082  << expectedSignalCount;
1083  }
1084  {
1085  initialItems.clear();
1086  initialItems << "foo" << "bar" << "baz";
1087  setCurrentIndex = 2;
1088  removeIndex = 2;
1089  insertIndex = -1;
1090  insertText = "";
1091  expectedCurrentIndex = 1;
1092  expectedCurrentText = "bar";
1093  expectedSignalCount = 3;
1094  QTest::newRow("check that the current index is moved to the one before if current is removed")
1095  << initialItems << setCurrentIndex << removeIndex
1096  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1097  << expectedSignalCount;
1098  }
1099  {
1100  initialItems.clear();
1101  initialItems << "foo" << "bar" << "baz";
1102  setCurrentIndex = 1;
1103  removeIndex = 2;
1104  insertIndex = -1;
1105  insertText = "";
1106  expectedCurrentIndex = 1;
1107  expectedCurrentText = "bar";
1108  expectedSignalCount = 2;
1109  QTest::newRow("check that the current index is unchanged if you remove an item after")
1110  << initialItems << setCurrentIndex << removeIndex
1111  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1112  << expectedSignalCount;
1113  }
1114  {
1115  initialItems.clear();
1116  initialItems << "foo" << "bar";
1117  setCurrentIndex = 1;
1118  removeIndex = -1;
1119  insertIndex = 0;
1120  insertText = "baz";
1121  expectedCurrentIndex = 2;
1122  expectedCurrentText = "bar";
1123  expectedSignalCount = 3;
1124  QTest::newRow("check that the current index follows the item if you insert before current")
1125  << initialItems << setCurrentIndex << removeIndex
1126  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1127  << expectedSignalCount;
1128  }
1129  {
1130  initialItems.clear();
1131  initialItems << "foo";
1132  setCurrentIndex = 0;
1133  removeIndex = -1;
1134  insertIndex = 0;
1135  insertText = "bar";
1136  expectedCurrentIndex = 1;
1137  expectedCurrentText = "foo";
1138  expectedSignalCount = 2;
1139  QTest::newRow("check that the current index follows the item if you insert on the current")
1140  << initialItems << setCurrentIndex << removeIndex
1141  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1142  << expectedSignalCount;
1143  }
1144  {
1145  initialItems.clear();
1146  initialItems << "foo";
1147  setCurrentIndex = 0;
1148  removeIndex = -1;
1149  insertIndex = 1;
1150  insertText = "bar";
1151  expectedCurrentIndex = 0;
1152  expectedCurrentText = "foo";
1153  expectedSignalCount = 1;
1154  QTest::newRow("check that the current index stays the same if you insert after the current")
1155  << initialItems << setCurrentIndex << removeIndex
1156  << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
1157  << expectedSignalCount;
1158  }
1159 }
1160 
1161 void tst_QComboBox::currentIndex()
1162 {
1163  QFETCH(QStringList, initialItems);
1164  QFETCH(int, setCurrentIndex);
1165  QFETCH(int, removeIndex);
1166  QFETCH(int, insertIndex);
1167  QFETCH(QString, insertText);
1168  QFETCH(int, expectedCurrentIndex);
1169  QFETCH(QString, expectedCurrentText);
1170  QFETCH(int, expectedSignalCount);
1171 
1172  TestWidget topLevel;
1173  topLevel.show();
1175  QComboBox *testWidget = topLevel.comboBox();
1176  // test both editable/non-editable combobox
1177  for (int edit = 0; edit < 2; ++edit) {
1178  testWidget->clear();
1179  testWidget->setEditable(edit ? true : false);
1180  if (edit)
1181  QVERIFY(testWidget->lineEdit());
1182 
1183  // verify it is empty, has no current index and no current text
1184  QCOMPARE(testWidget->count(), 0);
1185  QCOMPARE(testWidget->currentIndex(), -1);
1186  QVERIFY(testWidget->currentText().isEmpty());
1187 
1188  // spy on currentIndexChanged
1189  QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int)));
1190 
1191  // stuff items into it
1192  foreach(QString text, initialItems) {
1193  testWidget->addItem(text);
1194  }
1195  QCOMPARE(testWidget->count(), initialItems.count());
1196 
1197  // set current index, remove and/or insert
1198  if (setCurrentIndex >= -1) {
1199  testWidget->setCurrentIndex(setCurrentIndex);
1200  QCOMPARE(testWidget->currentIndex(), setCurrentIndex);
1201  }
1202 
1203  if (removeIndex >= 0)
1204  testWidget->removeItem(removeIndex);
1205  if (insertIndex >= 0)
1206  testWidget->insertItem(insertIndex, insertText);
1207 
1208  // compare with expected index and text
1209  QCOMPARE(testWidget->currentIndex(), expectedCurrentIndex);
1210  QCOMPARE(testWidget->currentText(), expectedCurrentText);
1211 
1212  // check that signal count is correct
1213  QCOMPARE(indexChangedInt.count(), expectedSignalCount);
1214 
1215  // compare with last sent signal values
1216  if (indexChangedInt.count())
1217  QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(),
1218  testWidget->currentIndex());
1219 
1220  if (edit) {
1221  testWidget->setCurrentIndex(-1);
1222  testWidget->setInsertPolicy(QComboBox::InsertAtBottom);
1223  QTest::keyPress(testWidget, 'a');
1224  QTest::keyPress(testWidget, 'b');
1225  QCOMPARE(testWidget->currentText(), QString("ab"));
1226  QCOMPARE(testWidget->currentIndex(), -1);
1227  int numItems = testWidget->count();
1228  QTest::keyPress(testWidget, Qt::Key_Return);
1229  QCOMPARE(testWidget->count(), numItems + 1);
1230  QCOMPARE(testWidget->currentIndex(), numItems);
1231  testWidget->setCurrentIndex(-1);
1232  QTest::keyPress(testWidget, 'a');
1233  QTest::keyPress(testWidget, 'b');
1234  QCOMPARE(testWidget->currentIndex(), -1);
1235  }
1236  }
1237 }
1238 
1239 void tst_QComboBox::insertItems_data()
1240 {
1241  QTest::addColumn<QStringList>("initialItems");
1242  QTest::addColumn<QStringList>("insertedItems");
1243  QTest::addColumn<int>("insertIndex");
1244  QTest::addColumn<int>("expectedIndex");
1245 
1246  QStringList initialItems;
1247  QStringList insertedItems;
1248 
1249  initialItems << "foo" << "bar";
1250  insertedItems << "mongo";
1251 
1252  QTest::newRow("prepend") << initialItems << insertedItems << 0 << 0;
1253  QTest::newRow("prepend with negative value") << initialItems << insertedItems << -1 << 0;
1254  QTest::newRow("append") << initialItems << insertedItems << initialItems.count() << initialItems.count();
1255  QTest::newRow("append with too high value") << initialItems << insertedItems << 999 << initialItems.count();
1256  QTest::newRow("insert") << initialItems << insertedItems << 1 << 1;
1257 }
1258 
1259 void tst_QComboBox::insertItems()
1260 {
1261  QFETCH(QStringList, initialItems);
1262  QFETCH(QStringList, insertedItems);
1263  QFETCH(int, insertIndex);
1264  QFETCH(int, expectedIndex);
1265 
1266  TestWidget topLevel;
1267  topLevel.show();
1269  QComboBox *testWidget = topLevel.comboBox();
1270  testWidget->insertItems(0, initialItems);
1271  QCOMPARE(testWidget->count(), initialItems.count());
1272 
1273  testWidget->insertItems(insertIndex, insertedItems);
1274 
1275  QCOMPARE(testWidget->count(), initialItems.count() + insertedItems.count());
1276  for (int i=0; i<insertedItems.count(); ++i)
1277  QCOMPARE(testWidget->itemText(expectedIndex + i), insertedItems.at(i));
1278 }
1279 
1280 void tst_QComboBox::insertItem_data()
1281 {
1282  QTest::addColumn<QStringList>("initialItems");
1283  QTest::addColumn<int>("insertIndex");
1284  QTest::addColumn<QString>("itemLabel");
1285  QTest::addColumn<int>("expectedIndex");
1286  QTest::addColumn<bool>("editable");
1287 
1288  QStringList initialItems;
1289  initialItems << "foo" << "bar";
1290  for(int e = 0 ; e<2 ; e++) {
1291  bool editable = (e==0);
1292  QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0 << editable;
1293  QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0 << editable;
1294  QTest::newRow("Insert beyond count") << initialItems << 3 << "inserted" << 2 << editable;
1295  QTest::newRow("Insert at count") << initialItems << 2 << "inserted" << 2 << editable;
1296  QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1 << editable;
1297  }
1298 }
1299 
1300 void tst_QComboBox::insertItem()
1301 {
1302  QFETCH(QStringList, initialItems);
1303  QFETCH(int, insertIndex);
1304  QFETCH(QString, itemLabel);
1305  QFETCH(int, expectedIndex);
1306  QFETCH(bool, editable);
1307 
1308  TestWidget topLevel;
1309  topLevel.show();
1311  QComboBox *testWidget = topLevel.comboBox();
1312  testWidget->insertItems(0, initialItems);
1313  QCOMPARE(testWidget->count(), initialItems.count());
1314 
1315  testWidget->setEditable(true);
1316  if (editable)
1317  testWidget->setEditText("FOO");
1318  testWidget->insertItem(insertIndex, itemLabel);
1319 
1320  QCOMPARE(testWidget->count(), initialItems.count() + 1);
1321  QCOMPARE(testWidget->itemText(expectedIndex), itemLabel);
1322 
1323  if (editable)
1324  QCOMPARE(testWidget->currentText(), QString("FOO"));
1325 }
1326 
1327 void tst_QComboBox::insertOnCurrentIndex()
1328 {
1329  TestWidget topLevel;
1330  topLevel.show();
1332  QComboBox *testWidget = topLevel.comboBox();
1333  testWidget->setEditable(true);
1334  testWidget->addItem("first item");
1335  testWidget->setCurrentIndex(0);
1336  testWidget->insertItem(0, "second item");
1337  QCOMPARE(testWidget->lineEdit()->text(), QString::fromLatin1("first item"));
1338 }
1339 
1340 void tst_QComboBox::textpixmapdata_data()
1341 {
1342  QTest::addColumn<QStringList>("text");
1343  QTest::addColumn<IconList>("icons");
1344  QTest::addColumn<VariantList>("variant");
1345 
1346  QStringList text;
1347  IconList icon;
1349  QString qtlogoPath = QFINDTESTDATA("qtlogo.png");
1350  QString qtlogoinvertedPath = QFINDTESTDATA("qtlogoinverted.png");
1351 
1352  {
1353  text.clear(); icon.clear(); variant.clear();
1354  text << "foo" << "bar";
1355  icon << QIcon() << QIcon();
1356  variant << QVariant() << QVariant();
1357  QTest::newRow("just text") << text << icon << variant;
1358  }
1359  {
1360  text.clear(); icon.clear(); variant.clear();
1361  text << QString() << QString();
1362  icon << QIcon(QPixmap(qtlogoPath)) << QIcon(QPixmap(qtlogoinvertedPath));
1363  variant << QVariant() << QVariant();
1364  QTest::newRow("just icons") << text << icon << variant;
1365  }
1366  {
1367  text.clear(); icon.clear(); variant.clear();
1368  text << QString() << QString();
1369  icon << QIcon() << QIcon();
1370  variant << 12 << "bingo";
1371  QTest::newRow("just user data") << text << icon << variant;
1372  }
1373  {
1374  text.clear(); icon.clear(); variant.clear();
1375  text << "foo" << "bar";
1376  icon << QIcon(QPixmap(qtlogoPath)) << QIcon(QPixmap(qtlogoinvertedPath));
1377  variant << 12 << "bingo";
1378  QTest::newRow("text, icons and user data") << text << icon << variant;
1379  }
1380 }
1381 
1382 void tst_QComboBox::textpixmapdata()
1383 {
1384  QFETCH(QStringList, text);
1385  QFETCH(IconList, icons);
1387 
1388  QVERIFY(text.count() == icons.count() && text.count() == variant.count());
1389 
1390  TestWidget topLevel;
1391  topLevel.show();
1393  QComboBox *testWidget = topLevel.comboBox();
1394  for (int i = 0; i<text.count(); ++i) {
1395  testWidget->insertItem(i, text.at(i));
1396  testWidget->setItemIcon(i, icons.at(i));
1397  testWidget->setItemData(i, variant.at(i), Qt::UserRole);
1398  }
1399 
1400  QCOMPARE(testWidget->count(), text.count());
1401 
1402  for (int i = 0; i<text.count(); ++i) {
1403  QIcon icon = testWidget->itemIcon(i);
1404  QCOMPARE(icon.cacheKey(), icons.at(i).cacheKey());
1405  QPixmap original = icons.at(i).pixmap(1024);
1406  QPixmap pixmap = icon.pixmap(1024);
1407  QCOMPARE(pixmap.toImage(), original.toImage());
1408  }
1409 
1410  for (int i = 0; i<text.count(); ++i) {
1411  QCOMPARE(testWidget->itemText(i), text.at(i));
1412  // ### we should test icons/pixmap as well, but I need to fix the api mismatch first
1413  QCOMPARE(testWidget->itemData(i, Qt::UserRole), variant.at(i));
1414  }
1415 }
1416 
1417 void tst_QComboBox::setCurrentIndex()
1418 {
1419  TestWidget topLevel;
1420  topLevel.show();
1422  QComboBox *testWidget = topLevel.comboBox();
1423  QCOMPARE(testWidget->count(), 0);
1424  testWidget->addItem("foo");
1425  testWidget->addItem("bar");
1426  QCOMPARE(testWidget->count(), 2);
1427 
1428  QCOMPARE(testWidget->currentIndex(), 0);
1429  testWidget->setCurrentIndex(0);
1430  QCOMPARE(testWidget->currentText(), QString("foo"));
1431 
1432  testWidget->setCurrentIndex(1);
1433  QCOMPARE(testWidget->currentText(), QString("bar"));
1434 
1435  testWidget->setCurrentIndex(0);
1436  QCOMPARE(testWidget->currentText(), QString("foo"));
1437 }
1438 
1439 void tst_QComboBox::setCurrentText_data()
1440 {
1441  QTest::addColumn<bool>("editable");
1442  QTest::newRow("editable") << true;
1443  QTest::newRow("not editable") << false;
1444 }
1445 
1446 void tst_QComboBox::setCurrentText()
1447 {
1448  QFETCH(bool, editable);
1449 
1450  TestWidget topLevel;
1451  topLevel.show();
1453  QComboBox *testWidget = topLevel.comboBox();
1454  QCOMPARE(testWidget->count(), 0);
1455  testWidget->addItems(QStringList() << "foo" << "bar");
1456  QCOMPARE(testWidget->count(), 2);
1457 
1458  testWidget->setEditable(editable);
1459  testWidget->setCurrentIndex(0);
1460  QCOMPARE(testWidget->currentIndex(), 0);
1461 
1462  // effect on currentText and currentIndex
1463  // currentIndex not changed if editable
1464  QCOMPARE(testWidget->currentText(), QString("foo"));
1465  testWidget->setCurrentText(QString("bar"));
1466  QCOMPARE(testWidget->currentText(), QString("bar"));
1467  if (editable)
1468  QCOMPARE(testWidget->currentIndex(), 0);
1469  else
1470  QCOMPARE(testWidget->currentIndex(), 1);
1471 
1472  testWidget->setCurrentText(QString("foo"));
1473  QCOMPARE(testWidget->currentIndex(), 0);
1474  QCOMPARE(testWidget->currentText(), QString("foo"));
1475 
1476  // effect of text not found in list
1477  testWidget->setCurrentText(QString("qt"));
1478  QCOMPARE(testWidget->currentIndex(), 0);
1479  if (editable)
1480  QCOMPARE(testWidget->currentText(), QString("qt"));
1481  else
1482  QCOMPARE(testWidget->currentText(), QString("foo"));
1483 
1484 #ifndef QT_NO_PROPERTIES
1485  // verify WRITE for currentText property
1486  testWidget->setCurrentIndex(0);
1487  const QByteArray n("currentText");
1488  QCOMPARE(testWidget->property(n).toString(), QString("foo"));
1489  testWidget->setProperty(n, QString("bar"));
1490  QCOMPARE(testWidget->property(n).toString(), QString("bar"));
1491 #endif
1492 }
1493 
1494 void tst_QComboBox::currentTextChanged_data()
1495 {
1496  QTest::addColumn<bool>("editable");
1497  QTest::newRow("editable") << true;
1498  QTest::newRow("not editable") << false;
1499 }
1500 
1501 void tst_QComboBox::currentTextChanged()
1502 {
1503  QFETCH(bool, editable);
1504 
1505  TestWidget topLevel;
1506  topLevel.show();
1508  QComboBox *testWidget = topLevel.comboBox();
1509  QCOMPARE(testWidget->count(), 0);
1510  testWidget->addItems(QStringList() << "foo" << "bar");
1511  QCOMPARE(testWidget->count(), 2);
1512 
1513  QSignalSpy spy(testWidget, SIGNAL(currentTextChanged(QString)));
1514 
1515  testWidget->setEditable(editable);
1516 
1517  // set text in list
1518  testWidget->setCurrentIndex(0);
1519  QCOMPARE(testWidget->currentIndex(), 0);
1520  spy.clear();
1521  testWidget->setCurrentText(QString("bar"));
1522  QCOMPARE(spy.count(), 1);
1523  QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("bar"));
1524 
1525  // set text not in list
1526  testWidget->setCurrentIndex(0);
1527  QCOMPARE(testWidget->currentIndex(), 0);
1528  spy.clear();
1529  testWidget->setCurrentText(QString("qt"));
1530  if (editable) {
1531  QCOMPARE(spy.count(), 1);
1532  QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("qt"));
1533  } else {
1534  QCOMPARE(spy.count(), 0);
1535  }
1536 
1537  // item changed
1538  testWidget->setCurrentIndex(0);
1539  QCOMPARE(testWidget->currentIndex(), 0);
1540  spy.clear();
1541  testWidget->setItemText(0, QString("ape"));
1542  QCOMPARE(spy.count(), 1);
1543  QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("ape"));
1544  // change it back
1545  spy.clear();
1546  testWidget->setItemText(0, QString("foo"));
1547  QCOMPARE(spy.count(), 1);
1548  QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("foo"));
1549 }
1550 
1551 void tst_QComboBox::editTextChanged()
1552 {
1553  TestWidget topLevel;
1554  topLevel.show();
1556  QComboBox *testWidget = topLevel.comboBox();
1557  QCOMPARE(testWidget->count(), 0);
1558  testWidget->addItem("foo");
1559  testWidget->addItem("bar");
1560  QCOMPARE(testWidget->count(), 2);
1561 
1562  // first we test non editable
1563  testWidget->setEditable(false);
1564  QCOMPARE(testWidget->isEditable(), false);
1565 
1566  QSignalSpy spy(testWidget, SIGNAL(editTextChanged(QString)));
1567 
1568  // no signal should be sent when current is set to the same
1569  QCOMPARE(testWidget->currentIndex(), 0);
1570  testWidget->setCurrentIndex(0);
1571  QCOMPARE(testWidget->currentIndex(), 0);
1572  QCOMPARE(spy.count(), 0);
1573 
1574  // no signal should be sent when changing to other index because we are not editable
1575  QCOMPARE(testWidget->currentIndex(), 0);
1576  testWidget->setCurrentIndex(1);
1577  QCOMPARE(testWidget->currentIndex(), 1);
1578  QCOMPARE(spy.count(), 0);
1579 
1580  // now set to editable and reset current index
1581  testWidget->setEditable(true);
1582  QCOMPARE(testWidget->isEditable(), true);
1583  testWidget->setCurrentIndex(0);
1584 
1585  // no signal should be sent when current is set to the same
1586  spy.clear();
1587  QCOMPARE(testWidget->currentIndex(), 0);
1588  testWidget->setCurrentIndex(0);
1589  QCOMPARE(testWidget->currentIndex(), 0);
1590  QCOMPARE(spy.count(), 0);
1591 
1592  // signal should be sent when changing to other index
1593  QCOMPARE(testWidget->currentIndex(), 0);
1594  testWidget->setCurrentIndex(1);
1595  QCOMPARE(testWidget->currentIndex(), 1);
1596  QCOMPARE(spy.count(), 1);
1597  QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("bar"));
1598 
1599 
1600  // insert some keys and notice they are all signaled
1601  spy.clear();
1602  QTest::keyClicks(testWidget, "bingo");
1603  QCOMPARE(spy.count(), 5);
1604  QCOMPARE(qvariant_cast<QString>(spy.at(4).at(0)), QString("barbingo"));
1605 }
1606 
1607 void tst_QComboBox::setModel()
1608 {
1609  QComboBox box;
1610  QCOMPARE(box.currentIndex(), -1);
1611  box.addItems((QStringList() << "foo" << "bar"));
1612  QCOMPARE(box.currentIndex(), 0);
1613  box.setCurrentIndex(1);
1614  QCOMPARE(box.currentIndex(), 1);
1615 
1616  // check that currentIndex is set to invalid
1617  QAbstractItemModel *oldModel = box.model();
1618  box.setModel(new QStandardItemModel(&box));
1619  QCOMPARE(box.currentIndex(), -1);
1620  QVERIFY(box.model() != oldModel);
1621 
1622  // check that currentIndex is set to first item
1623  oldModel = box.model();
1624  box.setModel(new QStandardItemModel(2,1, &box));
1625  QCOMPARE(box.currentIndex(), 0);
1626  QVERIFY(box.model() != oldModel);
1627 
1628  // set a new root index
1629  QModelIndex rootModelIndex;
1630  rootModelIndex = box.model()->index(0, 0);
1631  QVERIFY(rootModelIndex.isValid());
1632  box.setRootModelIndex(rootModelIndex);
1633  QCOMPARE(box.rootModelIndex(), rootModelIndex);
1634 
1635  // change the model, ensure that the root index gets reset
1636  oldModel = box.model();
1637  box.setModel(new QStandardItemModel(2, 1, &box));
1638  QCOMPARE(box.currentIndex(), 0);
1639  QVERIFY(box.model() != oldModel);
1640  QVERIFY(box.rootModelIndex() != rootModelIndex);
1641  QCOMPARE(box.rootModelIndex(), QModelIndex());
1642 
1643  // check that setting the very same model doesn't move the current item
1644  box.setCurrentIndex(1);
1645  QCOMPARE(box.currentIndex(), 1);
1646  box.setModel(box.model());
1647  QCOMPARE(box.currentIndex(), 1);
1648 
1649  // check that setting the very same model doesn't move the root index
1650  rootModelIndex = box.model()->index(0, 0);
1651  QVERIFY(rootModelIndex.isValid());
1652  box.setRootModelIndex(rootModelIndex);
1653  QCOMPARE(box.rootModelIndex(), rootModelIndex);
1654  box.setModel(box.model());
1655  QCOMPARE(box.rootModelIndex(), rootModelIndex);
1656 
1657  // check that setting the same model as the completer's doesn't crash
1659  box.setEditable(true);
1660  box.setCompleter(completer);
1661  auto *listModel = new QStringListModel({ "one", "two" }, completer);
1662  completer->setModel(listModel);
1663  QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted
1664  box.setModel(listModel);
1665  QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted
1666 }
1667 
1668 void tst_QComboBox::setCustomModelAndView()
1669 {
1670  // QTBUG-27597, ensure the correct text is returned when using custom view and a tree model.
1671  QComboBox combo;
1672  combo.setWindowTitle("QTBUG-27597, setCustomModelAndView");
1673  combo.setEditable(true);
1674  combo.setMinimumWidth(400);
1675  const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
1676  combo.move(availableGeometry.center() - QPoint(200, 20));
1677 
1678  QStandardItemModel *model = new QStandardItemModel(0, 1, &combo);
1679 
1681  item->appendRow(new QStandardItem(QStringLiteral("Item11")));
1682  model->appendRow(item);
1683 
1684  item = new QStandardItem(QStringLiteral("Item2"));
1685  model->appendRow(item);
1686  const QString subItem21Text = QStringLiteral("Item21");
1687  QStandardItem *subItem = new QStandardItem(subItem21Text);
1688  item->appendRow(subItem);
1689 
1690  QTreeView* view = new QTreeView(&combo);
1691  view->setHeaderHidden(true);
1692  view->setSelectionMode(QAbstractItemView::SingleSelection);
1693  view->setModel(model);
1694  view->expandAll();
1695  combo.setModel(model);
1696  combo.setView(view);
1697  combo.show();
1699  combo.showPopup();
1700  QTRY_VERIFY(combo.view()->isVisible());
1701  const QRect subItemRect = view->visualRect(model->indexFromItem(subItem));
1702  QWidget *window = view->window();
1703 
1704  // QComboBox sometimes ignores the mouse click event for doubleClickInterval
1705  // depending on which tests have been run previously. On arm this happens
1706  // more often than on x86. Search for maybeIgnoreMouseButtonRelease to see
1707  // why this happens.
1709 
1710  QTest::mouseClick(window->windowHandle(), Qt::LeftButton, {}, view->mapTo(window, subItemRect.center()));
1711  QTRY_COMPARE(combo.currentText(), subItem21Text);
1712 }
1713 
1714 void tst_QComboBox::modelDeleted()
1715 {
1716  QComboBox box;
1718  box.setModel(model);
1719  QCOMPARE(box.model(), static_cast<QAbstractItemModel *>(model));
1720  delete model;
1721  QVERIFY(box.model());
1722  QCOMPARE(box.findText("bubu"), -1);
1723 
1724  delete box.model();
1725  QVERIFY(box.model());
1726  delete box.model();
1727  QVERIFY(box.model());
1728 }
1729 
1730 void tst_QComboBox::setMaxCount()
1731 {
1733  items << "1" << "2" << "3" << "4" << "5";
1734 
1735  QComboBox box;
1736  box.addItems(items);
1737  QCOMPARE(box.count(), 5);
1738 
1739  box.setMaxCount(4);
1740  QCOMPARE(box.count(), 4);
1741  QCOMPARE(box.itemText(0), QString("1"));
1742  QCOMPARE(box.itemText(1), QString("2"));
1743  QCOMPARE(box.itemText(2), QString("3"));
1744  QCOMPARE(box.itemText(3), QString("4"));
1745 
1746  // appending should do nothing
1747  box.addItem("foo");
1748  QCOMPARE(box.count(), 4);
1749  QCOMPARE(box.findText("foo"), -1);
1750 
1751  // inserting one item at top should remove the last
1752  box.insertItem(0, "0");
1753  QCOMPARE(box.count(), 4);
1754  QCOMPARE(box.itemText(0), QString("0"));
1755  QCOMPARE(box.itemText(1), QString("1"));
1756  QCOMPARE(box.itemText(2), QString("2"));
1757  QCOMPARE(box.itemText(3), QString("3"));
1758 
1759  // insert 5 items in a box with maxCount 4
1760  box.insertItems(0, items);
1761  QCOMPARE(box.count(), 4);
1762  QCOMPARE(box.itemText(0), QString("1"));
1763  QCOMPARE(box.itemText(1), QString("2"));
1764  QCOMPARE(box.itemText(2), QString("3"));
1765  QCOMPARE(box.itemText(3), QString("4"));
1766 
1767  // insert 5 items at pos 2. Make sure only two get inserted
1768  QSignalSpy spy(box.model(), SIGNAL(rowsInserted(QModelIndex,int,int)));
1769  box.insertItems(2, items);
1770  QCOMPARE(spy.count(), 1);
1771  QCOMPARE(spy.at(0).at(1).toInt(), 2);
1772  QCOMPARE(spy.at(0).at(2).toInt(), 3);
1773 
1774  QCOMPARE(box.count(), 4);
1775  QCOMPARE(box.itemText(0), QString("1"));
1776  QCOMPARE(box.itemText(1), QString("2"));
1777  QCOMPARE(box.itemText(2), QString("1"));
1778  QCOMPARE(box.itemText(3), QString("2"));
1779 
1780  box.insertItems(0, QStringList());
1781  QCOMPARE(box.count(), 4);
1782 
1783  box.setMaxCount(0);
1784  QCOMPARE(box.count(), 0);
1785  box.addItem("foo");
1786  QCOMPARE(box.count(), 0);
1787  box.addItems(items);
1788  QCOMPARE(box.count(), 0);
1789 }
1790 
1791 void tst_QComboBox::convenienceViews()
1792 {
1793  // QListWidget
1794  QComboBox listCombo;
1795  QListWidget *list = new QListWidget();
1796  listCombo.setModel(list->model());
1797  listCombo.setView(list);
1798  // add items
1799  list->addItem("list0");
1800  listCombo.addItem("list1");
1801  QCOMPARE(listCombo.count(), 2);
1802  QCOMPARE(listCombo.itemText(0), QString("list0"));
1803  QCOMPARE(listCombo.itemText(1), QString("list1"));
1804 
1805  // QTreeWidget
1806  QComboBox treeCombo;
1807  QTreeWidget *tree = new QTreeWidget();
1808  tree->setColumnCount(1);
1809  tree->header()->hide();
1810  treeCombo.setModel(tree->model());
1811  treeCombo.setView(tree);
1812  // add items
1813  tree->addTopLevelItem(new QTreeWidgetItem(QStringList("tree0")));
1814  treeCombo.addItem("tree1");
1815  QCOMPARE(treeCombo.count(), 2);
1816  QCOMPARE(treeCombo.itemText(0), QString("tree0"));
1817  QCOMPARE(treeCombo.itemText(1), QString("tree1"));
1818 
1819  // QTableWidget
1820  QComboBox tableCombo;
1821  QTableWidget *table = new QTableWidget(0,1);
1822  table->verticalHeader()->hide();
1823  table->horizontalHeader()->hide();
1824  tableCombo.setModel(table->model());
1825  tableCombo.setView(table);
1826  // add items
1827  table->setRowCount(table->rowCount() + 1);
1828  table->setItem(0, table->rowCount() - 1, new QTableWidgetItem("table0"));
1829  tableCombo.addItem("table1");
1830  QCOMPARE(tableCombo.count(), 2);
1831  QCOMPARE(tableCombo.itemText(0), QString("table0"));
1832  QCOMPARE(tableCombo.itemText(1), QString("table1"));
1833 }
1834 
1835 class ReturnClass : public QWidget
1836 {
1837  Q_OBJECT
1838 public:
1839  ReturnClass(QWidget *parent = nullptr)
1840  : QWidget(parent), received(false)
1841  {
1842  QComboBox *box = new QComboBox(this);
1843  box->setEditable(true);
1844  edit = box->lineEdit();
1845  box->setGeometry(rect());
1846  }
1847 
1848  void keyPressEvent(QKeyEvent *e) override
1849  {
1850  received = (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter);
1851  }
1852 
1854 
1855  bool received;
1856 
1857 };
1858 
1859 
1860 
1861 void tst_QComboBox::ensureReturnIsIgnored()
1862 {
1863  ReturnClass r;
1864  r.move(200, 200);
1865  r.show();
1866 
1867  QTest::keyClick(r.edit, Qt::Key_Return);
1868  QVERIFY(r.received);
1869  r.received = false;
1870  QTest::keyClick(r.edit, Qt::Key_Enter);
1871  QVERIFY(r.received);
1872 }
1873 
1874 
1875 void tst_QComboBox::findText_data()
1876 {
1877  QTest::addColumn<QStringList>("items");
1878  QTest::addColumn<int>("matchflags");
1879  QTest::addColumn<QString>("search");
1880  QTest::addColumn<int>("result");
1881 
1882  QStringList list;
1883  list << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "one";
1884  QTest::newRow("CaseSensitive_1") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1885  << QString("Two") << 1;
1886  QTest::newRow("CaseSensitive_2") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1887  << QString("two") << -1;
1888  QTest::newRow("CaseSensitive_3") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1889  << QString("One") << 0;
1890  QTest::newRow("CaseSensitive_4") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
1891  << QString("one") << 6;
1892  QTest::newRow("CaseInsensitive_1") << list << (int)(Qt::MatchExactly) << QString("Two") << 1;
1893  QTest::newRow("CaseInsensitive_2") << list << (int)(Qt::MatchExactly) << QString("two") << -1;
1894  QTest::newRow("CaseInsensitive_3") << list << (int)(Qt::MatchExactly) << QString("One") << 0;
1895  QTest::newRow("CaseInsensitive_4") << list << (int)(Qt::MatchExactly) << QString("one") << 6;
1896 }
1897 void tst_QComboBox::findText()
1898 {
1900  QFETCH(int, matchflags);
1901  QFETCH(QString, search);
1902  QFETCH(int, result);
1903 
1904  TestWidget topLevel;
1905  topLevel.show();
1907  QComboBox *testWidget = topLevel.comboBox();
1908  testWidget->clear();
1909  testWidget->addItems(items);
1910 
1911  QCOMPARE(testWidget->findText(search, (Qt::MatchFlags)matchflags), result);
1912 }
1913 
1917 
1918 void tst_QComboBox::flaggedItems_data()
1919 {
1920  QTest::addColumn<QStringList>("itemList");
1921  QTest::addColumn<IntList>("deselectFlagList");
1922  QTest::addColumn<IntList>("disableFlagList");
1923  QTest::addColumn<KeyList>("keyMovementList");
1924  QTest::addColumn<bool>("editable");
1925  QTest::addColumn<int>("expectedIndex");
1926 
1927  for (int editable=0;editable<2;editable++) {
1928  QString testCase = editable ? "editable:" : "non-editable:";
1929  QStringList itemList;
1930  itemList << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "Seven" << "Eight";
1931  IntList deselectFlagList;
1932  IntList disableFlagList;
1933  KeyList keyMovementList;
1934 
1935  keyMovementList << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down;
1936  QTest::newRow(testCase.toLatin1() + "normal") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1937 
1938  deselectFlagList.clear();
1939  disableFlagList.clear();
1940  deselectFlagList << 1 << 3;
1941  QTest::newRow(testCase.toLatin1() + "non-selectable") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1942 
1943  deselectFlagList.clear();
1944  disableFlagList.clear();
1945  disableFlagList << 2;
1946  QTest::newRow(testCase.toLatin1() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 5;
1947 
1948  deselectFlagList.clear();
1949  disableFlagList.clear();
1950  deselectFlagList << 1 << 3;
1951  disableFlagList << 2 << 3;
1952  QTest::newRow(testCase.toLatin1() + "mixed") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 6;
1953  deselectFlagList.clear();
1954  disableFlagList.clear();
1955  disableFlagList << 0 << 1 << 2 << 3 << 4 << 5 << 6;
1956  QTest::newRow(testCase.toLatin1() + "nearly-empty") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
1957 
1958  deselectFlagList.clear();
1959  disableFlagList.clear();
1960  disableFlagList << 0 << 1 << 2 << 3 << 5 << 6 << 7;
1961  keyMovementList.clear();
1962  QTest::newRow(testCase.toLatin1() + "only one enabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1963 
1964  if (!editable) {
1965  deselectFlagList.clear();
1966  disableFlagList.clear();
1967  keyMovementList.clear();
1968  disableFlagList << 0 << 2 << 3;
1969  keyMovementList << Qt::Key_Down << Qt::Key_Home;
1970  QTest::newRow(testCase.toLatin1() + "home-disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 1;
1971 
1972  keyMovementList.clear();
1973  keyMovementList << Qt::Key_End;
1974  QTest::newRow(testCase.toLatin1() + "end-key") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
1975 
1976  disableFlagList.clear();
1977  disableFlagList << 1 ;
1978  keyMovementList << Qt::Key_T;
1979  QTest::newRow(testCase.toLatin1() + "keyboard-search") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1980 
1981  itemList << "nine" << "ten";
1982  keyMovementList << Qt::Key_T;
1983  QTest::newRow(testCase.toLatin1() + "search same start letter") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1984 
1985  keyMovementList.clear();
1986  keyMovementList << Qt::Key_T << Qt::Key_H;
1987  QTest::newRow(testCase.toLatin1() + "keyboard search item") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
1988 
1989  disableFlagList.clear();
1990  disableFlagList << 1 << 3 << 5 << 7 << 9;
1991  keyMovementList.clear();
1993  QTest::newRow(testCase.toLatin1() + "all key combinations") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
1994  } else {
1995  deselectFlagList.clear();
1996  disableFlagList.clear();
1997  disableFlagList << 1;
1998  keyMovementList.clear();
1999  keyMovementList << Qt::Key_T << Qt::Key_Enter;
2000  QTest::newRow(testCase.toLatin1() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
2001  QTest::newRow(testCase.toLatin1() + "broken autocompletion") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
2002  }
2003  }
2004 }
2005 
2006 void tst_QComboBox::flaggedItems()
2007 {
2009  QSKIP("Wayland: This fails. Figure out why.");
2010 
2011  QFETCH(QStringList, itemList);
2012  QFETCH(IntList, deselectFlagList);
2013  QFETCH(IntList, disableFlagList);
2014  QFETCH(KeyList, keyMovementList);
2015  QFETCH(bool, editable);
2016  QFETCH(int, expectedIndex);
2017 
2018  QComboBox comboBox;
2019  setFrameless(&comboBox);
2020  QListWidget listWidget;
2021  listWidget.addItems(itemList);
2022 
2023  comboBox.setEditable(editable);
2024  foreach (int index, deselectFlagList)
2025  listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsSelectable);
2026 
2027  foreach (int index, disableFlagList)
2028  listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
2029 
2030  comboBox.setModel(listWidget.model());
2031  comboBox.setView(&listWidget);
2032  comboBox.move(200, 200);
2033  comboBox.show();
2034  QApplication::setActiveWindow(&comboBox);
2035  comboBox.activateWindow();
2036  comboBox.setFocus();
2038  QTRY_VERIFY(comboBox.isVisible());
2039  QTRY_VERIFY(comboBox.hasFocus());
2040 
2041  if (editable)
2042  comboBox.lineEdit()->selectAll();
2043 
2044  for (int i = 0; i < keyMovementList.count(); ++i) {
2045  Qt::Key key = keyMovementList[i];
2046  QTest::keyClick(&comboBox, key);
2047  }
2048 
2049  QCOMPARE(comboBox.currentIndex() , expectedIndex);
2050 }
2051 
2052 void tst_QComboBox::pixmapIcon()
2053 {
2054  QComboBox box;
2056 
2057  QPixmap pix(10, 10);
2058  pix.fill(Qt::red);
2059  model->setData(model->index(0, 0), "Element 1");
2061 
2062  QIcon icon(pix);
2063  model->setData(model->index(1, 0), "Element 2");
2065 
2066  box.setModel(model);
2067 
2068  QCOMPARE( box.itemIcon(0).isNull(), false );
2069  QCOMPARE( box.itemIcon(1).isNull(), false );
2070 }
2071 
2072 #if QT_CONFIG(wheelevent)
2073 // defined to be 120 by the wheel mouse vendors according to the docs
2074 #define WHEEL_DELTA 120
2075 
2076 void tst_QComboBox::mouseWheel_data()
2077 {
2078  QTest::addColumn<IntList>("disabledItems");
2079  QTest::addColumn<int>("startIndex");
2080  QTest::addColumn<int>("wheelDirection");
2081  QTest::addColumn<int>("expectedIndex");
2082 
2083  IntList disabled;
2084  disabled << 0 << 1 << 2 << 4;
2085  int start = 3;
2086  int wheel = 1;
2087  int expected = 3;
2088  QTest::newRow("upper locked") << disabled << start << wheel << expected;
2089 
2090  wheel = -1;
2091  const bool allowsWheelScroll = QApplication::style()->styleHint(QStyle::SH_ComboBox_AllowWheelScrolling);
2092  // on OS X & iOS mouse wheel shall have no effect on combo box
2093  if (!allowsWheelScroll)
2094  expected = start;
2095  else // on other OSes we should jump to next enabled item (no. 5)
2096  expected = 5;
2097 
2098  QTest::newRow("jump over") << disabled << start << wheel << expected;
2099 
2100  disabled.clear();
2101  disabled << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9;
2102  start = 0;
2103  wheel = -1;
2104  expected = 0;
2105  QTest::newRow("single Item enabled") << disabled << start << wheel << expected;
2106 }
2107 
2108 void tst_QComboBox::mouseWheel()
2109 {
2110  QFETCH(IntList, disabledItems);
2111  QFETCH(int, startIndex);
2112  QFETCH(int, wheelDirection);
2113  QFETCH(int, expectedIndex);
2114 
2115  QCoreApplication *applicationInstance = QCoreApplication::instance();
2116  QVERIFY(applicationInstance != 0);
2117 
2118  QComboBox box;
2119  QStringList list;
2120  list << "one" << "two" << "three" << "four" << "five" << "six" << "seven" << "eight" << "nine" << "ten";
2121 
2122  QListWidget listWidget;
2123  listWidget.addItems(list);
2124 
2125  foreach (int index, disabledItems)
2126  listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
2127 
2128  box.setModel(listWidget.model());
2129  box.setView(&listWidget);
2130  for (int i=0; i < 2; ++i) {
2131  box.setEditable(i==0?false:true);
2132  box.setCurrentIndex(startIndex);
2133 
2134  const QPoint wheelPoint = box.rect().bottomRight();
2135  QWheelEvent event(wheelPoint, box.mapToGlobal(wheelPoint), QPoint(), QPoint(0, WHEEL_DELTA * wheelDirection),
2137  QVERIFY(applicationInstance->sendEvent(&box,&event));
2138 
2139  QCOMPARE(box.currentIndex(), expectedIndex);
2140  }
2141 }
2142 
2143 void tst_QComboBox::popupWheelHandling()
2144 {
2145  // QTBUG-40656, QTBUG-42731 combo and other popups should not be affected by wheel events.
2147  scrollArea.move(300, 300);
2148  QWidget *widget = new QWidget;
2149  scrollArea.setWidget(widget);
2150  QVBoxLayout *layout = new QVBoxLayout(widget);
2151  layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
2152  layout->addSpacing(100);
2153  QComboBox *comboBox = new QComboBox;
2154  comboBox->addItems(QStringList() << QStringLiteral("Won") << QStringLiteral("Too")
2155  << QStringLiteral("3") << QStringLiteral("fore"));
2156  layout->addWidget(comboBox);
2157  layout->addSpacing(100);
2158  const QPoint sizeP(scrollArea.width(), scrollArea.height());
2159  scrollArea.move(QGuiApplication::primaryScreen()->availableGeometry().center() - sizeP / 2);
2160  scrollArea.show();
2162  comboBox->showPopup();
2163  QTRY_VERIFY(comboBox->view() && comboBox->view()->isVisible());
2164  const QPoint popupPos = comboBox->view()->pos();
2165  const QPoint wheelPoint(10, 10);
2166  QWheelEvent event(wheelPoint, scrollArea.mapToGlobal(wheelPoint), QPoint(), QPoint(0, WHEEL_DELTA),
2170  QVERIFY(comboBox->view()->isVisible());
2171  QCOMPARE(comboBox->view()->pos(), popupPos);
2172 }
2173 #endif // QT_CONFIG(wheelevent)
2174 
2175 void tst_QComboBox::layoutDirection()
2176 {
2177  QComboBox box;
2180 
2181  // RTL
2182  box.setLayoutDirection(Qt::RightToLeft);
2186 
2187  QCOMPARE(box.view()->layoutDirection(), dir);
2188  box.setEditable(true);
2189  QCOMPARE(box.lineEdit()->layoutDirection(), dir);
2190  lineEdit = new QLineEdit;
2191  QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
2192  box.setLineEdit(lineEdit);
2194 
2195  // LTR
2196  box.setLayoutDirection(Qt::LeftToRight);
2197  qApp->setLayoutDirection(Qt::RightToLeft);
2198 
2201 
2202  QCOMPARE(box.view()->layoutDirection(), dir);
2203  box.setEditable(true);
2204  QCOMPARE(box.lineEdit()->layoutDirection(), dir);
2205  lineEdit = new QLineEdit;
2206  QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
2207  box.setLineEdit(lineEdit);
2209 
2210 }
2211 
2212 void tst_QComboBox::itemListPosition()
2213 {
2214  //tests that the list is not out of the screen boundaries
2215 
2216  //put the QApplication layout back
2218 
2219  //we test QFontComboBox because it has the specific behaviour to set a fixed size
2220  //to the list view
2221  QWidget topLevel;
2222  QHBoxLayout *layout = new QHBoxLayout(&topLevel);
2223 
2224  QFontComboBox combo(&topLevel);
2225 
2226  layout->addWidget(&combo);
2227 
2228  bool useFullScreenForPopupMenu = false;
2230  useFullScreenForPopupMenu = theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool();
2231  const QRect screen = useFullScreenForPopupMenu ?
2232  combo.screen()->geometry() :
2233  combo.screen()->availableGeometry();
2234 
2235  topLevel.move(screen.width() - topLevel.sizeHint().width() - 10, 0); //puts the combo to the top-right corner
2236 
2237  topLevel.showNormal();
2238 
2239  //wait because the window manager can move the window if there is a right panel
2241  combo.showPopup();
2242  QTRY_VERIFY(combo.view());
2243  QTRY_VERIFY(combo.view()->isVisible());
2244  QVERIFY( combo.view()->window()->x() + combo.view()->window()->width() <= screen.x() + screen.width() );
2245 }
2246 
2247 void tst_QComboBox::separatorItem_data()
2248 {
2249  QTest::addColumn<QStringList>("items");
2250  QTest::addColumn<IntList>("separators");
2251 
2252  QTest::newRow("test") << (QStringList() << "one" << "two" << "three" << "other...")
2253  << (IntList() << 4);
2254 }
2255 
2256 void tst_QComboBox::separatorItem()
2257 {
2259  QFETCH(IntList, separators);
2260 
2261  QComboBox box;
2262  box.addItems(items);
2263  foreach(int index, separators)
2264  box.insertSeparator(index);
2265  QCOMPARE(box.count(), (items.count() + separators.count()));
2266  for (int i = 0, s = 0; i < box.count(); ++i) {
2267  if (i == separators.at(s)) {
2268  QCOMPARE(box.itemText(i), QString());
2269  ++s;
2270  } else {
2271  QCOMPARE(box.itemText(i), items.at(i - s));
2272  }
2273  }
2274 }
2275 
2276 // This test requires the Fusionstyle
2277 #ifndef QT_NO_STYLE_FUSION
2278 void tst_QComboBox::task190351_layout()
2279 {
2280  const QString oldStyle = QApplication::style()->objectName();
2282 
2283  QComboBox listCombo;
2284  listCombo.move(200, 200);
2285  setFrameless(&listCombo);
2286  QListWidget *list = new QListWidget();
2287  listCombo.setModel(list->model());
2288  listCombo.setView(list);
2289  for(int i = 1; i < 150; i++)
2290  list->addItem(QLatin1String("list") + QString::number(i));
2291 
2292  listCombo.show();
2294  QTRY_VERIFY(listCombo.isVisible());
2295  listCombo.setCurrentIndex(70);
2296  listCombo.showPopup();
2297  QTRY_VERIFY(listCombo.view());
2298  QVERIFY(QTest::qWaitForWindowExposed(listCombo.view()));
2299  QTRY_VERIFY(listCombo.view()->isVisible());
2301 
2302 #ifdef QT_BUILD_INTERNAL
2303  QFrame *container = listCombo.findChild<QComboBoxPrivateContainer *>();
2304  QVERIFY(container);
2305  QCOMPARE(static_cast<QAbstractItemView *>(list), container->findChild<QAbstractItemView *>());
2306  QWidget *top = container->findChild<QComboBoxPrivateScroller *>();
2307  QVERIFY(top);
2308  QVERIFY(top->isVisible());
2309  QCOMPARE(top->mapToGlobal(QPoint(0, top->height())).y(), list->mapToGlobal(QPoint()).y());
2310 #endif
2311 
2312  QApplication::setStyle(oldStyle);
2313 }
2314 #endif
2315 
2316 class task166349_ComboBox : public QComboBox
2317 {
2318  Q_OBJECT
2319 public:
2320  task166349_ComboBox(QWidget *parent = nullptr) : QComboBox(parent)
2321  {
2322  QStringList list;
2323  list << "one" << "two";
2324  connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
2325  addItems(list);
2326  }
2327 public slots:
2329  {
2330  setEditable(index % 2 == 1);
2331  }
2332 };
2333 
2334 void tst_QComboBox::task166349_setEditableOnReturn()
2335 {
2336  task166349_ComboBox comboBox;
2337  QTest::keyClick(&comboBox, Qt::Key_Down);
2338  QTest::keyClick(&comboBox, Qt::Key_1);
2339  QTest::keyClick(&comboBox, Qt::Key_Enter);
2340  QCOMPARE(QLatin1String("two1"), comboBox.itemText(comboBox.count() - 1));
2341 }
2342 
2343 // This test requires the Fusion style.
2344 #ifndef QT_NO_STYLE_FUSION
2345 void tst_QComboBox::task191329_size()
2346 {
2347  const QString oldStyle = QApplication::style()->objectName();
2349 
2350 
2351  QComboBox tableCombo;
2352  setFrameless(&tableCombo);
2353  tableCombo.move(200, 200);
2354  int rows;
2355  if (QApplication::primaryScreen()->geometry().height() < 480)
2356  rows = 8;
2357  else
2358  rows = 15;
2359 
2360  QStandardItemModel model(rows, 2);
2361  for (int row = 0; row < model.rowCount(); ++row) {
2362  const QString rowS = QLatin1String("row ") + QString::number(row);
2363  for (int column = 0; column < model.columnCount(); ++column) {
2364  const QString text = rowS + QLatin1String(", column ") + QString::number(column);
2365  model.setItem(row, column, new QStandardItem(text));
2366  }
2367  }
2368  QTableView *table = new QTableView();
2369  table->verticalHeader()->hide();
2370  table->horizontalHeader()->hide();
2371  tableCombo.setView(table);
2372  tableCombo.setModel(&model);
2373 
2374  tableCombo.show();
2375  QTRY_VERIFY(tableCombo.isVisible());
2376  tableCombo.showPopup();
2377  QTRY_VERIFY(tableCombo.view());
2378  QTRY_VERIFY(tableCombo.view()->isVisible());
2379 
2380 #ifdef QT_BUILD_INTERNAL
2381  QFrame *container = tableCombo.findChild<QComboBoxPrivateContainer *>();
2382  QVERIFY(container);
2383  QCOMPARE(static_cast<QAbstractItemView *>(table), container->findChild<QAbstractItemView *>());
2384  foreach (QWidget *button, container->findChildren<QComboBoxPrivateScroller *>()) {
2385  //the popup should be large enough to contains everithing so the top and left button are hidden
2386  QVERIFY(!button->isVisible());
2387  }
2388 #endif
2389 
2390  QApplication::setStyle(oldStyle);
2391 }
2392 #endif
2393 
2394 void tst_QComboBox::task190205_setModelAdjustToContents()
2395 {
2396  QStringList initialContent;
2397  QStringList finalContent;
2398  initialContent << "foo" << "bar";
2399  finalContent << "bar" << "foooooooobar";
2400 
2401  QComboBox box;
2402  setFrameless(&box);
2403  box.move(100, 100);
2404  box.setSizeAdjustPolicy(QComboBox::AdjustToContents);
2405  box.addItems(initialContent);
2406  box.showNormal();
2407 
2408  //wait needed in order to get the combo initial size
2409  QTRY_VERIFY(box.isVisible());
2410 
2411  box.setModel(new QStringListModel(finalContent));
2412 
2413  QComboBox correctBox;
2414  setFrameless(&correctBox);
2415  correctBox.move(400, 100);
2416 
2417  correctBox.addItems(finalContent);
2418  correctBox.showNormal();
2419 
2421  QVERIFY(QTest::qWaitForWindowExposed(&correctBox));
2422 
2423  // box should be resized to the same size as correctBox
2424  QTRY_COMPARE(box.size(), correctBox.size());
2425 }
2426 
2427 void tst_QComboBox::task248169_popupWithMinimalSize()
2428 {
2429  QStringList initialContent;
2430  initialContent << "foo" << "bar" << "foobar";
2431 
2432  QComboBox comboBox;
2433  comboBox.addItems(initialContent);
2434  QRect desktopSize = QGuiApplication::primaryScreen()->availableGeometry();
2435  comboBox.view()->setMinimumWidth(desktopSize.width() / 2);
2436 
2437  comboBox.setGeometry(desktopSize.width() - (desktopSize.width() / 4), (desktopSize.width() / 4), (desktopSize.width() / 2), (desktopSize.width() / 4));
2438 
2439  comboBox.showNormal();
2441  QTRY_VERIFY(comboBox.isVisible());
2442  comboBox.showPopup();
2443  QTRY_VERIFY(comboBox.view());
2444  QVERIFY(QTest::qWaitForWindowExposed(comboBox.view()));
2445  QTRY_VERIFY(comboBox.view()->isVisible());
2446 
2447 #if defined QT_BUILD_INTERNAL
2448  QFrame *container = comboBox.findChild<QComboBoxPrivateContainer *>();
2449  QVERIFY(container);
2450  QTRY_VERIFY(container->screen()->geometry().contains(container->geometry()));
2451 #endif
2452 }
2453 
2454 void tst_QComboBox::task247863_keyBoardSelection()
2455 {
2456  QComboBox combo;
2457  setFrameless(&combo);
2458  combo.move(200, 200);
2459  combo.setEditable(false);
2460  combo.addItem( QLatin1String("111"));
2461  combo.addItem( QLatin1String("222"));
2462  combo.show();
2464  QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
2465 
2467  qApp->setEffectEnabled(Qt::UI_AnimateCombo, false);
2468  QTest::keyClick(&combo, Qt::Key_Space);
2469  qApp->setEffectEnabled(Qt::UI_AnimateCombo, true);
2470  QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down);
2471  QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter);
2472  QCOMPARE(combo.currentText(), QLatin1String("222"));
2473  QCOMPARE(spy.count(), 1);
2474 }
2475 
2476 void tst_QComboBox::task220195_keyBoardSelection2()
2477 {
2479  QSKIP("Wayland: This fails. Figure out why.");
2480 
2481  QComboBox combo;
2482  setFrameless(&combo);
2483  combo.move(200, 200);
2484  combo.setEditable(false);
2485  combo.addItem( QLatin1String("foo1"));
2486  combo.addItem( QLatin1String("foo2"));
2487  combo.addItem( QLatin1String("foo3"));
2488  combo.show();
2491 
2492  combo.setCurrentIndex(-1);
2493  QVERIFY(combo.currentText().isNull());
2494 
2495  QTest::keyClick(&combo, 'f');
2496  QCOMPARE(combo.currentText(), QLatin1String("foo1"));
2498  QTest::keyClick(&combo, 'f');
2499  QCOMPARE(combo.currentText(), QLatin1String("foo2"));
2501  QTest::keyClick(&combo, 'f');
2502  QCOMPARE(combo.currentText(), QLatin1String("foo3"));
2504  QTest::keyClick(&combo, 'f');
2505  QCOMPARE(combo.currentText(), QLatin1String("foo1"));
2507 
2508  combo.setCurrentIndex(1);
2509  QCOMPARE(combo.currentText(), QLatin1String("foo2"));
2510  QTest::keyClick(&combo, 'f');
2511  QCOMPARE(combo.currentText(), QLatin1String("foo3"));
2512 }
2513 
2514 
2515 void tst_QComboBox::setModelColumn()
2516 {
2518  model.setItem(0,0, new QStandardItem("0"));
2519  model.setItem(1,0, new QStandardItem("1"));
2520  model.setItem(2,0, new QStandardItem("2"));
2521  model.setItem(3,0, new QStandardItem("3"));
2522  model.setItem(4,0, new QStandardItem("4"));
2523  model.setItem(0,1, new QStandardItem("zero"));
2524  model.setItem(1,1, new QStandardItem("un"));
2525  model.setItem(2,1, new QStandardItem("deux"));
2526  model.setItem(3,1, new QStandardItem("trois"));
2527  model.setItem(4,1, new QStandardItem("quatre"));
2528  model.setItem(0,2, new QStandardItem("a"));
2529  model.setItem(1,2, new QStandardItem("b"));
2530  model.setItem(2,2, new QStandardItem("c"));
2531  model.setItem(3,2, new QStandardItem("d"));
2532  model.setItem(4,2, new QStandardItem("e"));
2533 
2534  QComboBox box;
2535  box.setModel(&model);
2536  QCOMPARE(box.currentText(), QString("0"));
2537  box.setModelColumn(1);
2538  QCOMPARE(box.currentText(), QString("zero"));
2539 }
2540 
2541 void tst_QComboBox::noScrollbar_data()
2542 {
2543  QTest::addColumn<QString>("stylesheet");
2544 
2545  QTest::newRow("normal") << QString();
2546  QTest::newRow("border") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue;}");
2547  QTest::newRow("margin") << QString::fromLatin1("QAbstractItemView { margin: 12px 15px 13px 10px; }");
2548  QTest::newRow("padding") << QString::fromLatin1("QAbstractItemView { padding: 12px 15px 13px 10px;}");
2549  QTest::newRow("everything") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue; "
2550  " padding: 12px 15px 13px 10px; margin: 12px 15px 13px 10px; }");
2551  QTest::newRow("everything and more") << QString::fromLatin1("QAbstractItemView { border: 1px 3px 5px 1px solid blue; "
2552  " padding: 2px 5px 3px 1px; margin: 2px 5px 3px 1px; } "
2553  " QAbstractItemView::item { border: 2px solid green; "
2554  " padding: 1px 1px 2px 2px; margin: 1px; } " );
2555 }
2556 
2557 void tst_QComboBox::noScrollbar()
2558 {
2559  QStringList initialContent;
2560  initialContent << "foo" << "bar" << "foobar" << "moo";
2561  QFETCH(QString, stylesheet);
2562  QString oldCss = qApp->styleSheet();
2563  qApp->setStyleSheet(stylesheet);
2564 
2565  {
2566  QWidget topLevel;
2567  QComboBox comboBox(&topLevel);
2568  comboBox.addItems(initialContent);
2569  topLevel.move(200, 200);
2570  topLevel.show();
2571  comboBox.resize(200, comboBox.height());
2572  QTRY_VERIFY(comboBox.isVisible());
2573  comboBox.showPopup();
2574  QTRY_VERIFY(comboBox.view());
2575  QTRY_VERIFY(comboBox.view()->isVisible());
2576 
2577  QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
2578  QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
2579  }
2580 
2581  {
2582  QTableWidget *table = new QTableWidget(2,2);
2583  QComboBox comboBox;
2584  comboBox.setModel(table->model());
2585  comboBox.setView(table);
2586  comboBox.move(200, 200);
2587  comboBox.show();
2588  QTRY_VERIFY(comboBox.isVisible());
2589  comboBox.resize(200, comboBox.height());
2590  comboBox.showPopup();
2591  QTRY_VERIFY(comboBox.view());
2592  QTRY_VERIFY(comboBox.view()->isVisible());
2593 
2594  QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
2595  QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
2596  }
2597 
2598  qApp->setStyleSheet(oldCss);
2599 }
2600 
2601 void tst_QComboBox::setItemDelegate()
2602 {
2603  QComboBox comboBox;
2604  QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
2605  comboBox.setItemDelegate(itemDelegate);
2606  // the cast is a workaround for the XLC and Metrowerks compilers
2607  QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2608 }
2609 
2610 void tst_QComboBox::task253944_itemDelegateIsReset()
2611 {
2612  QComboBox comboBox;
2613  QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
2614  comboBox.setItemDelegate(itemDelegate);
2615 
2616  // the casts are workarounds for the XLC and Metrowerks compilers
2617 
2618  comboBox.setEditable(true);
2619  QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2620 
2621  comboBox.setStyleSheet("QComboBox { border: 1px solid gray; }");
2622  QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
2623 }
2624 
2625 
2626 void tst_QComboBox::subControlRectsWithOffset_data()
2627 {
2628  QTest::addColumn<bool>("editable");
2629 
2630  QTest::newRow("editable = true") << true;
2631  QTest::newRow("editable = false") << false;
2632 }
2633 
2634 void tst_QComboBox::subControlRectsWithOffset()
2635 {
2636  // The sub control rect relative position should not depends
2637  // on the position of the combobox
2638 
2639  class FriendlyCombo : public QComboBox {
2640  public:
2641  void styleOption(QStyleOptionComboBox *optCombo) {
2642  initStyleOption(optCombo);
2643  }
2644  } combo;
2645  QStyleOptionComboBox optCombo;
2646  combo.styleOption(&optCombo);
2647 
2648 
2649  const QRect rectAtOrigin(0, 0, 80, 30);
2650  const QPoint offset(25, 50);
2651  const QRect rectWithOffset = rectAtOrigin.translated(offset);
2652 
2653  QStyle *style = combo.style();
2654 
2655  QFETCH(bool, editable);
2656  optCombo.editable = editable;
2657 
2658  optCombo.rect = rectAtOrigin;
2659  QRect editFieldRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
2660  QRect arrowRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
2661  QRect listboxRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
2662 
2663  optCombo.rect = rectWithOffset;
2664  QRect editFieldRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
2665  QRect arrowRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
2666  QRect listboxRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
2667 
2668  QCOMPARE(editFieldRect, editFieldRectWithOffset.translated(-offset));
2669  QCOMPARE(arrowRect, arrowRectWithOffset.translated(-offset));
2670  QCOMPARE(listboxRect, listboxRectWithOffset.translated(-offset));
2671 
2672 }
2673 
2674 // This test depends on Windows style.
2675 #ifndef QT_NO_STYLE_WINDOWS
2676 void tst_QComboBox::task260974_menuItemRectangleForComboBoxPopup()
2677 {
2678  class TestStyle: public QProxyStyle
2679  {
2680  public:
2681  TestStyle() : QProxyStyle(QStyleFactory::create("windows")) { }
2682 
2683  int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *ret) const override
2684  {
2685  if (hint == SH_ComboBox_Popup) return 1;
2686  else return QCommonStyle::styleHint(hint, option, widget, ret);
2687  }
2688 
2689  void drawControl(ControlElement element, const QStyleOption *option, QPainter *, const QWidget *) const override
2690  {
2691  if (element == CE_MenuItem)
2692  discoveredRect = option->rect;
2693  }
2694 
2695  mutable QRect discoveredRect;
2696  } style;
2697 
2698 
2699  {
2700  QComboBox comboBox;
2701  comboBox.setStyle(&style);
2702  comboBox.addItem("Item 1");
2703  comboBox.move(200, 200);
2704 
2705  comboBox.show();
2706  QTRY_VERIFY(comboBox.isVisible());
2707  comboBox.showPopup();
2708  QTRY_VERIFY(comboBox.view());
2709  QTRY_VERIFY(comboBox.view()->isVisible());
2710 
2711  QTRY_VERIFY(style.discoveredRect.width() <= comboBox.width());
2712  }
2713 }
2714 #endif
2715 
2716 void tst_QComboBox::removeItem()
2717 {
2718  QComboBox cb;
2719  cb.removeItem(-1);
2720  cb.removeItem(1);
2721  cb.removeItem(0);
2722  QCOMPARE(cb.count(), 0);
2723 
2724  cb.addItem("foo");
2725  cb.removeItem(-1);
2726  QCOMPARE(cb.count(), 1);
2727  cb.removeItem(1);
2728  QCOMPARE(cb.count(), 1);
2729  cb.removeItem(0);
2730  QCOMPARE(cb.count(), 0);
2731 }
2732 
2733 void tst_QComboBox::resetModel()
2734 {
2735  class StringListModel : public QStringListModel
2736  {
2737  public:
2739  void reset()
2740  {
2743  }
2744  };
2745  QComboBox cb;
2746  StringListModel model({"1", "2"});
2748  QCOMPARE(spy.count(), 0);
2749  QCOMPARE(cb.currentIndex(), -1); //no selection
2750 
2751  cb.setModel(&model);
2752 
2753  QCOMPARE(spy.count(), 1);
2754  QCOMPARE(cb.currentIndex(), 0); //first item selected
2755 
2756  model.reset();
2757  QCOMPARE(spy.count(), 2);
2758  QCOMPARE(cb.currentIndex(), 0); //first item selected
2759 
2760 }
2761 
2762 void tst_QComboBox::keyBoardNavigationWithMouse()
2763 {
2765  QSKIP("Wayland: This fails. Figure out why.");
2766 
2767  QComboBox combo;
2768  combo.setEditable(false);
2769  setFrameless(&combo);
2770  for (int i = 0; i < 200; i++)
2771  combo.addItem(QString::number(i));
2772 
2773  combo.move(200, 200);
2774  combo.showNormal();
2777 
2778  QCOMPARE(combo.currentText(), QLatin1String("0"));
2779 
2780  combo.setFocus();
2781  QTRY_VERIFY(combo.hasFocus());
2782 
2783  QTest::keyClick(combo.lineEdit(), Qt::Key_Space);
2784  QTRY_VERIFY(combo.view());
2785  QTRY_VERIFY(combo.view()->isVisible());
2786 
2787  QCOMPARE(combo.currentText(), QLatin1String("0"));
2788 
2789  QTest::mouseMove(&combo, combo.rect().center());
2790 
2791 #define GET_SELECTION(SEL) \
2792  QCOMPARE(combo.view()->selectionModel()->selection().count(), 1); \
2793  QCOMPARE(combo.view()->selectionModel()->selection().indexes().count(), 1); \
2794  SEL = combo.view()->selectionModel()->selection().indexes().first().row()
2795 
2796  int selection;
2797  GET_SELECTION(selection); // get initial selection
2798 
2799  const int final = 40;
2800  for (int i = selection + 1; i <= final; i++)
2801  {
2802  QTest::keyClick(combo.view(), Qt::Key_Down);
2804  QCOMPARE(selection, i);
2805  }
2806 
2807  QTest::keyClick(combo.view(), Qt::Key_Enter);
2808  QTRY_COMPARE(combo.currentText(), QString::number(final));
2809 #undef GET_SELECTION
2810 }
2811 
2812 void tst_QComboBox::task_QTBUG_1071_changingFocusEmitsActivated()
2813 {
2815  QSKIP("Wayland: This fails. Figure out why.");
2816 
2817  QWidget w;
2818  w.move(200, 200);
2819  QVBoxLayout layout(&w);
2820  QComboBox cb;
2821  cb.setEditable(true);
2822  QSignalSpy spy(&cb, SIGNAL(activated(int)));
2823  cb.addItem("0");
2824  cb.addItem("1");
2825  cb.addItem("2");
2826  QLineEdit edit;
2827  layout.addWidget(&cb);
2828  layout.addWidget(&edit);
2829 
2830  w.show();
2833  cb.clearEditText();
2834  cb.setFocus();
2836  QTRY_VERIFY(cb.hasFocus());
2837  QTest::keyClick(static_cast<QWidget *>(0), '1');
2838  QCOMPARE(spy.count(), 0);
2839  edit.setFocus();
2841  QTRY_COMPARE(spy.count(), 1);
2842 }
2843 
2844 void tst_QComboBox::maxVisibleItems_data()
2845 {
2846  QTest::addColumn<int>("spacing");
2847  QTest::newRow("Default") << -1;
2848  QTest::newRow("No spacing") << 0;
2849  QTest::newRow("20") << -1;
2850 }
2851 
2852 void tst_QComboBox::maxVisibleItems()
2853 {
2854  QFETCH(int, spacing);
2855 
2856  QComboBox comboBox;
2857  QCOMPARE(comboBox.maxVisibleItems(), 10); //default value.
2858 
2859  QStringList content;
2860  for(int i = 1; i < 50; i++)
2861  content += QString::number(i);
2862 
2863  comboBox.addItems(content);
2864  comboBox.move(200, 200);
2865  comboBox.show();
2866  comboBox.resize(200, comboBox.height());
2867  QTRY_VERIFY(comboBox.isVisible());
2868 
2869  comboBox.setMaxVisibleItems(5);
2870  QCOMPARE(comboBox.maxVisibleItems(), 5);
2871 
2872  comboBox.showPopup();
2873  QTRY_VERIFY(comboBox.view());
2874  QTRY_VERIFY(comboBox.view()->isVisible());
2875 
2876  QListView *listView = qobject_cast<QListView*>(comboBox.view());
2877  QVERIFY(listView);
2878  if (spacing >= 0)
2880 
2881  const int itemHeight = listView->visualRect(listView->model()->index(0,0)).height()
2882  + 2 * listView->spacing();
2883 
2885  opt.initFrom(&comboBox);
2886  if (!comboBox.style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
2887  QCOMPARE(listView->viewport()->height(), itemHeight * comboBox.maxVisibleItems());
2888 }
2889 
2890 void tst_QComboBox::task_QTBUG_10491_currentIndexAndModelColumn()
2891 {
2892  QComboBox comboBox;
2893 
2894  QStandardItemModel model(4, 4, &comboBox);
2895  for (int i = 0; i < 4; i++){
2896  const QString iS = QString::number(i);
2897  model.setItem(i, 0, new QStandardItem(QLatin1String("Employee Nr ") + iS));
2898  model.setItem(i, 1, new QStandardItem(QLatin1String("Street Nr ") + iS));
2899  model.setItem(i, 2, new QStandardItem(QLatin1String("Town Nr ") + iS));
2900  model.setItem(i, 3, new QStandardItem(QLatin1String("Phone Nr ") + iS));
2901  }
2902  comboBox.setModel(&model);
2903  comboBox.setModelColumn(0);
2904 
2905  QComboBoxPrivate *d = static_cast<QComboBoxPrivate *>(QComboBoxPrivate::get(&comboBox));
2906  d->setCurrentIndex(model.index(2, 2));
2907  QCOMPARE(QModelIndex(d->currentIndex), model.index(2, comboBox.modelColumn()));
2908 }
2909 
2910 void tst_QComboBox::highlightedSignal()
2911 {
2912  QComboBox comboBox;
2913 
2914  QSignalSpy spy(&comboBox, SIGNAL(highlighted(int)));
2915  QVERIFY(spy.isValid());
2916 
2917  // Calling view() before setting the model causes the creation
2918  // of a QComboBoxPrivateContainer containing an actual view, and connecting to
2919  // the selectionModel to generate the highlighted signal. When setModel is called
2920  // further down, that selectionModel is obsolete. We test that the highlighted
2921  // signal is emitted anyway as the bug fix. (QTBUG-4454)
2922  comboBox.view();
2923  QItemSelectionModel *initialItemSelectionModel = comboBox.view()->selectionModel();
2924 
2925 
2927  for (int i = 0; i < 5; i++)
2928  model.appendRow(new QStandardItem(QString::number(i)));
2929  comboBox.setModel(&model);
2930 
2931  comboBox.view()->selectionModel()->setCurrentIndex(model.index(0, 0), QItemSelectionModel::Current);
2932 
2933  QVERIFY(initialItemSelectionModel != comboBox.view()->selectionModel());
2934 
2935  QCOMPARE(spy.size(), 1);
2936 }
2937 
2938 void tst_QComboBox::itemData()
2939 {
2940  QComboBox comboBox;
2941  const int itemCount = 10;
2942 
2943  // ensure that the currentText(), the DisplayRole and the EditRole
2944  // stay in sync when using QComboBox's default model
2945  for (int i = 0; i < itemCount; ++i) {
2946  QString itemText = QLatin1String("item text ") + QString::number(i);
2947  comboBox.addItem(itemText);
2948  }
2949 
2950  for (int i = 0; i < itemCount; ++i) {
2951  QString itemText = QLatin1String("item text ") + QString::number(i);
2952  QCOMPARE(comboBox.itemText(i), itemText);
2953  QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
2954  QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
2955 
2956  comboBox.setCurrentIndex(i);
2957  QCOMPARE(comboBox.currentIndex(), i);
2958  QCOMPARE(comboBox.currentText(), itemText);
2959  QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
2960  QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
2961  }
2962 
2963  for (int i = 0; i < itemCount; ++i) // now change by using setItemText
2964  comboBox.setItemText(i, QLatin1String("setItemText ") + QString::number(i));
2965 
2966  for (int i = 0; i < itemCount; ++i) {
2967  QString itemText = QLatin1String("setItemText ") + QString::number(i);
2968  QCOMPARE(comboBox.itemText(i), itemText);
2969  QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
2970  QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
2971 
2972  comboBox.setCurrentIndex(i);
2973  QCOMPARE(comboBox.currentIndex(), i);
2974  QCOMPARE(comboBox.currentText(), itemText);
2975  QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
2976  QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
2977  }
2978 
2979  for (int i = 0; i < itemCount; ++i) {
2980  // now change by changing the DisplayRole's data
2981  QString itemText = QLatin1String("setItemData(DisplayRole) ") + QString::number(i);
2982  comboBox.setItemData(i, QVariant(itemText), Qt::DisplayRole);
2983  }
2984 
2985  for (int i = 0; i < itemCount; ++i) {
2986  QString itemText = QLatin1String("setItemData(DisplayRole) ") + QString::number(i);
2987  QCOMPARE(comboBox.itemText(i), itemText);
2988  QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
2989  QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
2990 
2991  comboBox.setCurrentIndex(i);
2992  QCOMPARE(comboBox.currentIndex(), i);
2993  QCOMPARE(comboBox.currentText(), itemText);
2994  QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
2995  QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
2996  }
2997 
2998  for (int i = 0; i < itemCount; ++i) {
2999  // now change by changing the EditRole's data
3000  QString itemText = QLatin1String("setItemData(EditRole) ") + QString::number(i);
3001  comboBox.setItemData(i, QVariant(itemText), Qt::EditRole);
3002  }
3003 
3004  for (int i = 0; i < itemCount; ++i) {
3005  QString itemText = QLatin1String("setItemData(EditRole) ") + QString::number(i);
3006  QCOMPARE(comboBox.itemText(i), itemText);
3007  QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
3008  QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
3009 
3010  comboBox.setCurrentIndex(i);
3011  QCOMPARE(comboBox.currentIndex(), i);
3012  QCOMPARE(comboBox.currentText(), itemText);
3013  QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
3014  QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
3015  }
3016 
3017  comboBox.clear();
3018 
3019 
3020  // set additional user data in the addItem call
3021  for (int i = 0; i < itemCount; ++i) {
3022  const QString iS = QString::number(i);
3023  comboBox.addItem(QLatin1String("item text ") + iS, QVariant(QLatin1String("item data ") + iS));
3024  }
3025 
3026  for (int i = 0; i < itemCount; ++i) {
3027  const QString iS = QString::number(i);
3028  QString itemText = QLatin1String("item text ") + iS;
3029  QString itemDataText = QLatin1String("item data ") + iS;
3030  QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
3031  QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
3032  QCOMPARE(comboBox.itemData(i).toString(), itemDataText);
3033 
3034  comboBox.setCurrentIndex(i);
3035  QCOMPARE(comboBox.currentIndex(), i);
3036  QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
3037  QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
3038  QCOMPARE(comboBox.currentData().toString(), itemDataText);
3039 
3040  }
3041 
3042  comboBox.clear();
3043 
3044 
3045  // additional roles, setItemData
3046  // UserRole + 0 -> string
3047  // UserRole + 1 -> double
3048  // UserRole + 2 -> icon
3049  QString qtlogoPath = QFINDTESTDATA("qtlogo.png");
3050  QIcon icon = QIcon(QPixmap(qtlogoPath));
3051  for (int i = 0; i < itemCount; ++i) {
3052  const QString iS = QString::number(i);
3053  QString itemText = QLatin1String("item text ") + iS;
3054  QString itemDataText = QLatin1String("item data ") + iS;
3055  double d = i;
3056  comboBox.addItem(itemText);
3057  comboBox.setItemData(i, QVariant(itemDataText), Qt::UserRole);
3058  comboBox.setItemData(i, QVariant(d), Qt::UserRole + 1);
3059  comboBox.setItemData(i, QVariant::fromValue(icon), Qt::UserRole + 2);
3060  }
3061 
3062  for (int i = 0; i < itemCount; ++i) {
3063  const QString iS = QString::number(i);
3064  QString itemText = QLatin1String("item text ") + iS;
3065  QString itemDataText = QLatin1String("item data ") + iS;
3066  double d = i;
3067  QCOMPARE(comboBox.itemData(i, Qt::DisplayRole).toString(), itemText);
3068  QCOMPARE(comboBox.itemData(i, Qt::EditRole).toString(), itemText);
3069  QCOMPARE(comboBox.itemData(i, Qt::UserRole).toString(), itemDataText);
3070  QCOMPARE(comboBox.itemData(i, Qt::UserRole + 1).toDouble(), d);
3071  QCOMPARE(comboBox.itemData(i, Qt::UserRole + 2).value<QIcon>(), icon);
3072 
3073  comboBox.setCurrentIndex(i);
3074  QCOMPARE(comboBox.currentData(Qt::DisplayRole).toString(), itemText);
3075  QCOMPARE(comboBox.currentData(Qt::EditRole).toString(), itemText);
3076  QCOMPARE(comboBox.currentData(Qt::UserRole).toString(), itemDataText);
3077  QCOMPARE(comboBox.currentData(Qt::UserRole + 1).toDouble(), d);
3078  QCOMPARE(comboBox.currentData(Qt::UserRole + 2).value<QIcon>(), icon);
3079  }
3080 }
3081 
3082 void tst_QComboBox::task_QTBUG_31146_popupCompletion()
3083 {
3085  QSKIP("Wayland: This fails. Figure out why.");
3086 
3087  QComboBox comboBox;
3088  comboBox.setEditable(true);
3089  comboBox.setInsertPolicy(QComboBox::NoInsert);
3090  comboBox.completer()->setCaseSensitivity(Qt::CaseInsensitive);
3091  comboBox.completer()->setCompletionMode(QCompleter::PopupCompletion);
3092 
3093  comboBox.addItems(QStringList() << QStringLiteral("item") << QStringLiteral("item"));
3094 
3095  comboBox.show();
3096  comboBox.activateWindow();
3098 
3099  QCOMPARE(comboBox.currentIndex(), 0);
3100 
3101  comboBox.lineEdit()->selectAll();
3102  QTest::keyClicks(comboBox.lineEdit(), "item");
3103 
3104  QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Down);
3105  QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Down);
3106  QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Enter);
3107  QCOMPARE(comboBox.currentIndex(), 1);
3108 
3109  comboBox.lineEdit()->selectAll();
3110  QTest::keyClicks(comboBox.lineEdit(), "item");
3111 
3112  QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Up);
3113  QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Up);
3114  QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Enter);
3115  QCOMPARE(comboBox.currentIndex(), 0);
3116 }
3117 
3118 void tst_QComboBox::task_QTBUG_41288_completerChangesCurrentIndex()
3119 {
3121  QSKIP("Wayland: This fails. Figure out why.");
3122 
3123  QComboBox comboBox;
3124  comboBox.setEditable(true);
3125 
3126  comboBox.addItems(QStringList() << QStringLiteral("111") << QStringLiteral("222"));
3127 
3128  comboBox.show();
3129  comboBox.activateWindow();
3131 
3132  {
3133  // change currentIndex() by keyboard
3134  comboBox.lineEdit()->selectAll();
3135  QTest::keyClicks(comboBox.lineEdit(), "222");
3136  QTest::keyClick(comboBox.lineEdit(), Qt::Key_Enter);
3137  QCOMPARE(comboBox.currentIndex(), 1);
3138 
3139  QTest::keyClick(&comboBox, Qt::Key_Up);
3140  comboBox.lineEdit()->selectAll();
3141  QTest::keyClick(comboBox.lineEdit(), Qt::Key_Enter);
3142  QCOMPARE(comboBox.currentIndex(), 0);
3143  }
3144 
3145  {
3146  // change currentIndex() programmatically
3147  comboBox.lineEdit()->selectAll();
3148  QTest::keyClicks(comboBox.lineEdit(), "222");
3149  QTest::keyClick(comboBox.lineEdit(), Qt::Key_Enter);
3150  QCOMPARE(comboBox.currentIndex(), 1);
3151 
3152  comboBox.setCurrentIndex(0);
3153  comboBox.lineEdit()->selectAll();
3154  QTest::keyClick(comboBox.lineEdit(), Qt::Key_Enter);
3155  QCOMPARE(comboBox.currentIndex(), 0);
3156  }
3157 }
3158 
3159 namespace {
3160  struct SetReadOnly {
3161  QComboBox *cb;
3162  explicit SetReadOnly(QComboBox *cb) : cb(cb) {}
3163  void operator()() const
3164  { cb->setEditable(false); }
3165  };
3166 }
3167 
3168 void tst_QComboBox::task_QTBUG_54191_slotOnEditTextChangedSetsComboBoxToReadOnly()
3169 {
3170  QComboBox cb;
3171  cb.addItems(QStringList() << "one" << "two");
3172  cb.setEditable(true);
3173  cb.setCurrentIndex(0);
3174 
3176  SetReadOnly(&cb));
3177 
3178  cb.setCurrentIndex(1);
3179  // the real test is that it didn't crash...
3180  QCOMPARE(cb.currentIndex(), 1);
3181 }
3182 
3183 void tst_QComboBox::keyboardSelection()
3184 {
3185  QComboBox comboBox;
3186  const int keyboardInterval = QApplication::keyboardInputInterval();
3187  QStringList list;
3188  list << "OA" << "OB" << "OC" << "OO" << "OP" << "PP";
3189  comboBox.addItems(list);
3190 
3191  // Clear any remaining keyboard input from previous tests.
3192  QTest::qWait(keyboardInterval);
3193  QTest::keyClicks(&comboBox, "oo", Qt::NoModifier, 50);
3194  QCOMPARE(comboBox.currentText(), list.at(3));
3195 
3196  QTest::qWait(keyboardInterval);
3197  QTest::keyClicks(&comboBox, "op", Qt::NoModifier, 50);
3198  QCOMPARE(comboBox.currentText(), list.at(4));
3199 
3200  QTest::keyClick(&comboBox, Qt::Key_P, Qt::NoModifier, keyboardInterval);
3201  QCOMPARE(comboBox.currentText(), list.at(5));
3202 
3203  QTest::keyClick(&comboBox, Qt::Key_O, Qt::NoModifier, keyboardInterval);
3204  QCOMPARE(comboBox.currentText(), list.at(0));
3205 
3206  QTest::keyClick(&comboBox, Qt::Key_O, Qt::NoModifier, keyboardInterval);
3207  QCOMPARE(comboBox.currentText(), list.at(1));
3208 }
3209 
3210 void tst_QComboBox::updateDelegateOnEditableChange()
3211 {
3212 
3213  QComboBox box;
3214  box.addItem(QStringLiteral("Foo"));
3215  box.addItem(QStringLiteral("Bar"));
3216  box.setEditable(false);
3217 
3219 
3220  {
3221  bool menuDelegateBefore = qobject_cast<QComboMenuDelegate *>(box.itemDelegate()) != 0;
3222  d->updateDelegate();
3223  bool menuDelegateAfter = qobject_cast<QComboMenuDelegate *>(box.itemDelegate()) != 0;
3224  QCOMPARE(menuDelegateAfter, menuDelegateBefore);
3225  }
3226 
3227  box.setEditable(true);
3228 
3229  {
3230  bool menuDelegateBefore = qobject_cast<QComboMenuDelegate *>(box.itemDelegate()) != 0;
3231  d->updateDelegate();
3232  bool menuDelegateAfter = qobject_cast<QComboMenuDelegate *>(box.itemDelegate()) != 0;
3233  QCOMPARE(menuDelegateAfter, menuDelegateBefore);
3234  }
3235 }
3236 
3237 void tst_QComboBox::task_QTBUG_39088_inputMethodHints()
3238 {
3239  QComboBox box;
3240  box.setEditable(true);
3241  box.setInputMethodHints(Qt::ImhNoPredictiveText);
3242  QCOMPARE(box.lineEdit()->inputMethodHints(), Qt::ImhNoPredictiveText);
3243 }
3244 
3245 void tst_QComboBox::respectChangedOwnershipOfItemView()
3246 {
3247  QComboBox box1;
3248  QComboBox box2;
3249  QTableView *v1 = new QTableView;
3250  box1.setView(v1);
3251 
3252  QSignalSpy spy1(v1, SIGNAL(destroyed()));
3253  box2.setView(v1); // Ownership should now be transferred to box2
3254 
3255 
3256  QTableView *v2 = new QTableView(&box1);
3257  box1.setView(v2); // Here we do not expect v1 to be deleted
3259  QCOMPARE(spy1.count(), 0);
3260 
3261  QSignalSpy spy2(v2, SIGNAL(destroyed()));
3262  box1.setView(v1);
3263  QCOMPARE(spy2.count(), 1);
3264 }
3265 
3266 void tst_QComboBox::task_QTBUG_49831_scrollerNotActivated()
3267 {
3268  QStringList modelData;
3269  for (int i = 0; i < 1000; i++)
3270  modelData << QStringLiteral("Item %1").arg(i);
3271  QStringListModel model(modelData);
3272 
3273  QComboBox box;
3274  box.setModel(&model);
3275  box.setCurrentIndex(500);
3276  box.show();
3278  QTest::mouseMove(&box, QPoint(5, 5), 100);
3279  box.showPopup();
3280  QFrame *container = box.findChild<QComboBoxPrivateContainer *>();
3281  QVERIFY(container);
3283 
3285  // Not all styles support scrollers. We rely only on those platforms that do to catch any regression.
3286  if (!scrollers.isEmpty()) {
3287  Q_FOREACH (QComboBoxPrivateScroller *scroller, scrollers) {
3288  if (scroller->isVisible()) {
3289  QSignalSpy doScrollSpy(scroller, SIGNAL(doScroll(int)));
3290  QTest::mouseMove(scroller, QPoint(5, 5), 500);
3291  QTRY_VERIFY(doScrollSpy.count() > 0);
3292  }
3293  }
3294  }
3295 }
3296 
3298 {
3299 public:
3300  QTBUG_56693_Model(QObject *parent = nullptr)
3302  { }
3303 
3304  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
3305  {
3306  if (role == Qt::FontRole) {
3307  if (index.row() < 5) {
3308  QFont font = QApplication::font();
3309  font.setItalic(true);
3310  return font;
3311  } else {
3312  return QApplication::font();
3313  }
3314  }
3315  return QStandardItemModel::data(index, role);
3316  }
3317 };
3318 
3320 {
3321 public:
3323  : QProxyStyle(style), italicItemsNo(0)
3324  {
3325 
3326  }
3327 
3328  void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w = nullptr) const override
3329  {
3330  if (element == CE_MenuItem)
3331  if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt))
3332  if (menuItem->font.italic())
3333  italicItemsNo++;
3334 
3335  baseStyle()->drawControl(element, opt, p, w);
3336  }
3337 
3338  mutable int italicItemsNo;
3339 };
3340 
3341 void tst_QComboBox::task_QTBUG_56693_itemFontFromModel()
3342 {
3343  QComboBox box;
3344  if (!qobject_cast<QComboMenuDelegate *>(box.itemDelegate()))
3345  QSKIP("Only for combo boxes using QComboMenuDelegate");
3346 
3348  box.setModel(&model);
3349 
3350  QTBUG_56693_ProxyStyle *proxyStyle = new QTBUG_56693_ProxyStyle(box.style());
3351  box.setStyle(proxyStyle);
3352  box.setFont(QApplication::font());
3353 
3354  for (int i = 0; i < 10; i++)
3355  box.addItem(QLatin1String("Item ") + QString::number(i));
3356 
3357  box.show();
3359  box.showPopup();
3360  QFrame *container = box.findChild<QComboBoxPrivateContainer *>();
3361  QVERIFY(container);
3363 
3364  QCOMPARE(proxyStyle->italicItemsNo, 5);
3365 
3366  box.hidePopup();
3367 }
3368 
3369 void tst_QComboBox::inputMethodUpdate()
3370 {
3372  QSKIP("Wayland: This fails. Figure out why.");
3373 
3374  TestWidget topLevel;
3375  topLevel.show();
3377  QComboBox *testWidget = topLevel.comboBox();
3378  // make sure we have no lineedit
3379  QVERIFY(!testWidget->lineEdit());
3380  // test setEditable(true)
3381  testWidget->setEditable(true);
3382  QVERIFY(testWidget->lineEdit());
3383 
3384  testWidget->activateWindow();
3385  testWidget->setFocus();
3386  QTRY_VERIFY(testWidget->hasFocus());
3387  QTRY_COMPARE(qApp->focusObject(), testWidget);
3388 
3389  m_platformInputContext.m_updateCallCount = 0;
3390  {
3392  QInputMethodEvent event("preedit text", attributes);
3393  QApplication::sendEvent(testWidget, &event);
3394  }
3395  QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
3396 
3397  m_platformInputContext.m_updateCallCount = 0;
3398  {
3401  QInputMethodEvent event("preedit text", attributes);
3402  QApplication::sendEvent(testWidget, &event);
3403  }
3404  QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
3405 
3406  m_platformInputContext.m_updateCallCount = 0;
3407  {
3409  QInputMethodEvent event("", attributes);
3410  event.setCommitString("preedit text");
3411  QApplication::sendEvent(testWidget, &event);
3412  }
3413  QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
3414  QCOMPARE(testWidget->lineEdit()->text(), QString("preedit text"));
3415 
3416  m_platformInputContext.m_updateCallCount = 0;
3417  {
3420  QInputMethodEvent event("", attributes);
3421  QApplication::sendEvent(testWidget, &event);
3422  }
3423  QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
3424 }
3425 
3426 void tst_QComboBox::task_QTBUG_52027_mapCompleterIndex()
3427 {
3429  QSKIP("Wayland: This fails. Figure out why.");
3430 
3431  QStringList words;
3432  words << "" << "foobar1" << "foobar2";
3433 
3434  QStringList altWords;
3435  altWords << "foobar2" << "hello" << "," << "world" << "" << "foobar0" << "foobar1";
3436 
3437  QComboBox cbox;
3438  setFrameless(&cbox);
3439  cbox.setEditable(true);
3440  cbox.setInsertPolicy(QComboBox::NoInsert);
3441  cbox.addItems(words);
3442 
3443  QCompleter *completer = new QCompleter(altWords);
3445  cbox.setCompleter(completer);
3446 
3447  QSignalSpy spy(&cbox, SIGNAL(activated(int)));
3448  QCOMPARE(spy.count(), 0);
3449  cbox.move(200, 200);
3450  cbox.show();
3453 
3454  QTest::keyClicks(&cbox, "foobar2");
3457  QTest::keyClick(completer->popup(), Qt::Key_Down);
3459  QTest::keyClick(completer->popup(), Qt::Key_Return);
3462  QCOMPARE(arguments.at(0).toInt(), 2);
3463 
3464  cbox.lineEdit()->selectAll();
3465  cbox.lineEdit()->del();
3466 
3468  model->setSourceModel(cbox.model());
3469  model->setFilterFixedString("foobar1");
3471 
3472  if (QGuiApplication::platformName() == "offscreen") {
3473  qWarning("Offscreen platform requires explicit activateWindow()");
3474  cbox.activateWindow();
3475  }
3476 
3479 
3480  QTest::keyClicks(&cbox, "foobar1");
3483  QTest::keyClick(completer->popup(), Qt::Key_Down);
3485  QTest::keyClick(completer->popup(), Qt::Key_Return);
3487  arguments = spy.takeLast();
3488  QCOMPARE(arguments.at(0).toInt(), 1);
3489 }
3490 
3491 void tst_QComboBox::checkMenuItemPosWhenStyleSheetIsSet()
3492 {
3493  QString newCss = "QComboBox {font-size: 18pt;}";
3494  QString oldCss = qApp->styleSheet();
3495  qApp->setStyleSheet(newCss);
3496 
3497  QWidget topLevel;
3498  QVBoxLayout *layout = new QVBoxLayout(&topLevel);
3499  QStackedWidget *stack = new QStackedWidget(&topLevel);
3500  layout->addWidget(stack);
3501  QWidget *container = new QWidget(&topLevel);
3502  QHBoxLayout *cLayout = new QHBoxLayout(container);
3503  QComboBox *cBox = new QComboBox;
3504 
3507  model->appendRow(item);
3508  item = new QStandardItem(QStringLiteral("Item2"));
3509  model->appendRow(item);
3510  item = new QStandardItem(QStringLiteral("Item3"));
3511  model->appendRow(item);
3512  item = new QStandardItem(QStringLiteral("Item4"));
3513  model->appendRow(item);
3514  cBox->setModel(model);
3515 
3516  cLayout->addWidget(cBox);
3517  stack->addWidget(container);
3518  topLevel.show();
3519  cBox->showPopup();
3520 
3521  QTRY_VERIFY(cBox->view());
3522  QTRY_VERIFY(cBox->view()->isVisible());
3523 
3524  int menuHeight = cBox->view()->geometry().height();
3525  QRect menuItemRect = cBox->view()->visualRect(model->indexFromItem(item));
3526 
3527  QCOMPARE(menuHeight, menuItemRect.y() + menuItemRect.height());
3528 
3529  qApp->setStyleSheet(oldCss);
3530 }
3531 
3532 void tst_QComboBox::checkEmbeddedLineEditWhenStyleSheetIsSet()
3533 {
3534  QString newCss = "QWidget { background-color: red; color: white; }";
3535  QString oldCss = qApp->styleSheet();
3536  qApp->setStyleSheet(newCss);
3537 
3538  QWidget topLevel;
3539  auto layout = new QVBoxLayout(&topLevel);
3540  topLevel.setLayout(layout);
3541  auto comboBox = new QComboBox;
3542  layout->addWidget(comboBox);
3543  topLevel.show();
3544  comboBox->setEditable(true);
3545  QApplication::setActiveWindow(&topLevel);
3547 
3548  QImage grab = comboBox->grab().toImage();
3549  auto color = grab.pixelColor(grab.rect().center());
3550 
3551  QVERIFY(color.red() > 240);
3552  QVERIFY(color.green() < 20);
3553  QVERIFY(color.blue() < 20);
3554 
3555  qApp->setStyleSheet(oldCss);
3556 }
3557 
3565 void tst_QComboBox::propagateStyleChanges()
3566 {
3567  class FrameStyle : public QProxyStyle
3568  {
3569  public:
3570  FrameStyle(int frameStyle, QStyle *style = nullptr)
3571  : QProxyStyle(style), frameStyle(frameStyle)
3572  {}
3573 
3574  int styleHint(QStyle::StyleHint hint, const QStyleOption *opt,
3575  const QWidget *widget, QStyleHintReturn *returnData) const override
3576  {
3578  inquired = true;
3579  return frameStyle;
3580  }
3581  return QProxyStyle::styleHint(hint, opt, widget, returnData);
3582  }
3583 
3584  int frameStyle;
3585  mutable bool inquired = false;
3586  };
3587 
3588  FrameStyle framelessStyle(QFrame::NoFrame);
3589  FrameStyle frameStyle(QFrame::Plain | QFrame::Sunken);
3590 
3591  QComboBox combo;
3592  // container will be created and take settings from this style
3593  combo.setStyle(&framelessStyle);
3594  QVERIFY(framelessStyle.inquired);
3595  combo.addItem(QLatin1String("Open"));
3596  combo.addItem(QLatin1String("Close"));
3597  // needed because of QComboBox's adjustSizeTimer not doing anything otherwise
3598  combo.setSizeAdjustPolicy(QComboBox::AdjustToContents);
3599  combo.setStyle(&frameStyle);
3600  QVERIFY(frameStyle.inquired);
3601 }
3602 
3604 #include "tst_qcombobox.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Arabic default style
Definition: afstyles.h:94
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override
bool setData(const QModelIndex &, const QVariant &, int) override
QVariant data(const QModelIndex &, int) const override
bool insertColumns(int, int, const QModelIndex &) override
bool removeRows(int, int, const QModelIndex &) override
int columnCount(const QModelIndex &) const override
QModelIndex parent(const QModelIndex &) const override
bool insertRows(int, int, const QModelIndex &) override
bool removeColumns(int, int, const QModelIndex &) override
QModelIndex index(int, int, const QModelIndex &) const override
bool hasChildren(const QModelIndex &) const override
void setPersistent(const QModelIndex &, const QModelIndex &)
int rowCount(const QModelIndex &) const override
QRegion visualRegionForSelection(const QItemSelection &) const override
int verticalOffset() const override
QModelIndex indexAt(const QPoint &) const override
void scrollTo(const QModelIndex &, ScrollHint) override
bool isIndexHidden(const QModelIndex &) const override
int horizontalOffset() const override
void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) override
QRect visualRect(const QModelIndex &) const override
QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers) override
The QAbstractItemDelegate class is used to display and edit data items from a model.
The QAbstractItemModel class provides the abstract interface for item model classes.
virtual Q_INVOKABLE bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
The QAbstractItemView class provides the basic functionality for item view classes.
QAbstractItemModel * model() const
void setCurrentIndex(const QModelIndex &index)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
static QStyle * style()
static void setStyle(QStyle *)
static QFont font()
int doubleClickInterval
the time limit in milliseconds that distinguishes a double click from two consecutive mouse clicks
Definition: qapplication.h:71
static QWidget * activeWindow()
int keyboardInputInterval
the time limit in milliseconds that distinguishes a key press from two consecutive key presses
Definition: qapplication.h:72
static void setKeyboardInputInterval(int)
static void setActiveWindow(QWidget *act)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
@ InsertAtCurrent
Definition: qcombobox.h:106
@ InsertAtTop
Definition: qcombobox.h:105
@ InsertBeforeCurrent
Definition: qcombobox.h:109
@ InsertAfterCurrent
Definition: qcombobox.h:108
@ InsertAlphabetically
Definition: qcombobox.h:110
@ InsertAtBottom
Definition: qcombobox.h:107
SizeAdjustPolicy
Definition: qcombobox.h:117
@ AdjustToContents
Definition: qcombobox.h:118
@ AdjustToMinimumContentsLengthWithIcon
Definition: qcombobox.h:120
@ AdjustToContentsOnFirstShow
Definition: qcombobox.h:119
void activated(int index)
void editTextChanged(const QString &)
void currentIndexChanged(int index)
int styleHint(StyleHint sh, const QStyleOption *opt=nullptr, const QWidget *w=nullptr, QStyleHintReturn *shret=nullptr) const override
The QCompleter class provides completions based on an item model.
Definition: qcompleter.h:60
@ PopupCompletion
Definition: qcompleter.h:74
QAbstractItemView * popup() const
void setModel(QAbstractItemModel *c)
void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity)
static QCoreApplication * instance()
static bool sendEvent(QObject *receiver, QEvent *event)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
@ KeyRelease
Definition: qcoreevent.h:78
@ KeyPress
Definition: qcoreevent.h:77
The QFontComboBox widget is a combobox that lets the user select a font family.
Definition: qfontcombobox.h:54
The QFrame class is the base class of widgets that can have a frame.
Definition: qframe.h:53
@ Plain
Definition: qframe.h:85
@ Sunken
Definition: qframe.h:87
@ NoFrame
Definition: qframe.h:75
QScreen * primaryScreen
the primary (or default) screen of the application.
static void setLayoutDirection(Qt::LayoutDirection direction)
QString platformName
The name of the underlying platform plugin.
static QPlatformTheme * platformTheme()
void setModel(QAbstractItemModel *model) override
The QInputMethodEvent::Attribute class stores an input method attribute.
Definition: qevent.h:706
The QInputMethodEvent class provides parameters for input method events. \inmodule QtGui.
Definition: qevent.h:696
QPlatformInputContext * testContext
static QInputMethodPrivate * get(QInputMethod *inputMethod)
The QIntValidator class provides a validator that ensures a string contains a valid integer within a ...
Definition: qvalidator.h:92
The QItemSelection class manages information about selected items in a model.
The QKeyEvent class describes a key event.
Definition: qevent.h:471
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
@ SetMinAndMaxSize
Definition: qlayout.h:77
The QLineEdit widget is a one-line text editor.
Definition: qlineedit.h:64
qsizetype size() const noexcept
Definition: qlist.h:414
bool isEmpty() const noexcept
Definition: qlist.h:418
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
value_type takeLast()
Definition: qlist.h:565
qsizetype count() const noexcept
Definition: qlist.h:415
void clear()
Definition: qlist.h:445
The QListView class provides a list or icon view onto a model.
Definition: qlistview.h:53
void setSpacing(int space)
Definition: qlistview.cpp:374
int spacing
the space around the items in the layout
Definition: qlistview.h:60
QRect visualRect(const QModelIndex &index) const override
Definition: qlistview.cpp:558
The QListWidget class provides an item-based list widget.
Definition: qlistwidget.h:188
void addItems(const QStringList &labels)
Definition: qlistwidget.h:210
QListWidgetItem * item(int row) const
void setFlags(Qt::ItemFlags flags)
Qt::ItemFlags flags() const
Definition: qlistwidget.h:81
The QModelIndex class is used to locate data in a data model.
constexpr bool isValid() const noexcept
T findChild(const QString &aName=QString(), Qt::FindChildOptions options=Qt::FindChildrenRecursively) const
Definition: qobject.h:168
QString objectName
the name of this object
Definition: qobject.h:129
QList< T > findChildren(const QString &aName, Qt::FindChildOptions options=Qt::FindChildrenRecursively) const
Definition: qobject.h:175
@ Base
Definition: qpalette.h:87
The QProxyStyle class is a convenience class that simplifies dynamically overriding QStyle elements.
Definition: qproxystyle.h:53
int styleHint(StyleHint hint, const QStyleOption *option=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const override
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:63
QRect availableGeometry
the screen's available geometry in pixels
Definition: qscreen.h:82
QRect geometry
the screen's geometry in pixels
Definition: qscreen.h:81
The QScrollArea class provides a scrolling view onto another widget.
Definition: qscrollarea.h:53
bool isValid() const
Definition: qsignalspy.h:130
The QSortFilterProxyModel class provides support for sorting and filtering data passed between anothe...
int rowCount(const QModelIndex &parent=QModelIndex()) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
virtual void clear()
The QStackedWidget class provides a stack of widgets where only one widget is visible at a time.
int addWidget(QWidget *w)
The QStandardItem class provides an item for use with the QStandardItemModel class.
The QStandardItemModel class provides a generic model for storing custom data.\inmodule QtGui.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
The QString class provides a Unicode character string.
Definition: qstring.h:388
QByteArray toLatin1() const &
Definition: qstring.h:745
qsizetype count() const
Definition: qstring.h:414
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
void clear()
Definition: qstring.h:1240
const QChar at(qsizetype i) const
Definition: qstring.h:1212
static QString number(int, int base=10)
Definition: qstring.cpp:7538
void resize(qsizetype size)
Definition: qstring.cpp:2670
The QStringList class provides a list of strings.
The QStringListModel class provides a model that supplies strings to views.
QStringListModel(QObject *parent=nullptr)
The QStyleFactory class creates QStyle objects.
Definition: qstylefactory.h:52
static QStyle * create(const QString &)
the exposed rectangle, in item coordinates
Definition: qstyleoption.h:724
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition: qstyle.h:65
StyleHint
Definition: qstyle.h:618
@ SH_ComboBox_Popup
Definition: qstyle.h:644
@ SH_ComboBox_PopupFrameStyle
Definition: qstyle.h:688
@ SH_ComboBox_LayoutDirection
Definition: qstyle.h:677
@ SH_ComboBox_AllowWheelScrolling
Definition: qstyle.h:735
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const =0
ControlElement
Definition: qstyle.h:206
@ PM_SmallIconSize
Definition: qstyle.h:529
@ CC_ComboBox
Definition: qstyle.h:369
@ SC_ComboBoxListBoxPopup
Definition: qstyle.h:403
@ SC_ComboBoxEditField
Definition: qstyle.h:401
@ SC_ComboBoxArrow
Definition: qstyle.h:402
an OR combination of the tool button's features
Definition: qstyleoption.h:608
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:75
void initFrom(const QWidget *w)
Qt::LayoutDirection direction
Definition: qstyleoption.h:96
the minimum value for the progress bar
Definition: qstyleoption.h:369
The QStyledItemDelegate class provides display and editing facilities for data items from a model.
QTBUG_56693_Model(QObject *parent=nullptr)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w=nullptr) const override
QTBUG_56693_ProxyStyle(QStyle *style)
The QTableView class provides a default model/view implementation of a table view.
Definition: qtableview.h:54
The QTableWidget class provides an item-based table view with a default model.
Definition: qtablewidget.h:215
The QTableWidgetItem class provides an item for use with the QTableWidget class.
Definition: qtablewidget.h:84
The QTreeView class provides a default model/view implementation of a tree view.
Definition: qtreeview.h:56
QHeaderView * header() const
Definition: qtreeview.cpp:295
The QTreeWidget class provides a tree view that uses a predefined tree model.
Definition: qtreewidget.h:250
void addTopLevelItem(QTreeWidgetItem *item)
void setColumnCount(int columns)
The QTreeWidgetItem class provides an item for use with the QTreeWidget convenience class.
Definition: qtreewidget.h:59
The QValidator class provides validation of input text. \inmodule QtGui.
Definition: qvalidator.h:60
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
void clear()
Definition: qvariant.cpp:1082
int toInt(bool *ok=nullptr) const
Definition: qvariant.cpp:1833
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
Definition: qwidget.h:204
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:140
void setFocus()
Definition: qwidget.h:454
void show()
Definition: qwidget.cpp:7825
bool hasFocus() const
Definition: qwidget.cpp:6430
QScreen * screen() const
Definition: qwidget.cpp:2508
bool isVisible() const
Definition: qwidget.h:907
static QWidgetPrivate * get(QWidget *w)
Definition: qwidget_p.h:252
ReturnClass(QWidget *parent=nullptr)
void keyPressEvent(QKeyEvent *e) override
QLineEdit * edit
QWidget(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
QComboBox * comboBox() const
void onCurrentIndexChanged(int index)
task166349_ComboBox(QWidget *parent=nullptr)
#define this
Definition: dialogs.cpp:56
QOpenGLWidget * widget
[1]
b clear()
a resize(100000)
QString text
[meta data]
qreal spacing
QPushButton * button
[2]
double e
object setObjectName("A new object name")
QSignalSpy spy(myCustomObject, SIGNAL(mySignal(int, QString, double)))
[0]
QList< QVariant > arguments
QCOMPARE(spy.count(), 1)
void drawControl(ControlElement element, QPainter *painter, const QWidget *widget, const QRect &rect, const QColorGroup &colorGroup, SFlags how=Style_Default, const QStyleOption &option=QStyleOption::Default) const
[1]
rect
[4]
QPixmap pix
QStyleOptionButton opt
palette
constexpr T & operator()(T &v) const
Definition: hb-algs.hh:2
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout=5000)
Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout=5000)
void mouseMove(QWindow *window, QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:175
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Definition: qtestcase.cpp:2292
void mouseDClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:171
void mouseClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:167
Q_CORE_EXPORT void qWait(int ms)
Definition: qnamespace.h:55
@ LeftButton
Definition: qnamespace.h:83
@ NoButton
Definition: qnamespace.h:82
LayoutDirection
Definition: qnamespace.h:1462
@ LeftToRight
Definition: qnamespace.h:1463
@ RightToLeft
Definition: qnamespace.h:1464
@ ImhNoPredictiveText
Definition: qnamespace.h:1417
@ blue
Definition: qnamespace.h:68
@ green
Definition: qnamespace.h:67
@ red
Definition: qnamespace.h:66
@ FontRole
Definition: qnamespace.h:1509
@ UserRole
Definition: qnamespace.h:1527
@ DecorationRole
Definition: qnamespace.h:1503
@ EditRole
Definition: qnamespace.h:1504
@ DisplayRole
Definition: qnamespace.h:1502
@ UI_AnimateCombo
Definition: qnamespace.h:1170
@ Key_O
Definition: qnamespace.h:586
@ Key_B
Definition: qnamespace.h:573
@ Key_Return
Definition: qnamespace.h:688
@ Key_Enter
Definition: qnamespace.h:689
@ Key_PageUp
Definition: qnamespace.h:702
@ Key_Space
Definition: qnamespace.h:538
@ Key_Backspace
Definition: qnamespace.h:687
@ Key_A
Definition: qnamespace.h:572
@ Key_P
Definition: qnamespace.h:587
@ Key_1
Definition: qnamespace.h:556
@ Key_Up
Definition: qnamespace.h:699
@ Key_Down
Definition: qnamespace.h:701
@ Key_T
Definition: qnamespace.h:591
@ Key_Delete
Definition: qnamespace.h:691
@ Key_H
Definition: qnamespace.h:579
@ Key_PageDown
Definition: qnamespace.h:703
@ Key_Home
Definition: qnamespace.h:696
@ Key_End
Definition: qnamespace.h:697
@ NoModifier
Definition: qnamespace.h:1074
@ CaseInsensitive
Definition: qnamespace.h:1283
@ CaseSensitive
Definition: qnamespace.h:1284
QTextStream & center(QTextStream &stream)
@ NoScrollPhase
Definition: qnamespace.h:1696
@ ItemIsSelectable
Definition: qnamespace.h:1532
@ ItemIsEnabled
Definition: qnamespace.h:1537
@ MatchCaseSensitive
Definition: qnamespace.h:1554
@ MatchExactly
Definition: qnamespace.h:1546
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
#define QString()
Definition: parse-defines.h:51
QList< QString > QStringList
Definition: qcontainerfwd.h:64
#define qApp
@ QtWarningMsg
Definition: qlogging.h:62
#define qWarning
Definition: qlogging.h:179
#define Q_DECLARE_METATYPE(TYPE)
Definition: qmetatype.h:1417
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLint GLfloat GLfloat GLfloat v2
GLuint64 key
GLboolean r
[2]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLuint index
[2]
GLdouble GLdouble GLdouble GLdouble top
GLuint color
[2]
GLint GLfloat GLfloat v1
GLuint start
GLenum GLuint GLintptr offset
GLfloat n
GLsizei const GLint * box
GLint y
GLenum GLenum GLsizei void GLsizei void * column
Definition: qopenglext.h:2747
struct _cl_event * event
Definition: qopenglext.h:2998
GLboolean reset
Definition: qopenglext.h:2748
GLenum GLenum GLsizei void * row
Definition: qopenglext.h:2747
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLuint GLenum option
Definition: qopenglext.h:5929
GLenum GLenum GLenum input
Definition: qopenglext.h:10816
GLenum GLenum GLsizei void * table
Definition: qopenglext.h:2745
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define QStringLiteral(str)
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QTRY_COMPARE(expr, expected)
Definition: qtestcase.h:214
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define QFINDTESTDATA(basepath)
Definition: qtestcase.h:251
#define QTRY_VERIFY(expr)
Definition: qtestcase.h:196
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
#define disabled
view setModel(model)
[17] //! [18]
QSqlQueryModel * model
[16]
struct Window Window
Definition: sqlite3.c:14312
QScreen * screen
[1]
Definition: main.cpp:76
QIcon icon
[15]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QVBoxLayout * layout
QLineEdit * lineEdit
QListView * listView
timer inherits("QTimer")
QVariant variant
[1]
QString dir
[11]
QGraphicsItem * item
edit hide()
QItemSelection * selection
[0]
QList< QTreeWidgetItem * > items
widget render & pixmap
aWidget window() -> setWindowTitle("New Window Title")
[2]
QCompleter * completer
[0]
QQuickView * view
[0]
view create()
QStringList list
[0]
QScroller * scroller
Definition: jquant2.c:237
#define WHEEL_DELTA
QList< QIcon > IconList
QList< Qt::Key > KeyList
QList< int > IntList
QList< QVariant > VariantList
#define GET_SELECTION(SEL)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent