Remove usage of deprecated qWaitForWindowShown(QWidget *) method.
[profile/ivi/qtbase.git] / tests / auto / widgets / itemviews / qitemdelegate / tst_qitemdelegate.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #include <qabstractitemview.h>
46 #include <qstandarditemmodel.h>
47 #include <qapplication.h>
48 #include <qdatetimeedit.h>
49 #include <qspinbox.h>
50 #include <qlistview.h>
51 #include <qtableview.h>
52 #include <qtreeview.h>
53 #include <qheaderview.h>
54 #include <qitemeditorfactory.h>
55 #include <qlineedit.h>
56 #include <qvalidator.h>
57 #include <qtablewidget.h>
58 #include <qtreewidget.h>
59
60 #include <QItemDelegate>
61 #include <QComboBox>
62 #include <QAbstractItemDelegate>
63 #include <QTextEdit>
64 #include <QPlainTextEdit>
65 #include <QDialog>
66
67 Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint)
68
69 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
70 #include <windows.h>
71 #define Q_CHECK_PAINTEVENTS \
72     if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
73         QSKIP("The widgets don't get the paint events");
74 #else
75 #define Q_CHECK_PAINTEVENTS
76 #endif
77
78 //Begin of class definitions
79
80 class TestItemDelegate : public QItemDelegate
81 {
82 public:
83     TestItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {}
84     ~TestItemDelegate() {}
85
86     void drawDisplay(QPainter *painter,
87                      const QStyleOptionViewItem &option,
88                      const QRect &rect, const QString &text) const
89     {
90         displayText = text;
91         displayFont = option.font;
92         QItemDelegate::drawDisplay(painter, option, rect, text);
93     }
94
95     void drawDecoration(QPainter *painter,
96                         const QStyleOptionViewItem &option,
97                         const QRect &rect, const QPixmap &pixmap) const
98     {
99         decorationPixmap = pixmap;
100         decorationRect = rect;
101         QItemDelegate::drawDecoration(painter, option, rect, pixmap);
102     }
103
104
105     inline QRect textRectangle(QPainter * painter, const QRect &rect,
106                                const QFont &font, const QString &text) const
107     {
108         return QItemDelegate::textRectangle(painter, rect, font, text);
109     }
110
111     inline void doLayout(const QStyleOptionViewItem &option,
112                          QRect *checkRect, QRect *pixmapRect,
113                          QRect *textRect, bool hint) const
114     {
115         QItemDelegate::doLayout(option, checkRect, pixmapRect, textRect, hint);
116     }
117
118     inline QRect rect(const QStyleOptionViewItem &option,
119                       const QModelIndex &index, int role) const
120     {
121         return QItemDelegate::rect(option, index, role);
122     }
123
124     inline bool eventFilter(QObject *object, QEvent *event)
125     {
126         return QItemDelegate::eventFilter(object, event);
127     }
128
129     inline bool editorEvent(QEvent *event,
130                             QAbstractItemModel *model,
131                             const QStyleOptionViewItem &option,
132                             const QModelIndex &index)
133     {
134         return QItemDelegate::editorEvent(event, model, option, index);
135     }
136
137     // stored values for testing
138     mutable QString displayText;
139     mutable QFont displayFont;
140     mutable QPixmap decorationPixmap;
141     mutable QRect decorationRect;
142 };
143
144 class TestItemModel : public QAbstractTableModel
145 {
146 public:
147
148     enum Roles {
149         PixmapTestRole,
150         ImageTestRole,
151         IconTestRole,
152         ColorTestRole,
153         DoubleTestRole
154     };
155
156     TestItemModel(const QSize &size) : size(size) {}
157
158     ~TestItemModel() {}
159
160     int rowCount(const QModelIndex &parent) const
161     {
162         Q_UNUSED(parent);
163         return 1;
164     }
165
166     int columnCount(const QModelIndex &parent) const
167     {
168         Q_UNUSED(parent);
169         return 1;
170     }
171
172     QVariant data(const QModelIndex& index, int role) const
173     {
174         Q_UNUSED(index);
175         static QPixmap pixmap(size);
176         static QImage image(size, QImage::Format_Mono);
177         static QIcon icon(pixmap);
178         static QColor color(Qt::green);
179
180         switch (role) {
181         case PixmapTestRole: return pixmap;
182         case ImageTestRole:  return image;
183         case IconTestRole:   return icon;
184         case ColorTestRole:  return color;
185         case DoubleTestRole:  return 10.00000001;
186         default: break;
187         }
188
189         return QVariant();
190     }
191
192 private:
193     QSize size;
194 };
195
196 class tst_QItemDelegate : public QObject
197 {
198     Q_OBJECT
199
200 public:
201     tst_QItemDelegate();
202     virtual ~tst_QItemDelegate();
203
204 private slots:
205     void initTestCase();
206     void cleanupTestCase();
207     void init();
208     void cleanup();
209     void getSetCheck();
210     void textRectangle_data();
211     void textRectangle();
212     void sizeHint_data();
213     void sizeHint();
214     void editorKeyPress_data();
215     void editorKeyPress();
216     void doubleEditorNegativeInput();
217     void font_data();
218     void font();
219     void doLayout_data();
220     void doLayout();
221     void rect_data();
222     void rect();
223     void eventFilter();
224     void dateTimeEditor_data();
225     void dateTimeEditor();
226     void dateAndTimeEditorTest2();
227     void decoration_data();
228     void decoration();
229     void editorEvent_data();
230     void editorEvent();
231     void enterKey_data();
232     void enterKey();
233     void comboBox();
234
235     void task257859_finalizeEdit();
236     void QTBUG4435_keepSelectionOnCheck();
237 };
238
239
240 //End of class definitions
241
242 // Testing get/set functions
243 void tst_QItemDelegate::getSetCheck()
244 {
245     QItemDelegate obj1;
246
247     // QItemEditorFactory * QItemDelegate::itemEditorFactory()
248     // void QItemDelegate::setItemEditorFactory(QItemEditorFactory *)
249     QItemEditorFactory *var1 = new QItemEditorFactory;
250     obj1.setItemEditorFactory(var1);
251     QCOMPARE(var1, obj1.itemEditorFactory());
252     obj1.setItemEditorFactory((QItemEditorFactory *)0);
253     QCOMPARE((QItemEditorFactory *)0, obj1.itemEditorFactory());
254     delete var1;
255
256     QCOMPARE(obj1.hasClipping(), true);
257     obj1.setClipping(false);
258     QCOMPARE(obj1.hasClipping(), false);
259     obj1.setClipping(true);
260     QCOMPARE(obj1.hasClipping(), true);
261 }
262
263 tst_QItemDelegate::tst_QItemDelegate()
264 {
265 }
266
267 tst_QItemDelegate::~tst_QItemDelegate()
268 {
269 }
270
271 void tst_QItemDelegate::initTestCase()
272 {
273 }
274
275 void tst_QItemDelegate::cleanupTestCase()
276 {
277 }
278
279 void tst_QItemDelegate::init()
280 {
281 }
282
283 void tst_QItemDelegate::cleanup()
284 {
285 }
286
287 void tst_QItemDelegate::textRectangle_data()
288 {
289     QFont font;
290     QFontMetrics fontMetrics(font);
291     int pm = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
292     int margins = 2 * (pm + 1); // margin on each side of the text
293     int height = fontMetrics.height();
294
295     QTest::addColumn<QString>("text");
296     QTest::addColumn<QRect>("rect");
297     QTest::addColumn<QRect>("expected");
298
299     QTest::newRow("empty") << QString()
300                            << QRect()
301                            << QRect(0, 0, margins, height);
302 }
303
304 void tst_QItemDelegate::textRectangle()
305 {
306     QFETCH(QString, text);
307     QFETCH(QRect, rect);
308     QFETCH(QRect, expected);
309
310     QFont font;
311     TestItemDelegate delegate;
312     QRect result = delegate.textRectangle(0, rect, font, text);
313
314     QCOMPARE(result, expected);
315 }
316
317 void tst_QItemDelegate::sizeHint_data()
318 {
319     QTest::addColumn<QSize>("expected");
320
321     QFont font;
322     QFontMetrics fontMetrics(font);
323     //int m = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
324     QTest::newRow("empty")
325         << QSize(0, fontMetrics.height());
326
327 }
328
329 void tst_QItemDelegate::sizeHint()
330 {
331     QFETCH(QSize, expected);
332
333     QModelIndex index;
334     QStyleOptionViewItem option;
335
336     TestItemDelegate delegate;
337     QSize result = delegate.sizeHint(option, index);
338     QCOMPARE(result, expected);
339 }
340
341 void tst_QItemDelegate::editorKeyPress_data()
342 {
343     QTest::addColumn<QString>("initial");
344     QTest::addColumn<QString>("expected");
345
346     QTest::newRow("foo bar")
347         << QString("foo")
348         << QString("bar");
349 }
350
351 void tst_QItemDelegate::editorKeyPress()
352 {
353     QFETCH(QString, initial);
354     QFETCH(QString, expected);
355
356     QStandardItemModel model;
357     model.appendRow(new QStandardItem(initial));
358
359     QListView view;
360     view.setModel(&model);
361     view.show();
362
363     QModelIndex index = model.index(0, 0);
364     view.setCurrentIndex(index); // the editor will only selectAll on the current index
365     view.edit(index);
366
367     QList<QLineEdit*> lineEditors = qFindChildren<QLineEdit *>(view.viewport());
368     QCOMPARE(lineEditors.count(), 1);
369
370     QLineEdit *editor = lineEditors.at(0);
371     QCOMPARE(editor->selectedText(), initial);
372
373     QTest::keyClicks(editor, expected);
374     QTest::keyClick(editor, Qt::Key_Enter);
375     QApplication::processEvents();
376
377     QCOMPARE(index.data().toString(), expected);
378 }
379
380 void tst_QItemDelegate::doubleEditorNegativeInput()
381 {
382     QStandardItemModel model;
383
384     QStandardItem *item = new QStandardItem;
385     item->setData(10.0, Qt::DisplayRole);
386     model.appendRow(item);
387
388     QListView view;
389     view.setModel(&model);
390     view.show();
391
392     QModelIndex index = model.index(0, 0);
393     view.setCurrentIndex(index); // the editor will only selectAll on the current index
394     view.edit(index);
395
396     QList<QDoubleSpinBox*> editors = qFindChildren<QDoubleSpinBox *>(view.viewport());
397     QCOMPARE(editors.count(), 1);
398
399     QDoubleSpinBox *editor = editors.at(0);
400     QCOMPARE(editor->value(), double(10));
401
402     QTest::keyClick(editor, Qt::Key_Minus);
403     QTest::keyClick(editor, Qt::Key_1);
404     QTest::keyClick(editor, Qt::Key_0);
405     QTest::keyClick(editor, Qt::Key_Comma); //support both , and . locales
406     QTest::keyClick(editor, Qt::Key_Period);
407     QTest::keyClick(editor, Qt::Key_0);
408     QTest::keyClick(editor, Qt::Key_Enter);
409     QApplication::processEvents();
410
411     QCOMPARE(index.data().toString(), QString("-10"));
412 }
413
414 void tst_QItemDelegate::font_data()
415 {
416     QTest::addColumn<QString>("itemText");
417     QTest::addColumn<QString>("properties");
418     QTest::addColumn<QFont>("itemFont");
419     QTest::addColumn<QFont>("viewFont");
420
421     QFont itemFont;
422     itemFont.setItalic(true);
423     QFont viewFont;
424
425     QTest::newRow("foo italic")
426         << QString("foo")
427         << QString("italic")
428         << itemFont
429         << viewFont;
430
431     itemFont.setItalic(true);
432
433     QTest::newRow("foo bold")
434         << QString("foo")
435         << QString("bold")
436         << itemFont
437         << viewFont;
438
439     itemFont.setFamily(itemFont.defaultFamily());
440
441     QTest::newRow("foo family")
442         << QString("foo")
443         << QString("family")
444         << itemFont
445         << viewFont;
446  }
447
448 void tst_QItemDelegate::font()
449 {
450     Q_CHECK_PAINTEVENTS
451
452     QFETCH(QString, itemText);
453     QFETCH(QString, properties);
454     QFETCH(QFont, itemFont);
455     QFETCH(QFont, viewFont);
456
457     QTableWidget table(1, 1);
458     table.setFont(viewFont);
459
460     TestItemDelegate *delegate = new TestItemDelegate(&table);
461     table.setItemDelegate(delegate);
462     table.show();
463     QVERIFY(QTest::qWaitForWindowExposed(&table));
464
465     QTableWidgetItem *item = new QTableWidgetItem;
466     item->setText(itemText);
467     item->setFont(itemFont);
468     table.setItem(0, 0, item);
469
470     QApplication::processEvents();
471 #ifdef Q_WS_QWS
472     QApplication::sendPostedEvents(); //glib workaround
473 #endif
474
475     QTRY_COMPARE(delegate->displayText, item->text());
476     if (properties.contains("italic")) {
477         QCOMPARE(delegate->displayFont.italic(), item->font().italic());
478     }
479     if (properties.contains("bold")){
480         QCOMPARE(delegate->displayFont.bold(), item->font().bold());
481     }
482     if (properties.contains("family")){
483         QCOMPARE(delegate->displayFont.family(), item->font().family());
484     }
485 }
486
487 //Testing the different QRect created by the doLayout function.
488 //Tests are made with different values for the QStyleOptionViewItem properties:
489 //decorationPosition and position.
490
491 void tst_QItemDelegate::doLayout_data()
492 {
493     QTest::addColumn<int>("position");
494     QTest::addColumn<int>("direction");
495     QTest::addColumn<bool>("hint");
496     QTest::addColumn<QRect>("itemRect");
497     QTest::addColumn<QRect>("checkRect");
498     QTest::addColumn<QRect>("pixmapRect");
499     QTest::addColumn<QRect>("textRect");
500     QTest::addColumn<QRect>("expectedCheckRect");
501     QTest::addColumn<QRect>("expectedPixmapRect");
502     QTest::addColumn<QRect>("expectedTextRect");
503
504     int m = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
505     //int item = 400;
506     //int check = 50;
507     //int pixmap = 1000;
508     //int text = 400;
509
510     QTest::newRow("top, left to right, hint")
511         << (int)QStyleOptionViewItem::Top
512         << (int)Qt::LeftToRight
513         << true
514         << QRect(0, 0, 400, 400)
515         << QRect(0, 0, 50, 50)
516         << QRect(0, 0, 1000, 1000)
517         << QRect(0, 0, 400, 400)
518         << QRect(m, 0, 50 + 2*m, 1000)
519         << QRect(50 + 2*m, 0, 1000 + 2*m, 1000 + m)
520         << QRect(50 + 2*m, 1000 + m, 1000 + 2*m, 400);
521     /*
522     QTest::newRow("top, left to right, limited")
523         << (int)QStyleOptionViewItem::Top
524         << (int)Qt::LeftToRight
525         << false
526         << QRect(0, 0, 400, 400)
527         << QRect(0, 0, 50, 50)
528         << QRect(0, 0, 1000, 1000)
529         << QRect(0, 0, 400, 400)
530         << QRect(m, (400/2) - (50/2), 50, 50)
531         << QRect(50 + 2*m, 0, 1000, 1000)
532         << QRect(50 + 2*m, 1000 + m, 400 - (50 + 2*m), 400 - 1000 - m);
533     */
534     QTest::newRow("top, right to left, hint")
535         << (int)QStyleOptionViewItem::Top
536         << (int)Qt::RightToLeft
537         << true
538         << QRect(0, 0, 400, 400)
539         << QRect(0, 0, 50, 50)
540         << QRect(0, 0, 1000, 1000)
541         << QRect(0, 0, 400, 400)
542         << QRect(1000 + 2 * m, 0, 50 + 2 * m, 1000)
543         << QRect(0, 0, 1000 + 2 * m, 1000 + m)
544         << QRect(0, 1000 + m, 1000 + 2 * m, 400);
545
546     QTest::newRow("bottom, left to right, hint")
547         << (int)QStyleOptionViewItem::Bottom
548         << (int)Qt::LeftToRight
549         << true
550         << QRect(0, 0, 400, 400)
551         << QRect(0, 0, 50, 50)
552         << QRect(0, 0, 1000, 1000)
553         << QRect(0, 0, 400, 400)
554         << QRect(m, 0, 50 + 2 * m, 1000)
555         << QRect(50 + 2 * m, 400 + m, 1000 + 2 * m, 1000)
556         << QRect(50 + 2 * m, 0, 1000 + 2 * m, 400 + m);
557
558     QTest::newRow("bottom, right to left, hint")
559         << (int)QStyleOptionViewItem::Bottom
560         << (int)Qt::RightToLeft
561         << true
562         << QRect(0, 0, 400, 400)
563         << QRect(0, 0, 50, 50)
564         << QRect(0, 0, 1000, 1000)
565         << QRect(0, 0, 400, 400)
566         << QRect(1000 + 2 * m, 0, 50 + 2 * m, 1000)
567         << QRect(0, 400 + m, 1000 + 2 * m, 1000)
568         << QRect(0, 0, 1000 + 2 * m, 400 + m);
569
570     QTest::newRow("left, left to right, hint")
571         << (int)QStyleOptionViewItem::Left
572         << (int)Qt::LeftToRight
573         << true
574         << QRect(0, 0, 400, 400)
575         << QRect(0, 0, 50, 50)
576         << QRect(0, 0, 1000, 1000)
577         << QRect(0, 0, 400, 400)
578         << QRect(m, 0, 50 + 2 * m, 1000)
579         << QRect(50 + 2 * m, 0, 1000 + 2 * m, 1000)
580         << QRect(1050 + 4 * m, 0, 400 + 2 * m, 1000);
581
582     QTest::newRow("left, right to left, hint")
583         << (int)QStyleOptionViewItem::Left
584         << (int)Qt::RightToLeft
585         << true
586         << QRect(0, 0, 400, 400)
587         << QRect(0, 0, 50, 50)
588         << QRect(0, 0, 1000, 1000)
589         << QRect(0, 0, 400, 400)
590         << QRect(1400 + 4 * m, 0, 50 + 2 * m, 1000)
591         << QRect(400 + 2 * m, 0, 1000 + 2 * m, 1000)
592         << QRect(0, 0, 400 + 2 * m, 1000);
593
594     QTest::newRow("right, left to right, hint")
595         << (int)QStyleOptionViewItem::Right
596         << (int)Qt::LeftToRight
597         << true
598         << QRect(0, 0, 400, 400)
599         << QRect(0, 0, 50, 50)
600         << QRect(0, 0, 1000, 1000)
601         << QRect(0, 0, 400, 400)
602         << QRect(m, 0, 50 + 2 * m, 1000)
603         << QRect(450 + 4 * m, 0, 1000 + 2 * m, 1000)
604         << QRect(50 + 2 * m, 0, 400 + 2 * m, 1000);
605
606     QTest::newRow("right, right to left, hint")
607         << (int)QStyleOptionViewItem::Right
608         << (int)Qt::RightToLeft
609         << true
610         << QRect(0, 0, 400, 400)
611         << QRect(0, 0, 50, 50)
612         << QRect(0, 0, 1000, 1000)
613         << QRect(0, 0, 400, 400)
614         << QRect(1400 + 4 * m, 0, 50 + 2 * m, 1000)
615         << QRect(0, 0, 1000 + 2 * m, 1000)
616         << QRect(1000 + 2 * m, 0, 400 + 2 * m, 1000);
617 }
618
619 void tst_QItemDelegate::doLayout()
620 {
621     QFETCH(int, position);
622     QFETCH(int, direction);
623     QFETCH(bool, hint);
624     QFETCH(QRect, itemRect);
625     QFETCH(QRect, checkRect);
626     QFETCH(QRect, pixmapRect);
627     QFETCH(QRect, textRect);
628     QFETCH(QRect, expectedCheckRect);
629     QFETCH(QRect, expectedPixmapRect);
630     QFETCH(QRect, expectedTextRect);
631
632     TestItemDelegate delegate;
633     QStyleOptionViewItem option;
634
635     option.rect = itemRect;
636     option.decorationPosition = (QStyleOptionViewItem::Position)position;
637     option.direction = (Qt::LayoutDirection)direction;
638
639     delegate.doLayout(option, &checkRect, &pixmapRect, &textRect, hint);
640
641     QCOMPARE(checkRect, expectedCheckRect);
642     QCOMPARE(pixmapRect, expectedPixmapRect);
643     QCOMPARE(textRect, expectedTextRect);
644 }
645
646 void tst_QItemDelegate::rect_data()
647 {
648     QTest::addColumn<int>("role");
649     QTest::addColumn<QSize>("size");
650     QTest::addColumn<QRect>("expected");
651
652     QTest::newRow("pixmap")
653         << (int)TestItemModel::PixmapTestRole
654         << QSize(200, 300)
655         << QRect(0, 0, 200, 300);
656
657     QTest::newRow("image")
658         << (int)TestItemModel::ImageTestRole
659         << QSize(200, 300)
660         << QRect(0, 0, 200, 300);
661
662     QTest::newRow("icon")
663         << (int)TestItemModel::IconTestRole
664         << QSize(200, 300)
665         << QRect(0, 0, 200, 300);
666
667     QTest::newRow("color")
668         << (int)TestItemModel::ColorTestRole
669         << QSize(200, 300)
670         << QRect(0, 0, 200, 300);
671
672     QTest::newRow("double")
673             << (int)TestItemModel::DoubleTestRole
674             << QSize()
675             << QRect();
676 }
677
678 void tst_QItemDelegate::rect()
679 {
680     QFETCH(int, role);
681     QFETCH(QSize, size);
682     QFETCH(QRect, expected);
683
684     TestItemModel model(size);
685     QStyleOptionViewItem option;
686     TestItemDelegate delegate;
687     option.decorationSize = size;
688
689     if (role == TestItemModel::DoubleTestRole)
690         expected = delegate.textRectangle(0, QRect(), QFont(), QLatin1String("10.00000001"));
691
692     QModelIndex index = model.index(0, 0);
693     QVERIFY(index.isValid());
694     QRect result = delegate.rect(option, index, role);
695     QCOMPARE(result, expected);
696 }
697
698 //TODO : Add a test for the keyPress event
699 //with Qt::Key_Enter and Qt::Key_Return
700 void tst_QItemDelegate::eventFilter()
701 {
702     TestItemDelegate delegate;
703     QWidget widget;
704     QEvent *event;
705
706     qRegisterMetaType<QAbstractItemDelegate::EndEditHint>("QAbstractItemDelegate::EndEditHint");
707
708     QSignalSpy commitDataSpy(&delegate, SIGNAL(commitData(QWidget *)));
709     QSignalSpy closeEditorSpy(&delegate,
710                               SIGNAL(closeEditor(QWidget *,
711                                                  QAbstractItemDelegate::EndEditHint)));
712
713     //Subtest KeyPress
714     //For each test we send a key event and check if signals were emitted.
715     event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
716     QVERIFY(delegate.eventFilter(&widget, event));
717     QCOMPARE(closeEditorSpy.count(), 1);
718     QCOMPARE(commitDataSpy.count(), 1);
719     delete event;
720
721     event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier);
722     QVERIFY(delegate.eventFilter(&widget, event));
723     QCOMPARE(closeEditorSpy.count(), 2);
724     QCOMPARE(commitDataSpy.count(), 2);
725     delete event;
726
727     event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
728     QVERIFY(delegate.eventFilter(&widget, event));
729     QCOMPARE(closeEditorSpy.count(), 3);
730     QCOMPARE(commitDataSpy.count(), 2);
731     delete event;
732
733     event = new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
734     QVERIFY(!delegate.eventFilter(&widget, event));
735     QCOMPARE(closeEditorSpy.count(), 3);
736     QCOMPARE(commitDataSpy.count(), 2);
737     delete event;
738
739     //Subtest focusEvent
740     event = new QFocusEvent(QEvent::FocusOut);
741     QVERIFY(!delegate.eventFilter(&widget, event));
742     QCOMPARE(closeEditorSpy.count(), 4);
743     QCOMPARE(commitDataSpy.count(), 3);
744     delete event;
745 }
746
747 void tst_QItemDelegate::dateTimeEditor_data()
748 {
749     QTest::addColumn<QTime>("time");
750     QTest::addColumn<QDate>("date");
751
752     QTest::newRow("data")
753         << QTime(7, 16, 34)
754         << QDate(2006, 10, 31);
755 }
756
757 void tst_QItemDelegate::dateTimeEditor()
758 {
759     QFETCH(QTime, time);
760     QFETCH(QDate, date);
761
762     QTableWidgetItem *item1 = new QTableWidgetItem;
763     item1->setData(Qt::DisplayRole, time);
764
765     QTableWidgetItem *item2 = new QTableWidgetItem;
766     item2->setData(Qt::DisplayRole, date);
767
768     QTableWidgetItem *item3 = new QTableWidgetItem;
769     item3->setData(Qt::DisplayRole, QDateTime(date, time));
770
771     QTableWidget widget(1, 3);
772     widget.setItem(0, 0, item1);
773     widget.setItem(0, 1, item2);
774     widget.setItem(0, 2, item3);
775     widget.show();
776
777     widget.editItem(item1);
778
779     QTestEventLoop::instance().enterLoop(1);
780
781     QTimeEdit *timeEditor = qFindChild<QTimeEdit *>(widget.viewport());
782     QVERIFY(timeEditor);
783     QCOMPARE(timeEditor->time(), time);
784     // The data must actually be different in order for the model
785     // to be updated.
786     timeEditor->setTime(time.addSecs(60));
787
788     widget.clearFocus();
789     qApp->setActiveWindow(&widget);
790     widget.setFocus();
791     widget.editItem(item2);
792
793     QTestEventLoop::instance().enterLoop(1);
794
795     QDateEdit *dateEditor = qFindChild<QDateEdit *>(widget.viewport());
796     QVERIFY(dateEditor);
797     QCOMPARE(dateEditor->date(), date);
798     dateEditor->setDate(date.addDays(60));
799
800     widget.clearFocus();
801     widget.setFocus();
802     widget.editItem(item3);
803
804     QTestEventLoop::instance().enterLoop(1);
805
806     QList<QDateTimeEdit *> dateTimeEditors = widget.findChildren<QDateTimeEdit *>();
807     QDateTimeEdit *dateTimeEditor = 0;
808     foreach(dateTimeEditor, dateTimeEditors)
809         if (dateTimeEditor->metaObject()->className() == QLatin1String("QDateTimeEdit"))
810             break;
811     QVERIFY(dateTimeEditor);
812     QCOMPARE(dateTimeEditor->date(), date);
813     QCOMPARE(dateTimeEditor->time(), time);
814     dateTimeEditor->setTime(time.addSecs(600));
815     widget.clearFocus();
816
817     QVERIFY(item1->data(Qt::EditRole).userType() == QMetaType::QTime);
818     QVERIFY(item2->data(Qt::EditRole).userType() == QMetaType::QDate);
819     QVERIFY(item3->data(Qt::EditRole).userType() == QMetaType::QDateTime);
820 }
821
822 // A delegate where we can either enforce a certain widget or use the standard widget.
823 class ChooseEditorDelegate : public QItemDelegate
824 {
825 public:
826     virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &o, const QModelIndex &i) const
827     {
828         if (m_editor) {
829             m_editor->setParent(parent);
830             return m_editor;
831         }
832         m_editor = QItemDelegate::createEditor(parent, o, i);
833         return m_editor;
834     }
835
836     virtual void destroyEditor(QWidget *editor, const QModelIndex &i) const
837     {   // This is a reimplementation of QAbstractItemDelegate::destroyEditor just set the variable m_editor to 0
838         // The only reason we do this is to avoid the not recommended direct delete of editor (destroyEditor uses deleteLater)
839         QItemDelegate::destroyEditor(editor, i); // Allow destroy
840         m_editor = 0;                            // but clear the variable
841     }
842
843     ChooseEditorDelegate(QObject *parent = 0) : QItemDelegate(parent) { }
844     void setNextOpenEditor(QWidget *w) { m_editor = w; }
845     QWidget* currentEditor() const { return m_editor; }
846 private:
847     mutable QPointer<QWidget> m_editor;
848 };
849
850 // We could (nearly) use a normal QTableView but in order not to add many seconds to the autotest
851 // (and save a few lines) we do this
852 class FastEditItemView : public QTableView
853 {
854 public:
855     QWidget* fastEdit(const QModelIndex &i) // Consider this as QAbstractItemView::edit( )
856     {
857         QWidget *v = itemDelegate()->createEditor(viewport(), viewOptions(), i);
858         if (v)
859             itemDelegate()->setEditorData(v, i);
860         return v;
861     }
862     void doCloseEditor(QWidget *editor) // Consider this as QAbstractItemView::closeEditor( )
863     {
864         itemDelegate()->destroyEditor(editor, QModelIndex());
865     }
866 };
867
868 void tst_QItemDelegate::dateAndTimeEditorTest2()
869 {
870     // prepare createeditor
871     FastEditItemView w;
872     QStandardItemModel s;
873     s.setRowCount(2);
874     s.setColumnCount(1);
875     w.setModel(&s);
876     ChooseEditorDelegate *d = new ChooseEditorDelegate(&w);
877     w.setItemDelegate(d);
878     const QTime time1(3, 13, 37);
879     const QDate date1(2013, 3, 7);
880
881     QPointer<QTimeEdit> timeEdit;
882     QPointer<QDateEdit> dateEdit;
883     QPointer<QDateTimeEdit> dateTimeEdit;
884
885     // Do some checks
886     // a. Open time editor on empty cell + write QTime data
887     const QModelIndex i1 = s.index(0, 0);
888     timeEdit = new QTimeEdit();
889     d->setNextOpenEditor(timeEdit);
890     QCOMPARE(w.fastEdit(i1), timeEdit.data());
891     timeEdit->setTime(time1);
892     d->setModelData(timeEdit, &s, i1);
893     QCOMPARE(s.data(i1).type(), QVariant::Time); // ensure that we wrote a time variant.
894     QCOMPARE(s.data(i1).toTime(), time1);        // ensure that it is the correct time.
895     w.doCloseEditor(timeEdit);
896     QVERIFY(d->currentEditor() == 0); // should happen at doCloseEditor. We only test this once.
897
898     // b. Test that automatic edit of a QTime value is QTimeEdit (and not QDateTimeEdit)
899     QWidget *editor = w.fastEdit(i1);
900     timeEdit = qobject_cast<QTimeEdit*>(editor);
901     QVERIFY(timeEdit);
902     QCOMPARE(timeEdit->time(), time1);
903     w.doCloseEditor(timeEdit);
904
905     const QTime time2(4, 14, 37);
906     const QDate date2(2014, 4, 7);
907     const QDateTime datetime1(date1, time1);
908     const QDateTime datetime2(date2, time2);
909
910     // c. Test that the automatic open of an QDateTime is QDateTimeEdit + value check + set check
911     s.setData(i1, datetime2);
912     editor = w.fastEdit(i1);
913     timeEdit = qobject_cast<QTimeEdit*>(editor);
914     QVERIFY(timeEdit == 0);
915     dateEdit = qobject_cast<QDateEdit*>(editor);
916     QVERIFY(dateEdit == 0);
917     dateTimeEdit =  qobject_cast<QDateTimeEdit*>(editor);
918     QVERIFY(dateTimeEdit);
919     QCOMPARE(dateTimeEdit->dateTime(), datetime2);
920     dateTimeEdit->setDateTime(datetime1);
921     d->setModelData(dateTimeEdit, &s, i1);
922     QCOMPARE(s.data(i1).type(), QVariant::DateTime); // ensure that we wrote a datetime variant.
923     QCOMPARE(s.data(i1).toDateTime(), datetime1);
924     w.doCloseEditor(dateTimeEdit);
925
926     // d. Open date editor on empty cell + write QDate data (similar to a)
927     const QModelIndex i2 = s.index(1, 0);
928     dateEdit = new QDateEdit();
929     d->setNextOpenEditor(dateEdit);
930     QCOMPARE(w.fastEdit(i2), dateEdit.data());
931     dateEdit->setDate(date1);
932     d->setModelData(dateEdit, &s, i2);
933     QCOMPARE(s.data(i2).type(), QVariant::Date); // ensure that we wrote a time variant.
934     QCOMPARE(s.data(i2).toDate(), date1);        // ensure that it is the correct date.
935     w.doCloseEditor(dateEdit);
936
937     // e. Test that the default editor editor (QDateEdit) on a QDate (index i2)  (similar to b)
938     editor = w.fastEdit(i2);
939     dateEdit = qobject_cast<QDateEdit*>(editor);
940     QVERIFY(dateEdit);
941     QCOMPARE(dateEdit->date(), date1);
942     w.doCloseEditor(dateEdit);
943 }
944
945 void tst_QItemDelegate::decoration_data()
946 {
947     QTest::addColumn<int>("type");
948     QTest::addColumn<QSize>("size");
949     QTest::addColumn<QSize>("expected");
950
951     int pm = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
952
953     QTest::newRow("pixmap 30x30")
954         << (int)QVariant::Pixmap
955         << QSize(30, 30)
956         << QSize(30, 30);
957
958     QTest::newRow("image 30x30")
959         << (int)QVariant::Image
960         << QSize(30, 30)
961         << QSize(30, 30);
962
963 //The default engine scales pixmaps down if required, but never up. For WinCE we need bigger IconSize than 30
964     QTest::newRow("icon 30x30")
965         << (int)QVariant::Icon
966         << QSize(60, 60)
967         << QSize(pm, pm);
968
969     QTest::newRow("color 30x30")
970         << (int)QVariant::Color
971         << QSize(30, 30)
972         << QSize(pm, pm);
973
974     // This demands too much memory and potentially hangs. Feel free to uncomment
975     // for your own testing.
976 //    QTest::newRow("pixmap 30x30 big")
977 //        << (int)QVariant::Pixmap
978 //        << QSize(1024, 1024)        // Over 1M
979 //        << QSize(1024, 1024);
980 }
981
982 void tst_QItemDelegate::decoration()
983 {
984     Q_CHECK_PAINTEVENTS
985
986     QFETCH(int, type);
987     QFETCH(QSize, size);
988     QFETCH(QSize, expected);
989
990     QTableWidget table(1, 1);
991     TestItemDelegate delegate;
992     table.setItemDelegate(&delegate);
993     table.show();
994     QApplication::setActiveWindow(&table);
995     QVERIFY(QTest::qWaitForWindowActive(&table));
996
997     QVariant value;
998     switch ((QVariant::Type)type) {
999     case QVariant::Pixmap: {
1000         QPixmap pm(size);
1001         pm.fill(Qt::black);
1002         value = pm;
1003         break;
1004     }
1005     case QVariant::Image: {
1006         QImage img(size, QImage::Format_Mono);
1007         memset(img.bits(), 0, img.byteCount());
1008         value = img;
1009         break;
1010     }
1011     case QVariant::Icon: {
1012         QPixmap pm(size);
1013         pm.fill(Qt::black);
1014         value = QIcon(pm);
1015         break;
1016     }
1017     case QVariant::Color:
1018         value = QColor(Qt::green);
1019         break;
1020     default:
1021         break;
1022     }
1023
1024     QTableWidgetItem *item = new QTableWidgetItem;
1025     item->setData(Qt::DecorationRole, value);
1026     table.setItem(0, 0, item);
1027     item->setSelected(true);
1028
1029     QApplication::processEvents();
1030
1031     QTRY_COMPARE(delegate.decorationRect.size(), expected);
1032 }
1033
1034 void tst_QItemDelegate::editorEvent_data()
1035 {
1036     QTest::addColumn<QRect>("rect");
1037     QTest::addColumn<QString>("text");
1038     QTest::addColumn<int>("checkState");
1039     QTest::addColumn<int>("flags");
1040     QTest::addColumn<bool>("inCheck");
1041     QTest::addColumn<int>("type");
1042     QTest::addColumn<int>("button");
1043     QTest::addColumn<bool>("edited");
1044     QTest::addColumn<int>("expectedCheckState");
1045
1046     QTest::newRow("unchecked, checkable, release")
1047         << QRect(0, 0, 20, 20)
1048         << QString("foo")
1049         << (int)(Qt::Unchecked)
1050         << (int)(Qt::ItemIsEditable
1051             |Qt::ItemIsSelectable
1052             |Qt::ItemIsUserCheckable
1053             |Qt::ItemIsEnabled
1054             |Qt::ItemIsDragEnabled
1055             |Qt::ItemIsDropEnabled)
1056         << true
1057         << (int)(QEvent::MouseButtonRelease)
1058         << (int)(Qt::LeftButton)
1059         << true
1060         << (int)(Qt::Checked);
1061
1062     QTest::newRow("checked, checkable, release")
1063         << QRect(0, 0, 20, 20)
1064         << QString("foo")
1065         << (int)(Qt::Checked)
1066         << (int)(Qt::ItemIsEditable
1067             |Qt::ItemIsSelectable
1068             |Qt::ItemIsUserCheckable
1069             |Qt::ItemIsEnabled
1070             |Qt::ItemIsDragEnabled
1071             |Qt::ItemIsDropEnabled)
1072         << true
1073         << (int)(QEvent::MouseButtonRelease)
1074         << (int)(Qt::LeftButton)
1075         << true
1076         << (int)(Qt::Unchecked);
1077
1078     QTest::newRow("unchecked, checkable, release")
1079         << QRect(0, 0, 20, 20)
1080         << QString("foo")
1081         << (int)(Qt::Unchecked)
1082         << (int)(Qt::ItemIsEditable
1083             |Qt::ItemIsSelectable
1084             |Qt::ItemIsUserCheckable
1085             |Qt::ItemIsEnabled
1086             |Qt::ItemIsDragEnabled
1087             |Qt::ItemIsDropEnabled)
1088         << true
1089         << (int)(QEvent::MouseButtonRelease)
1090         << (int)(Qt::LeftButton)
1091         << true
1092         << (int)(Qt::Checked);
1093
1094     QTest::newRow("unchecked, checkable, release, right button")
1095         << QRect(0, 0, 20, 20)
1096         << QString("foo")
1097         << (int)(Qt::Unchecked)
1098         << (int)(Qt::ItemIsEditable
1099             |Qt::ItemIsSelectable
1100             |Qt::ItemIsUserCheckable
1101             |Qt::ItemIsEnabled
1102             |Qt::ItemIsDragEnabled
1103             |Qt::ItemIsDropEnabled)
1104         << true
1105         << (int)(QEvent::MouseButtonRelease)
1106         << (int)(Qt::RightButton)
1107         << false
1108         << (int)(Qt::Unchecked);
1109
1110     QTest::newRow("unchecked, checkable, release outside")
1111         << QRect(0, 0, 20, 20)
1112         << QString("foo")
1113         << (int)(Qt::Unchecked)
1114         << (int)(Qt::ItemIsEditable
1115             |Qt::ItemIsSelectable
1116             |Qt::ItemIsUserCheckable
1117             |Qt::ItemIsEnabled
1118             |Qt::ItemIsDragEnabled
1119             |Qt::ItemIsDropEnabled)
1120         << false
1121         << (int)(QEvent::MouseButtonRelease)
1122         << (int)(Qt::LeftButton)
1123         << false
1124         << (int)(Qt::Unchecked);
1125
1126     QTest::newRow("unchecked, checkable, dblclick")
1127         << QRect(0, 0, 20, 20)
1128         << QString("foo")
1129         << (int)(Qt::Unchecked)
1130         << (int)(Qt::ItemIsEditable
1131             |Qt::ItemIsSelectable
1132             |Qt::ItemIsUserCheckable
1133             |Qt::ItemIsEnabled
1134             |Qt::ItemIsDragEnabled
1135             |Qt::ItemIsDropEnabled)
1136         << true
1137         << (int)(QEvent::MouseButtonDblClick)
1138         << (int)(Qt::LeftButton)
1139         << true
1140         << (int)(Qt::Unchecked);
1141 }
1142
1143 void tst_QItemDelegate::editorEvent()
1144 {
1145     QFETCH(QRect, rect);
1146     QFETCH(QString, text);
1147     QFETCH(int, checkState);
1148     QFETCH(int, flags);
1149     QFETCH(bool, inCheck);
1150     QFETCH(int, type);
1151     QFETCH(int, button);
1152     QFETCH(bool, edited);
1153     QFETCH(int, expectedCheckState);
1154
1155     QStandardItemModel model(1, 1);
1156     QModelIndex index = model.index(0, 0);
1157     QVERIFY(index.isValid());
1158
1159     QStandardItem *item = model.itemFromIndex(index);
1160     item->setText(text);
1161     item->setCheckState((Qt::CheckState)checkState);
1162     item->setFlags((Qt::ItemFlags)flags);
1163
1164     QStyleOptionViewItem option;
1165     option.rect = rect;
1166     option.state |= QStyle::State_Enabled;
1167     // mimic QStyledItemDelegate::initStyleOption logic
1168     option.features |= QStyleOptionViewItem::HasCheckIndicator | QStyleOptionViewItem::HasDisplay;
1169     option.checkState = Qt::CheckState(checkState);
1170
1171     const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
1172     QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200);
1173
1174     QEvent *event = new QMouseEvent((QEvent::Type)type,
1175                                     pos,
1176                                     (Qt::MouseButton)button,
1177                                     (Qt::MouseButton)button,
1178                                     Qt::NoModifier);
1179     TestItemDelegate delegate;
1180     bool wasEdited = delegate.editorEvent(event, &model, option, index);
1181     delete event;
1182
1183     QApplication::processEvents();
1184
1185     QCOMPARE(wasEdited, edited);
1186     QCOMPARE(index.data(Qt::CheckStateRole).toInt(), expectedCheckState);
1187 }
1188
1189 enum WidgetType
1190 {
1191     LineEdit,
1192     TextEdit,
1193     PlainTextEdit
1194 };
1195 Q_DECLARE_METATYPE(WidgetType);
1196
1197 void tst_QItemDelegate::enterKey_data()
1198 {
1199     QTest::addColumn<WidgetType>("widget");
1200     QTest::addColumn<int>("key");
1201     QTest::addColumn<bool>("expectedFocus");
1202
1203     QTest::newRow("lineedit enter") << LineEdit << int(Qt::Key_Enter) << false;
1204     QTest::newRow("textedit enter") << TextEdit << int(Qt::Key_Enter) << true;
1205     QTest::newRow("plaintextedit enter") << PlainTextEdit << int(Qt::Key_Enter) << true;
1206     QTest::newRow("plaintextedit return") << PlainTextEdit << int(Qt::Key_Return) << true;
1207     QTest::newRow("plaintextedit tab") << PlainTextEdit << int(Qt::Key_Tab) << false;
1208     QTest::newRow("lineedit tab") << LineEdit << int(Qt::Key_Tab) << false;
1209 }
1210
1211 void tst_QItemDelegate::enterKey()
1212 {
1213     QFETCH(WidgetType, widget);
1214     QFETCH(int, key);
1215     QFETCH(bool, expectedFocus);
1216
1217     QStandardItemModel model;
1218     model.appendRow(new QStandardItem());
1219
1220     QListView view;
1221     view.setModel(&model);
1222     view.show();
1223     QApplication::setActiveWindow(&view);
1224     view.setFocus();
1225     QTest::qWait(30);
1226
1227     struct TestDelegate : public QItemDelegate
1228     {
1229         WidgetType widgetType;
1230         virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
1231         {
1232             QWidget *editor = 0;
1233             switch(widgetType) {
1234                 case LineEdit:
1235                     editor = new QLineEdit(parent);
1236                     break;
1237                 case TextEdit:
1238                     editor = new QTextEdit(parent);
1239                     break;
1240                 case PlainTextEdit:
1241                     editor = new QPlainTextEdit(parent);
1242                     break;
1243             }
1244             editor->setObjectName(QString::fromLatin1("TheEditor"));
1245             return editor;
1246         }
1247     } delegate;
1248
1249     delegate.widgetType = widget;
1250
1251     view.setItemDelegate(&delegate);
1252     QModelIndex index = model.index(0, 0);
1253     view.setCurrentIndex(index); // the editor will only selectAll on the current index
1254     view.edit(index);
1255     QTest::qWait(30);
1256
1257     QList<QWidget*> lineEditors = qFindChildren<QWidget *>(view.viewport(), QString::fromLatin1("TheEditor"));
1258     QCOMPARE(lineEditors.count(), 1);
1259
1260     QPointer<QWidget> editor = lineEditors.at(0);
1261     QCOMPARE(editor->hasFocus(), true);
1262
1263     QTest::keyClick(editor, Qt::Key(key));
1264     QApplication::processEvents();
1265
1266     // The line edit has already been destroyed, so avoid that case.
1267     if (widget == TextEdit || widget == PlainTextEdit) {
1268         QVERIFY(!editor.isNull());
1269         QCOMPARE(editor && editor->hasFocus(), expectedFocus);
1270     }
1271 }
1272
1273 void tst_QItemDelegate::task257859_finalizeEdit()
1274 {
1275     QStandardItemModel model;
1276     model.appendRow(new QStandardItem());
1277
1278     QListView view;
1279     view.setModel(&model);
1280     view.show();
1281     QApplication::setActiveWindow(&view);
1282     view.setFocus();
1283     QTest::qWait(30);
1284
1285     QModelIndex index = model.index(0, 0);
1286     view.edit(index);
1287     QTest::qWait(30);
1288
1289     QList<QLineEdit *> lineEditors = qFindChildren<QLineEdit *>(view.viewport());
1290     QCOMPARE(lineEditors.count(), 1);
1291
1292     QPointer<QWidget> editor = lineEditors.at(0);
1293     QCOMPARE(editor->hasFocus(), true);
1294
1295     QDialog dialog;
1296     QTimer::singleShot(500, &dialog, SLOT(close()));
1297     dialog.exec();
1298     QTRY_VERIFY(!editor);
1299 }
1300
1301 void tst_QItemDelegate::QTBUG4435_keepSelectionOnCheck()
1302 {
1303     QStandardItemModel model(3, 1);
1304     for (int i = 0; i < 3; ++i) {
1305         QStandardItem *item = new QStandardItem(QLatin1String("Item ") + QString::number(i));
1306         item->setCheckable(true);
1307         item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
1308         model.setItem(i, item);
1309     }
1310     QTableView view;
1311     view.setModel(&model);
1312     view.setItemDelegate(new TestItemDelegate);
1313     view.show();
1314     view.selectAll();
1315     QVERIFY(QTest::qWaitForWindowExposed(&view));
1316     QStyleOptionViewItem option;
1317     option.rect = view.visualRect(model.index(0, 0));
1318     // mimic QStyledItemDelegate::initStyleOption logic
1319     option.features = QStyleOptionViewItem::HasDisplay | QStyleOptionViewItem::HasCheckIndicator;
1320     option.checkState = Qt::CheckState(model.index(0, 0).data(Qt::CheckStateRole).toInt());
1321     const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
1322     QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center()
1323                  + QPoint(checkMargin, 0);
1324     QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pos);
1325     QTRY_VERIFY(view.selectionModel()->isColumnSelected(0, QModelIndex()));
1326     QCOMPARE(model.item(0)->checkState(), Qt::Checked);
1327 }
1328
1329 void tst_QItemDelegate::comboBox()
1330 {
1331     QTableWidgetItem *item1 = new QTableWidgetItem;
1332     item1->setData(Qt::DisplayRole, true);
1333
1334     QTableWidget widget(1, 1);
1335     widget.setItem(0, 0, item1);
1336     widget.show();
1337
1338     widget.editItem(item1);
1339
1340     QTestEventLoop::instance().enterLoop(1);
1341
1342     QComboBox *boolEditor = qFindChild<QComboBox*>(widget.viewport());
1343     QVERIFY(boolEditor);
1344     QCOMPARE(boolEditor->currentIndex(), 1); // True is selected initially.
1345     // The data must actually be different in order for the model
1346     // to be updated.
1347     boolEditor->setCurrentIndex(0);
1348     QCOMPARE(boolEditor->currentIndex(), 0); // Changed to false.
1349
1350     widget.clearFocus();
1351     widget.setFocus();
1352
1353     QVariant data = item1->data(Qt::EditRole);
1354     QCOMPARE(data.userType(), (int)QMetaType::Bool);
1355     QCOMPARE(data.toBool(), false);
1356 }
1357
1358
1359 // ### _not_ covered:
1360
1361 // editing with a custom editor factory
1362
1363 // painting when editing
1364 // painting elided text
1365 // painting wrapped text
1366 // painting focus
1367 // painting icon
1368 // painting color
1369 // painting check
1370 // painting selected
1371
1372 // rect for invalid
1373 // rect for pixmap
1374 // rect for image
1375 // rect for icon
1376 // rect for check
1377
1378 QTEST_MAIN(tst_QItemDelegate)
1379 #include "tst_qitemdelegate.moc"