summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets
diff options
context:
space:
mode:
authorJo Asplin <jo.asplin@nokia.com>2011-10-20 13:17:26 +0200
committerQt by Nokia <qt-info@nokia.com>2011-10-20 19:45:41 +0200
commit9f1aa866bda7678261f2f441d4cfd5bb524c2411 (patch)
tree5028f578122e7feb9200d571405494c73d96db89 /tests/auto/widgets
parent78d02e93aca5325fc5be9bfd275862795207abaa (diff)
Moved tests into integrationtests/ and widgets/
Task-number: QTBUG-19013 Change-Id: Ibb776f5967c0645ce6d22ef7afdc40657c575461 Reviewed-by: Holger Ihrig <holger.ihrig@nokia.com>
Diffstat (limited to 'tests/auto/widgets')
-rw-r--r--tests/auto/widgets/dialogs/dialogs.pro18
-rw-r--r--tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro9
-rw-r--r--tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp146
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro6
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp164
-rw-r--r--tests/auto/widgets/dialogs/qdialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qdialog/qdialog.pro5
-rw-r--r--tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp609
-rw-r--r--tests/auto/widgets/dialogs/qerrormessage/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro10
-rw-r--r--tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp158
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro23
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/resources/file.txt1
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp1349
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro20
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp1213
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro7
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp1046
-rw-r--r--tests/auto/widgets/dialogs/qfontdialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro12
-rw-r--r--tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp186
-rw-r--r--tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm67
-rw-r--r--tests/auto/widgets/dialogs/qinputdialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro5
-rw-r--r--tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp430
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro9
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp674
-rw-r--r--tests/auto/widgets/dialogs/qprogressdialog/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro9
-rw-r--r--tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp157
-rw-r--r--tests/auto/widgets/dialogs/qsidebar/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qsidebar/qsidebar.pro6
-rw-r--r--tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp231
-rw-r--r--tests/auto/widgets/dialogs/qwizard/.gitignore1
-rw-r--r--tests/auto/widgets/dialogs/qwizard/images/background.pngbin0 -> 22932 bytes
-rw-r--r--tests/auto/widgets/dialogs/qwizard/images/banner.pngbin0 -> 4230 bytes
-rw-r--r--tests/auto/widgets/dialogs/qwizard/images/logo.pngbin0 -> 1661 bytes
-rw-r--r--tests/auto/widgets/dialogs/qwizard/images/watermark.pngbin0 -> 15788 bytes
-rw-r--r--tests/auto/widgets/dialogs/qwizard/qwizard.pro4
-rw-r--r--tests/auto/widgets/dialogs/qwizard/qwizard.qrc8
-rw-r--r--tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp2645
-rw-r--r--tests/auto/widgets/effects/effects.pro4
-rw-r--r--tests/auto/widgets/effects/qgraphicseffect/qgraphicseffect.pro7
-rw-r--r--tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp760
-rw-r--r--tests/auto/widgets/graphicsview/graphicsview.pro32
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp2091
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp3111
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro7
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp422
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp3465
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro9
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp11402
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp192
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro9
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp992
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp376
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp1650
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro7
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp297
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp427
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp349
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro8
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp3649
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpgbin0 -> 4751 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.databin0 -> 854488 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro20
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.pngbin0 -> 2181 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.pngbin0 -> 1953 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.pngbin0 -> 2399 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.pngbin0 -> 1872 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.pngbin0 -> 1884 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.pngbin0 -> 1819 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.pngbin0 -> 1255 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.pngbin0 -> 1896 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.pngbin0 -> 1560 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.pngbin0 -> 1550 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.pngbin0 -> 1566 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.pngbin0 -> 1547 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.pngbin0 -> 1172 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.pngbin0 -> 1690 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.pngbin0 -> 1736 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.pngbin0 -> 1642 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.pngbin0 -> 1093 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.pngbin0 -> 1661 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.pngbin0 -> 1289 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.pngbin0 -> 1823 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.pngbin0 -> 1236 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.pngbin0 -> 1839 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.pngbin0 -> 1174 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.pngbin0 -> 1703 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.pngbin0 -> 1973 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.pngbin0 -> 1650 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.pngbin0 -> 2018 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.pngbin0 -> 1669 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp4710
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp366
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp408
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro9
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp4558
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp976
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro10
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp3361
-rw-r--r--tests/auto/widgets/itemviews/itemviews.pro33
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro3
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp1504
-rw-r--r--tests/auto/widgets/itemviews/qabstractproxymodel/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qabstractproxymodel/qabstractproxymodel.pro3
-rw-r--r--tests/auto/widgets/itemviews/qabstractproxymodel/tst_qabstractproxymodel.cpp449
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/qcolumnview.pro6
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp1040
-rw-r--r--tests/auto/widgets/itemviews/qdatawidgetmapper/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qdatawidgetmapper/qdatawidgetmapper.pro5
-rw-r--r--tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp411
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/dummy1
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/test0
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro20
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/test/file01.tst0
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/test/file02.tst0
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/test/file03.tst0
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/test/file04.tst0
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp698
-rw-r--r--tests/auto/widgets/itemviews/qfileiconprovider/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qfileiconprovider/qfileiconprovider.pro5
-rw-r--r--tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp181
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/qheaderview.pro8
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp2135
-rw-r--r--tests/auto/widgets/itemviews/qidentityproxymodel/qidentityproxymodel.pro7
-rw-r--r--tests/auto/widgets/itemviews/qidentityproxymodel/tst_qidentityproxymodel.cpp333
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro6
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp1216
-rw-r--r--tests/auto/widgets/itemviews/qitemeditorfactory/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qitemeditorfactory/qitemeditorfactory.pro5
-rw-r--r--tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp105
-rw-r--r--tests/auto/widgets/itemviews/qitemselectionmodel/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qitemselectionmodel/qitemselectionmodel.pro5
-rw-r--r--tests/auto/widgets/itemviews/qitemselectionmodel/tst_qitemselectionmodel.cpp2714
-rw-r--r--tests/auto/widgets/itemviews/qitemview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qitemview/qitemview.pro5
-rw-r--r--tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp928
-rw-r--r--tests/auto/widgets/itemviews/qitemview/viewstotest.cpp165
-rw-r--r--tests/auto/widgets/itemviews/qlistview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qlistview/qlistview.pro6
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp2073
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/qlistwidget.pro6
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp1685
-rw-r--r--tests/auto/widgets/itemviews/qsortfilterproxymodel/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qsortfilterproxymodel/qsortfilterproxymodel.pro8
-rw-r--r--tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp3274
-rw-r--r--tests/auto/widgets/itemviews/qstandarditem/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qstandarditem/qstandarditem.pro5
-rw-r--r--tests/auto/widgets/itemviews/qstandarditem/tst_qstandarditem.cpp1110
-rw-r--r--tests/auto/widgets/itemviews/qstandarditemmodel/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qstandarditemmodel/qstandarditemmodel.pro8
-rw-r--r--tests/auto/widgets/itemviews/qstandarditemmodel/tst_qstandarditemmodel.cpp1666
-rw-r--r--tests/auto/widgets/itemviews/qstringlistmodel/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qstringlistmodel/qmodellistener.h75
-rw-r--r--tests/auto/widgets/itemviews/qstringlistmodel/qstringlistmodel.pro8
-rw-r--r--tests/auto/widgets/itemviews/qstringlistmodel/tst_qstringlistmodel.cpp286
-rw-r--r--tests/auto/widgets/itemviews/qtableview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qtableview/qtableview.pro7
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp4075
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/qtablewidget.pro3
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp1500
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/qtreeview.pro3
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp3942
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/qtreewidget.pro3
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp3349
-rw-r--r--tests/auto/widgets/itemviews/qtreewidgetitemiterator/.gitignore1
-rw-r--r--tests/auto/widgets/itemviews/qtreewidgetitemiterator/qtreewidgetitemiterator.pro5
-rw-r--r--tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp1243
-rw-r--r--tests/auto/widgets/kernel/kernel.pro17
-rw-r--r--tests/auto/widgets/kernel/qaction/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qaction/qaction.pro5
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp373
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro5
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp247
-rw-r--r--tests/auto/widgets/kernel/qapplication/.gitignore3
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro14
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp54
-rw-r--r--tests/auto/widgets/kernel/qapplication/heart.svg55
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/base.cpp62
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/base.h64
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/main.cpp54
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/modal.pro9
-rw-r--r--tests/auto/widgets/kernel/qapplication/qapplication.pro7
-rw-r--r--tests/auto/widgets/kernel/qapplication/test/test.pro27
-rw-r--r--tests/auto/widgets/kernel/qapplication/tmp/README3
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp2107
-rw-r--r--tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp53
-rw-r--r--tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro8
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro5
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp280
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro3
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp187
-rw-r--r--tests/auto/widgets/kernel/qformlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qformlayout/qformlayout.pro3
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp913
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro10
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/sortdialog.ui135
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp1646
-rw-r--r--tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro7
-rw-r--r--tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp398
-rw-r--r--tests/auto/widgets/kernel/qlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize1792
-rw-r--r--tests/auto/widgets/kernel/qlayout/qlayout.pro16
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp345
-rw-r--r--tests/auto/widgets/kernel/qsound/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qsound/4.wavbin0 -> 5538 bytes
-rw-r--r--tests/auto/widgets/kernel/qsound/qsound.pro10
-rw-r--r--tests/auto/widgets/kernel/qsound/tst_qsound.cpp88
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro6
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp372
-rw-r--r--tests/auto/widgets/kernel/qtooltip/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qtooltip/qtooltip.pro5
-rw-r--r--tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp186
-rw-r--r--tests/auto/widgets/kernel/qwidget/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qwidget/geometry-fullscreen.datbin0 -> 46 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/geometry-maximized.datbin0 -> 46 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/geometry.datbin0 -> 46 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro23
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.qrc7
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnapbin0 -> 722 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnapbin0 -> 1509 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnapbin0 -> 7965 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnapbin0 -> 8265 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnapbin0 -> 710 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnapbin0 -> 1497 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnapbin0 -> 7953 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnapbin0 -> 8253 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp9472
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h52
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm83
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro8
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp326
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro5
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp405
-rw-r--r--tests/auto/widgets/styles/qmacstyle/.gitignore1
-rw-r--r--tests/auto/widgets/styles/qmacstyle/qmacstyle.pro6
-rw-r--r--tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp413
-rw-r--r--tests/auto/widgets/styles/qstyle/.gitignore1
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/button.pngbin0 -> 1785 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/combobox.pngbin0 -> 1808 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/lineedit.pngbin0 -> 953 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/mdi.pngbin0 -> 3092 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/menu.pngbin0 -> 1139 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/radiobutton.pngbin0 -> 1498 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/slider.pngbin0 -> 1074 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/spinbox.pngbin0 -> 1299 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/button.pngbin0 -> 722 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/combobox.pngbin0 -> 809 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/lineedit.pngbin0 -> 530 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/menu.pngbin0 -> 646 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/radiobutton.pngbin0 -> 844 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/slider.pngbin0 -> 575 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/spinbox.pngbin0 -> 583 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/qstyle.pro13
-rw-r--r--tests/auto/widgets/styles/qstyle/task_25863.pngbin0 -> 910 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/tst_qstyle.cpp794
-rw-r--r--tests/auto/widgets/styles/qstyleoption/.gitignore1
-rw-r--r--tests/auto/widgets/styles/qstyleoption/qstyleoption.pro11
-rw-r--r--tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp161
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/.gitignore1
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/images/testimage.pngbin0 -> 299 bytes
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro7
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/resources.qrc6
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp1644
-rw-r--r--tests/auto/widgets/styles/styles.pro13
-rw-r--r--tests/auto/widgets/util/qcompleter/.gitignore1
-rw-r--r--tests/auto/widgets/util/qcompleter/qcompleter.pro11
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp1519
-rw-r--r--tests/auto/widgets/util/qscroller/qscroller.pro4
-rw-r--r--tests/auto/widgets/util/qscroller/tst_qscroller.cpp530
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/.gitignore1
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/icons/icon.pngbin0 -> 1086 bytes
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro9
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp152
-rw-r--r--tests/auto/widgets/util/qundogroup/.gitignore1
-rw-r--r--tests/auto/widgets/util/qundogroup/qundogroup.pro4
-rw-r--r--tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts25
-rw-r--r--tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp668
-rw-r--r--tests/auto/widgets/util/qundostack/.gitignore1
-rw-r--r--tests/auto/widgets/util/qundostack/qundostack.pro4
-rw-r--r--tests/auto/widgets/util/qundostack/testdata/qundostack.ts25
-rw-r--r--tests/auto/widgets/util/qundostack/tst_qundostack.cpp3039
-rw-r--r--tests/auto/widgets/util/util.pro11
-rw-r--r--tests/auto/widgets/widgets.pro10
-rw-r--r--tests/auto/widgets/widgets/qabstractbutton/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qabstractbutton/qabstractbutton.pro5
-rw-r--r--tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp650
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/qabstractscrollarea.pro9
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp390
-rw-r--r--tests/auto/widgets/widgets/qabstractslider/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qabstractslider/qabstractslider.pro5
-rw-r--r--tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp1247
-rw-r--r--tests/auto/widgets/widgets/qabstractspinbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qabstractspinbox/qabstractspinbox.pro9
-rw-r--r--tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp163
-rw-r--r--tests/auto/widgets/widgets/qbuttongroup/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qbuttongroup/qbuttongroup.pro6
-rw-r--r--tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp525
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro5
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp368
-rw-r--r--tests/auto/widgets/widgets/qcheckbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qcheckbox/qcheckbox.pro6
-rw-r--r--tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp358
-rw-r--r--tests/auto/widgets/widgets/qcombobox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qcombobox/qcombobox.pro3
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp2579
-rw-r--r--tests/auto/widgets/widgets/qcommandlinkbutton/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro6
-rw-r--r--tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp590
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/qdatetimeedit.pro8
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp3458
-rw-r--r--tests/auto/widgets/widgets/qdial/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qdial/qdial.pro5
-rw-r--r--tests/auto/widgets/widgets/qdial/tst_qdial.cpp211
-rw-r--r--tests/auto/widgets/widgets/qdialogbuttonbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qdialogbuttonbox/qdialogbuttonbox.pro7
-rw-r--r--tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp810
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/qdockwidget.pro7
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp877
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/qdoublespinbox.pro5
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp1111
-rw-r--r--tests/auto/widgets/widgets/qdoublevalidator/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qdoublevalidator/qdoublevalidator.pro5
-rw-r--r--tests/auto/widgets/widgets/qdoublevalidator/tst_qdoublevalidator.cpp387
-rw-r--r--tests/auto/widgets/widgets/qfocusframe/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qfocusframe/qfocusframe.pro9
-rw-r--r--tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp89
-rw-r--r--tests/auto/widgets/widgets/qfontcombobox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qfontcombobox/qfontcombobox.pro5
-rw-r--r--tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp303
-rw-r--r--tests/auto/widgets/widgets/qgroupbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro6
-rw-r--r--tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp475
-rw-r--r--tests/auto/widgets/widgets/qintvalidator/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qintvalidator/qintvalidator.pro4
-rw-r--r--tests/auto/widgets/widgets/qintvalidator/tst_qintvalidator.cpp255
-rw-r--r--tests/auto/widgets/widgets/qlabel/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qlabel/green.pngbin0 -> 97 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/qlabel.pro15
-rw-r--r--tests/auto/widgets/widgets/qlabel/red.pngbin0 -> 105 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_data0.qsnapbin0 -> 328 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnapbin0 -> 330 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnapbin0 -> 322 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnapbin0 -> 328 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnapbin0 -> 330 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnapbin0 -> 324 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnapbin0 -> 320 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnapbin0 -> 322 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnapbin0 -> 328 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnapbin0 -> 330 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnapbin0 -> 318 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnapbin0 -> 324 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnapbin0 -> 332 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnapbin0 -> 316 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnapbin0 -> 322 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnapbin0 -> 324 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnapbin0 -> 318 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnapbin0 -> 314 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnapbin0 -> 316 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnapbin0 -> 322 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnapbin0 -> 324 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnapbin0 -> 312 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnapbin0 -> 318 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnapbin0 -> 326 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnapbin0 -> 318 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnapbin0 -> 324 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnapbin0 -> 326 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnapbin0 -> 320 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnapbin0 -> 316 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnapbin0 -> 318 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnapbin0 -> 324 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnapbin0 -> 326 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnapbin0 -> 314 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnapbin0 -> 320 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnapbin0 -> 328 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnapbin0 -> 344 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnapbin0 -> 346 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnapbin0 -> 346 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnapbin0 -> 338 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnapbin0 -> 340 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnapbin0 -> 340 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnapbin0 -> 340 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnapbin0 -> 342 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnapbin0 -> 342 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnapbin0 -> 405 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnapbin0 -> 399 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnapbin0 -> 397 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Motif_data0.qsnapbin0 -> 257 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_data0.qsnapbin0 -> 251 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnapbin0 -> 249 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnapbin0 -> 1040 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnapbin0 -> 1034 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnapbin0 -> 984 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data0.qsnapbin0 -> 352 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data1.qsnapbin0 -> 398 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data2.qsnapbin0 -> 448 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data3.qsnapbin0 -> 744 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data0.qsnapbin0 -> 346 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data1.qsnapbin0 -> 392 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data2.qsnapbin0 -> 442 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data3.qsnapbin0 -> 738 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data0.qsnapbin0 -> 344 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data1.qsnapbin0 -> 390 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data2.qsnapbin0 -> 440 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data3.qsnapbin0 -> 736 bytes
-rw-r--r--tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp581
-rw-r--r--tests/auto/widgets/widgets/qlcdnumber/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qlcdnumber/qlcdnumber.pro9
-rw-r--r--tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp88
-rw-r--r--tests/auto/widgets/widgets/qlineedit/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qlineedit/qlineedit.pro5
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.pngbin0 -> 30154 bytes
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp3835
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/qmainwindow.pro3
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp1742
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/qmdiarea.pro14
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp2773
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro8
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp2032
-rw-r--r--tests/auto/widgets/widgets/qmenu/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qmenu/qmenu.pro5
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp943
-rw-r--r--tests/auto/widgets/widgets/qmenubar/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qmenubar/qmenubar.pro3
-rw-r--r--tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp1291
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro10
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp1524
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/qprogressbar.pro6
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp295
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro6
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnapbin0 -> 890 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnapbin0 -> 758 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnapbin0 -> 725 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnapbin0 -> 735 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnapbin0 -> 829 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnapbin0 -> 796 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnapbin0 -> 796 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Motif_data0.qsnapbin0 -> 742 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_data0.qsnapbin0 -> 709 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnapbin0 -> 719 bytes
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp637
-rw-r--r--tests/auto/widgets/widgets/qradiobutton/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qradiobutton/qradiobutton.pro6
-rw-r--r--tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp108
-rw-r--r--tests/auto/widgets/widgets/qregexpvalidator/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qregexpvalidator/qregexpvalidator.pro4
-rw-r--r--tests/auto/widgets/widgets/qregexpvalidator/tst_qregexpvalidator.cpp127
-rw-r--r--tests/auto/widgets/widgets/qscrollarea/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qscrollarea/qscrollarea.pro9
-rw-r--r--tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp185
-rw-r--r--tests/auto/widgets/widgets/qscrollbar/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qscrollbar/qscrollbar.pro6
-rw-r--r--tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp147
-rw-r--r--tests/auto/widgets/widgets/qsizegrip/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qsizegrip/qsizegrip.pro6
-rw-r--r--tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp201
-rw-r--r--tests/auto/widgets/widgets/qslider/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qslider/qslider.pro9
-rw-r--r--tests/auto/widgets/widgets/qslider/tst_qslider.cpp98
-rw-r--r--tests/auto/widgets/widgets/qspinbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qspinbox/qspinbox.pro3
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp1049
-rw-r--r--tests/auto/widgets/widgets/qsplitter/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qsplitter/extradata.txt10067
-rw-r--r--tests/auto/widgets/widgets/qsplitter/qsplitter.pro12
-rw-r--r--tests/auto/widgets/widgets/qsplitter/setSizes3.dat2250
-rw-r--r--tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp777
-rw-r--r--tests/auto/widgets/widgets/qstackedwidget/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qstackedwidget/qstackedwidget.pro9
-rw-r--r--tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp124
-rw-r--r--tests/auto/widgets/widgets/qstatusbar/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qstatusbar/qstatusbar.pro6
-rw-r--r--tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp279
-rw-r--r--tests/auto/widgets/widgets/qtabbar/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qtabbar/qtabbar.pro6
-rw-r--r--tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp655
-rw-r--r--tests/auto/widgets/widgets/qtabwidget/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro12
-rw-r--r--tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp680
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/anchor.html11
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/bigpage.html934
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/firstpage.html2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/pagewithbg.html1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/pagewithimage.html1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/pagewithoutbg.html1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro15
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/secondpage.html1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/subdir/index.html1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/thirdpage.html1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp672
-rw-r--r--tests/auto/widgets/widgets/qtextedit/.gitignore2
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-fully-selected.pngbin0 -> 1232 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-partly-selected.pngbin0 -> 1231 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-line.pngbin0 -> 1226 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-parag.pngbin0 -> 1223 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/multiple-full-width-lines.pngbin0 -> 1236 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/nowrap_long.pngbin0 -> 1199 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/fullWidthSelection/single-full-width-line.pngbin0 -> 1225 bytes
-rw-r--r--tests/auto/widgets/widgets/qtextedit/qtextedit.pro18
-rw-r--r--tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp2391
-rw-r--r--tests/auto/widgets/widgets/qtoolbar/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qtoolbar/qtoolbar.pro7
-rw-r--r--tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp1101
-rw-r--r--tests/auto/widgets/widgets/qtoolbox/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qtoolbox/qtoolbox.pro6
-rw-r--r--tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp338
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/qtoolbutton.pro3
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp231
-rw-r--r--tests/auto/widgets/widgets/qworkspace/.gitignore1
-rw-r--r--tests/auto/widgets/widgets/qworkspace/qworkspace.pro3
-rw-r--r--tests/auto/widgets/widgets/qworkspace/tst_qworkspace.cpp679
-rw-r--r--tests/auto/widgets/widgets/widgets.pro57
582 files changed, 172546 insertions, 0 deletions
diff --git a/tests/auto/widgets/dialogs/dialogs.pro b/tests/auto/widgets/dialogs/dialogs.pro
new file mode 100644
index 0000000000..e74323a305
--- /dev/null
+++ b/tests/auto/widgets/dialogs/dialogs.pro
@@ -0,0 +1,18 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qabstractprintdialog \
+ qcolordialog \
+ qdialog \
+ qerrormessage \
+ qfiledialog \
+ qfiledialog2 \
+ qfilesystemmodel \
+ qfontdialog \
+ qinputdialog \
+ qmessagebox \
+ qprogressdialog \
+ qsidebar \
+ qwizard \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qsidebar \
diff --git a/tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore b/tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore
new file mode 100644
index 0000000000..a768494da5
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore
@@ -0,0 +1 @@
+tst_qabstractprintdialog
diff --git a/tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro b/tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro
new file mode 100644
index 0000000000..fb72bbf7a9
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qabstractprintdialog.h
+############################################################
+
+load(qttest_p4)
+QT += widgets printsupport
+SOURCES += tst_qabstractprintdialog.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp b/tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
new file mode 100644
index 0000000000..5d6165d174
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qabstractprintdialog.h>
+#include <qprinter.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAbstractPrintDialog : public QObject
+{
+Q_OBJECT
+
+#if defined(QT_NO_PRINTER) || defined(QT_NO_PRINTDIALOG)
+public slots:
+ void initTestCase();
+#else
+private slots:
+ void getSetCheck();
+ void setMinMax();
+ void setFromTo();
+#endif
+};
+
+#if defined(QT_NO_PRINTER) || defined(QT_NO_PRINTDIALOG)
+void tst_QAbstractPrintDialog::initTestCase()
+{
+ QSKIP("This test requires printing and print dialog support", SkipAll);
+}
+
+#else
+
+class MyAbstractPrintDialog : public QAbstractPrintDialog
+{
+public:
+ MyAbstractPrintDialog(QPrinter *p) : QAbstractPrintDialog(p) {}
+ int exec() { return 0; }
+};
+
+// Testing get/set functions
+void tst_QAbstractPrintDialog::getSetCheck()
+{
+ QPrinter printer;
+ MyAbstractPrintDialog obj1(&printer);
+ QCOMPARE(obj1.printer(), &printer);
+ // PrintDialogOptions QAbstractPrintDialog::enabledOptions()
+ // void QAbstractPrintDialog::setEnabledOptions(PrintDialogOptions)
+ obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::None));
+ QCOMPARE(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::None), obj1.enabledOptions());
+ obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintToFile));
+ QCOMPARE(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintToFile), obj1.enabledOptions());
+ obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintSelection));
+ QCOMPARE(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintSelection), obj1.enabledOptions());
+ obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintPageRange));
+ QCOMPARE(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintPageRange), obj1.enabledOptions());
+ obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintCollateCopies));
+ QCOMPARE(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintCollateCopies), obj1.enabledOptions());
+
+ // PrintRange QAbstractPrintDialog::printRange()
+ // void QAbstractPrintDialog::setPrintRange(PrintRange)
+ obj1.setPrintRange(QAbstractPrintDialog::PrintRange(QAbstractPrintDialog::AllPages));
+ QCOMPARE(QAbstractPrintDialog::PrintRange(QAbstractPrintDialog::AllPages), obj1.printRange());
+ obj1.setPrintRange(QAbstractPrintDialog::PrintRange(QAbstractPrintDialog::Selection));
+ QCOMPARE(QAbstractPrintDialog::PrintRange(QAbstractPrintDialog::Selection), obj1.printRange());
+ obj1.setPrintRange(QAbstractPrintDialog::PrintRange(QAbstractPrintDialog::PageRange));
+ QCOMPARE(QAbstractPrintDialog::PrintRange(QAbstractPrintDialog::PageRange), obj1.printRange());
+}
+
+void tst_QAbstractPrintDialog::setMinMax()
+{
+ QPrinter printer;
+ MyAbstractPrintDialog obj1(&printer);
+ obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::None));
+ QCOMPARE(obj1.minPage(), 1);
+ QCOMPARE(obj1.maxPage(), INT_MAX);
+ QVERIFY(!obj1.isOptionEnabled(QAbstractPrintDialog::PrintPageRange));
+ obj1.setMinMax(2,5);
+ QCOMPARE(obj1.minPage(), 2);
+ QCOMPARE(obj1.maxPage(), 5);
+ QVERIFY(obj1.enabledOptions() & QAbstractPrintDialog::PrintPageRange);
+ QVERIFY(obj1.isOptionEnabled(QAbstractPrintDialog::PrintPageRange));
+}
+
+void tst_QAbstractPrintDialog::setFromTo()
+{
+ QPrinter printer;
+ MyAbstractPrintDialog obj1(&printer);
+ QCOMPARE(obj1.fromPage(), 0);
+ QCOMPARE(obj1.toPage(), 0);
+ obj1.setMinMax(0,0);
+ QCOMPARE(obj1.minPage(), 0);
+ QCOMPARE(obj1.maxPage(), 0);
+ obj1.setFromTo(20,50);
+ QCOMPARE(obj1.fromPage(), 20);
+ QCOMPARE(obj1.toPage(), 50);
+ QCOMPARE(obj1.minPage(), 1);
+ QCOMPARE(obj1.maxPage(), 50);
+}
+
+#endif
+
+QTEST_MAIN(tst_QAbstractPrintDialog)
+#include "tst_qabstractprintdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qcolordialog/.gitignore b/tests/auto/widgets/dialogs/qcolordialog/.gitignore
new file mode 100644
index 0000000000..b7a8ebd8f8
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qcolordialog/.gitignore
@@ -0,0 +1 @@
+tst_qcolordialog
diff --git a/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro b/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro
new file mode 100644
index 0000000000..4f195dac2b
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qcolordialog.cpp
+
+
+
diff --git a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
new file mode 100644
index 0000000000..3ae1e63a8e
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui/QtGui>
+#include <QtWidgets/QColorDialog>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+QT_FORWARD_DECLARE_CLASS(QtTestEventThread)
+
+class tst_QColorDialog : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QColorDialog();
+ virtual ~tst_QColorDialog();
+
+#ifndef Q_WS_MAC
+public slots:
+ void postKeyReturn();
+private slots:
+ void defaultOkButton();
+#endif
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void native_activeModalWidget();
+ void task247349_alpha();
+};
+
+class TestNativeDialog : public QColorDialog
+{
+ Q_OBJECT
+public:
+ QWidget *m_activeModalWidget;
+
+ TestNativeDialog(QWidget *parent = 0)
+ : QColorDialog(parent), m_activeModalWidget(0)
+ {
+ QTimer::singleShot(1, this, SLOT(test_activeModalWidgetSignal()));
+ }
+
+public slots:
+ void test_activeModalWidgetSignal()
+ {
+ m_activeModalWidget = qApp->activeModalWidget();
+ }
+};
+
+tst_QColorDialog::tst_QColorDialog()
+{
+}
+
+tst_QColorDialog::~tst_QColorDialog()
+{
+}
+
+void tst_QColorDialog::native_activeModalWidget()
+{
+ // Check that QApplication::activeModalWidget retruns the
+ // color dialog when it is executing, even when using a native
+ // dialog:
+ TestNativeDialog d;
+ QTimer::singleShot(1000, &d, SLOT(hide()));
+ d.exec();
+ QVERIFY(&d == d.m_activeModalWidget);
+}
+
+void tst_QColorDialog::initTestCase()
+{
+}
+
+void tst_QColorDialog::cleanupTestCase()
+{
+}
+
+void tst_QColorDialog::init()
+{
+}
+
+void tst_QColorDialog::cleanup()
+{
+}
+
+#ifndef Q_WS_MAC
+//copied from QFontDialogTest
+void tst_QColorDialog::postKeyReturn() {
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i=0; i<list.count(); ++i) {
+ QColorDialog *dialog = qobject_cast<QColorDialog *>(list[i]);
+ if (dialog) {
+ QTest::keyClick( list[i], Qt::Key_Return, Qt::NoModifier );
+ return;
+ }
+ }
+}
+
+void tst_QColorDialog::defaultOkButton()
+{
+ bool ok = false;
+ QTimer::singleShot(500, this, SLOT(postKeyReturn()));
+ QColorDialog::getRgba(0xffffffff, &ok);
+ QVERIFY(ok);
+}
+#endif
+
+void tst_QColorDialog::task247349_alpha()
+{
+ QColorDialog dialog;
+ dialog.setOption(QColorDialog::ShowAlphaChannel, true);
+ int alpha = 0x17;
+ dialog.setCurrentColor(QColor(0x01, 0x02, 0x03, alpha));
+ QCOMPARE(alpha, dialog.currentColor().alpha());
+ QCOMPARE(alpha, qAlpha(dialog.currentColor().rgba()));
+}
+
+QTEST_MAIN(tst_QColorDialog)
+#include "tst_qcolordialog.moc"
diff --git a/tests/auto/widgets/dialogs/qdialog/.gitignore b/tests/auto/widgets/dialogs/qdialog/.gitignore
new file mode 100644
index 0000000000..4a4b5ebcbe
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qdialog/.gitignore
@@ -0,0 +1 @@
+tst_qdialog
diff --git a/tests/auto/widgets/dialogs/qdialog/qdialog.pro b/tests/auto/widgets/dialogs/qdialog/qdialog.pro
new file mode 100644
index 0000000000..a3596b60f6
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qdialog/qdialog.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdialog.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
new file mode 100644
index 0000000000..0f4acdcc9e
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -0,0 +1,609 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qdialog.h>
+#include <qapplication.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qstyle.h>
+#include <QVBoxLayout>
+#include <QSizeGrip>
+
+Q_DECLARE_METATYPE(QSize)
+
+
+QT_FORWARD_DECLARE_CLASS(QDialog)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QDialog : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDialog();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+private slots:
+ void getSetCheck();
+ void showExtension_data();
+ void showExtension();
+ void defaultButtons();
+ void showMaximized();
+ void showMinimized();
+ void showFullScreen();
+#if !defined(Q_WS_X11) && !defined(Q_OS_WINCE)
+ void showAsTool();
+#endif
+#ifndef Q_OS_WINCE
+ void toolDialogPosition();
+#endif
+ void deleteMainDefault();
+ void deleteInExec();
+#if !defined(QT_NO_EXCEPTIONS) && !defined(Q_OS_MAC) && !(defined(Q_OS_WINCE) && defined(_ARM_))
+ void throwInExec();
+#endif
+ void showSizeGrip();
+ void setVisible();
+ void reject();
+
+private:
+ QDialog *testWidget;
+};
+
+// Testing get/set functions
+void tst_QDialog::getSetCheck()
+{
+ QDialog obj1;
+ // QWidget* QDialog::extension()
+ // void QDialog::setExtension(QWidget*)
+ QWidget *var1 = new QWidget;
+ obj1.setExtension(var1);
+ QCOMPARE(var1, obj1.extension());
+ obj1.setExtension((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.extension());
+ // No delete var1, since setExtension takes ownership
+
+ // int QDialog::result()
+ // void QDialog::setResult(int)
+ obj1.setResult(0);
+ QCOMPARE(0, obj1.result());
+ obj1.setResult(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.result());
+ obj1.setResult(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.result());
+}
+
+// work around function being protected
+class DummyDialog : public QDialog {
+public:
+ DummyDialog(): QDialog(0) {}
+ void showExtension( bool b ) { QDialog::showExtension( b ); }
+};
+
+class ToolDialog : public QDialog
+{
+public:
+ ToolDialog(QWidget *parent = 0) : QDialog(parent, Qt::Tool), mWasActive(false), tId(-1) {
+ }
+ bool wasActive() const { return mWasActive; }
+
+ int exec() {
+ tId = startTimer(300);
+ return QDialog::exec();
+ }
+protected:
+ void timerEvent(QTimerEvent *event) {
+ if (tId == event->timerId()) {
+ killTimer(tId);
+ mWasActive = isActiveWindow();
+ reject();
+ }
+ }
+
+private:
+ int mWasActive;
+ int tId;
+};
+
+tst_QDialog::tst_QDialog()
+
+{
+}
+
+void tst_QDialog::initTestCase()
+{
+ // Create the test class
+ testWidget = new QDialog(0, Qt::X11BypassWindowManagerHint);
+ testWidget->resize(200,200);
+ testWidget->show();
+ qApp->setActiveWindow(testWidget);
+}
+
+void tst_QDialog::cleanupTestCase()
+{
+ if (testWidget) {
+ delete testWidget;
+ testWidget = 0;
+ }
+}
+
+void tst_QDialog::showExtension_data()
+{
+ QTest::addColumn<QSize>("dlgSize");
+ QTest::addColumn<QSize>("extSize");
+ QTest::addColumn<bool>("horizontal");
+ QTest::addColumn<QSize>("result");
+
+ //next we fill it with data
+ QTest::newRow( "data0" ) << QSize(100,100) << QSize(50,50) << (bool)FALSE << QSize(100,150);
+ QTest::newRow( "data1" ) << QSize(100,100) << QSize(120,50) << (bool)FALSE << QSize(120,150);
+ QTest::newRow( "data2" ) << QSize(100,100) << QSize(50,50) << (bool)TRUE << QSize(150,100);
+ QTest::newRow( "data3" ) << QSize(100,100) << QSize(50,120) << (bool)TRUE << QSize(150,120);
+}
+
+void tst_QDialog::showExtension()
+{
+ QFETCH( QSize, dlgSize );
+ QFETCH( QSize, extSize );
+ QFETCH( bool, horizontal );
+
+ // set geometry of main dialog and extension widget
+ testWidget->setFixedSize( dlgSize );
+ QWidget *ext = new QWidget( testWidget );
+ ext->setFixedSize( extSize );
+ testWidget->setExtension( ext );
+ testWidget->setOrientation( horizontal ? Qt::Horizontal : Qt::Vertical );
+
+ QCOMPARE( testWidget->size(), dlgSize );
+ QPoint oldPosition = testWidget->pos();
+
+ // show
+ ((DummyDialog*)testWidget)->showExtension( TRUE );
+// while ( testWidget->size() == dlgSize )
+// qApp->processEvents();
+
+ QTEST( testWidget->size(), "result" );
+
+ QCOMPARE(testWidget->pos(), oldPosition);
+
+ // hide extension. back to old size ?
+ ((DummyDialog*)testWidget)->showExtension( FALSE );
+ QCOMPARE( testWidget->size(), dlgSize );
+
+ testWidget->setExtension( 0 );
+}
+
+void tst_QDialog::defaultButtons()
+{
+ QLineEdit *lineEdit = new QLineEdit(testWidget);
+ QPushButton *push = new QPushButton("Button 1", testWidget);
+ QPushButton *pushTwo = new QPushButton("Button 2", testWidget);
+ QPushButton *pushThree = new QPushButton("Button 3", testWidget);
+ pushThree->setAutoDefault(FALSE);
+
+ //we need to show the buttons. Otherwise they won't get the focus
+ push->show();
+ pushTwo->show();
+ pushThree->show();
+
+ push->setDefault(TRUE);
+ QVERIFY(push->isDefault());
+
+ pushTwo->setFocus();
+ QVERIFY(pushTwo->isDefault());
+ pushThree->setFocus();
+ QVERIFY(push->isDefault());
+ lineEdit->setFocus();
+ QVERIFY(push->isDefault());
+
+ pushTwo->setDefault(TRUE);
+ QVERIFY(pushTwo->isDefault());
+
+ pushTwo->setFocus();
+ QVERIFY(pushTwo->isDefault());
+ lineEdit->setFocus();
+ QVERIFY(pushTwo->isDefault());
+}
+
+void tst_QDialog::showMaximized()
+{
+ QDialog dialog(0);
+ dialog.setSizeGripEnabled(true);
+ QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(&dialog);
+ QVERIFY(sizeGrip);
+
+ dialog.showMaximized();
+ QVERIFY(dialog.isMaximized());
+ QVERIFY(dialog.isVisible());
+#if !defined(Q_OS_MAC) && !defined(Q_OS_IRIX) && !defined(Q_OS_HPUX)
+ QVERIFY(!sizeGrip->isVisible());
+#endif
+
+ dialog.showNormal();
+ QVERIFY(!dialog.isMaximized());
+ QVERIFY(dialog.isVisible());
+ QVERIFY(sizeGrip->isVisible());
+
+ dialog.showMaximized();
+ QVERIFY(dialog.isMaximized());
+ QVERIFY(dialog.isVisible());
+
+ dialog.hide();
+ QVERIFY(dialog.isMaximized());
+ QVERIFY(!dialog.isVisible());
+
+ dialog.show();
+ QVERIFY(dialog.isMaximized());
+ QVERIFY(dialog.isVisible());
+
+ dialog.hide();
+ QVERIFY(dialog.isMaximized());
+ QVERIFY(!dialog.isVisible());
+
+ dialog.showMaximized();
+ QVERIFY(dialog.isMaximized());
+ QVERIFY(dialog.isVisible());
+}
+
+void tst_QDialog::showMinimized()
+{
+ QDialog dialog(0);
+
+ dialog.showMinimized();
+ QVERIFY(dialog.isMinimized());
+ QVERIFY(dialog.isVisible());
+
+ dialog.showNormal();
+ QVERIFY(!dialog.isMinimized());
+ QVERIFY(dialog.isVisible());
+
+ dialog.showMinimized();
+ QVERIFY(dialog.isMinimized());
+ QVERIFY(dialog.isVisible());
+
+ dialog.hide();
+ QVERIFY(dialog.isMinimized());
+ QVERIFY(!dialog.isVisible());
+
+ dialog.show();
+ QVERIFY(dialog.isMinimized());
+ QVERIFY(dialog.isVisible());
+
+ dialog.hide();
+ QVERIFY(dialog.isMinimized());
+ QVERIFY(!dialog.isVisible());
+
+ dialog.showMinimized();
+ QVERIFY(dialog.isMinimized());
+ QVERIFY(dialog.isVisible());
+}
+
+void tst_QDialog::showFullScreen()
+{
+ QDialog dialog(0, Qt::X11BypassWindowManagerHint);
+ dialog.setSizeGripEnabled(true);
+ QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(&dialog);
+ QVERIFY(sizeGrip);
+
+ qApp->syncX();
+ dialog.showFullScreen();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(dialog.isVisible());
+ QVERIFY(!sizeGrip->isVisible());
+
+ qApp->syncX();
+ dialog.showNormal();
+ QVERIFY(!dialog.isFullScreen());
+ QVERIFY(dialog.isVisible());
+ QVERIFY(sizeGrip->isVisible());
+
+ qApp->syncX();
+ dialog.showFullScreen();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(dialog.isVisible());
+
+ qApp->syncX();
+ dialog.hide();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(!dialog.isVisible());
+
+ qApp->syncX();
+ dialog.show();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(dialog.isVisible());
+
+ qApp->syncX();
+ dialog.hide();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(!dialog.isVisible());
+
+ qApp->syncX();
+ dialog.showFullScreen();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(dialog.isVisible());
+
+ qApp->syncX();
+ dialog.hide();
+ QVERIFY(dialog.isFullScreen());
+ QVERIFY(!dialog.isVisible());
+}
+
+// Qt/X11: Skipped since activeWindow() is not respected by all window managers.
+// Qt/WinCE: No real support for Qt::Tool on WinCE.
+#if !defined(Q_WS_X11) && !defined(Q_OS_WINCE)
+void tst_QDialog::showAsTool()
+{
+ ToolDialog dialog(testWidget);
+ testWidget->activateWindow();
+ dialog.exec();
+ QTest::qWait(100);
+ if (testWidget->style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, testWidget)) {
+ QCOMPARE(dialog.wasActive(), true);
+ } else {
+ QCOMPARE(dialog.wasActive(), false);
+ }
+}
+#endif
+
+// Verify that pos() returns the same before and after show()
+// for a dialog with the Tool window type.
+// No real support for Qt::Tool on WinCE, so skip this test.
+#ifndef Q_OS_WINCE
+void tst_QDialog::toolDialogPosition()
+{
+ QDialog dialog(0, Qt::Tool);
+ dialog.move(QPoint(100,100));
+ const QPoint beforeShowPosition = dialog.pos();
+ dialog.show();
+ const QPoint afterShowPosition = dialog.pos();
+ QCOMPARE(afterShowPosition, beforeShowPosition);
+}
+#endif
+
+class Dialog : public QDialog
+{
+public:
+ Dialog(QPushButton *&button)
+ {
+ button = new QPushButton(this);
+ }
+};
+
+void tst_QDialog::deleteMainDefault()
+{
+ QPushButton *button;
+ Dialog dialog(button);
+ button->setDefault(true);
+ delete button;
+ dialog.show();
+ QTestEventLoop::instance().enterLoop(2);
+}
+
+void tst_QDialog::deleteInExec()
+{
+ QDialog *dialog = new QDialog(0);
+ QMetaObject::invokeMethod(dialog, "deleteLater", Qt::QueuedConnection);
+ QCOMPARE(dialog->exec(), int(QDialog::Rejected));
+}
+
+// Throwing exceptions in exec() is not supported on Mac or on WinCE/ARM.
+#if !defined(QT_NO_EXCEPTIONS) && !defined(Q_OS_MAC) && !(defined(Q_OS_WINCE) && defined(_ARM_))
+class QDialogTestException : public std::exception { };
+
+class ExceptionDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ ExceptionDialog() : QDialog(0) { }
+public slots:
+ void throwException()
+ {
+ QDialogTestException e;
+ throw e;
+ }
+};
+
+void tst_QDialog::throwInExec()
+{
+#if defined(Q_OS_LINUX)
+ // C++ exceptions can't be passed through glib callbacks. Skip the test if
+ // we're using the glib event loop.
+ QByteArray dispatcher = QAbstractEventDispatcher::instance()->metaObject()->className();
+ if (dispatcher.contains("Glib")) {
+ QSKIP(
+ qPrintable(QString(
+ "Throwing exceptions in exec() won't work if %1 event dispatcher is used.\n"
+ "Try running with QT_NO_GLIB=1 in environment."
+ ).arg(QString::fromLatin1(dispatcher))),
+ SkipAll
+ );
+ }
+#endif
+
+ int caughtExceptions = 0;
+ try {
+ ExceptionDialog dialog;
+ QMetaObject::invokeMethod(&dialog, "throwException", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&dialog, "reject", Qt::QueuedConnection);
+ (void) dialog.exec();
+ } catch(...) {
+ ++caughtExceptions;
+ }
+ QCOMPARE(caughtExceptions, 1);
+}
+#endif
+
+// From Task 124269
+void tst_QDialog::showSizeGrip()
+{
+#ifndef QT_NO_SIZEGRIP
+ QDialog dialog(0);
+ dialog.show();
+ QWidget *ext = new QWidget(&dialog);
+ QVERIFY(!dialog.extension());
+ QVERIFY(!dialog.isSizeGripEnabled());
+
+ dialog.setSizeGripEnabled(true);
+ QPointer<QSizeGrip> sizeGrip = qFindChild<QSizeGrip *>(&dialog);
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+ QVERIFY(dialog.isSizeGripEnabled());
+
+ dialog.setExtension(ext);
+ QVERIFY(dialog.extension() && !dialog.extension()->isVisible());
+ QVERIFY(dialog.isSizeGripEnabled());
+
+ // normal show/hide sequence
+ dialog.showExtension(true);
+ QVERIFY(dialog.extension() && dialog.extension()->isVisible());
+ QVERIFY(!dialog.isSizeGripEnabled());
+ QVERIFY(!sizeGrip);
+
+ dialog.showExtension(false);
+ QVERIFY(dialog.extension() && !dialog.extension()->isVisible());
+ QVERIFY(dialog.isSizeGripEnabled());
+ sizeGrip = qFindChild<QSizeGrip *>(&dialog);
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+
+ // show/hide sequence with interleaved size grip update
+ dialog.showExtension(true);
+ QVERIFY(dialog.extension() && dialog.extension()->isVisible());
+ QVERIFY(!dialog.isSizeGripEnabled());
+ QVERIFY(!sizeGrip);
+
+ dialog.setSizeGripEnabled(false);
+ QVERIFY(!dialog.isSizeGripEnabled());
+
+ dialog.showExtension(false);
+ QVERIFY(dialog.extension() && !dialog.extension()->isVisible());
+ QVERIFY(!dialog.isSizeGripEnabled());
+
+ dialog.setSizeGripEnabled(true);
+ sizeGrip = qFindChild<QSizeGrip *>(&dialog);
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+ sizeGrip->hide();
+ dialog.hide();
+ dialog.show();
+ QVERIFY(!sizeGrip->isVisible());
+#endif
+}
+
+void tst_QDialog::setVisible()
+{
+ QWidget topLevel;
+ topLevel.show();
+
+ QDialog *dialog = new QDialog;
+ dialog->setLayout(new QVBoxLayout);
+ dialog->layout()->addWidget(new QPushButton("dialog button"));
+
+ QWidget *widget = new QWidget(&topLevel);
+ widget->setLayout(new QVBoxLayout);
+ widget->layout()->addWidget(dialog);
+
+ QVERIFY(!dialog->isVisible());
+ QVERIFY(!dialog->isHidden());
+
+ widget->show();
+ QVERIFY(dialog->isVisible());
+ QVERIFY(!dialog->isHidden());
+
+ widget->hide();
+ dialog->hide();
+ widget->show();
+ QVERIFY(!dialog->isVisible());
+ QVERIFY(dialog->isHidden());
+}
+
+class TestRejectDialog : public QDialog
+{
+ public:
+ TestRejectDialog() : cancelReject(false), called(0) {}
+ void reject()
+ {
+ called++;
+ if (!cancelReject)
+ QDialog::reject();
+ }
+ bool cancelReject;
+ int called;
+};
+
+void tst_QDialog::reject()
+{
+ TestRejectDialog dialog;
+ dialog.show();
+ QTest::qWaitForWindowShown(&dialog);
+ QTRY_VERIFY(dialog.isVisible());
+ dialog.reject();
+ QTRY_VERIFY(!dialog.isVisible());
+ QCOMPARE(dialog.called, 1);
+
+ dialog.show();
+ QTest::qWaitForWindowShown(&dialog);
+ QTRY_VERIFY(dialog.isVisible());
+ QVERIFY(dialog.close());
+ QTRY_VERIFY(!dialog.isVisible());
+ QCOMPARE(dialog.called, 2);
+
+ dialog.cancelReject = true;
+ dialog.show();
+ QTest::qWaitForWindowShown(&dialog);
+ QTRY_VERIFY(dialog.isVisible());
+ dialog.reject();
+ QTRY_VERIFY(dialog.isVisible());
+ QCOMPARE(dialog.called, 3);
+ QVERIFY(!dialog.close());
+ QTRY_VERIFY(dialog.isVisible());
+ QCOMPARE(dialog.called, 4);
+}
+
+
+QTEST_MAIN(tst_QDialog)
+#include "tst_qdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qerrormessage/.gitignore b/tests/auto/widgets/dialogs/qerrormessage/.gitignore
new file mode 100644
index 0000000000..1bb653fb72
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qerrormessage/.gitignore
@@ -0,0 +1 @@
+tst_qerrormessage
diff --git a/tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro b/tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro
new file mode 100644
index 0000000000..363d085cbf
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qerrormessage
+DEPENDPATH += .
+INCLUDEPATH += .
+
+QT += widgets
+
+# Input
+SOURCES += tst_qerrormessage.cpp
diff --git a/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp b/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp
new file mode 100644
index 0000000000..d3ee640b1a
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QErrorMessage>
+#include <QDebug>
+#include <QCheckBox>
+
+class tst_QErrorMessage : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void dontShowAgain();
+ void dontShowCategoryAgain();
+
+};
+
+void tst_QErrorMessage::dontShowAgain()
+{
+ QString plainString = QLatin1String("foo");
+ QString htmlString = QLatin1String("foo<br>bar");
+ QCheckBox *checkBox = 0;
+
+ QErrorMessage errorMessageDialog(0);
+
+ // show an error with plain string
+ errorMessageDialog.showMessage(plainString);
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(plainString);
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ checkBox->setChecked(false);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(plainString);
+ QVERIFY(!errorMessageDialog.isVisible());
+
+ // show an error with an html string
+ errorMessageDialog.showMessage(htmlString);
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(!checkBox->isChecked());
+ checkBox->setChecked(true);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(htmlString);
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ checkBox->setChecked(false);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(htmlString);
+ QVERIFY(!errorMessageDialog.isVisible());
+}
+
+void tst_QErrorMessage::dontShowCategoryAgain()
+{
+ QString htmlString = QLatin1String("foo<br>bar");
+ QString htmlString2 = QLatin1String("foo2<br>bar2");
+ QCheckBox *checkBox = 0;
+
+ QErrorMessage errorMessageDialog(0);
+
+ errorMessageDialog.showMessage(htmlString,"Cat 1");
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ checkBox->setChecked(true);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(htmlString,"Cat 1");
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ checkBox->setChecked(true);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(htmlString2,"Cat 1");
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ checkBox->setChecked(true);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(htmlString,"Cat 1");
+ QVERIFY(errorMessageDialog.isVisible());
+ checkBox = qFindChild<QCheckBox*>(&errorMessageDialog);
+ QVERIFY(checkBox);
+ QVERIFY(checkBox->isChecked());
+ checkBox->setChecked(false);
+ errorMessageDialog.close();
+
+ errorMessageDialog.showMessage(htmlString2,"Cat 1");
+ QVERIFY(!errorMessageDialog.isVisible());
+
+ errorMessageDialog.showMessage(htmlString,"Cat 1");
+ QVERIFY(!errorMessageDialog.isVisible());
+
+ errorMessageDialog.showMessage(htmlString);
+ QVERIFY(errorMessageDialog.isVisible());
+
+ errorMessageDialog.showMessage(htmlString,"Cat 2");
+ QVERIFY(errorMessageDialog.isVisible());
+}
+
+QTEST_MAIN(tst_QErrorMessage)
+#include "tst_qerrormessage.moc"
diff --git a/tests/auto/widgets/dialogs/qfiledialog/.gitignore b/tests/auto/widgets/dialogs/qfiledialog/.gitignore
new file mode 100644
index 0000000000..a696596ee9
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog/.gitignore
@@ -0,0 +1 @@
+tst_qfiledialog
diff --git a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro
new file mode 100644
index 0000000000..92fba98796
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro
@@ -0,0 +1,23 @@
+############################################################
+# Project file for autotest for file qfiledialog.h
+############################################################
+
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qfiledialog.cpp
+
+wince* {
+ addFiles.files = *.cpp
+ addFiles.path = .
+ filesInDir.files = *.pro
+ filesInDir.path = someDir
+ DEPLOYMENT += addFiles filesInDir
+}
+
+wince* {
+ DEFINES += SRCDIR=\\\"./\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
diff --git a/tests/auto/widgets/dialogs/qfiledialog/resources/file.txt b/tests/auto/widgets/dialogs/qfiledialog/resources/file.txt
new file mode 100644
index 0000000000..8a03e0e55f
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog/resources/file.txt
@@ -0,0 +1 @@
+This is a simple text file.
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
new file mode 100644
index 0000000000..9abcd407d0
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -0,0 +1,1349 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qfiledialog.h>
+#include <qabstractitemdelegate.h>
+#include <qdirmodel.h>
+#include <qitemdelegate.h>
+#include <qlistview.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qtreeview.h>
+#include <qheaderview.h>
+#include <qcompleter.h>
+#include <qaction.h>
+#include <qdialogbuttonbox.h>
+#include <qsortfilterproxymodel.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#if defined QT_BUILD_INTERNAL
+#include "../../../src/widgets/dialogs/qsidebar_p.h"
+#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h"
+#include "../../../src/widgets/dialogs/qfiledialog_p.h"
+#endif
+#include <QFileDialog>
+#include <QFileSystemModel>
+
+#include "../../../network-settings.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#if defined(Q_OS_UNIX)
+#ifdef QT_BUILD_INTERNAL
+QT_BEGIN_NAMESPACE
+extern Q_GUI_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0);
+QT_END_NAMESPACE
+#endif
+#endif
+
+class QNonNativeFileDialog : public QFileDialog
+{
+ Q_OBJECT
+public:
+ QNonNativeFileDialog(QWidget *parent = 0, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString())
+ : QFileDialog(parent, caption, directory, filter)
+ {
+ setOption(QFileDialog::DontUseNativeDialog, true);
+ }
+};
+
+class tst_QFiledialog : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QFiledialog();
+ virtual ~tst_QFiledialog();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void currentChangedSignal();
+ void directoryEnteredSignal();
+ void filesSelectedSignal_data();
+ void filesSelectedSignal();
+ void filterSelectedSignal();
+
+ void args();
+ void directory();
+ void completer_data();
+ void completer();
+ void completer_up();
+ void acceptMode();
+ void confirmOverwrite();
+ void defaultSuffix();
+ void fileMode();
+ void filters();
+ void history();
+ void iconProvider();
+ void isReadOnly();
+ void itemDelegate();
+ void labelText();
+ void resolveSymlinks();
+ void selectFile_data();
+ void selectFile();
+ void selectFiles();
+ void selectFilter();
+ void viewMode();
+ void proxymodel();
+ void setNameFilter();
+ void focus();
+ void caption();
+ void historyBack();
+ void historyForward();
+ void disableSaveButton_data();
+ void disableSaveButton();
+ void saveButtonText_data();
+ void saveButtonText();
+ void clearLineEdit();
+ void enableChooseButton();
+ void hooks();
+#if defined(Q_OS_UNIX) && defined(QT_BUILD_INTERNAL)
+ void tildeExpansion_data();
+ void tildeExpansion();
+#endif
+
+private:
+ QByteArray userSettings;
+};
+
+tst_QFiledialog::tst_QFiledialog()
+{
+}
+
+tst_QFiledialog::~tst_QFiledialog()
+{
+}
+
+void tst_QFiledialog::init()
+{
+ // Save the developers settings so they don't get mad when their sidebar folders are gone.
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ userSettings = settings.value(QLatin1String("filedialog")).toByteArray();
+ settings.remove(QLatin1String("filedialog"));
+
+ // populate it with some default settings
+ QNonNativeFileDialog fd;
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1000);
+#endif
+}
+
+void tst_QFiledialog::cleanup()
+{
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ settings.setValue(QLatin1String("filedialog"), userSettings);
+}
+
+class MyAbstractItemDelegate : public QAbstractItemDelegate
+{
+public:
+ MyAbstractItemDelegate() : QAbstractItemDelegate() {};
+ void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
+ QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
+};
+
+// emitted any time the selection model emits current changed
+void tst_QFiledialog::currentChangedSignal()
+{
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
+
+ QListView* listView = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(listView);
+ fd.setDirectory(QDir::root());
+ QModelIndex root = listView->rootIndex();
+ QTRY_COMPARE(listView->model()->rowCount(root) > 0, true);
+
+ QModelIndex folder;
+ for (int i = 0; i < listView->model()->rowCount(root); ++i) {
+ folder = listView->model()->index(i, 0, root);
+ if (listView->model()->hasChildren(folder))
+ break;
+ }
+ QVERIFY(listView->model()->hasChildren(folder));
+ listView->setCurrentIndex(folder);
+
+ QCOMPARE(spyCurrentChanged.count(), 1);
+}
+
+// only emitted from the views, sidebar, or lookin combo
+void tst_QFiledialog::directoryEnteredSignal()
+{
+#if defined QT_BUILD_INTERNAL
+ QNonNativeFileDialog fd(0, "", QDir::root().path());
+ fd.setOptions(QFileDialog::DontUseNativeDialog);
+ fd.show();
+ QTRY_COMPARE(fd.isVisible(), true);
+ QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
+
+ // sidebar
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
+ sidebar->setCurrentIndex(sidebar->model()->index(1, 0));
+ QTest::keyPress(sidebar->viewport(), Qt::Key_Return);
+ QCOMPARE(spyDirectoryEntered.count(), 1);
+ spyDirectoryEntered.clear();
+
+ // lookInCombo
+ QComboBox *comboBox = qFindChild<QComboBox*>(&fd, "lookInCombo");
+ comboBox->showPopup();
+ QVERIFY(comboBox->view()->model()->index(1, 0).isValid());
+ comboBox->view()->setCurrentIndex(comboBox->view()->model()->index(1, 0));
+ QTest::keyPress(comboBox->view()->viewport(), Qt::Key_Return);
+ QCOMPARE(spyDirectoryEntered.count(), 1);
+ spyDirectoryEntered.clear();
+
+ // view
+ /*
+ // platform specific
+ fd.setViewMode(QFileDialog::ViewMode(QFileDialog::List));
+ QListView* listView = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(listView);
+ QModelIndex root = listView->rootIndex();
+ QTRY_COMPARE(listView->model()->rowCount(root) > 0, true);
+
+ QModelIndex folder;
+ for (int i = 0; i < listView->model()->rowCount(root); ++i) {
+ folder = listView->model()->index(i, 0, root);
+ if (listView->model()->hasChildren(folder))
+ break;
+ }
+ QVERIFY(listView->model()->hasChildren(folder));
+ listView->setCurrentIndex(folder);
+ QTRY_COMPARE((listView->indexAt(listView->visualRect(folder).center())), folder);
+ QTest::mouseDClick(listView->viewport(), Qt::LeftButton, 0, listView->visualRect(folder).center());
+ QTRY_COMPARE(spyDirectoryEntered.count(), 1);
+ */
+#endif
+}
+
+Q_DECLARE_METATYPE(QFileDialog::FileMode)
+void tst_QFiledialog::filesSelectedSignal_data()
+{
+ QTest::addColumn<QFileDialog::FileMode>("fileMode");
+ QTest::newRow("any") << QFileDialog::AnyFile;
+ QTest::newRow("existing") << QFileDialog::ExistingFile;
+ QTest::newRow("directory") << QFileDialog::Directory;
+ QTest::newRow("directoryOnly") << QFileDialog::DirectoryOnly;
+ QTest::newRow("existingFiles") << QFileDialog::ExistingFiles;
+}
+
+// emitted when the dialog closes with the selected files
+void tst_QFiledialog::filesSelectedSignal()
+{
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ fd.setOptions(QFileDialog::DontUseNativeDialog);
+ QDir testDir(SRCDIR);
+ fd.setDirectory(testDir);
+ QFETCH(QFileDialog::FileMode, fileMode);
+ fd.setFileMode(fileMode);
+ QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
+
+ fd.show();
+ QTest::qWait(500);
+ QListView *listView = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(listView);
+
+ QModelIndex root = listView->rootIndex();
+ QTRY_COMPARE(listView->model()->rowCount(root) > 0, true);
+ QModelIndex file;
+ for (int i = 0; i < listView->model()->rowCount(root); ++i) {
+ file = listView->model()->index(i, 0, root);
+ if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
+ if (listView->model()->hasChildren(file))
+ break;
+ } else {
+ if (!listView->model()->hasChildren(file))
+ break;
+ }
+ file = QModelIndex();
+ }
+ QVERIFY(file.isValid());
+ listView->selectionModel()->select(file, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ listView->setCurrentIndex(file);
+
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Open);
+ QVERIFY(button);
+ QVERIFY(button->isEnabled());
+ button->animateClick();
+ QTRY_COMPARE(fd.isVisible(), false);
+ QCOMPARE(spyFilesSelected.count(), 1);
+}
+
+// only emitted when the combo box is activated
+void tst_QFiledialog::filterSelectedSignal()
+{
+ QNonNativeFileDialog fd;
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.show();
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+
+ QStringList filterChoices;
+ filterChoices << "Image files (*.png *.xpm *.jpg)"
+ << "Text files (*.txt)"
+ << "Any files (*.*)";
+ fd.setFilters(filterChoices);
+ QCOMPARE(fd.filters(), filterChoices);
+
+ QComboBox *filters = qFindChild<QComboBox*>(&fd, "fileTypeCombo");
+ QVERIFY(filters);
+ QVERIFY(filters->view());
+ QCOMPARE(filters->isVisible(), true);
+
+ QTest::keyPress(filters, Qt::Key_Down);
+
+ QCOMPARE(spyFilterSelected.count(), 1);
+}
+
+void tst_QFiledialog::args()
+{
+ QWidget *parent = 0;
+ QString caption = "caption";
+ QString directory = QDir::tempPath();
+ QString filter = "*.mp3";
+ QNonNativeFileDialog fd(parent, caption, directory, filter);
+ QCOMPARE(fd.parent(), (QObject *)parent);
+ QCOMPARE(fd.windowTitle(), caption);
+#ifndef Q_OS_WIN
+ QCOMPARE(fd.directory(), QDir(directory));
+#endif
+ QCOMPARE(fd.filters(), QStringList(filter));
+}
+
+void tst_QFiledialog::directory()
+{
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ fd.setDirectory(QDir::currentPath());
+ QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
+ QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
+ QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+
+ QCOMPARE(QDir::current().absolutePath(), fd.directory().absolutePath());
+ QDir temp = QDir::temp();
+ QString tempPath = temp.absolutePath();
+#ifdef Q_OS_WIN
+ // since the user can have lowercase temp dir, check that we are actually case-insensitive.
+ tempPath = tempPath.toLower();
+#endif
+ fd.setDirectory(tempPath);
+#ifndef Q_OS_WIN
+ QCOMPARE(tempPath, fd.directory().absolutePath());
+#endif
+ QCOMPARE(spyCurrentChanged.count(), 0);
+ QCOMPARE(spyDirectoryEntered.count(), 0);
+ QCOMPARE(spyFilesSelected.count(), 0);
+ QCOMPARE(spyFilterSelected.count(), 0);
+
+ // Check my way
+ QList<QListView*> list = qFindChildren<QListView*>(&fd, "listView");
+ QVERIFY(list.count() > 0);
+#ifdef Q_OS_WIN
+ QCOMPARE(list.at(0)->rootIndex().data().toString().toLower(), temp.dirName().toLower());
+#else
+ QCOMPARE(list.at(0)->rootIndex().data().toString(), temp.dirName());
+#endif
+ QNonNativeFileDialog *dlg = new QNonNativeFileDialog(0, "", tempPath);
+ QCOMPARE(model->index(tempPath), model->index(dlg->directory().absolutePath()));
+ QCOMPARE(model->index(tempPath).data(QFileSystemModel::FileNameRole).toString(),
+ model->index(dlg->directory().absolutePath()).data(QFileSystemModel::FileNameRole).toString());
+ delete dlg;
+ dlg = new QNonNativeFileDialog();
+ QCOMPARE(model->index(tempPath), model->index(dlg->directory().absolutePath()));
+ delete dlg;
+}
+
+void tst_QFiledialog::completer_data()
+{
+ QTest::addColumn<QString>("startPath");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("r, 10") << "" << "r" << 10;
+ QTest::newRow("x, 0") << "" << "x" << 0;
+ QTest::newRow("../, -1") << "" << "../" << -1;
+
+ QTest::newRow("goto root") << QString() << QDir::rootPath() << -1;
+ QTest::newRow("start at root") << QDir::rootPath() << QString() << -1;
+
+ QDir root = QDir::root();
+ QStringList list = root.entryList();
+ QString folder;
+ for (int i = 0; i < list.count(); ++i) {
+ if (list.at(0) == QChar('.'))
+ continue;
+ QFileInfo info(QDir::rootPath() + list[i]);
+ if (info.isDir()) {
+ folder = QDir::rootPath() + list[i];
+ break;
+ }
+ }
+
+ QTest::newRow("start at one below root r") << folder << "r" << -1;
+ QTest::newRow("start at one below root ../") << folder << "../" << -1;
+}
+
+void tst_QFiledialog::completer()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, startPath);
+ QFETCH(int, expected);
+
+ QString tempPath = QDir::tempPath() + '/' + "QFileDialogTestDir";
+ if (startPath.isEmpty())
+ startPath = tempPath;
+
+ startPath = QDir::cleanPath(startPath);
+
+ // make temp dir and files
+ {
+ QDir cleanup(tempPath);
+ QStringList x = cleanup.entryList();
+ for (int i = 0; i < x.count(); ++i)
+ QFile::remove(tempPath + '/' + x[i]);
+ cleanup.rmdir(tempPath);
+ }
+ QDir tmp(QDir::tempPath());
+ if (!tmp.exists(tempPath))
+ QVERIFY(tmp.mkdir("QFileDialogTestDir"));
+ QList<QTemporaryFile*> files;
+ QT_TRY {
+ for (int i = 0; i < 10; ++i) {
+ QScopedPointer<QTemporaryFile> file(new QTemporaryFile(tempPath + "/rXXXXXX"));
+ file->open();
+ files.append(file.take());
+ }
+
+ // ### flesh this out more
+ QNonNativeFileDialog fd(0,QString("Test it"),startPath);
+ fd.setOptions(QFileDialog::DontUseNativeDialog);
+ fd.show();
+ QVERIFY(fd.isVisible());
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QVERIFY(lineEdit);
+ QCompleter *completer = lineEdit->completer();
+ QVERIFY(completer);
+ QAbstractItemModel *cModel = completer->completionModel();
+ QVERIFY(cModel);
+
+ //wait a bit
+ QTest::qWait(500);
+
+ // path C:\depot\qt\examples\dialogs\standarddialogs
+ // files
+ // [debug] [release] [tmp] dialog dialog main makefile makefile.debug makefile.release standarddialgos
+ //
+ // d -> D:\ debug dialog.cpp dialog.h
+ // ..\ -> ..\classwizard ..\configdialog ..\dialogs.pro
+ // c -> C:\ control panel
+ // c: -> C:\ (nothing more)
+ // C:\ -> C:\, C:\_viminfo, ...
+ // \ -> \_viminfo
+ // c:\depot -> 'nothing'
+ // c:\depot\ -> C:\depot\devtools, C:\depot\dteske
+ QCOMPARE(model->index(fd.directory().path()), model->index(startPath));
+
+ if (input.isEmpty()) {
+ QModelIndex r = model->index(model->rootPath());
+ QVERIFY(model->rowCount(r) > 0);
+ QModelIndex idx = model->index(0, 0, r);
+ input = idx.data().toString().at(0);
+ }
+
+ // press 'keys' for the input
+ for (int i = 0; i < input.count(); ++i)
+ QTest::keyPress(lineEdit, input[i].toAscii());
+
+ QStringList expectedFiles;
+ if (expected == -1) {
+ QString fullPath = startPath.isEmpty() ? tempPath : startPath;
+ if (!fullPath.endsWith(QLatin1Char('/')))
+ fullPath.append(QLatin1Char('/'));
+ fullPath.append(input);
+ bool inputStartsWithRootPath = false;
+ if (input.startsWith(QDir::rootPath())) {
+ fullPath = input;
+ input.clear();
+ inputStartsWithRootPath = true;
+ }
+
+ QFileInfo fi(fullPath);
+ QDir x(fi.absolutePath());
+ expectedFiles = x.entryList(model->filter());
+ expected = 0;
+ if (input.startsWith(".."))
+ input.clear();
+ for (int ii = 0; ii < expectedFiles.count(); ++ii) {
+#if defined(Q_OS_WIN)
+ if (expectedFiles.at(ii).startsWith(input,Qt::CaseInsensitive))
+#else
+ if (expectedFiles.at(ii).startsWith(input))
+#endif
+ ++expected;
+ }
+ }
+
+ QTest::qWait(1000);
+ if (cModel->rowCount() != expected) {
+ for (int i = 0; i < cModel->rowCount(); ++i) {
+ QString file = cModel->index(i, 0).data().toString();
+ expectedFiles.removeAll(file);
+ }
+ //qDebug() << expectedFiles;
+ }
+
+ QTRY_COMPARE(cModel->rowCount(), expected);
+ } QT_CATCH(...) {
+ qDeleteAll(files);
+ QT_RETHROW;
+ }
+ qDeleteAll(files);
+}
+
+void tst_QFiledialog::completer_up()
+{
+ QNonNativeFileDialog fd;
+ fd.setOptions(QFileDialog::DontUseNativeDialog);
+ QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
+ QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
+ QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+
+ fd.show();
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QVERIFY(lineEdit);
+ QCOMPARE(spyFilesSelected.count(), 0);
+ int depth = QDir::currentPath().split('/').count();
+ for (int i = 0; i <= depth * 3 + 1; ++i) {
+ lineEdit->insert("../");
+ qApp->processEvents();
+ }
+ QCOMPARE(spyCurrentChanged.count(), 0);
+ QCOMPARE(spyDirectoryEntered.count(), 0);
+ QCOMPARE(spyFilesSelected.count(), 0);
+ QCOMPARE(spyFilterSelected.count(), 0);
+}
+
+void tst_QFiledialog::acceptMode()
+{
+ QNonNativeFileDialog fd;
+ fd.show();
+
+ QToolButton* newButton = qFindChild<QToolButton*>(&fd, "newFolderButton");
+ QVERIFY(newButton);
+
+ // default
+ QCOMPARE(fd.acceptMode(), QFileDialog::AcceptOpen);
+ QCOMPARE(newButton && newButton->isVisible(), true);
+
+ //fd.setDetailsExpanded(true);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ QCOMPARE(fd.acceptMode(), QFileDialog::AcceptSave);
+ QCOMPARE(newButton->isVisible(), true);
+
+ fd.setAcceptMode(QFileDialog::AcceptOpen);
+ QCOMPARE(fd.acceptMode(), QFileDialog::AcceptOpen);
+ QCOMPARE(newButton->isVisible(), true);
+}
+
+void tst_QFiledialog::confirmOverwrite()
+{
+ QNonNativeFileDialog fd;
+ QCOMPARE(fd.confirmOverwrite(), true);
+ fd.setConfirmOverwrite(true);
+ QCOMPARE(fd.confirmOverwrite(), true);
+ fd.setConfirmOverwrite(false);
+ QCOMPARE(fd.confirmOverwrite(), false);
+ fd.setConfirmOverwrite(true);
+ QCOMPARE(fd.confirmOverwrite(), true);
+}
+
+void tst_QFiledialog::defaultSuffix()
+{
+ QNonNativeFileDialog fd;
+ QCOMPARE(fd.defaultSuffix(), QString());
+ fd.setDefaultSuffix("txt");
+ QCOMPARE(fd.defaultSuffix(), QString("txt"));
+ fd.setDefaultSuffix(QString());
+ QCOMPARE(fd.defaultSuffix(), QString());
+}
+
+void tst_QFiledialog::fileMode()
+{
+ QNonNativeFileDialog fd;
+ QCOMPARE(fd.fileMode(), QFileDialog::AnyFile);
+ fd.setFileMode(QFileDialog::ExistingFile);
+ QCOMPARE(fd.fileMode(), QFileDialog::ExistingFile);
+ fd.setFileMode(QFileDialog::Directory);
+ QCOMPARE(fd.fileMode(), QFileDialog::Directory);
+ fd.setFileMode(QFileDialog::DirectoryOnly);
+ QCOMPARE(fd.fileMode(), QFileDialog::DirectoryOnly);
+ fd.setFileMode(QFileDialog::ExistingFiles);
+ QCOMPARE(fd.fileMode(), QFileDialog::ExistingFiles);
+}
+
+void tst_QFiledialog::caption()
+{
+ QNonNativeFileDialog fd;
+ fd.setWindowTitle("testing");
+ fd.setFileMode(QFileDialog::Directory);
+ QCOMPARE(fd.windowTitle(), QString("testing"));
+}
+
+void tst_QFiledialog::filters()
+{
+ QNonNativeFileDialog fd;
+ fd.setOptions(QFileDialog::DontUseNativeDialog);
+ QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
+ QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
+ QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+ QCOMPARE(fd.filters(), QStringList("All Files (*)"));
+
+ // effects
+ QList<QComboBox*> views = qFindChildren<QComboBox*>(&fd, "fileTypeCombo");
+ QVERIFY(views.count() == 1);
+ QCOMPARE(views.at(0)->isVisible(), false);
+
+ QStringList filters;
+ filters << "Image files (*.png *.xpm *.jpg)"
+ << "Text files (*.txt)"
+ << "Any files (*.*)";
+ fd.setFilters(filters);
+ QCOMPARE(views.at(0)->isVisible(), false);
+ fd.show();
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ QCOMPARE(views.at(0)->isVisible(), true);
+ QCOMPARE(fd.filters(), filters);
+ fd.setFilter("Image files (*.png *.xpm *.jpg);;Text files (*.txt);;Any files (*.*)");
+ QCOMPARE(fd.filters(), filters);
+ QCOMPARE(spyCurrentChanged.count(), 0);
+ QCOMPARE(spyDirectoryEntered.count(), 0);
+ QCOMPARE(spyFilesSelected.count(), 0);
+ QCOMPARE(spyFilterSelected.count(), 0);
+
+ // setting shouldn't emit any signals
+ for (int i = views.at(0)->currentIndex(); i < views.at(0)->count(); ++i)
+ views.at(0)->setCurrentIndex(i);
+ QCOMPARE(spyFilterSelected.count(), 0);
+
+ //Let check if filters with whitespaces
+ QNonNativeFileDialog fd2;
+ QStringList expected;
+ expected << "C++ Source Files(*.cpp)";
+ expected << "Any(*.*)";
+ fd2.setFilter("C++ Source Files(*.cpp);;Any(*.*)");
+ QCOMPARE(expected, fd2.filters());
+ fd2.setFilter("C++ Source Files(*.cpp) ;;Any(*.*)");
+ QCOMPARE(expected, fd2.filters());
+ fd2.setFilter("C++ Source Files(*.cpp);; Any(*.*)");
+ QCOMPARE(expected, fd2.filters());
+ fd2.setFilter(" C++ Source Files(*.cpp);; Any(*.*)");
+ QCOMPARE(expected, fd2.filters());
+ fd2.setFilter("C++ Source Files(*.cpp) ;; Any(*.*)");
+ QCOMPARE(expected, fd2.filters());
+}
+
+void tst_QFiledialog::selectFilter()
+{
+ QNonNativeFileDialog fd;
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+ QCOMPARE(fd.selectedFilter(), QString("All Files (*)"));
+ QStringList filters;
+ filters << "Image files (*.png *.xpm *.jpg)"
+ << "Text files (*.txt)"
+ << "Any files (*.*)";
+ fd.setFilters(filters);
+ QCOMPARE(fd.selectedFilter(), filters.at(0));
+ fd.selectFilter(filters.at(1));
+ QCOMPARE(fd.selectedFilter(), filters.at(1));
+ fd.selectFilter(filters.at(2));
+ QCOMPARE(fd.selectedFilter(), filters.at(2));
+
+ fd.selectFilter("bob");
+ QCOMPARE(fd.selectedFilter(), filters.at(2));
+ fd.selectFilter("");
+ QCOMPARE(fd.selectedFilter(), filters.at(2));
+ QCOMPARE(spyFilterSelected.count(), 0);
+}
+
+void tst_QFiledialog::history()
+{
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
+ QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
+ QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+ QCOMPARE(model->index(fd.history().first()), model->index(QDir::toNativeSeparators(fd.directory().absolutePath())));
+ fd.setDirectory(QDir::current().absolutePath());
+ QStringList history;
+ history << QDir::toNativeSeparators(QDir::current().absolutePath())
+ << QDir::toNativeSeparators(QDir::home().absolutePath())
+ << QDir::toNativeSeparators(QDir::temp().absolutePath());
+ fd.setHistory(history);
+ if (fd.history() != history) {
+ qDebug() << fd.history() << history;
+ // quick and dirty output for windows failure.
+ QListView* list = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(list);
+ QModelIndex root = list->rootIndex();
+ while (root.isValid()) {
+ qDebug() << root.data();
+ root = root.parent();
+ }
+ }
+ QCOMPARE(fd.history(), history);
+
+ QStringList badHistory;
+ badHistory << "junk";
+ fd.setHistory(badHistory);
+ badHistory << QDir::toNativeSeparators(QDir::current().absolutePath());
+ QCOMPARE(fd.history(), badHistory);
+
+ QCOMPARE(spyCurrentChanged.count(), 0);
+ QCOMPARE(spyDirectoryEntered.count(), 0);
+ QCOMPARE(spyFilesSelected.count(), 0);
+ QCOMPARE(spyFilterSelected.count(), 0);
+}
+
+void tst_QFiledialog::iconProvider()
+{
+ QNonNativeFileDialog *fd = new QNonNativeFileDialog();
+ QVERIFY(fd->iconProvider() != 0);
+ QFileIconProvider *ip = new QFileIconProvider();
+ fd->setIconProvider(ip);
+ QCOMPARE(fd->iconProvider(), ip);
+ delete fd;
+ delete ip;
+}
+
+void tst_QFiledialog::isReadOnly()
+{
+ QNonNativeFileDialog fd;
+
+ QPushButton* newButton = qFindChild<QPushButton*>(&fd, "newFolderButton");
+ QAction* renameAction = qFindChild<QAction*>(&fd, "qt_rename_action");
+ QAction* deleteAction = qFindChild<QAction*>(&fd, "qt_delete_action");
+
+ QCOMPARE(fd.isReadOnly(), false);
+
+ // This is dependent upon the file/dir, find cross platform way to test
+ //fd.setDirectory(QDir::home());
+ //QCOMPARE(newButton && newButton->isEnabled(), true);
+ //QCOMPARE(renameAction && renameAction->isEnabled(), true);
+ //QCOMPARE(deleteAction && deleteAction->isEnabled(), true);
+
+ fd.setReadOnly(true);
+ QCOMPARE(fd.isReadOnly(), true);
+
+ QCOMPARE(newButton && newButton->isEnabled(), false);
+ QCOMPARE(renameAction && renameAction->isEnabled(), false);
+ QCOMPARE(deleteAction && deleteAction->isEnabled(), false);
+}
+
+void tst_QFiledialog::itemDelegate()
+{
+ QNonNativeFileDialog fd;
+ QVERIFY(fd.itemDelegate() != 0);
+ QItemDelegate *id = new QItemDelegate(&fd);
+ fd.setItemDelegate(id);
+ QCOMPARE(fd.itemDelegate(), (QAbstractItemDelegate *)id);
+}
+
+void tst_QFiledialog::labelText()
+{
+ QNonNativeFileDialog fd;
+ QDialogButtonBox buttonBox;
+ QPushButton *cancelButton = buttonBox.addButton(QDialogButtonBox::Cancel);
+ QCOMPARE(fd.labelText(QFileDialog::LookIn), QString("Look in:"));
+ QCOMPARE(fd.labelText(QFileDialog::FileName), QString("File &name:"));
+ QCOMPARE(fd.labelText(QFileDialog::FileType), QString("Files of type:"));
+ QCOMPARE(fd.labelText(QFileDialog::Accept), QString("&Open")); ///### see task 241462
+ QCOMPARE(fd.labelText(QFileDialog::Reject), cancelButton->text());
+
+ fd.setLabelText(QFileDialog::LookIn, "1");
+ QCOMPARE(fd.labelText(QFileDialog::LookIn), QString("1"));
+ fd.setLabelText(QFileDialog::FileName, "2");
+ QCOMPARE(fd.labelText(QFileDialog::FileName), QString("2"));
+ fd.setLabelText(QFileDialog::FileType, "3");
+ QCOMPARE(fd.labelText(QFileDialog::FileType), QString("3"));
+ fd.setLabelText(QFileDialog::Accept, "4");
+ QCOMPARE(fd.labelText(QFileDialog::Accept), QString("4"));
+ fd.setLabelText(QFileDialog::Reject, "5");
+ QCOMPARE(fd.labelText(QFileDialog::Reject), QString("5"));
+}
+
+void tst_QFiledialog::resolveSymlinks()
+{
+ QNonNativeFileDialog fd;
+
+ // default
+ QCOMPARE(fd.resolveSymlinks(), true);
+ fd.setResolveSymlinks(false);
+ QCOMPARE(fd.resolveSymlinks(), false);
+ fd.setResolveSymlinks(true);
+ QCOMPARE(fd.resolveSymlinks(), true);
+
+ // the file dialog doesn't do anything based upon this, just passes it to the model
+ // the model should fully test it, don't test it here
+}
+
+void tst_QFiledialog::selectFile_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<int>("count");
+ QTest::newRow("null") << QString() << 1;
+ QTest::newRow("file") << "foo" << 1;
+ QTest::newRow("tmp") << "temp" << 1;
+}
+
+void tst_QFiledialog::selectFile()
+{
+ QFETCH(QString, file);
+ QFETCH(int, count);
+ QNonNativeFileDialog fd;
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ fd.setDirectory(QDir::currentPath());
+ // default value
+ QCOMPARE(fd.selectedFiles().count(), 1);
+
+ QTemporaryFile tempFile(QDir::tempPath() + "/aXXXXXX");
+ bool inTemp = (file == "temp");
+ if (inTemp) {
+ tempFile.open();
+ file = tempFile.fileName();
+ }
+
+ fd.selectFile(file);
+ QCOMPARE(fd.selectedFiles().count(), count);
+ if (inTemp) {
+ QCOMPARE(model->index(fd.directory().path()), model->index(QDir::tempPath()));
+ } else {
+ QCOMPARE(model->index(fd.directory().path()), model->index(QDir::currentPath()));
+ }
+}
+
+void tst_QFiledialog::selectFiles()
+{
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ QString tempPath = QDir::tempPath() + '/' + "QFileDialogTestDir4SelectFiles";
+ QDir dir;
+ QVERIFY(dir.mkpath(tempPath));
+ fd.setDirectory(tempPath);
+ QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
+ QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
+ QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
+ QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
+ fd.show();
+ fd.setFileMode(QFileDialog::ExistingFiles);
+
+ QString filesPath = fd.directory().absolutePath();
+ for (int i=0; i < 5; ++i) {
+ QFile file(filesPath + QString::fromLatin1("/qfiledialog_auto_test_not_pres_%1").arg(i));
+ file.open(QIODevice::WriteOnly);
+ file.resize(1024);
+ file.flush();
+ file.close();
+ }
+
+ // Get a list of files in the view and then get the corresponding index's
+ QStringList list = fd.directory().entryList(QDir::Files);
+ QModelIndexList toSelect;
+ QVERIFY(list.count() > 1);
+ QListView* listView = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(listView);
+ for (int i = 0; i < list.count(); ++i) {
+ fd.selectFile(fd.directory().path() + "/" + list.at(i));
+#if defined(Q_WS_MAC) || defined(Q_WS_WIN)
+ QEXPECT_FAIL("", "This test does not work on Mac or Windows", Abort);
+#endif
+ QTRY_VERIFY(!listView->selectionModel()->selectedRows().isEmpty());
+ toSelect.append(listView->selectionModel()->selectedRows().last());
+ }
+ QCOMPARE(spyFilesSelected.count(), 0);
+
+ listView->selectionModel()->clear();
+ QCOMPARE(spyFilesSelected.count(), 0);
+
+ // select the indexes
+ for (int i = 0; i < toSelect.count(); ++i) {
+ listView->selectionModel()->select(toSelect.at(i),
+ QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ }
+ QCOMPARE(fd.selectedFiles().count(), toSelect.count());
+ QCOMPARE(spyCurrentChanged.count(), 0);
+ QCOMPARE(spyDirectoryEntered.count(), 0);
+ QCOMPARE(spyFilesSelected.count(), 0);
+ QCOMPARE(spyFilterSelected.count(), 0);
+ for (int i=0; i < 5; ++i)
+ QFile::remove(filesPath + QString::fromLatin1("/qfiledialog_auto_test_not_pres_%1").arg(i));
+
+ //If the selection is invalid then we fill the line edit but without the /
+ QNonNativeFileDialog * dialog = new QNonNativeFileDialog( 0, "Save" );
+ dialog->setFileMode( QFileDialog::AnyFile );
+ dialog->setAcceptMode( QFileDialog::AcceptSave );
+ QString temporary = QDir::tempPath() + QLatin1String("/blah");
+ dialog->selectFile(temporary);
+ dialog->show();
+ QTest::qWait(500);
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(dialog, "fileNameEdit");
+ QVERIFY(lineEdit);
+ QCOMPARE(lineEdit->text(),QLatin1String("blah"));
+ delete dialog;
+}
+
+void tst_QFiledialog::viewMode()
+{
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ fd.show();
+
+ // find widgets
+ QList<QTreeView*> treeView = qFindChildren<QTreeView*>(&fd, "treeView");
+ QCOMPARE(treeView.count(), 1);
+ QList<QListView*> listView = qFindChildren<QListView*>(&fd, "listView");
+ QCOMPARE(listView.count(), 1);
+ QList<QToolButton*> listButton = qFindChildren<QToolButton*>(&fd, "listModeButton");
+ QCOMPARE(listButton.count(), 1);
+ QList<QToolButton*> treeButton = qFindChildren<QToolButton*>(&fd, "detailModeButton");
+ QCOMPARE(treeButton.count(), 1);
+
+ // default value
+ QCOMPARE(fd.viewMode(), QFileDialog::List);
+
+ // detail
+ fd.setViewMode(QFileDialog::ViewMode(QFileDialog::Detail));
+
+ QCOMPARE(QFileDialog::ViewMode(QFileDialog::Detail), fd.viewMode());
+ QCOMPARE(listView.at(0)->isVisible(), false);
+ QCOMPARE(listButton.at(0)->isDown(), false);
+ QCOMPARE(treeView.at(0)->isVisible(), true);
+ QCOMPARE(treeButton.at(0)->isDown(), true);
+
+ // list
+ fd.setViewMode(QFileDialog::ViewMode(QFileDialog::List));
+
+ QCOMPARE(QFileDialog::ViewMode(QFileDialog::List), fd.viewMode());
+ QCOMPARE(treeView.at(0)->isVisible(), false);
+ QCOMPARE(treeButton.at(0)->isDown(), false);
+ QCOMPARE(listView.at(0)->isVisible(), true);
+ QCOMPARE(listButton.at(0)->isDown(), true);
+}
+
+void tst_QFiledialog::proxymodel()
+{
+ QNonNativeFileDialog fd;
+ QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0);
+
+ fd.setProxyModel(0);
+ QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0);
+
+ QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(&fd);
+ fd.setProxyModel(proxyModel);
+ QCOMPARE(fd.proxyModel(), (QAbstractProxyModel *)proxyModel);
+
+ fd.setProxyModel(0);
+ QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0);
+}
+
+void tst_QFiledialog::setNameFilter()
+{
+ QNonNativeFileDialog fd;
+ fd.setFilter(QString());
+ fd.setFilters(QStringList());
+}
+
+void tst_QFiledialog::focus()
+{
+ QNonNativeFileDialog fd;
+ fd.setDirectory(QDir::currentPath());
+ fd.show();
+ QApplication::setActiveWindow(&fd);
+ QTest::qWaitForWindowShown(&fd);
+ QTRY_COMPARE(fd.isVisible(), true);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
+ qApp->processEvents();
+
+ // make sure the tests work with focus follows mouse
+ QCursor::setPos(fd.geometry().center());
+ QApplication::syncX();
+
+ QList<QWidget*> treeView = qFindChildren<QWidget*>(&fd, "fileNameEdit");
+ QCOMPARE(treeView.count(), 1);
+ QVERIFY(treeView.at(0));
+ QTRY_COMPARE(treeView.at(0)->hasFocus(), true);
+ QCOMPARE(treeView.at(0)->hasFocus(), true);
+}
+
+
+void tst_QFiledialog::historyBack()
+{
+ QNonNativeFileDialog fd;
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ QToolButton *backButton = qFindChild<QToolButton*>(&fd, "backButton");
+ QVERIFY(backButton);
+ QToolButton *forwardButton = qFindChild<QToolButton*>(&fd, "forwardButton");
+ QVERIFY(forwardButton);
+
+ QSignalSpy spy(model, SIGNAL(rootPathChanged(const QString &)));
+
+ QString home = fd.directory().absolutePath();
+ QString desktop = QDir::homePath();
+ QString temp = QDir::tempPath();
+
+ QCOMPARE(backButton->isEnabled(), false);
+ QCOMPARE(forwardButton->isEnabled(), false);
+ fd.setDirectory(temp);
+ qApp->processEvents();
+ QCOMPARE(backButton->isEnabled(), true);
+ QCOMPARE(forwardButton->isEnabled(), false);
+ fd.setDirectory(desktop);
+ QCOMPARE(spy.count(), 2);
+
+ backButton->click();
+ qApp->processEvents();
+ QCOMPARE(backButton->isEnabled(), true);
+ QCOMPARE(forwardButton->isEnabled(), true);
+ QCOMPARE(spy.count(), 3);
+ QString currentPath = qVariantValue<QString>(spy.last().first());
+ QCOMPARE(model->index(currentPath), model->index(temp));
+
+ backButton->click();
+ currentPath = qVariantValue<QString>(spy.last().first());
+ QCOMPARE(currentPath, home);
+ QCOMPARE(backButton->isEnabled(), false);
+ QCOMPARE(forwardButton->isEnabled(), true);
+ QCOMPARE(spy.count(), 4);
+
+ // nothing should change at this point
+ backButton->click();
+ QCOMPARE(spy.count(), 4);
+ QCOMPARE(backButton->isEnabled(), false);
+ QCOMPARE(forwardButton->isEnabled(), true);
+}
+
+void tst_QFiledialog::historyForward()
+{
+ QNonNativeFileDialog fd;
+ fd.setDirectory(QDir::currentPath());
+ QToolButton *backButton = qFindChild<QToolButton*>(&fd, "backButton");
+ QVERIFY(backButton);
+ QToolButton *forwardButton = qFindChild<QToolButton*>(&fd, "forwardButton");
+ QVERIFY(forwardButton);
+
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ QSignalSpy spy(model, SIGNAL(rootPathChanged(const QString &)));
+
+ QString home = fd.directory().absolutePath();
+ QString desktop = QDir::homePath();
+ QString temp = QDir::tempPath();
+
+ fd.setDirectory(home);
+ fd.setDirectory(temp);
+ fd.setDirectory(desktop);
+
+ backButton->click();
+ QCOMPARE(forwardButton->isEnabled(), true);
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(temp));
+
+ forwardButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(desktop));
+ QCOMPARE(backButton->isEnabled(), true);
+ QCOMPARE(forwardButton->isEnabled(), false);
+ QCOMPARE(spy.count(), 4);
+
+ backButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(temp));
+ QCOMPARE(backButton->isEnabled(), true);
+
+ backButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(home));
+ QCOMPARE(backButton->isEnabled(), false);
+ QCOMPARE(forwardButton->isEnabled(), true);
+ QCOMPARE(spy.count(), 6);
+
+ forwardButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(temp));
+ backButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(home));
+ QCOMPARE(spy.count(), 8);
+
+ forwardButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(temp));
+ forwardButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(desktop));
+
+ backButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(temp));
+ backButton->click();
+ QCOMPARE(model->index(qVariantValue<QString>(spy.last().first())), model->index(home));
+ fd.setDirectory(desktop);
+ QCOMPARE(forwardButton->isEnabled(), false);
+}
+
+void tst_QFiledialog::disableSaveButton_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("isEnabled");
+
+ QTest::newRow("valid path") << QDir::temp().absolutePath() + QDir::separator() + "qfiledialog.new_file" << true;
+ QTest::newRow("no path") << "" << false;
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_OPENBSD)
+ QTest::newRow("too long path") << "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" << false;
+#endif
+ QTest::newRow("file") << "foo.html" << true;
+}
+
+void tst_QFiledialog::disableSaveButton()
+{
+ QFETCH(QString, path);
+ QFETCH(bool, isEnabled);
+
+ QNonNativeFileDialog fd(0, "caption", path);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Save);
+ QVERIFY(button);
+ QCOMPARE(button->isEnabled(), isEnabled);
+}
+
+void tst_QFiledialog::saveButtonText_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("label");
+ QTest::addColumn<QString>("caption");
+
+ QTest::newRow("empty path") << "" << QString() << QFileDialog::tr("&Save");
+ QTest::newRow("file path") << "qfiledialog.new_file" << QString() << QFileDialog::tr("&Save");
+ QTest::newRow("dir") << QDir::temp().absolutePath() << QString() << QFileDialog::tr("&Open");
+ QTest::newRow("setTextLabel") << "qfiledialog.new_file" << "Mooo" << "Mooo";
+ QTest::newRow("dir & label") << QDir::temp().absolutePath() << "Poo" << QFileDialog::tr("&Open");
+}
+
+void tst_QFiledialog::saveButtonText()
+{
+ QFETCH(QString, path);
+ QFETCH(QString, label);
+ QFETCH(QString, caption);
+
+ QNonNativeFileDialog fd(0, "auto test", QDir::temp().absolutePath());
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ if (!label.isNull())
+ fd.setLabelText(QFileDialog::Accept, label);
+ fd.setDirectory(QDir::temp());
+ fd.selectFile(path);
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QVERIFY(buttonBox);
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Save);
+ QVERIFY(button);
+ QCOMPARE(button->text(), caption);
+}
+
+void tst_QFiledialog::clearLineEdit()
+{
+ QNonNativeFileDialog fd(0, "caption", "foo");
+ fd.setViewMode(QFileDialog::List);
+ fd.setFileMode(QFileDialog::AnyFile);
+ fd.setOptions(QFileDialog::DontUseNativeDialog);
+ fd.show();
+
+ //play it really safe by creating a directory
+ QDir::home().mkdir("_____aaaaaaaaaaaaaaaaaaaaaa");
+
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QVERIFY(lineEdit);
+ QVERIFY(lineEdit->text() == "foo");
+ fd.setDirectory(QDir::home());
+
+ QListView* list = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(list);
+
+ // saving a file the text shouldn't be cleared
+ fd.setDirectory(QDir::home());
+
+ QTest::qWait(1000);
+#ifdef QT_KEYPAD_NAVIGATION
+ list->setEditFocus(true);
+#endif
+ QTest::keyClick(list, Qt::Key_Down);
+#ifndef Q_WS_MAC
+ QTest::keyClick(list, Qt::Key_Return);
+#else
+ QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
+#endif
+
+ QTest::qWait(2000);
+ QVERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
+ QVERIFY(!lineEdit->text().isEmpty());
+
+ // selecting a dir the text should be cleared so one can just hit ok
+ // and it selects that directory
+ fd.setFileMode(QNonNativeFileDialog::Directory);
+ fd.setDirectory(QDir::home());
+
+ QTest::qWait(1000);
+ QTest::keyClick(list, Qt::Key_Down);
+#ifndef Q_WS_MAC
+ QTest::keyClick(list, Qt::Key_Return);
+#else
+ QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
+#endif
+
+ QTest::qWait(2000);
+ QVERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
+ QVERIFY(lineEdit->text().isEmpty());
+
+ //remove the dir
+ QDir::home().rmdir("_____aaaaaaaaaaaaaaaaaaaaaa");
+}
+
+void tst_QFiledialog::enableChooseButton()
+{
+ QNonNativeFileDialog fd;
+ fd.setFileMode(QFileDialog::Directory);
+ fd.show();
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Open);
+ QVERIFY(button);
+ QCOMPARE(button->isEnabled(), true);
+}
+
+QT_BEGIN_NAMESPACE
+typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
+extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook;
+QT_END_NAMESPACE
+QString existing(QWidget *, const QString &, const QString &, QFileDialog::Options) {
+ return "dir";
+}
+
+QT_BEGIN_NAMESPACE
+typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
+extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook;
+QT_END_NAMESPACE
+QString openName(QWidget *, const QString &, const QString &, const QString &, QString *, QFileDialog::Options) {
+ return "openName";
+}
+
+QT_BEGIN_NAMESPACE
+typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
+extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook;
+QT_END_NAMESPACE
+QStringList openNames(QWidget *, const QString &, const QString &, const QString &, QString *, QFileDialog::Options) {
+ return QStringList("openNames");
+}
+
+QT_BEGIN_NAMESPACE
+typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
+extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook;
+QT_END_NAMESPACE
+QString saveName(QWidget *, const QString &, const QString &, const QString &, QString *, QFileDialog::Options) {
+ return "saveName";
+}
+
+
+void tst_QFiledialog::hooks()
+{
+ qt_filedialog_existing_directory_hook = &existing;
+ qt_filedialog_save_filename_hook = &saveName;
+ qt_filedialog_open_filename_hook = &openName;
+ qt_filedialog_open_filenames_hook = &openNames;
+
+ QCOMPARE(QFileDialog::getExistingDirectory(), QString("dir"));
+ QCOMPARE(QFileDialog::getOpenFileName(), QString("openName"));
+ QCOMPARE(QFileDialog::getOpenFileNames(), QStringList("openNames"));
+ QCOMPARE(QFileDialog::getSaveFileName(), QString("saveName"));
+}
+
+// Test case relies on developer build (AUTOTEST_EXPORT).
+#if defined(Q_OS_UNIX) && defined(QT_BUILD_INTERNAL)
+void tst_QFiledialog::tildeExpansion_data()
+{
+ QTest::addColumn<QString>("tildePath");
+ QTest::addColumn<QString>("expandedPath");
+
+ QTest::newRow("empty path") << QString() << QString();
+ QTest::newRow("~") << QString::fromLatin1("~") << QDir::homePath();
+ QTest::newRow("~/some/sub/dir/") << QString::fromLatin1("~/some/sub/dir") << QDir::homePath()
+ + QString::fromLatin1("/some/sub/dir");
+ QString userHome = QString(qgetenv("USER"));
+ userHome.prepend('~');
+ QTest::newRow("current user (~<user> syntax)") << userHome << QDir::homePath();
+ QString invalid = QString::fromLatin1("~thisIsNotAValidUserName");
+ QTest::newRow("invalid user name") << invalid << invalid;
+}
+
+void tst_QFiledialog::tildeExpansion()
+{
+ QFETCH(QString, tildePath);
+ QFETCH(QString, expandedPath);
+
+ QCOMPARE(qt_tildeExpansion(tildePath), expandedPath);
+}
+#endif
+
+QTEST_MAIN(tst_QFiledialog)
+#include "tst_qfiledialog.moc"
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro
new file mode 100644
index 0000000000..a2149c8a39
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro
@@ -0,0 +1,20 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qfiledialog2.cpp
+
+wince* {
+ addFiles.files = *.cpp
+ addFiles.path = .
+ filesInDir.files = *.pro
+ filesInDir.path = someDir
+ DEPLOYMENT += addFiles filesInDir
+}
+
+wince* {
+ DEFINES += SRCDIR=\\\"./\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
new file mode 100644
index 0000000000..a2d18eb847
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -0,0 +1,1213 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qfiledialog.h>
+#include <qabstractitemdelegate.h>
+#include <qdirmodel.h>
+#include <qitemdelegate.h>
+#include <qlistview.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qtreeview.h>
+#include <qheaderview.h>
+#include <qcompleter.h>
+#include <qaction.h>
+#include <qdialogbuttonbox.h>
+#include <qsortfilterproxymodel.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include "../../../../../src/widgets/dialogs/qsidebar_p.h"
+#include "../../../../../src/widgets/dialogs/qfilesystemmodel_p.h"
+#include "../../../../../src/widgets/dialogs/qfiledialog_p.h"
+
+#include "../../../network-settings.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#if defined QT_BUILD_INTERNAL
+QT_BEGIN_NAMESPACE
+Q_GUI_EXPORT bool qt_test_isFetchedRoot();
+Q_GUI_EXPORT void qt_test_resetFetchedRoot();
+QT_END_NAMESPACE
+#endif
+
+class QNonNativeFileDialog : public QFileDialog
+{
+ Q_OBJECT
+public:
+ QNonNativeFileDialog(QWidget *parent = 0, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString())
+ : QFileDialog(parent, caption, directory, filter)
+ {
+ setOption(QFileDialog::DontUseNativeDialog, true);
+ }
+};
+
+class tst_QFileDialog2 : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QFileDialog2();
+ virtual ~tst_QFileDialog2();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void listRoot();
+ void heapCorruption();
+ void deleteDirAndFiles();
+ void filter();
+ void showNameFilterDetails();
+ void unc();
+ void emptyUncPath();
+
+ void task178897_minimumSize();
+ void task180459_lastDirectory_data();
+ void task180459_lastDirectory();
+ void task227304_proxyOnFileDialog();
+ void task227930_correctNavigationKeyboardBehavior();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ void task226366_lowerCaseHardDriveWindows();
+#endif
+ void completionOnLevelAfterRoot();
+ void task233037_selectingDirectory();
+ void task235069_hideOnEscape();
+ void task236402_dontWatchDeletedDir();
+ void task203703_returnProperSeparator();
+ void task228844_ensurePreviousSorting();
+ void task239706_editableFilterCombo();
+ void task218353_relativePaths();
+ void task251321_sideBarHiddenEntries();
+ void task251341_sideBarRemoveEntries();
+ void task254490_selectFileMultipleTimes();
+ void task257579_sideBarWithNonCleanUrls();
+ void task259105_filtersCornerCases();
+
+ void QTBUG4419_lineEditSelectAll();
+ void QTBUG6558_showDirsOnly();
+ void QTBUG4842_selectFilterWithHideNameFilterDetails();
+ void dontShowCompleterOnRoot();
+
+private:
+ QByteArray userSettings;
+};
+
+tst_QFileDialog2::tst_QFileDialog2()
+{
+#if defined(Q_OS_WINCE)
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+tst_QFileDialog2::~tst_QFileDialog2()
+{
+}
+
+void tst_QFileDialog2::init()
+{
+ // Save the developers settings so they don't get mad when their sidebar folders are gone.
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ userSettings = settings.value(QLatin1String("filedialog")).toByteArray();
+ settings.remove(QLatin1String("filedialog"));
+
+ // populate it with some default settings
+ QNonNativeFileDialog fd;
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1000);
+#endif
+}
+
+void tst_QFileDialog2::cleanup()
+{
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ settings.setValue(QLatin1String("filedialog"), userSettings);
+}
+
+void tst_QFileDialog2::listRoot()
+{
+#if defined QT_BUILD_INTERNAL
+ QFileInfoGatherer fileInfoGatherer;
+ fileInfoGatherer.start();
+ QTest::qWait(1500);
+ qt_test_resetFetchedRoot();
+ QString dir(QDir::currentPath());
+ QNonNativeFileDialog fd(0, QString(), dir);
+ fd.show();
+ QCOMPARE(qt_test_isFetchedRoot(),false);
+ fd.setDirectory("");
+#ifdef Q_OS_WINCE
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QCOMPARE(qt_test_isFetchedRoot(),true);
+#endif
+}
+
+void tst_QFileDialog2::heapCorruption()
+{
+ QVector<QNonNativeFileDialog*> dialogs;
+ for (int i=0; i < 10; i++) {
+ QNonNativeFileDialog *f = new QNonNativeFileDialog(NULL);
+ dialogs << f;
+ }
+ qDeleteAll(dialogs);
+}
+
+struct FriendlyQFileDialog : public QNonNativeFileDialog
+{
+ friend class tst_QFileDialog2;
+ Q_DECLARE_PRIVATE(QFileDialog)
+};
+
+
+void tst_QFileDialog2::deleteDirAndFiles()
+{
+#if defined QT_BUILD_INTERNAL
+ QString tempPath = QDir::tempPath() + '/' + "QFileDialogTestDir4FullDelete";
+ QDir dir;
+ QVERIFY(dir.mkpath(tempPath + "/foo"));
+ QVERIFY(dir.mkpath(tempPath + "/foo/B"));
+ QVERIFY(dir.mkpath(tempPath + "/foo/B"));
+ QVERIFY(dir.mkpath(tempPath + "/foo/c"));
+ QVERIFY(dir.mkpath(tempPath + "/bar"));
+ QFile(tempPath + "/foo/a");
+ QTemporaryFile *t;
+ t = new QTemporaryFile(tempPath + "/foo/aXXXXXX");
+ t->setAutoRemove(false);
+ t->open();
+ t->close();
+ delete t;
+
+ t = new QTemporaryFile(tempPath + "/foo/B/yXXXXXX");
+ t->setAutoRemove(false);
+ t->open();
+ t->close();
+ delete t;
+ FriendlyQFileDialog fd;
+ fd.setOption(QFileDialog::DontUseNativeDialog);
+ fd.d_func()->removeDirectory(tempPath);
+ QFileInfo info(tempPath);
+ QTest::qWait(2000);
+ QVERIFY(!info.exists());
+#endif
+}
+
+void tst_QFileDialog2::filter()
+{
+ QNonNativeFileDialog fd;
+ QAction *hiddenAction = qFindChild<QAction*>(&fd, "qt_show_hidden_action");
+ QVERIFY(hiddenAction);
+ QVERIFY(hiddenAction->isEnabled());
+ QVERIFY(!hiddenAction->isChecked());
+ QDir::Filters filter = fd.filter();
+ filter |= QDir::Hidden;
+ fd.setFilter(filter);
+ QVERIFY(hiddenAction->isChecked());
+}
+
+void tst_QFileDialog2::showNameFilterDetails()
+{
+ QNonNativeFileDialog fd;
+ QComboBox *filters = qFindChild<QComboBox*>(&fd, "fileTypeCombo");
+ QVERIFY(filters);
+ QVERIFY(fd.isNameFilterDetailsVisible());
+
+
+ QStringList filterChoices;
+ filterChoices << "Image files (*.png *.xpm *.jpg)"
+ << "Text files (*.txt)"
+ << "Any files (*.*)";
+ fd.setFilters(filterChoices);
+
+ fd.setNameFilterDetailsVisible(false);
+ QCOMPARE(filters->itemText(0), QString("Image files"));
+ QCOMPARE(filters->itemText(1), QString("Text files"));
+ QCOMPARE(filters->itemText(2), QString("Any files"));
+
+ fd.setNameFilterDetailsVisible(true);
+ QCOMPARE(filters->itemText(0), filterChoices.at(0));
+ QCOMPARE(filters->itemText(1), filterChoices.at(1));
+ QCOMPARE(filters->itemText(2), filterChoices.at(2));
+}
+
+void tst_QFileDialog2::unc()
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ // Only test UNC on Windows./
+ QString dir("\\\\" + QtNetworkSettings::winServerName() + "\\testsharewritable");
+#else
+ QString dir(QDir::currentPath());
+#endif
+ QVERIFY(QFile::exists(dir));
+ QNonNativeFileDialog fd(0, QString(), dir);
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+ QCOMPARE(model->index(fd.directory().absolutePath()), model->index(dir));
+}
+
+void tst_QFileDialog2::emptyUncPath()
+{
+ QNonNativeFileDialog fd;
+ fd.show();
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QVERIFY(lineEdit);
+ // press 'keys' for the input
+ for (int i = 0; i < 3 ; ++i)
+ QTest::keyPress(lineEdit, Qt::Key_Backslash);
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QVERIFY(model);
+}
+
+void tst_QFileDialog2::task178897_minimumSize()
+{
+ QNonNativeFileDialog fd;
+ QSize oldMs = fd.layout()->minimumSize();
+ QStringList history = fd.history();
+ history << QDir::toNativeSeparators("/verylongdirectory/"
+ "aaaaaaaaaabbbbbbbbcccccccccccddddddddddddddeeeeeeeeeeeeffffffffffgggtggggggggghhhhhhhhiiiiiijjjk");
+ fd.setHistory(history);
+ fd.show();
+
+ QSize ms = fd.layout()->minimumSize();
+ QVERIFY(ms.width() <= oldMs.width());
+}
+
+void tst_QFileDialog2::task180459_lastDirectory_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("directory");
+ QTest::addColumn<bool>("isEnabled");
+ QTest::addColumn<QString>("result");
+
+ QTest::newRow("path+file") << QDir::homePath() + QDir::separator() + "foo"
+ << QDir::homePath() << true
+ << QDir::homePath() + QDir::separator() + "foo" ;
+ QTest::newRow("no path") << ""
+ << QDir::tempPath() << false << QString();
+ QTest::newRow("file") << "foo"
+ << QDir::currentPath() << true
+ << QDir::currentPath() + QDir::separator() + "foo" ;
+ QTest::newRow("path") << QDir::homePath()
+ << QDir::homePath() << false << QString();
+ QTest::newRow("path not existing") << "/usr/bin/foo/bar/foo/foo.txt"
+ << QDir::tempPath() << true
+ << QDir::tempPath() + QDir::separator() + "foo.txt";
+
+}
+
+void tst_QFileDialog2::task180459_lastDirectory()
+{
+ //first visit the temp directory and close the dialog
+ QNonNativeFileDialog *dlg = new QNonNativeFileDialog(0, "", QDir::tempPath());
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(dlg, "qt_filesystem_model");
+ QVERIFY(model);
+ QCOMPARE(model->index(QDir::tempPath()), model->index(dlg->directory().absolutePath()));
+ delete dlg;
+
+ QFETCH(QString, path);
+ QFETCH(QString, directory);
+ QFETCH(bool, isEnabled);
+ QFETCH(QString, result);
+
+ dlg = new QNonNativeFileDialog(0, "", path);
+ model = qFindChild<QFileSystemModel*>(dlg, "qt_filesystem_model");
+ QVERIFY(model);
+ dlg->setAcceptMode(QFileDialog::AcceptSave);
+ QCOMPARE(model->index(dlg->directory().absolutePath()), model->index(directory));
+
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(dlg, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Save);
+ QVERIFY(button);
+ QCOMPARE(button->isEnabled(), isEnabled);
+ if (isEnabled)
+ QCOMPARE(model->index(result), model->index(dlg->selectedFiles().first()));
+
+ delete dlg;
+}
+
+
+
+class FilterDirModel : public QSortFilterProxyModel
+{
+
+public:
+ FilterDirModel(QString root, QObject* parent=0):QSortFilterProxyModel(parent), m_root(root)
+ {}
+ ~FilterDirModel()
+ {};
+
+protected:
+ bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
+ {
+ QModelIndex parentIndex;
+ parentIndex = source_parent;
+
+ QString path;
+ path = parentIndex.child(source_row,0).data(Qt::DisplayRole).toString();
+
+ do {
+ path = parentIndex.data(Qt::DisplayRole).toString() + "/" + path;
+ parentIndex = parentIndex.parent();
+ } while(parentIndex.isValid());
+
+ QFileInfo info(path);
+ if (info.isDir() && (QDir(path) != m_root))
+ return false;
+ return true;
+ }
+
+
+private:
+ QDir m_root;
+
+
+};
+
+class sortProxy : public QSortFilterProxyModel
+{
+public:
+ sortProxy(QObject *parent) : QSortFilterProxyModel(parent)
+ {
+ }
+protected:
+ virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const
+ {
+ QFileSystemModel * const model = qobject_cast<QFileSystemModel *>(sourceModel());
+ const QFileInfo leftInfo(model->fileInfo(left));
+ const QFileInfo rightInfo(model->fileInfo(right));
+
+ if (leftInfo.isDir() == rightInfo.isDir())
+ return(leftInfo.filePath().compare(rightInfo.filePath(),Qt::CaseInsensitive) < 0);
+ else if (leftInfo.isDir())
+ return(false);
+ else
+ return(true);
+ }
+};
+
+class CrashDialog : public QNonNativeFileDialog
+{
+ Q_OBJECT
+
+public:
+ CrashDialog(QWidget *parent, const QString &caption, const
+QString &dir, const QString &filter)
+ : QNonNativeFileDialog(parent, caption, dir, filter)
+ {
+ sortProxy *proxyModel = new sortProxy(this);
+ setProxyModel(proxyModel);
+ }
+};
+
+void tst_QFileDialog2::task227304_proxyOnFileDialog()
+{
+#if defined QT_BUILD_INTERNAL
+ QNonNativeFileDialog fd(0, "", QDir::currentPath(), 0);
+ fd.setProxyModel(new FilterDirModel(QDir::currentPath()));
+ fd.show();
+ QLineEdit *edit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QTest::qWait(200);
+ QTest::keyClick(edit, Qt::Key_T);
+ QTest::keyClick(edit, Qt::Key_S);
+ QTest::qWait(200);
+ QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
+
+ CrashDialog *dialog = new CrashDialog(0, QString("crash dialog test"), QDir::homePath(), QString("*") );
+ dialog->setFileMode(QFileDialog::ExistingFile);
+ dialog->show();
+
+ QListView *list = qFindChild<QListView*>(dialog, "listView");
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::keyClick(list, Qt::Key_Return);
+ QTest::qWait(200);
+
+ dialog->close();
+ fd.close();
+
+ QNonNativeFileDialog fd2(0, "I should not crash with a proxy", QDir::tempPath(), 0);
+ QSortFilterProxyModel *pm = new QSortFilterProxyModel;
+ fd2.setProxyModel(pm);
+ fd2.show();
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd2, "sidebar");
+ sidebar->setFocus();
+ sidebar->selectUrl(QUrl::fromLocalFile(QDir::homePath()));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(1, 0)).center());
+ QTest::qWait(250);
+ //We shouldn't crash
+#endif
+}
+
+void tst_QFileDialog2::task227930_correctNavigationKeyboardBehavior()
+{
+ QDir current = QDir::currentPath();
+ current.mkdir("test");
+ current.cd("test");
+ QFile file("test/out.txt");
+ QFile file2("test/out2.txt");
+ QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
+ QVERIFY(file2.open(QIODevice::WriteOnly | QIODevice::Text));
+ current.cdUp();
+ current.mkdir("test2");
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ fd.setDirectory(current.absolutePath());
+ fd.show();
+ QListView *list = qFindChild<QListView*>(&fd, "listView");
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::keyClick(list, Qt::Key_Return);
+ QTest::qWait(200);
+ QTest::mouseClick(list->viewport(), Qt::LeftButton,0);
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::keyClick(list, Qt::Key_Backspace);
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::keyClick(list, Qt::Key_Return);
+ QTest::qWait(200);
+ QCOMPARE(fd.isVisible(), true);
+ QTest::qWait(200);
+ file.close();
+ file2.close();
+ file.remove();
+ file2.remove();
+ current.rmdir("test");
+ current.rmdir("test2");
+}
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+void tst_QFileDialog2::task226366_lowerCaseHardDriveWindows()
+{
+ QNonNativeFileDialog fd;
+ fd.setDirectory(QDir::root().path());
+ fd.show();
+ QLineEdit *edit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QToolButton *buttonParent = qFindChild<QToolButton*>(&fd, "toParentButton");
+ QTest::qWait(200);
+ QTest::mouseClick(buttonParent, Qt::LeftButton,0,QPoint(0,0));
+ QTest::qWait(2000);
+ QTest::keyClick(edit, Qt::Key_C);
+ QTest::qWait(200);
+ QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
+ QTest::qWait(200);
+ QCOMPARE(edit->text(), QString("C:/"));
+ QTest::qWait(2000);
+ //i clear my previous selection in the completer
+ QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
+ edit->clear();
+ QTest::keyClick(edit, (char)(Qt::Key_C | Qt::SHIFT));
+ QTest::qWait(200);
+ QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
+ QCOMPARE(edit->text(), QString("C:/"));
+}
+#endif
+
+void tst_QFileDialog2::completionOnLevelAfterRoot()
+{
+ QNonNativeFileDialog fd;
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ fd.setDirectory("C:");
+ QDir current = fd.directory();
+ current.mkdir("completionOnLevelAfterRootTest");
+#else
+ fd.setFilter(QDir::Hidden | QDir::AllDirs | QDir::Files | QDir::System);
+ fd.setDirectory("/");
+ QDir etc("/etc");
+ if (!etc.exists())
+ QSKIP("This test requires to have an etc directory under /", SkipAll);
+#endif
+ fd.show();
+ QLineEdit *edit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QTest::qWait(2000);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ //I love testlib :D
+ QTest::keyClick(edit, Qt::Key_C);
+ QTest::keyClick(edit, Qt::Key_O);
+ QTest::keyClick(edit, Qt::Key_M);
+ QTest::keyClick(edit, Qt::Key_P);
+ QTest::keyClick(edit, Qt::Key_L);
+#else
+ QTest::keyClick(edit, Qt::Key_E);
+ QTest::keyClick(edit, Qt::Key_T);
+#endif
+ QTest::qWait(200);
+ QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
+ QTest::qWait(200);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QCOMPARE(edit->text(), QString("completionOnLevelAfterRootTest"));
+ current.rmdir("completionOnLevelAfterRootTest");
+#else
+ QTRY_COMPARE(edit->text(), QString("etc"));
+#endif
+}
+
+void tst_QFileDialog2::task233037_selectingDirectory()
+{
+ QDir current = QDir::currentPath();
+ current.mkdir("test");
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ fd.setDirectory(current.absolutePath());
+ fd.setAcceptMode( QFileDialog::AcceptSave);
+ fd.show();
+ QListView *list = qFindChild<QListView*>(&fd, "listView");
+ QTest::qWait(3000); // Wait for sort to settle (I need a signal).
+#ifdef QT_KEYPAD_NAVIGATION
+ list->setEditFocus(true);
+#endif
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::qWait(100);
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Save);
+ QVERIFY(button);
+ QCOMPARE(button->isEnabled(), true);
+ current.rmdir("test");
+}
+
+void tst_QFileDialog2::task235069_hideOnEscape()
+{
+ QDir current = QDir::currentPath();
+ QNonNativeFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ fd.setDirectory(current.absolutePath());
+ fd.setAcceptMode( QFileDialog::AcceptSave);
+ fd.show();
+ QListView *list = qFindChild<QListView*>(&fd, "listView");
+ list->setFocus();
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Escape);
+ QCOMPARE(fd.isVisible(), false);
+ QNonNativeFileDialog fd2;
+ fd2.setDirectory(current.absolutePath());
+ fd2.setAcceptMode( QFileDialog::AcceptSave);
+ fd2.show();
+ QLineEdit *edit = qFindChild<QLineEdit*>(&fd2, "fileNameEdit");
+ QTest::keyClick(edit, Qt::Key_Escape);
+ QCOMPARE(fd2.isVisible(), false);
+}
+
+void tst_QFileDialog2::task236402_dontWatchDeletedDir()
+{
+#if defined QT_BUILD_INTERNAL
+ //THIS TEST SHOULD NOT DISPLAY WARNINGS
+ QDir current = QDir::currentPath();
+ //make sure it is the first on the list
+ current.mkdir("aaaaaaaaaa");
+ FriendlyQFileDialog fd;
+ fd.setViewMode(QFileDialog::List);
+ fd.setDirectory(current.absolutePath());
+ fd.setAcceptMode( QFileDialog::AcceptSave);
+ fd.show();
+ QListView *list = qFindChild<QListView*>(&fd, "listView");
+ list->setFocus();
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Return);
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Backspace);
+ QTest::keyClick(list, Qt::Key_Down);
+ QTest::qWait(200);
+ fd.d_func()->removeDirectory(current.absolutePath() + "/aaaaaaaaaa/");
+ QTest::qWait(1000);
+#endif
+}
+
+void tst_QFileDialog2::task203703_returnProperSeparator()
+{
+ QDir current = QDir::currentPath();
+ current.mkdir("aaaaaaaaaaaaaaaaaa");
+ QNonNativeFileDialog fd;
+ fd.setDirectory(current.absolutePath());
+ fd.setViewMode(QFileDialog::List);
+ fd.setFileMode(QFileDialog::Directory);
+ fd.show();
+ QTest::qWait(500);
+ QListView *list = qFindChild<QListView*>(&fd, "listView");
+ list->setFocus();
+ QTest::qWait(200);
+ QTest::keyClick(list, Qt::Key_Return);
+ QTest::qWait(1000);
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Cancel);
+ QTest::keyClick(button, Qt::Key_Return);
+ QTest::qWait(500);
+ QString result = fd.selectedFiles().first();
+ QVERIFY(result.at(result.count() - 1) != '/');
+ QVERIFY(!result.contains('\\'));
+ current.rmdir("aaaaaaaaaaaaaaaaaa");
+}
+
+void tst_QFileDialog2::task228844_ensurePreviousSorting()
+{
+ QDir current = QDir::currentPath();
+ current.mkdir("aaaaaaaaaaaaaaaaaa");
+ current.cd("aaaaaaaaaaaaaaaaaa");
+ current.mkdir("a");
+ current.mkdir("b");
+ current.mkdir("c");
+ current.mkdir("d");
+ current.mkdir("e");
+ current.mkdir("f");
+ current.mkdir("g");
+ QTemporaryFile *tempFile = new QTemporaryFile(current.absolutePath() + "/rXXXXXX");
+ tempFile->open();
+ current.cdUp();
+
+ QNonNativeFileDialog fd;
+ fd.setDirectory(current.absolutePath());
+ fd.setViewMode(QFileDialog::Detail);
+ fd.show();
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QTreeView *tree = qFindChild<QTreeView*>(&fd, "treeView");
+ tree->header()->setSortIndicator(3,Qt::DescendingOrder);
+ QTest::qWait(200);
+ QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
+ QPushButton *button = buttonBox->button(QDialogButtonBox::Open);
+ QTest::mouseClick(button, Qt::LeftButton);
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QNonNativeFileDialog fd2;
+ fd2.setFileMode(QFileDialog::Directory);
+ fd2.restoreState(fd.saveState());
+ current.cd("aaaaaaaaaaaaaaaaaa");
+ fd2.setDirectory(current.absolutePath());
+ fd2.show();
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QTreeView *tree2 = qFindChild<QTreeView*>(&fd2, "treeView");
+ tree2->setFocus();
+
+ QCOMPARE(tree2->rootIndex().data(QFileSystemModel::FilePathRole).toString(),current.absolutePath());
+
+ QDialogButtonBox *buttonBox2 = qFindChild<QDialogButtonBox*>(&fd2, "buttonBox");
+ QPushButton *button2 = buttonBox2->button(QDialogButtonBox::Open);
+ fd2.selectFile("g");
+ QTest::mouseClick(button2, Qt::LeftButton);
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QCOMPARE(fd2.selectedFiles().first(), current.absolutePath() + QChar('/') + QLatin1String("g"));
+
+ QNonNativeFileDialog fd3(0, "This is a third file dialog", tempFile->fileName());
+ fd3.restoreState(fd.saveState());
+ fd3.setFileMode(QFileDialog::Directory);
+ fd3.show();
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QTreeView *tree3 = qFindChild<QTreeView*>(&fd3, "treeView");
+ tree3->setFocus();
+
+ QCOMPARE(tree3->rootIndex().data(QFileSystemModel::FilePathRole).toString(), current.absolutePath());
+
+ QDialogButtonBox *buttonBox3 = qFindChild<QDialogButtonBox*>(&fd3, "buttonBox");
+ QPushButton *button3 = buttonBox3->button(QDialogButtonBox::Open);
+ QTest::mouseClick(button3, Qt::LeftButton);
+#if defined(Q_OS_WINCE)
+ QTest::qWait(1500);
+#else
+ QTest::qWait(500);
+#endif
+ QCOMPARE(fd3.selectedFiles().first(), tempFile->fileName());
+
+ current.cd("aaaaaaaaaaaaaaaaaa");
+ current.rmdir("a");
+ current.rmdir("b");
+ current.rmdir("c");
+ current.rmdir("d");
+ current.rmdir("e");
+ current.rmdir("f");
+ current.rmdir("g");
+ tempFile->close();
+ delete tempFile;
+ current.cdUp();
+ current.rmdir("aaaaaaaaaaaaaaaaaa");
+}
+
+
+void tst_QFileDialog2::task239706_editableFilterCombo()
+{
+ QNonNativeFileDialog d;
+ d.setNameFilter("*.cpp *.h");
+
+ d.show();
+ QTest::qWait(500);
+
+ QList<QComboBox *> comboList = d.findChildren<QComboBox *>();
+ QComboBox *filterCombo = 0;
+ foreach (QComboBox *combo, comboList) {
+ if (combo->objectName() == QString("fileTypeCombo")) {
+ filterCombo = combo;
+ break;
+ }
+ }
+ QVERIFY(filterCombo);
+ filterCombo->setEditable(true);
+ QTest::mouseClick(filterCombo, Qt::LeftButton);
+ QTest::keyPress(filterCombo, Qt::Key_X);
+ QTest::keyPress(filterCombo, Qt::Key_Enter); // should not trigger assertion failure
+}
+
+void tst_QFileDialog2::task218353_relativePaths()
+{
+ QDir appDir = QDir::current();
+ QVERIFY(appDir.cdUp() != false);
+ QNonNativeFileDialog d(0, "TestDialog", "..");
+ QCOMPARE(d.directory().absolutePath(), appDir.absolutePath());
+
+ d.setDirectory(appDir.absolutePath() + QLatin1String("/non-existing-directory/../another-non-existing-dir/../"));
+ QCOMPARE(d.directory().absolutePath(), appDir.absolutePath());
+
+ QDir::current().mkdir("test");
+ appDir = QDir::current();
+ d.setDirectory(appDir.absolutePath() + QLatin1String("/test/../test/../"));
+ QCOMPARE(d.directory().absolutePath(), appDir.absolutePath());
+ appDir.rmdir("test");
+}
+
+void tst_QFileDialog2::task251321_sideBarHiddenEntries()
+{
+#if defined QT_BUILD_INTERNAL
+ QNonNativeFileDialog fd;
+
+ QDir current = QDir::currentPath();
+ current.mkdir(".hidden");
+ QDir hiddenDir = QDir(".hidden");
+ hiddenDir.mkdir("subdir");
+ QDir hiddenSubDir = QDir(".hidden/subdir");
+ hiddenSubDir.mkdir("happy");
+ hiddenSubDir.mkdir("happy2");
+
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(hiddenSubDir.absolutePath());
+ fd.setSidebarUrls(urls);
+ fd.show();
+ QTest::qWait(250);
+
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
+ sidebar->setFocus();
+ sidebar->selectUrl(QUrl::fromLocalFile(hiddenSubDir.absolutePath()));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(0, 0)).center());
+ // give the background processes more time on windows mobile
+#ifdef Q_OS_WINCE
+ QTest::qWait(1000);
+#else
+ QTest::qWait(250);
+#endif
+
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QCOMPARE(model->rowCount(model->index(hiddenSubDir.absolutePath())), 2);
+
+ hiddenSubDir.rmdir("happy2");
+ hiddenSubDir.rmdir("happy");
+ hiddenDir.rmdir("subdir");
+ current.rmdir(".hidden");
+#endif
+}
+
+#if defined QT_BUILD_INTERNAL
+class MyQSideBar : public QSidebar
+{
+public :
+ MyQSideBar(QWidget *parent = 0) : QSidebar(parent)
+ {}
+
+ void removeSelection() {
+ QList<QModelIndex> idxs = selectionModel()->selectedIndexes();
+ QList<QPersistentModelIndex> indexes;
+ for (int i = 0; i < idxs.count(); i++)
+ indexes.append(idxs.at(i));
+
+ for (int i = 0; i < indexes.count(); ++i)
+ if (!indexes.at(i).data(Qt::UserRole + 1).toUrl().path().isEmpty())
+ model()->removeRow(indexes.at(i).row());
+ }
+};
+#endif
+
+void tst_QFileDialog2::task251341_sideBarRemoveEntries()
+{
+#if defined QT_BUILD_INTERNAL
+ QNonNativeFileDialog fd;
+
+ QDir current = QDir::currentPath();
+ current.mkdir("testDir");
+ QDir testSubDir = QDir("testDir");
+
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(testSubDir.absolutePath());
+ urls << QUrl::fromLocalFile("NotFound");
+ fd.setSidebarUrls(urls);
+ fd.show();
+ QTest::qWait(250);
+
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
+ sidebar->setFocus();
+ //We enter in the first bookmark
+ sidebar->selectUrl(QUrl::fromLocalFile(testSubDir.absolutePath()));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(0, 0)).center());
+ QTest::qWait(250);
+
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ //There is no file
+ QCOMPARE(model->rowCount(model->index(testSubDir.absolutePath())), 0);
+ //Icon is not enabled QUrlModel::EnabledRole
+ QVariant value = sidebar->model()->index(0, 0).data(Qt::UserRole + 2);
+ QCOMPARE(qvariant_cast<bool>(value), true);
+
+ sidebar->setFocus();
+ //We enter in the second bookmark which is invalid
+ sidebar->selectUrl(QUrl::fromLocalFile("NotFound"));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(1, 0)).center());
+ QTest::qWait(250);
+
+ //We fallback to root because the entry in the bookmark is invalid
+ QCOMPARE(model->rowCount(model->index("NotFound")), model->rowCount(model->index(model->rootPath())));
+ //Icon is not enabled QUrlModel::EnabledRole
+ value = sidebar->model()->index(1, 0).data(Qt::UserRole + 2);
+ QCOMPARE(qvariant_cast<bool>(value), false);
+
+ MyQSideBar mySideBar;
+ mySideBar.init(model, urls);
+ mySideBar.show();
+ mySideBar.selectUrl(QUrl::fromLocalFile(testSubDir.absolutePath()));
+ QTest::qWait(1000);
+ mySideBar.removeSelection();
+
+ //We remove the first entry
+ QList<QUrl> expected;
+ expected << QUrl::fromLocalFile("NotFound");
+ QCOMPARE(mySideBar.urls(), expected);
+
+ mySideBar.selectUrl(QUrl::fromLocalFile("NotFound"));
+ mySideBar.removeSelection();
+
+ //We remove the second entry
+ expected.clear();
+ QCOMPARE(mySideBar.urls(), expected);
+
+ current.rmdir("testDir");
+#endif
+}
+
+void tst_QFileDialog2::task254490_selectFileMultipleTimes()
+{
+ QString tempPath = QDir::tempPath();
+ QTemporaryFile *t;
+ t = new QTemporaryFile;
+ t->open();
+ QNonNativeFileDialog fd(0, "TestFileDialog");
+
+ fd.setDirectory(tempPath);
+ fd.setViewMode(QFileDialog::List);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setFileMode(QFileDialog::AnyFile);
+
+ //This should select the file in the QFileDialog
+ fd.selectFile(t->fileName());
+
+ //This should clear the selection and write it into the filename line edit
+ fd.selectFile("new_file.txt");
+
+ fd.show();
+ QTest::qWait(250);
+
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QVERIFY(lineEdit);
+ QCOMPARE(lineEdit->text(),QLatin1String("new_file.txt"));
+ QListView *list = qFindChild<QListView*>(&fd, "listView");
+ QVERIFY(list);
+ QCOMPARE(list->selectionModel()->selectedRows(0).count(), 0);
+
+ t->deleteLater();
+}
+
+void tst_QFileDialog2::task257579_sideBarWithNonCleanUrls()
+{
+#if defined QT_BUILD_INTERNAL
+ QDir tempDir = QDir::temp();
+ QLatin1String dirname("autotest_task257579");
+ tempDir.rmdir(dirname); //makes sure it doesn't exist any more
+ QVERIFY(tempDir.mkdir(dirname));
+ QString url = QString::fromLatin1("%1/%2/..").arg(tempDir.absolutePath()).arg(dirname);
+ QNonNativeFileDialog fd;
+ fd.setSidebarUrls(QList<QUrl>() << QUrl::fromLocalFile(url));
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
+ QCOMPARE(sidebar->urls().count(), 1);
+ QVERIFY(sidebar->urls().first().toLocalFile() != url);
+ QCOMPARE(sidebar->urls().first().toLocalFile(), QDir::cleanPath(url));
+
+#ifdef Q_OS_WIN
+ QCOMPARE(sidebar->model()->index(0,0).data().toString().toLower(), tempDir.dirName().toLower());
+#else
+ QCOMPARE(sidebar->model()->index(0,0).data().toString(), tempDir.dirName());
+#endif
+
+ //all tests are finished, we can remove the temporary dir
+ QVERIFY(tempDir.rmdir(dirname));
+#endif
+}
+
+void tst_QFileDialog2::task259105_filtersCornerCases()
+{
+ QNonNativeFileDialog fd(0, "TestFileDialog");
+ fd.setNameFilter(QLatin1String("All Files! (*);;Text Files (*.txt)"));
+ fd.setOption(QFileDialog::HideNameFilterDetails, true);
+ fd.show();
+ QTest::qWait(250);
+
+ //Extensions are hidden
+ QComboBox *filters = qFindChild<QComboBox*>(&fd, "fileTypeCombo");
+ QVERIFY(filters);
+ QCOMPARE(filters->currentText(), QLatin1String("All Files!"));
+ filters->setCurrentIndex(1);
+ QCOMPARE(filters->currentText(), QLatin1String("Text Files"));
+
+ //We should have the full names
+ fd.setOption(QFileDialog::HideNameFilterDetails, false);
+ QTest::qWait(250);
+ filters->setCurrentIndex(0);
+ QCOMPARE(filters->currentText(), QLatin1String("All Files! (*)"));
+ filters->setCurrentIndex(1);
+ QCOMPARE(filters->currentText(), QLatin1String("Text Files (*.txt)"));
+
+ //Corner case undocumented of the task
+ fd.setNameFilter(QLatin1String("\352 (I like cheese) All Files! (*);;Text Files (*.txt)"));
+ QCOMPARE(filters->currentText(), QLatin1String("\352 (I like cheese) All Files! (*)"));
+ filters->setCurrentIndex(1);
+ QCOMPARE(filters->currentText(), QLatin1String("Text Files (*.txt)"));
+
+ fd.setOption(QFileDialog::HideNameFilterDetails, true);
+ filters->setCurrentIndex(0);
+ QTest::qWait(500);
+ QCOMPARE(filters->currentText(), QLatin1String("\352 (I like cheese) All Files!"));
+ filters->setCurrentIndex(1);
+ QCOMPARE(filters->currentText(), QLatin1String("Text Files"));
+
+ fd.setOption(QFileDialog::HideNameFilterDetails, true);
+ filters->setCurrentIndex(0);
+ QTest::qWait(500);
+ QCOMPARE(filters->currentText(), QLatin1String("\352 (I like cheese) All Files!"));
+ filters->setCurrentIndex(1);
+ QCOMPARE(filters->currentText(), QLatin1String("Text Files"));
+}
+
+void tst_QFileDialog2::QTBUG4419_lineEditSelectAll()
+{
+ QString tempPath = QDir::tempPath();
+ QTemporaryFile *t;
+ t = new QTemporaryFile;
+ t->open();
+ QNonNativeFileDialog fd(0, "TestFileDialog", t->fileName());
+
+ fd.setDirectory(tempPath);
+ fd.setViewMode(QFileDialog::List);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setFileMode(QFileDialog::AnyFile);
+
+ fd.show();
+ QApplication::setActiveWindow(&fd);
+ QTest::qWaitForWindowShown(&fd);
+ QTRY_COMPARE(fd.isVisible(), true);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
+
+ QTest::qWait(250);
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+
+ QCOMPARE(tempPath + QChar('/') + lineEdit->text(), t->fileName());
+ QCOMPARE(tempPath + QChar('/') + lineEdit->selectedText(), t->fileName());
+}
+
+void tst_QFileDialog2::QTBUG6558_showDirsOnly()
+{
+ const QString tempPath = QDir::tempPath();
+ QDir dirTemp(tempPath);
+ const QString tempName = QLatin1String("showDirsOnly.") + QString::number(qrand());
+ dirTemp.mkdir(tempName);
+ dirTemp.cd(tempName);
+ QTRY_VERIFY(dirTemp.exists());
+
+ const QString dirPath = dirTemp.absolutePath();
+ QDir dir(dirPath);
+
+ //We create two dirs
+ dir.mkdir("a");
+ dir.mkdir("b");
+
+ //Create a file
+ QFile tempFile(dirPath + "/plop.txt");
+ tempFile.open(QIODevice::WriteOnly | QIODevice::Text);
+ QTextStream out(&tempFile);
+ out << "The magic number is: " << 49 << "\n";
+ tempFile.close();
+
+ QNonNativeFileDialog fd(0, "TestFileDialog");
+
+ fd.setDirectory(dir.absolutePath());
+ fd.setViewMode(QFileDialog::List);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setOption(QFileDialog::ShowDirsOnly, true);
+ fd.show();
+
+ QApplication::setActiveWindow(&fd);
+ QTest::qWaitForWindowShown(&fd);
+ QTRY_COMPARE(fd.isVisible(), true);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
+
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 2);
+
+ fd.setOption(QFileDialog::ShowDirsOnly, false);
+ QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 3);
+
+ fd.setOption(QFileDialog::ShowDirsOnly, true);
+ QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 2);
+
+ fd.setFileMode(QFileDialog::DirectoryOnly);
+ QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 2);
+ QTRY_COMPARE(bool(fd.options() & QFileDialog::ShowDirsOnly), true);
+
+ fd.setFileMode(QFileDialog::AnyFile);
+ QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 3);
+ QTRY_COMPARE(bool(fd.options() & QFileDialog::ShowDirsOnly), false);
+
+ fd.setDirectory(QDir::homePath());
+
+ //We remove the dirs
+ dir.rmdir("a");
+ dir.rmdir("b");
+
+ //we delete the file
+ tempFile.remove();
+
+ dirTemp.cdUp();
+ dirTemp.rmdir(tempName);
+}
+
+void tst_QFileDialog2::QTBUG4842_selectFilterWithHideNameFilterDetails()
+{
+ QStringList filtersStr;
+ filtersStr << "Images (*.png *.xpm *.jpg)" << "Text files (*.txt)" << "XML files (*.xml)";
+ QString chosenFilterString("Text files (*.txt)");
+
+ QNonNativeFileDialog fd(0, "TestFileDialog");
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setOption(QFileDialog::HideNameFilterDetails, true);
+ fd.setNameFilters(filtersStr);
+ fd.selectNameFilter(chosenFilterString);
+ fd.show();
+
+ QApplication::setActiveWindow(&fd);
+ QTest::qWaitForWindowShown(&fd);
+ QTRY_COMPARE(fd.isVisible(), true);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
+
+ QComboBox *filters = qFindChild<QComboBox*>(&fd, "fileTypeCombo");
+ //We compare the current combobox text with the stripped version
+ QCOMPARE(filters->currentText(), QString("Text files"));
+
+ QNonNativeFileDialog fd2(0, "TestFileDialog");
+ fd2.setAcceptMode(QFileDialog::AcceptSave);
+ fd2.setOption(QFileDialog::HideNameFilterDetails, false);
+ fd2.setNameFilters(filtersStr);
+ fd2.selectNameFilter(chosenFilterString);
+ fd2.show();
+
+ QApplication::setActiveWindow(&fd2);
+ QTest::qWaitForWindowShown(&fd2);
+ QTRY_COMPARE(fd2.isVisible(), true);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd2));
+
+ QComboBox *filters2 = qFindChild<QComboBox*>(&fd2, "fileTypeCombo");
+ //We compare the current combobox text with the non stripped version
+ QCOMPARE(filters2->currentText(), chosenFilterString);
+
+}
+
+void tst_QFileDialog2::dontShowCompleterOnRoot()
+{
+ QNonNativeFileDialog fd(0, "TestFileDialog");
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.show();
+
+ QApplication::setActiveWindow(&fd);
+ QTest::qWaitForWindowShown(&fd);
+ QTRY_COMPARE(fd.isVisible(), true);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
+
+ fd.setDirectory("");
+ QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
+ QTRY_VERIFY(lineEdit->text().isEmpty());
+
+ //The gatherer thread will then return the result
+ QApplication::processEvents();
+
+ QTRY_VERIFY(lineEdit->completer()->popup()->isHidden());
+}
+
+QTEST_MAIN(tst_QFileDialog2)
+#include "tst_qfiledialog2.moc"
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore b/tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore
new file mode 100644
index 0000000000..9804e5a3d7
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore
@@ -0,0 +1 @@
+tst_qfilesystemmodel
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro
new file mode 100644
index 0000000000..a7d042ce5e
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro
@@ -0,0 +1,7 @@
+CONFIG += qttest_p4
+
+QT += widgets widgets-private
+QT += core-private gui
+
+SOURCES += tst_qfilesystemmodel.cpp
+TARGET = tst_qfilesystemmodel
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
new file mode 100644
index 0000000000..26fa58e649
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -0,0 +1,1046 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#ifdef QT_BUILD_INTERNAL
+#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h"
+#endif
+#include <QFileSystemModel>
+#include <QFileIconProvider>
+#include <QTreeView>
+#include <QHeaderView>
+#include <QTime>
+#include <QStyle>
+#include <QtGlobal>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#define WAITTIME 1000
+
+// Will try to wait for the condition while allowing event processing
+// for a maximum of 5 seconds.
+#define TRY_WAIT(expr) \
+ do { \
+ const int step = 50; \
+ for (int __i = 0; __i < 5000 && !(expr); __i+=step) { \
+ QTest::qWait(step); \
+ } \
+ } while(0)
+
+class tst_QFileSystemModel : public QObject {
+ Q_OBJECT
+
+public:
+ tst_QFileSystemModel();
+ virtual ~tst_QFileSystemModel();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void indexPath();
+
+ void rootPath();
+ void naturalCompare_data();
+ void naturalCompare();
+ void readOnly();
+ void iconProvider();
+
+ void rowCount();
+
+ void rowsInserted_data();
+ void rowsInserted();
+
+ void rowsRemoved_data();
+ void rowsRemoved();
+
+ void dataChanged_data();
+ void dataChanged();
+
+ void filters_data();
+ void filters();
+
+ void nameFilters();
+
+ void setData_data();
+ void setData();
+
+ void sort_data();
+ void sort();
+
+ void mkdir();
+
+ void caseSensitivity();
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ void Win32LongFileName();
+#endif
+
+ void drives_data();
+ void drives();
+ void dirsBeforeFiles();
+
+ void roleNames_data();
+ void roleNames();
+
+protected:
+ bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList(), const QString &baseDir = QDir::temp().absolutePath());
+
+private:
+ QFileSystemModel *model;
+ QString flatDirTestPath;
+};
+
+tst_QFileSystemModel::tst_QFileSystemModel() : model(0)
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+
+ QTime midnight(0, 0, 0);
+ qsrand(midnight.secsTo(QTime::currentTime()));
+ // generating unique temporary directory name
+ flatDirTestPath = QDir::temp().path() + '/' + QString("flatdirtest.") + QString::number(qrand());
+}
+
+tst_QFileSystemModel::~tst_QFileSystemModel()
+{
+ QString tmp = flatDirTestPath;
+ QDir dir(tmp);
+ if (dir.exists() && !dir.rmdir(tmp))
+ qWarning("failed to remove tmp dir %s", dir.dirName().toAscii().data());
+}
+
+void tst_QFileSystemModel::init()
+{
+ cleanup();
+ QCOMPARE(model, (QFileSystemModel*)0);
+ model = new QFileSystemModel;
+}
+
+void tst_QFileSystemModel::cleanup()
+{
+ delete model;
+ model = 0;
+ QString tmp = flatDirTestPath;
+ QDir dir(tmp);
+ if (dir.exists(tmp)) {
+ QStringList list = dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot);
+ for (int i = 0; i < list.count(); ++i) {
+ QFileInfo fi(dir.path() + '/' + list.at(i));
+ if (fi.exists() && fi.isFile()) {
+ QFile p(fi.absoluteFilePath());
+ p.setPermissions(QFile::ReadUser | QFile::ReadOwner | QFile::ExeOwner | QFile::ExeUser | QFile::WriteUser | QFile::WriteOwner | QFile::WriteOther);
+ QFile dead(dir.path() + '/' + list.at(i));
+ dead.remove();
+ }
+ if (fi.exists() && fi.isDir())
+ QVERIFY(dir.rmdir(list.at(i)));
+ }
+ list = dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot);
+ QVERIFY(list.count() == 0);
+ }
+}
+
+void tst_QFileSystemModel::indexPath()
+{
+#if !defined(Q_OS_WIN)
+ int depth = QDir::currentPath().count('/');
+ model->setRootPath(QDir::currentPath());
+ QTest::qWait(WAITTIME);
+ QString backPath;
+ for (int i = 0; i <= depth * 2 + 1; ++i) {
+ backPath += "../";
+ QModelIndex idx = model->index(backPath);
+ QVERIFY(i != depth - 1 ? idx.isValid() : !idx.isValid());
+ }
+ QTest::qWait(WAITTIME * 3);
+ qApp->processEvents();
+#endif
+}
+
+void tst_QFileSystemModel::rootPath()
+{
+ QCOMPARE(model->rootPath(), QString(QDir().path()));
+
+ QSignalSpy rootChanged(model, SIGNAL(rootPathChanged(const QString &)));
+ QModelIndex root = model->setRootPath(model->rootPath());
+ root = model->setRootPath("this directory shouldn't exist");
+ QCOMPARE(rootChanged.count(), 0);
+
+ QString oldRootPath = model->rootPath();
+ root = model->setRootPath(QDir::homePath());
+
+ QTRY_VERIFY(model->rowCount(root) >= 0);
+ QCOMPARE(model->rootPath(), QString(QDir::homePath()));
+ QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? 0 : 1);
+ QCOMPARE(model->rootDirectory().absolutePath(), QDir::homePath());
+
+ model->setRootPath(QDir::rootPath());
+ int oldCount = rootChanged.count();
+ oldRootPath = model->rootPath();
+ root = model->setRootPath(QDir::homePath() + QLatin1String("/."));
+ QTRY_VERIFY(model->rowCount(root) >= 0);
+ QCOMPARE(model->rootPath(), QDir::homePath());
+ QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? oldCount : oldCount + 1);
+ QCOMPARE(model->rootDirectory().absolutePath(), QDir::homePath());
+
+ QDir newdir = QDir::home();
+ if (newdir.cdUp()) {
+ oldCount = rootChanged.count();
+ oldRootPath = model->rootPath();
+ root = model->setRootPath(QDir::homePath() + QLatin1String("/.."));
+ QTRY_VERIFY(model->rowCount(root) >= 0);
+ QCOMPARE(model->rootPath(), newdir.path());
+ QCOMPARE(rootChanged.count(), oldCount + 1);
+ QCOMPARE(model->rootDirectory().absolutePath(), newdir.path());
+ }
+}
+
+void tst_QFileSystemModel::naturalCompare_data()
+{
+ QTest::addColumn<QString>("s1");
+ QTest::addColumn<QString>("s2");
+ QTest::addColumn<int>("caseSensitive");
+ QTest::addColumn<int>("result");
+ QTest::addColumn<int>("swap");
+ for (int j = 0; j < 4; ++j) { // <- set a prefix and a postfix string (not numbers)
+ QString prefix = (j == 0 || j == 1) ? "b" : "";
+ QString postfix = (j == 1 || j == 2) ? "y" : "";
+
+ for (int k = 0; k < 3; ++k) { // <- make 0 not a special case
+ QString num = QString("%1").arg(k);
+ QString nump = QString("%1").arg(k + 1);
+ for (int i = 10; i < 12; ++i) { // <- swap s1 and s2 and reverse the result
+ QTest::newRow("basic") << prefix + "0" + postfix << prefix + "0" + postfix << int(Qt::CaseInsensitive) << 0;
+
+ // s1 should always be less then s2
+ QTest::newRow("just text") << prefix + "fred" + postfix << prefix + "jane" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("just numbers") << prefix + num + postfix << prefix + "9" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("zero") << prefix + num + postfix << prefix + "0" + nump + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("space b") << prefix + num + postfix << prefix + " " + nump + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("space a") << prefix + num + postfix << prefix + nump + " " + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("tab b") << prefix + num + postfix << prefix + " " + nump + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("tab a") << prefix + num + postfix << prefix + nump + " " + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("10 vs 2") << prefix + num + postfix << prefix + "10" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("diff len") << prefix + num + postfix << prefix + nump + postfix + "x" << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("01 before 1") << prefix + "0" + num + postfix << prefix + nump + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums 2nd") << prefix + "1-" + num + postfix << prefix + "1-" + nump + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums 2nd") << prefix + "10-" + num + postfix<< prefix + "10-10" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums 2nd") << prefix + "10-0"+ num + postfix<< prefix + "10-10" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums 2nd") << prefix + "10-" + num + postfix<< prefix + "10-010" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums big") << prefix + "10-" + num + postfix<< prefix + "20-0" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums big") << prefix + "2-" + num + postfix << prefix + "10-0" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul alphabet") << prefix + num + "-a" + postfix << prefix + num + "-c" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul alphabet2")<< prefix + num + "-a9" + postfix<< prefix + num + "-c0" + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("mul nums w\\0")<< prefix + num + "-"+ num + postfix<< prefix + num+"-0"+nump + postfix << int(Qt::CaseInsensitive) << i;
+ QTest::newRow("num first") << prefix + num + postfix << prefix + "a" + postfix << int(Qt::CaseInsensitive) << i;
+ }
+ }
+ }
+}
+
+void tst_QFileSystemModel::naturalCompare()
+{
+#ifdef QT_BUILD_INTERNAL
+ QFETCH(QString, s1);
+ QFETCH(QString, s2);
+ QFETCH(int, caseSensitive);
+ QFETCH(int, result);
+
+ if (result == 10)
+ QCOMPARE(QFileSystemModelPrivate::naturalCompare(s1, s2, Qt::CaseSensitivity(caseSensitive)), -1);
+ else
+ if (result == 11)
+ QCOMPARE(QFileSystemModelPrivate::naturalCompare(s2, s1, Qt::CaseSensitivity(caseSensitive)), 1);
+ else
+ QCOMPARE(QFileSystemModelPrivate::naturalCompare(s2, s1, Qt::CaseSensitivity(caseSensitive)), result);
+#if defined(Q_OS_WINCE)
+ // On Windows CE we need to wait after each test, otherwise no new threads can be
+ // created. The scheduler takes its time to recognize ended threads.
+ QTest::qWait(300);
+#endif
+#endif
+}
+
+void tst_QFileSystemModel::readOnly()
+{
+ QCOMPARE(model->isReadOnly(), true);
+ QTemporaryFile file;
+ file.open();
+ QModelIndex root = model->setRootPath(QDir::tempPath());
+
+ QTRY_VERIFY(model->rowCount(root) > 0);
+ QVERIFY(!(model->flags(model->index(file.fileName())) & Qt::ItemIsEditable));
+ model->setReadOnly(false);
+ QCOMPARE(model->isReadOnly(), false);
+ QVERIFY(model->flags(model->index(file.fileName())) & Qt::ItemIsEditable);
+}
+
+class CustomFileIconProvider : public QFileIconProvider
+{
+public:
+ CustomFileIconProvider() : QFileIconProvider() {
+ mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical);
+ dvd = qApp->style()->standardIcon(QStyle::SP_DriveDVDIcon);
+ }
+
+ virtual QIcon icon(const QFileInfo &info) const
+ {
+ if (info.isDir())
+ return mb;
+
+ return QFileIconProvider::icon(info);
+ }
+ virtual QIcon icon(IconType type) const
+ {
+ if (type == QFileIconProvider::Folder)
+ return dvd;
+
+ return QFileIconProvider::icon(type);
+ }
+private:
+ QIcon mb;
+ QIcon dvd;
+};
+
+void tst_QFileSystemModel::iconProvider()
+{
+ QVERIFY(model->iconProvider());
+ QFileIconProvider *p = new QFileIconProvider();
+ model->setIconProvider(p);
+ QCOMPARE(model->iconProvider(), p);
+ model->setIconProvider(0);
+ delete p;
+
+ QFileSystemModel *myModel = new QFileSystemModel();
+ myModel->setRootPath(QDir::homePath());
+ //Let's wait to populate the model
+ QTest::qWait(250);
+ //We change the provider, icons must me updated
+ CustomFileIconProvider *custom = new CustomFileIconProvider();
+ myModel->setIconProvider(custom);
+
+ QPixmap mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50);
+ QCOMPARE(myModel->fileIcon(myModel->index(QDir::homePath())).pixmap(50, 50), mb);
+ delete myModel;
+ delete custom;
+}
+
+bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs, const QString &dir)
+{
+ QDir baseDir(dir);
+ if (!baseDir.exists(test_path)) {
+ if (!baseDir.mkdir(test_path) && false) {
+ qDebug() << "failed to create dir" << test_path;
+ return false;
+ }
+ }
+ //qDebug() << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files;
+ TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount));
+ for (int i = 0; i < initial_dirs.count(); ++i) {
+ QDir dir(test_path);
+ if (!dir.exists()) {
+ qWarning() << "error" << test_path << "doesn't exists";
+ return false;
+ }
+ if(!dir.mkdir(initial_dirs.at(i))) {
+ qWarning() << "error" << "failed to make" << initial_dirs.at(i);
+ return false;
+ }
+ //qDebug() << test_path + '/' + initial_dirs.at(i) << (QFile::exists(test_path + '/' + initial_dirs.at(i)));
+ }
+ for (int i = 0; i < initial_files.count(); ++i) {
+ QFile file(test_path + '/' + initial_files.at(i));
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ qDebug() << "failed to open file" << initial_files.at(i);
+ return false;
+ }
+ if (!file.resize(1024 + file.size())) {
+ qDebug() << "failed to resize file" << initial_files.at(i);
+ return false;
+ }
+ if (!file.flush()) {
+ qDebug() << "failed to flush file" << initial_files.at(i);
+ return false;
+ }
+ file.close();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ if (initial_files.at(i)[0] == '.')
+ QProcess::execute(QString("attrib +h %1").arg(file.fileName()));
+#endif
+ //qDebug() << test_path + '/' + initial_files.at(i) << (QFile::exists(test_path + '/' + initial_files.at(i)));
+ }
+ return true;
+}
+
+void tst_QFileSystemModel::rowCount()
+{
+ QString tmp = flatDirTestPath;
+ QVERIFY(createFiles(tmp, QStringList()));
+
+ QSignalSpy spy2(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
+ QSignalSpy spy3(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
+
+#if !defined(Q_OS_WINCE)
+ QStringList files = QStringList() << "b" << "d" << "f" << "h" << "j" << ".a" << ".c" << ".e" << ".g";
+ QString l = "b,d,f,h,j,.a,.c,.e,.g";
+#else
+ // Cannot hide them on CE
+ QStringList files = QStringList() << "b" << "d" << "f" << "h" << "j";
+ QString l = "b,d,f,h,j";
+#endif
+ QVERIFY(createFiles(tmp, files));
+
+ QModelIndex root = model->setRootPath(tmp);
+ QTRY_COMPARE(model->rowCount(root), 5);
+ QVERIFY(spy2.count() > 0);
+ QVERIFY(spy3.count() > 0);
+}
+
+void tst_QFileSystemModel::rowsInserted_data()
+{
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("assending");
+ for (int i = 0; i < 4; ++i) {
+ QTest::newRow(QString("Qt::AscendingOrder %1").arg(i).toLocal8Bit().constData()) << i << (int)Qt::AscendingOrder;
+ QTest::newRow(QString("Qt::DescendingOrder %1").arg(i).toLocal8Bit().constData()) << i << (int)Qt::DescendingOrder;
+ }
+}
+
+void tst_QFileSystemModel::rowsInserted()
+{
+#if defined(Q_OS_WINCE)
+ QSKIP("Watching directories does not work on CE(see #137910)", SkipAll);
+#endif
+ QString tmp = flatDirTestPath;
+ rowCount();
+ QModelIndex root = model->index(model->rootPath());
+
+ QFETCH(int, assending);
+ QFETCH(int, count);
+ model->sort(0, (Qt::SortOrder)assending);
+
+ QSignalSpy spy0(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
+ QSignalSpy spy1(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
+ int oldCount = model->rowCount(root);
+ QStringList files;
+ for (int i = 0; i < count; ++i)
+ files.append(QString("c%1").arg(i));
+ QVERIFY(createFiles(tmp, files, 5));
+ TRY_WAIT(model->rowCount(root) == oldCount + count);
+ QTRY_COMPARE(model->rowCount(root), oldCount + count);
+ QTest::qWait(100); // Let the sort settle.
+ int totalRowsInserted = 0;
+ for (int i = 0; i < spy0.count(); ++i) {
+ int start = spy0[i].value(1).toInt();
+ int end = spy0[i].value(2).toInt();
+ totalRowsInserted += end - start + 1;
+ }
+ QCOMPARE(totalRowsInserted, count);
+ if (assending == (Qt::SortOrder)Qt::AscendingOrder) {
+ QString letter = model->index(model->rowCount(root) - 1, 0, root).data().toString();
+ QCOMPARE(letter, QString("j"));
+ } else {
+ QCOMPARE(model->index(model->rowCount(root) - 1, 0, root).data().toString(), QString("b"));
+ }
+ if (spy0.count() > 0) {
+ if (count == 0)
+ QCOMPARE(spy0.count(), 0);
+ else
+ QVERIFY(spy0.count() >= 1);
+ }
+ if (count == 0) QCOMPARE(spy1.count(), 0); else QVERIFY(spy1.count() >= 1);
+
+ QVERIFY(createFiles(tmp, QStringList(".hidden_file"), 5 + count));
+
+ if (count != 0) QTRY_VERIFY(spy0.count() >= 1); else QTRY_VERIFY(spy0.count() == 0);
+ if (count != 0) QTRY_VERIFY(spy1.count() >= 1); else QTRY_VERIFY(spy1.count() == 0);
+}
+
+void tst_QFileSystemModel::rowsRemoved_data()
+{
+ rowsInserted_data();
+}
+
+void tst_QFileSystemModel::rowsRemoved()
+{
+#if defined(Q_OS_WINCE)
+ QSKIP("Watching directories does not work on CE(see #137910)", SkipAll);
+#endif
+ QString tmp = flatDirTestPath;
+ rowCount();
+ QModelIndex root = model->index(model->rootPath());
+
+ QFETCH(int, count);
+ QFETCH(int, assending);
+ model->sort(0, (Qt::SortOrder)assending);
+ QTest::qWait(WAITTIME);
+
+ QSignalSpy spy0(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
+ QSignalSpy spy1(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
+ int oldCount = model->rowCount(root);
+ for (int i = count - 1; i >= 0; --i) {
+ //qDebug() << "removing" << model->index(i, 0, root).data().toString();
+ QVERIFY(QFile::remove(tmp + '/' + model->index(i, 0, root).data().toString()));
+ }
+ for (int i = 0 ; i < 10; ++i) {
+ QTest::qWait(WAITTIME);
+ qApp->processEvents();
+ if (count != 0) {
+ if (i == 10 || spy0.count() != 0) {
+ QVERIFY(spy0.count() >= 1);
+ QVERIFY(spy1.count() >= 1);
+ }
+ } else {
+ if (i == 10 || spy0.count() == 0) {
+ QVERIFY(spy0.count() == 0);
+ QVERIFY(spy1.count() == 0);
+ }
+ }
+ QStringList lst;
+ for (int i = 0; i < model->rowCount(root); ++i)
+ lst.append(model->index(i, 0, root).data().toString());
+ if (model->rowCount(root) == oldCount - count)
+ break;
+ qDebug() << "still have:" << lst << QFile::exists(tmp + '/' + QString(".a"));
+ QDir tmpLister(tmp);
+ qDebug() << tmpLister.entryList();
+ }
+ QTRY_COMPARE(model->rowCount(root), oldCount - count);
+
+ QVERIFY(QFile::exists(tmp + '/' + QString(".a")));
+ QVERIFY(QFile::remove(tmp + '/' + QString(".a")));
+ QVERIFY(QFile::remove(tmp + '/' + QString(".c")));
+ QTest::qWait(WAITTIME);
+
+ if (count != 0) QVERIFY(spy0.count() >= 1); else QVERIFY(spy0.count() == 0);
+ if (count != 0) QVERIFY(spy1.count() >= 1); else QVERIFY(spy1.count() == 0);
+}
+
+void tst_QFileSystemModel::dataChanged_data()
+{
+ rowsInserted_data();
+}
+
+void tst_QFileSystemModel::dataChanged()
+{
+ // This can't be tested right now sense we don't watch files, only directories
+ return;
+
+ /*
+ QString tmp = flatDirTestPath;
+ rowCount();
+ QModelIndex root = model->index(model->rootPath());
+
+ QFETCH(int, count);
+ QFETCH(int, assending);
+ model->sort(0, (Qt::SortOrder)assending);
+
+ QSignalSpy spy(model, SIGNAL(dataChanged (const QModelIndex &, const QModelIndex &)));
+ QStringList files;
+ for (int i = 0; i < count; ++i)
+ files.append(model->index(i, 0, root).data().toString());
+ createFiles(tmp, files);
+
+ QTest::qWait(WAITTIME);
+
+ if (count != 0) QVERIFY(spy.count() >= 1); else QVERIFY(spy.count() == 0);
+ */
+}
+
+void tst_QFileSystemModel::filters_data()
+{
+ QTest::addColumn<QStringList>("files");
+ QTest::addColumn<QStringList>("dirs");
+ QTest::addColumn<int>("dirFilters");
+ QTest::addColumn<QStringList>("nameFilters");
+ QTest::addColumn<int>("rowCount");
+#if !defined(Q_OS_WINCE)
+ QTest::newRow("no dirs") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs) << QStringList() << 2;
+ QTest::newRow("no dirs - dot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 1;
+ QTest::newRow("no dirs - dotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 1;
+ QTest::newRow("no dirs - dotanddotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0;
+ QTest::newRow("one dir - dot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 2;
+ QTest::newRow("one dir - dotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 2;
+ QTest::newRow("one dir - dotanddotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1;
+ QTest::newRow("one dir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs) << QStringList() << 3;
+ QTest::newRow("no dir + hidden") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::Hidden) << QStringList() << 2;
+ QTest::newRow("dir+hid+files") << (QStringList() << "a" << "b" << "c") << QStringList() <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 5;
+ QTest::newRow("dir+file+hid-dot .A") << (QStringList() << "a" << "b" << "c") << (QStringList() << ".A") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4;
+ QTest::newRow("dir+files+hid+dot A") << (QStringList() << "a" << "b" << "c") << (QStringList() << "AFolder") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << (QStringList() << "A*") << 2;
+ QTest::newRow("dir+files+hid+dot+cas1") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "Z") << 1;
+ QTest::newRow("dir+files+hid+dot+cas2") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "a") << 1;
+ QTest::newRow("dir+files+hid+dot+cas+alldir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << (QStringList() << "Z") << 1;
+#else
+ QTest::qWait(3000); // We need to calm down a bit...
+ QTest::newRow("no dirs") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs) << QStringList() << 0;
+ QTest::newRow("no dirs - dot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 1;
+ QTest::newRow("no dirs - dotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 1;
+ QTest::newRow("no dirs - dotanddotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0;
+ QTest::newRow("one dir - dot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 2;
+ QTest::newRow("one dir - dotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 2;
+ QTest::newRow("one dir - dotanddotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1;
+ QTest::newRow("one dir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs) << QStringList() << 1;
+ QTest::newRow("no dir + hidden") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::Hidden) << QStringList() << 0;
+ QTest::newRow("dir+hid+files") << (QStringList() << "a" << "b" << "c") << QStringList() <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 3;
+ QTest::newRow("dir+file+hid-dot .A") << (QStringList() << "a" << "b" << "c") << (QStringList() << ".A") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4;
+ QTest::newRow("dir+files+hid+dot A") << (QStringList() << "a" << "b" << "c") << (QStringList() << "AFolder") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << (QStringList() << "A*") << 2;
+ QTest::newRow("dir+files+hid+dot+cas1") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "Z") << 1;
+ QTest::newRow("dir+files+hid+dot+cas2") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "a") << 1;
+ QTest::newRow("dir+files+hid+dot+cas+alldir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
+ (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << (QStringList() << "Z") << 1;
+#endif
+
+ QTest::newRow("case sensitive") << (QStringList() << "Antiguagdb" << "Antiguamtd"
+ << "Antiguamtp" << "afghanistangdb" << "afghanistanmtd")
+ << QStringList() << (int)(QDir::Files) << QStringList() << 5;
+}
+
+void tst_QFileSystemModel::filters()
+{
+ QString tmp = flatDirTestPath;
+ QVERIFY(createFiles(tmp, QStringList()));
+ QModelIndex root = model->setRootPath(tmp);
+ QFETCH(QStringList, files);
+ QFETCH(QStringList, dirs);
+ QFETCH(int, dirFilters);
+ QFETCH(QStringList, nameFilters);
+ QFETCH(int, rowCount);
+
+ if (nameFilters.count() > 0)
+ model->setNameFilters(nameFilters);
+ model->setNameFilterDisables(false);
+ model->setFilter((QDir::Filters)dirFilters);
+
+ QVERIFY(createFiles(tmp, files, 0, dirs));
+ QTRY_COMPARE(model->rowCount(root), rowCount);
+
+ // Make sure that we do what QDir does
+ QDir xFactor(tmp);
+ QDir::Filters filters = (QDir::Filters)dirFilters;
+ QStringList dirEntries;
+
+ if (nameFilters.count() > 0)
+ dirEntries = xFactor.entryList(nameFilters, filters);
+ else
+ dirEntries = xFactor.entryList(filters);
+
+ QCOMPARE(dirEntries.count(), rowCount);
+
+ QStringList modelEntries;
+
+ for (int i = 0; i < rowCount; ++i)
+ modelEntries.append(model->data(model->index(i, 0, root), QFileSystemModel::FileNameRole).toString());
+
+ qSort(dirEntries);
+ qSort(modelEntries);
+ QCOMPARE(dirEntries, modelEntries);
+
+#ifdef Q_OS_LINUX
+ if (files.count() >= 3 && rowCount >= 3 && rowCount != 5) {
+ QString fileName1 = (tmp + '/' + files.at(0));
+ QString fileName2 = (tmp + '/' + files.at(1));
+ QString fileName3 = (tmp + '/' + files.at(2));
+ QFile::Permissions originalPermissions = QFile::permissions(fileName1);
+ QVERIFY(QFile::setPermissions(fileName1, QFile::WriteOwner));
+ QVERIFY(QFile::setPermissions(fileName2, QFile::ReadOwner));
+ QVERIFY(QFile::setPermissions(fileName3, QFile::ExeOwner));
+
+ model->setFilter((QDir::Files | QDir::Readable));
+ QTRY_COMPARE(model->rowCount(root), 1);
+
+ model->setFilter((QDir::Files | QDir::Writable));
+ QTRY_COMPARE(model->rowCount(root), 1);
+
+ model->setFilter((QDir::Files | QDir::Executable));
+ QTRY_COMPARE(model->rowCount(root), 1);
+
+ // reset permissions
+ QVERIFY(QFile::setPermissions(fileName1, originalPermissions));
+ QVERIFY(QFile::setPermissions(fileName2, originalPermissions));
+ QVERIFY(QFile::setPermissions(fileName3, originalPermissions));
+ }
+#endif
+}
+
+void tst_QFileSystemModel::nameFilters()
+{
+ QStringList list;
+ list << "a" << "b" << "c";
+ model->setNameFilters(list);
+ model->setNameFilterDisables(false);
+ QCOMPARE(model->nameFilters(), list);
+
+ QString tmp = flatDirTestPath;
+ QVERIFY(createFiles(tmp, list));
+ QModelIndex root = model->setRootPath(tmp);
+ QTRY_COMPARE(model->rowCount(root), 3);
+
+ QStringList filters;
+ filters << "a" << "b";
+ model->setNameFilters(filters);
+ QTRY_COMPARE(model->rowCount(root), 2);
+}
+void tst_QFileSystemModel::setData_data()
+{
+ QTest::addColumn<QStringList>("files");
+ QTest::addColumn<QString>("oldFileName");
+ QTest::addColumn<QString>("newFileName");
+ QTest::addColumn<bool>("success");
+ /*QTest::newRow("outside current dir") << (QStringList() << "a" << "b" << "c")
+ << flatDirTestPath + '/' + "a"
+ << QDir::temp().absolutePath() + '/' + "a"
+ << false;
+ */
+ QTest::newRow("in current dir") << (QStringList() << "a" << "b" << "c")
+ << "a"
+ << "d"
+ << true;
+}
+
+void tst_QFileSystemModel::setData()
+{
+ QSignalSpy spy(model, SIGNAL(fileRenamed(const QString&, const QString&, const QString&)));
+ QString tmp = flatDirTestPath;
+ QFETCH(QStringList, files);
+ QFETCH(QString, oldFileName);
+ QFETCH(QString, newFileName);
+ QFETCH(bool, success);
+
+ QVERIFY(createFiles(tmp, files));
+ QModelIndex root = model->setRootPath(tmp);
+ QTRY_COMPARE(model->rowCount(root), files.count());
+
+ QModelIndex idx = model->index(tmp + '/' + oldFileName);
+ QCOMPARE(idx.isValid(), true);
+ QCOMPARE(model->setData(idx, newFileName), false);
+
+ model->setReadOnly(false);
+ QCOMPARE(model->setData(idx, newFileName), success);
+ if (success) {
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(model->data(idx, QFileSystemModel::FileNameRole).toString(), newFileName);
+ QCOMPARE(model->index(arguments.at(0).toString()), model->index(tmp));
+ QCOMPARE(arguments.at(1).toString(), oldFileName);
+ QCOMPARE(arguments.at(2).toString(), newFileName);
+ QCOMPARE(QFile::rename(tmp + '/' + newFileName, tmp + '/' + oldFileName), true);
+ }
+ QTRY_COMPARE(model->rowCount(root), files.count());
+}
+
+class MyFriendFileSystemModel : public QFileSystemModel
+{
+ friend class tst_QFileSystemModel;
+ Q_DECLARE_PRIVATE(QFileSystemModel)
+};
+
+void tst_QFileSystemModel::sort_data()
+{
+ QTest::addColumn<bool>("fileDialogMode");
+ QTest::newRow("standard usage") << false;
+ QTest::newRow("QFileDialog usage") << true;
+}
+
+void tst_QFileSystemModel::sort()
+{
+ QTemporaryFile file;
+ file.open();
+ QModelIndex root = model->setRootPath(QDir::tempPath());
+ QTRY_VERIFY(model->rowCount(root) > 0);
+
+ QPersistentModelIndex idx = model->index(0, 1, root);
+ model->sort(0, Qt::AscendingOrder);
+ model->sort(0, Qt::DescendingOrder);
+ QVERIFY(idx.column() != 0);
+
+ model->setRootPath(QDir::homePath());
+
+ QFETCH(bool, fileDialogMode);
+
+ MyFriendFileSystemModel *myModel = new MyFriendFileSystemModel();
+ QTreeView *tree = new QTreeView();
+
+#ifdef QT_BUILD_INTERNAL
+ if (fileDialogMode)
+ myModel->d_func()->disableRecursiveSort = true;
+#endif
+
+ QDir dir(QDir::tempPath());
+ //initialize the randomness
+ qsrand(QDateTime::currentDateTime().toTime_t());
+ QString tempName = QLatin1String("sortTemp.") + QString::number(qrand());
+ dir.mkdir(tempName);
+ dir.cd(tempName);
+ QTRY_VERIFY(dir.exists());
+
+ const QString dirPath = dir.absolutePath();
+ QVERIFY(dir.exists());
+
+ //Create a file that will be at the end when sorting by name (For Mac, the default)
+ //but if we sort by size descending it will be the first
+ QFile tempFile(dirPath + "/plop2.txt");
+ tempFile.open(QIODevice::WriteOnly | QIODevice::Text);
+ QTextStream out(&tempFile);
+ out << "The magic number is: " << 49 << "\n";
+ tempFile.close();
+
+ QFile tempFile2(dirPath + "/plop.txt");
+ tempFile2.open(QIODevice::WriteOnly | QIODevice::Text);
+ QTextStream out2(&tempFile2);
+ out2 << "The magic number is : " << 49 << " but i write some stuff in the file \n";
+ tempFile2.close();
+
+ myModel->setRootPath("");
+ myModel->setFilter(QDir::AllEntries | QDir::System | QDir::Hidden);
+ tree->setSortingEnabled(true);
+ tree->setModel(myModel);
+ tree->show();
+ tree->resize(800, 800);
+ QTest::qWait(500);
+ tree->header()->setSortIndicator(1,Qt::DescendingOrder);
+ tree->header()->setResizeMode(0, QHeaderView::ResizeToContents);
+ QStringList dirsToOpen;
+ do
+ {
+ dirsToOpen<<dir.absolutePath();
+ } while (dir.cdUp());
+
+ for (int i = dirsToOpen.size() -1 ; i > 0 ; --i) {
+ QString path = dirsToOpen[i];
+ QTest::qWait(500);
+ tree->expand(myModel->index(path, 0));
+ }
+ tree->expand(myModel->index(dirPath, 0));
+ QTest::qWait(500);
+ QModelIndex parent = myModel->index(dirPath, 0);
+ QList<QString> expectedOrder;
+ expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + "." << dirPath + QChar('/') + "..";
+ //File dialog Mode means sub trees are not sorted, only the current root
+ if (fileDialogMode) {
+ // FIXME: we were only able to disableRecursiveSort in developer builds, so we can only
+ // stably perform this test for developer builds
+#ifdef QT_BUILD_INTERNAL
+ QList<QString> actualRows;
+ for(int i = 0; i < myModel->rowCount(parent); ++i)
+ {
+ actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString();
+ }
+ QVERIFY(actualRows != expectedOrder);
+#endif
+ } else {
+ for(int i = 0; i < myModel->rowCount(parent); ++i)
+ {
+ QTRY_COMPARE(dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString(), expectedOrder.at(i));
+ }
+ }
+
+ delete tree;
+ delete myModel;
+
+ dir.setPath(QDir::tempPath());
+ dir.cd(tempName);
+ tempFile.remove();
+ tempFile2.remove();
+ dir.cdUp();
+ dir.rmdir(tempName);
+
+}
+
+void tst_QFileSystemModel::mkdir()
+{
+ QString tmp = QDir::tempPath();
+ QString newFolderPath = QDir::toNativeSeparators(tmp + '/' + "NewFoldermkdirtest4");
+ QModelIndex tmpDir = model->index(tmp);
+ QVERIFY(tmpDir.isValid());
+ QDir bestatic(newFolderPath);
+ if (bestatic.exists()) {
+ if (!bestatic.rmdir(newFolderPath))
+ qWarning() << "unable to remove" << newFolderPath;
+ QTest::qWait(WAITTIME);
+ }
+ model->mkdir(tmpDir, "NewFoldermkdirtest3");
+ model->mkdir(tmpDir, "NewFoldermkdirtest5");
+ QModelIndex idx = model->mkdir(tmpDir, "NewFoldermkdirtest4");
+ QVERIFY(idx.isValid());
+ int oldRow = idx.row();
+ QTest::qWait(WAITTIME);
+ idx = model->index(newFolderPath);
+ QDir cleanup(tmp);
+ QVERIFY(cleanup.rmdir(QLatin1String("NewFoldermkdirtest3")));
+ QVERIFY(cleanup.rmdir(QLatin1String("NewFoldermkdirtest5")));
+ bestatic.rmdir(newFolderPath);
+ QVERIFY(0 != idx.row());
+ QCOMPARE(oldRow, idx.row());
+}
+
+void tst_QFileSystemModel::caseSensitivity()
+{
+ QString tmp = flatDirTestPath;
+ QStringList files;
+ files << "a" << "c" << "C";
+ QVERIFY(createFiles(tmp, files));
+ QModelIndex root = model->index(tmp);
+ QCOMPARE(model->rowCount(root), 0);
+ for (int i = 0; i < files.count(); ++i) {
+ QVERIFY(model->index(tmp + '/' + files.at(i)).isValid());
+ }
+}
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+void tst_QFileSystemModel::Win32LongFileName()
+{
+ QString tmp = flatDirTestPath;
+ QStringList files;
+ files << "aaaaaaaaaa" << "bbbbbbbbbb" << "cccccccccc";
+ QVERIFY(createFiles(tmp, files));
+ QModelIndex root = model->setRootPath(tmp);
+ QTRY_VERIFY(model->index(tmp + QLatin1String("/aaaaaa~1")).isValid());
+ QTRY_VERIFY(model->index(tmp + QLatin1String("/bbbbbb~1")).isValid());
+ QTRY_VERIFY(model->index(tmp + QLatin1String("/cccccc~1")).isValid());
+}
+#endif
+
+void tst_QFileSystemModel::drives_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::newRow("current") << QDir::currentPath();
+ QTest::newRow("slash") << "/";
+ QTest::newRow("My Computer") << "My Computer";
+}
+
+void tst_QFileSystemModel::drives()
+{
+ QFETCH(QString, path);
+ QFileSystemModel model;
+ model.setRootPath(path);
+ model.fetchMore(QModelIndex());
+ QFileInfoList drives = QDir::drives();
+ int driveCount = 0;
+ foreach(const QFileInfo& driveRoot, drives)
+ if (driveRoot.exists())
+ driveCount++;
+ QTest::qWait(5000);
+ QTRY_COMPARE(model.rowCount(), driveCount);
+}
+
+void tst_QFileSystemModel::dirsBeforeFiles()
+{
+ const QString dirPath = QString("%1/task221717_sortedOrder_test_dir").arg(QDir::tempPath());
+ QDir dir(dirPath);
+ // clean up from last time
+ if (dir.exists()) {
+ for (int i = 0; i < 3; ++i) {
+ QLatin1Char c('a' + i);
+ dir.rmdir(QString("%1-dir").arg(c));
+ QFile::remove(dirPath + QString("/%1-file").arg(c));
+ }
+ dir.rmdir(dirPath);
+ }
+ QVERIFY(dir.mkpath(dirPath));
+ QVERIFY(QDir(dirPath).exists());
+
+ for (int i = 0; i < 3; ++i) {
+ QLatin1Char c('a' + i);
+ dir.mkdir(QString("%1-dir").arg(c));
+ QFile file(dirPath + QString("/%1-file").arg(c));
+ file.open(QIODevice::ReadWrite);
+ file.close();
+ }
+
+ QModelIndex root = model->setRootPath(dirPath);
+ QTest::qWait(1000); // allow model to be notified by the file system watcher
+
+ // ensure that no file occurs before a directory
+ for (int i = 0; i < model->rowCount(root); ++i) {
+#ifndef Q_OS_MAC
+ QVERIFY(i == 0 ||
+ !(model->fileInfo(model->index(i - 1, 0, root)).isFile()
+ && model->fileInfo(model->index(i, 0, root)).isDir()));
+#else
+ QVERIFY(i == 0 ||
+ model->fileInfo(model->index(i - 1, 0, root)).fileName() <
+ model->fileInfo(model->index(i, 0, root)).fileName());
+#endif
+ }
+}
+
+void tst_QFileSystemModel::roleNames_data()
+{
+ QTest::addColumn<int>("role");
+ QTest::addColumn<QByteArray>("roleName");
+ QTest::newRow("decoration") << int(Qt::DecorationRole) << QByteArray("decoration");
+ QTest::newRow("display") << int(Qt::DisplayRole) << QByteArray("display");
+ QTest::newRow("fileIcon") << int(QFileSystemModel::FileIconRole) << QByteArray("fileIcon");
+ QTest::newRow("filePath") << int(QFileSystemModel::FilePathRole) << QByteArray("filePath");
+ QTest::newRow("fileName") << int(QFileSystemModel::FileNameRole) << QByteArray("fileName");
+ QTest::newRow("filePermissions") << int(QFileSystemModel::FilePermissions) << QByteArray("filePermissions");
+}
+
+void tst_QFileSystemModel::roleNames()
+{
+ QFileSystemModel model;
+ QHash<int, QByteArray> roles = model.roleNames();
+
+ QFETCH(int, role);
+ QVERIFY(roles.contains(role));
+
+ QFETCH(QByteArray, roleName);
+ QList<QByteArray> values = roles.values(role);
+ QVERIFY(values.contains(roleName));
+}
+
+QTEST_MAIN(tst_QFileSystemModel)
+#include "tst_qfilesystemmodel.moc"
+
diff --git a/tests/auto/widgets/dialogs/qfontdialog/.gitignore b/tests/auto/widgets/dialogs/qfontdialog/.gitignore
new file mode 100644
index 0000000000..5bd48d4951
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfontdialog/.gitignore
@@ -0,0 +1 @@
+tst_qfontdialog
diff --git a/tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro b/tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro
new file mode 100644
index 0000000000..5a0c2b66bf
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qfontdialog.cpp
+
+mac:!qpa {
+ OBJECTIVE_SOURCES += tst_qfontdialog_mac_helpers.mm
+ LIBS += -framework Cocoa
+}
+
diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp
new file mode 100644
index 0000000000..3f12b7501c
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qapplication.h>
+#include <qfontinfo.h>
+#include <qtimer.h>
+#include <qmainwindow.h>
+#include <qlistview.h>
+#include "qfontdialog.h"
+#include <private/qfontdialog_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+QT_FORWARD_DECLARE_CLASS(QtTestEventThread)
+
+class tst_QFontDialog : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QFontDialog();
+ virtual ~tst_QFontDialog();
+
+
+public slots:
+ void postKeyReturn();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void defaultOkButton();
+ void setFont();
+ void task256466_wrongStyle();
+};
+
+tst_QFontDialog::tst_QFontDialog()
+{
+}
+
+tst_QFontDialog::~tst_QFontDialog()
+{
+}
+
+void tst_QFontDialog::initTestCase()
+{
+}
+
+void tst_QFontDialog::cleanupTestCase()
+{
+}
+
+void tst_QFontDialog::init()
+{
+}
+
+void tst_QFontDialog::cleanup()
+{
+}
+
+
+void tst_QFontDialog::postKeyReturn() {
+#ifndef Q_WS_MAC
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i=0; i<list.count(); ++i) {
+ QFontDialog *dialog = qobject_cast<QFontDialog*>(list[i]);
+ if (dialog) {
+ QTest::keyClick( list[i], Qt::Key_Return, Qt::NoModifier );
+ return;
+ }
+ }
+#else
+ extern void click_cocoa_button();
+ click_cocoa_button();
+#endif
+}
+
+void tst_QFontDialog::defaultOkButton()
+{
+ bool ok = FALSE;
+ QTimer::singleShot(2000, this, SLOT(postKeyReturn()));
+ QFontDialog::getFont(&ok);
+ QVERIFY(ok == TRUE);
+}
+
+
+void tst_QFontDialog::setFont()
+{
+ /* The font should be the same before as it is after if nothing changed
+ while the font dialog was open.
+ Task #27662
+ */
+ bool ok = FALSE;
+#if defined Q_OS_HPUX
+ QString fontName = "Courier";
+ int fontSize = 25;
+#elif defined Q_OS_AIX
+ QString fontName = "Charter";
+ int fontSize = 13;
+#else
+ QString fontName = "Arial";
+ int fontSize = 24;
+#endif
+ QFont f1(fontName, fontSize);
+ f1.setPixelSize(QFontInfo(f1).pixelSize());
+ QTimer::singleShot(2000, this, SLOT(postKeyReturn()));
+ QFont f2 = QFontDialog::getFont(&ok, f1);
+ QCOMPARE(QFontInfo(f2).pointSize(), QFontInfo(f1).pointSize());
+}
+
+
+class FriendlyFontDialog : public QFontDialog
+{
+ friend class tst_QFontDialog;
+ Q_DECLARE_PRIVATE(QFontDialog);
+};
+
+void tst_QFontDialog::task256466_wrongStyle()
+{
+ QFontDatabase fdb;
+ FriendlyFontDialog dialog;
+ QListView *familyList = reinterpret_cast<QListView*>(dialog.d_func()->familyList);
+ QListView *styleList = reinterpret_cast<QListView*>(dialog.d_func()->styleList);
+ QListView *sizeList = reinterpret_cast<QListView*>(dialog.d_func()->sizeList);
+ for (int i = 0; i < familyList->model()->rowCount(); ++i) {
+ QModelIndex currentFamily = familyList->model()->index(i, 0);
+ familyList->setCurrentIndex(currentFamily);
+ const QFont current = dialog.currentFont(),
+ expected = fdb.font(currentFamily.data().toString(),
+ styleList->currentIndex().data().toString(), sizeList->currentIndex().data().toInt());
+ QCOMPARE(current.family(), expected.family());
+ QCOMPARE(current.style(), expected.style());
+ QCOMPARE(current.pointSizeF(), expected.pointSizeF());
+ }
+}
+
+
+
+
+QTEST_MAIN(tst_QFontDialog)
+#include "tst_qfontdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm
new file mode 100644
index 0000000000..d12f696f7e
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qt_mac_p.h>
+#include <AppKit/AppKit.h>
+
+void click_cocoa_button()
+{
+ QMacCocoaAutoReleasePool pool;
+ NSArray *windows = [NSApp windows];
+ for (NSWindow *window in windows) {
+ // This is NOT how one should do RTTI, but since I don't want to leak the class too much...
+ if ([[window delegate] respondsToSelector:@selector(qtFont)]) {
+ NSArray *subviews = [[window contentView] subviews];
+ for (NSView *view in subviews) {
+ if ([view isKindOfClass:[NSButton class]]
+ && [[static_cast<NSButton *>(view) title] isEqualTo:@"OK"]) {
+ [static_cast<NSButton *>(view) performClick:view];
+ [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ subtype:SHRT_MAX data1:0 data2:0] atStart:NO];
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
diff --git a/tests/auto/widgets/dialogs/qinputdialog/.gitignore b/tests/auto/widgets/dialogs/qinputdialog/.gitignore
new file mode 100644
index 0000000000..b62797193c
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qinputdialog/.gitignore
@@ -0,0 +1 @@
+tst_qinputdialog
diff --git a/tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro b/tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro
new file mode 100644
index 0000000000..f7e56bd783
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qinputdialog.cpp
+
+
diff --git a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp
new file mode 100644
index 0000000000..5c74ab217b
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QString>
+#include <QSpinBox>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QDialogButtonBox>
+#include <qinputdialog.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QInputDialog : public QObject
+{
+ Q_OBJECT
+ QWidget *parent;
+ QDialog::DialogCode doneCode;
+ void (*testFunc)(QInputDialog *);
+ static void testFuncGetInteger(QInputDialog *dialog);
+ static void testFuncGetDouble(QInputDialog *dialog);
+ static void testFuncGetText(QInputDialog *dialog);
+ static void testFuncGetItem(QInputDialog *dialog);
+ void timerEvent(QTimerEvent *event);
+private slots:
+ void getInteger_data();
+ void getInteger();
+ void getDouble_data();
+ void getDouble();
+ void task255502getDouble();
+ void getText_data();
+ void getText();
+ void getItem_data();
+ void getItem();
+ void task256299_getTextReturnNullStringOnRejected();
+ void inputMethodHintsOfChildWidget();
+};
+
+QString stripFraction(const QString &s)
+{
+ int period;
+ if (s.contains('.'))
+ period = s.indexOf('.');
+ else if (s.contains(','))
+ period = s.indexOf(',');
+ else
+ return s;
+ int end;
+ for (end = s.size() - 1; end > period && s[end] == '0'; --end) ;
+ return s.left(end + (end == period ? 0 : 1));
+}
+
+QString normalizeNumericString(const QString &s)
+{
+ return stripFraction(s); // assumed to be sufficient
+}
+
+void _keyClick(QWidget *widget, char key)
+{
+ QTest::keyClick(widget, key);
+}
+
+void _keyClick(QWidget *widget, Qt::Key key)
+{
+ QTest::keyClick(widget, key);
+}
+
+template <typename SpinBoxType>
+void testTypingValue(
+ SpinBoxType* sbox, QPushButton *okButton, const QString &value)
+{
+ sbox->selectAll();
+ for (int i = 0; i < value.size(); ++i) {
+ const QChar valChar = value[i];
+ _keyClick(static_cast<QWidget *>(sbox), valChar.toAscii()); // ### always guaranteed to work?
+ if (sbox->hasAcceptableInput())
+ QVERIFY(okButton->isEnabled());
+ else
+ QVERIFY(!okButton->isEnabled());
+ }
+}
+
+void testTypingValue(QLineEdit *ledit, QPushButton *okButton, const QString &value)
+{
+ ledit->selectAll();
+ for (int i = 0; i < value.size(); ++i) {
+ const QChar valChar = value[i];
+ _keyClick(ledit, valChar.toAscii()); // ### always guaranteed to work?
+ QVERIFY(ledit->hasAcceptableInput());
+ QVERIFY(okButton->isEnabled());
+ }
+}
+
+template <typename SpinBoxType, typename ValueType>
+void testInvalidateAndRestore(
+ SpinBoxType* sbox, QPushButton *okButton, QLineEdit *ledit, ValueType * = 0)
+{
+ const ValueType lastValidValue = sbox->value();
+
+ sbox->selectAll();
+ _keyClick(ledit, Qt::Key_Delete);
+ QVERIFY(!sbox->hasAcceptableInput());
+ QVERIFY(!okButton->isEnabled());
+
+ _keyClick(ledit, Qt::Key_Return); // should work with Qt::Key_Enter too
+ QVERIFY(sbox->hasAcceptableInput());
+ QVERIFY(okButton->isEnabled());
+ QCOMPARE(sbox->value(), lastValidValue);
+ QLocale loc;
+ QCOMPARE(
+ normalizeNumericString(ledit->text()),
+ normalizeNumericString(loc.toString(sbox->value())));
+}
+
+template <typename SpinBoxType, typename ValueType>
+void testGetNumeric(QInputDialog *dialog, SpinBoxType * = 0, ValueType * = 0)
+{
+ SpinBoxType *sbox = qFindChild<SpinBoxType *>(dialog);
+ QVERIFY(sbox != 0);
+
+ QLineEdit *ledit = qFindChild<QLineEdit *>(static_cast<QObject *>(sbox));
+ QVERIFY(ledit != 0);
+
+ QDialogButtonBox *bbox = qFindChild<QDialogButtonBox *>(dialog);
+ QVERIFY(bbox != 0);
+ QPushButton *okButton = bbox->button(QDialogButtonBox::Ok);
+ QVERIFY(okButton != 0);
+
+ QVERIFY(sbox->value() >= sbox->minimum());
+ QVERIFY(sbox->value() <= sbox->maximum());
+ QVERIFY(sbox->hasAcceptableInput());
+ QLocale loc;
+ QCOMPARE(
+ normalizeNumericString(ledit->selectedText()),
+ normalizeNumericString(loc.toString(sbox->value())));
+ QVERIFY(okButton->isEnabled());
+
+ const ValueType origValue = sbox->value();
+
+ testInvalidateAndRestore<SpinBoxType, ValueType>(sbox, okButton, ledit);
+ testTypingValue<SpinBoxType>(sbox, okButton, QString("%1").arg(sbox->minimum()));
+ testTypingValue<SpinBoxType>(sbox, okButton, QString("%1").arg(sbox->maximum()));
+ testTypingValue<SpinBoxType>(sbox, okButton, QString("%1").arg(sbox->minimum() - 1));
+ testTypingValue<SpinBoxType>(sbox, okButton, QString("%1").arg(sbox->maximum() + 1));
+ testTypingValue<SpinBoxType>(sbox, okButton, "0");
+ testTypingValue<SpinBoxType>(sbox, okButton, "0.0");
+ testTypingValue<SpinBoxType>(sbox, okButton, "foobar");
+
+ testTypingValue<SpinBoxType>(sbox, okButton, loc.toString(origValue));
+}
+
+void testGetText(QInputDialog *dialog)
+{
+ QLineEdit *ledit = qFindChild<QLineEdit *>(dialog);
+ QVERIFY(ledit);
+
+ QDialogButtonBox *bbox = qFindChild<QDialogButtonBox *>(dialog);
+ QVERIFY(bbox);
+ QPushButton *okButton = bbox->button(QDialogButtonBox::Ok);
+ QVERIFY(okButton);
+
+ QVERIFY(ledit->hasAcceptableInput());
+ QCOMPARE(ledit->selectedText(), ledit->text());
+ QVERIFY(okButton->isEnabled());
+ const QString origValue = ledit->text();
+
+ testTypingValue(ledit, okButton, origValue);
+}
+
+void testGetItem(QInputDialog *dialog)
+{
+ QComboBox *cbox = qFindChild<QComboBox *>(dialog);
+ QVERIFY(cbox);
+
+ QDialogButtonBox *bbox = qFindChild<QDialogButtonBox *>(dialog);
+ QVERIFY(bbox);
+ QPushButton *okButton = bbox->button(QDialogButtonBox::Ok);
+ QVERIFY(okButton);
+
+ QVERIFY(okButton->isEnabled());
+ const int origIndex = cbox->currentIndex();
+ cbox->setCurrentIndex(origIndex - 1);
+ cbox->setCurrentIndex(origIndex);
+ QVERIFY(okButton->isEnabled());
+}
+
+void tst_QInputDialog::testFuncGetInteger(QInputDialog *dialog)
+{
+ testGetNumeric<QSpinBox, int>(dialog);
+}
+
+void tst_QInputDialog::testFuncGetDouble(QInputDialog *dialog)
+{
+ testGetNumeric<QDoubleSpinBox, double>(dialog);
+}
+
+void tst_QInputDialog::testFuncGetText(QInputDialog *dialog)
+{
+ ::testGetText(dialog);
+}
+
+void tst_QInputDialog::testFuncGetItem(QInputDialog *dialog)
+{
+ ::testGetItem(dialog);
+}
+
+void tst_QInputDialog::timerEvent(QTimerEvent *event)
+{
+ killTimer(event->timerId());
+ QInputDialog *dialog = qFindChild<QInputDialog *>(parent);
+ QVERIFY(dialog);
+ if (testFunc)
+ testFunc(dialog);
+ dialog->done(doneCode); // cause static function call to return
+}
+
+void tst_QInputDialog::getInteger_data()
+{
+ QTest::addColumn<int>("min");
+ QTest::addColumn<int>("max");
+ QTest::newRow("getInteger() - -") << -20 << -10;
+ QTest::newRow("getInteger() - 0") << -20 << 0;
+ QTest::newRow("getInteger() - +") << -20 << 20;
+ QTest::newRow("getInteger() 0 +") << 0 << 20;
+ QTest::newRow("getInteger() + +") << 10 << 20;
+}
+
+void tst_QInputDialog::getInteger()
+{
+ QFETCH(int, min);
+ QFETCH(int, max);
+ QVERIFY(min < max);
+ parent = new QWidget;
+ doneCode = QDialog::Accepted;
+ testFunc = &tst_QInputDialog::testFuncGetInteger;
+ startTimer(0);
+ bool ok = false;
+ const int value = min + (max - min) / 2;
+ const int result = QInputDialog::getInteger(parent, "", "", value, min, max, 1, &ok);
+ QVERIFY(ok);
+ QCOMPARE(result, value);
+ delete parent;
+}
+
+void tst_QInputDialog::getDouble_data()
+{
+ QTest::addColumn<double>("min");
+ QTest::addColumn<double>("max");
+ QTest::addColumn<int>("decimals");
+ QTest::newRow("getDouble() - - d0") << -20.0 << -10.0 << 0;
+ QTest::newRow("getDouble() - 0 d0") << -20.0 << 0.0 << 0;
+ QTest::newRow("getDouble() - + d0") << -20.0 << 20.0 << 0;
+ QTest::newRow("getDouble() 0 + d0") << 0.0 << 20.0 << 0;
+ QTest::newRow("getDouble() + + d0") << 10.0 << 20.0 << 0;
+ QTest::newRow("getDouble() - - d1") << -20.5 << -10.5 << 1;
+ QTest::newRow("getDouble() - 0 d1") << -20.5 << 0.0 << 1;
+ QTest::newRow("getDouble() - + d1") << -20.5 << 20.5 << 1;
+ QTest::newRow("getDouble() 0 + d1") << 0.0 << 20.5 << 1;
+ QTest::newRow("getDouble() + + d1") << 10.5 << 20.5 << 1;
+ QTest::newRow("getDouble() - - d2") << -20.05 << -10.05 << 2;
+ QTest::newRow("getDouble() - 0 d2") << -20.05 << 0.0 << 2;
+ QTest::newRow("getDouble() - + d2") << -20.05 << 20.05 << 2;
+ QTest::newRow("getDouble() 0 + d2") << 0.0 << 20.05 << 2;
+ QTest::newRow("getDouble() + + d2") << 10.05 << 20.05 << 2;
+}
+
+void tst_QInputDialog::getDouble()
+{
+ QFETCH(double, min);
+ QFETCH(double, max);
+ QFETCH(int, decimals);
+ QVERIFY(min < max && decimals >= 0 && decimals <= 13);
+ parent = new QWidget;
+ doneCode = QDialog::Accepted;
+ testFunc = &tst_QInputDialog::testFuncGetDouble;
+ startTimer(0);
+ bool ok = false;
+ // avoid decimals due to inconsistent roundoff behavior in QInputDialog::getDouble()
+ // (at one decimal, 10.25 is rounded off to 10.2, while at two decimals, 10.025 is
+ // rounded off to 10.03)
+ const double value = static_cast<int>(min + (max - min) / 2);
+ const double result =
+ QInputDialog::getDouble(parent, "", "", value, min, max, decimals, &ok);
+ QVERIFY(ok);
+ QCOMPARE(result, value);
+ delete parent;
+}
+
+void tst_QInputDialog::task255502getDouble()
+{
+ parent = new QWidget;
+ doneCode = QDialog::Accepted;
+ testFunc = &tst_QInputDialog::testFuncGetDouble;
+ startTimer(0);
+ bool ok = false;
+ const double value = 0.001;
+ const double result =
+ QInputDialog::getDouble(parent, "", "", value, -1, 1, 4, &ok);
+ QVERIFY(ok);
+ QCOMPARE(result, value);
+ delete parent;
+}
+
+void tst_QInputDialog::getText_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::newRow("getText() 1") << "";
+ QTest::newRow("getText() 2") << "foobar";
+ QTest::newRow("getText() 3") << " foobar";
+ QTest::newRow("getText() 4") << "foobar ";
+ QTest::newRow("getText() 5") << "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?";
+}
+
+void tst_QInputDialog::getText()
+{
+ QFETCH(QString, text);
+ parent = new QWidget;
+ doneCode = QDialog::Accepted;
+ testFunc = &tst_QInputDialog::testFuncGetText;
+ startTimer(0);
+ bool ok = false;
+ const QString result = QInputDialog::getText(parent, "", "", QLineEdit::Normal, text, &ok);
+ QVERIFY(ok);
+ QCOMPARE(result, text);
+ delete parent;
+}
+
+void tst_QInputDialog::task256299_getTextReturnNullStringOnRejected()
+{
+ parent = new QWidget;
+ doneCode = QDialog::Rejected;
+ testFunc = 0;
+ startTimer(0);
+ bool ok = true;
+ const QString result = QInputDialog::getText(parent, "", "", QLineEdit::Normal, "foobar", &ok);
+ QVERIFY(!ok);
+ QVERIFY(result.isNull());
+ delete parent;
+}
+
+void tst_QInputDialog::getItem_data()
+{
+ QTest::addColumn<QStringList>("items");
+ QTest::addColumn<bool>("editable");
+ QTest::newRow("getItem() 1 true") << (QStringList() << "") << true;
+ QTest::newRow("getItem() 2 true") <<
+ (QStringList() << "spring" << "summer" << "fall" << "winter") << true;
+ QTest::newRow("getItem() 1 false") << (QStringList() << "") << false;
+ QTest::newRow("getItem() 2 false") <<
+ (QStringList() << "spring" << "summer" << "fall" << "winter") << false;
+}
+
+void tst_QInputDialog::getItem()
+{
+ QFETCH(QStringList, items);
+ QFETCH(bool, editable);
+ parent = new QWidget;
+ doneCode = QDialog::Accepted;
+ testFunc = &tst_QInputDialog::testFuncGetItem;
+ startTimer(0);
+ bool ok = false;
+ const int index = items.size() / 2;
+ const QString result = QInputDialog::getItem(parent, "", "", items, index, editable, &ok);
+ QVERIFY(ok);
+ QCOMPARE(result, items[index]);
+ delete parent;
+}
+
+void tst_QInputDialog::inputMethodHintsOfChildWidget()
+{
+ QInputDialog dialog;
+ dialog.setInputMode(QInputDialog::TextInput);
+ QList<QObject *> children = dialog.children();
+ QLineEdit *editWidget = 0;
+ for (int c = 0; c < children.size(); c++) {
+ editWidget = qobject_cast<QLineEdit *>(children.at(c));
+ if (editWidget)
+ break;
+ }
+ QVERIFY(editWidget);
+ QCOMPARE(editWidget->inputMethodHints(), dialog.inputMethodHints());
+ QCOMPARE(editWidget->inputMethodHints(), Qt::ImhNone);
+ dialog.setInputMethodHints(Qt::ImhDigitsOnly);
+ QCOMPARE(editWidget->inputMethodHints(), dialog.inputMethodHints());
+ QCOMPARE(editWidget->inputMethodHints(), Qt::ImhDigitsOnly);
+}
+
+QTEST_MAIN(tst_QInputDialog)
+#include "tst_qinputdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qmessagebox/.gitignore b/tests/auto/widgets/dialogs/qmessagebox/.gitignore
new file mode 100644
index 0000000000..19a0a35121
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qmessagebox/.gitignore
@@ -0,0 +1 @@
+tst_qmessagebox
diff --git a/tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro b/tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro
new file mode 100644
index 0000000000..e3f6ddb1f6
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qmessagebox
+QT += widgets
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += tst_qmessagebox.cpp
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
new file mode 100644
index 0000000000..a07d7cf7a9
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -0,0 +1,674 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QMessageBox>
+#include <QDebug>
+#include <QPair>
+#include <QList>
+#include <QPointer>
+#include <QTimer>
+#include <QApplication>
+#include <QPushButton>
+#include <QDialogButtonBox>
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+#include <QMacStyle>
+#endif
+#if !defined(QT_NO_STYLE_CLEANLOOKS)
+#include <QCleanlooksStyle>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#define CONVENIENCE_FUNC_SYMS(func) \
+ { \
+ int x1 = QMessageBox::func(0, "Foo", "Bar"); \
+ int x3 = QMessageBox::func(0, "Foo", "Bar", "Save"); \
+ int x6 = QMessageBox::func(0, "Foo", "Bar", "Save", "Save As"); \
+ int x7 = QMessageBox::func(0, "Foo", "Bar", "Save", "Save As", "Dont Save"); \
+ int x8 = QMessageBox::func(0, "Foo", "Bar", "Save", "Save As", "Dont Save", 1); \
+ int x9 = QMessageBox::func(0, "Foo", "Bar", "Save", "Save As", "Dont Save", 1, 2); \
+ int x10 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::YesAll, QMessageBox::Yes); \
+ int x11 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::YesAll, QMessageBox::Yes, \
+ QMessageBox::No); \
+ qDebug("%d %d %d %d %d %d %d %d", x1, x3, x6, x7, x8, x9, x10, x11); \
+ { \
+ int x4 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes, (int)QMessageBox::No); \
+ int x5 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes, (int)QMessageBox::No); \
+ int x6 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default, (int)QMessageBox::No); \
+ int x7 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes, QMessageBox::No); \
+ int x8 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes, QMessageBox::No); \
+ int x9 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No); \
+ int x10 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes, (int)QMessageBox::No, (int)QMessageBox::Ok); \
+ int x11 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes, (int)QMessageBox::No, (int)QMessageBox::Ok); \
+ int x12 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default, (int)QMessageBox::No, (int)QMessageBox::Ok); \
+ int x13 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes, QMessageBox::No, (int)QMessageBox::Ok); \
+ int x14 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes, QMessageBox::No, (int)QMessageBox::Ok); \
+ int x15 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, (int)QMessageBox::Ok); \
+ int x16 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes, (int)QMessageBox::No, QMessageBox::Ok); \
+ int x17 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes, (int)QMessageBox::No, QMessageBox::Ok); \
+ int x18 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default, (int)QMessageBox::No, QMessageBox::Ok); \
+ int x19 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes, QMessageBox::No, QMessageBox::Ok); \
+ int x20 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes, QMessageBox::No, QMessageBox::Ok); \
+ int x21 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Ok); \
+ qDebug("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21); \
+ } \
+ }
+
+#define CONVENIENCE_FUNC_SYMS_EXTRA(func) \
+ { \
+ int x1 = QMessageBox::func(0, "Foo", "Bar", (int)QMessageBox::Yes); \
+ int x2 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes); \
+ int x3 = QMessageBox::func(0, "Foo", "Bar", QMessageBox::Yes | QMessageBox::Default); \
+ qDebug("%d %d %d", x1, x2, x3); \
+ }
+
+class tst_QMessageBox : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMessageBox();
+ int exec(QMessageBox *msgBox, int key = -1);
+ void sendKeySoon();
+
+public slots:
+ void sendKey();
+
+private slots:
+ void sanityTest();
+ void defaultButton();
+ void escapeButton();
+ void button();
+ void statics();
+ void about();
+ void detailsText();
+ void detailsButtonText();
+
+#ifndef Q_WS_MAC
+ void shortcut();
+#endif
+
+ void staticSourceCompat();
+ void instanceSourceCompat();
+
+ void testSymbols();
+ void incorrectDefaultButton();
+ void updateSize();
+
+ void setInformativeText();
+ void iconPixmap();
+
+ void init();
+ void initTestCase();
+
+private:
+ int keyToSend;
+ QTimer keySendTimer;
+};
+
+tst_QMessageBox::tst_QMessageBox() : keyToSend(-1)
+{
+ int argc = qApp->argc();
+ QT_REQUIRE_VERSION(argc, qApp->argv(), "4.6.2")
+}
+
+int tst_QMessageBox::exec(QMessageBox *msgBox, int key)
+{
+ if (key == -1) {
+ QTimer::singleShot(1000, msgBox, SLOT(close()));
+ } else {
+ keyToSend = key;
+ sendKeySoon();
+ }
+ return msgBox->exec();
+}
+
+void tst_QMessageBox::sendKey()
+{
+ if (keyToSend == -2) {
+ QApplication::activeModalWidget()->close();
+ keyToSend = -1;
+ return;
+ }
+ if (keyToSend == -1)
+ return;
+ QKeyEvent *ke = new QKeyEvent(QEvent::KeyPress, keyToSend, Qt::NoModifier);
+ qApp->postEvent(QApplication::activeModalWidget(), ke);
+ keyToSend = -1;
+}
+
+void tst_QMessageBox::sendKeySoon()
+{
+ keySendTimer.start();
+}
+
+void tst_QMessageBox::init()
+{
+ // if there is any pending key send from the last test, cancel it.
+ keySendTimer.stop();
+}
+
+void tst_QMessageBox::initTestCase()
+{
+ keySendTimer.setInterval(1000);
+ keySendTimer.setSingleShot(true);
+ QVERIFY(QObject::connect(&keySendTimer, SIGNAL(timeout()), this, SLOT(sendKey())));
+}
+
+void tst_QMessageBox::sanityTest()
+{
+ QMessageBox msgBox;
+ msgBox.setText("This is insane");
+ for (int i = 0; i < 10; i++)
+ msgBox.setIcon(QMessageBox::Icon(i));
+ msgBox.setIconPixmap(QPixmap());
+ msgBox.setIconPixmap(QPixmap("whatever.png"));
+ msgBox.setTextFormat(Qt::RichText);
+ msgBox.setTextFormat(Qt::PlainText);
+ exec(&msgBox);
+}
+
+void tst_QMessageBox::button()
+{
+ QMessageBox msgBox;
+ msgBox.addButton("retry", QMessageBox::DestructiveRole);
+ QVERIFY(msgBox.button(QMessageBox::Ok) == 0); // not added yet
+ QPushButton *b1 = msgBox.addButton(QMessageBox::Ok);
+ QCOMPARE(msgBox.button(QMessageBox::Ok), (QAbstractButton *)b1); // just added
+ QCOMPARE(msgBox.standardButton(b1), QMessageBox::Ok);
+ msgBox.addButton(QMessageBox::Cancel);
+ QCOMPARE(msgBox.standardButtons(), QMessageBox::Ok | QMessageBox::Cancel);
+
+ // remove the cancel, should not exist anymore
+ msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+ QVERIFY(msgBox.button(QMessageBox::Cancel) == 0);
+ QVERIFY(msgBox.button(QMessageBox::Yes) != 0);
+
+ // should not crash
+ QPushButton *b4 = new QPushButton;
+ msgBox.addButton(b4, QMessageBox::DestructiveRole);
+ msgBox.addButton(0, QMessageBox::ActionRole);
+}
+
+void tst_QMessageBox::defaultButton()
+{
+ QMessageBox msgBox;
+ QVERIFY(msgBox.defaultButton() == 0);
+ msgBox.addButton(QMessageBox::Ok);
+ msgBox.addButton(QMessageBox::Cancel);
+ QVERIFY(msgBox.defaultButton() == 0);
+ QPushButton pushButton;
+ msgBox.setDefaultButton(&pushButton);
+ QVERIFY(msgBox.defaultButton() == 0); // we have not added it yet
+ QPushButton *retryButton = msgBox.addButton(QMessageBox::Retry);
+ msgBox.setDefaultButton(retryButton);
+ QCOMPARE(msgBox.defaultButton(), retryButton);
+ exec(&msgBox);
+ QCOMPARE(msgBox.clickedButton(), msgBox.button(QMessageBox::Cancel));
+
+ exec(&msgBox, Qt::Key_Enter);
+ QCOMPARE(msgBox.clickedButton(), (QAbstractButton *)retryButton);
+
+ QAbstractButton *okButton = msgBox.button(QMessageBox::Ok);
+ msgBox.setDefaultButton(QMessageBox::Ok);
+ QCOMPARE(msgBox.defaultButton(), (QPushButton *)okButton);
+ exec(&msgBox, Qt::Key_Enter);
+ QCOMPARE(msgBox.clickedButton(), okButton);
+ msgBox.setDefaultButton(QMessageBox::Yes); // its not in there!
+ QVERIFY(msgBox.defaultButton() == okButton);
+ msgBox.removeButton(okButton);
+ delete okButton;
+ okButton = 0;
+ QVERIFY(msgBox.defaultButton() == 0);
+ msgBox.setDefaultButton(QMessageBox::Ok);
+ QVERIFY(msgBox.defaultButton() == 0);
+}
+
+void tst_QMessageBox::escapeButton()
+{
+ QMessageBox msgBox;
+ QVERIFY(msgBox.escapeButton() == 0);
+ msgBox.addButton(QMessageBox::Ok);
+ exec(&msgBox);
+ QVERIFY(msgBox.clickedButton() == msgBox.button(QMessageBox::Ok)); // auto detected (one button only)
+ msgBox.addButton(QMessageBox::Cancel);
+ QVERIFY(msgBox.escapeButton() == 0);
+ QPushButton invalidButton;
+ msgBox.setEscapeButton(&invalidButton);
+ QVERIFY(msgBox.escapeButton() == 0);
+ QAbstractButton *retryButton = msgBox.addButton(QMessageBox::Retry);
+
+ exec(&msgBox);
+ QVERIFY(msgBox.clickedButton() == msgBox.button(QMessageBox::Cancel)); // auto detected (cancel)
+
+ msgBox.setEscapeButton(retryButton);
+ QCOMPARE(msgBox.escapeButton(), (QAbstractButton *)retryButton);
+
+ // with escape
+ exec(&msgBox, Qt::Key_Escape);
+ QCOMPARE(msgBox.clickedButton(), retryButton);
+
+ // with close
+ exec(&msgBox);
+ QCOMPARE(msgBox.clickedButton(), (QAbstractButton *)retryButton);
+
+ QAbstractButton *okButton = msgBox.button(QMessageBox::Ok);
+ msgBox.setEscapeButton(QMessageBox::Ok);
+ QCOMPARE(msgBox.escapeButton(), okButton);
+ exec(&msgBox, Qt::Key_Escape);
+ QCOMPARE(msgBox.clickedButton(), okButton);
+ msgBox.setEscapeButton(QMessageBox::Yes); // its not in there!
+ QVERIFY(msgBox.escapeButton() == okButton);
+ msgBox.removeButton(okButton);
+ delete okButton;
+ okButton = 0;
+ QVERIFY(msgBox.escapeButton() == 0);
+ msgBox.setEscapeButton(QMessageBox::Ok);
+ QVERIFY(msgBox.escapeButton() == 0);
+
+ QMessageBox msgBox2;
+ msgBox2.addButton(QMessageBox::Yes);
+ msgBox2.addButton(QMessageBox::No);
+ exec(&msgBox2);
+ QVERIFY(msgBox2.clickedButton() == msgBox2.button(QMessageBox::No)); // auto detected (one No button only)
+
+ QPushButton *rejectButton = new QPushButton;
+ msgBox2.addButton(rejectButton, QMessageBox::RejectRole);
+ exec(&msgBox2);
+ QVERIFY(msgBox2.clickedButton() == rejectButton); // auto detected (one reject button only)
+
+ msgBox2.addButton(new QPushButton, QMessageBox::RejectRole);
+ exec(&msgBox2);
+ QVERIFY(msgBox2.clickedButton() == msgBox2.button(QMessageBox::No)); // auto detected (one No button only)
+}
+
+void tst_QMessageBox::statics()
+{
+ QMessageBox::StandardButton (*statics[4])(QWidget *, const QString &,
+ const QString&, QMessageBox::StandardButtons buttons,
+ QMessageBox::StandardButton);
+
+ statics[0] = QMessageBox::information;
+ statics[1] = QMessageBox::critical;
+ statics[2] = QMessageBox::question;
+ statics[3] = QMessageBox::warning;
+
+ for (int i = 0; i < 4; i++) {
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ QMessageBox::StandardButton sb = (*statics[i])(0, "caption",
+ "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help | QMessageBox::Cancel,
+ QMessageBox::NoButton);
+ QCOMPARE(sb, QMessageBox::Cancel);
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = -2; // close()
+ sendKeySoon();
+ sb = (*statics[i])(0, "caption",
+ "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help | QMessageBox::Cancel,
+ QMessageBox::NoButton);
+ QCOMPARE(sb, QMessageBox::Cancel);
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ sb = (*statics[i])(0, "caption",
+ "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help,
+ QMessageBox::Yes);
+ QCOMPARE(sb, QMessageBox::Yes);
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ sb = (*statics[i])(0, "caption",
+ "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help,
+ QMessageBox::No);
+ QCOMPARE(sb, QMessageBox::No);
+ QCOMPARE(keyToSend, -1);
+ }
+}
+
+// Shortcuts are not used on Mac OS X.
+#ifndef Q_WS_MAC
+void tst_QMessageBox::shortcut()
+{
+ QMessageBox msgBox;
+ msgBox.addButton("O&k", QMessageBox::YesRole);
+ msgBox.addButton("&No", QMessageBox::YesRole);
+ msgBox.addButton("&Maybe", QMessageBox::YesRole);
+ QCOMPARE(exec(&msgBox, Qt::Key_M), 2);
+}
+#endif
+
+void tst_QMessageBox::about()
+{
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ QMessageBox::about(0, "Caption", "This is an auto test");
+ // On Mac, about and aboutQt are not modal, so we need to
+ // explicitly run the event loop
+#ifdef Q_WS_MAC
+ QTRY_COMPARE(keyToSend, -1);
+#else
+ QCOMPARE(keyToSend, -1);
+#endif
+
+#if !defined(Q_OS_WINCE)
+ keyToSend = Qt::Key_Enter;
+#else
+ keyToSend = Qt::Key_Escape;
+#endif
+ sendKeySoon();
+ QMessageBox::aboutQt(0, "Caption");
+#ifdef Q_WS_MAC
+ QTRY_COMPARE(keyToSend, -1);
+#else
+ QCOMPARE(keyToSend, -1);
+#endif
+}
+
+void tst_QMessageBox::staticSourceCompat()
+{
+ int ret;
+
+ // source compat tests for < 4.2
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes, QMessageBox::No);
+ int expectedButton = int(QMessageBox::Yes);
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+ if (qobject_cast<QMacStyle *>(qApp->style()))
+ expectedButton = int(QMessageBox::No);
+#elif !defined(QT_NO_STYLE_CLEANLOOKS)
+ if (qobject_cast<QCleanlooksStyle *>(qApp->style()))
+ expectedButton = int(QMessageBox::No);
+#endif
+ QCOMPARE(ret, expectedButton);
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No);
+ QCOMPARE(ret, int(QMessageBox::Yes));
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default);
+ QCOMPARE(ret, int(QMessageBox::No));
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape);
+ QCOMPARE(ret, int(QMessageBox::Yes));
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes | QMessageBox::Escape, QMessageBox::No | QMessageBox::Default);
+ QCOMPARE(ret, int(QMessageBox::No));
+ QCOMPARE(keyToSend, -1);
+
+ // the button text versions
+ keyToSend = Qt::Key_Enter;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", "Yes", "No", QString(), 1);
+ QCOMPARE(ret, 1);
+ QCOMPARE(keyToSend, -1);
+
+ if (0) { // dont run these tests since the dialog wont close!
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", "Yes", "No", QString(), 1);
+ QCOMPARE(ret, -1);
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ ret = QMessageBox::information(0, "title", "text", "Yes", "No", QString(), 0, 1);
+ QCOMPARE(ret, 1);
+ QCOMPARE(keyToSend, -1);
+ }
+}
+
+void tst_QMessageBox::instanceSourceCompat()
+{
+ QMessageBox mb("Application name here",
+ "Saving the file will overwrite the original file on the disk.\n"
+ "Do you really want to save?",
+ QMessageBox::Information,
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No,
+ QMessageBox::Cancel | QMessageBox::Escape);
+ mb.setButtonText(QMessageBox::Yes, "Save");
+ mb.setButtonText(QMessageBox::No, "Discard");
+ mb.addButton("&Revert", QMessageBox::RejectRole);
+ mb.addButton("&Zoo", QMessageBox::ActionRole);
+
+ QCOMPARE(exec(&mb, Qt::Key_Enter), int(QMessageBox::Yes));
+ QCOMPARE(exec(&mb, Qt::Key_Escape), int(QMessageBox::Cancel));
+#ifndef Q_WS_MAC
+ // mnemonics are not used on Mac OS X
+ QCOMPARE(exec(&mb, Qt::ALT + Qt::Key_R), 0);
+ QCOMPARE(exec(&mb, Qt::ALT + Qt::Key_Z), 1);
+#endif
+}
+
+void tst_QMessageBox::testSymbols()
+{
+ return;
+
+ QMessageBox::Icon icon;
+ icon = QMessageBox::NoIcon;
+ icon = QMessageBox::Information;
+ icon = QMessageBox::Warning;
+ icon = QMessageBox::Critical;
+ icon = QMessageBox::Question;
+
+ QMessageBox mb1;
+ QMessageBox mb2(0);
+ QMessageBox mb3(&mb1);
+ QMessageBox mb3b("title", "text", QMessageBox::Critical, int(QMessageBox::Yes),
+ int(QMessageBox::No), int(QMessageBox::Cancel), &mb1, Qt::Dialog);
+
+ QMessageBox::Button button = QMessageBox::NoButton;
+ button = QMessageBox::Ok;
+ button = QMessageBox::Cancel;
+ button = QMessageBox::Yes;
+ button = QMessageBox::No;
+ button = QMessageBox::Abort;
+ button = QMessageBox::Retry;
+ button = QMessageBox::Ignore;
+ button = QMessageBox::YesAll;
+ button = QMessageBox::NoAll;
+ button = QMessageBox::ButtonMask;
+ button = QMessageBox::Default;
+ button = QMessageBox::Escape;
+ button = QMessageBox::FlagMask;
+
+ const QString text = QStringLiteral("Foo");
+ mb1.setText(text);
+ QCOMPARE(mb1.text(), text);
+
+ icon = mb1.icon();
+ QVERIFY(icon == QMessageBox::NoIcon);
+ mb1.setIcon(QMessageBox::Question);
+ QVERIFY(mb1.icon() == QMessageBox::Question);
+
+ QPixmap iconPixmap = mb1.iconPixmap();
+ mb1.setIconPixmap(iconPixmap);
+ QVERIFY(mb1.icon() == QMessageBox::NoIcon);
+
+ QCOMPARE(mb1.buttonText(QMessageBox::Ok), QLatin1String("OK"));
+ QCOMPARE(mb1.buttonText(QMessageBox::Cancel), QString());
+ QCOMPARE(mb1.buttonText(QMessageBox::Ok | QMessageBox::Default), QString());
+
+ const QString button1 = QStringLiteral("Bar");
+ mb2.setButtonText(QMessageBox::Cancel, QStringLiteral("Foo"));
+ mb2.setButtonText(QMessageBox::Ok, button1);
+ mb2.setButtonText(QMessageBox::Ok | QMessageBox::Default, QStringLiteral("Baz"));
+
+ QCOMPARE(mb2.buttonText(QMessageBox::Cancel), QString());
+ QCOMPARE(mb2.buttonText(QMessageBox::Ok), button1);
+
+ QVERIFY(mb3b.buttonText(QMessageBox::Yes).endsWith("Yes"));
+ QCOMPARE(mb3b.buttonText(QMessageBox::YesAll), QString());
+ QCOMPARE(mb3b.buttonText(QMessageBox::Ok), QString());
+
+ const QString button2 = QStringLiteral("Blah");
+ mb3b.setButtonText(QMessageBox::Yes, button2);
+ mb3b.setButtonText(QMessageBox::YesAll, QStringLiteral("Zoo"));
+ mb3b.setButtonText(QMessageBox::Ok, QStringLiteral("Zoo"));
+
+ QCOMPARE(mb3b.buttonText(QMessageBox::Yes), button2);
+ QCOMPARE(mb3b.buttonText(QMessageBox::YesAll), QString());
+ QCOMPARE(mb3b.buttonText(QMessageBox::Ok), QString());
+
+ QCOMPARE(mb1.textFormat(), Qt::AutoText);
+ mb1.setTextFormat(Qt::PlainText);
+ QCOMPARE(mb1.textFormat(), Qt::PlainText);
+
+ CONVENIENCE_FUNC_SYMS(information);
+ CONVENIENCE_FUNC_SYMS_EXTRA(information);
+ CONVENIENCE_FUNC_SYMS(question);
+ CONVENIENCE_FUNC_SYMS_EXTRA(question);
+ CONVENIENCE_FUNC_SYMS(warning);
+ CONVENIENCE_FUNC_SYMS(critical);
+
+ QSize sizeHint = mb1.sizeHint();
+ QVERIFY(sizeHint.width() > 20 && sizeHint.height() > 20);
+
+ QMessageBox::about(&mb1, "title", "text");
+ QMessageBox::aboutQt(&mb1);
+ QMessageBox::aboutQt(&mb1, "title");
+}
+
+void tst_QMessageBox::detailsText()
+{
+ QMessageBox box;
+ QString text("This is the details text.");
+ box.setDetailedText(text);
+ QCOMPARE(box.detailedText(), text);
+}
+
+void tst_QMessageBox::detailsButtonText()
+{
+ QMessageBox box;
+ box.setDetailedText("bla");
+ box.open();
+ QApplication::postEvent(&box, new QEvent(QEvent::LanguageChange));
+ QApplication::processEvents();
+ QDialogButtonBox* bb = box.findChild<QDialogButtonBox*>("qt_msgbox_buttonbox");
+ QVERIFY(bb); //get the detail button
+
+ QList<QAbstractButton *> list = bb->buttons();
+ QAbstractButton* btn = NULL;
+ foreach(btn, list) {
+ if (btn && (btn->inherits("QPushButton"))) {
+ if (btn->text() != QMessageBox::tr("OK") && btn->text() != QMessageBox::tr("Show Details...")) {
+ QFAIL(qPrintable(QString("Unexpected messagebox button text: %1").arg(btn->text())));
+ }
+ }
+ }
+}
+
+void tst_QMessageBox::incorrectDefaultButton()
+{
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ //Do not crash here
+ QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
+ QMessageBox::question( 0, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save );
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
+ QMessageBox::question( 0, "", "I've been hit!",QFlag(QMessageBox::Ok | QMessageBox::Cancel),QMessageBox::Save );
+ QCOMPARE(keyToSend, -1);
+
+ keyToSend = Qt::Key_Escape;
+ sendKeySoon();
+ QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
+ QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
+ //do not crash here -> call old function of QMessageBox in this case
+ QMessageBox::question( 0, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Ok);
+ QCOMPARE(keyToSend, -1);
+}
+
+void tst_QMessageBox::updateSize()
+{
+ QMessageBox box;
+ box.setText("This is awesome");
+ box.show();
+ QSize oldSize = box.size();
+ QString longText;
+ for (int i = 0; i < 20; i++)
+ longText += box.text();
+ box.setText(longText);
+ QVERIFY(box.size() != oldSize); // should have grown
+ QVERIFY(box.width() > oldSize.width() || box.height() > oldSize.height());
+ oldSize = box.size();
+ box.setStandardButtons(QMessageBox::StandardButtons(0xFFFF));
+ QVERIFY(box.size() != oldSize); // should have grown
+ QVERIFY(box.width() > oldSize.width() || box.height() > oldSize.height());
+}
+
+void tst_QMessageBox::setInformativeText()
+{
+ QMessageBox msgbox(QMessageBox::Warning, "", "", QMessageBox::Ok);
+ QString itext = "This is a very long message and it should make the dialog have enough width to fit this message in";
+ msgbox.setInformativeText(itext);
+ msgbox.show();
+ QCOMPARE(msgbox.informativeText(), itext);
+ QVERIFY2(msgbox.width() > 190, //verify it's big enough (task181688)
+ qPrintable(QString("%1 > 190").arg(msgbox.width())));
+}
+
+void tst_QMessageBox::iconPixmap()
+{
+ QMessageBox messageBox;
+ QCOMPARE(messageBox.iconPixmap(), QPixmap());
+}
+
+QTEST_MAIN(tst_QMessageBox)
+#include "tst_qmessagebox.moc"
diff --git a/tests/auto/widgets/dialogs/qprogressdialog/.gitignore b/tests/auto/widgets/dialogs/qprogressdialog/.gitignore
new file mode 100644
index 0000000000..ce3cd0d7dd
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qprogressdialog/.gitignore
@@ -0,0 +1 @@
+tst_qprogressdialog
diff --git a/tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro b/tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro
new file mode 100644
index 0000000000..f3861e4cd3
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qprogressdialog.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qprogressdialog.cpp
+
+
diff --git a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
new file mode 100644
index 0000000000..5fbd5d747a
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qprogressdialog.h>
+#include <qlabel.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QProgressDialog : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QProgressDialog();
+ virtual ~tst_QProgressDialog();
+
+private slots:
+ void getSetCheck();
+ void task198202();
+};
+
+tst_QProgressDialog::tst_QProgressDialog()
+{
+}
+
+tst_QProgressDialog::~tst_QProgressDialog()
+{
+}
+
+// Testing get/set functions
+void tst_QProgressDialog::getSetCheck()
+{
+ QProgressDialog obj1;
+ // bool QProgressDialog::autoReset()
+ // void QProgressDialog::setAutoReset(bool)
+ obj1.setAutoReset(false);
+ QCOMPARE(false, obj1.autoReset());
+ obj1.setAutoReset(true);
+ QCOMPARE(true, obj1.autoReset());
+
+ // bool QProgressDialog::autoClose()
+ // void QProgressDialog::setAutoClose(bool)
+ obj1.setAutoClose(false);
+ QCOMPARE(false, obj1.autoClose());
+ obj1.setAutoClose(true);
+ QCOMPARE(true, obj1.autoClose());
+
+ // int QProgressDialog::maximum()
+ // void QProgressDialog::setMaximum(int)
+ obj1.setMaximum(0);
+ QCOMPARE(0, obj1.maximum());
+ obj1.setMaximum(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.maximum());
+ obj1.setMaximum(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.maximum());
+
+ // int QProgressDialog::minimum()
+ // void QProgressDialog::setMinimum(int)
+ obj1.setMinimum(0);
+ QCOMPARE(0, obj1.minimum());
+ obj1.setMinimum(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.minimum());
+ obj1.setMinimum(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.minimum());
+
+ // int QProgressDialog::value()
+ // void QProgressDialog::setValue(int)
+ obj1.setMaximum(INT_MAX);
+ obj1.setMinimum(INT_MIN);
+ obj1.setValue(0);
+ QCOMPARE(0, obj1.value());
+ obj1.setValue(INT_MIN+1);
+ QCOMPARE(INT_MIN+1, obj1.value());
+ obj1.setValue(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.value());
+ obj1.setValue(INT_MAX-1);
+ QCOMPARE(INT_MAX-1, obj1.value());
+
+ obj1.setValue(INT_MAX);
+ QCOMPARE(INT_MIN, obj1.value()); // We set autoReset, the thing is reset
+
+ obj1.setAutoReset(false);
+ obj1.setValue(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.value());
+ obj1.setAutoReset(true);
+
+ // int QProgressDialog::minimumDuration()
+ // void QProgressDialog::setMinimumDuration(int)
+ obj1.setMinimumDuration(0);
+ QCOMPARE(0, obj1.minimumDuration());
+ obj1.setMinimumDuration(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.minimumDuration());
+ obj1.setMinimumDuration(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.minimumDuration());
+}
+
+void tst_QProgressDialog::task198202()
+{
+ //should not crash
+ QProgressDialog dlg(QLatin1String("test"),QLatin1String("test"),1,10);
+ dlg.show();
+ QTest::qWait(20);
+ int futureHeight = dlg.sizeHint().height() - qFindChild<QLabel*>(&dlg)->sizeHint().height();
+ dlg.setLabel(0);
+ QTest::ignoreMessage(QtWarningMsg, "QProgressDialog::setBar: Cannot set a null progress bar");
+ dlg.setBar(0);
+ QTest::qWait(20);
+ QCOMPARE(dlg.sizeHint().height(), futureHeight);
+}
+
+QTEST_MAIN(tst_QProgressDialog)
+#include "tst_qprogressdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qsidebar/.gitignore b/tests/auto/widgets/dialogs/qsidebar/.gitignore
new file mode 100644
index 0000000000..194ca9f244
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qsidebar/.gitignore
@@ -0,0 +1 @@
+tst_qsidebar
diff --git a/tests/auto/widgets/dialogs/qsidebar/qsidebar.pro b/tests/auto/widgets/dialogs/qsidebar/qsidebar.pro
new file mode 100644
index 0000000000..9f6e094784
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qsidebar/qsidebar.pro
@@ -0,0 +1,6 @@
+CONFIG += qttest_p4
+
+QT += core-private
+QT += widgets widgets-private
+SOURCES += tst_qsidebar.cpp
+TARGET = tst_qsidebar
diff --git a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp
new file mode 100644
index 0000000000..912719f76a
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "../../../src/widgets/dialogs/qsidebar_p.h"
+#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QSidebar : public QObject {
+ Q_OBJECT
+
+public:
+ tst_QSidebar();
+ virtual ~tst_QSidebar();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void setUrls();
+ void selectUrls();
+ void addUrls();
+
+ void goToUrl();
+};
+
+tst_QSidebar::tst_QSidebar()
+{
+}
+
+tst_QSidebar::~tst_QSidebar()
+{
+}
+
+void tst_QSidebar::init()
+{
+}
+
+void tst_QSidebar::cleanup()
+{
+}
+
+void tst_QSidebar::setUrls()
+{
+ QList<QUrl> urls;
+ QFileSystemModel fsmodel;
+ QSidebar qsidebar;
+ qsidebar.init(&fsmodel, urls);
+ QAbstractItemModel *model = qsidebar.model();
+
+ urls << QUrl::fromLocalFile(QDir::rootPath())
+ << QUrl::fromLocalFile(QDir::temp().absolutePath());
+
+ QCOMPARE(model->rowCount(), 0);
+ qsidebar.setUrls(urls);
+ QCOMPARE(qsidebar.urls(), urls);
+ QCOMPARE(model->rowCount(), urls.count());
+ qsidebar.setUrls(urls);
+ QCOMPARE(model->rowCount(), urls.count());
+}
+
+void tst_QSidebar::selectUrls()
+{
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(QDir::rootPath())
+ << QUrl::fromLocalFile(QDir::temp().absolutePath());
+ QFileSystemModel fsmodel;
+ QSidebar qsidebar;
+ qsidebar.init(&fsmodel, urls);
+
+ QSignalSpy spy(&qsidebar, SIGNAL(goToUrl(const QUrl &)));
+ qsidebar.selectUrl(urls.at(0));
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QSidebar::addUrls()
+{
+ QList<QUrl> emptyUrls;
+ QFileSystemModel fsmodel;
+ QSidebar qsidebar;
+ qsidebar.init(&fsmodel, emptyUrls);
+ QAbstractItemModel *model = qsidebar.model();
+ QDir testDir = QDir::home();
+
+ // default
+ QCOMPARE(model->rowCount(), 0);
+
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(QDir::rootPath())
+ << QUrl::fromLocalFile(QDir::temp().absolutePath());
+
+ // test < 0
+ qsidebar.addUrls(urls, -1);
+ QCOMPARE(model->rowCount(), 2);
+
+ // test = 0
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(urls, 0);
+ QCOMPARE(model->rowCount(), 2);
+
+ // test > 0
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(urls, 100);
+ QCOMPARE(model->rowCount(), 2);
+
+ // test inserting with already existing rows
+ QList<QUrl> moreUrls;
+ moreUrls << QUrl::fromLocalFile(testDir.absolutePath());
+ qsidebar.addUrls(moreUrls, -1);
+ QCOMPARE(model->rowCount(), 3);
+
+ // make sure invalid urls are still added
+ QList<QUrl> badUrls;
+ badUrls << QUrl::fromLocalFile(testDir.absolutePath() + "/I used to exist");
+ qsidebar.addUrls(badUrls, 0);
+ QCOMPARE(model->rowCount(), 4);
+
+ // check that every item has text and an icon including the above invalid one
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QVERIFY(!model->index(i, 0).data().toString().isEmpty());
+ QIcon icon = qvariant_cast<QIcon>(model->index(i, 0).data(Qt::DecorationRole));
+ QVERIFY(!icon.isNull());
+ }
+
+ // test moving up the list
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(urls, 100);
+ qsidebar.addUrls(moreUrls, 100);
+ QCOMPARE(model->rowCount(), 3);
+ qsidebar.addUrls(moreUrls, 1);
+ QCOMPARE(qsidebar.urls()[1], moreUrls[0]);
+
+ // test appending with -1
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(urls, -1);
+ qsidebar.addUrls(moreUrls, -1);
+ QCOMPARE(qsidebar.urls()[0], urls[0]);
+
+ QList<QUrl> doubleUrls;
+ //tow exact same paths, we have only one entry
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath());
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath());
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(doubleUrls, 1);
+ QCOMPARE(qsidebar.urls().size(), 1);
+
+ // Two paths that are effectively pointing to the same location
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath());
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath() + "/.");
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(doubleUrls, 1);
+ QCOMPARE(qsidebar.urls().size(), 1);
+
+#if defined(Q_OS_WIN)
+ //Windows is case insensitive so no duplicate entries in that case
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath());
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath().toUpper());
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(doubleUrls, 1);
+ QCOMPARE(qsidebar.urls().size(), 1);
+#else
+ //Two different paths we should have two entries
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath());
+ doubleUrls << QUrl::fromLocalFile(testDir.absolutePath().toUpper());
+ qsidebar.setUrls(emptyUrls);
+ qsidebar.addUrls(doubleUrls, 1);
+ QCOMPARE(qsidebar.urls().size(), 2);
+#endif
+}
+
+void tst_QSidebar::goToUrl()
+{
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(QDir::rootPath())
+ << QUrl::fromLocalFile(QDir::temp().absolutePath());
+ QFileSystemModel fsmodel;
+ QSidebar qsidebar;
+ qsidebar.init(&fsmodel, urls);
+ qsidebar.show();
+
+ QSignalSpy spy(&qsidebar, SIGNAL(goToUrl(const QUrl &)));
+ QTest::mousePress(qsidebar.viewport(), Qt::LeftButton, 0, qsidebar.visualRect(qsidebar.model()->index(0, 0)).center());
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((spy.value(0)).at(0).toUrl(), urls.first());
+}
+
+QTEST_MAIN(tst_QSidebar)
+#include "tst_qsidebar.moc"
+
diff --git a/tests/auto/widgets/dialogs/qwizard/.gitignore b/tests/auto/widgets/dialogs/qwizard/.gitignore
new file mode 100644
index 0000000000..9494c96da2
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/.gitignore
@@ -0,0 +1 @@
+tst_qwizard
diff --git a/tests/auto/widgets/dialogs/qwizard/images/background.png b/tests/auto/widgets/dialogs/qwizard/images/background.png
new file mode 100644
index 0000000000..db7d67dc3d
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/images/background.png
Binary files differ
diff --git a/tests/auto/widgets/dialogs/qwizard/images/banner.png b/tests/auto/widgets/dialogs/qwizard/images/banner.png
new file mode 100644
index 0000000000..be36202d99
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/images/banner.png
Binary files differ
diff --git a/tests/auto/widgets/dialogs/qwizard/images/logo.png b/tests/auto/widgets/dialogs/qwizard/images/logo.png
new file mode 100644
index 0000000000..9cf3350c4b
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/images/logo.png
Binary files differ
diff --git a/tests/auto/widgets/dialogs/qwizard/images/watermark.png b/tests/auto/widgets/dialogs/qwizard/images/watermark.png
new file mode 100644
index 0000000000..9305675549
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/images/watermark.png
Binary files differ
diff --git a/tests/auto/widgets/dialogs/qwizard/qwizard.pro b/tests/auto/widgets/dialogs/qwizard/qwizard.pro
new file mode 100644
index 0000000000..c27801b82f
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/qwizard.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qwizard.cpp
+RESOURCES = qwizard.qrc
diff --git a/tests/auto/widgets/dialogs/qwizard/qwizard.qrc b/tests/auto/widgets/dialogs/qwizard/qwizard.qrc
new file mode 100644
index 0000000000..471da9def6
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/qwizard.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/background.png</file>
+ <file>images/banner.png</file>
+ <file>images/logo.png</file>
+ <file>images/watermark.png</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
new file mode 100644
index 0000000000..2e05eb5bab
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
@@ -0,0 +1,2645 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QFont>
+#include <QtTest/QtTest>
+#include <QCheckBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QList>
+#include <QPushButton>
+#include <QToolButton>
+#include <QVBoxLayout>
+#include <QWizard>
+#include <QStyle>
+#include <QPlastiqueStyle>
+#include <QTreeWidget>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+static QImage grabWidget(QWidget *window)
+{
+ return QPixmap::grabWidget(window).toImage();
+}
+
+class tst_QWizard : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWizard();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void buttonText();
+ void setButtonLayout();
+ void setButton();
+ void setTitleFormatEtc();
+ void setPixmap();
+ void setDefaultProperty();
+ void addPage();
+ void setPage();
+ void setStartId();
+ void setOption_IndependentPages();
+ void setOption_IgnoreSubTitles();
+ void setOption_ExtendedWatermarkPixmap();
+ void setOption_NoDefaultButton();
+ void setOption_NoBackButtonOnStartPage();
+ void setOption_NoBackButtonOnLastPage();
+ void setOption_DisabledBackButtonOnLastPage();
+ void setOption_HaveNextButtonOnLastPage();
+ void setOption_HaveFinishButtonOnEarlyPages();
+ void setOption_NoCancelButton();
+ void setOption_CancelButtonOnLeft();
+ void setOption_HaveHelpButton();
+ void setOption_HelpButtonOnRight();
+ void setOption_HaveCustomButtonX();
+#ifndef Q_OS_WINCE
+ void combinations_data();
+ void combinations();
+#endif
+ void showCurrentPageOnly();
+ void setButtonText();
+ void setCommitPage();
+ void setWizardStyle();
+ void removePage();
+ void sideWidget();
+
+ // task-specific tests below me:
+ void task161660_buttonSpacing();
+ void task177716_disableCommitButton();
+ void task183550_stretchFactor();
+ void task161658_alignments();
+ void task177022_setFixedSize();
+ void task248107_backButton();
+ void task255350_fieldObjectDestroyed();
+
+ /*
+ Things that could be added:
+
+ 1. Test virtual functions that are called, signals that are
+ emitted, etc.
+
+ 2. Test QWizardPage more thorougly.
+
+ 3. Test the look and field a bit more (especially the
+ different wizard styles, and how they interact with
+ pixmaps, titles, subtitles, etc.).
+
+ 4. Test minimum sizes, sizes, maximum sizes, resizing, etc.
+
+ 5. Try setting various options and wizard styles in various
+ orders and check that the results are the same every time,
+ no matter the order in which the properties were set.
+
+ -> Initial version done (tst_QWizard::combinations())
+
+ 6. Test done() and restart().
+
+ 7. Test default properties of built-in widgets.
+
+ 8. Test mutual exclusiveness of Next and Commit buttons.
+ */
+};
+
+tst_QWizard::tst_QWizard()
+{
+}
+
+void tst_QWizard::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QWizard::cleanup()
+{
+}
+
+void tst_QWizard::buttonText()
+{
+ QWizard wizard;
+ wizard.setWizardStyle(QWizard::ClassicStyle);
+
+ // Check the buttons' original text in Classic and Modern styles.
+ for (int pass = 0; pass < 2; ++pass) {
+ QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("< &Back"));
+ QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
+ QVERIFY(wizard.buttonText(QWizard::FinishButton).endsWith("Finish"));
+ QVERIFY(wizard.buttonText(QWizard::CancelButton).endsWith("Cancel"));
+ QVERIFY(wizard.buttonText(QWizard::HelpButton).endsWith("Help"));
+
+ QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::CustomButton2).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
+
+ // robustness
+ QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
+
+ wizard.setWizardStyle(QWizard::ModernStyle);
+ }
+
+ // Check the buttons' original text in Mac style.
+ wizard.setWizardStyle(QWizard::MacStyle);
+
+ QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("Go Back"));
+ QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("Continue"));
+ QCOMPARE(wizard.buttonText(QWizard::FinishButton), QString("Done"));
+ QCOMPARE(wizard.buttonText(QWizard::CancelButton), QString("Cancel"));
+ QCOMPARE(wizard.buttonText(QWizard::HelpButton), QString("Help"));
+
+ QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::CustomButton2).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
+
+ // robustness
+ QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
+
+ // Modify the buttons' text and see what happens.
+ wizard.setButtonText(QWizard::NextButton, "N&este");
+ wizard.setButtonText(QWizard::CustomButton2, "&Cucu");
+ wizard.setButtonText(QWizard::Stretch, "Stretch");
+
+ QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("Go Back"));
+ QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("N&este"));
+ QCOMPARE(wizard.buttonText(QWizard::FinishButton), QString("Done"));
+ QCOMPARE(wizard.buttonText(QWizard::CancelButton), QString("Cancel"));
+ QCOMPARE(wizard.buttonText(QWizard::HelpButton), QString("Help"));
+
+ QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
+ QCOMPARE(wizard.buttonText(QWizard::CustomButton2), QString("&Cucu"));
+ QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
+
+ // robustness
+ QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
+
+ // Switch back to Classic style and see what happens.
+ wizard.setWizardStyle(QWizard::ClassicStyle);
+
+ for (int pass = 0; pass < 2; ++pass) {
+ QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("< &Back"));
+ QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("N&este"));
+ QVERIFY(wizard.buttonText(QWizard::FinishButton).endsWith("Finish"));
+ QVERIFY(wizard.buttonText(QWizard::CancelButton).endsWith("Cancel"));
+ QVERIFY(wizard.buttonText(QWizard::HelpButton).endsWith("Help"));
+
+ QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
+ QCOMPARE(wizard.buttonText(QWizard::CustomButton2), QString("&Cucu"));
+ QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
+
+ // robustness
+ QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
+ QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
+
+ wizard.setOptions(QWizard::NoDefaultButton
+ | QWizard::NoBackButtonOnStartPage
+ | QWizard::NoBackButtonOnLastPage
+ | QWizard::DisabledBackButtonOnLastPage
+ | QWizard::NoCancelButton
+ | QWizard::CancelButtonOnLeft
+ | QWizard::HaveHelpButton
+ | QWizard::HelpButtonOnRight
+ | QWizard::HaveCustomButton1
+ | QWizard::HaveCustomButton2
+ | QWizard::HaveCustomButton3);
+ }
+}
+
+void tst_QWizard::setButtonLayout()
+{
+ QList<QWizard::WizardButton> layout;
+
+ QWizard wizard;
+ wizard.setWizardStyle(QWizard::ClassicStyle);
+ wizard.setOptions(0);
+ wizard.setButtonLayout(layout);
+ wizard.show();
+ qApp->processEvents();
+
+ // if these crash, this means there's a bug in QWizard
+ QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
+ QVERIFY(wizard.button(QWizard::BackButton)->text().contains("Back"));
+ QVERIFY(wizard.button(QWizard::FinishButton)->text().contains("Finish"));
+ QVERIFY(wizard.button(QWizard::CancelButton)->text().contains("Cancel"));
+ QVERIFY(wizard.button(QWizard::HelpButton)->text().contains("Help"));
+ QVERIFY(wizard.button(QWizard::CustomButton1)->text().isEmpty());
+ QVERIFY(wizard.button(QWizard::CustomButton2)->text().isEmpty());
+ QVERIFY(wizard.button(QWizard::CustomButton3)->text().isEmpty());
+ QVERIFY(!wizard.button(QWizard::Stretch));
+ QVERIFY(!wizard.button(QWizard::NoButton));
+
+ QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
+
+ layout << QWizard::NextButton << QWizard::HelpButton;
+ wizard.setButtonLayout(layout);
+ qApp->processEvents();
+
+ QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ qApp->processEvents();
+
+ QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+
+ wizard.restart();
+ qApp->processEvents();
+
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+
+ layout.clear();
+ layout << QWizard::NextButton << QWizard::HelpButton << QWizard::BackButton
+ << QWizard::FinishButton << QWizard::CancelButton << QWizard::Stretch
+ << QWizard::CustomButton2;
+
+ // Turn on all the button-related wizard options. Some of these
+ // should have no impact on a custom layout; others should.
+ wizard.setButtonLayout(layout);
+ wizard.setOptions(QWizard::NoDefaultButton
+ | QWizard::NoBackButtonOnStartPage
+ | QWizard::NoBackButtonOnLastPage
+ | QWizard::DisabledBackButtonOnLastPage
+ | QWizard::HaveNextButtonOnLastPage
+ | QWizard::HaveFinishButtonOnEarlyPages
+ | QWizard::NoCancelButton
+ | QWizard::CancelButtonOnLeft
+ | QWizard::HaveHelpButton
+ | QWizard::HelpButtonOnRight
+ | QWizard::HaveCustomButton1
+ | QWizard::HaveCustomButton2
+ | QWizard::HaveCustomButton3);
+ qApp->processEvents();
+
+ // we're on first page
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::CancelButton)->isVisible()); // NoCancelButton overridden
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::CustomButton1)->isVisible());
+ QVERIFY(wizard.button(QWizard::CustomButton2)->isVisible()); // HaveCustomButton2 overridden
+ QVERIFY(!wizard.button(QWizard::CustomButton3)->isVisible());
+
+ wizard.next();
+ qApp->processEvents();
+
+ // we're on last page
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::FinishButton)->isEnabled());
+ QVERIFY(wizard.button(QWizard::CancelButton)->isVisible()); // NoCancelButton overridden
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::CustomButton1)->isVisible());
+ QVERIFY(wizard.button(QWizard::CustomButton2)->isVisible()); // HaveCustomButton2 overridden
+ QVERIFY(!wizard.button(QWizard::CustomButton3)->isVisible());
+
+ // Check that the buttons are in the right order on screen.
+ for (int pass = 0; pass < 2; ++pass) {
+ wizard.setLayoutDirection(pass == 0 ? Qt::LeftToRight : Qt::RightToLeft);
+ qApp->processEvents();
+
+ int sign = (pass == 0) ? +1 : -1;
+
+ int p[5];
+ p[0] = sign * wizard.button(QWizard::NextButton)->x();
+ p[1] = sign * wizard.button(QWizard::HelpButton)->x();
+ p[2] = sign * wizard.button(QWizard::FinishButton)->x();
+ p[3] = sign * wizard.button(QWizard::CancelButton)->x();
+ p[4] = sign * wizard.button(QWizard::CustomButton2)->x();
+
+ QVERIFY(p[0] < p[1]);
+ QVERIFY(p[1] < p[2]);
+ QVERIFY(p[2] < p[3]);
+ QVERIFY(p[3] < p[4]);
+ }
+
+ layout.clear();
+ wizard.setButtonLayout(layout);
+ qApp->processEvents();
+
+ for (int i = -1; i < 50; ++i) {
+ QAbstractButton *button = wizard.button(QWizard::WizardButton(i));
+ QVERIFY(!button || !button->isVisible());
+ }
+}
+
+void tst_QWizard::setButton()
+{
+ QPointer<QToolButton> toolButton = new QToolButton;
+
+ QWizard wizard;
+ wizard.setWizardStyle(QWizard::ClassicStyle);
+ wizard.setButton(QWizard::NextButton, toolButton);
+ wizard.setButton(QWizard::CustomButton2, new QCheckBox("Kustom 2"));
+
+ QVERIFY(qobject_cast<QToolButton *>(wizard.button(QWizard::NextButton)));
+ QVERIFY(qobject_cast<QCheckBox *>(wizard.button(QWizard::CustomButton2)));
+ QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::CustomButton1)));
+
+ QVERIFY(toolButton != 0);
+
+ // resetting the same button does nothing
+ wizard.setButton(QWizard::NextButton, toolButton);
+ QVERIFY(toolButton != 0);
+
+ // revert to default button
+ wizard.setButton(QWizard::NextButton, 0);
+ QVERIFY(toolButton == 0);
+ QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton)));
+ QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
+}
+
+void tst_QWizard::setTitleFormatEtc()
+{
+ QWizard wizard;
+ QVERIFY(wizard.titleFormat() == Qt::AutoText);
+ QVERIFY(wizard.subTitleFormat() == Qt::AutoText);
+
+ wizard.setTitleFormat(Qt::RichText);
+ QVERIFY(wizard.titleFormat() == Qt::RichText);
+ QVERIFY(wizard.subTitleFormat() == Qt::AutoText);
+
+ wizard.setSubTitleFormat(Qt::PlainText);
+ QVERIFY(wizard.titleFormat() == Qt::RichText);
+ QVERIFY(wizard.subTitleFormat() == Qt::PlainText);
+}
+
+void tst_QWizard::setPixmap()
+{
+ QPixmap p1(1, 1);
+ QPixmap p2(2, 2);
+ QPixmap p3(3, 3);
+ QPixmap p4(4, 4);
+ QPixmap p5(5, 5);
+
+ QWizard wizard;
+ QWizardPage *page = new QWizardPage;
+ QWizardPage *page2 = new QWizardPage;
+
+ wizard.addPage(page);
+ wizard.addPage(page2);
+
+ QVERIFY(wizard.pixmap(QWizard::BannerPixmap).isNull());
+ QVERIFY(wizard.pixmap(QWizard::LogoPixmap).isNull());
+ QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).isNull());
+#ifdef Q_WS_MAC
+ if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_3)
+ QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull() == false);
+ else // fall through since the image doesn't exist on a 10.3 system.
+ QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
+#else
+ QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull());
+#endif
+
+ QVERIFY(page->pixmap(QWizard::BannerPixmap).isNull());
+ QVERIFY(page->pixmap(QWizard::LogoPixmap).isNull());
+ QVERIFY(page->pixmap(QWizard::WatermarkPixmap).isNull());
+#ifdef Q_WS_MAC
+ if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_3)
+ QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull() == false);
+ else // fall through since the image doesn't exist on a 10.3 system.
+ QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
+#else
+ QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
+#endif
+ wizard.setPixmap(QWizard::BannerPixmap, p1);
+ wizard.setPixmap(QWizard::LogoPixmap, p2);
+ wizard.setPixmap(QWizard::WatermarkPixmap, p3);
+ wizard.setPixmap(QWizard::BackgroundPixmap, p4);
+
+ page->setPixmap(QWizard::LogoPixmap, p5);
+
+ QVERIFY(wizard.pixmap(QWizard::BannerPixmap).size() == p1.size());
+ QVERIFY(wizard.pixmap(QWizard::LogoPixmap).size() == p2.size());
+ QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).size() == p3.size());
+ QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).size() == p4.size());
+
+ QVERIFY(page->pixmap(QWizard::BannerPixmap).size() == p1.size());
+ QVERIFY(page->pixmap(QWizard::LogoPixmap).size() == p5.size());
+ QVERIFY(page->pixmap(QWizard::WatermarkPixmap).size() == p3.size());
+ QVERIFY(page->pixmap(QWizard::BackgroundPixmap).size() == p4.size());
+
+ QVERIFY(page2->pixmap(QWizard::BannerPixmap).size() == p1.size());
+ QVERIFY(page2->pixmap(QWizard::LogoPixmap).size() == p2.size());
+ QVERIFY(page2->pixmap(QWizard::WatermarkPixmap).size() == p3.size());
+ QVERIFY(page2->pixmap(QWizard::BackgroundPixmap).size() == p4.size());
+}
+
+class MyPage1 : public QWizardPage
+{
+public:
+ MyPage1() {
+ edit1 = new QLineEdit("Bla 1", this);
+
+ edit2 = new QLineEdit("Bla 2", this);
+ edit2->setInputMask("Mask");
+
+ edit3 = new QLineEdit("Bla 3", this);
+ edit3->setMaxLength(25);
+
+ edit4 = new QLineEdit("Bla 4", this);
+ }
+
+ void registerField(const QString &name, QWidget *widget,
+ const char *property = 0,
+ const char *changedSignal = 0)
+ { QWizardPage::registerField(name, widget, property, changedSignal); }
+
+ QLineEdit *edit1;
+ QLineEdit *edit2;
+ QLineEdit *edit3;
+ QLineEdit *edit4;
+};
+
+void tst_QWizard::setDefaultProperty()
+{
+ QWizard wizard;
+ MyPage1 *page = new MyPage1;
+ wizard.addPage(page);
+
+ page->registerField("edit1", page->edit1);
+
+ wizard.setDefaultProperty("QLineEdit", "inputMask", 0);
+ page->registerField("edit2", page->edit2);
+
+ wizard.setDefaultProperty("QLineEdit", "maxLength", 0);
+ page->registerField("edit3", page->edit3);
+
+ wizard.setDefaultProperty("QLineEdit", "text", SIGNAL(textChanged(QString)));
+ page->registerField("edit3bis", page->edit3);
+
+ wizard.setDefaultProperty("QWidget", "enabled", 0); // less specific, i.e. ignored
+ page->registerField("edit4", page->edit4);
+ QTest::ignoreMessage(QtWarningMsg,"QWizard::setField: Couldn't write to property 'customProperty'");
+ wizard.setDefaultProperty("QLineEdit", "customProperty", 0);
+ page->registerField("edit4bis", page->edit4);
+
+ QCOMPARE(wizard.field("edit1").toString(), QString("Bla 1"));
+ QCOMPARE(wizard.field("edit2").toString(), page->edit2->inputMask());
+ QCOMPARE(wizard.field("edit3").toInt(), 25);
+ QCOMPARE(wizard.field("edit3bis").toString(), QString("Bla 3"));
+ QCOMPARE(wizard.field("edit4").toString(), QString("Bla 4"));
+ QCOMPARE(wizard.field("edit4bis").toString(), QString());
+
+ wizard.setField("edit1", "Alpha");
+ wizard.setField("edit2", "Beta");
+ wizard.setField("edit3", 50);
+ wizard.setField("edit3bis", "Gamma");
+ wizard.setField("edit4", "Delta");
+ wizard.setField("edit4bis", "Epsilon");
+
+ QCOMPARE(wizard.field("edit1").toString(), QString("Alpha"));
+ QVERIFY(wizard.field("edit2").toString().contains("Beta"));
+ QCOMPARE(wizard.field("edit3").toInt(), 50);
+ QCOMPARE(wizard.field("edit3bis").toString(), QString("Gamma"));
+ QCOMPARE(wizard.field("edit4").toString(), QString("Delta"));
+ QCOMPARE(wizard.field("edit4bis").toString(), QString("Epsilon"));
+
+ // make sure the data structure is reasonable
+ for (int i = 0; i < 200000; ++i) {
+ wizard.setDefaultProperty("QLineEdit", "x" + QByteArray::number(i), 0);
+ wizard.setDefaultProperty("QLabel", "y" + QByteArray::number(i), 0);
+ }
+}
+
+void tst_QWizard::addPage()
+{
+ QWidget *parent = new QWidget;
+ QWizard wizard;
+ const int N = 100;
+ QWizardPage *pages[N];
+ QSignalSpy spy(&wizard, SIGNAL(pageAdded(int)));
+
+ for (int i = 0; i < N; ++i) {
+ pages[i] = new QWizardPage(parent);
+ QCOMPARE(wizard.addPage(pages[i]), i);
+ QCOMPARE(pages[i]->window(), (QWidget *)&wizard);
+ QCOMPARE(wizard.startId(), 0);
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), i);
+ }
+
+ for (int i = 0; i < N; ++i) {
+ QVERIFY(pages[i] == wizard.page(i));
+ }
+ QVERIFY(!wizard.page(-1));
+ QVERIFY(!wizard.page(N));
+ QVERIFY(!wizard.page(N + 1));
+
+ wizard.setPage(N + 50, new QWizardPage);
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), N + 50);
+ wizard.setPage(-3000, new QWizardPage);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), -3000);
+
+ QWizardPage *pageX = new QWizardPage;
+ QCOMPARE(wizard.addPage(pageX), N + 51);
+ QCOMPARE(wizard.page(N + 51), pageX);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), N + 51);
+
+ QCOMPARE(wizard.addPage(new QWizardPage), N + 52);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), N + 52);
+
+ QTest::ignoreMessage(QtWarningMsg,"QWizard::setPage: Cannot insert null page");
+ wizard.addPage(0); // generates a warning
+ QCOMPARE(spy.count(), 0);
+ delete parent;
+}
+
+#define CHECK_VISITED(wizard, list) \
+ do { \
+ QList<int> myList = list; \
+ QCOMPARE((wizard).visitedPages(), myList); \
+ Q_FOREACH(int id, myList) \
+ QVERIFY((wizard).hasVisitedPage(id)); \
+ } while (0)
+
+void tst_QWizard::setPage()
+{
+ QWidget *parent = new QWidget;
+ QWizard wizard;
+ QWizardPage *page;
+ QSignalSpy spy(&wizard, SIGNAL(pageAdded(int)));
+
+ QCOMPARE(wizard.startId(), -1);
+ QCOMPARE(wizard.currentId(), -1);
+ QVERIFY(!wizard.currentPage());
+ QCOMPARE(wizard.nextId(), -1);
+
+ page = new QWizardPage(parent);
+ QTest::ignoreMessage(QtWarningMsg,"QWizard::setPage: Cannot insert page with ID -1");
+ wizard.setPage(-1, page); // gives a warning and does nothing
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(!wizard.page(-2));
+ QVERIFY(!wizard.page(-1));
+ QVERIFY(!wizard.page(0));
+ QCOMPARE(wizard.startId(), -1);
+ QCOMPARE(wizard.currentId(), -1);
+ QVERIFY(!wizard.currentPage());
+ QCOMPARE(wizard.nextId(), -1);
+ CHECK_VISITED(wizard, QList<int>());
+
+ page = new QWizardPage(parent);
+ wizard.setPage(0, page);
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 0);
+ QCOMPARE(page->window(), (QWidget *)&wizard);
+ QCOMPARE(wizard.page(0), page);
+ QCOMPARE(wizard.startId(), 0);
+ QCOMPARE(wizard.currentId(), -1);
+ QVERIFY(!wizard.currentPage());
+ QCOMPARE(wizard.nextId(), -1);
+ CHECK_VISITED(wizard, QList<int>());
+
+ page = new QWizardPage(parent);
+ wizard.setPage(-2, page);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), -2);
+ QCOMPARE(page->window(), (QWidget *)&wizard);
+ QCOMPARE(wizard.page(-2), page);
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.currentId(), -1);
+ QVERIFY(!wizard.currentPage());
+ QCOMPARE(wizard.nextId(), -1);
+ CHECK_VISITED(wizard, QList<int>());
+
+ wizard.restart();
+ QCOMPARE(wizard.page(-2), page);
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == page);
+ QCOMPARE(wizard.nextId(), 0);
+ CHECK_VISITED(wizard, QList<int>() << -2);
+
+ page = new QWizardPage(parent);
+ wizard.setPage(2, page);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 2);
+ QCOMPARE(wizard.page(2), page);
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == wizard.page(-2));
+ QCOMPARE(wizard.nextId(), 0);
+ CHECK_VISITED(wizard, QList<int>() << -2);
+
+ wizard.restart();
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == wizard.page(-2));
+ QCOMPARE(wizard.nextId(), 0);
+ CHECK_VISITED(wizard, QList<int>() << -2);
+
+ page = new QWizardPage(parent);
+ wizard.setPage(-3, page);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), -3);
+ QCOMPARE(wizard.page(-3), page);
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == wizard.page(-2));
+ QCOMPARE(wizard.nextId(), 0);
+ CHECK_VISITED(wizard, QList<int>() << -2);
+
+ wizard.restart();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), -3);
+ QVERIFY(wizard.currentPage() == wizard.page(-3));
+ QCOMPARE(wizard.nextId(), -2);
+ CHECK_VISITED(wizard, QList<int>() << -3);
+
+ wizard.next();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == wizard.page(-2));
+ QCOMPARE(wizard.nextId(), 0);
+ CHECK_VISITED(wizard, QList<int>() << -3 << -2);
+
+ wizard.next();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), 0);
+ QVERIFY(wizard.currentPage() == wizard.page(0));
+ QCOMPARE(wizard.nextId(), 2);
+ CHECK_VISITED(wizard, QList<int>() << -3 << -2 << 0);
+
+ for (int i = 0; i < 100; ++i) {
+ wizard.next();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), 2);
+ QVERIFY(wizard.currentPage() == wizard.page(2));
+ QCOMPARE(wizard.nextId(), -1);
+ CHECK_VISITED(wizard, QList<int>() << -3 << -2 << 0 << 2);
+ }
+
+ wizard.back();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), 0);
+ QVERIFY(wizard.currentPage() == wizard.page(0));
+ QCOMPARE(wizard.nextId(), 2);
+ CHECK_VISITED(wizard, QList<int>() << -3 << -2 << 0);
+
+ wizard.back();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == wizard.page(-2));
+ QCOMPARE(wizard.nextId(), 0);
+ CHECK_VISITED(wizard, QList<int>() << -3 << -2);
+
+ for (int i = 0; i < 100; ++i) {
+ wizard.back();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), -3);
+ QVERIFY(wizard.currentPage() == wizard.page(-3));
+ QCOMPARE(wizard.nextId(), -2);
+ CHECK_VISITED(wizard, QList<int>() << -3);
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ wizard.restart();
+ QCOMPARE(wizard.startId(), -3);
+ QCOMPARE(wizard.currentId(), -3);
+ QVERIFY(wizard.currentPage() == wizard.page(-3));
+ QCOMPARE(wizard.nextId(), -2);
+ CHECK_VISITED(wizard, QList<int>() << -3);
+ }
+ QCOMPARE(spy.count(), 0);
+ delete parent;
+}
+
+void tst_QWizard::setStartId()
+{
+ QWizard wizard;
+ QCOMPARE(wizard.startId(), -1);
+
+ wizard.setPage(INT_MIN, new QWizardPage);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setPage(-2, new QWizardPage);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setPage(0, new QWizardPage);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setPage(1, new QWizardPage);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setPage(INT_MAX, new QWizardPage);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ QTest::ignoreMessage(QtWarningMsg,"QWizard::setStartId: Invalid page ID 123");
+ wizard.setStartId(123);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setStartId(-1);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setStartId(-2);
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.nextId(), -1);
+
+ wizard.setStartId(-1);
+ QCOMPARE(wizard.startId(), INT_MIN);
+
+ wizard.setStartId(-2);
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.nextId(), -1);
+
+ wizard.restart();
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.currentId(), -2);
+ QVERIFY(wizard.currentPage() == wizard.page(-2));
+ QCOMPARE(wizard.nextId(), 0);
+
+ wizard.next();
+ QCOMPARE(wizard.startId(), -2);
+ QCOMPARE(wizard.currentId(), 0);
+ QVERIFY(wizard.currentPage() == wizard.page(0));
+ QCOMPARE(wizard.nextId(), 1);
+
+ wizard.setStartId(INT_MIN);
+ QCOMPARE(wizard.startId(), INT_MIN);
+ QCOMPARE(wizard.currentId(), 0);
+ QVERIFY(wizard.currentPage() == wizard.page(0));
+ QCOMPARE(wizard.nextId(), 1);
+
+ wizard.next();
+ QCOMPARE(wizard.startId(), INT_MIN);
+ QCOMPARE(wizard.currentId(), 1);
+ QVERIFY(wizard.currentPage() == wizard.page(1));
+ QCOMPARE(wizard.nextId(), INT_MAX);
+
+ wizard.next();
+ QCOMPARE(wizard.startId(), INT_MIN);
+ QCOMPARE(wizard.currentId(), INT_MAX);
+ QVERIFY(wizard.currentPage() == wizard.page(INT_MAX));
+ QCOMPARE(wizard.nextId(), -1);
+ CHECK_VISITED(wizard, QList<int>() << -2 << 0 << 1 << INT_MAX);
+}
+
+struct MyPage2 : public QWizardPage
+{
+public:
+ MyPage2() : init(0), cleanup(0), validate(0) {}
+
+ void initializePage() { ++init; QWizardPage::initializePage(); }
+ void cleanupPage() { ++cleanup; QWizardPage::cleanupPage(); }
+ bool validatePage() { ++validate; return QWizardPage::validatePage(); }
+
+ bool check(int init, int cleanup)
+ {
+ return init == this->init
+ && cleanup == this->cleanup
+ && (this->init == this->cleanup || this->init - 1 == this->cleanup);
+ }
+
+ int init;
+ int cleanup;
+ int validate;
+};
+
+#define CHECK_PAGE_INIT(i0, c0, i1, c1, i2, c2) \
+ QVERIFY(page0->check((i0), (c0))); \
+ QVERIFY(page1->check((i1), (c1))); \
+ QVERIFY(page2->check((i2), (c2)));
+
+void tst_QWizard::setOption_IndependentPages()
+{
+ MyPage2 *page0 = new MyPage2;
+ MyPage2 *page1 = new MyPage2;
+ MyPage2 *page2 = new MyPage2;
+
+ QWizard wizard;
+ wizard.addPage(page0);
+ wizard.addPage(page1);
+ wizard.addPage(page2);
+
+ QVERIFY(!wizard.testOption(QWizard::IndependentPages));
+
+ wizard.restart();
+
+ // Make sure initializePage() and cleanupPage() are called are
+ // they should when the
+ // wizard.testOption(QWizard::IndependentPages option is off.
+ for (int i = 0; i < 10; ++i) {
+ CHECK_PAGE_INIT(i + 1, i, i, i, i, i);
+
+ wizard.next();
+ CHECK_PAGE_INIT(i + 1, i, i + 1, i, i, i);
+
+ wizard.next();
+ CHECK_PAGE_INIT(i + 1, i, i + 1, i, i + 1, i);
+
+ wizard.next();
+ CHECK_PAGE_INIT(i + 1, i, i + 1, i, i + 1, i);
+
+ wizard.back();
+ CHECK_PAGE_INIT(i + 1, i, i + 1, i, i + 1, i + 1);
+
+ wizard.back();
+ CHECK_PAGE_INIT(i + 1, i, i + 1, i + 1, i + 1, i + 1);
+
+ wizard.back();
+ CHECK_PAGE_INIT(i + 1, i, i + 1, i + 1, i + 1, i + 1);
+
+ wizard.restart();
+ }
+
+ CHECK_PAGE_INIT(11, 10, 10, 10, 10, 10);
+
+ wizard.next();
+ CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
+
+ // Now, turn on the option and check that they're called at the
+ // appropriate times (which aren't the same).
+ wizard.setOption(QWizard::IndependentPages, true);
+ CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
+
+ wizard.back();
+ CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
+
+ wizard.next();
+ CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
+
+ wizard.next();
+ CHECK_PAGE_INIT(11, 10, 11, 10, 11, 10);
+
+ wizard.next();
+ CHECK_PAGE_INIT(11, 10, 11, 10, 11, 10);
+
+ wizard.back();
+ CHECK_PAGE_INIT(11, 10, 11, 10, 11, 10);
+
+ wizard.setStartId(2);
+
+ wizard.restart();
+ CHECK_PAGE_INIT(11, 11, 11, 11, 12, 11);
+
+ wizard.back();
+ CHECK_PAGE_INIT(11, 11, 11, 11, 12, 11);
+
+ wizard.next();
+ CHECK_PAGE_INIT(11, 11, 11, 11, 12, 11);
+
+ wizard.setStartId(0);
+ wizard.restart();
+ CHECK_PAGE_INIT(12, 11, 11, 11, 12, 12);
+
+ wizard.next();
+ CHECK_PAGE_INIT(12, 11, 12, 11, 12, 12);
+
+ wizard.next();
+ CHECK_PAGE_INIT(12, 11, 12, 11, 13, 12);
+
+ wizard.back();
+ CHECK_PAGE_INIT(12, 11, 12, 11, 13, 12);
+
+ // Fun stuff here.
+
+ wizard.setOption(QWizard::IndependentPages, false);
+ CHECK_PAGE_INIT(12, 11, 12, 11, 13, 13);
+
+ wizard.setOption(QWizard::IndependentPages, true);
+ CHECK_PAGE_INIT(12, 11, 12, 11, 13, 13);
+
+ wizard.setOption(QWizard::IndependentPages, false);
+ CHECK_PAGE_INIT(12, 11, 12, 11, 13, 13);
+
+ wizard.back();
+ CHECK_PAGE_INIT(12, 11, 12, 12, 13, 13);
+
+ wizard.back();
+ CHECK_PAGE_INIT(12, 11, 12, 12, 13, 13);
+}
+
+void tst_QWizard::setOption_IgnoreSubTitles()
+{
+#if defined(Q_OS_WINCE)
+ QSKIP("Skipped because of limited resources and potential crash. (Task: 166824)", SkipAll);
+#endif
+ QWizard wizard1;
+ wizard1.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
+ wizard1.resize(500, 500);
+ QVERIFY(!wizard1.testOption(QWizard::IgnoreSubTitles));
+ QWizardPage *page11 = new QWizardPage;
+ page11->setTitle("Page X");
+ page11->setSubTitle("Some subtitle");
+
+ QWizardPage *page12 = new QWizardPage;
+ page12->setTitle("Page X");
+
+ wizard1.addPage(page11);
+ wizard1.addPage(page12);
+
+ QWizard wizard2;
+ wizard2.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
+ wizard2.resize(500, 500);
+ wizard2.setOption(QWizard::IgnoreSubTitles, true);
+ QWizardPage *page21 = new QWizardPage;
+ page21->setTitle("Page X");
+ page21->setSubTitle("Some subtitle");
+
+ QWizardPage *page22 = new QWizardPage;
+ page22->setTitle("Page X");
+
+ wizard2.addPage(page21);
+ wizard2.addPage(page22);
+
+ wizard1.show();
+ wizard2.show();
+
+ // Check that subtitles are shown when they should (i.e.,
+ // they're set and IgnoreSubTitles is off).
+
+ qApp->setActiveWindow(0); // ensure no focus rectangle around cancel button
+ QImage i11 = grabWidget(&wizard1);
+ QImage i21 = grabWidget(&wizard2);
+ QVERIFY(i11 != i21);
+
+ wizard1.next();
+ wizard2.next();
+
+ QImage i12 = grabWidget(&wizard1);
+ QImage i22 = grabWidget(&wizard2);
+ QVERIFY(i12 == i22);
+ QVERIFY(i21 == i22);
+
+ wizard1.back();
+ wizard2.back();
+
+ QImage i13 = grabWidget(&wizard1);
+ QImage i23 = grabWidget(&wizard2);
+ QVERIFY(i13 == i11);
+ QVERIFY(i23 == i21);
+
+ wizard1.setOption(QWizard::IgnoreSubTitles, true);
+ wizard2.setOption(QWizard::IgnoreSubTitles, false);
+
+ QImage i14 = grabWidget(&wizard1);
+ QImage i24 = grabWidget(&wizard2);
+ QVERIFY(i14 == i21);
+ QVERIFY(i24 == i11);
+
+ // Check the impact of subtitles on the rest of the layout, by
+ // using a subtitle that looks empty (but that isn't). In
+ // Classic and Modern styles, this should be enough to trigger a
+ // "header"; in Mac style, this only creates a QLabel, with no
+ // text, i.e. it doesn't affect the layout.
+
+ page11->setSubTitle("<b></b>"); // not quite empty, but looks empty
+
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ wizard1.setOption(QWizard::IgnoreSubTitles, j == 0);
+
+ wizard1.setWizardStyle(i == 0 ? QWizard::ClassicStyle
+ : i == 1 ? QWizard::ModernStyle
+ : QWizard::MacStyle);
+ wizard1.restart();
+ QImage i1 = grabWidget(&wizard1);
+
+ wizard1.next();
+ QImage i2 = grabWidget(&wizard1);
+
+ if (j == 0 || wizard1.wizardStyle() == QWizard::MacStyle) {
+ QVERIFY(i1 == i2);
+ } else {
+ QVERIFY(i1 != i2);
+ }
+ }
+ }
+}
+
+void tst_QWizard::setOption_ExtendedWatermarkPixmap()
+{
+#if defined(Q_OS_WINCE)
+ QSKIP("Skipped because of limited resources and potential crash. (Task: 166824)", SkipAll);
+#endif
+ QPixmap watermarkPixmap(200, 400);
+ watermarkPixmap.fill(Qt::black);
+
+ QWizard wizard1;
+ wizard1.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
+ QVERIFY(!wizard1.testOption(QWizard::ExtendedWatermarkPixmap));
+ QWizardPage *page11 = new QWizardPage;
+ page11->setTitle("Page X");
+ page11->setPixmap(QWizard::WatermarkPixmap, watermarkPixmap);
+
+ QWizardPage *page12 = new QWizardPage;
+ page12->setTitle("Page X");
+
+ wizard1.addPage(page11);
+ wizard1.addPage(page12);
+
+ QWizard wizard2;
+ wizard2.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
+ wizard2.setOption(QWizard::ExtendedWatermarkPixmap, true);
+ QWizardPage *page21 = new QWizardPage;
+ page21->setTitle("Page X");
+ page21->setPixmap(QWizard::WatermarkPixmap, watermarkPixmap);
+
+ QWizardPage *page22 = new QWizardPage;
+ page22->setTitle("Page X");
+
+ wizard2.addPage(page21);
+ wizard2.addPage(page22);
+
+ wizard1.show();
+ wizard2.show();
+
+ // Check the impact of watermark pixmaps on the rest of the layout.
+
+ for (int i = 0; i < 3; ++i) {
+ QImage i1[2];
+ QImage i2[2];
+ for (int j = 0; j < 2; ++j) {
+ wizard1.setOption(QWizard::ExtendedWatermarkPixmap, j == 0);
+
+ wizard1.setWizardStyle(i == 0 ? QWizard::ClassicStyle
+ : i == 1 ? QWizard::ModernStyle
+ : QWizard::MacStyle);
+ wizard1.restart();
+ wizard1.setMaximumSize(1000, 1000);
+ wizard1.resize(600, 600);
+ i1[j] = grabWidget(&wizard1);
+
+ wizard1.next();
+ wizard1.setMaximumSize(1000, 1000);
+ wizard1.resize(600, 600);
+ i2[j] = grabWidget(&wizard1);
+ }
+
+ if (wizard1.wizardStyle() == QWizard::MacStyle) {
+ QVERIFY(i1[0] == i1[1]);
+ QVERIFY(i2[0] == i2[1]);
+ QVERIFY(i1[0] == i2[0]);
+ } else {
+ QVERIFY(i1[0] != i1[1]);
+ QVERIFY(i2[0] == i2[1]);
+ QVERIFY(i1[0] != i2[0]);
+ QVERIFY(i1[1] != i2[1]);
+ }
+ }
+}
+
+void tst_QWizard::setOption_NoDefaultButton()
+{
+ QWizard wizard;
+ wizard.setOption(QWizard::NoDefaultButton, false);
+ wizard.setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
+ wizard.addPage(new QWizardPage);
+ wizard.page(0)->setFinalPage(true);
+ wizard.addPage(new QWizardPage);
+
+ if (QPushButton *pb = qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton)))
+ pb->setAutoDefault(false);
+ if (QPushButton *pb = qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton)))
+ pb->setAutoDefault(false);
+
+ wizard.show();
+ qApp->processEvents();
+ QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
+ QVERIFY(wizard.button(QWizard::FinishButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
+
+ wizard.back();
+ QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
+
+ wizard.setOption(QWizard::NoDefaultButton, true);
+ QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
+ QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
+
+ wizard.next();
+ QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
+ QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
+
+ wizard.back();
+ QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
+ QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
+
+ wizard.setOption(QWizard::NoDefaultButton, false);
+ QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
+}
+
+void tst_QWizard::setOption_NoBackButtonOnStartPage()
+{
+ QWizard wizard;
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, true);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+
+ wizard.setStartId(1);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, true);
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, true);
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.back();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+}
+
+void tst_QWizard::setOption_NoBackButtonOnLastPage()
+{
+ for (int i = 0; i < 2; ++i) {
+ QWizard wizard;
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
+ wizard.setOption(QWizard::NoBackButtonOnLastPage, true);
+ wizard.setOption(QWizard::DisabledBackButtonOnLastPage, i == 0); // changes nothing
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.page(1)->setFinalPage(true); // changes nothing (final != last in general)
+ wizard.addPage(new QWizardPage);
+
+ wizard.setStartId(1);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.back();
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.setOption(QWizard::NoBackButtonOnLastPage, false);
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.setOption(QWizard::NoBackButtonOnLastPage, true);
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
+
+ wizard.addPage(new QWizardPage);
+ QVERIFY(!wizard.button(QWizard::BackButton)->isVisible()); // this is maybe wrong
+ }
+}
+
+void tst_QWizard::setOption_DisabledBackButtonOnLastPage()
+{
+ QWizard wizard;
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
+ wizard.setOption(QWizard::DisabledBackButtonOnLastPage, true);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.page(1)->setFinalPage(true); // changes nothing (final != last in general)
+ wizard.addPage(new QWizardPage);
+
+ wizard.setStartId(1);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.back();
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.setOption(QWizard::DisabledBackButtonOnLastPage, false);
+ QVERIFY(wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.setOption(QWizard::DisabledBackButtonOnLastPage, true);
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.addPage(new QWizardPage);
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled()); // this is maybe wrong
+}
+
+void tst_QWizard::setOption_HaveNextButtonOnLastPage()
+{
+ QWizard wizard;
+ wizard.setOption(QWizard::HaveNextButtonOnLastPage, false);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.page(1)->setFinalPage(true); // changes nothing (final != last in general)
+ wizard.addPage(new QWizardPage);
+
+ wizard.setStartId(1);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::NextButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
+
+ wizard.setOption(QWizard::HaveNextButtonOnLastPage, true);
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
+
+ wizard.back();
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::NextButton)->isEnabled());
+
+ wizard.setOption(QWizard::HaveNextButtonOnLastPage, false);
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(wizard.button(QWizard::NextButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
+
+ wizard.setOption(QWizard::HaveNextButtonOnLastPage, true);
+ QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
+ QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
+}
+
+void tst_QWizard::setOption_HaveFinishButtonOnEarlyPages()
+{
+ QWizard wizard;
+ QVERIFY(!wizard.testOption(QWizard::HaveFinishButtonOnEarlyPages));
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.page(1)->setFinalPage(true);
+ wizard.addPage(new QWizardPage);
+
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(!wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.next();
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.next();
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.back();
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.back();
+ QVERIFY(!wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.next();
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.setOption(QWizard::HaveFinishButtonOnEarlyPages, false);
+ QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
+
+ wizard.back();
+ QVERIFY(!wizard.button(QWizard::FinishButton)->isVisible());
+}
+
+void tst_QWizard::setOption_NoCancelButton()
+{
+ for (int i = 0; i < 2; ++i) {
+ QWizard wizard;
+ wizard.setOption(QWizard::NoCancelButton, true);
+ wizard.setOption(QWizard::CancelButtonOnLeft, i == 0);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(!wizard.button(QWizard::CancelButton)->isVisible());
+
+ wizard.next();
+ QVERIFY(!wizard.button(QWizard::CancelButton)->isVisible());
+
+ wizard.setOption(QWizard::NoCancelButton, false);
+ QVERIFY(wizard.button(QWizard::CancelButton)->isVisible());
+
+ wizard.back();
+ QVERIFY(wizard.button(QWizard::CancelButton)->isVisible());
+
+ wizard.setOption(QWizard::NoCancelButton, true);
+ QVERIFY(!wizard.button(QWizard::CancelButton)->isVisible());
+ }
+}
+
+void tst_QWizard::setOption_CancelButtonOnLeft()
+{
+ for (int i = 0; i < 2; ++i) {
+ int sign = (i == 0) ? +1 : -1;
+
+ QWizard wizard;
+ wizard.setLayoutDirection(i == 0 ? Qt::LeftToRight : Qt::RightToLeft);
+ wizard.setOption(QWizard::NoCancelButton, false);
+ wizard.setOption(QWizard::CancelButtonOnLeft, true);
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ qApp->processEvents();
+
+ const QAbstractButton *refButton = wizard.button((wizard.wizardStyle() == QWizard::AeroStyle)
+ ? QWizard::NextButton : QWizard::BackButton);
+ const QAbstractButton *refButton2 = wizard.button((wizard.wizardStyle() == QWizard::AeroStyle)
+ ? QWizard::FinishButton : QWizard::BackButton);
+
+ QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() < sign * refButton->x());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() < sign * refButton->x());
+
+ wizard.setOption(QWizard::CancelButtonOnLeft, false);
+ qApp->processEvents();
+ QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() > sign * refButton2->x());
+
+ wizard.back();
+ qApp->processEvents();
+ QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() > sign * refButton->x());
+ }
+}
+
+void tst_QWizard::setOption_HaveHelpButton()
+{
+ for (int i = 0; i < 2; ++i) {
+ QWizard wizard;
+ QVERIFY(!wizard.testOption(QWizard::HaveHelpButton));
+ wizard.setOption(QWizard::HaveHelpButton, false);
+ wizard.setOption(QWizard::HelpButtonOnRight, i == 0);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
+
+ wizard.next();
+ QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
+
+ wizard.setOption(QWizard::HaveHelpButton, true);
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+
+ wizard.back();
+ QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
+
+ wizard.setOption(QWizard::HaveHelpButton, false);
+ QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
+ }
+}
+
+void tst_QWizard::setOption_HelpButtonOnRight()
+{
+ for (int i = 0; i < 2; ++i) {
+ int sign = (i == 0) ? +1 : -1;
+
+ QWizard wizard;
+ wizard.setLayoutDirection(i == 0 ? Qt::LeftToRight : Qt::RightToLeft);
+ wizard.setOption(QWizard::HaveHelpButton, true);
+ wizard.setOption(QWizard::HelpButtonOnRight, false);
+ wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ qApp->processEvents();
+
+ const QAbstractButton *refButton = wizard.button((wizard.wizardStyle() == QWizard::AeroStyle)
+ ? QWizard::NextButton : QWizard::BackButton);
+
+ QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() < sign * refButton->x());
+
+ wizard.next();
+ qApp->processEvents();
+ QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() < sign * refButton->x());
+
+ wizard.setOption(QWizard::HelpButtonOnRight, true);
+ qApp->processEvents();
+ QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() > sign * refButton->x());
+
+ wizard.back();
+ qApp->processEvents();
+ QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() > sign * refButton->x());
+ }
+}
+
+void tst_QWizard::setOption_HaveCustomButtonX()
+{
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ for (int k = 0; k < 2; ++k) {
+ QWizard wizard;
+ wizard.setLayoutDirection(Qt::LeftToRight);
+ wizard.addPage(new QWizardPage);
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+
+ wizard.setButtonText(QWizard::CustomButton1, "Foo");
+ wizard.setButton(QWizard::CustomButton2, new QCheckBox("Bar"));
+ wizard.button(QWizard::CustomButton3)->setText("Baz");
+
+ wizard.setOption(QWizard::HaveCustomButton1, i == 0);
+ wizard.setOption(QWizard::HaveCustomButton2, j == 0);
+ wizard.setOption(QWizard::HaveCustomButton3, k == 0);
+
+ QVERIFY(wizard.button(QWizard::CustomButton1)->isHidden() == (i != 0));
+ QVERIFY(wizard.button(QWizard::CustomButton2)->isHidden() == (j != 0));
+ QVERIFY(wizard.button(QWizard::CustomButton3)->isHidden() == (k != 0));
+
+ if (i + j + k == 0) {
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::CustomButton1)->x()
+ < wizard.button(QWizard::CustomButton2)->x());
+ QVERIFY(wizard.button(QWizard::CustomButton2)->x()
+ < wizard.button(QWizard::CustomButton3)->x());
+ }
+ }
+ }
+ }
+}
+
+class Operation
+{
+public:
+ virtual void apply(QWizard *) const = 0;
+ virtual QString describe() const = 0;
+protected:
+ virtual ~Operation() {}
+};
+
+class SetPage : public Operation
+{
+ void apply(QWizard *wizard) const
+ {
+ wizard->restart();
+ for (int j = 0; j < page; ++j)
+ wizard->next();
+ }
+ QString describe() const { return QString("set page %1").arg(page); }
+ const int page;
+public:
+ SetPage(int page) : page(page) {}
+};
+
+class SetStyle : public Operation
+{
+ void apply(QWizard *wizard) const { wizard->setWizardStyle(style); }
+ QString describe() const { return QString("set style %1").arg(style); }
+ const QWizard::WizardStyle style;
+public:
+ SetStyle(QWizard::WizardStyle style) : style(style) {}
+};
+
+class SetOption : public Operation
+{
+ void apply(QWizard *wizard) const { wizard->setOption(option, on); }
+ QString describe() const;
+ const QWizard::WizardOption option;
+ const bool on;
+public:
+ SetOption(QWizard::WizardOption option, bool on) : option(option), on(on) {}
+};
+
+class OptionInfo
+{
+ OptionInfo()
+ {
+ tags[QWizard::IndependentPages] = "0/IPP";
+ tags[QWizard::IgnoreSubTitles] = "1/IST";
+ tags[QWizard::ExtendedWatermarkPixmap] = "2/EWP";
+ tags[QWizard::NoDefaultButton] = "3/NDB";
+ tags[QWizard::NoBackButtonOnStartPage] = "4/BSP";
+ tags[QWizard::NoBackButtonOnLastPage] = "5/BLP";
+ tags[QWizard::DisabledBackButtonOnLastPage] = "6/DLP";
+ tags[QWizard::HaveNextButtonOnLastPage] = "7/NLP";
+ tags[QWizard::HaveFinishButtonOnEarlyPages] = "8/FEP";
+ tags[QWizard::NoCancelButton] = "9/NCB";
+ tags[QWizard::CancelButtonOnLeft] = "10/CBL";
+ tags[QWizard::HaveHelpButton] = "11/HHB";
+ tags[QWizard::HelpButtonOnRight] = "12/HBR";
+ tags[QWizard::HaveCustomButton1] = "13/CB1";
+ tags[QWizard::HaveCustomButton2] = "14/CB2";
+ tags[QWizard::HaveCustomButton3] = "15/CB3";
+
+ for (int i = 0; i < 2; ++i) {
+ QMap<QWizard::WizardOption, Operation *> operations_;
+ foreach (QWizard::WizardOption option, tags.keys())
+ operations_[option] = new SetOption(option, i == 1);
+ operations << operations_;
+ }
+ }
+ OptionInfo(OptionInfo const&);
+ OptionInfo& operator=(OptionInfo const&);
+ QMap<QWizard::WizardOption, QString> tags;
+ QList<QMap<QWizard::WizardOption, Operation *> > operations;
+public:
+ static OptionInfo &instance()
+ {
+ static OptionInfo optionInfo;
+ return optionInfo;
+ }
+
+ QString tag(QWizard::WizardOption option) const { return tags.value(option); }
+ Operation * operation(QWizard::WizardOption option, bool on) const
+ { return operations.at(on).value(option); }
+ QList<QWizard::WizardOption> options() const { return tags.keys(); }
+};
+
+QString SetOption::describe() const
+{
+ return QString("set opt %1 %2").arg(OptionInfo::instance().tag(option)).arg(on);
+}
+
+Q_DECLARE_METATYPE(Operation *)
+Q_DECLARE_METATYPE(SetPage *)
+Q_DECLARE_METATYPE(SetStyle *)
+Q_DECLARE_METATYPE(SetOption *)
+Q_DECLARE_METATYPE(QList<Operation *>)
+
+class TestGroup
+{
+public:
+ enum Type {Equality, NonEquality};
+
+ TestGroup(const QString &name = QString("no name"), Type type = Equality)
+ : name(name), type(type), nRows_(0) {}
+
+ void reset(const QString &name, Type type = Equality)
+ {
+ this->name = name;
+ this->type = type;
+ combinations.clear();
+ }
+
+ QList<Operation *> &add()
+ { combinations << new QList<Operation *>; return *(combinations.last()); }
+
+ void createTestRows()
+ {
+ for (int i = 0; i < combinations.count(); ++i) {
+ QTest::newRow((name + QString(", row %1").arg(i)).toLatin1().data())
+ << (i == 0) << (type == Equality) << *(combinations.at(i));
+ ++nRows_;
+ }
+ }
+
+ int nRows() const { return nRows_; }
+
+private:
+ QString name;
+ Type type;
+ int nRows_;
+ QList<QList<Operation *> *> combinations;
+};
+
+class IntroPage : public QWizardPage
+{
+ Q_OBJECT
+public:
+ IntroPage()
+ {
+ setTitle(tr("Intro"));
+ setSubTitle(tr("Intro Subtitle"));
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QLabel(tr("Intro Label")));
+ setLayout(layout);
+ }
+};
+
+class MiddlePage : public QWizardPage
+{
+ Q_OBJECT
+public:
+ MiddlePage()
+ {
+ setTitle(tr("Middle"));
+ setSubTitle(tr("Middle Subtitle"));
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QLabel(tr("Middle Label")));
+ setLayout(layout);
+ }
+};
+
+class ConclusionPage : public QWizardPage
+{
+ Q_OBJECT
+public:
+ ConclusionPage()
+ {
+ setTitle(tr("Conclusion"));
+ setSubTitle(tr("Conclusion Subtitle"));
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QLabel(tr("Conclusion Label")));
+ setLayout(layout);
+ }
+};
+
+class TestWizard : public QWizard
+{
+ Q_OBJECT
+ QList<int> pageIds;
+ QString opsDescr;
+public:
+ TestWizard()
+ {
+ setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png"));
+ setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png"));
+ setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark.png"));
+ setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo.png"));
+ setButtonText(QWizard::CustomButton1, "custom 1");
+ setButtonText(QWizard::CustomButton2, "custom 2");
+ setButtonText(QWizard::CustomButton3, "custom 3");
+ pageIds << addPage(new IntroPage);
+ pageIds << addPage(new MiddlePage);
+ pageIds << addPage(new ConclusionPage);
+
+ // Disable antialiased font rendering since this may sometimes result in tiny
+ // and (apparent) non-deterministic pixel variations between images expected to be
+ // identical. This may only be a problem on X11.
+ QFont f = font();
+ f.setStyleStrategy(QFont::NoAntialias);
+ setFont(f);
+
+ // ### Required to work with a deficiency(?) in QWizard:
+// setFixedSize(800, 600);
+ }
+
+ ~TestWizard()
+ {
+ foreach (int id, pageIds) {
+ QWizardPage *page_to_delete = page(id);
+ removePage(id);
+ delete page_to_delete;
+ }
+ }
+
+ void applyOperations(const QList<Operation *> &operations)
+ {
+ foreach (Operation * op, operations) {
+ if (op) {
+ op->apply(this);
+ opsDescr += QString("(%1) ").arg(op->describe());
+ }
+ }
+ }
+
+ QImage createImage() const
+ {
+ return QPixmap::grabWidget(const_cast<TestWizard *>(this))
+ .toImage().convertToFormat(QImage::Format_ARGB32);
+ }
+
+ QString operationsDescription() const { return opsDescr; }
+};
+
+class CombinationsTestData
+{
+ TestGroup testGroup;
+ QList<Operation *> pageOps;
+ QList<Operation *> styleOps;
+ QMap<bool, QList<Operation *> *> setAllOptions;
+public:
+ CombinationsTestData()
+ {
+ QTest::addColumn<bool>("ref");
+ QTest::addColumn<bool>("testEquality");
+ QTest::addColumn<QList<Operation *> >("operations");
+ pageOps << new SetPage(0) << new SetPage(1) << new SetPage(2);
+ styleOps << new SetStyle(QWizard::ClassicStyle) << new SetStyle(QWizard::ModernStyle)
+ << new SetStyle(QWizard::MacStyle);
+#define SETPAGE(page) pageOps.at(page)
+#define SETSTYLE(style) styleOps.at(style)
+#define OPT(option, on) OptionInfo::instance().operation(option, on)
+#define CLROPT(option) OPT(option, false)
+#define SETOPT(option) OPT(option, true)
+ setAllOptions[false] = new QList<Operation *>;
+ setAllOptions[true] = new QList<Operation *>;
+ foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
+ *setAllOptions.value(false) << CLROPT(option);
+ *setAllOptions.value(true) << SETOPT(option);
+ }
+#define CLRALLOPTS *setAllOptions.value(false)
+#define SETALLOPTS *setAllOptions.value(true)
+ }
+
+ int nRows() const { return testGroup.nRows(); }
+
+ // Creates "all" possible test rows. (WARNING: This typically makes the test take too long!)
+ void createAllTestRows()
+ {
+ testGroup.reset("testAll 1.1");
+ testGroup.add(); // i.e. no operations applied!
+ testGroup.add() << SETPAGE(0);
+ testGroup.add() << SETSTYLE(0);
+ testGroup.add() << SETPAGE(0) << SETSTYLE(0);
+ testGroup.add() << SETSTYLE(0) << SETPAGE(0);
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.1");
+ testGroup.add();
+ testGroup.add() << CLRALLOPTS;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.2");
+ testGroup.add() << SETALLOPTS;
+ testGroup.add() << SETALLOPTS << SETALLOPTS;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.3");
+ testGroup.add() << CLRALLOPTS;
+ testGroup.add() << CLRALLOPTS << CLRALLOPTS;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.4");
+ testGroup.add() << CLRALLOPTS;
+ testGroup.add() << SETALLOPTS << CLRALLOPTS;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.5");
+ testGroup.add() << SETALLOPTS;
+ testGroup.add() << CLRALLOPTS << SETALLOPTS;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.6");
+ testGroup.add() << SETALLOPTS;
+ testGroup.add() << SETALLOPTS << CLRALLOPTS << SETALLOPTS;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 2.7");
+ testGroup.add() << CLRALLOPTS;
+ testGroup.add() << CLRALLOPTS << SETALLOPTS << CLRALLOPTS;
+ testGroup.createTestRows();
+
+ for (int i = 0; i < 2; ++i) {
+ QList<Operation *> setOptions = *setAllOptions.value(i == 1);
+
+ testGroup.reset("testAll 3.1");
+ testGroup.add() << setOptions;
+ testGroup.add() << SETPAGE(0) << setOptions;
+ testGroup.add() << setOptions << SETPAGE(0);
+ testGroup.add() << SETSTYLE(0) << setOptions;
+ testGroup.add() << setOptions << SETSTYLE(0);
+ testGroup.add() << setOptions << SETPAGE(0) << SETSTYLE(0);
+ testGroup.add() << SETPAGE(0) << setOptions << SETSTYLE(0);
+ testGroup.add() << SETPAGE(0) << SETSTYLE(0) << setOptions;
+ testGroup.add() << setOptions << SETSTYLE(0) << SETPAGE(0);
+ testGroup.add() << SETSTYLE(0) << setOptions << SETPAGE(0);
+ testGroup.add() << SETSTYLE(0) << SETPAGE(0) << setOptions;
+ testGroup.createTestRows();
+ }
+
+ foreach (Operation *pageOp, pageOps) {
+ testGroup.reset("testAll 4.1");
+ testGroup.add() << pageOp;
+ testGroup.add() << pageOp << pageOp;
+ testGroup.createTestRows();
+
+ for (int i = 0; i < 2; ++i) {
+ QList<Operation *> optionOps = *setAllOptions.value(i == 1);
+ testGroup.reset("testAll 4.2");
+ testGroup.add() << optionOps << pageOp;
+ testGroup.add() << pageOp << optionOps;
+ testGroup.createTestRows();
+
+ foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
+ Operation *optionOp = OPT(option, i == 1);
+ testGroup.reset("testAll 4.3");
+ testGroup.add() << optionOp << pageOp;
+ testGroup.add() << pageOp << optionOp;
+ testGroup.createTestRows();
+ }
+ }
+ }
+
+ foreach (Operation *styleOp, styleOps) {
+ testGroup.reset("testAll 5.1");
+ testGroup.add() << styleOp;
+ testGroup.add() << styleOp << styleOp;
+ testGroup.createTestRows();
+
+ for (int i = 0; i < 2; ++i) {
+ QList<Operation *> optionOps = *setAllOptions.value(i == 1);
+ testGroup.reset("testAll 5.2");
+ testGroup.add() << optionOps << styleOp;
+ testGroup.add() << styleOp << optionOps;
+ testGroup.createTestRows();
+
+ foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
+ Operation *optionOp = OPT(option, i == 1);
+ testGroup.reset("testAll 5.3");
+ testGroup.add() << optionOp << styleOp;
+ testGroup.add() << styleOp << optionOp;
+ testGroup.createTestRows();
+ }
+ }
+ }
+
+ foreach (Operation *pageOp, pageOps) {
+ foreach (Operation *styleOp, styleOps) {
+
+ testGroup.reset("testAll 6.1");
+ testGroup.add() << pageOp;
+ testGroup.add() << pageOp << pageOp;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 6.2");
+ testGroup.add() << styleOp;
+ testGroup.add() << styleOp << styleOp;
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 6.3");
+ testGroup.add() << pageOp << styleOp;
+ testGroup.add() << styleOp << pageOp;
+ testGroup.createTestRows();
+
+ for (int i = 0; i < 2; ++i) {
+ QList<Operation *> optionOps = *setAllOptions.value(i == 1);
+ testGroup.reset("testAll 6.4");
+ testGroup.add() << optionOps << pageOp << styleOp;
+ testGroup.add() << pageOp << optionOps << styleOp;
+ testGroup.add() << pageOp << styleOp << optionOps;
+ testGroup.add() << optionOps << styleOp << pageOp;
+ testGroup.add() << styleOp << optionOps << pageOp;
+ testGroup.add() << styleOp << pageOp << optionOps;
+ testGroup.createTestRows();
+
+ foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
+ Operation *optionOp = OPT(option, i == 1);
+ testGroup.reset("testAll 6.5");
+ testGroup.add() << optionOp << pageOp << styleOp;
+ testGroup.add() << pageOp << optionOp << styleOp;
+ testGroup.add() << pageOp << styleOp << optionOp;
+ testGroup.add() << optionOp << styleOp << pageOp;
+ testGroup.add() << styleOp << optionOp << pageOp;
+ testGroup.add() << styleOp << pageOp << optionOp;
+ testGroup.createTestRows();
+ }
+ }
+ }
+ }
+
+ testGroup.reset("testAll 7.1", TestGroup::NonEquality);
+ testGroup.add() << SETPAGE(0);
+ testGroup.add() << SETPAGE(1);
+ testGroup.add() << SETPAGE(2);
+ testGroup.createTestRows();
+
+ testGroup.reset("testAll 7.2", TestGroup::NonEquality);
+ testGroup.add() << SETSTYLE(0);
+ testGroup.add() << SETSTYLE(1);
+ testGroup.add() << SETSTYLE(2);
+ testGroup.createTestRows();
+
+ // more to follow ...
+ }
+
+ // Creates a "small" number of interesting test rows.
+ void createTestRows1()
+ {
+ testGroup.reset("test1 1");
+ testGroup.add() << SETPAGE(0) << SETOPT(QWizard::HaveCustomButton3);
+ testGroup.add() << SETOPT(QWizard::HaveCustomButton3);
+ testGroup.createTestRows();
+
+ testGroup.reset("test1 2");
+ testGroup.add() << SETOPT(QWizard::HaveFinishButtonOnEarlyPages) << SETPAGE(0);
+ testGroup.add() << SETPAGE(0) << SETOPT(QWizard::HaveFinishButtonOnEarlyPages);
+ testGroup.createTestRows();
+
+ testGroup.reset("test1 3");
+ testGroup.add() << SETPAGE(2) << SETOPT(QWizard::HaveNextButtonOnLastPage);
+ testGroup.add() << SETOPT(QWizard::HaveNextButtonOnLastPage) << SETPAGE(2);
+ testGroup.createTestRows();
+ }
+};
+
+// Too much memory usage for testing on CE emulator.
+#ifndef Q_OS_WINCE
+void tst_QWizard::combinations_data()
+{
+ CombinationsTestData combTestData;
+// combTestData.createAllTestRows();
+ combTestData.createTestRows1();
+
+// qDebug() << "test rows:" << combTestData.nRows();
+}
+
+void tst_QWizard::combinations()
+{
+ QFETCH(bool, ref);
+ QFETCH(bool, testEquality);
+ QFETCH(QList<Operation *>, operations);
+
+ TestWizard wizard;
+#if !defined(QT_NO_STYLE_WINDOWSVISTA)
+ if (wizard.wizardStyle() == QWizard::AeroStyle)
+ return; // ### TODO: passes/fails in a unpredictable way, so disable for now
+#endif
+ wizard.applyOperations(operations);
+ wizard.show(); // ### TODO: Required, but why? Should wizard.createImage() care?
+
+ static QImage refImage;
+ static QSize refMinSize;
+ static QString refDescr;
+
+ if (ref) {
+ refImage = wizard.createImage();
+ refMinSize = wizard.minimumSizeHint();
+ refDescr = wizard.operationsDescription();
+ return;
+ }
+
+ QImage image = wizard.createImage();
+
+ bool minSizeTest = wizard.minimumSizeHint() != refMinSize;
+ bool imageTest = image != refImage;
+ QLatin1String otor("!=");
+ QLatin1String reason("differ");
+
+ if (!testEquality) {
+ minSizeTest = false; // the image test is sufficient!
+ imageTest = !imageTest;
+ otor = QLatin1String("==");
+ reason = QLatin1String("are equal");
+ }
+
+ if (minSizeTest)
+ qDebug() << "minimum sizes" << reason.latin1() << ";" << wizard.minimumSizeHint()
+ << otor.latin1() << refMinSize;
+
+ if (imageTest)
+ qDebug() << "images" << reason.latin1();
+
+ if (minSizeTest || imageTest) {
+ qDebug() << "\t row 0 operations:" << refDescr.toLatin1();
+ qDebug() << "\tcurrent row operations:" << wizard.operationsDescription().toLatin1();
+ QVERIFY(false);
+ }
+}
+#endif
+
+class WizardPage : public QWizardPage
+{
+ Q_OBJECT
+ bool shown_;
+ void showEvent(QShowEvent *) { shown_ = true; }
+ void hideEvent(QHideEvent *) { shown_ = false; }
+public:
+ WizardPage() : shown_(false) {}
+ bool shown() const { return shown_; }
+};
+
+class WizardPages
+{
+ QList<WizardPage *> pages;
+public:
+ void add(WizardPage *page) { pages << page; }
+ QList<WizardPage *> all() const { return pages; }
+ QList<WizardPage *> shown() const
+ {
+ QList<WizardPage *> result;
+ foreach (WizardPage *page, pages)
+ if (page->shown())
+ result << page;
+ return result;
+ }
+};
+
+void tst_QWizard::showCurrentPageOnly()
+{
+ QWizard wizard;
+ WizardPages pages;
+ for (int i = 0; i < 5; ++i) {
+ pages.add(new WizardPage);
+ wizard.addPage(pages.all().last());
+ }
+
+ wizard.show();
+
+ QCOMPARE(pages.shown().count(), 1);
+ QCOMPARE(pages.shown().first(), pages.all().first());
+
+ const int steps = 2;
+ for (int i = 0; i < steps; ++i)
+ wizard.next();
+
+ QCOMPARE(pages.shown().count(), 1);
+ QCOMPARE(pages.shown().first(), pages.all().at(steps));
+
+ wizard.restart();
+
+ QCOMPARE(pages.shown().count(), 1);
+ QCOMPARE(pages.shown().first(), pages.all().first());
+}
+
+void tst_QWizard::setButtonText()
+{
+ QWizard wizard;
+ wizard.setWizardStyle(QWizard::ClassicStyle);
+ QWizardPage* page1 = new QWizardPage;
+ QWizardPage* page2 = new QWizardPage;
+ wizard.addPage(page1);
+ wizard.addPage(page2);
+
+ wizard.show();
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
+ QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
+ QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
+ QVERIFY(page2->buttonText(QWizard::NextButton).contains("Next"));
+
+ page2->setButtonText(QWizard::NextButton, "Page2");
+ QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
+ QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
+ QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
+ QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
+
+ wizard.next();
+ qApp->processEvents();
+ QCOMPARE(wizard.button(QWizard::NextButton)->text(), QString("Page2"));
+ QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
+ QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
+ QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
+
+ wizard.back();
+ qApp->processEvents();
+ QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
+ QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
+ QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
+ QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
+
+ wizard.setButtonText(QWizard::NextButton, "Wizard");
+ QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Wizard"));
+ QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("Wizard"));
+ QCOMPARE(page1->buttonText(QWizard::NextButton), QString("Wizard"));
+ QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
+
+ wizard.next();
+ qApp->processEvents();
+ QCOMPARE(wizard.button(QWizard::NextButton)->text(), QString("Page2"));
+ QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Wizard"));
+ QCOMPARE(page1->buttonText(QWizard::NextButton), QString("Wizard"));
+ QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
+}
+
+void tst_QWizard::setCommitPage()
+{
+ QWizard wizard;
+ QWizardPage* page1 = new QWizardPage;
+ QWizardPage* page2 = new QWizardPage;
+ wizard.addPage(page1);
+ wizard.addPage(page2);
+ wizard.show();
+ qApp->processEvents();
+
+ QVERIFY(!page1->isCommitPage());
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(wizard.button(QWizard::BackButton)->isEnabled());
+
+ page1->setCommitPage(true);
+ QVERIFY(page1->isCommitPage());
+
+ wizard.back();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ page1->setCommitPage(false);
+ QVERIFY(!page1->isCommitPage());
+
+ wizard.back();
+ QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
+
+ wizard.next();
+ QVERIFY(wizard.button(QWizard::BackButton)->isEnabled());
+
+ // ### test relabeling of the Cancel button to "Close" once this is implemented
+}
+
+void tst_QWizard::setWizardStyle()
+{
+ QWizard wizard;
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ qApp->processEvents();
+
+ // defaults
+ const bool styleHintMatch =
+ wizard.wizardStyle() ==
+ QWizard::WizardStyle(wizard.style()->styleHint(QStyle::SH_WizardStyle, 0, &wizard));
+#if !defined(QT_NO_STYLE_WINDOWSVISTA)
+ QVERIFY(styleHintMatch || wizard.wizardStyle() == QWizard::AeroStyle);
+#else
+ QVERIFY(styleHintMatch);
+#endif
+
+ // set/get consistency
+ for (int wstyle = 0; wstyle < QWizard::NStyles; ++wstyle) {
+ wizard.setWizardStyle((QWizard::WizardStyle)wstyle);
+ QCOMPARE((int)wizard.wizardStyle(), wstyle);
+ }
+}
+
+void tst_QWizard::removePage()
+{
+ QWizard wizard;
+ QWizardPage *page0 = new QWizardPage;
+ QWizardPage *page1 = new QWizardPage;
+ QWizardPage *page2 = new QWizardPage;
+ QWizardPage *page3 = new QWizardPage;
+ QSignalSpy spy(&wizard, SIGNAL(pageRemoved(int)));
+
+ wizard.setPage(0, page0);
+ wizard.setPage(1, page1);
+ wizard.setPage(2, page2);
+ wizard.setPage(3, page3);
+
+ wizard.restart();
+ QCOMPARE(wizard.pageIds().size(), 4);
+ QCOMPARE(wizard.visitedPages().size(), 1);
+ QCOMPARE(spy.count(), 0);
+
+ // Removing a non-existent page
+ wizard.removePage(4);
+ QCOMPARE(wizard.pageIds().size(), 4);
+ QCOMPARE(spy.count(), 0);
+
+ // Removing and then reinserting a page
+ QCOMPARE(wizard.pageIds().size(), 4);
+ QVERIFY(wizard.pageIds().contains(2));
+ wizard.removePage(2);
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 2);
+ QCOMPARE(wizard.pageIds().size(), 3);
+ QVERIFY(!wizard.pageIds().contains(2));
+ wizard.setPage(2, page2);
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(wizard.pageIds().size(), 4);
+ QVERIFY(wizard.pageIds().contains(2));
+
+ // Removing the same page twice
+ wizard.removePage(2); // restore
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 2);
+ QCOMPARE(wizard.pageIds().size(), 3);
+ QVERIFY(!wizard.pageIds().contains(2));
+ wizard.removePage(2);
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(wizard.pageIds().size(), 3);
+ QVERIFY(!wizard.pageIds().contains(2));
+
+ // Removing a page not in the history
+ wizard.setPage(2, page2); // restore
+ wizard.restart();
+ wizard.next();
+ QCOMPARE(wizard.visitedPages().size(), 2);
+ QCOMPARE(wizard.currentPage(), page1);
+ QCOMPARE(spy.count(), 0);
+ wizard.removePage(2);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 2);
+ QCOMPARE(wizard.visitedPages().size(), 2);
+ QVERIFY(!wizard.pageIds().contains(2));
+ QCOMPARE(wizard.currentPage(), page1);
+
+ // Removing a page in the history before the current page
+ wizard.setPage(2, page2); // restore
+ wizard.restart();
+ wizard.next();
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(wizard.visitedPages().size(), 2);
+ QCOMPARE(wizard.currentPage(), page1);
+ wizard.removePage(0);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 0);
+ QCOMPARE(wizard.visitedPages().size(), 1);
+ QVERIFY(!wizard.visitedPages().contains(0));
+ QVERIFY(!wizard.pageIds().contains(0));
+ QCOMPARE(wizard.currentPage(), page1);
+
+ // Remove the current page which is not the first one in the history
+ wizard.setPage(0, page0); // restore
+ wizard.restart();
+ wizard.next();
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(wizard.visitedPages().size(), 2);
+ QCOMPARE(wizard.currentPage(), page1);
+ wizard.removePage(1);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 1);
+ QCOMPARE(wizard.visitedPages().size(), 1);
+ QVERIFY(!wizard.visitedPages().contains(1));
+ QVERIFY(!wizard.pageIds().contains(1));
+ QCOMPARE(wizard.currentPage(), page0);
+
+ // Remove the current page which is the first (and only) one in the history
+ wizard.removePage(0);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 0);
+ QCOMPARE(wizard.visitedPages().size(), 1);
+ QVERIFY(!wizard.visitedPages().contains(0));
+ QCOMPARE(wizard.pageIds().size(), 2);
+ QVERIFY(!wizard.pageIds().contains(0));
+ QCOMPARE(wizard.currentPage(), page2);
+ //
+ wizard.removePage(2);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 2);
+ QCOMPARE(wizard.visitedPages().size(), 1);
+ QVERIFY(!wizard.visitedPages().contains(2));
+ QCOMPARE(wizard.pageIds().size(), 1);
+ QVERIFY(!wizard.pageIds().contains(2));
+ QCOMPARE(wizard.currentPage(), page3);
+ //
+ wizard.removePage(3);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toInt(), 3);
+ QVERIFY(wizard.visitedPages().empty());
+ QVERIFY(wizard.pageIds().empty());
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage *>(0));
+}
+
+void tst_QWizard::sideWidget()
+{
+ QWizard wizard;
+
+ wizard.setSideWidget(0);
+ QVERIFY(wizard.sideWidget() == 0);
+ QWidget *w1 = new QWidget(&wizard);
+ wizard.setSideWidget(w1);
+ QVERIFY(wizard.sideWidget() == w1);
+ QWidget *w2 = new QWidget(&wizard);
+ wizard.setSideWidget(w2);
+ QVERIFY(wizard.sideWidget() == w2);
+ QVERIFY(w1->parent() != 0);
+ QCOMPARE(w1->window(), static_cast<QWidget *>(&wizard));
+ QCOMPARE(w2->window(), static_cast<QWidget *>(&wizard));
+ w1->setParent(0);
+ wizard.setSideWidget(0);
+ QVERIFY(wizard.sideWidget() == 0);
+}
+
+void tst_QWizard::task161660_buttonSpacing()
+{
+#ifndef QT_NO_STYLE_PLASTIQUE
+ QString origStyle = QApplication::style()->objectName();
+ QApplication::setStyle(new QPlastiqueStyle);
+ QWizard wizard;
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ const QAbstractButton *finishButton = wizard.button(QWizard::FinishButton);
+ const QAbstractButton *cancelButton = wizard.button(QWizard::CancelButton);
+ const int spacing = cancelButton->geometry().left() - finishButton->geometry().right() - 1;
+ QCOMPARE(spacing, wizard.style()->layoutSpacing(
+ QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal));
+ QApplication::setStyle(origStyle);
+#endif
+}
+
+class task177716_CommitPage : public QWizardPage
+{
+ Q_OBJECT
+public:
+ task177716_CommitPage()
+ {
+ setCommitPage(true);
+ QVBoxLayout *layout = new QVBoxLayout;
+ ledit = new QLineEdit(this);
+ registerField("foo*", ledit);
+ layout->addWidget(ledit);
+ setLayout(layout);
+ }
+ QLineEdit *ledit;
+};
+
+void tst_QWizard::task177716_disableCommitButton()
+{
+ QWizard wizard;
+ task177716_CommitPage *commitPage = new task177716_CommitPage;
+ wizard.addPage(commitPage);
+ // the following page must be there to prevent the first page from replacing the Commit button
+ // with the Finish button:
+ wizard.addPage(new QWizardPage);
+ wizard.show();
+ QVERIFY(!wizard.button(QWizard::CommitButton)->isEnabled());
+ commitPage->ledit->setText("some non-empty text");
+ QVERIFY(wizard.button(QWizard::CommitButton)->isEnabled());
+ commitPage->ledit->setText("");
+ QVERIFY(!wizard.button(QWizard::CommitButton)->isEnabled());
+}
+
+class WizardPage_task183550 : public QWizardPage
+{
+public:
+ WizardPage_task183550(QWidget *parent = 0)
+ : QWizardPage(parent)
+ , treeWidget(new QTreeWidget)
+ , verticalPolicy(QSizePolicy::MinimumExpanding) {}
+ void enableVerticalExpansion() { verticalPolicy = QSizePolicy::MinimumExpanding; }
+ void disableVerticalExpansion() { verticalPolicy = QSizePolicy::Preferred; }
+ int treeWidgetHeight() const { return treeWidget->height(); }
+ int treeWidgetSizeHintHeight() const { return treeWidget->sizeHint().height(); }
+
+private:
+ QTreeWidget *treeWidget;
+ QSizePolicy::Policy verticalPolicy;
+
+ void initializePage()
+ {
+ if (layout())
+ delete layout();
+ if (treeWidget)
+ delete treeWidget;
+
+ QLayout *layout_ = new QVBoxLayout(this);
+ layout_->addWidget(treeWidget = new QTreeWidget);
+
+ QSizePolicy policy = sizePolicy();
+ policy.setVerticalPolicy(verticalPolicy);
+ treeWidget->setSizePolicy(policy);
+ }
+};
+
+void tst_QWizard::task183550_stretchFactor()
+{
+ QWizard wizard;
+ WizardPage_task183550 *page1 = new WizardPage_task183550;
+ WizardPage_task183550 *page2 = new WizardPage_task183550;
+ wizard.addPage(page1);
+ wizard.addPage(page2);
+ wizard.resize(500, 2 * page2->treeWidgetSizeHintHeight());
+ wizard.show();
+
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page1));
+
+ // ----
+ page2->disableVerticalExpansion();
+ wizard.next();
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page2));
+ QVERIFY(page2->treeWidgetHeight() == page2->treeWidgetSizeHintHeight());
+
+ wizard.back();
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page1));
+
+ // ----
+ page2->enableVerticalExpansion();
+ wizard.next();
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page2));
+ QVERIFY(page2->treeWidgetHeight() > page2->treeWidgetSizeHintHeight());
+
+ wizard.back();
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page1));
+
+ // ----
+ page2->disableVerticalExpansion();
+ wizard.next();
+ QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page2));
+ QVERIFY(page2->treeWidgetHeight() == page2->treeWidgetSizeHintHeight());
+}
+
+void tst_QWizard::task161658_alignments()
+{
+ QWizard wizard;
+ wizard.setWizardStyle(QWizard::MacStyle);
+
+ QWizardPage page;
+ page.setTitle("Title");
+ page.setSubTitle("SUBTITLE#: The subtitle bust be alligned with the rest of the widget");
+
+ QLabel label1("Field:");
+ QLineEdit lineEdit1;
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(&label1, 0, 0);
+ layout->addWidget(&lineEdit1, 0, 1);
+ page.setLayout(layout);
+
+ int idx = wizard.addPage(&page);
+ wizard.setStartId(idx);
+ wizard.show();
+ QTest::qWait(100);
+
+ foreach (QLabel *subtitleLabel, qFindChildren<QLabel *>(&wizard)) {
+ if (subtitleLabel->text().startsWith("SUBTITLE#")) {
+ QCOMPARE(lineEdit1.mapToGlobal(lineEdit1.contentsRect().bottomRight()).x(),
+ subtitleLabel->mapToGlobal(subtitleLabel->contentsRect().bottomRight()).x());
+ return;
+ }
+ }
+ QFAIL("Subtitle label not found");
+}
+
+void tst_QWizard::task177022_setFixedSize()
+{
+ int width = 300;
+ int height = 200;
+ QWizard wiz;
+ QWizardPage page1;
+ QWizardPage page2;
+ int page1_id = wiz.addPage(&page1);
+ int page2_id = wiz.addPage(&page2);
+ wiz.setFixedSize(width, height);
+ if (wiz.wizardStyle() == QWizard::AeroStyle)
+ QEXPECT_FAIL("", "this probably relates to non-client area hack for AeroStyle titlebar "
+ "effect; not sure if it qualifies as a bug or not", Continue);
+ QCOMPARE(wiz.size(), QSize(width, height));
+ QCOMPARE(wiz.minimumWidth(), width);
+ QCOMPARE(wiz.minimumHeight(), height);
+ QCOMPARE(wiz.maximumWidth(), width);
+ QCOMPARE(wiz.maximumHeight(), height);
+
+ wiz.show();
+ QTest::qWait(100);
+ QCOMPARE(wiz.size(), QSize(width, height));
+ QCOMPARE(wiz.minimumWidth(), width);
+ QCOMPARE(wiz.minimumHeight(), height);
+ QCOMPARE(wiz.maximumWidth(), width);
+ QCOMPARE(wiz.maximumHeight(), height);
+
+ wiz.next();
+ QTest::qWait(100);
+ QCOMPARE(wiz.size(), QSize(width, height));
+ QCOMPARE(wiz.minimumWidth(), width);
+ QCOMPARE(wiz.minimumHeight(), height);
+ QCOMPARE(wiz.maximumWidth(), width);
+ QCOMPARE(wiz.maximumHeight(), height);
+
+ wiz.removePage(page1_id);
+ wiz.removePage(page2_id);
+}
+
+void tst_QWizard::task248107_backButton()
+{
+ QWizard wizard;
+ QWizardPage page1;
+ QWizardPage page2;
+ QWizardPage page3;
+ QWizardPage page4;
+ wizard.addPage(&page1);
+ wizard.addPage(&page2);
+ wizard.addPage(&page3);
+ wizard.addPage(&page4);
+
+ wizard.show();
+ QTest::qWait(100);
+ QCOMPARE(wizard.currentPage(), &page1);
+
+ QTest::mouseClick(wizard.button(QWizard::NextButton), Qt::LeftButton);
+ QCOMPARE(wizard.currentPage(), &page2);
+
+ QTest::mouseClick(wizard.button(QWizard::NextButton), Qt::LeftButton);
+ QCOMPARE(wizard.currentPage(), &page3);
+
+ QTest::mouseClick(wizard.button(QWizard::NextButton), Qt::LeftButton);
+ QCOMPARE(wizard.currentPage(), &page4);
+
+ QTest::mouseClick(wizard.button(QWizard::BackButton), Qt::LeftButton);
+ QCOMPARE(wizard.currentPage(), &page3);
+
+ QTest::mouseClick(wizard.button(QWizard::BackButton), Qt::LeftButton);
+ QCOMPARE(wizard.currentPage(), &page2);
+
+ QTest::mouseClick(wizard.button(QWizard::BackButton), Qt::LeftButton);
+ QCOMPARE(wizard.currentPage(), &page1);
+}
+
+class WizardPage_task255350 : public QWizardPage
+{
+public:
+ QLineEdit *lineEdit;
+ WizardPage_task255350()
+ : lineEdit(new QLineEdit)
+ {
+ registerField("dummy*", lineEdit);
+ }
+};
+
+void tst_QWizard::task255350_fieldObjectDestroyed()
+{
+ QWizard wizard;
+ WizardPage_task255350 *page = new WizardPage_task255350;
+ int id = wizard.addPage(page);
+ delete page->lineEdit;
+ wizard.removePage(id); // don't crash!
+ delete page;
+}
+
+QTEST_MAIN(tst_QWizard)
+#include "tst_qwizard.moc"
diff --git a/tests/auto/widgets/effects/effects.pro b/tests/auto/widgets/effects/effects.pro
new file mode 100644
index 0000000000..fab24d6296
--- /dev/null
+++ b/tests/auto/widgets/effects/effects.pro
@@ -0,0 +1,4 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qgraphicseffect \
+
diff --git a/tests/auto/widgets/effects/qgraphicseffect/qgraphicseffect.pro b/tests/auto/widgets/effects/qgraphicseffect/qgraphicseffect.pro
new file mode 100644
index 0000000000..171ab3ffda
--- /dev/null
+++ b/tests/auto/widgets/effects/qgraphicseffect/qgraphicseffect.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicseffect.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
new file mode 100644
index 0000000000..2d9d87a2c5
--- /dev/null
+++ b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
@@ -0,0 +1,760 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qdesktopwidget.h>
+#include <QtWidgets/qgraphicseffect.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qgraphicsscene.h>
+#include <QtWidgets/qgraphicsitem.h>
+#include <QtWidgets/qgraphicswidget.h>
+#include <QtWidgets/qstyleoption.h>
+
+#include <private/qgraphicseffect_p.h>
+#include "../../../platformquirks.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QGraphicsEffect : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void setEnabled();
+ void source();
+ void boundingRectFor();
+ void boundingRect();
+ void boundingRect2();
+ void draw();
+ void opacity();
+ void grayscale();
+ void colorize();
+ void drawPixmapItem();
+ void deviceCoordinateTranslateCaching();
+ void inheritOpacity();
+ void dropShadowClipping();
+ void childrenVisibilityShouldInvalidateCache();
+ void prepareGeometryChangeInvalidateCache();
+ void itemHasNoContents();
+};
+
+void tst_QGraphicsEffect::initTestCase()
+{}
+
+class CustomItem : public QGraphicsRectItem
+{
+public:
+ CustomItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(x, y, width, height, parent), numRepaints(0),
+ m_painter(0), m_styleOption(0)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ m_painter = painter;
+ m_styleOption = option;
+ ++numRepaints;
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+
+ void reset()
+ {
+ numRepaints = 0;
+ m_painter = 0;
+ m_styleOption = 0;
+ }
+
+ int numRepaints;
+ QPainter *m_painter;
+ const QStyleOption *m_styleOption;
+};
+
+class CustomEffect : public QGraphicsEffect
+{
+public:
+ CustomEffect()
+ : QGraphicsEffect(), numRepaints(0), m_margin(10),
+ doNothingInDraw(false), m_painter(0), m_styleOption(0), m_source(0), m_opacity(1.0)
+ {}
+
+ QRectF boundingRectFor(const QRectF &rect) const
+ { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); }
+
+ void reset()
+ {
+ numRepaints = 0;
+ m_sourceChangedFlags = QGraphicsEffect::ChangeFlags();
+ m_painter = 0;
+ m_styleOption = 0;
+ m_source = 0;
+ m_opacity = 1.0;
+ }
+
+ void setMargin(int margin)
+ {
+ m_margin = margin;
+ updateBoundingRect();
+ }
+
+ int margin() const
+ { return m_margin; }
+
+ void draw(QPainter *painter)
+ {
+ ++numRepaints;
+ if (doNothingInDraw)
+ return;
+ m_source = source();
+ m_painter = painter;
+ m_styleOption = source()->styleOption();
+ m_opacity = painter->opacity();
+ drawSource(painter);
+ }
+
+ void sourceChanged(QGraphicsEffect::ChangeFlags flags)
+ { m_sourceChangedFlags |= flags; }
+
+ int numRepaints;
+ int m_margin;
+ QGraphicsEffect::ChangeFlags m_sourceChangedFlags;
+ bool doNothingInDraw;
+ QPainter *m_painter;
+ const QStyleOption *m_styleOption;
+ QGraphicsEffectSource *m_source;
+ qreal m_opacity;
+};
+
+void tst_QGraphicsEffect::setEnabled()
+{
+ CustomEffect effect;
+ QVERIFY(effect.isEnabled());
+
+ effect.setEnabled(false);
+ QVERIFY(!effect.isEnabled());
+}
+
+void tst_QGraphicsEffect::source()
+{
+ QPointer<CustomEffect> effect = new CustomEffect;
+ QVERIFY(!effect->source());
+ QVERIFY(!effect->m_sourceChangedFlags);
+
+ // Install effect on QGraphicsItem.
+ QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
+ item->setGraphicsEffect(effect);
+ QVERIFY(effect->source());
+ QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
+ QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceAttached);
+ effect->reset();
+
+ // Make sure disabling/enabling the effect doesn't change the source.
+ effect->setEnabled(false);
+ QVERIFY(effect->source());
+ QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
+ QVERIFY(!effect->m_sourceChangedFlags);
+ effect->reset();
+
+ effect->setEnabled(true);
+ QVERIFY(effect->source());
+ QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
+ QVERIFY(!effect->m_sourceChangedFlags);
+ effect->reset();
+
+ // Uninstall effect on QGraphicsItem.
+ effect->reset();
+ item->setGraphicsEffect(0);
+ QVERIFY(!effect);
+ effect = new CustomEffect;
+
+ // The item takes ownership and should delete the effect when destroyed.
+ item->setGraphicsEffect(effect);
+ QPointer<QGraphicsEffectSource> source = effect->source();
+ QVERIFY(source);
+ QCOMPARE(source->graphicsItem(), (const QGraphicsItem*)item);
+ delete item;
+ QVERIFY(!effect);
+ QVERIFY(!source);
+}
+
+void tst_QGraphicsEffect::boundingRectFor()
+{
+ CustomEffect effect;
+ int margin = effect.margin();
+ const QRectF source(0, 0, 100, 100);
+ QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin));
+
+ effect.setMargin(margin = 20);
+ QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin));
+}
+
+void tst_QGraphicsEffect::boundingRect()
+{
+ // No source; empty bounding rect.
+ CustomEffect *effect = new CustomEffect;
+ QCOMPARE(effect->boundingRect(), QRectF());
+
+ // Install effect on QGraphicsItem.
+ QRectF itemRect(0, 0, 100, 100);
+ QGraphicsRectItem *item = new QGraphicsRectItem;
+ item->setRect(itemRect);
+ item->setGraphicsEffect(effect);
+ int margin = effect->margin();
+ QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
+
+ // Make sure disabling/enabling the effect doesn't change the bounding rect.
+ effect->setEnabled(false);
+ QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
+ effect->setEnabled(true);
+ QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
+
+ // Change effect margins.
+ effect->setMargin(margin = 20);
+ QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
+
+ // Uninstall effect on QGraphicsItem.
+ QPointer<CustomEffect> ptr = effect;
+ item->setGraphicsEffect(0);
+ QVERIFY(!ptr);
+
+ delete item;
+}
+
+void tst_QGraphicsEffect::boundingRect2()
+{
+ CustomEffect *effect = new CustomEffect;
+ QGraphicsRectItem *root = new QGraphicsRectItem;
+ root->setGraphicsEffect(effect);
+
+ QGraphicsRectItem *child = new QGraphicsRectItem;
+ QRectF childRect(0, 0, 100, 100);
+ child->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ child->setRect(childRect);
+ child->setParentItem(root);
+
+ QGraphicsRectItem *grandChild = new QGraphicsRectItem;
+ QRectF grandChildRect(0, 0, 200, 200);
+ grandChild->setRect(grandChildRect);
+ grandChild->setParentItem(child);
+
+ // Make sure the effect's bounding rect is clipped to the child's bounding rect.
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect));
+
+ // Disable ItemClipsChildrenToShape; effect's bounding rect is no longer clipped.
+ child->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
+
+ // Add root item to a scene, do the same tests as above. Results should be the same.
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ child->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect));
+
+ child->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
+
+ // Now add the scene to a view, results should be the same.
+ QGraphicsView view(&scene);
+
+ child->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect));
+
+ child->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
+
+ CustomEffect *childEffect = new CustomEffect;
+ child->setGraphicsEffect(childEffect);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childEffect->boundingRectFor(childRect | grandChildRect)));
+
+ child->setGraphicsEffect(0);
+ QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
+}
+
+void tst_QGraphicsEffect::draw()
+{
+ QGraphicsScene scene;
+ CustomItem *item = new CustomItem(0, 0, 100, 100);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(item->numRepaints > 0);
+ item->reset();
+
+ // Make sure installing the effect triggers a repaint.
+ CustomEffect *effect = new CustomEffect;
+ item->setGraphicsEffect(effect);
+ QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_COMPARE(item->numRepaints, 1);
+
+ // Make sure QPainter* and QStyleOptionGraphicsItem* stays persistent
+ // during QGraphicsEffect::draw/QGraphicsItem::paint.
+ QVERIFY(effect->m_painter);
+ QCOMPARE(effect->m_painter, item->m_painter);
+ QCOMPARE(effect->m_styleOption, item->m_styleOption);
+ // Make sure QGraphicsEffect::source is persistent.
+ QCOMPARE(effect->m_source, effect->source());
+ effect->reset();
+ item->reset();
+
+ // Make sure updating the source triggers a repaint.
+ item->update();
+ QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_COMPARE(item->numRepaints, 1);
+ QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceInvalidated);
+ effect->reset();
+ item->reset();
+
+ // Make sure changing the effect's bounding rect triggers a repaint.
+ effect->setMargin(20);
+ QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_COMPARE(item->numRepaints, 1);
+ effect->reset();
+ item->reset();
+
+ // Make sure change the item's bounding rect triggers a repaint.
+ item->setRect(0, 0, 50, 50);
+ QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_COMPARE(item->numRepaints, 1);
+ QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceBoundingRectChanged);
+ effect->reset();
+ item->reset();
+
+ // Make sure the effect is the one to issue a repaint of the item.
+ effect->doNothingInDraw = true;
+ item->update();
+ QTRY_COMPARE(effect->numRepaints, 1);
+ QCOMPARE(item->numRepaints, 0);
+ effect->doNothingInDraw = false;
+ effect->reset();
+ item->reset();
+
+ // Make sure we update the source when disabling/enabling the effect.
+ effect->setEnabled(false);
+ QTest::qWait(50);
+ QCOMPARE(effect->numRepaints, 0);
+ QCOMPARE(item->numRepaints, 1);
+ effect->reset();
+ item->reset();
+
+ effect->setEnabled(true);
+ QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_COMPARE(item->numRepaints, 1);
+ effect->reset();
+ item->reset();
+
+ // Effect is already enabled; nothing should happen.
+ effect->setEnabled(true);
+ QTest::qWait(50);
+ QCOMPARE(effect->numRepaints, 0);
+ QCOMPARE(item->numRepaints, 0);
+
+ // Make sure uninstalling an effect triggers a repaint.
+ QPointer<CustomEffect> ptr = effect;
+ item->setGraphicsEffect(0);
+ QVERIFY(!ptr);
+ QTRY_COMPARE(item->numRepaints, 1);
+}
+
+void tst_QGraphicsEffect::opacity()
+{
+ // Make sure the painter's opacity is correct in QGraphicsEffect::draw.
+ QGraphicsScene scene;
+ CustomItem *item = new CustomItem(0, 0, 100, 100);
+ item->setOpacity(0.5);
+ CustomEffect *effect = new CustomEffect;
+ item->setGraphicsEffect(effect);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(effect->numRepaints > 0);
+ QCOMPARE(effect->m_opacity, qreal(0.5));
+}
+
+void tst_QGraphicsEffect::grayscale()
+{
+ if (qApp->desktop()->depth() < 24)
+ QSKIP("Test only works on 32 bit displays", SkipAll);
+
+ QGraphicsScene scene(0, 0, 100, 100);
+
+ QGraphicsRectItem *item = scene.addRect(0, 0, 50, 50);
+ item->setPen(Qt::NoPen);
+ item->setBrush(QColor(122, 193, 66)); // Qt light green
+
+ QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect;
+ effect->setColor(Qt::black);
+ item->setGraphicsEffect(effect);
+
+ QPainter painter;
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(10, 10), qRgb(148, 148, 148));
+
+ effect->setStrength(0.5);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(10, 10), qRgb(135, 171, 107));
+
+ effect->setStrength(0.0);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66));
+}
+
+void tst_QGraphicsEffect::colorize()
+{
+ if (qApp->desktop()->depth() < 24)
+ QSKIP("Test only works on 32 bit displays", SkipAll);
+
+ QGraphicsScene scene(0, 0, 100, 100);
+
+ QGraphicsRectItem *item = scene.addRect(0, 0, 50, 50);
+ item->setPen(Qt::NoPen);
+ item->setBrush(QColor(122, 193, 66)); // Qt light green
+
+ QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect;
+ effect->setColor(QColor(102, 153, 51)); // Qt dark green
+ item->setGraphicsEffect(effect);
+
+ QPainter painter;
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(10, 10), qRgb(191, 212, 169));
+
+ effect->setStrength(0.5);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(10, 10), qRgb(156, 203, 117));
+
+ effect->setStrength(0.0);
+
+ image.fill(0);
+ painter.begin(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66));
+}
+
+class PixmapItemEffect : public QGraphicsEffect
+{
+public:
+ PixmapItemEffect(const QPixmap &source)
+ : QGraphicsEffect()
+ , pixmap(source)
+ , repaints(0)
+ {}
+
+ QRectF boundingRectFor(const QRectF &rect) const
+ { return rect; }
+
+ void draw(QPainter *painter)
+ {
+ QVERIFY(sourcePixmap(Qt::LogicalCoordinates).handle() == pixmap.handle());
+ QVERIFY((painter->worldTransform().type() <= QTransform::TxTranslate) == (sourcePixmap(Qt::DeviceCoordinates).handle() == pixmap.handle()));
+
+ ++repaints;
+ }
+ QPixmap pixmap;
+ int repaints;
+};
+
+void tst_QGraphicsEffect::drawPixmapItem()
+{
+ QImage image(32, 32, QImage::Format_RGB32);
+ QPainter p(&image);
+ p.fillRect(0, 0, 32, 16, Qt::blue);
+ p.fillRect(0, 16, 32, 16, Qt::red);
+ p.end();
+
+ QGraphicsScene scene;
+ QGraphicsPixmapItem *item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
+ scene.addItem(item);
+
+ PixmapItemEffect *effect = new PixmapItemEffect(item->pixmap());
+ item->setGraphicsEffect(effect);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(effect->repaints >= 1);
+
+ item->rotate(180);
+
+ QTRY_VERIFY(effect->repaints >= 2);
+}
+
+class DeviceEffect : public QGraphicsEffect
+{
+public:
+ QRectF boundingRectFor(const QRectF &rect) const
+ { return rect; }
+
+ void draw(QPainter *painter)
+ {
+ QPoint offset;
+ QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, QGraphicsEffect::NoPad);
+
+ if (pixmap.isNull())
+ return;
+
+ painter->save();
+ painter->setWorldTransform(QTransform());
+ painter->drawPixmap(offset, pixmap);
+ painter->restore();
+ }
+};
+
+void tst_QGraphicsEffect::deviceCoordinateTranslateCaching()
+{
+ QGraphicsScene scene;
+ CustomItem *item = new CustomItem(0, 0, 10, 10);
+ scene.addItem(item);
+ scene.setSceneRect(0, 0, 50, 0);
+
+ item->setGraphicsEffect(new DeviceEffect);
+ item->setPen(Qt::NoPen);
+ item->setBrush(Qt::red);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_VERIFY(item->numRepaints >= 1);
+ int numRepaints = item->numRepaints;
+
+ item->translate(10, 0);
+
+ QTRY_VERIFY(item->numRepaints == numRepaints);
+}
+
+void tst_QGraphicsEffect::inheritOpacity()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 10, 10);
+ CustomItem *item = new CustomItem(0, 0, 10, 10, rectItem);
+
+ scene.addItem(rectItem);
+
+ item->setGraphicsEffect(new DeviceEffect);
+ item->setPen(Qt::NoPen);
+ item->setBrush(Qt::red);
+
+ rectItem->setOpacity(0.5);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_VERIFY(item->numRepaints >= 1);
+
+ int numRepaints = item->numRepaints;
+
+ rectItem->setOpacity(1);
+
+ // item should have been rerendered due to opacity changing
+ QTRY_VERIFY(item->numRepaints > numRepaints);
+}
+
+void tst_QGraphicsEffect::dropShadowClipping()
+{
+ QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0xffffffff);
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = new QGraphicsRectItem(-5, -500, 10, 1000);
+ item->setGraphicsEffect(new QGraphicsDropShadowEffect);
+ item->setPen(Qt::NoPen);
+ item->setBrush(Qt::red);
+
+ scene.addItem(item);
+
+ QPainter p(&img);
+ scene.render(&p, img.rect(), QRect(-64, -64, 128, 128));
+ p.end();
+
+ for (int y = 1; y < img.height(); ++y)
+ for (int x = 0; x < img.width(); ++x)
+ QCOMPARE(img.pixel(x, y), img.pixel(x, y-1));
+}
+
+class MyGraphicsItem : public QGraphicsWidget
+{
+public:
+ MyGraphicsItem(QGraphicsItem *parent = 0) :
+ QGraphicsWidget(parent), nbPaint(0)
+ {}
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ nbPaint++;
+ QGraphicsWidget::paint(painter, option, widget);
+ }
+ int nbPaint;
+};
+
+void tst_QGraphicsEffect::childrenVisibilityShouldInvalidateCache()
+{
+ QGraphicsScene scene;
+ MyGraphicsItem parent;
+ parent.resize(200, 200);
+ QGraphicsWidget child(&parent);
+ child.resize(200, 200);
+ child.setVisible(false);
+ scene.addItem(&parent);
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(parent.nbPaint >= 1);
+ //we set an effect on the parent
+ parent.setGraphicsEffect(new QGraphicsDropShadowEffect(&parent));
+ //flush the events
+ QApplication::processEvents();
+ //new effect applied->repaint
+ QVERIFY(parent.nbPaint >= 2);
+ child.setVisible(true);
+ //flush the events
+ QApplication::processEvents();
+ //a new child appears we need to redraw the effect.
+ QVERIFY(parent.nbPaint >= 3);
+}
+
+void tst_QGraphicsEffect::prepareGeometryChangeInvalidateCache()
+{
+ MyGraphicsItem *item = new MyGraphicsItem;
+ item->resize(200, 200);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(item->nbPaint >= 1);
+
+ item->nbPaint = 0;
+ item->setGraphicsEffect(new QGraphicsDropShadowEffect);
+ QTRY_COMPARE(item->nbPaint, 1);
+
+ item->nbPaint = 0;
+ item->resize(300, 300);
+ QTRY_COMPARE(item->nbPaint, 1);
+
+ item->nbPaint = 0;
+ item->setPos(item->pos() + QPointF(10, 10));
+ QTest::qWait(50);
+ QCOMPARE(item->nbPaint, 0);
+}
+
+void tst_QGraphicsEffect::itemHasNoContents()
+{
+ QGraphicsRectItem *parent = new QGraphicsRectItem;
+ parent->setFlag(QGraphicsItem::ItemHasNoContents);
+
+ MyGraphicsItem *child = new MyGraphicsItem;
+ child->setParentItem(parent);
+ child->resize(200, 200);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(child->nbPaint >= 1);
+
+ CustomEffect *effect = new CustomEffect;
+ parent->setGraphicsEffect(effect);
+ QTRY_COMPARE(effect->numRepaints, 1);
+
+ for (int i = 0; i < 3; ++i) {
+ effect->reset();
+ effect->update();
+ QTRY_COMPARE(effect->numRepaints, 1);
+ }
+}
+
+QTEST_MAIN(tst_QGraphicsEffect)
+#include "tst_qgraphicseffect.moc"
+
diff --git a/tests/auto/widgets/graphicsview/graphicsview.pro b/tests/auto/widgets/graphicsview/graphicsview.pro
new file mode 100644
index 0000000000..9955e45b64
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/graphicsview.pro
@@ -0,0 +1,32 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qgraphicsanchorlayout \
+ qgraphicsanchorlayout1 \
+ qgraphicseffectsource \
+ qgraphicsgridlayout \
+ qgraphicsitem \
+ qgraphicsitemanimation \
+ qgraphicslayout \
+ qgraphicslayoutitem \
+ qgraphicslinearlayout \
+ qgraphicsobject \
+ qgraphicspixmapitem \
+ qgraphicspolygonitem \
+ qgraphicsproxywidget \
+ qgraphicsscene \
+ qgraphicssceneindex \
+ qgraphicstransform \
+ qgraphicsview \
+ qgraphicswidget \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qgraphicsanchorlayout \
+ qgraphicsanchorlayout1 \
+ qgraphicsitem \
+ qgraphicsscene \
+ qgraphicssceneindex \
+
+# These tests require the cleanlooks style
+!contains(styles, cleanlooks):SUBDIRS -= \
+ qgraphicsproxywidget \
+ qgraphicswidget \
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
new file mode 100644
index 0000000000..5aa2936e3e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsanchorlayout.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
new file mode 100644
index 0000000000..5dbe501ea8
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
@@ -0,0 +1,2091 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qgraphicsanchorlayout.h>
+#include <private/qgraphicsanchorlayout_p.h>
+#include <QtWidgets/qgraphicswidget.h>
+#include <QtWidgets/qgraphicsproxywidget.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qwindowsstyle.h>
+
+
+class tst_QGraphicsAnchorLayout : public QObject {
+ Q_OBJECT
+
+public:
+ tst_QGraphicsAnchorLayout() : QObject() {
+ hasSimplification = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
+ }
+
+private:
+ bool hasSimplification;
+
+private slots:
+ void simple();
+ void simple_center();
+ void simple_semifloat();
+ void layoutDirection();
+ void diagonal();
+ void parallel();
+ void parallel2();
+ void snake();
+ void snakeOppositeDirections();
+ void fairDistribution();
+ void fairDistributionOppositeDirections();
+ void proportionalPreferred();
+ void example();
+ void setSpacing();
+ void styleDefaults();
+ void hardComplexS60();
+ void stability();
+ void delete_anchor();
+ void conflicts();
+ void sizePolicy();
+ void floatConflict();
+ void infiniteMaxSizes();
+ void simplifiableUnfeasible();
+ void simplificationVsOrder();
+ void parallelSimplificationOfCenter();
+ void simplificationVsRedundance();
+ void spacingPersistency();
+ void snakeParallelWithLayout();
+ void parallelToHalfLayout();
+ void globalSpacing();
+ void graphicsAnchorHandling();
+ void invalidHierarchyCheck();
+};
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent){}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+};
+
+static QGraphicsWidget *createItem(const QSizeF &minimum = QSizeF(100.0, 100.0),
+ const QSizeF &preferred = QSize(150.0, 100.0),
+ const QSizeF &maximum = QSizeF(200.0, 100.0),
+ const QString &name = QString())
+{
+ QGraphicsWidget *w = new RectWidget;
+ w->setMinimumSize(minimum);
+ w->setPreferredSize(preferred);
+ w->setMaximumSize(maximum);
+ w->setData(0, name);
+ return w;
+}
+
+static void setAnchor(QGraphicsAnchorLayout *l,
+ QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ qreal spacing = 0)
+{
+ QGraphicsAnchor *anchor = l->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
+ anchor->setSpacing(spacing);
+}
+
+static bool checkReverseDirection(QGraphicsWidget *widget)
+{
+ QGraphicsLayout *layout = widget->layout();
+ qreal left, top, right, bottom;
+ layout->getContentsMargins(&left, &top, &right, &bottom);
+ widget->setLayoutDirection(Qt::LeftToRight);
+ QApplication::processEvents();
+ const QRectF layoutGeometry = layout->geometry();
+ QMap<QGraphicsLayoutItem *, QRectF> geometries;
+ for (int i = 0; i < layout->count(); ++i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ geometries.insert(item, item->geometry());
+ }
+ widget->setLayoutDirection(Qt::RightToLeft);
+ QApplication::processEvents();
+ layoutGeometry.adjusted(+right, +top, -left, -bottom);
+ for (int i = 0; i < layout->count(); ++i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ const QRectF rightToLeftGeometry = item->geometry();
+ const QRectF leftToRightGeometry = geometries.value(item);
+ QRectF expectedGeometry = leftToRightGeometry;
+ expectedGeometry.moveRight(layoutGeometry.right() - leftToRightGeometry.left());
+ if (expectedGeometry != rightToLeftGeometry) {
+ qDebug() << "layout->geometry():" << layoutGeometry
+ << "expected:" << expectedGeometry
+ << "actual:" << rightToLeftGeometry;
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool layoutHasConflict(QGraphicsAnchorLayout *l)
+{
+ return QGraphicsAnchorLayoutPrivate::get(l)->hasConflicts();
+}
+
+static bool usedSimplex(QGraphicsAnchorLayout *l, Qt::Orientation o)
+{
+ QGraphicsAnchorLayoutPrivate::Orientation oo = (o == Qt::Horizontal) ?
+ QGraphicsAnchorLayoutPrivate::Horizontal :
+ QGraphicsAnchorLayoutPrivate::Vertical;
+
+ return QGraphicsAnchorLayoutPrivate::get(l)->lastCalculationUsedSimplex[oo];
+}
+
+void tst_QGraphicsAnchorLayout::simple()
+{
+ QGraphicsWidget *w1 = createItem();
+ QGraphicsWidget *w2 = createItem();
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // Horizontal
+ l->addAnchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft);
+ l->addAnchor(w1, Qt::AnchorRight, w2, Qt::AnchorLeft);
+ l->addAnchor(w2, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ // Vertical
+ l->addAnchors(l, w1, Qt::Vertical);
+ l->addAnchors(l, w2, Qt::Vertical);
+
+ QCOMPARE(l->count(), 2);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+ p.adjustSize();
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::simple_center()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "c");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
+ setAnchor(l, b, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+ setAnchor(l, a, Qt::AnchorHorizontalCenter, c, Qt::AnchorLeft, 0);
+ setAnchor(l, c, Qt::AnchorRight, b, Qt::AnchorHorizontalCenter, 0);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, a, Qt::AnchorTop, 0);
+ setAnchor(l, l, Qt::AnchorTop, b, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, b, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, c, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QCOMPARE(layoutMinimumSize, QSizeF(20, 20));
+
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QCOMPARE(layoutMaximumSize, QSizeF(200, 20));
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::simple_semifloat()
+{
+ // Useful for testing simplification between A_left and B_left.
+ // Unfortunately the only way to really test that now is to manually inspect the
+ // simplified graph.
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *A = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *B = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, A, Qt::AnchorLeft, 0);
+ setAnchor(l, A, Qt::AnchorRight, B, Qt::AnchorLeft, 0);
+ setAnchor(l, B, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+
+ setAnchor(l, A, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, B, Qt::AnchorLeft, b, Qt::AnchorLeft, 0);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, A, Qt::AnchorTop, 0);
+ setAnchor(l, l, Qt::AnchorTop, B, Qt::AnchorTop, 0);
+ setAnchor(l, A, Qt::AnchorBottom, a, Qt::AnchorTop, 0);
+ setAnchor(l, B, Qt::AnchorBottom, b, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+ setAnchor(l, b, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+
+ QCOMPARE(l->count(), 4);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QCOMPARE(layoutMinimumSize, QSizeF(20, 20));
+
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(100, 20));
+
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QCOMPARE(layoutMaximumSize, QSizeF(200, 20));
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::layoutDirection()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, QSizeF(100, 20), "c");
+
+ a->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ c->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 5, 10, 15);
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
+ setAnchor(l, b, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+ setAnchor(l, a, Qt::AnchorHorizontalCenter, c, Qt::AnchorLeft, 0);
+ setAnchor(l, c, Qt::AnchorRight, b, Qt::AnchorHorizontalCenter, 0);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, a, Qt::AnchorTop, 0);
+ setAnchor(l, l, Qt::AnchorTop, b, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, b, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, c, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayoutDirection(Qt::LeftToRight);
+ p->setLayout(l);
+
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ scene.addItem(p);
+ p->show();
+ view->show();
+
+ QVERIFY(p->layout());
+ QCOMPARE(checkReverseDirection(p), true);
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ delete p;
+ delete view;
+}
+
+void tst_QGraphicsAnchorLayout::diagonal()
+{
+ QSizeF minSize(10, 100);
+ QSizeF pref(70, 100);
+ QSizeF maxSize(100, 100);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "D");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "E");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ // vertical
+ l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ // horizontal
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ QCOMPARE(l->count(), 5);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(30.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(170.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 10.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(10.0, 0.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(10.0, 100.0, 10.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 20.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(20.0, 200.0, 10.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 70.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(70.0, 0.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(70.0, 100.0, 30.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 100.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(100.0, 200.0, 70.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 90.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(90.0, 0.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(90.0, 100.0, 10.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 100.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(100.0, 200.0, 90.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QSizeF testA(175.0, 300.0);
+ p.resize(testA);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 75.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(75.0, 0.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(75.0, 100.0, 25.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 100.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(100.0, 200.0, 75.0, 100.0));
+ QCOMPARE(p.size(), testA);
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ QVERIFY(p.layout());
+ QCOMPARE(checkReverseDirection(&p), true);
+
+ c->setMinimumWidth(300);
+ QVERIFY(layoutHasConflict(l));
+}
+
+void tst_QGraphicsAnchorLayout::parallel()
+{
+ QGraphicsWidget *a = createItem(QSizeF(100, 100),
+ QSizeF(150, 100),
+ QSizeF(200, 100), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(100, 100),
+ QSizeF(150, 100),
+ QSizeF(300, 100), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(100, 100),
+ QSizeF(200, 100),
+ QSizeF(350, 100), "C");
+
+ QGraphicsWidget *d = createItem(QSizeF(100, 100),
+ QSizeF(170, 100),
+ QSizeF(200, 100), "D");
+
+ QGraphicsWidget *e = createItem(QSizeF(150, 100),
+ QSizeF(150, 100),
+ QSizeF(200, 100), "E");
+
+ QGraphicsWidget *f = createItem(QSizeF(100, 100),
+ QSizeF(150, 100),
+ QSizeF(200, 100), "F");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, e, Qt::AnchorTop);
+ l->addAnchor(e, Qt::AnchorBottom, f, Qt::AnchorTop);
+ l->addAnchor(f, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, d, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, e, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, f, Qt::AnchorLeft);
+ l->addAnchor(d, Qt::AnchorRight, f, Qt::AnchorLeft);
+ l->addAnchor(e, Qt::AnchorRight, f, Qt::AnchorLeft);
+ l->addAnchor(f, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 6);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(450, 600));
+ QCOMPARE(layoutPreferredSize, QSizeF(620, 600));
+ QCOMPARE(layoutMaximumSize, QSizeF(750, 600));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(b->geometry(), QRectF(100, 100, 100, 100));
+ QCOMPARE(c->geometry(), QRectF(100, 200, 250, 100));
+ QCOMPARE(d->geometry(), QRectF(200, 300, 150, 100));
+ QCOMPARE(e->geometry(), QRectF(200, 400, 150, 100));
+ QCOMPARE(f->geometry(), QRectF(350, 500, 100, 100));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ if (!hasSimplification)
+ return;
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 150, 100));
+ QCOMPARE(b->geometry(), QRectF(150, 100, 150, 100));
+ QCOMPARE(c->geometry(), QRectF(150, 200, 320, 100));
+ QCOMPARE(d->geometry(), QRectF(300, 300, 170, 100));
+ QCOMPARE(e->geometry(), QRectF(300, 400, 170, 100));
+ QCOMPARE(f->geometry(), QRectF(470, 500, 150, 100));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ // Maximum size depends on simplification / fair distribution
+ // Without that, test may or may not pass, depending on the
+ // solution found by the solver at runtime.
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 200, 100));
+ QCOMPARE(b->geometry(), QRectF(200, 100, 175, 100));
+ QCOMPARE(c->geometry(), QRectF(200, 200, 350, 100));
+ QCOMPARE(d->geometry(), QRectF(375, 300, 175, 100));
+ QCOMPARE(e->geometry(), QRectF(375, 400, 175, 100));
+ QCOMPARE(f->geometry(), QRectF(550, 500, 200, 100));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+}
+
+void tst_QGraphicsAnchorLayout::parallel2()
+{
+ QGraphicsWidget *a = createItem(QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0),
+ QSizeF(200.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(100.0, 100.0),
+ QSizeF(150.0, 100.0),
+ QSizeF(190.0, 100.0), "B");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchors(l, a, Qt::Horizontal);
+ l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 2);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(100.0, 200.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(150.0, 200.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 200.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::snake()
+{
+ QGraphicsWidget *a = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(20.0, 100.0),
+ QSizeF(40.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight);
+ l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(120.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 50.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(10.0, 100.0, 40.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(10.0, 200.0, 50.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 70.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(50.0, 100.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(50.0, 200.0, 70.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 100.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(90.0, 100.0, 10.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(90.0, 200.0, 100.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(layoutHasConflict(l) == false);
+
+ // Test QSizePolicy::ExpandFlag, it shouldn't change the extreme
+ // points of the layout...
+ b->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ QSizeF newLayoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF newLayoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF newLayoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, newLayoutMinimumSize);
+ QCOMPARE(layoutMaximumSize, newLayoutMaximumSize);
+ QCOMPARE(layoutPreferredSize, newLayoutPreferredSize);
+}
+
+void tst_QGraphicsAnchorLayout::snakeOppositeDirections()
+{
+ QGraphicsWidget *a = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(20.0, 100.0),
+ QSizeF(40.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+
+ // Both a and c are 'pointing' to b
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorLeft, b, Qt::AnchorLeft);
+
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(120.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 50.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(10.0, 100.0, 40.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(10.0, 200.0, 50.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 70.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(50.0, 100.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(50.0, 200.0, 70.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 100.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(90.0, 100.0, 10.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(90.0, 200.0, 100.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(p.layout());
+ QCOMPARE(checkReverseDirection(&p), true);
+}
+
+void tst_QGraphicsAnchorLayout::fairDistribution()
+{
+ QGraphicsWidget *a = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsWidget *d = createItem(QSizeF(60.0, 100.0),
+ QSizeF(165.0, 100.0),
+ QSizeF(600.0, 100.0), "D");
+
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
+ l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 4);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 400.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(165.0, 400.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(300.0, 400.0));
+
+ p.resize(layoutMinimumSize);
+ if (!hasSimplification)
+ QEXPECT_FAIL("", "Without simplification there is no fair distribution.", Abort);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 20.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(20.0, 100.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(40.0, 200.0, 20.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 300.0, 60.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 55.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(55.0, 100.0, 55.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(110.0, 200.0, 55.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 300.0, 165.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 100.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(100.0, 100.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(200.0, 200.0, 100.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 300.0, 300.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::fairDistributionOppositeDirections()
+{
+ QGraphicsWidget *a = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsWidget *d = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "D");
+
+ QGraphicsWidget *e = createItem(QSizeF(60.0, 100.0),
+ QSizeF(220.0, 100.0),
+ QSizeF(600.0, 100.0), "E");
+
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, e, Qt::AnchorTop);
+ l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(a, Qt::AnchorLeft, l, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorLeft, a, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorLeft, b, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorLeft, c, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchors(l, e, Qt::Horizontal);
+
+ QCOMPARE(l->count(), 5);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 500.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(220.0, 500.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(400.0, 500.0));
+
+ if (!hasSimplification)
+ return;
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->size(), b->size());
+ QCOMPARE(a->size(), c->size());
+ QCOMPARE(a->size(), d->size());
+ QCOMPARE(e->size().width(), 4 * a->size().width());
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->size(), b->size());
+ QCOMPARE(a->size(), c->size());
+ QCOMPARE(a->size(), d->size());
+ QCOMPARE(e->size().width(), 4 * a->size().width());
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->size(), b->size());
+ QCOMPARE(a->size(), c->size());
+ QCOMPARE(a->size(), d->size());
+ QCOMPARE(e->size().width(), 4 * a->size().width());
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+}
+
+void tst_QGraphicsAnchorLayout::proportionalPreferred()
+{
+ QSizeF minSize(0, 100);
+
+ QGraphicsWidget *a = createItem(minSize, QSizeF(10, 100), QSizeF(20, 100), "A");
+ QGraphicsWidget *b = createItem(minSize, QSizeF(20, 100), QSizeF(30, 100), "B");
+ QGraphicsWidget *c = createItem(minSize, QSizeF(14, 100), QSizeF(20, 100), "C");
+ QGraphicsWidget *d = createItem(minSize, QSizeF(10, 100), QSizeF(20, 100), "D");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, d, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 4);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(0, 400));
+ QCOMPARE(layoutPreferredSize, QSizeF(24, 400));
+ QCOMPARE(layoutMaximumSize, QSizeF(30, 400));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(c->size().width(), d->size().width());
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ p.resize(QSizeF(12, 400));
+
+ // Proportionality between size given and preferred size, this
+ // should be respected in this graph for (a) and (b)|(c).
+ qreal factor = 12.0 / 24.0;
+
+ QCOMPARE(c->size().width(), d->size().width());
+ QCOMPARE(a->size().width(), 10 * factor);
+ QCOMPARE(c->size().width(), 14 * factor);
+ QCOMPARE(p.size(), QSizeF(12, 400));
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::example()
+{
+ QSizeF minSize(30, 100);
+ QSizeF pref(210, 100);
+ QSizeF maxSize(300, 100);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "D");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "E");
+ QGraphicsWidget *f = createItem(QSizeF(30, 50), QSizeF(150, 50), maxSize, "F");
+ QGraphicsWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ // vertical
+ l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop);
+
+ l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop);
+
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom);
+ l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom);
+
+ // horizontal
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft);
+ l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 7);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(90.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(510.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(570.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(p.size(), layoutMinimumSize);
+ QCOMPARE(a->size(), e->size());
+ QCOMPARE(b->size(), d->size());
+ QCOMPARE(f->size(), g->size());
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(p.size(), layoutPreferredSize);
+ QCOMPARE(a->size(), e->size());
+ QCOMPARE(b->size(), d->size());
+ QCOMPARE(f->size(), g->size());
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(p.size(), layoutMaximumSize);
+ QCOMPARE(a->size(), e->size());
+ QCOMPARE(b->size(), d->size());
+ QCOMPARE(f->size(), g->size());
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::setSpacing()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 20);
+ QSizeF maxSize(50, 50);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize);
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize);
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize);
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->addCornerAnchors(l, Qt::TopLeftCorner, a, Qt::TopLeftCorner);
+ l->addCornerAnchors(b, Qt::TopRightCorner, l, Qt::TopRightCorner);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ l->addAnchors(l, c, Qt::Horizontal);
+
+ l->addAnchor(a, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+
+ p->setLayout(l);
+ l->setSpacing(1);
+
+ // don't let the style influence the test.
+ l->setContentsMargins(0, 0, 0, 0);
+
+ QGraphicsScene scene;
+ scene.addItem(p);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->show();
+ p->show();
+
+ QApplication::processEvents();
+#ifdef Q_WS_MAC
+ QTest::qWait(200);
+#endif
+
+ // 21x21
+ QCOMPARE(p->size(), QSizeF(41, 41));
+ QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(21, 0, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(0, 21, 41, 20));
+
+ l->setHorizontalSpacing(4);
+ QApplication::processEvents();
+ p->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(24, 0, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(0, 21, 44, 20));
+
+ l->setVerticalSpacing(0);
+ QApplication::processEvents();
+ p->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(24, 0, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(0, 20, 44, 20));
+
+ delete p;
+ delete view;
+}
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+
+protected slots:
+ int layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption *option = 0,
+ const QWidget *widget = 0) const;
+
+};
+
+#define CT1(c) CT2(c, c)
+#define CT2(c1, c2) ((uint)c1 << 16) | (uint)c2
+
+int CustomLayoutStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption * /*option = 0*/,
+ const QWidget * /*widget = 0*/) const
+{
+ if (orientation == Qt::Horizontal) {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::PushButton):
+ return 2;
+ break;
+ }
+ return 5;
+ } else {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::RadioButton):
+ return 2;
+ break;
+
+ }
+ return 10;
+ }
+}
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ break;
+ case PM_LayoutTopMargin:
+ return 3;
+ break;
+ case PM_LayoutRightMargin:
+ return 6;
+ break;
+ case PM_LayoutBottomMargin:
+ return 9;
+ break;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+void tst_QGraphicsAnchorLayout::styleDefaults()
+{
+ QSizeF minSize (10, 10);
+ QSizeF pref(20, 20);
+ QSizeF maxSize (50, 50);
+
+ /*
+ create this layout, where a,b have controlType QSizePolicy::RadioButton
+ c,d have controlType QSizePolicy::PushButton:
+ +-------+
+ |a |
+ | b |
+ | c |
+ | d|
+ +-------+
+ */
+ QGraphicsScene scene;
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize);
+ QSizePolicy spRadioButton = a->sizePolicy();
+ spRadioButton.setControlType(QSizePolicy::RadioButton);
+ a->setSizePolicy(spRadioButton);
+
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize);
+ b->setSizePolicy(spRadioButton);
+
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize);
+ QSizePolicy spPushButton = c->sizePolicy();
+ spPushButton.setControlType(QSizePolicy::PushButton);
+ c->setSizePolicy(spPushButton);
+
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize);
+ d->setSizePolicy(spPushButton);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+
+ // Test layoutSpacingImplementation
+ CustomLayoutStyle *style = new CustomLayoutStyle;
+ style->hspacing = -1;
+ style->vspacing = -1;
+ window->setStyle(style);
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+
+ l->addCornerAnchors(l, Qt::TopLeftCorner, a, Qt::TopLeftCorner);
+ l->addCornerAnchors(a, Qt::BottomRightCorner, b, Qt::TopLeftCorner);
+ l->addCornerAnchors(b, Qt::BottomRightCorner, c, Qt::TopLeftCorner);
+ l->addCornerAnchors(c, Qt::BottomRightCorner, d, Qt::TopLeftCorner);
+ l->addCornerAnchors(d, Qt::BottomRightCorner, l, Qt::BottomRightCorner);
+
+ window->setLayout(l);
+
+ scene.addItem(window);
+
+ window->show();
+ QGraphicsView view(&scene);
+ view.resize(200, 200);
+ view.show();
+
+ window->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 3, 20, 20)); //radio
+ QCOMPARE(b->geometry(), QRectF(25, 25, 20, 20)); //radio
+ QCOMPARE(c->geometry(), QRectF(50, 55, 20, 20)); //push
+ QCOMPARE(d->geometry(), QRectF(72, 85, 20, 20)); //push
+ QCOMPARE(l->geometry(), QRectF(0, 0, 98, 114));
+
+
+ // Test pixelMetric(PM_Layout{Horizontal|Vertical}Spacing
+ window->setStyle(0);
+
+ style->hspacing = 1;
+ style->vspacing = 2;
+
+ window->setStyle(style);
+ window->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 3, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(21, 25, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(42, 47, 20, 20));
+ QCOMPARE(d->geometry(), QRectF(63, 69, 20, 20));
+ QCOMPARE(l->geometry(), QRectF(0, 0, 89, 98));
+
+ window->setStyle(0);
+ delete style;
+}
+
+
+/*!
+ Taken from "hard" complex case, found at
+ https://cwiki.nokia.com/S60QTUI/AnchorLayoutComplexCases
+
+ This layout has a special property, since it has two possible solutions for its minimum size.
+
+ For instance, when it is in its minimum size - the layout have two possible solutions:
+ 1. c.width == 10, e.width == 10 and g.width == 10
+ (all others have width 0)
+ 2. d.width == 10 and g.width == 10
+ (all others have width 0)
+
+ It also has several solutions for preferred size.
+*/
+static QGraphicsAnchorLayout *createAmbiguousS60Layout()
+{
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ QSizeF minSize(0, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "c");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "d");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "e");
+ QGraphicsWidget *f = createItem(minSize, pref, maxSize, "f");
+ QGraphicsWidget *g = createItem(minSize, pref, maxSize, "g");
+
+ //<!-- Trunk -->
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 10);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 10);
+ setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft, 10);
+ setAnchor(l, c, Qt::AnchorRight, d, Qt::AnchorLeft, 10);
+ setAnchor(l, d, Qt::AnchorRight, l, Qt::AnchorRight, 10);
+
+ //<!-- Above trunk -->
+ setAnchor(l, b, Qt::AnchorLeft, e, Qt::AnchorLeft, 10);
+ setAnchor(l, e, Qt::AnchorRight, d, Qt::AnchorLeft, 10);
+
+ //<!-- Below trunk -->
+ setAnchor(l, a, Qt::AnchorHorizontalCenter, g, Qt::AnchorLeft, 10);
+ setAnchor(l, g, Qt::AnchorRight, f, Qt::AnchorHorizontalCenter, 10);
+ setAnchor(l, c, Qt::AnchorLeft, f, Qt::AnchorLeft, 10);
+ setAnchor(l, f, Qt::AnchorRight, d, Qt::AnchorRight, 10);
+
+ //<!-- vertical is simpler -->
+ setAnchor(l, l, Qt::AnchorTop, e, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, a, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, b, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, d, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, f, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, b, Qt::AnchorBottom, 0);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorBottom, 0);
+ setAnchor(l, a, Qt::AnchorBottom, d, Qt::AnchorBottom, 0);
+ setAnchor(l, f, Qt::AnchorBottom, g, Qt::AnchorTop, 0);
+ setAnchor(l, g, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+ return l;
+}
+
+void tst_QGraphicsAnchorLayout::hardComplexS60()
+{
+ QGraphicsAnchorLayout *l = createAmbiguousS60Layout();
+ QCOMPARE(l->count(), 7);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QCOMPARE(layoutMinimumSize, QSizeF(60, 40));
+ // expected preferred might be wrong, (haven't manually verified it)
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QCOMPARE(layoutPreferredSize, QSizeF(220, 40));
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QCOMPARE(layoutMaximumSize, QSizeF(240, 40));
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::stability()
+{
+ QVector<QRectF> geometries;
+ geometries.resize(7);
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ bool sameAsPreviousArrangement = true;
+ // it usually fails after 3-4 iterations
+ for (int pass = 0; pass < 20 && sameAsPreviousArrangement; ++pass) {
+ // In case we need to "scramble" the heap allocator to provoke this bug.
+ //static const int primes[] = {2, 3, 5, 13, 89, 233, 1597, 28657, 514229}; // fibo primes
+ //const int primeCount = sizeof(primes)/sizeof(int);
+ //int alloc = primes[pass % primeCount] + pass;
+ //void *mem = qMalloc(alloc);
+ //qFree(mem);
+ QGraphicsAnchorLayout *l = createAmbiguousS60Layout();
+ p->setLayout(l);
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ l->setGeometry(QRectF(QPointF(0,0), layoutMinimumSize));
+ QApplication::processEvents();
+ for (int i = l->count() - 1; i >=0 && sameAsPreviousArrangement; --i) {
+ QRectF geom = l->itemAt(i)->geometry();
+ if (pass != 0) {
+ sameAsPreviousArrangement = (geometries[i] == geom);
+ }
+ geometries[i] = geom;
+ }
+ p->setLayout(0); // uninstalls and deletes the layout
+ QApplication::processEvents();
+ }
+ delete p;
+ QEXPECT_FAIL("", "The layout have several solutions, but which solution it picks is not stable", Continue);
+ QCOMPARE(sameAsPreviousArrangement, true);
+}
+
+void tst_QGraphicsAnchorLayout::delete_anchor()
+{
+ QGraphicsScene scene;
+ QSizeF minSize(0, 0);
+ QSizeF prefSize(50, 50);
+ QSizeF maxSize(100, 100);
+ QGraphicsWidget *w1 = createItem(minSize, prefSize, maxSize, "w1");
+ QGraphicsWidget *w2 = createItem(minSize, prefSize, maxSize, "w2");
+ QGraphicsWidget *w3 = createItem(minSize, prefSize, maxSize, "w3");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setSpacing(0);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // Horizontal
+ l->addAnchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft);
+ l->addAnchor(w1, Qt::AnchorRight, w2, Qt::AnchorLeft);
+ l->addAnchor(w2, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(w1, Qt::AnchorRight, w3, Qt::AnchorLeft);
+ l->addAnchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ // Vertical
+ l->addAnchors(l, w1, Qt::Vertical);
+ l->addAnchors(l, w2, Qt::Vertical);
+ l->addAnchors(l, w3, Qt::Vertical);
+
+ QGraphicsAnchor *anchor = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+ anchor->setSpacing(10);
+
+ QGraphicsWidget *p = new QGraphicsWidget;
+ p->setLayout(l);
+
+ QCOMPARE(l->count(), 3);
+
+ scene.addItem(p);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QApplication::processEvents();
+ // Should now be simplified
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize).width(), qreal(110));
+ QGraphicsAnchor *anchor1 = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+ QVERIFY(anchor1);
+ QGraphicsAnchor *anchor2 = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+ QVERIFY(anchor2);
+ QGraphicsAnchor *anchor3 = l->anchor(l, Qt::AnchorRight, w3, Qt::AnchorRight);
+ QVERIFY(anchor3);
+ QGraphicsAnchor *anchor4 = l->anchor(l, Qt::AnchorRight, w3, Qt::AnchorRight);
+ QVERIFY(anchor4);
+
+ // should all be the same object
+ QCOMPARE(anchor1, anchor2);
+ QCOMPARE(anchor2, anchor3);
+ QCOMPARE(anchor3, anchor4);
+
+ // check if removal works
+ delete anchor1;
+
+ QApplication::processEvents();
+
+ // it should also change the preferred size of the layout
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize).width(), qreal(100));
+
+ delete p;
+ delete view;
+}
+
+void tst_QGraphicsAnchorLayout::sizePolicy()
+{
+ QGraphicsScene scene;
+ QSizeF minSize(0, 0);
+ QSizeF prefSize(50, 50);
+ QSizeF maxSize(100, 100);
+ QGraphicsWidget *w1 = createItem(minSize, prefSize, maxSize, "w1");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setSpacing(0);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // horizontal and vertical
+ l->addAnchors(l, w1);
+
+ QGraphicsWidget *p = new QGraphicsWidget;
+ p->setLayout(l);
+
+ scene.addItem(p);
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ // QSizePolicy::Minimum
+ w1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(100, 100));
+
+ // QSizePolicy::Maximum
+ w1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(50, 50));
+
+ // QSizePolicy::Fixed
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(50, 50));
+
+ // QSizePolicy::Preferred
+ w1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(100, 100));
+
+ // QSizePolicy::Ignored
+ w1->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(100, 100));
+
+ // Anchor size policies
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QGraphicsAnchor *anchor = l->anchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft);
+ anchor->setSpacing(10);
+
+ // QSizePolicy::Minimum
+ anchor->setSizePolicy(QSizePolicy::Minimum);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(60, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 50));
+ // The layout has a maximum size of QWIDGETSIZE_MAX, so the result won't exceed that value.
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(QWIDGETSIZE_MAX, 50));
+
+ // QSizePolicy::Preferred
+ anchor->setSizePolicy(QSizePolicy::Preferred);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 50));
+ // The layout has a maximum size of QWIDGETSIZE_MAX, so the result won't exceed that value.
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(QWIDGETSIZE_MAX, 50));
+
+ // QSizePolicy::Maximum
+ anchor->setSizePolicy(QSizePolicy::Maximum);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(60, 50));
+
+ // QSizePolicy::Ignored
+ anchor->setSizePolicy(QSizePolicy::Ignored);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(QWIDGETSIZE_MAX, 50));
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ delete p;
+ delete view;
+}
+
+/*!
+ \internal
+
+ Uses private API. (We have decided to pull hasConflicts() out of the API). However, it also
+ tests some tight conditions (almost-in-conflict) that we really want to test.
+*/
+void tst_QGraphicsAnchorLayout::conflicts()
+{
+ QGraphicsWidget *a = createItem(QSizeF(80,10), QSizeF(90,10), QSizeF(100,10), "a");
+ QGraphicsWidget *b = createItem(QSizeF(10,10), QSizeF(20,10), QSizeF(30,10), "b");
+ QGraphicsWidget *c = createItem(QSizeF(10,10), QSizeF(20,10), QSizeF(30,10), "c");
+
+ QGraphicsAnchorLayout *l;
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+
+ l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // with the following setup, 'a' cannot be larger than 30 we will first have a Simplex conflict
+
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft);
+ setAnchor(l, c, Qt::AnchorRight, l, Qt::AnchorRight);
+ setAnchor(l, b, Qt::AnchorHorizontalCenter, a, Qt::AnchorLeft);
+ setAnchor(l, a, Qt::AnchorRight, c, Qt::AnchorHorizontalCenter);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, a, Qt::AnchorTop);
+ setAnchor(l, a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorTop);
+ setAnchor(l, b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ setAnchor(l, c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ p->setLayout(l);
+
+ QCOMPARE(layoutHasConflict(l), true);
+
+ a->setMinimumSize(QSizeF(29,10));
+ QCOMPARE(layoutHasConflict(l), false);
+
+ a->setMinimumSize(QSizeF(30,10));
+ QCOMPARE(layoutHasConflict(l), false);
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::floatConflict()
+{
+ QGraphicsWidget *a = createItem(QSizeF(80,10), QSizeF(90,10), QSizeF(100,10), "a");
+ QGraphicsWidget *b = createItem(QSizeF(80,10), QSizeF(90,10), QSizeF(100,10), "b");
+
+ QGraphicsAnchorLayout *l;
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+
+ l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ p->setLayout(l);
+
+ // horizontal
+ // with this anchor we have two floating items
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ // Just checking if the layout is handling well the removal of floating items
+ delete l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ QCOMPARE(l->count(), 0);
+ QCOMPARE(layoutHasConflict(l), false);
+
+ // setting back the same anchor
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ // We don't support floating items but they should be counted as if they are in the layout
+ QCOMPARE(l->count(), 2);
+ // Although, we have an invalid situation
+ QCOMPARE(layoutHasConflict(l), true);
+
+ // Semi-floats are supported
+ setAnchor(l, a, Qt::AnchorLeft, l, Qt::AnchorLeft);
+ QCOMPARE(l->count(), 2);
+
+ // Vertically the layout has floating items. Therefore, we have a conflict
+ QCOMPARE(layoutHasConflict(l), true);
+
+ // No more floating items
+ setAnchor(l, b, Qt::AnchorRight, l, Qt::AnchorRight);
+ setAnchor(l, a, Qt::AnchorTop, l, Qt::AnchorTop);
+ setAnchor(l, a, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ setAnchor(l, b, Qt::AnchorTop, l, Qt::AnchorTop);
+ setAnchor(l, b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ QCOMPARE(layoutHasConflict(l), false);
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::infiniteMaxSizes()
+{
+ if (sizeof(qreal) <= 4) {
+ QSKIP("qreal has too little precision, result will be wrong", SkipAll);
+ }
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(QWIDGETSIZE_MAX, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "c");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "d");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "e");
+
+ //<!-- Trunk -->
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
+ setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft, 0);
+ setAnchor(l, c, Qt::AnchorRight, d, Qt::AnchorLeft, 0);
+ setAnchor(l, d, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+ setAnchor(l, b, Qt::AnchorHorizontalCenter, e, Qt::AnchorLeft, 0);
+ setAnchor(l, e, Qt::AnchorRight, c, Qt::AnchorHorizontalCenter, 0);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QCOMPARE(int(p.effectiveSizeHint(Qt::MaximumSize).width()),
+ QWIDGETSIZE_MAX);
+
+ p.resize(200, 10);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 50, 10));
+ QCOMPARE(b->geometry(), QRectF(50, 0, 50, 10));
+ QCOMPARE(c->geometry(), QRectF(100, 0, 50, 10));
+ QCOMPARE(d->geometry(), QRectF(150, 0, 50, 10));
+
+ p.resize(1000, 10);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 250, 10));
+ QCOMPARE(b->geometry(), QRectF(250, 0, 250, 10));
+ QCOMPARE(c->geometry(), QRectF(500, 0, 250, 10));
+ QCOMPARE(d->geometry(), QRectF(750, 0, 250, 10));
+
+ p.resize(40000, 10);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 10000, 10));
+ QCOMPARE(b->geometry(), QRectF(10000, 0, 10000, 10));
+ QCOMPARE(c->geometry(), QRectF(20000, 0, 10000, 10));
+ QCOMPARE(d->geometry(), QRectF(30000, 0, 10000, 10));
+}
+
+void tst_QGraphicsAnchorLayout::simplifiableUnfeasible()
+{
+ QGraphicsWidget *a = createItem(QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(110.0, 100.0),
+ QSizeF(150.0, 100.0),
+ QSizeF(190.0, 100.0), "B");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchors(l, a, Qt::Horizontal);
+ l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 2);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ l->invalidate();
+ QVERIFY(layoutHasConflict(l));
+ if (hasSimplification)
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+
+ // Now we make it valid
+ b->setMinimumWidth(100);
+
+ l->invalidate();
+ QVERIFY(!layoutHasConflict(l));
+ if (hasSimplification)
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+
+ // And make it invalid again
+ a->setPreferredWidth(70);
+ a->setMaximumWidth(70);
+
+ l->invalidate();
+ QVERIFY(layoutHasConflict(l));
+ if (hasSimplification)
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+}
+
+/*
+ Test whether the anchor direction can prevent it from
+ being simplificated
+*/
+void tst_QGraphicsAnchorLayout::simplificationVsOrder()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 10);
+ QSizeF maxSize(50, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+
+ QGraphicsWidget frame;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&frame);
+
+ // Bulk anchors
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ // Problematic anchor, direction b->c
+ QGraphicsAnchor *anchor = l->addAnchor(b, Qt::AnchorRight, c, Qt::AnchorRight);
+ anchor->setSpacing(5);
+
+ l->effectiveSizeHint(Qt::MinimumSize);
+ if (hasSimplification) {
+ QCOMPARE(usedSimplex(l, Qt::Horizontal), false);
+ QCOMPARE(usedSimplex(l, Qt::Vertical), false);
+ }
+
+ // Problematic anchor, direction c->b
+ delete anchor;
+ anchor = l->addAnchor(c, Qt::AnchorRight, b, Qt::AnchorRight);
+ anchor->setSpacing(5);
+
+ l->effectiveSizeHint(Qt::MinimumSize);
+ if (hasSimplification) {
+ QCOMPARE(usedSimplex(l, Qt::Horizontal), false);
+ QCOMPARE(usedSimplex(l, Qt::Vertical), false);
+ }
+}
+
+void tst_QGraphicsAnchorLayout::parallelSimplificationOfCenter()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 10);
+ QSizeF maxSize(50, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+
+ QGraphicsWidget parent;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&parent);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ l->addAnchor(a, Qt::AnchorHorizontalCenter, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ parent.resize(l->effectiveSizeHint(Qt::PreferredSize));
+
+ QCOMPARE(a->geometry(), QRectF(0, 0, 40, 10));
+ QCOMPARE(b->geometry(), QRectF(20, 0, 20, 10));
+}
+
+/*
+ Test whether redundance of anchors (in this case by using addCornerAnchors), will
+ prevent simplification to take place when it should.
+*/
+void tst_QGraphicsAnchorLayout::simplificationVsRedundance()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 10);
+ QSizeF maxSize(50, 30);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+
+ QGraphicsWidget frame;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&frame);
+
+ l->addCornerAnchors(a, Qt::TopLeftCorner, l, Qt::TopLeftCorner);
+ l->addCornerAnchors(a, Qt::BottomLeftCorner, l, Qt::BottomLeftCorner);
+
+ l->addCornerAnchors(b, Qt::TopLeftCorner, a, Qt::TopRightCorner);
+ l->addCornerAnchors(b, Qt::TopRightCorner, l, Qt::TopRightCorner);
+
+ l->addCornerAnchors(c, Qt::TopLeftCorner, b, Qt::BottomLeftCorner);
+ l->addCornerAnchors(c, Qt::BottomLeftCorner, a, Qt::BottomRightCorner);
+ l->addCornerAnchors(c, Qt::TopRightCorner, b, Qt::BottomRightCorner);
+ l->addCornerAnchors(c, Qt::BottomRightCorner, l, Qt::BottomRightCorner);
+
+ l->effectiveSizeHint(Qt::MinimumSize);
+
+ QCOMPARE(layoutHasConflict(l), false);
+
+ if (!hasSimplification)
+ QEXPECT_FAIL("", "Test depends on simplification.", Abort);
+
+ QCOMPARE(usedSimplex(l, Qt::Horizontal), false);
+ QCOMPARE(usedSimplex(l, Qt::Vertical), false);
+}
+
+/*
+ Avoid regression where the saved prefSize would be lost. This was
+ solved by saving the original spacing in the QGraphicsAnchorPrivate class
+*/
+void tst_QGraphicsAnchorLayout::spacingPersistency()
+{
+ QGraphicsWidget w;
+ QGraphicsWidget *a = createItem();
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w);
+
+ l->addAnchors(l, a, Qt::Horizontal);
+ QGraphicsAnchor *anchor = l->anchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+
+ anchor->setSpacing(-30);
+ QCOMPARE(anchor->spacing(), -30.0);
+
+ anchor->setSpacing(30);
+ QCOMPARE(anchor->spacing(), 30.0);
+
+ anchor->setSizePolicy(QSizePolicy::Ignored);
+ w.effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(anchor->spacing(), 30.0);
+}
+
+/*
+ Test whether a correct preferred size is set when a "snake" sequence is in parallel with the
+ layout or half of the layout. The tricky thing here is that all items on the snake should
+ keep their preferred sizes.
+*/
+void tst_QGraphicsAnchorLayout::snakeParallelWithLayout()
+{
+ QSizeF minSize(10, 20);
+ QSizeF pref(50, 20);
+ QSizeF maxSize(100, 20);
+
+ QGraphicsWidget *a = createItem(maxSize, maxSize, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(maxSize, maxSize, maxSize, "C");
+
+ QGraphicsWidget parent;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&parent);
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ // First we'll do the case in parallel with the entire layout...
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight);
+ l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ parent.resize(l->effectiveSizeHint(Qt::PreferredSize));
+
+ // Note that A and C are fixed in the maximum size
+ QCOMPARE(l->geometry(), QRectF(QPointF(0, 0), QSizeF(150, 60)));
+ QCOMPARE(a->geometry(), QRectF(QPointF(0, 0), maxSize));
+ QCOMPARE(b->geometry(), QRectF(QPointF(50, 20), pref));
+ QCOMPARE(c->geometry(), QRectF(QPointF(50, 40), maxSize));
+
+ // Then, we change the "snake" to be in parallel with half of the layout
+ delete l->anchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorHorizontalCenter);
+
+ parent.resize(l->effectiveSizeHint(Qt::PreferredSize));
+
+ QCOMPARE(l->geometry(), QRectF(QPointF(0, 0), QSizeF(300, 60)));
+ QCOMPARE(a->geometry(), QRectF(QPointF(0, 0), maxSize));
+ QCOMPARE(b->geometry(), QRectF(QPointF(50, 20), pref));
+ QCOMPARE(c->geometry(), QRectF(QPointF(50, 40), maxSize));
+}
+
+/*
+ Avoid regression where the sizeHint constraints would not be
+ created for a parallel anchor that included the first layout half
+*/
+void tst_QGraphicsAnchorLayout::parallelToHalfLayout()
+{
+ QGraphicsWidget *a = createItem();
+
+ QGraphicsWidget w;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w);
+ l->setContentsMargins(10, 10, 10, 10);
+
+ l->addAnchors(l, a, Qt::Vertical);
+
+ QGraphicsAnchor *anchor;
+ anchor = l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ anchor->setSpacing(5);
+ anchor = l->addAnchor(l, Qt::AnchorHorizontalCenter, a, Qt::AnchorRight);
+ anchor->setSpacing(-5);
+
+ const QSizeF minimumSizeHint = w.effectiveSizeHint(Qt::MinimumSize);
+ const QSizeF preferredSizeHint = w.effectiveSizeHint(Qt::PreferredSize);
+ const QSizeF maximumSizeHint = w.effectiveSizeHint(Qt::MaximumSize);
+
+ const QSizeF overhead = QSizeF(10 + 5 + 5, 10) * 2;
+
+ QCOMPARE(minimumSizeHint, QSizeF(200, 100) + overhead);
+ QCOMPARE(preferredSizeHint, QSizeF(300, 100) + overhead);
+ QCOMPARE(maximumSizeHint, QSizeF(400, 100) + overhead);
+}
+
+void tst_QGraphicsAnchorLayout::globalSpacing()
+{
+ QGraphicsWidget *a = createItem();
+ QGraphicsWidget *b = createItem();
+
+ QGraphicsWidget w;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w);
+
+ l->addCornerAnchors(l, Qt::TopLeftCorner, a, Qt::TopLeftCorner);
+ l->addCornerAnchors(a, Qt::BottomRightCorner, b, Qt::TopLeftCorner);
+ l->addCornerAnchors(b, Qt::BottomRightCorner, l, Qt::BottomRightCorner);
+
+ w.resize(w.effectiveSizeHint(Qt::PreferredSize));
+ qreal vSpacing = b->geometry().top() - a->geometry().bottom();
+ qreal hSpacing = b->geometry().left() - a->geometry().right();
+
+ // Set spacings manually
+ l->setVerticalSpacing(vSpacing + 10);
+ l->setHorizontalSpacing(hSpacing + 5);
+
+ w.resize(w.effectiveSizeHint(Qt::PreferredSize));
+ qreal newVSpacing = b->geometry().top() - a->geometry().bottom();
+ qreal newHSpacing = b->geometry().left() - a->geometry().right();
+
+ QCOMPARE(newVSpacing, vSpacing + 10);
+ QCOMPARE(newHSpacing, hSpacing + 5);
+
+ // Set a negative spacing. This will unset the previous spacing and
+ // bring back the widget-defined spacing.
+ l->setSpacing(-1);
+
+ w.resize(w.effectiveSizeHint(Qt::PreferredSize));
+ newVSpacing = b->geometry().top() - a->geometry().bottom();
+ newHSpacing = b->geometry().left() - a->geometry().right();
+
+ QCOMPARE(newVSpacing, vSpacing);
+ QCOMPARE(newHSpacing, hSpacing);
+}
+
+void tst_QGraphicsAnchorLayout::graphicsAnchorHandling()
+{
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout();
+ QGraphicsWidget *a = createItem();
+
+ l->addAnchors(l, a);
+
+ QGraphicsAnchor *layoutAnchor = l->anchor(l, Qt::AnchorTop, l, Qt::AnchorBottom);
+ QGraphicsAnchor *itemAnchor = l->anchor(a, Qt::AnchorTop, a, Qt::AnchorBottom);
+ QGraphicsAnchor *invalidAnchor = l->anchor(a, Qt::AnchorTop, l, Qt::AnchorBottom);
+
+ // Ensure none of these anchors are accessible.
+ QVERIFY(layoutAnchor == 0);
+ QVERIFY(itemAnchor == 0);
+ QVERIFY(invalidAnchor == 0);
+
+ // Hook the anchors to a QObject
+ QObject object;
+ QGraphicsAnchor *userAnchor = l->anchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ userAnchor->setParent(&object);
+ userAnchor = l->anchor(l, Qt::AnchorBottom, a, Qt::AnchorBottom);
+ userAnchor->setParent(&object);
+ userAnchor = l->anchor(l, Qt::AnchorRight, a, Qt::AnchorRight);
+ userAnchor->setParent(&object);
+ userAnchor = l->anchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ userAnchor->setParent(&object);
+
+ QCOMPARE(object.children().size(), 4);
+
+ // Delete layout, this will cause all anchors to be deleted internally.
+ // We expect the public QGraphicsAnchor instances to be deleted too.
+ delete l;
+ QCOMPARE(object.children().size(), 0);
+
+ delete a;
+}
+
+void tst_QGraphicsAnchorLayout::invalidHierarchyCheck()
+{
+ QGraphicsWidget window(0, Qt::Window);
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ window.setLayout(l);
+
+ QCOMPARE(l->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): "
+ "You cannot add the parent of the layout to the layout.");
+ QVERIFY(!l->addAnchor(l, Qt::AnchorLeft, &window, Qt::AnchorLeft));
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): "
+ "You cannot add the parent of the layout to the layout.");
+ l->addAnchors(l, &window);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): "
+ "You cannot add the parent of the layout to the layout.");
+ l->addCornerAnchors(l, Qt::TopLeftCorner, &window, Qt::TopLeftCorner);
+ QCOMPARE(l->count(), 0);
+}
+
+QTEST_MAIN(tst_QGraphicsAnchorLayout)
+#include "tst_qgraphicsanchorlayout.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro
new file mode 100644
index 0000000000..bcad43fc12
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsanchorlayout1.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp
new file mode 100644
index 0000000000..05f08e8719
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp
@@ -0,0 +1,3111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QtTest/QtTest>
+#include <QTest>
+#include <QMetaType>
+#include <QtWidgets/qgraphicsanchorlayout.h>
+#include <private/qgraphicsanchorlayout_p.h>
+
+#define TEST_COMPLEX_CASES
+
+
+//---------------------- AnchorLayout helper class ----------------------------
+class TheAnchorLayout : public QGraphicsAnchorLayout
+{
+public:
+ TheAnchorLayout() : QGraphicsAnchorLayout()
+ {
+ setContentsMargins( 0,0,0,0 );
+ setSpacing( 0 );
+ }
+
+ bool isValid()
+ {
+ return !QGraphicsAnchorLayoutPrivate::get(this)->hasConflicts();
+ }
+
+ void setAnchor(
+ QGraphicsLayoutItem *startItem,
+ Qt::AnchorPoint startEdge,
+ QGraphicsLayoutItem *endItem,
+ Qt::AnchorPoint endEdge,
+ qreal value)
+ {
+ QGraphicsAnchor *anchor = addAnchor( startItem, startEdge, endItem, endEdge);
+ if (anchor)
+ anchor->setSpacing(value);
+ }
+
+ int indexOf(const QGraphicsLayoutItem* item) const
+ {
+ for ( int i=0; i< count(); i++) {
+ if ( itemAt(i) == item ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ void removeItem(QGraphicsLayoutItem* item)
+ {
+ removeAt(indexOf(item));
+ }
+
+ void removeAnchor(
+ QGraphicsLayoutItem *startItem,
+ Qt::AnchorPoint startEdge,
+ QGraphicsLayoutItem *endItem,
+ Qt::AnchorPoint endEdge)
+ {
+ delete QGraphicsAnchorLayout::anchor(startItem, startEdge, endItem, endEdge);
+ }
+};
+//-----------------------------------------------------------------------------
+
+
+struct BasicLayoutTestData
+{
+ inline BasicLayoutTestData(
+ int index1, Qt::AnchorPoint edge1,
+ int index2, Qt::AnchorPoint edge2,
+ qreal distance)
+ : firstIndex(index1), firstEdge(edge1),
+ secondIndex(index2), secondEdge(edge2),
+ spacing(distance)
+ {
+ }
+
+ int firstIndex;
+ Qt::AnchorPoint firstEdge;
+ int secondIndex;
+ Qt::AnchorPoint secondEdge;
+ qreal spacing;
+};
+
+struct AnchorItemSizeHint
+{
+ inline AnchorItemSizeHint(
+ qreal hmin, qreal hpref, qreal hmax,
+ qreal vmin, qreal vpref, qreal vmax )
+ : hmin(hmin), hpref(hpref), hmax(hmax), vmin(vmin), vpref(vpref), vmax(vmax)
+ {
+ }
+ qreal hmin, hpref, hmax;
+ qreal vmin, vpref, vmax;
+};
+
+// some test results
+
+struct BasicLayoutTestResult
+{
+ inline BasicLayoutTestResult(
+ int resultIndex, const QRectF& resultRect )
+ : index(resultIndex), rect(resultRect)
+ {
+ }
+
+ int index;
+ QRectF rect;
+};
+
+typedef QList<BasicLayoutTestData> BasicLayoutTestDataList;
+Q_DECLARE_METATYPE(BasicLayoutTestDataList)
+
+typedef QList<BasicLayoutTestResult> BasicLayoutTestResultList;
+Q_DECLARE_METATYPE(BasicLayoutTestResultList)
+
+typedef QList<AnchorItemSizeHint> AnchorItemSizeHintList;
+Q_DECLARE_METATYPE(AnchorItemSizeHintList)
+
+
+//---------------------- Test Widget used on all tests ------------------------
+class TestWidget : public QGraphicsWidget
+{
+public:
+ inline TestWidget(QGraphicsItem *parent = 0, const QString &name = QString())
+ : QGraphicsWidget(parent)
+ {
+ setContentsMargins( 0,0,0,0 );
+ if (name.isEmpty())
+ setData(0, QString::fromAscii("w%1").arg(quintptr(this)));
+ else
+ setData(0, name);
+ }
+ ~TestWidget()
+ {
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+};
+
+QSizeF TestWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED( constraint );
+ if (which == Qt::MinimumSize) {
+ return QSizeF(5,5);
+ }
+
+ if (which == Qt::PreferredSize) {
+ return QSizeF(50,50);
+ }
+
+ return QSizeF(500,500);
+}
+//-----------------------------------------------------------------------------
+
+
+
+//----------------------------- Test class ------------------------------------
+class tst_QGraphicsAnchorLayout1 : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCount();
+
+ void testRemoveAt();
+ void testRemoveItem();
+
+ void testItemAt();
+ void testIndexOf();
+
+ void testAddAndRemoveAnchor();
+ void testIsValid();
+ void testSpecialCases();
+
+ void testBasicLayout_data();
+ void testBasicLayout();
+
+ void testNegativeSpacing_data();
+ void testNegativeSpacing();
+
+ void testMixedSpacing_data();
+ void testMixedSpacing();
+
+ void testMulti_data();
+ void testMulti();
+
+ void testCenterAnchors_data();
+ void testCenterAnchors();
+
+ void testRemoveCenterAnchor_data();
+ void testRemoveCenterAnchor();
+
+ void testSingleSizePolicy_data();
+ void testSingleSizePolicy();
+
+ void testDoubleSizePolicy_data();
+ void testDoubleSizePolicy();
+
+ void testSizeDistribution_data();
+ void testSizeDistribution();
+
+ void testSizeHint();
+
+#ifdef TEST_COMPLEX_CASES
+ void testComplexCases_data();
+ void testComplexCases();
+#endif
+};
+
+
+void tst_QGraphicsAnchorLayout1::testCount()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ QVERIFY( layout->count() == 0 );
+
+ TestWidget *widget1 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ QCOMPARE( layout->count(), 1 );
+
+ // adding one more anchor for already added widget should not increase the count
+ layout->setAnchor(layout, Qt::AnchorRight, widget1, Qt::AnchorRight, 1);
+ QCOMPARE( layout->count(), 1 );
+
+ // create one more widget and attach with anchor layout
+ TestWidget *widget2 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 1);
+ QCOMPARE( layout->count(), 2 );
+
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveAt()
+{
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ QVERIFY( layout->count() == 0 );
+
+ TestWidget *widget1 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 2);
+ QVERIFY( layout->count() == 1 );
+
+ TestWidget *widget2 = new TestWidget();
+ layout->setAnchor(widget2, Qt::AnchorLeft, layout, Qt::AnchorLeft, 0.1);
+ QVERIFY( layout->count() == 2 );
+
+ layout->removeAt(0);
+ QVERIFY( layout->count() == 1 );
+
+ layout->removeAt(-55);
+ layout->removeAt(55);
+ QVERIFY( layout->count() == 1 );
+
+ layout->removeAt(0);
+ QVERIFY( layout->count() == 0 );
+
+ delete layout;
+ delete widget1;
+ delete widget2;
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveItem()
+{
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ QCOMPARE( layout->count(), 0 );
+
+ TestWidget *widget1 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 2);
+ QCOMPARE( layout->count(), 1 );
+
+ TestWidget *widget2 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.1);
+ QCOMPARE( layout->count(), 2 );
+
+ layout->removeItem(0);
+ QCOMPARE( layout->count(), 2 );
+
+ layout->removeItem(widget1);
+ QCOMPARE( layout->count(), 1 );
+ QCOMPARE( layout->indexOf(widget1), -1 );
+ QCOMPARE( layout->indexOf(widget2), 0 );
+
+ layout->removeItem(widget1);
+ QCOMPARE( layout->count(), 1 );
+
+ layout->removeItem(widget2);
+ QVERIFY( layout->count() == 0 );
+
+ delete layout;
+ delete widget1;
+ delete widget2;
+}
+
+void tst_QGraphicsAnchorLayout1::testItemAt()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+ TestWidget *widget3 = new TestWidget();
+ TestWidget *widget4 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 0.1);
+
+ QVERIFY( layout->itemAt(0) == widget1 );
+
+ layout->removeAt(0);
+
+ QVERIFY( layout->itemAt(0) == widget2 );
+
+ delete widget1;
+
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testIndexOf()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+ TestWidget *widget3 = new TestWidget();
+ TestWidget *widget4 = new TestWidget();
+
+ QCOMPARE( layout->indexOf(widget1), -1 );
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft, 0.1);
+
+ QCOMPARE( layout->indexOf(widget4), -1 );
+ layout->setAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 0.1);
+
+ QCOMPARE( layout->count(), 4 );
+ for (int i = 0; i < layout->count(); ++i) {
+ QCOMPARE(layout->indexOf(layout->itemAt(i)), i);
+ }
+
+ QCOMPARE( layout->indexOf(0), -1 );
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testAddAndRemoveAnchor()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+ TestWidget *widget3 = new TestWidget();
+ TestWidget *widget4 = new TestWidget();
+ TestWidget *widget5 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.5);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft, 10);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 0.1);
+ QCOMPARE( layout->count(), 4 );
+
+ // test setting invalid anchors
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor NULL items");
+ layout->setAnchor(0, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor NULL items");
+ layout->setAnchor(layout, Qt::AnchorLeft, 0, Qt::AnchorLeft, 1);
+ QCOMPARE( layout->count(), 4 );
+
+ // test removing invalid anchors
+ layout->removeAnchor(widget4, Qt::AnchorRight, widget1, Qt::AnchorRight);
+
+ // anchor one horizontal edge with vertical edge. it should not add this widget as a child
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ layout->setAnchor(layout, Qt::AnchorLeft, widget5, Qt::AnchorTop, 10);
+ QCOMPARE( layout->count(), 4 );
+
+ // anchor two edges of a widget (to define width / height)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ layout->setAnchor(widget5, Qt::AnchorLeft, widget5, Qt::AnchorRight, 10);
+ // QCOMPARE( layout->count(), 5 );
+ QCOMPARE( layout->count(), 4 );
+
+ // anchor yet new widget properly
+ layout->setAnchor(layout, Qt::AnchorRight, widget5, Qt::AnchorRight, 20 );
+ QCOMPARE( layout->count(), 5 );
+
+ // remove anchor for widget1. widget1 should be removed from layout since the
+ // last anchor was removed.
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft);
+
+ QCOMPARE( layout->count(), 4 );
+ QVERIFY( !widget1->parentLayoutItem() );
+
+ // test that item is not removed from layout if other anchors remain set
+ layout->setAnchor(widget2, Qt::AnchorLeft, widget3, Qt::AnchorRight, 10);
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft);
+ QCOMPARE( layout->count(), 4 );
+
+ // remove all the anchors
+ layout->removeAnchor(widget2, Qt::AnchorLeft, widget3, Qt::AnchorRight);
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft);
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft);
+ layout->removeAnchor(widget5, Qt::AnchorLeft, widget5, Qt::AnchorRight);
+ layout->removeAnchor(layout, Qt::AnchorRight, widget5, Qt::AnchorRight);
+
+ QCOMPARE( layout->count(), 0 );
+
+ // set one anchor "another way round" to get full coverage for "removeAnchor"
+ layout->setAnchor(widget1, Qt::AnchorLeft, layout, Qt::AnchorLeft, 0.1);
+ layout->removeAnchor(widget1, Qt::AnchorLeft, layout, Qt::AnchorLeft);
+
+ QCOMPARE( layout->count(), 0 );
+
+ delete widget1;
+ delete widget2;
+ delete widget3;
+ delete widget4;
+ delete widget5;
+
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testIsValid()
+{
+ // Empty, valid
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+ widget->setGeometry(QRectF(0,0,100,100));
+
+ QCOMPARE(layout->isValid(), true);
+ delete widget;
+ }
+
+ // One widget, valid
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorTop, widget1, Qt::AnchorTop, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorRight, layout, Qt::AnchorRight, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 0.1);
+
+ widget->setLayout(layout);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(layout->isValid(), true);
+ delete widget;
+ }
+
+ // Overconstrained one widget, invalid
+ // ### Our understanding is that this case is valid. What happens though,
+ // is that the layout minimum and maximum vertical size hints become
+ // the same, 10.1. That means its height is fixed.
+ // What will "fail" then is the "setGeometry(0, 0, 100, 100)" call,
+ // after which the layout geometry will be (0, 0, 100, 10.1).
+
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorTop, widget1, Qt::AnchorTop, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorRight, layout, Qt::AnchorRight, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 0.1);
+
+ layout->setAnchor(widget1, Qt::AnchorTop, layout, Qt::AnchorBottom, 10);
+
+ widget->setLayout(layout);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(layout->isValid(), true);
+ delete widget;
+ }
+
+ // Underconstrained two widgets, valid
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+
+ // Vertically the layout has floating items. Therefore, we have a conflict
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorRight, widget1, Qt::AnchorRight, -0.1);
+
+ // Horizontally the layout has floating items. Therefore, we have a conflict
+ layout->setAnchor(layout, Qt::AnchorTop, widget2, Qt::AnchorTop, 0.1);
+ layout->setAnchor(layout, Qt::AnchorBottom, widget2, Qt::AnchorBottom, -0.1);
+
+ widget->setLayout(layout);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(layout->isValid(), false);
+ delete widget;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testSpecialCases()
+{
+ // One widget, setLayout before defining layouts
+ {
+#ifdef QT_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+
+ TestWidget *widget1 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout->setAnchor(widget1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(widget1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(1,1,98,98));
+ delete widget1;
+ delete widget;
+ }
+
+ // One widget, layout inside layout, layout inside layout inside layout
+ {
+#ifdef QT_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+ TestWidget *widget1 = new TestWidget();
+ layout1->setAnchor(layout1, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout1->setAnchor(widget1, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(widget1, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ TheAnchorLayout *layout2 = new TheAnchorLayout();
+ TestWidget *widget2 = new TestWidget();
+ layout2->setAnchor(layout2, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, widget2, Qt::AnchorTop, 1);
+ layout2->setAnchor(widget2, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(widget2, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ layout1->setAnchor(layout1, Qt::AnchorLeft, layout2, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, layout2, Qt::AnchorTop, 1);
+ layout1->setAnchor(layout2, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(layout2, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ // remove and add again to improve test coverage.
+ layout->removeItem(layout1);
+
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(2,2,96,96));
+ QCOMPARE(widget2->geometry(), QRectF(3,3,94,94));
+ delete widget;
+ }
+
+ // One widget, layout inside layout, setLayout after layout definition
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ layout1->setAnchor(layout1, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout1->setAnchor(widget1, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(widget1, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ widget->setLayout(layout);
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(2,2,96,96));
+ delete widget;
+ }
+
+ // One widget, layout inside layout, setLayout after layout definition, widget transferred from
+ // one layout to another
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+ TestWidget *widget1 = new TestWidget();
+
+ // Additional layout + widget to improve coverage.
+ TheAnchorLayout *layout0 = new TheAnchorLayout();
+ TestWidget *widget0 = new TestWidget();
+
+ // widget0 to layout0
+ layout0->setAnchor(layout0, Qt::AnchorLeft, widget0, Qt::AnchorLeft, 1);
+ layout0->setAnchor(layout0, Qt::AnchorTop, widget0, Qt::AnchorTop, 1);
+ layout0->setAnchor(widget0, Qt::AnchorRight, layout0, Qt::AnchorRight, 1);
+ layout0->setAnchor(widget0, Qt::AnchorBottom, layout0, Qt::AnchorBottom, 1);
+
+ // layout0 to layout
+ layout->setAnchor(layout, Qt::AnchorLeft, layout0, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout0, Qt::AnchorTop, 1);
+ layout->setAnchor(layout0, Qt::AnchorRight, layout, Qt::AnchorRight, 50);
+ layout->setAnchor(layout0, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ // widget1 to layout1
+ layout1->setAnchor(layout1, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout1->setAnchor(widget1, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(widget1, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ // layout1 to layout
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 50);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ TheAnchorLayout *layout2 = new TheAnchorLayout();
+
+ // layout2 to layout
+ layout->setAnchor(layout, Qt::AnchorLeft, layout2, Qt::AnchorLeft, 50);
+ layout->setAnchor(layout, Qt::AnchorTop, layout2, Qt::AnchorTop, 1);
+ layout->setAnchor(layout2, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout2, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ // transfer widget1 to layout2
+ layout2->setAnchor(layout2, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout2->setAnchor(widget1, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(widget1, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(51,2,47,96));
+ delete widget;
+ }
+
+ // One widget, set first to one layout then to another. Child reparented.
+ // In addition widget as a direct child of another widget. Child reparented.
+ {
+ QGraphicsWidget *widget1 = new QGraphicsWidget;
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+ widget1->setLayout(layout1);
+
+ TestWidget *childWidget = new TestWidget();
+
+ // childWidget to layout1
+ layout1->setAnchor(layout1, Qt::AnchorLeft, childWidget, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, childWidget, Qt::AnchorTop, 1);
+ layout1->setAnchor(childWidget, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(childWidget, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ widget1->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(childWidget->geometry(), QRectF(1,1,98,98));
+ QVERIFY(childWidget->parentLayoutItem() == layout1);
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ TheAnchorLayout *layout2 = new TheAnchorLayout();
+ widget2->setLayout(layout2);
+
+ // childWidget to layout2
+ layout2->setAnchor(layout2, Qt::AnchorLeft, childWidget, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, childWidget, Qt::AnchorTop, 1);
+ layout2->setAnchor(childWidget, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(childWidget, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ QGraphicsWidget *widget3 = new QGraphicsWidget;
+ QGraphicsWidget *widget4 = new QGraphicsWidget;
+ // widget4 is a direct child of widget3 (i.e. not in any layout)
+ widget4->setParentItem(widget3);
+
+ // widget4 to layout2
+ layout2->setAnchor(layout2, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, widget4, Qt::AnchorTop, 1);
+ layout2->setAnchor(widget4, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(widget4, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ widget2->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(childWidget->geometry(), QRectF(1,1,98,98));
+ QVERIFY(childWidget->parentLayoutItem() == layout2);
+ QCOMPARE(widget4->geometry(), QRectF(1,1,98,98));
+ QVERIFY(widget4->parentLayoutItem() == layout2);
+ QVERIFY(widget4->parentItem() == widget2);
+
+ delete widget4;
+ delete widget3;
+ delete widget1;
+ delete childWidget;
+ delete widget2;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testBasicLayout_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // One widget, basic
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 40)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(20, 10, 150, 50) )
+ ;
+
+ QTest::newRow("One, simple") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, duplicates
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 40)
+
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 0)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(0, 0, 200, 100) )
+ ;
+
+ QTest::newRow("One, duplicates") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, mixed
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorBottom, 80)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 150)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorRight, 150)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorBottom, 80)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(50, 20, 100, 60) )
+ ;
+
+ QTest::newRow("One, mixed") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets (same layout), different ordering
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 180, 80) )
+ << BasicResult(1, QRectF(10, 10, 180, 80) )
+ ;
+
+ QTest::newRow("Two, orderings") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, duplicate anchors
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(30, 10, 160, 70) )
+ << BasicResult(1, QRectF(10, 0, 190, 90) )
+ ;
+
+ QTest::newRow("Two, duplicates") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, mixed
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorBottom, 90)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 190)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorRight, 190)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorBottom, 90)
+
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorBottom, 20)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorRight, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 180, 80) )
+ << BasicResult(1, QRectF(10, 80, 10, 10) )
+ ;
+
+ QTest::newRow("Two, mixed") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 horizontal connection, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(30, 10, 160, 70) )
+ ;
+
+ QTest::newRow("Two, 1h connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal connections, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ // ### QGAL is not sensible to the argument order in this case
+ // To achieve the desired result we must explicitly set a negative
+ // spacing.
+ // << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, 100)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, -100)
+
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 30)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(50, 10, 60, 70) )
+ ;
+
+ QTest::newRow("Two, 2h connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 vertical connection, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 30)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(30, 20, 160, 60) )
+ ;
+
+ QTest::newRow("Two, 1v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 vertical connections, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 30)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(30, 20, 160, 50) )
+ ;
+
+ QTest::newRow("Two, 2v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 horizontal and 1 vertical connection, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 80)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 100)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(80, 10, 40, 70) )
+ ;
+
+ QTest::newRow("Two, 1h+1v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal and 2 vertical connections, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 80)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 100)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(90, 20, 30, 60) )
+ ;
+
+ QTest::newRow("Two, 2h+2v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal and 2 vertical connections, dependent on each other.
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 150)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 10)
+
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 90)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 30, 60) )
+ << BasicResult(1, QRectF(100, 20, 90, 60) )
+ ;
+
+ QTest::newRow("Two, 2h+2v connected2") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, connected, overlapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ // << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, 30)
+ // ### QGAL has different semantics and assumes right edges are always
+ // to the left of left edges. Thus we need the minus sign here.
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, -30)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 40)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 40)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 60, 40) )
+ << BasicResult(1, QRectF(40, 20, 150, 70) )
+ ;
+
+ QTest::newRow("Two, connected overlapping") << QSizeF(200, 100) << theData << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testNegativeSpacing_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // One widget, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ /// ### QGAL assumes items are always inside the layout.
+ // In this case, the negative spacing would make the item
+ // grow beyond the layout edges, which is OK, but gives a
+ // different result.
+ // Changing the direction of anchors (-1 to 0 or vice-versa)
+ // has no effect in this case.
+
+ theData
+ // << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ // << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -20)
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -30)
+ // << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -40)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, -20)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, -30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, -40)
+
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(20, 10, 150, 50) )
+ << BasicResult(0, QRectF(-20, -10, 250, 150) )
+ ;
+
+ QTest::newRow("One, simple (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, duplicates, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -20)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -20)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -30)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -40)
+
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -10)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+ ;
+
+ theResult
+ // ### Same as above...
+ // << BasicResult(0, QRectF(10, 10, 180, 80) )
+ << BasicResult(0, QRectF(-10, -10, 220, 120) )
+ ;
+
+ QTest::newRow("One, duplicates (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, mixed, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // ### All anchors of negative spacing between the layout and an
+ // item are handled as to make sure the item is _outside_ the
+ // layout.
+ // To keep it inside, one _must_ use positive spacings.
+ // << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorTop, -80)
+ // << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorLeft, -150)
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorLeft, -150)
+ // << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorTop, -80)
+
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorTop, 80)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorLeft, 150)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorLeft, 150)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorTop, 80)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(50, 20, 100, 60) )
+ ;
+
+ QTest::newRow("One, mixed (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 horizontal connection, first completely defined, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ // << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+ // << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -180)
+
+ // << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, -10)
+ // << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ // << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ // << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -20)
+
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, 180)
+
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, -10)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -20)
+
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(10, 10, 10, 80) )
+ // << BasicResult(1, QRectF(30, 10, 160, 70) )
+
+ << BasicResult(0, QRectF(-10, -10, 30, 120) )
+ << BasicResult(1, QRectF(10, -10, 200, 130) )
+ ;
+
+ QTest::newRow("Two, 1h connected (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal and 2 vertical connections, dependent on each other, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ << BasicData(1, Qt::AnchorRight, 0, Qt::AnchorRight, -150)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorLeft, -90)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -20)
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(10, 10, 30, 60) )
+ // << BasicResult(1, QRectF(100, 20, 90, 60) )
+ << BasicResult(0, QRectF(-10, -10, 70, 120) )
+ << BasicResult(1, QRectF(80, 0, 130, 120) )
+ ;
+
+ QTest::newRow("Two, 2h+2v connected2 (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testMixedSpacing_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Two widgets, partial overlapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -50)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 50)
+ << BasicData(1, Qt::AnchorRight, 0, Qt::AnchorRight, 15)
+
+ // << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorBottom, 5)
+ << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorBottom, -5)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, -10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 20)
+ << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -5)
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(50, 10, 45, 40) )
+ // << BasicResult(1, QRectF(40, 45, 40, 50) )
+ << BasicResult(0, QRectF(-50, 10, 145, 40) )
+ << BasicResult(1, QRectF(-60, 45, 140, 60) )
+ ;
+
+ QTest::newRow("Two, partial overlap") << QSizeF(100, 100) << theData << theResult;
+ }
+
+ // Two widgets, complete overlapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 25)
+
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 0)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+ << BasicData(1, Qt::AnchorLeft, -1, Qt::AnchorRight, 50)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(65, 5, 35, 35) )
+ << BasicResult(1, QRectF(40, 5, 60, 35) )
+ ;
+
+ QTest::newRow("Two, complete overlap") << QSizeF(90, 45) << theData << theResult;
+ }
+
+ // Five widgets, v shaped, edges shared
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // edges shared
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 0)
+ << BasicData(1, Qt::AnchorRight, 2, Qt::AnchorLeft, 0)
+ << BasicData(2, Qt::AnchorRight, 3, Qt::AnchorLeft, 0)
+ << BasicData(3, Qt::AnchorRight, 4, Qt::AnchorLeft, 0)
+ << BasicData(1, Qt::AnchorBottom, 2, Qt::AnchorTop, 0)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorTop, 0)
+ << BasicData(3, Qt::AnchorBottom, 2, Qt::AnchorTop, 0)
+ << BasicData(4, Qt::AnchorBottom, 3, Qt::AnchorTop, 0)
+ << BasicData(0, Qt::AnchorBottom, 4, Qt::AnchorBottom, 0)
+ << BasicData(1, Qt::AnchorBottom, 3, Qt::AnchorBottom, 0)
+ << BasicData(0, Qt::AnchorTop, 4, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorTop, 3, Qt::AnchorTop, 0)
+
+ // margins
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 5)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 5)
+ << BasicData(2, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+ // << BasicData(-1, Qt::AnchorRight, 4, Qt::AnchorRight, -5)
+ << BasicData(-1, Qt::AnchorRight, 4, Qt::AnchorRight, 5)
+
+ // additional details for exact size determination easily
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 25)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorRight, 50)
+ // << BasicData(-1, Qt::AnchorRight, 3, Qt::AnchorRight, -25)
+ // << BasicData(-1, Qt::AnchorRight, 2, Qt::AnchorRight, -50)
+ << BasicData(-1, Qt::AnchorRight, 3, Qt::AnchorRight, 25)
+ << BasicData(-1, Qt::AnchorRight, 2, Qt::AnchorRight, 50)
+ << BasicData(-1, Qt::AnchorTop, 3, Qt::AnchorBottom, 50)
+ // << BasicData(-1, Qt::AnchorBottom, 3, Qt::AnchorTop, -50)
+ << BasicData(-1, Qt::AnchorBottom, 3, Qt::AnchorTop, 50)
+
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(5,5,20,20))
+ << BasicResult(1, QRectF(25,25,25,25))
+ << BasicResult(2, QRectF(50,50,25,20))
+ << BasicResult(3, QRectF(75,25,25,25))
+ << BasicResult(4, QRectF(100,5,20,20))
+ ;
+
+ QTest::newRow("Five, V shape") << QSizeF(125, 75) << theData << theResult;
+ }
+
+ // ### The behavior is different in QGraphicsAnchorLayout. What happens here is
+ // that when the above anchors are set, the layout size hints are changed.
+ // In the example, the minimum item width is 5, thus the minimum layout width
+ // becomes 105 (50 + 5 + 50). Once that size hint is set, trying to set
+ // the widget size to (10, 10) is not possible because
+ // QGraphicsWidget::setGeometry() will enforce the minimum is respected.
+ if (0)
+ // One widget, unsolvable
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 50)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 50)
+ ;
+ theResult
+ << BasicResult(0, QRectF(0,0,0,0))
+ ;
+
+ QTest::newRow("One widget, unsolvable") << QSizeF(10, 10) << theData << theResult;
+ }
+
+ // Two widgets, one has fixed size
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 50)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 50)
+ // not supported, use sizePolicy instead
+ // << BasicData(0, Qt::AnchorLeft, 0, Qt::AnchorRight, 50)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 50)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 50)
+ ;
+ theResult
+ << BasicResult(0, QRectF(50,0,50,50))
+ << BasicResult(1, QRectF(50,0,50,50))
+ ;
+
+ QTest::newRow("Two widgets, one has fixed size") << QSizeF(150, 150) << theData << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testMulti_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Multiple widgets, all overllapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const int n = 30;
+ for ( int i = 0 ; i < n; i++ ) {
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, 20)
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, 10)
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -40)
+ // << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, -30);
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, 40)
+ << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, 30);
+
+ theResult
+ << BasicResult(i, QRectF(10, 20, 160, 40) );
+ }
+
+
+ QTest::newRow("Overlapping multi") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Multiple widgets, linear order
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const qreal height = 1000.f;
+ const qreal width = 2000.f;
+
+ const int n = 30;
+
+ const qreal verticalStep = height/qreal(n+2);
+ const qreal horizontalStep = width/qreal(n+2);
+
+ for ( int i = 0 ; i < n; i++ ) {
+
+ if ( i == 0 ) {
+ // First item
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+
+ } else if ( i == n-1 ) {
+ // Last item
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, verticalStep)
+ << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, horizontalStep);
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ // << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+
+ } else {
+ // items in the middle
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ // << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ // << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+
+ }
+
+ theResult
+ << BasicResult(i, QRectF((i+1)*horizontalStep, (i+1)*verticalStep, horizontalStep, verticalStep) );
+ }
+
+
+ if (sizeof(qreal) == 4) {
+ qDebug("Linear multi: Skipping! (qreal has too little precision, result will be wrong)");
+ } else {
+ QTest::newRow("Linear multi") << QSizeF(width, height) << theData << theResult;
+ }
+ }
+
+ // Multiple widgets, V shape
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const qreal height = 100.f;
+ const qreal width = 200.f;
+
+ const int n = 31; // odd number please (3,5,7... )
+
+ const qreal verticalStep = height/(2.f+(n+1)/2.f);
+ const qreal horizontalStep = width/(n+2.f);
+
+ for ( int i = 0 ; i < n; i++ ) {
+
+ if ( i == 0 ) {
+ // First item
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+
+ } else if ( i == n-1 ) {
+ // Last item
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, -verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, -1, Qt::AnchorRight, horizontalStep);
+ } else if ( i == ((n-1)/2) ) {
+ // midway
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+ } else if ( i < ((n-1)/2) ) {
+ // before midway - going down
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+
+ } else {
+ // after midway - going up
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, -verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+
+ }
+
+ if ( i <= ((n-1)/2) ) {
+ // until midway
+ theResult
+ << BasicResult(i, QRectF((i+1)*horizontalStep, (i+1)*verticalStep, horizontalStep, verticalStep) );
+ } else {
+ // after midway
+ theResult
+ << BasicResult(i, QRectF((i+1)*horizontalStep, (n-i)*verticalStep, horizontalStep, verticalStep) );
+ }
+
+ }
+ if (sizeof(qreal) == 4) {
+ qDebug("V multi: Skipping! (qreal has too little precision, result will be wrong)");
+ } else {
+ QTest::newRow("V multi") << QSizeF(width, height) << theData << theResult;
+ }
+ }
+
+ // Multiple widgets, grid
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const qreal height = 100.f;
+ const qreal width = 200.f;
+
+ const int d = 10; // items per dimension
+ const int n = d*d;
+
+ const qreal verticalStep = height/(d+2.f);
+ const qreal horizontalStep = width/(d+2.f);
+
+ for ( int i = 0 ; i < n; i++ ) {
+ if ( i%d == 0 ) {
+ // left side item
+ theData
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ } else if ( (i+1)%d == 0 ) {
+ // rigth side item
+ theData
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ // << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, horizontalStep);
+ } else {
+ // horizontal middle
+ theData
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ }
+
+ if ( i < d ) {
+ // top line
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i+d, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep);
+ } else if ( i >= (d-1)*d ){
+ // bottom line
+ theData
+ << BasicData(i-d, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, verticalStep);
+ } else {
+ // vertical middle
+ theData
+ << BasicData(i-d, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i+d, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep);
+ }
+
+ theResult
+ << BasicResult(i, QRectF(((i%d)+1)*horizontalStep, ((i/d)+1)*verticalStep, horizontalStep, verticalStep) );
+ }
+
+ if (sizeof(qreal) == 4) {
+ qDebug("Grid multi: Skipping! (qreal has too little precision, result will be wrong)");
+ } else {
+ QTest::newRow("Grid multi") << QSizeF(200, 100) << theData << theResult;
+ }
+ }
+}
+
+inline QGraphicsLayoutItem *getItem(
+ int index,
+ const QList<QGraphicsWidget *>& widgets,
+ QGraphicsLayoutItem *defaultItem)
+{
+ if (index < 0) {
+ return defaultItem;
+ }
+
+ return widgets[index];
+}
+
+static bool fuzzierCompare(qreal a, qreal b)
+{
+ return qAbs(a - b) <= qreal(0.0001);
+}
+
+static bool fuzzierCompare(const QRectF &r1, const QRectF &r2)
+{
+
+ return fuzzierCompare(r1.x(), r2.x()) && fuzzierCompare(r1.y(), r2.y())
+ && fuzzierCompare(r1.width(), r2.width()) && fuzzierCompare(r1.height(), r2.height());
+}
+
+void tst_QGraphicsAnchorLayout1::testBasicLayout()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(BasicLayoutTestDataList, data);
+ QFETCH(BasicLayoutTestResultList, result);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ // Determine amount of widgets to add.
+ int widgetCount = -1;
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ widgetCount = qMax(widgetCount, item.firstIndex);
+ widgetCount = qMax(widgetCount, item.secondIndex);
+ }
+ ++widgetCount; // widgetCount is max of indices.
+
+ // Create dummy widgets
+ QList<QGraphicsWidget *> widgets;
+ for (int i = 0; i < widgetCount; ++i) {
+ TestWidget *w = new TestWidget(0, QString::fromAscii("W%1").arg(i));
+ widgets << w;
+ }
+
+ // Setup anchor layout
+ TheAnchorLayout *layout = new TheAnchorLayout;
+
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ layout->setAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge,
+ item.spacing );
+ }
+
+ widget->setLayout(layout);
+ widget->setContentsMargins(0,0,0,0);
+
+ widget->resize(size);
+ QCOMPARE(widget->size(), size);
+
+ // Validate
+ for (int i = 0; i < result.count(); ++i) {
+ const BasicLayoutTestResult item = result[i];
+ QRectF expected = item.rect;
+ QRectF actual = widgets[item.index]->geometry();
+
+ QVERIFY(fuzzierCompare(actual, expected));
+ }
+
+ // Test mirrored mode
+ widget->setLayoutDirection(Qt::RightToLeft);
+ layout->activate();
+ // Validate
+ for (int j = 0; j < result.count(); ++j) {
+ const BasicLayoutTestResult item = result[j];
+ QRectF mirroredRect(item.rect);
+ // only valid cases are mirrored
+ if (mirroredRect.isValid()){
+ mirroredRect.moveLeft(size.width()-item.rect.width()-item.rect.left());
+ }
+ QRectF expected = mirroredRect;
+ QRectF actual = widgets[item.index]->geometry();
+
+ QVERIFY(fuzzierCompare(actual, expected));
+ }
+
+ qDeleteAll(widgets);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testNegativeSpacing()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testMixedSpacing()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testMulti()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testCenterAnchors_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Basic center case
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("center, basic") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Basic center case, with invalid (shouldn't affect on result)
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+
+ // bogus definitions
+ << BasicData(0, Qt::AnchorHorizontalCenter, -1, Qt::AnchorBottom, 5)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorVerticalCenter, 5)
+ << BasicData(0, Qt::AnchorVerticalCenter, -1, Qt::AnchorRight, 5)
+ << BasicData(0, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 666)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 999)
+ << BasicData(0, Qt::AnchorLeft, 0, Qt::AnchorLeft, 333)
+ << BasicData(-1, Qt::AnchorRight, -1, Qt::AnchorRight, 222)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorTop, 111)
+ << BasicData(0, Qt::AnchorBottom, 0, Qt::AnchorBottom, 444);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::newRow("center, basic with invalid") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Basic center case 2
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 0)
+ // Not supported << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 0)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, -5);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("center, basic 2") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Basic center case, overrides
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 20)
+ << BasicData(0, Qt::AnchorHorizontalCenter, -1, Qt::AnchorHorizontalCenter, 30)
+ << BasicData(0, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 40)
+ // actual data:
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 0)
+ // << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, -5);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("center, overrides") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Two nested
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorLeft, 0)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 0)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorTop, 0)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 0);
+
+ theResult
+ << BasicResult(0, QRectF(20, 0, 20, 40))
+ << BasicResult(1, QRectF(20, 20, 20, 20));
+
+ QTest::newRow("center, two nested") << QSizeF(40, 40) << theData << theResult;
+ }
+
+ // Two overlap
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ // theData
+ // // horizontal
+ // << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ // << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorLeft, 0)
+ // << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, -5)
+ // << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ // << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 10)
+ // // vertical is pretty much same as horizontal, just roles swapped
+ // << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ // << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, 0)
+ // << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorBottom, -5)
+ // << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ // << BasicData(1, Qt::AnchorVerticalCenter, 1, Qt::AnchorBottom, 10);
+
+ theData
+ // horizontal
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorHorizontalCenter, 5)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 20)
+ // vertical
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorVerticalCenter, 5)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 20);
+
+ theResult
+ << BasicResult(0, QRectF(20, 30, 20, 30))
+ << BasicResult(1, QRectF(30, 20, 30, 20));
+
+ QTest::newRow("center, two overlap") << QSizeF(70, 70) << theData << theResult;
+ }
+
+ // Three
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 2, Qt::AnchorHorizontalCenter, 75)
+ << BasicData(1, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+ << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, -30)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 0)
+ << BasicData(1, Qt::AnchorLeft, 1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 35)
+ << BasicData(1, Qt::AnchorVerticalCenter, 2, Qt::AnchorVerticalCenter, 15)
+ << BasicData(1, Qt::AnchorBottom, 2, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ << BasicData(2, Qt::AnchorBottom, 0, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 20);
+
+ theResult
+ << BasicResult(0, QRectF(0, 30, 10, 20))
+ << BasicResult(1, QRectF(20, 0, 30, 10))
+ << BasicResult(2, QRectF(60, 15, 40, 10));
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+
+ QTest::newRow("center, three") << QSizeF(100, 50) << theData << theResult;
+ }
+
+ // Two, parent center
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // vertical is pretty much same as horizontal, just roles swapped
+ << BasicData(-1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, -15)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 0)
+ << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ // horizontal
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, -15)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 0);
+
+ theResult
+ << BasicResult(0, QRectF(20, 20, 30, 80))
+ << BasicResult(1, QRectF(20, 20, 80, 30));
+
+ QTest::newRow("center, parent") << QSizeF(100, 100) << theData << theResult;
+ }
+
+ // Two, parent center 2
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(1, Qt::AnchorLeft, -1, Qt::AnchorHorizontalCenter, 15)
+ << BasicData(1, Qt::AnchorLeft, -1, Qt::AnchorHorizontalCenter, -15)
+ << BasicData(1, Qt::AnchorRight, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorRight, -5)
+ // vertical
+ << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 20)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 20)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorTop, 10);
+
+ theResult
+ << BasicResult(0, QRectF(30, 10, 15, 10))
+ << BasicResult(1, QRectF(10, 30, 10, 10));
+
+ QTest::newRow("center, parent 2") << QSizeF(50, 50) << theData << theResult;
+ }
+
+ // Two, parent center 3
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, -5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorLeft, 5)
+ // << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, 100)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, -100)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, 0)
+
+ // vertical
+ << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 55)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorTop, 10)
+ // << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 45)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorBottom, 45)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(0, 0, 45, 45))
+ << BasicResult(1, QRectF(55, 55, 45, 45));
+
+ QTest::newRow("center, parent 3") << QSizeF(100, 100) << theData << theResult;
+ }
+
+}
+
+void tst_QGraphicsAnchorLayout1::testCenterAnchors()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestDataList>("removeData");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestDataList theRemoveData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 66)
+ << BasicData(1, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 99)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 33)
+ ;
+
+ theRemoveData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(1, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 0)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 0);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("remove, center, basic") << QSizeF(20, 20) << theData
+ << theRemoveData << theResult;
+ }
+
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestDataList theRemoveData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 2, Qt::AnchorHorizontalCenter, 75)
+ << BasicData(1, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+ << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, -30)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 0)
+ << BasicData(1, Qt::AnchorLeft, 1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+
+ // extra:
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 66)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 33)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 55)
+ << BasicData(1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 55)
+
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 35)
+ << BasicData(1, Qt::AnchorVerticalCenter, 2, Qt::AnchorVerticalCenter, 15)
+ << BasicData(1, Qt::AnchorBottom, 2, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ << BasicData(2, Qt::AnchorBottom, 0, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 20);
+
+ theRemoveData
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 66)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 33)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 55)
+ << BasicData(1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 55);
+
+ theResult
+ << BasicResult(0, QRectF(0, 30, 10, 20))
+ << BasicResult(1, QRectF(20, 0, 30, 10))
+ << BasicResult(2, QRectF(60, 15, 40, 10));
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+
+ QTest::newRow("remove, center, three") << QSizeF(100, 50) << theData << theRemoveData << theResult;
+ }
+
+ // add edge (item0,edge0,item1,edge1), remove (item1,edge1,item0,edge0)
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestDataList theRemoveData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 66)
+ << BasicData(1, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 99)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 33)
+ << BasicData(0, Qt::AnchorLeft, 0, Qt::AnchorRight, 22)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 11)
+ ;
+
+ theRemoveData
+ << BasicData(1, Qt::AnchorHorizontalCenter, -1, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 0)
+ << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(0, Qt::AnchorRight, 0, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorBottom, 0, Qt::AnchorTop, 0)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::newRow("remove, center, basic 2") << QSizeF(20, 20) << theData
+ << theRemoveData << theResult;
+ }
+
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(BasicLayoutTestDataList, data);
+ QFETCH(BasicLayoutTestDataList, removeData);
+ QFETCH(BasicLayoutTestResultList, result);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ // Determine amount of widgets to add.
+ int widgetCount = -1;
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ widgetCount = qMax(widgetCount, item.firstIndex);
+ widgetCount = qMax(widgetCount, item.secondIndex);
+ }
+ ++widgetCount; // widgetCount is max of indices.
+
+ // Create dummy widgets
+ QList<QGraphicsWidget *> widgets;
+ for (int i = 0; i < widgetCount; ++i) {
+ TestWidget *w = new TestWidget;
+ widgets << w;
+ }
+
+ // Setup anchor layout
+ TheAnchorLayout *layout = new TheAnchorLayout;
+
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ layout->setAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge,
+ item.spacing );
+ }
+
+ for (int i = 0; i < removeData.count(); ++i) {
+ const BasicLayoutTestData item = removeData[i];
+ layout->removeAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge);
+ }
+
+ widget->setLayout(layout);
+ widget->setContentsMargins(0,0,0,0);
+
+ widget->resize(size);
+ QCOMPARE(widget->size(), size);
+
+ // Validate
+ for (int i = 0; i < result.count(); ++i) {
+ const BasicLayoutTestResult item = result[i];
+
+ QCOMPARE(widgets[item.index]->geometry(), item.rect);
+ }
+
+ qDeleteAll(widgets);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testSingleSizePolicy_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QSizePolicy>("policy");
+ QTest::addColumn<bool>("valid");
+
+// FIXED
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QTest::newRow("single size policy: fixed ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QTest::newRow("single size policy: fixed too big") << QSizeF(100, 100) << sizePolicy << false;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QTest::newRow("single size policy: fixed too small") << QSizeF(50, 50) << sizePolicy << false;
+ }
+*/
+// MINIMUM
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QTest::newRow("single size policy: minimum bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QTest::newRow("single size policy: minimum limit ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QTest::newRow("single size policy: minimum too small") << QSizeF(50, 50) << sizePolicy << false;
+ }
+*/
+// MAXIMUM
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QTest::newRow("single size policy: maximum small ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QTest::newRow("single size policy: maximum limit ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QTest::newRow("single size policy: maximum bigger fail") << QSizeF(100, 100) << sizePolicy << false;
+ }
+*/
+// PREFERRED
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred smaller ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred too big") << QSizeF(700, 700) << sizePolicy << false;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred too small") << QSizeF(21, 21) << sizePolicy << false;
+ }
+*/
+// MINIMUMEXPANDING
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QTest::newRow("single size policy: min.expanding bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QTest::newRow("single size policy: min.expanding limit ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+
+ /*{
+ QSizePolicy sizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QTest::newRow("single size policy: min.expanding too small") << QSizeF(50, 50) << sizePolicy << false;
+ }*/
+
+// EXPANDING
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QTest::newRow("single size policy: expanding bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QTest::newRow("single size policy: expanding smaller ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+
+ // IGNORED
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QTest::newRow("single size policy: ignored bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QTest::newRow("single size policy: ignored smaller ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testSingleSizePolicy()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(QSizePolicy, policy);
+ QFETCH(bool, valid);
+
+ // create objects
+ QGraphicsWidget widget;
+ TheAnchorLayout *layout = new TheAnchorLayout;
+ TestWidget *childWidget = new TestWidget;
+
+ // set anchors
+ layout->setAnchor( layout, Qt::AnchorLeft, childWidget, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget, Qt::AnchorRight, layout, Qt::AnchorRight, 10 );
+ layout->setAnchor( layout, Qt::AnchorTop, childWidget, Qt::AnchorTop, 10 );
+ layout->setAnchor( childWidget, Qt::AnchorBottom, layout, Qt::AnchorBottom, 10 );
+
+ widget.setLayout( layout );
+
+ // set test case specific: policy and size
+ childWidget->setSizePolicy( policy );
+ widget.setGeometry( QRectF( QPoint(0,0), size ) );
+
+ QCOMPARE( layout->isValid() , valid );
+
+ const QRectF childRect = childWidget->geometry();
+ Q_UNUSED( childRect );
+}
+
+void tst_QGraphicsAnchorLayout1::testDoubleSizePolicy_data()
+{
+ // tests only horizontal direction
+ QTest::addColumn<QSizePolicy>("policy1");
+ QTest::addColumn<QSizePolicy>("policy2");
+ QTest::addColumn<qreal>("width1");
+ QTest::addColumn<qreal>("width2");
+
+ // layout size always 100x100 and size hints for items are 5<50<500
+ // gabs: 10-item1-10-item2-10
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 50;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: fixed-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 50;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: minimum-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: maximum-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: preferred-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 50;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: min.expanding-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: expanding-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ // QGAL handling of ignored flag is different
+ if (0)
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: ignored-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ /*{
+ QSizePolicy sizePolicy1( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = -1;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: fixed-fixed invalid") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }*/
+
+ /*{
+ QSizePolicy sizePolicy1( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = -1;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: minimum-fixed invalid") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }*/
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: maximum-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: preferred-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ /*{
+ QSizePolicy sizePolicy1( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = -1;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: min.expanding-fixed invalid") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }*/
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: expanding-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: ignored-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testDoubleSizePolicy()
+{
+ QFETCH(QSizePolicy, policy1);
+ QFETCH(QSizePolicy, policy2);
+ QFETCH(qreal, width1);
+ QFETCH(qreal, width2);
+
+ // create objects
+ QGraphicsWidget widget;
+ TheAnchorLayout *layout = new TheAnchorLayout;
+ TestWidget *childWidget1 = new TestWidget;
+ TestWidget *childWidget2 = new TestWidget;
+
+ // set anchors
+ layout->setAnchor( layout, Qt::AnchorLeft, childWidget1, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget1, Qt::AnchorRight, childWidget2, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget2, Qt::AnchorRight, layout, Qt::AnchorRight, 10 );
+
+ widget.setLayout( layout );
+
+ // set test case specific: policy
+ childWidget1->setSizePolicy( policy1 );
+ childWidget2->setSizePolicy( policy2 );
+
+ widget.setGeometry( QRectF( QPoint(0,0), QSize( 100,100 ) ) );
+
+ // check results:
+ if ( width1 == -1.0f ) {
+ // invalid
+ QCOMPARE( layout->isValid() , false );
+ } else {
+ // valid
+ QCOMPARE( childWidget1->geometry().width(), width1 );
+ QCOMPARE( childWidget2->geometry().width(), width2 );
+ }
+}
+
+typedef QMap<int,qreal> SizeHintArray;
+Q_DECLARE_METATYPE(SizeHintArray)
+
+void tst_QGraphicsAnchorLayout1::testSizeDistribution_data()
+{
+ // tests only horizontal direction
+ QTest::addColumn<SizeHintArray>("sizeHints1");
+ QTest::addColumn<SizeHintArray>("sizeHints2");
+ QTest::addColumn<qreal>("width1");
+ QTest::addColumn<qreal>("width2");
+
+ // layout size always 100x100 and size policy for items is preferred-preferred
+ // gabs: 10-item1-10-item2-10
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 30 );
+ sizeHints1.insert( Qt::PreferredSize, 35 );
+ sizeHints1.insert( Qt::MaximumSize, 40 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 5 );
+ sizeHints2.insert( Qt::PreferredSize, 35 );
+ sizeHints2.insert( Qt::MaximumSize, 300 );
+
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: preferred equal") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 0 );
+ sizeHints1.insert( Qt::PreferredSize, 20 );
+ sizeHints1.insert( Qt::MaximumSize, 100 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 0 );
+ sizeHints2.insert( Qt::PreferredSize, 50 );
+ sizeHints2.insert( Qt::MaximumSize, 100 );
+
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: preferred non-equal") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 0 );
+ sizeHints1.insert( Qt::PreferredSize, 40 );
+ sizeHints1.insert( Qt::MaximumSize, 100 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 0 );
+ sizeHints2.insert( Qt::PreferredSize, 60 );
+ sizeHints2.insert( Qt::MaximumSize, 100 );
+
+ const qreal width1 = 28; // got from manual calculation
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: below preferred") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 0 );
+ sizeHints1.insert( Qt::PreferredSize, 10 );
+ sizeHints1.insert( Qt::MaximumSize, 100 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 0 );
+ sizeHints2.insert( Qt::PreferredSize, 40 );
+ sizeHints2.insert( Qt::MaximumSize, 100 );
+
+ const qreal width1 = 22; // got from manual calculation
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: above preferred") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+}
+
+void tst_QGraphicsAnchorLayout1::testSizeDistribution()
+{
+ QFETCH(SizeHintArray, sizeHints1);
+ QFETCH(SizeHintArray, sizeHints2);
+ QFETCH(qreal, width1);
+ QFETCH(qreal, width2);
+
+ // sanity-check the test data - MinimumSize <= PreferredSize <= MaximumSize
+ QVERIFY( sizeHints1.value( Qt::MinimumSize ) <= sizeHints1.value( Qt::PreferredSize ) );
+ QVERIFY( sizeHints1.value( Qt::PreferredSize ) <= sizeHints1.value( Qt::MaximumSize ) );
+ QVERIFY( sizeHints2.value( Qt::MinimumSize ) <= sizeHints2.value( Qt::PreferredSize ) );
+ QVERIFY( sizeHints2.value( Qt::PreferredSize ) <= sizeHints2.value( Qt::MaximumSize ) );
+
+ // create objects
+ QGraphicsWidget widget;
+ TheAnchorLayout *layout = new TheAnchorLayout;
+ TestWidget *childWidget1 = new TestWidget;
+ TestWidget *childWidget2 = new TestWidget;
+
+ // set anchors
+ layout->setAnchor( layout, Qt::AnchorLeft, childWidget1, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget1, Qt::AnchorRight, childWidget2, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget2, Qt::AnchorRight, layout, Qt::AnchorRight, 10 );
+
+ widget.setLayout( layout );
+
+ // set test case specific: size hints
+ childWidget1->setMinimumWidth( sizeHints1.value( Qt::MinimumSize ) );
+ childWidget1->setPreferredWidth( sizeHints1.value( Qt::PreferredSize ) );
+ childWidget1->setMaximumWidth( sizeHints1.value( Qt::MaximumSize ) );
+
+ childWidget2->setMinimumWidth( sizeHints2.value( Qt::MinimumSize ) );
+ childWidget2->setPreferredWidth( sizeHints2.value( Qt::PreferredSize ) );
+ childWidget2->setMaximumWidth( sizeHints2.value( Qt::MaximumSize ) );
+
+ widget.setGeometry( QRectF( QPoint(0,0), QSize( 100,100 ) ) );
+
+ // check results:
+ if ( width1 == -1.0f ) {
+ // invalid
+ QCOMPARE( layout->isValid() , false );
+ } else {
+ // valid
+ QCOMPARE( float(childWidget1->geometry().width()), float(width1) );
+ QCOMPARE( float(childWidget2->geometry().width()), float(width2) );
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testSizeHint()
+{
+ QGraphicsWidget *widget[5];
+
+ for( int i = 0; i < 5; i++ ) {
+ widget[i] = new QGraphicsWidget;
+ widget[i]->setMinimumSize( 10, 10 );
+ widget[i]->setPreferredSize( 20, 20 );
+ widget[i]->setMaximumSize( 40, 40 );
+ }
+
+ // one, basic
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, 0 );
+
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() );
+
+
+ delete layout;
+ }
+
+ // one, basic again
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 10 );
+ // layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, -10 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, 10 );
+
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 10 );
+ // layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, -10 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 10 );
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() + QSizeF( 20, 20 ) );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() + QSizeF( 20, 20 ) );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() + QSizeF( 20, 20 ) );
+
+ delete layout;
+ }
+
+ // two, serial
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+
+ layout->setAnchor(widget[0], Qt::AnchorRight, widget[1], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[1], Qt::AnchorRight, layout, Qt::AnchorRight, 0 );
+
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() + QSizeF( widget[1]->minimumWidth(), 0 ) );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() + QSizeF( widget[1]->preferredWidth(), 0 ) );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() + QSizeF( widget[1]->maximumWidth(), 0 ) );
+
+ delete layout;
+ }
+
+ // two, parallel
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, 0 );
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[1], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[1], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[1], Qt::AnchorBottom, 0 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[1], Qt::AnchorRight, 0 );
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() );
+
+ delete layout;
+ }
+
+ // five, serial
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+
+ layout->setAnchor(widget[0], Qt::AnchorRight, widget[1], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[1], Qt::AnchorRight, widget[2], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[2], Qt::AnchorRight, widget[3], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[3], Qt::AnchorRight, widget[4], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[4], Qt::AnchorRight, layout, Qt::AnchorRight, 0 );
+
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() +
+ QSizeF( widget[1]->minimumWidth() +
+ widget[2]->minimumWidth() +
+ widget[3]->minimumWidth() +
+ widget[4]->minimumWidth(), 0 ) );
+
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() +
+ QSizeF( widget[1]->preferredWidth() +
+ widget[2]->preferredWidth() +
+ widget[3]->preferredWidth() +
+ widget[4]->preferredWidth(), 0 ) );
+
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() +
+ QSizeF( widget[1]->maximumWidth() +
+ widget[2]->maximumWidth() +
+ widget[3]->maximumWidth() +
+ widget[4]->maximumWidth(), 0 ) );
+
+ delete layout;
+ }
+
+
+ for( int i = 0; i < 5; i++ ) {
+ delete widget[i];
+ }
+}
+
+#ifdef TEST_COMPLEX_CASES
+
+void tst_QGraphicsAnchorLayout1::testComplexCases_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<AnchorItemSizeHintList>("sizehint");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Three widgets, the same sizehint
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult1;
+ BasicLayoutTestResultList theResult2;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+ theResult1
+ << BasicResult(0, QRectF(10, 0, 30, 50) )
+ << BasicResult(1, QRectF(50, 0, 30, 50) )
+ << BasicResult(2, QRectF(50, 0, 30, 50) )
+ ;
+
+ theResult2
+ << BasicResult(0, QRectF(10, 0, 60, 50) )
+ << BasicResult(1, QRectF(80, 0, 60, 50) )
+ << BasicResult(2, QRectF(80, 0, 60, 50) )
+ ;
+
+ QTest::newRow("Three, the same sizehint(1)") << QSizeF(90, 50) << theData << theSizeHint << theResult1;
+ QTest::newRow("Three, the same sizehint(2)") << QSizeF(150, 50) << theData << theSizeHint << theResult2;
+ }
+
+ // Three widgets, serial is bigger
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 100, 200, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 0, 70, 50) )
+ << BasicResult(1, QRectF(90, 0, 35, 50) )
+ << BasicResult(2, QRectF(90, 0, 35, 50) );
+
+ QTest::newRow("Three, serial is bigger") << QSizeF(135, 50) << theData << theSizeHint << theResult;
+
+ // theResult
+ // << BasicResult(0, QRectF(10, 0, 80, 50) )
+ // << BasicResult(1, QRectF(100, 0, 60, 50) )
+ // << BasicResult(2, QRectF(100, 0, 60, 50) )
+ // ;
+
+ // QTest::newRow("Three, serial is bigger") << QSizeF(170, 50) << theData << theSizeHint << theResult;
+ }
+
+
+ // Three widgets, parallel is bigger
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 100, 200, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+
+ // ### QGAL uses a different preferred size calculation algorithm.
+ // This algorithm was discussed with Jan-Arve and tries to grow
+ // items instead of shrinking them.
+ // In this case, the preferred size of each item becomes:
+ // Item 0: 50
+ // Item 1: 100 (grows to avoid shrinking item 2)
+ // Item 2: 100
+ // Therefore, the preferred size of the parent widget becomes
+ // 180 == (10 + 50 + 10 + 100 + 10)
+ // As we set its size to 150, each widget is shrinked in the same
+ // ratio, in order to achieve the width of 150 == (10 + 40 + 10 + 80 + 10)
+
+ theResult
+ << BasicResult(0, QRectF(10, 0, 40, 50) )
+ << BasicResult(1, QRectF(60, 0, 80, 50) )
+ << BasicResult(2, QRectF(60, 0, 80, 50) )
+ ;
+
+ QTest::newRow("Three, parallel is bigger") << QSizeF(150, 50) << theData << theSizeHint << theResult;
+
+ // #ifdef PREFERRED_IS_AVERAGE
+ // theResult
+ // << BasicResult(0, QRectF(10, 0, 50, 50) )
+ // << BasicResult(1, QRectF(70, 0, 75, 50) )
+ // << BasicResult(2, QRectF(70, 0, 75, 50) )
+ // ;
+
+ // QTest::newRow("Three, parallel is bigger") << QSizeF(155, 50) << theData << theSizeHint << theResult;
+ // #else
+ // theResult
+ // << BasicResult(0, QRectF(10, 0, 50, 50) )
+ // << BasicResult(1, QRectF(70, 0, 66.66666666666666, 50) )
+ // << BasicResult(2, QRectF(70, 0, 60.66666666666666, 50) )
+ // ;
+
+ // QTest::newRow("Three, parallel is bigger") << QSizeF(146.66666666666666, 50) << theData << theSizeHint << theResult;
+ // #endif
+ }
+
+ // Three widgets, the same sizehint, one center anchor
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+ theResult
+ << BasicResult(0, QRectF(10, 0, 40, 50) )
+ << BasicResult(1, QRectF(60, 0, 40, 50) )
+ << BasicResult(2, QRectF(40, 0, 60, 50) )
+ ;
+
+ ;
+
+ QTest::newRow("Three, the same sizehint, one center anchor") << QSizeF(110, 50) << theData << theSizeHint << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testComplexCases()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(BasicLayoutTestDataList, data);
+ QFETCH(AnchorItemSizeHintList, sizehint);
+ QFETCH(BasicLayoutTestResultList, result);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ // Determine amount of widgets to add.
+ int widgetCount = -1;
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ widgetCount = qMax(widgetCount, item.firstIndex);
+ widgetCount = qMax(widgetCount, item.secondIndex);
+ }
+ ++widgetCount; // widgetCount is max of indices.
+
+ // Create dummy widgets
+ QList<QGraphicsWidget *> widgets;
+ for (int i = 0; i < widgetCount; ++i) {
+ TestWidget *w = new TestWidget;
+
+ w->setMinimumWidth( sizehint[i].hmin );
+ w->setPreferredWidth( sizehint[i].hpref );
+ w->setMaximumWidth( sizehint[i].hmax );
+
+ w->setMinimumHeight( sizehint[i].vmin );
+ w->setPreferredHeight( sizehint[i].vpref );
+ w->setMaximumHeight( sizehint[i].vmax );
+
+ widgets << w;
+ }
+
+ // Setup anchor layout
+ TheAnchorLayout *layout = new TheAnchorLayout;
+
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ layout->setAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge,
+ item.spacing );
+ }
+
+ widget->setLayout(layout);
+ widget->setContentsMargins(0,0,0,0);
+
+ widget->resize(size);
+ QCOMPARE(widget->size(), size);
+
+// QTest::qWait(500); // layouting is asynchronous..
+
+ // Validate
+ for (int i = 0; i < result.count(); ++i) {
+ const BasicLayoutTestResult item = result[i];
+ QCOMPARE(widgets[item.index]->geometry(), item.rect);
+ }
+
+ // Test mirrored mode
+ widget->setLayoutDirection(Qt::RightToLeft);
+ layout->activate();
+ // Validate
+ for (int j = 0; j < result.count(); ++j) {
+ const BasicLayoutTestResult item = result[j];
+ QRectF mirroredRect(item.rect);
+ // only valid cases are mirrored
+ if (mirroredRect.isValid()){
+ mirroredRect.moveLeft(size.width()-item.rect.width()-item.rect.left());
+ }
+ QCOMPARE(widgets[item.index]->geometry(), mirroredRect);
+ delete widgets[item.index];
+ }
+
+ delete widget;
+}
+#endif //TEST_COMPLEX_CASES
+
+
+QTEST_MAIN(tst_QGraphicsAnchorLayout1)
+#include "tst_qgraphicsanchorlayout1.moc"
+//-----------------------------------------------------------------------------
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro b/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
new file mode 100644
index 0000000000..44ec70eef3
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicseffectsource.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
new file mode 100644
index 0000000000..4f39f991c6
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qgraphicseffect.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qgraphicsscene.h>
+#include <QtWidgets/qgraphicsitem.h>
+#include <QtWidgets/qstyleoption.h>
+
+#include <private/qgraphicseffect_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class CustomItem : public QGraphicsRectItem
+{
+public:
+ CustomItem(qreal x, qreal y, qreal width, qreal height)
+ : QGraphicsRectItem(x, y, width, height), numRepaints(0),
+ m_painter(0)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ m_painter = painter;
+ ++numRepaints;
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+
+ void reset()
+ {
+ numRepaints = 0;
+ m_painter = 0;
+ }
+
+ int numRepaints;
+ QPainter *m_painter;
+};
+
+class CustomEffect : public QGraphicsEffect
+{
+public:
+ CustomEffect()
+ : QGraphicsEffect(), numRepaints(0), m_margin(10), m_sourceChanged(false),
+ m_sourceBoundingRectChanged(false), doNothingInDraw(false),
+ storeDeviceDependentStuff(false),
+ m_painter(0), m_source(0)
+ {}
+
+ QRectF boundingRectFor(const QRectF &rect) const
+ { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); }
+
+ void reset()
+ {
+ numRepaints = 0;
+ m_sourceChanged = false;
+ m_sourceBoundingRectChanged = false;
+ m_painter = 0;
+ m_source = 0;
+ deviceCoordinatesPixmap = QPixmap();
+ deviceRect = QRect();
+ sourceDeviceBoundingRect = QRectF();
+ }
+
+ void setMargin(int margin)
+ {
+ m_margin = margin;
+ updateBoundingRect();
+ }
+
+ int margin() const
+ { return m_margin; }
+
+ void draw(QPainter *painter)
+ {
+ ++numRepaints;
+ if (storeDeviceDependentStuff) {
+ deviceCoordinatesPixmap = source()->pixmap(Qt::DeviceCoordinates);
+ deviceRect = QRect(0, 0, painter->device()->width(), painter->device()->height());
+ sourceDeviceBoundingRect = source()->boundingRect(Qt::DeviceCoordinates);
+ }
+ if (doNothingInDraw)
+ return;
+ m_source = source();
+ m_painter = painter;
+ source()->draw(painter);
+ }
+
+ void sourceChanged()
+ { m_sourceChanged = true; }
+
+ void sourceBoundingRectChanged()
+ { m_sourceBoundingRectChanged = true; }
+
+ int numRepaints;
+ int m_margin;
+ bool m_sourceChanged;
+ bool m_sourceBoundingRectChanged;
+ bool doNothingInDraw;
+ bool storeDeviceDependentStuff;
+ QPainter *m_painter;
+ QGraphicsEffectSource *m_source;
+ QPixmap deviceCoordinatesPixmap;
+ QRect deviceRect;
+ QRectF sourceDeviceBoundingRect;
+};
+
+class tst_QGraphicsEffectSource : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+
+private slots:
+ void graphicsItem();
+ void styleOption();
+ void isPixmap();
+ void draw();
+ void update();
+ void boundingRect();
+ void clippedBoundingRect();
+ void deviceRect();
+ void pixmap();
+
+ void pixmapPadding_data();
+ void pixmapPadding();
+
+private:
+ QGraphicsView *view;
+ QGraphicsScene *scene;
+ CustomItem *item;
+ CustomEffect *effect;
+};
+
+void tst_QGraphicsEffectSource::initTestCase()
+{
+ scene = new QGraphicsScene;
+ item = new CustomItem(0, 0, 100, 100);
+ effect = new CustomEffect;
+ item->setGraphicsEffect(effect);
+ scene->addItem(item);
+ view = new QGraphicsView(scene);
+ view->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(view);
+#endif
+ QTest::qWait(200);
+}
+
+void tst_QGraphicsEffectSource::cleanupTestCase()
+{
+ delete view;
+}
+
+void tst_QGraphicsEffectSource::init()
+{
+ QVERIFY(effect);
+ QVERIFY(item);
+ QVERIFY(effect->source());
+ effect->reset();
+ effect->storeDeviceDependentStuff = false;
+ effect->doNothingInDraw = false;
+ item->reset();
+}
+
+void tst_QGraphicsEffectSource::graphicsItem()
+{
+ QVERIFY(effect->source());
+ QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
+}
+
+void tst_QGraphicsEffectSource::styleOption()
+{
+ // We don't have style options unless the source is drawing.
+ QVERIFY(effect->source());
+ QVERIFY(!effect->source()->styleOption());
+
+ // Trigger an update and check that the style option in QGraphicsEffect::draw
+ // was the same as the one in QGraphicsItem::paint.
+ QCOMPARE(item->numRepaints, 0);
+ QCOMPARE(effect->numRepaints, 0);
+ item->update();
+ QTRY_COMPARE(item->numRepaints, 1);
+ QTRY_COMPARE(effect->numRepaints, 1);
+}
+
+void tst_QGraphicsEffectSource::isPixmap()
+{
+ // Current source is a CustomItem (which is not a pixmap item).
+ QVERIFY(!effect->source()->isPixmap());
+
+ // Make sure isPixmap() returns true for QGraphicsPixmapItem.
+ QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem;
+ CustomEffect *anotherEffect = new CustomEffect;
+ pixmapItem->setGraphicsEffect(anotherEffect);
+ QVERIFY(anotherEffect->source());
+ QCOMPARE(anotherEffect->source()->graphicsItem(), static_cast<const QGraphicsItem *>(pixmapItem));
+ QVERIFY(anotherEffect->source()->isPixmap());
+ delete pixmapItem;
+}
+
+void tst_QGraphicsEffectSource::draw()
+{
+ // The source can only draw as a result of QGraphicsEffect::draw.
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
+ QPixmap dummyPixmap(10, 10);
+ QPainter dummyPainter(&dummyPixmap);
+ effect->source()->draw(&dummyPainter);
+}
+
+void tst_QGraphicsEffectSource::update()
+{
+ QCOMPARE(item->numRepaints, 0);
+ QCOMPARE(effect->numRepaints, 0);
+
+ effect->source()->update();
+
+ QTRY_COMPARE(item->numRepaints, 1);
+ QTRY_COMPARE(effect->numRepaints, 1);
+}
+
+void tst_QGraphicsEffectSource::boundingRect()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
+ QCOMPARE(effect->source()->boundingRect(Qt::DeviceCoordinates), QRectF());
+
+ QRectF itemBoundingRect = item->boundingRect();
+ if (!item->children().isEmpty())
+ itemBoundingRect |= item->childrenBoundingRect();
+
+ // We can at least check that the device bounding rect was correct in QGraphicsEffect::draw.
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ const QTransform deviceTransform = item->deviceTransform(view->viewportTransform());
+ QTRY_COMPARE(effect->sourceDeviceBoundingRect, deviceTransform.mapRect(itemBoundingRect));
+
+ // Bounding rect in logical coordinates is of course fine.
+ QTRY_COMPARE(effect->source()->boundingRect(Qt::LogicalCoordinates), itemBoundingRect);
+ // Make sure default value is Qt::LogicalCoordinates.
+ QTRY_COMPARE(effect->source()->boundingRect(), itemBoundingRect);
+}
+
+void tst_QGraphicsEffectSource::clippedBoundingRect()
+{
+ QRectF itemBoundingRect = item->boundingRect();
+ item->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsRectItem *child = new QGraphicsRectItem(-1000, -1000, 2000, 2000);
+ child->setBrush(Qt::red);
+ child->setParentItem(item);
+
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ QTRY_COMPARE(effect->source()->boundingRect(Qt::LogicalCoordinates), itemBoundingRect);
+}
+
+void tst_QGraphicsEffectSource::deviceRect()
+{
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ QTRY_COMPARE(effect->deviceRect, view->viewport()->rect());
+}
+
+void tst_QGraphicsEffectSource::pixmap()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+ QCOMPARE(effect->source()->pixmap(Qt::DeviceCoordinates), QPixmap());
+
+ // We can at least verify a valid pixmap from QGraphicsEffect::draw.
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ QTRY_VERIFY(!effect->deviceCoordinatesPixmap.isNull());
+
+ // Pixmaps in logical coordinates we can do fine.
+ QPixmap pixmap1 = effect->source()->pixmap(Qt::LogicalCoordinates);
+ QVERIFY(!pixmap1.isNull());
+
+ // Make sure default value is Qt::LogicalCoordinates.
+ QPixmap pixmap2 = effect->source()->pixmap();
+ QCOMPARE(pixmap1, pixmap2);
+}
+
+class PaddingEffect : public QGraphicsEffect
+{
+public:
+ PaddingEffect(QObject *parent) : QGraphicsEffect(parent)
+ {
+ }
+
+ QRectF boundingRectFor(const QRectF &src) const {
+ return src.adjusted(-10, -10, 10, 10);
+ }
+
+ void draw(QPainter *) {
+ pix = source()->pixmap(coordinateMode, &offset, padMode);
+ }
+
+ QPixmap pix;
+ QPoint offset;
+ QGraphicsEffect::PixmapPadMode padMode;
+ Qt::CoordinateSystem coordinateMode;
+};
+
+void tst_QGraphicsEffectSource::pixmapPadding_data()
+{
+ QTest::addColumn<int>("coordinateMode");
+ QTest::addColumn<int>("padMode");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QPoint>("offset");
+ QTest::addColumn<uint>("ulPixel");
+
+ QTest::newRow("log,nopad") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffect::NoPad)
+ << QSize(10, 10) << QPoint(0, 0)
+ << 0xffff0000u;
+
+ QTest::newRow("log,transparent") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffect::PadToTransparentBorder)
+ << QSize(14, 14) << QPoint(-2, -2)
+ << 0x00000000u;
+
+ QTest::newRow("log,effectrect") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffect::PadToEffectiveBoundingRect)
+ << QSize(20, 20) << QPoint(-5, -5)
+ << 0x00000000u;
+
+ QTest::newRow("dev,nopad") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffect::NoPad)
+ << QSize(20, 20) << QPoint(40, 40)
+ << 0xffff0000u;
+
+ QTest::newRow("dev,transparent") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffect::PadToTransparentBorder)
+ << QSize(24, 24) << QPoint(38, 38)
+ << 0x00000000u;
+
+ QTest::newRow("dev,effectrect") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffect::PadToEffectiveBoundingRect)
+ << QSize(40, 40) << QPoint(30, 30)
+ << 0x00000000u;
+
+}
+
+void tst_QGraphicsEffectSource::pixmapPadding()
+{
+ QPixmap dummyTarget(100, 100);
+ QPainter dummyPainter(&dummyTarget);
+ dummyPainter.translate(40, 40);
+ dummyPainter.scale(2, 2);
+
+ QPixmap pm(10, 10);
+ pm.fill(Qt::red);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ PaddingEffect *effect = new PaddingEffect(scene);
+ QGraphicsPixmapItem *pmItem = new QGraphicsPixmapItem(pm);
+ scene->addItem(pmItem);
+ pmItem->setGraphicsEffect(effect);
+
+ QFETCH(int, coordinateMode);
+ QFETCH(int, padMode);
+ QFETCH(QPoint, offset);
+ QFETCH(QSize, size);
+ QFETCH(uint, ulPixel);
+
+ effect->padMode = (QGraphicsEffect::PixmapPadMode) padMode;
+ effect->coordinateMode = (Qt::CoordinateSystem) coordinateMode;
+
+ scene->render(&dummyPainter, scene->itemsBoundingRect(), scene->itemsBoundingRect());
+
+ QCOMPARE(effect->pix.size(), size);
+ QCOMPARE(effect->offset, offset);
+ QCOMPARE(effect->pix.toImage().pixel(0, 0), ulPixel);
+
+ // ### Fix corruption in scene destruction, then enable...
+ // delete scene;
+}
+
+QTEST_MAIN(tst_QGraphicsEffectSource)
+#include "tst_qgraphicseffectsource.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore
new file mode 100644
index 0000000000..e3a8cc317c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsgridlayout
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
new file mode 100644
index 0000000000..7db7c1ae6f
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+
+QT += widgets
+SOURCES += tst_qgraphicsgridlayout.cpp
+CONFIG += parallel_test
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
new file mode 100644
index 0000000000..e9d9cb67bb
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
@@ -0,0 +1,3465 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsgridlayout.h>
+#include <qgraphicswidget.h>
+#include <qgraphicsscene.h>
+#include <qgraphicsview.h>
+
+class tst_QGraphicsGridLayout : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicsgridlayout_data();
+ void qgraphicsgridlayout();
+ void addItem_data();
+ void addItem();
+#ifndef Q_WS_MAC
+ void alignment_data();
+ void alignment();
+#endif
+ void alignment2();
+ void alignment2_data();
+#ifndef Q_WS_MAC
+ void columnAlignment_data();
+ void columnAlignment();
+#endif
+ void columnCount_data();
+ void columnCount();
+ void columnMaximumWidth_data();
+ void columnMaximumWidth();
+ void columnMinimumWidth_data();
+ void columnMinimumWidth();
+ void columnPreferredWidth_data();
+ void columnPreferredWidth();
+ void setColumnFixedWidth();
+ void columnSpacing();
+ void columnStretchFactor();
+ void count();
+ void contentsMargins();
+ void horizontalSpacing_data();
+ void horizontalSpacing();
+ void itemAt();
+ void removeAt();
+ void removeItem();
+ void rowAlignment_data();
+ void rowAlignment();
+ void rowCount_data();
+ void rowCount();
+ void rowMaximumHeight_data();
+ void rowMaximumHeight();
+ void rowMinimumHeight_data();
+ void rowMinimumHeight();
+ void rowPreferredHeight_data();
+ void rowPreferredHeight();
+ void rowSpacing();
+ void rowStretchFactor_data();
+ void rowStretchFactor();
+ void setColumnSpacing_data();
+ void setColumnSpacing();
+ void setGeometry_data();
+ void setGeometry();
+ void setRowFixedHeight();
+ void setRowSpacing_data();
+ void setRowSpacing();
+ void setSpacing_data();
+ void setSpacing();
+ void sizeHint_data();
+ void sizeHint();
+ void verticalSpacing_data();
+ void verticalSpacing();
+ void layoutDirection_data();
+ void layoutDirection();
+ void removeLayout();
+ void defaultStretchFactors_data();
+ void defaultStretchFactors();
+ void geometries_data();
+ void geometries();
+ void avoidRecursionInInsertItem();
+ void styleInfoLeak();
+ void task236367_maxSizeHint();
+ void spanningItem2x2_data();
+ void spanningItem2x2();
+ void spanningItem2x3_data();
+ void spanningItem2x3();
+ void spanningItem();
+ void heightForWidth();
+ void widthForHeight();
+ void heightForWidthWithSpanning();
+ void stretchAndHeightForWidth();
+ void testDefaultAlignment();
+};
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent), m_fnConstraint(0) {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ if (constraint.width() < 0 && constraint.height() < 0 && m_sizeHints[which].isValid()) {
+ return m_sizeHints[which];
+ }
+ if (m_fnConstraint) {
+ return m_fnConstraint(which, constraint);
+ }
+ return QGraphicsWidget::sizeHint(which, constraint);
+ }
+
+ void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
+ m_sizeHints[which] = size;
+ updateGeometry();
+ }
+
+ void setConstraintFunction(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &)) {
+ m_fnConstraint = fnConstraint;
+ }
+
+ QSizeF m_sizeHints[Qt::NSizeHints];
+ QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &);
+
+};
+
+struct ItemDesc
+{
+ ItemDesc(int row, int col)
+ : m_pos(qMakePair(row, col)),
+ m_rowSpan(1),
+ m_colSpan(1),
+ m_sizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)),
+ m_align(0),
+ m_fnConstraint(0)
+ {
+ }
+
+ ItemDesc &rowSpan(int span) {
+ m_rowSpan = span;
+ return (*this);
+ }
+
+ ItemDesc &colSpan(int span) {
+ m_colSpan = span;
+ return (*this);
+ }
+
+ ItemDesc &sizePolicy(const QSizePolicy &sp) {
+ m_sizePolicy = sp;
+ return (*this);
+ }
+
+ ItemDesc &sizePolicy(QSizePolicy::Policy horAndVer) {
+ m_sizePolicy = QSizePolicy(horAndVer, horAndVer);
+ return (*this);
+ }
+
+ ItemDesc &sizePolicyH(QSizePolicy::Policy hor) {
+ m_sizePolicy.setHorizontalPolicy(hor);
+ return (*this);
+ }
+
+ ItemDesc &sizePolicyV(QSizePolicy::Policy ver) {
+ m_sizePolicy.setVerticalPolicy(ver);
+ return (*this);
+ }
+
+ ItemDesc &sizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver) {
+ m_sizePolicy = QSizePolicy(hor, ver);
+ return (*this);
+ }
+
+ ItemDesc &sizeHint(Qt::SizeHint which, const QSizeF &sh) {
+ m_sizeHints[which] = sh;
+ return (*this);
+ }
+
+ ItemDesc &preferredSizeHint(const QSizeF &sh) {
+ m_sizeHints[Qt::PreferredSize] = sh;
+ return (*this);
+ }
+
+ ItemDesc &minSize(const QSizeF &sz) {
+ m_sizes[Qt::MinimumSize] = sz;
+ return (*this);
+ }
+ ItemDesc &preferredSize(const QSizeF &sz) {
+ m_sizes[Qt::PreferredSize] = sz;
+ return (*this);
+ }
+ ItemDesc &maxSize(const QSizeF &sz) {
+ m_sizes[Qt::MaximumSize] = sz;
+ return (*this);
+ }
+
+ ItemDesc &alignment(Qt::Alignment alignment) {
+ m_align = alignment;
+ return (*this);
+ }
+
+ ItemDesc &dynamicConstraint(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &),
+ Qt::Orientation orientation) {
+ m_fnConstraint = fnConstraint;
+ m_constraintOrientation = orientation;
+ return (*this);
+ }
+
+ void apply(QGraphicsGridLayout *layout, QGraphicsWidget *item) {
+ QSizePolicy sp = m_sizePolicy;
+ if (m_fnConstraint) {
+ sp.setHeightForWidth(m_constraintOrientation == Qt::Vertical);
+ sp.setWidthForHeight(m_constraintOrientation == Qt::Horizontal);
+ }
+
+ item->setSizePolicy(sp);
+ for (int i = 0; i < Qt::NSizeHints; ++i) {
+ if (!m_sizes[i].isValid())
+ continue;
+ switch ((Qt::SizeHint)i) {
+ case Qt::MinimumSize:
+ item->setMinimumSize(m_sizes[i]);
+ break;
+ case Qt::PreferredSize:
+ item->setPreferredSize(m_sizes[i]);
+ break;
+ case Qt::MaximumSize:
+ item->setMaximumSize(m_sizes[i]);
+ break;
+ default:
+ qWarning("not implemented");
+ break;
+ }
+ }
+
+ layout->addItem(item, m_pos.first, m_pos.second, m_rowSpan, m_colSpan);
+ layout->setAlignment(item, m_align);
+ }
+
+ void apply(QGraphicsGridLayout *layout, RectWidget *item) {
+ for (int i = 0; i < Qt::NSizeHints; ++i)
+ item->setSizeHint((Qt::SizeHint)i, m_sizeHints[i]);
+ item->setConstraintFunction(m_fnConstraint);
+ apply(layout, static_cast<QGraphicsWidget*>(item));
+ }
+
+//private:
+ QPair<int,int> m_pos; // row,col
+ int m_rowSpan;
+ int m_colSpan;
+ QSizePolicy m_sizePolicy;
+ QSizeF m_sizeHints[Qt::NSizeHints];
+ QSizeF m_sizes[Qt::NSizeHints];
+ Qt::Alignment m_align;
+
+ Qt::Orientation m_constraintOrientation;
+ QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &);
+};
+
+typedef QList<ItemDesc> ItemList;
+Q_DECLARE_METATYPE(ItemList);
+
+typedef QList<QSizeF> SizeList;
+Q_DECLARE_METATYPE(SizeList);
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsGridLayout::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsGridLayout::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsGridLayout::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// This will be called after every test function.
+void tst_QGraphicsGridLayout::cleanup()
+{
+}
+
+void tst_QGraphicsGridLayout::qgraphicsgridlayout_data()
+{
+}
+
+void tst_QGraphicsGridLayout::qgraphicsgridlayout()
+{
+ QGraphicsGridLayout layout;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: invalid row span/column span: 0");
+ layout.addItem(0, 0, 0, 0, 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: cannot add null item");
+ layout.addItem(0, 0, 0);
+ layout.alignment(0);
+ layout.columnAlignment(0);
+ layout.columnCount();
+ layout.columnMaximumWidth(0);
+ layout.columnMinimumWidth(0);
+ layout.columnPreferredWidth(0);
+ layout.columnSpacing(0);
+ layout.columnStretchFactor(0);
+ layout.count();
+ layout.horizontalSpacing();
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::itemAt: invalid row, column 0, 0");
+ layout.itemAt(0, 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::itemAt: invalid index 0");
+ layout.itemAt(0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::removeAt: invalid index 0");
+ layout.removeAt(0);
+ layout.rowAlignment(0);
+ layout.rowCount();
+ layout.rowMaximumHeight(0);
+ layout.rowMinimumHeight(0);
+ layout.rowPreferredHeight(0);
+ layout.rowSpacing(0);
+ layout.rowStretchFactor(0);
+ layout.setAlignment(0, Qt::AlignRight);
+ layout.setColumnAlignment(0, Qt::AlignRight);
+ layout.setColumnFixedWidth(0, 0);
+ layout.setColumnMaximumWidth(0, 0);
+ layout.setColumnMinimumWidth(0, 0);
+ layout.setColumnPreferredWidth(0, 0);
+ layout.setColumnSpacing(0, 0);
+ layout.setColumnStretchFactor(0, 0);
+ layout.setGeometry(QRectF());
+ layout.setHorizontalSpacing(0);
+ layout.setRowAlignment(0, 0);
+ layout.setRowFixedHeight(0, 0);
+ layout.setRowMaximumHeight(0, 0);
+ layout.setRowMinimumHeight(0, 0);
+ layout.setRowPreferredHeight(0, 0);
+ layout.setRowSpacing(0, 0);
+ layout.setRowStretchFactor(0, 0);
+ layout.setSpacing(0);
+ layout.setVerticalSpacing(0);
+ layout.sizeHint(Qt::MinimumSize);
+ layout.verticalSpacing();
+}
+
+static void populateLayout(QGraphicsGridLayout *gridLayout, int width, int height, bool hasHeightForWidth = false)
+{
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ QGraphicsWidget *item = new RectWidget();
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ gridLayout->addItem(item, y, x);
+ QSizePolicy policy = item->sizePolicy();
+ policy.setHeightForWidth(hasHeightForWidth);
+ item->setSizePolicy(policy);
+ }
+ }
+}
+
+
+/** populates \a gridLayout with a 3x2 layout:
+ * +----+----+----+
+ * |+---|---+|xxxx|
+ * ||span=2 ||hole|
+ * |+---|---+|xxxx|
+ * +----+----+----+
+ * |xxxx|+---|---+|
+ * |hole||span=2 ||
+ * |xxxx|+---|---+|
+ * +----+----+----+
+ */
+static void populateLayoutWithSpansAndHoles(QGraphicsGridLayout *gridLayout, bool hasHeightForWidth = false)
+{
+ QGraphicsWidget *item = new RectWidget();
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ QSizePolicy sizepolicy = item->sizePolicy();
+ sizepolicy.setHeightForWidth(hasHeightForWidth);
+ item->setSizePolicy(sizepolicy);
+ gridLayout->addItem(item, 0, 0, 1, 2);
+
+ item = new RectWidget();
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ item->setSizePolicy(sizepolicy);
+ gridLayout->addItem(item, 1, 1, 1, 2);
+}
+
+Q_DECLARE_METATYPE(Qt::Alignment)
+void tst_QGraphicsGridLayout::addItem_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+ QTest::addColumn<Qt::Alignment>("alignment");
+
+ for (int a = -1; a < 3; ++a) {
+ for (int b = -1; b < 2; ++b) {
+ for (int c = -1; c < 2; ++c) {
+ for (int d = -1; d < 2; ++d) {
+ for (int e = 0; e < 9; ++e) {
+ int row = a;
+ int column = b;
+ int rowSpan = c;
+ int columnSpan = d;
+ QString name = QString::fromAscii("(%1,%2,%3,%4").arg(a).arg(b).arg(c).arg(d);
+ Qt::Alignment alignment = Qt::AlignLeft;
+ QTest::newRow(name.toLatin1()) << row << column << rowSpan << columnSpan << alignment;
+ }}}}}
+}
+
+// public void addItem(QGraphicsLayoutItem* item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = 0)
+void tst_QGraphicsGridLayout::addItem()
+{
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+ QFETCH(Qt::Alignment, alignment);
+
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+
+ QGraphicsWidget *wid = new QGraphicsWidget;
+ if (row < 0 || column < 0) {
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: invalid row/column: -1");
+ } else if (rowSpan < 1 || columnSpan < 1) {
+ char buf[1024];
+ ::qsnprintf(buf, sizeof(buf), "QGraphicsGridLayout::addItem: invalid row span/column span: %d",
+ rowSpan < 1 ? rowSpan : columnSpan);
+ QTest::ignoreMessage(QtWarningMsg, buf);
+ }
+ layout->addItem(wid, row, column, rowSpan, columnSpan, alignment);
+
+ delete layout;
+}
+
+// Resizing a QGraphicsWidget to effectiveSizeHint(Qt::MaximumSize) is currently not supported on mac.
+#ifndef Q_WS_MAC
+void tst_QGraphicsGridLayout::alignment_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public Qt::Alignment alignment(QGraphicsLayoutItem* item) const
+void tst_QGraphicsGridLayout::alignment()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+ // no alignment (the default)
+ QCOMPARE(layout->itemAt(0, 0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(0, 0)->geometry().right(), layout->itemAt(0, 1)->geometry().left());
+ QCOMPARE(layout->itemAt(0, 1)->geometry().left(), 25.0);
+ QCOMPARE(layout->itemAt(0, 1)->geometry().right(), layout->itemAt(0, 2)->geometry().left());
+ QCOMPARE(layout->itemAt(0, 2)->geometry().left(), 50.0);
+ QCOMPARE(layout->itemAt(0, 2)->geometry().right(), 75.0);
+
+ QCOMPARE(layout->itemAt(1, 0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(1, 0)->geometry().right(), layout->itemAt(1, 1)->geometry().left());
+ QCOMPARE(layout->itemAt(1, 1)->geometry().left(), 25.0);
+ QCOMPARE(layout->itemAt(1, 1)->geometry().right(), layout->itemAt(1, 2)->geometry().left());
+ QCOMPARE(layout->itemAt(1, 2)->geometry().left(), 50.0);
+ QCOMPARE(layout->itemAt(1, 2)->geometry().right(), 75.0);
+
+ QCOMPARE(layout->itemAt(0, 0)->geometry().top(), 0.0);
+ QCOMPARE(layout->itemAt(0, 0)->geometry().bottom(), layout->itemAt(1, 0)->geometry().top());
+ QCOMPARE(layout->itemAt(1, 0)->geometry().top(), 25.0);
+ QCOMPARE(layout->itemAt(1, 0)->geometry().bottom(), 50.0);
+
+ // align first column left, second hcenter, third right
+ layout->setColumnMinimumWidth(0, 100);
+ layout->setAlignment(layout->itemAt(0,0), Qt::AlignLeft);
+ layout->setAlignment(layout->itemAt(1,0), Qt::AlignLeft);
+ layout->setColumnMinimumWidth(1, 100);
+ layout->setAlignment(layout->itemAt(0,1), Qt::AlignHCenter);
+ layout->setAlignment(layout->itemAt(1,1), Qt::AlignHCenter);
+ layout->setColumnMinimumWidth(2, 100);
+ layout->setAlignment(layout->itemAt(0,2), Qt::AlignRight);
+ layout->setAlignment(layout->itemAt(1,2), Qt::AlignRight);
+
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(125, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(125, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(250, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(250, 50, 50, 50));
+
+ delete widget;
+}
+#endif
+
+// Resizing a QGraphicsWidget to effectiveSizeHint(Qt::MaximumSize) is currently not supported on mac.
+#ifndef Q_WS_MAC
+void tst_QGraphicsGridLayout::columnAlignment_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public void setColumnAlignment(int column, Qt::Alignment alignment)
+// public Qt::Alignment columnAlignment(int column) const
+void tst_QGraphicsGridLayout::columnAlignment()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(1);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ layout->setColumnMinimumWidth(0, 100);
+ layout->setColumnMinimumWidth(1, 100);
+ layout->setColumnMinimumWidth(2, 100);
+
+ view.resize(450,150);
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ view.show();
+ widget->show();
+ QApplication::sendPostedEvents(0, 0);
+ // Check default
+ QCOMPARE(layout->columnAlignment(0), 0);
+ QCOMPARE(layout->columnAlignment(1), 0);
+ QCOMPARE(layout->columnAlignment(2), 0);
+
+ layout->setColumnAlignment(0, Qt::AlignLeft);
+ layout->setColumnAlignment(1, Qt::AlignHCenter);
+ layout->setColumnAlignment(2, Qt::AlignRight);
+
+ // see if item alignment takes preference over columnAlignment
+ layout->setAlignment(layout->itemAt(1,0), Qt::AlignHCenter);
+ layout->setAlignment(layout->itemAt(1,1), Qt::AlignRight);
+ layout->setAlignment(layout->itemAt(1,2), Qt::AlignLeft);
+
+ QApplication::sendPostedEvents(0, 0); // process LayoutRequest
+ /*
+ +----------+------------+---------+
+ | Left | HCenter | Right |
+ +----------+------------+---------+
+ | HCenter | Right | Left |
+ +---------------------------------+
+ */
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(25, 51, 50, 50)); // item is king
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(126, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(151, 51, 50, 50)); // item is king
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(252, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(202, 51, 50, 50)); // item is king
+
+ delete widget;
+}
+#endif
+
+void tst_QGraphicsGridLayout::columnCount_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public int columnCount() const
+void tst_QGraphicsGridLayout::columnCount()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ view.show();
+ widget->show();
+ QApplication::processEvents();
+
+ QCOMPARE(layout->columnCount(), 0);
+ layout->addItem(new RectWidget(widget), 0, 0);
+ QCOMPARE(layout->columnCount(), 1);
+ layout->addItem(new RectWidget(widget), 1, 1);
+ QCOMPARE(layout->columnCount(), 2);
+ layout->addItem(new RectWidget(widget), 0, 2);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->addItem(new RectWidget(widget), 1, 0);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->addItem(new RectWidget(widget), 0, 1);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->addItem(new RectWidget(widget), 1, 2);
+ QCOMPARE(layout->columnCount(), 3);
+
+ // ### Talk with Jasmin. Not sure if removeAt() should adjust columnCount().
+ widget->setLayout(0);
+ layout = new QGraphicsGridLayout();
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(5);
+ layout->removeAt(3);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(1);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->columnCount(), 2);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::columnMaximumWidth_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal columnMaximumWidth(int column) const
+void tst_QGraphicsGridLayout::columnMaximumWidth()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(10+10+10, 10+10));
+ QCOMPARE(layout->preferredSize(), QSizeF(25+25+25, 25+25));
+ QCOMPARE(layout->maximumSize(), QSizeF(50+50+50, 50+50));
+
+ // should at least be a very large number
+ QVERIFY(layout->columnMaximumWidth(0) >= 10000);
+ QCOMPARE(layout->columnMaximumWidth(0), layout->columnMaximumWidth(1));
+ QCOMPARE(layout->columnMaximumWidth(1), layout->columnMaximumWidth(2));
+ layout->setColumnMaximumWidth(0, 20);
+ layout->setColumnMaximumWidth(2, 60);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(10+10+10, 10+10));
+ QCOMPARE(layout->preferredSize(), QSizeF(20+25+25, 25+25));
+ QCOMPARE(layout->maximumSize(), QSizeF(20+50+60, 50+50));
+ QCOMPARE(layout->maximumSize(), widget->maximumSize());
+
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ layout->activate();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 25));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 25, 20, 25));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 25, 25));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 25, 25, 25));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(45, 0, 25, 25));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(45, 25, 25, 25));
+
+ layout->setColumnAlignment(2, Qt::AlignCenter);
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,20+50+60, 50+50));
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 50, 20, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(75, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(75, 50, 50, 50));
+
+ for (int i = 0; i < layout->count(); i++)
+ layout->setAlignment(layout->itemAt(i), Qt::AlignRight | Qt::AlignBottom);
+ layout->activate();
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 50, 20, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(80, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(80, 50, 50, 50));
+ for (int i = 0; i < layout->count(); i++)
+ layout->setAlignment(layout->itemAt(i), Qt::AlignCenter);
+
+ layout->setMaximumSize(layout->maximumSize() + QSizeF(60,60));
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ layout->activate();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 15, 20, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 95, 20, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20+30, 15, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20+30, 95, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(20+60+50+5, 15, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(20+60+50+5, 95, 50, 50));
+
+ layout->setMaximumSize(layout->preferredSize() + QSizeF(20,20));
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ layout->activate();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 35));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 35, 20, 35));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 35, 35));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 35, 35, 35));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(55, 0, 35, 35));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(55, 35, 35, 35));
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::columnMinimumWidth_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal columnMinimumWidth(int column) const
+void tst_QGraphicsGridLayout::columnMinimumWidth()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // should at least be a very large number
+ QCOMPARE(layout->columnMinimumWidth(0), 0.0);
+ QCOMPARE(layout->columnMinimumWidth(0), layout->columnMinimumWidth(1));
+ QCOMPARE(layout->columnMinimumWidth(1), layout->columnMinimumWidth(2));
+ layout->setColumnMinimumWidth(0, 20);
+ layout->setColumnMinimumWidth(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().width(), 40.0);
+ QCOMPARE(layout->itemAt(1,2)->geometry().width(), 40.0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::columnPreferredWidth_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal columnPreferredWidth(int column) const
+void tst_QGraphicsGridLayout::columnPreferredWidth()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // default preferred width ??
+ QCOMPARE(layout->columnPreferredWidth(0), 0.0);
+ QCOMPARE(layout->columnPreferredWidth(0), layout->columnPreferredWidth(1));
+ QCOMPARE(layout->columnPreferredWidth(1), layout->columnPreferredWidth(2));
+ layout->setColumnPreferredWidth(0, 20);
+ layout->setColumnPreferredWidth(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().width(), 40.0);
+ QCOMPARE(layout->itemAt(1,2)->geometry().width(), 40.0);
+
+ delete widget;
+}
+
+// public void setColumnFixedWidth(int row, qreal height)
+void tst_QGraphicsGridLayout::setColumnFixedWidth()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setColumnFixedWidth(0, 20);
+ layout->setColumnFixedWidth(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().width(), 20.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().width(), 20.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().width(), 40.0);
+ QCOMPARE(layout->itemAt(1,2)->geometry().width(), 40.0);
+
+ delete widget;
+}
+
+// public qreal columnSpacing(int column) const
+void tst_QGraphicsGridLayout::columnSpacing()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ QCOMPARE(layout->columnSpacing(0), 0.0);
+
+ layout->setColumnSpacing(0, 20);
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(0,0)->geometry().right(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().left(), 45.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().right(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().left(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().right(), 95.0);
+
+ delete widget;
+ }
+
+ {
+ // don't include items and spacings that was previously part of the layout
+ // (horizontal)
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ populateLayout(layout, 3, 1);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->setColumnSpacing(0, 10);
+ layout->setColumnSpacing(1, 10);
+ layout->setColumnSpacing(2, 10);
+ layout->setColumnSpacing(3, 10);
+ QCOMPARE(layout->preferredSize(), QSizeF(95, 25));
+ layout->removeAt(2);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 25));
+ layout->removeAt(1);
+ QCOMPARE(layout->preferredSize(), QSizeF(25, 25));
+ delete layout;
+ }
+ {
+ // don't include items and spacings that was previously part of the layout
+ // (vertical)
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ populateLayout(layout, 2, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->setColumnSpacing(0, 10);
+ layout->setColumnSpacing(1, 10);
+ layout->setRowSpacing(0, 10);
+ layout->setRowSpacing(1, 10);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 60));
+ layout->removeAt(3);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 60));
+ layout->removeAt(2);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 25));
+ layout->removeAt(1);
+ QCOMPARE(layout->preferredSize(), QSizeF(25, 25));
+ delete layout;
+ }
+
+}
+
+// public int columnStretchFactor(int column) const
+void tst_QGraphicsGridLayout::columnStretchFactor()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setColumnStretchFactor(0, 1);
+ layout->setColumnStretchFactor(1, 2);
+ layout->setColumnStretchFactor(2, 3);
+ view.show();
+ widget->show();
+ widget->resize(130, 50);
+ QApplication::processEvents();
+
+ QVERIFY(layout->itemAt(0,0)->geometry().width() < layout->itemAt(0,1)->geometry().width());
+ QVERIFY(layout->itemAt(0,1)->geometry().width() < layout->itemAt(0,2)->geometry().width());
+ QVERIFY(layout->itemAt(1,0)->geometry().width() < layout->itemAt(1,1)->geometry().width());
+ QVERIFY(layout->itemAt(1,1)->geometry().width() < layout->itemAt(1,2)->geometry().width());
+
+ delete widget;
+}
+
+
+// public int count() const
+void tst_QGraphicsGridLayout::count()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ QCOMPARE(layout->count(), 6);
+ layout->removeAt(5);
+ layout->removeAt(3);
+ QCOMPARE(layout->count(), 4);
+ layout->removeAt(1);
+ QCOMPARE(layout->count(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 2);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 1);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::horizontalSpacing_data()
+{
+ QTest::addColumn<qreal>("horizontalSpacing");
+ QTest::newRow("zero") << qreal(0.0);
+ QTest::newRow("10") << qreal(10.0);
+}
+
+// public qreal horizontalSpacing() const
+void tst_QGraphicsGridLayout::horizontalSpacing()
+{
+ QFETCH(qreal, horizontalSpacing);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal w = layout->sizeHint(Qt::PreferredSize, QSizeF()).width();
+ qreal oldSpacing = layout->horizontalSpacing();
+ if (oldSpacing != -1) {
+ layout->setHorizontalSpacing(horizontalSpacing);
+ QApplication::processEvents();
+ qreal new_w = layout->sizeHint(Qt::PreferredSize, QSizeF()).width();
+ QCOMPARE(new_w, w - (3-1)*(oldSpacing - horizontalSpacing));
+ } else {
+ QSKIP("The current style uses non-uniform layout spacing", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::contentsMargins()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ QGraphicsGridLayout *sublayout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->addItem(sublayout,0, 1);
+
+ qreal left, top, right, bottom;
+ // sublayouts have 0 margin
+ sublayout->getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(left, 0.0);
+ QCOMPARE(top, 0.0);
+ QCOMPARE(right, 0.0);
+ QCOMPARE(bottom, 0.0);
+
+ // top level layouts have style dependent margins.
+ // we'll just check if its different from 0. (applies to all our styles)
+ layout->getContentsMargins(&left, &top, &right, &bottom);
+ QVERIFY(left >= 0.0);
+ QVERIFY(top >= 0.0);
+ QVERIFY(right >= 0.0);
+ QVERIFY(bottom >= 0.0);
+
+ delete widget;
+}
+
+// public QGraphicsLayoutItem* itemAt(int index) const
+void tst_QGraphicsGridLayout::itemAt()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayoutWithSpansAndHoles(layout);
+
+ //itemAt(int row, int column)
+ QVERIFY( layout->itemAt(0,0));
+ QVERIFY( layout->itemAt(0,1));
+ QCOMPARE(layout->itemAt(0,2), static_cast<QGraphicsLayoutItem*>(0));
+ QCOMPARE(layout->itemAt(1,0), static_cast<QGraphicsLayoutItem*>(0));
+ QVERIFY( layout->itemAt(1,1));
+ QVERIFY( layout->itemAt(1,2));
+
+
+ //itemAt(int index)
+ for (int i = -2; i < layout->count() + 2; ++i) {
+ if (i >= 0 && i < layout->count()) {
+ QVERIFY(layout->itemAt(i));
+ } else {
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::itemAt: invalid index %1").arg(i).toLatin1().constData());
+ QCOMPARE(layout->itemAt(i), static_cast<QGraphicsLayoutItem*>(0));
+ }
+ }
+ delete widget;
+}
+
+// public void removeAt(int index)
+void tst_QGraphicsGridLayout::removeAt()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ QCOMPARE(layout->count(), 6);
+ layout->removeAt(5);
+ layout->removeAt(3);
+ QCOMPARE(layout->count(), 4);
+ layout->removeAt(1);
+ QCOMPARE(layout->count(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 2);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 1);
+ QGraphicsLayoutItem *item0 = layout->itemAt(0);
+ QCOMPARE(item0->parentLayoutItem(), static_cast<QGraphicsLayoutItem *>(layout));
+ layout->removeAt(0);
+ QCOMPARE(item0->parentLayoutItem(), static_cast<QGraphicsLayoutItem *>(0));
+ QCOMPARE(layout->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index 0").toLatin1().constData());
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 0);
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::removeItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ scene.addItem(widget);
+ QGraphicsGridLayout *l = new QGraphicsGridLayout();
+ widget->setLayout(l);
+
+ populateLayout(l, 3, 2);
+ QCOMPARE(l->count(), 6);
+ l->removeItem(l->itemAt(5));
+ l->removeItem(l->itemAt(4));
+ QCOMPARE(l->count(), 4);
+
+ // Avoid crashing. Note that the warning message might change in the future.
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index -1").toLatin1().constData());
+ l->removeItem(0);
+ QCOMPARE(l->count(), 4);
+
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index -1").toLatin1().constData());
+ l->removeItem(new QGraphicsWidget);
+ QCOMPARE(l->count(), 4);
+}
+
+void tst_QGraphicsGridLayout::rowAlignment_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public Qt::Alignment rowAlignment(int row) const
+void tst_QGraphicsGridLayout::rowAlignment()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(1);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ view.resize(330,450);
+ widget->resize(300, 400);
+ view.show();
+ widget->show();
+ QApplication::sendPostedEvents(0, 0);
+ // Check default
+ QCOMPARE(layout->rowAlignment(0), 0);
+ QCOMPARE(layout->rowAlignment(1), 0);
+ QCOMPARE(layout->rowAlignment(2), 0);
+
+ // make the grids larger than the items, so that alignment kicks in
+ layout->setRowMinimumHeight(0, 100.0);
+ layout->setRowMinimumHeight(1, 100.0);
+ layout->setRowMinimumHeight(2, 100.0);
+ // expand columns also, so we can test combination of horiz and vertical alignment
+ layout->setColumnMinimumWidth(0, 100.0);
+ layout->setColumnMinimumWidth(1, 100.0);
+
+ layout->setRowAlignment(0, Qt::AlignBottom);
+ layout->setRowAlignment(1, Qt::AlignVCenter);
+ layout->setRowAlignment(2, Qt::AlignTop);
+
+ // see if item alignment takes preference over rowAlignment
+ layout->setAlignment(layout->itemAt(0,0), Qt::AlignRight);
+ layout->setAlignment(layout->itemAt(1,0), Qt::AlignTop);
+ layout->setAlignment(layout->itemAt(2,0), Qt::AlignHCenter);
+
+ QApplication::sendPostedEvents(0, 0); // process LayoutRequest
+
+ QCOMPARE(layout->alignment(layout->itemAt(0,0)), Qt::AlignRight); //Qt::AlignRight | Qt::AlignBottom
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(50, 50, 50, 50));
+ QCOMPARE(layout->rowAlignment(0), Qt::AlignBottom);
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(101, 50, 50, 50));
+ QCOMPARE(layout->alignment(layout->itemAt(1,0)), Qt::AlignTop);
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 101, 50, 50));
+ QCOMPARE(layout->rowAlignment(1), Qt::AlignVCenter);
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(101, 126, 50, 50));
+ QCOMPARE(layout->alignment(layout->itemAt(2,0)), Qt::AlignHCenter);
+ QCOMPARE(layout->itemAt(2,0)->geometry(), QRectF(25, 202, 50, 50));
+ QCOMPARE(layout->rowAlignment(2), Qt::AlignTop);
+ QCOMPARE(layout->itemAt(2,1)->geometry(), QRectF(101,202, 50, 50));
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowCount_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public int rowCount() const
+// public int columnCount() const
+void tst_QGraphicsGridLayout::rowCount()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ widget->setContentsMargins(0, 0, 0, 0);
+ QCOMPARE(layout->rowCount(), 3);
+ QCOMPARE(layout->columnCount(), 2);
+
+ // with spans and holes...
+ widget->setLayout(0);
+ layout = new QGraphicsGridLayout();
+ populateLayoutWithSpansAndHoles(layout, hasHeightForWidth);
+ QCOMPARE(layout->rowCount(), 2);
+ QCOMPARE(layout->columnCount(), 3);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowMaximumHeight_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public qreal rowMaximumHeight(int row) const
+void tst_QGraphicsGridLayout::rowMaximumHeight()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // should at least be a very large number
+ QVERIFY(layout->rowMaximumHeight(0) >= 10000);
+ QCOMPARE(layout->rowMaximumHeight(0), layout->rowMaximumHeight(1));
+ QCOMPARE(layout->rowMaximumHeight(1), layout->rowMaximumHeight(2));
+ layout->setRowMaximumHeight(0, 20);
+ layout->setRowMaximumHeight(2, 60);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 25.0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowMinimumHeight_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal rowMinimumHeight(int row) const
+void tst_QGraphicsGridLayout::rowMinimumHeight()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // should at least be a very large number
+ QCOMPARE(layout->rowMinimumHeight(0), 0.0);
+ QCOMPARE(layout->rowMinimumHeight(0), layout->rowMinimumHeight(1));
+ QCOMPARE(layout->rowMinimumHeight(1), layout->rowMinimumHeight(2));
+ layout->setRowMinimumHeight(0, 20);
+ layout->setRowMinimumHeight(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 40.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 40.0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowPreferredHeight_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal rowPreferredHeight(int row) const
+void tst_QGraphicsGridLayout::rowPreferredHeight()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // default preferred height ??
+ QCOMPARE(layout->rowPreferredHeight(0), 0.0);
+ QCOMPARE(layout->rowPreferredHeight(0), layout->rowPreferredHeight(1));
+ QCOMPARE(layout->rowPreferredHeight(1), layout->rowPreferredHeight(2));
+ layout->setRowPreferredHeight(0, 20);
+ layout->setRowPreferredHeight(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ // ### Jasmin: Should rowPreferredHeight have precedence over sizeHint(Qt::PreferredSize) ?
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 40.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 40.0);
+
+ delete widget;
+}
+
+// public void setRowFixedHeight(int row, qreal height)
+void tst_QGraphicsGridLayout::setRowFixedHeight()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setRowFixedHeight(0, 20.);
+ layout->setRowFixedHeight(2, 40.);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 40.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 40.0);
+
+ delete widget;
+}
+
+// public qreal rowSpacing(int row) const
+void tst_QGraphicsGridLayout::rowSpacing()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ QCOMPARE(layout->columnSpacing(0), 0.0);
+
+ layout->setColumnSpacing(0, 20);
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(0,0)->geometry().right(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().left(), 45.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().right(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().left(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().right(), 95.0);
+
+ delete widget;
+
+}
+
+void tst_QGraphicsGridLayout::rowStretchFactor_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public int rowStretchFactor(int row) const
+void tst_QGraphicsGridLayout::rowStretchFactor()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setRowStretchFactor(0, 1);
+ layout->setRowStretchFactor(1, 2);
+ layout->setRowStretchFactor(2, 3);
+ view.show();
+ widget->show();
+ widget->resize(50, 130);
+ QApplication::processEvents();
+
+ QVERIFY(layout->itemAt(0,0)->geometry().height() < layout->itemAt(1,0)->geometry().height());
+ QVERIFY(layout->itemAt(1,0)->geometry().height() < layout->itemAt(2,0)->geometry().height());
+ QVERIFY(layout->itemAt(0,1)->geometry().height() < layout->itemAt(1,1)->geometry().height());
+ QVERIFY(layout->itemAt(1,1)->geometry().height() < layout->itemAt(2,1)->geometry().height());
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::setColumnSpacing_data()
+{
+ QTest::addColumn<int>("column");
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("null") << 0 << qreal(0.0) << false;
+ QTest::newRow("10") << 0 << qreal(10.0) << false;
+ QTest::newRow("null, hasHeightForWidth") << 0 << qreal(0.0) << true;
+ QTest::newRow("10, hasHeightForWidth") << 0 << qreal(10.0) << true;
+}
+
+// public void setColumnSpacing(int column, qreal spacing)
+void tst_QGraphicsGridLayout::setColumnSpacing()
+{
+ QFETCH(int, column);
+ QFETCH(qreal, spacing);
+ QFETCH(bool, hasHeightForWidth);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal oldSpacing = layout->columnSpacing(column);
+ QCOMPARE(oldSpacing, 0.0);
+ qreal w = layout->sizeHint(Qt::PreferredSize, QSizeF()).width();
+ layout->setColumnSpacing(column, spacing);
+ QApplication::processEvents();
+ QCOMPARE(layout->sizeHint(Qt::PreferredSize, QSizeF()).width(), w + spacing);
+}
+
+void tst_QGraphicsGridLayout::setGeometry_data()
+{
+ QTest::addColumn<QRectF>("rect");
+ QTest::newRow("null") << QRectF();
+ QTest::newRow("normal") << QRectF(0,0, 50, 50);
+}
+
+// public void setGeometry(QRectF const& rect)
+void tst_QGraphicsGridLayout::setGeometry()
+{
+ QFETCH(QRectF, rect);
+
+ QGraphicsWidget *window = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ window->setLayout(layout);
+ QGraphicsGridLayout *layout2 = new QGraphicsGridLayout();
+ layout2->setMaximumSize(100, 100);
+ layout->addItem(layout2, 0, 0);
+ layout2->setGeometry(rect);
+ QCOMPARE(layout2->geometry(), rect);
+}
+
+void tst_QGraphicsGridLayout::setRowSpacing_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("null") << 0 << qreal(0.0) << false;
+ QTest::newRow("10") << 0 << qreal(10.0) << false;
+ QTest::newRow("null, hasHeightForWidth") << 0 << qreal(0.0) << true;
+ QTest::newRow("10, hasHeightForWidth") << 0 << qreal(10.0) << true;
+}
+
+// public void setRowSpacing(int row, qreal spacing)
+void tst_QGraphicsGridLayout::setRowSpacing()
+{
+ QFETCH(int, row);
+ QFETCH(qreal, spacing);
+ QFETCH(bool, hasHeightForWidth);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal oldSpacing = layout->rowSpacing(row);
+ QCOMPARE(oldSpacing, 0.0);
+ qreal h = layout->sizeHint(Qt::PreferredSize, QSizeF()).height();
+ layout->setRowSpacing(row, spacing);
+ QApplication::processEvents();
+ QCOMPARE(layout->sizeHint(Qt::PreferredSize, QSizeF()).height(), h + spacing);
+}
+
+void tst_QGraphicsGridLayout::setSpacing_data()
+{
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<bool>("hasHeightForWidth");
+ QTest::newRow("zero") << qreal(0.0) << false;
+ QTest::newRow("17") << qreal(17.0) << false;
+ QTest::newRow("zero, hasHeightForWidth") << qreal(0.0) << true;
+ QTest::newRow("17, hasHeightForWidth") << qreal(17.0) << true;
+}
+
+// public void setSpacing(qreal spacing)
+void tst_QGraphicsGridLayout::setSpacing()
+{
+ QFETCH(qreal, spacing);
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ QSizeF sh = layout->sizeHint(Qt::PreferredSize, QSizeF());
+ qreal oldVSpacing = layout->verticalSpacing();
+ qreal oldHSpacing = layout->horizontalSpacing();
+ if (oldVSpacing != -1) {
+ layout->setSpacing(spacing);
+ QApplication::processEvents();
+ QSizeF newSH = layout->sizeHint(Qt::PreferredSize, QSizeF());
+ QCOMPARE(newSH.height(), sh.height() - (2-1)*(oldVSpacing - spacing));
+ QCOMPARE(newSH.width(), sh.width() - (3-1)*(oldHSpacing - spacing));
+ } else {
+ QSKIP("The current style uses non-uniform layout spacing", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::sizeHint_data()
+{
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("expectedMinimumSizeHint");
+ QTest::addColumn<QSizeF>("expectedPreferredSizeHint");
+ QTest::addColumn<QSizeF>("expectedMaximumSizeHint");
+
+ QTest::newRow("rowSpan_larger_than_rows") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(50,300))
+ .maxSize(QSizeF(50,300))
+ .rowSpan(2)
+ << ItemDesc(0,1)
+ .minSize(QSizeF(50,0))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSize(50, 1000))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(50,0))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSize(50, 1000))
+ )
+ << QSizeF(100, 300)
+ << QSizeF(100, 300)
+ << QSizeF(100, 2000);
+
+ QTest::newRow("rowSpan_smaller_than_rows") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(50, 0))
+ .preferredSize(QSizeF(50, 50))
+ .maxSize(QSizeF(50, 300))
+ .rowSpan(2)
+ << ItemDesc(0,1)
+ .minSize(QSizeF(50, 50))
+ .preferredSize(QSizeF(50, 50))
+ .maxSize(QSize(50, 50))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(50, 50))
+ .preferredSize(QSizeF(50, 50))
+ .maxSize(QSize(50, 50))
+ )
+ << QSizeF(100, 100)
+ << QSizeF(100, 100)
+ << QSizeF(100, 100);
+
+}
+
+// public QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+void tst_QGraphicsGridLayout::sizeHint()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, expectedMinimumSizeHint);
+ QFETCH(QSizeF, expectedPreferredSizeHint);
+ QFETCH(QSizeF, expectedMaximumSizeHint);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::sendPostedEvents(0, 0);
+
+ widget->show();
+ view.show();
+ view.resize(400,300);
+ QCOMPARE(layout->sizeHint(Qt::MinimumSize), expectedMinimumSizeHint);
+ QCOMPARE(layout->sizeHint(Qt::PreferredSize), expectedPreferredSizeHint);
+ QCOMPARE(layout->sizeHint(Qt::MaximumSize), expectedMaximumSizeHint);
+
+}
+
+void tst_QGraphicsGridLayout::verticalSpacing_data()
+{
+ QTest::addColumn<qreal>("verticalSpacing");
+ QTest::newRow("zero") << qreal(0.0);
+ QTest::newRow("17") << qreal(10.0);
+}
+
+// public qreal verticalSpacing() const
+void tst_QGraphicsGridLayout::verticalSpacing()
+{
+ QFETCH(qreal, verticalSpacing);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal h = layout->sizeHint(Qt::PreferredSize, QSizeF()).height();
+ qreal oldSpacing = layout->verticalSpacing();
+ if (oldSpacing != -1) {
+ layout->setVerticalSpacing(verticalSpacing);
+ QApplication::processEvents();
+ qreal new_h = layout->sizeHint(Qt::PreferredSize, QSizeF()).height();
+ QCOMPARE(new_h, h - (2-1)*(oldSpacing - verticalSpacing));
+ } else {
+ QSKIP("The current style uses non-uniform layout spacing", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::layoutDirection_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+void tst_QGraphicsGridLayout::layoutDirection()
+{
+ QFETCH(bool, hasHeightForWidth);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ layout->setContentsMargins(1, 2, 3, 4);
+ layout->setSpacing(6);
+ RectWidget *w1 = new RectWidget;
+ w1->setMinimumSize(30, 20);
+ layout->addItem(w1, 0, 0);
+ RectWidget *w2 = new RectWidget;
+ w2->setMinimumSize(20, 20);
+ w2->setMaximumSize(20, 20);
+ layout->addItem(w2, 0, 1);
+ RectWidget *w3 = new RectWidget;
+ w3->setMinimumSize(20, 20);
+ w3->setMaximumSize(20, 20);
+ layout->addItem(w3, 1, 0);
+ RectWidget *w4 = new RectWidget;
+ w4->setMinimumSize(30, 20);
+ layout->addItem(w4, 1, 1);
+
+ QSizePolicy policy = w1->sizePolicy();
+ policy.setHeightForWidth(hasHeightForWidth);
+ w1->setSizePolicy(policy);
+ w2->setSizePolicy(policy);
+ w4->setSizePolicy(policy);
+
+ layout->setAlignment(w2, Qt::AlignRight);
+ layout->setAlignment(w3, Qt::AlignLeft);
+
+ scene.addItem(window);
+ window->setLayout(layout);
+ view.show();
+ window->resize(70, 52);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().left(), 1.0);
+ QCOMPARE(w1->geometry().right(), 31.0);
+ QCOMPARE(w2->geometry().left(), 47.0);
+ QCOMPARE(w2->geometry().right(), 67.0);
+ QCOMPARE(w3->geometry().left(), 1.0);
+ QCOMPARE(w3->geometry().right(), 21.0);
+ QCOMPARE(w4->geometry().left(), 37.0);
+ QCOMPARE(w4->geometry().right(), 67.0);
+
+ window->setLayoutDirection(Qt::RightToLeft);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().left(), 39.0);
+ QCOMPARE(w1->geometry().right(), 69.0);
+ QCOMPARE(w2->geometry().left(), 3.0);
+ QCOMPARE(w2->geometry().right(), 23.0);
+ QCOMPARE(w3->geometry().left(), 49.0);
+ QCOMPARE(w3->geometry().right(), 69.0);
+ QCOMPARE(w4->geometry().left(), 3.0);
+ QCOMPARE(w4->geometry().right(), 33.0);
+
+ delete window;
+}
+
+void tst_QGraphicsGridLayout::removeLayout()
+{
+ QGraphicsScene scene;
+ RectWidget *textEdit = new RectWidget;
+ RectWidget *pushButton = new RectWidget;
+ scene.addItem(textEdit);
+ scene.addItem(pushButton);
+
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ layout->addItem(textEdit, 0, 0);
+ layout->addItem(pushButton, 1, 0);
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout(layout);
+ scene.addItem(form);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(20);
+
+ QRectF r1 = textEdit->geometry();
+ QRectF r2 = pushButton->geometry();
+ form->setLayout(0);
+ //documentation of QGraphicsWidget::setLayout:
+ //If layout is 0, the widget is left without a layout. Existing subwidgets' geometries will remain unaffected.
+ QCOMPARE(textEdit->geometry(), r1);
+ QCOMPARE(pushButton->geometry(), r2);
+}
+
+void tst_QGraphicsGridLayout::defaultStretchFactors_data()
+{
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<SizeList>("expectedSizes");
+
+ QTest::newRow("usepreferredsize") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem01") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem01_resize120x40") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,10))
+ )
+ << QSizeF(120, 40)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(40,20) << QSizeF(60,20)
+ << QSizeF(20,20) << QSizeF(40,20) << QSizeF(60,20)
+ );
+
+ QTest::newRow("ignoreitem11_resize120x40") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,20))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,20))
+ )
+ << QSizeF(120, 60)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(40,20) << QSizeF(60,20)
+ << QSizeF(20,40) << QSizeF(40,40) << QSizeF(60,40)
+ );
+
+ QTest::newRow("ignoreitem01_span01_resize70x60") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicy(QSizePolicy::Ignored)
+ .rowSpan(2)
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,20))
+ )
+ << QSizeF(70, 60)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(10,60) << QSizeF(40,20)
+ << QSizeF(20,40) << QSizeF(40,40)
+ );
+
+ QTest::newRow("ignoreitem10_resize40x120") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(2,0)
+ .preferredSizeHint(QSizeF(10,30))
+ << ItemDesc(2,1)
+ .preferredSizeHint(QSizeF(10,30))
+ )
+ << QSizeF(40, 120)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(20,20)
+ << QSizeF(20,40) << QSizeF(20,40)
+ << QSizeF(20,60) << QSizeF(20,60)
+ );
+
+ QTest::newRow("ignoreitem01_span02") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .rowSpan(2)
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(0,20) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem02_span02") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .rowSpan(2)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(0,20)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem02_span00_span02") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .rowSpan(2)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .rowSpan(2)
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,20) << QSizeF(10,10) << QSizeF(0,20)
+ << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem00_colspan00") << (ItemList()
+ << ItemDesc(0,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .colSpan(2)
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(20,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem01_colspan01") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .colSpan(2)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(20,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignorecolumn1_resize70x60") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,20))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,20))
+ )
+ << QSizeF(70, 60)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(10,20) << QSizeF(40,20)
+ << QSizeF(20,40) << QSizeF(10,40) << QSizeF(40,40)
+ );
+
+ QTest::newRow("ignorerow0") << (ItemList()
+ << ItemDesc(0,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,0) << QSizeF(10,0) << QSizeF(10,0)
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignorerow1") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,0) << QSizeF(10,0) << QSizeF(10,0)
+ );
+
+ QTest::newRow("ignorerow0_resize60x50") << (ItemList()
+ << ItemDesc(0,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,30))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(20,30))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,30))
+ )
+ << QSizeF(60, 50)
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(20,10) << QSizeF(30,10)
+ << QSizeF(10,40) << QSizeF(20,40) << QSizeF(30,40)
+ );
+
+}
+
+void tst_QGraphicsGridLayout::defaultStretchFactors()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, newSize);
+ QFETCH(SizeList, expectedSizes);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::sendPostedEvents(0, 0);
+
+ widget->show();
+ view.show();
+ view.resize(400,300);
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::sendPostedEvents(0, 0);
+ for (i = 0; i < expectedSizes.count(); ++i) {
+ QSizeF itemSize = layout->itemAt(i)->geometry().size();
+ QCOMPARE(itemSize, expectedSizes.at(i));
+ }
+
+ delete widget;
+}
+
+typedef QList<QRectF> RectList;
+Q_DECLARE_METATYPE(RectList);
+
+void tst_QGraphicsGridLayout::alignment2_data()
+{
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<RectList>("expectedGeometries");
+
+ QTest::newRow("hor_sizepolicy_fixed") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 0, 10,10)
+ );
+
+ QTest::newRow("hor_sizepolicy_fixed_alignvcenter") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ .alignment(Qt::AlignVCenter)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 5, 10,10)
+ );
+
+ QTest::newRow("hor_sizepolicy_fixed_aligntop") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ .alignment(Qt::AlignTop)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 0, 10,10)
+ );
+
+ QTest::newRow("hor_sizepolicy_fixed_alignbottom") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ .alignment(Qt::AlignBottom)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(0, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed_alignhcenter") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ .alignment(Qt::AlignHCenter)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(5, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed_alignleft") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ .alignment(Qt::AlignLeft)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(0, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed_alignright") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ .alignment(Qt::AlignRight)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(10, 10, 10,10)
+ );
+}
+
+void tst_QGraphicsGridLayout::alignment2()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, newSize);
+ QFETCH(RectList, expectedGeometries);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::sendPostedEvents(0, 0);
+
+ widget->show();
+ view.resize(400,300);
+ view.show();
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::sendPostedEvents(0, 0);
+ for (i = 0; i < expectedGeometries.count(); ++i) {
+ QRectF itemRect = layout->itemAt(i)->geometry();
+ QCOMPARE(itemRect, expectedGeometries.at(i));
+ }
+
+ delete widget;
+}
+
+static QSizeF hfw1(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(50, 400);
+ } else if (cw > 0) {
+ result.setHeight(20000./cw);
+ }
+ return result;
+}
+
+static QSizeF wfh1(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(400, 50);
+ } else if (ch > 0) {
+ result.setWidth(20000./ch);
+ }
+ return result;
+}
+
+static QSizeF wfh2(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (ch < 0 && cw < 0)
+ return QSizeF(50, 50);
+ if (ch >= 0)
+ result.setWidth(ch);
+ return result;
+}
+
+static QSizeF hfw3(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(10, 10);
+ } else if (cw > 0) {
+ result.setHeight(100./cw);
+ }
+ return result;
+}
+
+static QSizeF hfw2(Qt::SizeHint /*which*/, const QSizeF &constraint)
+{
+ return QSizeF(constraint.width(), constraint.width());
+}
+
+void tst_QGraphicsGridLayout::geometries_data()
+{
+
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<RectList>("expectedGeometries");
+
+ QTest::newRow("combine_max_sizes") << (ItemList()
+ << ItemDesc(0,0)
+ .maxSize(QSizeF(50,10))
+ << ItemDesc(1,0)
+ .maxSize(QSizeF(10,10))
+ )
+ << QSizeF(50, 20)
+ << (RectList()
+ << QRectF(0, 0, 50,10) << QRectF(0, 10, 10,10)
+ );
+
+ QTest::newRow("combine_min_sizes") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(50,10))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(10,10))
+ )
+ << QSizeF(60, 20)
+ << (RectList()
+ << QRectF(0, 0, 60,10) << QRectF(0, 10, 60,10)
+ );
+
+ // change layout height and verify
+ QTest::newRow("hfw-100x401") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(40,-1))
+ .preferredSize(QSizeF(50,-1))
+ .maxSize(QSizeF(500, -1))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 401)
+ << (RectList()
+ << QRectF(0, 0, 50, 1) << QRectF(50, 0, 50, 1)
+ << QRectF(0, 1, 50,100) << QRectF(50, 1, 50,400)
+ );
+ QTest::newRow("hfw-h408") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(500, 500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 408)
+ << (RectList()
+ << QRectF(0, 0, 50, 8) << QRectF(50, 0, 50, 8)
+ << QRectF(0, 8, 50,100) << QRectF(50, 8, 50,400)
+ );
+ QTest::newRow("hfw-h410") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(40,40))
+ .preferredSize(QSizeF(50,400))
+ .maxSize(QSizeF(500, 500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 410)
+ << (RectList()
+ << QRectF(0, 0, 50,10) << QRectF(50, 0, 50,10)
+ << QRectF(0, 10, 50,100) << QRectF(50, 10, 50,400)
+ );
+
+ QTest::newRow("hfw-100x470") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(500,500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 470)
+ << (RectList()
+ << QRectF(0, 0, 50,70) << QRectF(50, 0, 50,70)
+ << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400)
+ );
+
+ // change layout width and verify
+ QTest::newRow("hfw-100x401") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(-1,-1))
+ .preferredSize(QSizeF(-1,-1))
+ .maxSize(QSizeF(-1, -1))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 401)
+ << (RectList()
+ << QRectF( 0, 0, 50, 1) << QRectF( 50, 0, 50, 1)
+ << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400)
+ );
+
+ QTest::newRow("hfw-160x350") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(160, 350)
+ << (RectList()
+ << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100)
+ << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250)
+ );
+
+ QTest::newRow("hfw-160x300") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000, 5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(160, 300)
+ << (RectList()
+ << QRectF( 0, 0, 80, 50) << QRectF( 80, 0, 80, 50)
+ << QRectF( 0, 50, 80, 100) << QRectF( 80, 50, 80, 250)
+ );
+
+ QTest::newRow("hfw-20x40") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,10))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1, 1))
+ .sizeHint(Qt::PreferredSize, QSizeF(50, 50))
+ .sizeHint(Qt::MaximumSize, QSizeF(100, 100))
+ .dynamicConstraint(hfw3, Qt::Vertical)
+ )
+ << QSizeF(20, 40)
+ << (RectList()
+ << QRectF(0, 0, 10, 20) << QRectF(10, 0, 10, 20)
+ << QRectF(0, 20, 10, 20) << QRectF(10, 20, 10, 10)
+ );
+
+ QTest::newRow("wfh-300x160") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(10,10))
+ .sizeHint(Qt::PreferredSize, QSizeF(400,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000, 5000))
+ .dynamicConstraint(wfh1, Qt::Horizontal)
+ )
+ << QSizeF(300, 160)
+ << (RectList()
+ << QRectF( 0, 0, 50, 80) << QRectF( 50, 0, 100, 80)
+ << QRectF( 0, 80, 50, 80) << QRectF( 50, 80, 250, 80)
+ );
+
+ QTest::newRow("wfh-40x20") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ // Note, must be 10 in order to match stretching of wfh item
+ // below (the same stretch makes it easier to test)
+ .minSize(QSizeF(10,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1,1))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(100, 100))
+ .dynamicConstraint(wfh2, Qt::Horizontal)
+ )
+ << QSizeF(40, 20)
+ << (RectList()
+ << QRectF(0, 0, 20, 10) << QRectF(20, 0, 20, 10)
+ << QRectF(0, 10, 20, 10) << QRectF(20, 10, 10, 10)
+ );
+
+ QTest::newRow("wfh-400x160") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1,1))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(100, 100))
+ .dynamicConstraint(wfh2, Qt::Horizontal)
+ )
+
+ << QSizeF(400, 160)
+ << (RectList()
+ << QRectF(0, 0, 100, 80) << QRectF(100, 0, 100, 80)
+ << QRectF(0, 80, 100, 80) << QRectF(100, 80, 80, 80)
+ );
+
+ QTest::newRow("wfh-160x100") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ // Note, preferred width must be 50 in order to match
+ // preferred width of wfh item below.
+ // (The same preferred size makes the stretch the same, and
+ // makes it easier to test) (The stretch algorithm is a
+ // blackbox)
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1,1))
+ .sizeHint(Qt::PreferredSize, QSizeF(10,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(500, 500))
+ .dynamicConstraint(wfh2, Qt::Horizontal)
+ )
+ << QSizeF(160, 100)
+ << (RectList()
+ << QRectF(0, 0, 80, 50) << QRectF( 80, 0, 80, 50)
+ << QRectF(0, 50, 80, 50) << QRectF( 80, 50, 50, 50)
+ );
+
+ QTest::newRow("hfw-h470") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(500,500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 470)
+ << (RectList()
+ << QRectF(0, 0, 50,70) << QRectF(50, 0, 50,70)
+ << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400)
+ );
+
+ // change layout width and verify
+ QTest::newRow("hfw-w100") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 401)
+ << (RectList()
+ << QRectF( 0, 0, 50, 1) << QRectF( 50, 0, 50, 1)
+ << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400)
+ );
+
+ QTest::newRow("hfw-w160") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(160, 350)
+ << (RectList()
+ << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100)
+ << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250)
+ );
+
+ QTest::newRow("hfw-w500") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(500, 200)
+ << (RectList()
+ << QRectF( 0, 0, 100, 100) << QRectF(100, 0, 100, 100)
+ << QRectF( 0, 100, 100, 100) << QRectF(100, 100, 400, 50)
+ );
+
+ QTest::newRow("hfw-alignment-defaults") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(100, 100))
+ .maxSize(QSizeF(100, 100))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ << ItemDesc(1,0)
+ .minSize(QSizeF(200, 200))
+ .maxSize(QSizeF(200, 200))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ << ItemDesc(2,0)
+ .minSize(QSizeF(300, 300))
+ .maxSize(QSizeF(300, 300))
+ )
+ << QSizeF(300, 600)
+ << (RectList()
+ << QRectF(0, 0, 100, 100)
+ << QRectF(0, 100, 200, 200)
+ << QRectF(0, 300, 300, 300)
+ );
+
+ QTest::newRow("hfw-alignment2") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(100, 100))
+ .maxSize(QSizeF(100, 100))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ .alignment(Qt::AlignRight)
+ << ItemDesc(1,0)
+ .minSize(QSizeF(200, 200))
+ .maxSize(QSizeF(200, 200))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ .alignment(Qt::AlignHCenter)
+ << ItemDesc(2,0)
+ .minSize(QSizeF(300, 300))
+ .maxSize(QSizeF(300, 300))
+ )
+ << QSizeF(300, 600)
+ << (RectList()
+ << QRectF(200, 0, 100, 100)
+ << QRectF( 50, 100, 200, 200)
+ << QRectF( 0, 300, 300, 300)
+ );
+
+}
+
+void tst_QGraphicsGridLayout::geometries()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, newSize);
+ QFETCH(RectList, expectedGeometries);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::processEvents();
+
+ widget->show();
+ view.resize(400,300);
+ view.show();
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::processEvents();
+ for (i = 0; i < expectedGeometries.count(); ++i) {
+ QRectF itemRect = layout->itemAt(i)->geometry();
+ QCOMPARE(itemRect, expectedGeometries.at(i));
+ }
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::avoidRecursionInInsertItem()
+{
+ QGraphicsWidget window(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(&window);
+ QCOMPARE(layout->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: cannot insert itself");
+ layout->addItem(layout, 0, 0);
+ QCOMPARE(layout->count(), 0);
+}
+
+void tst_QGraphicsGridLayout::styleInfoLeak()
+{
+ QGraphicsGridLayout grid;
+ grid.horizontalSpacing();
+}
+
+void tst_QGraphicsGridLayout::task236367_maxSizeHint()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ int w = 203;
+ int h = 204;
+ widget->resize(w, h);
+ QCOMPARE(widget->size(), QSizeF(w, h));
+}
+
+static QSizeF hfw(Qt::SizeHint /*which*/, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal cw = constraint.width();
+ const qreal ch = constraint.height();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(200, 100);
+ } else if (cw >= 0) {
+ result.setHeight(20000./cw);
+ } else if (cw == 0) {
+ result.setHeight(20000);
+ } else if (ch >= 0) {
+ result.setWidth(20000./ch);
+ } else if (ch == 0) {
+ result.setWidth(20000);
+ }
+ return result;
+}
+
+static QSizeF wfh(Qt::SizeHint /*which*/, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ if (ch >= 0) {
+ result.setWidth(ch);
+ }
+ return result;
+}
+
+bool qFuzzyCompare(const QSizeF &a, const QSizeF &b)
+{
+ return qFuzzyCompare(a.width(), b.width()) && qFuzzyCompare(a.height(), b.height());
+}
+
+void tst_QGraphicsGridLayout::heightForWidth()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ RectWidget *w00 = new RectWidget;
+ w00->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w00->setSizeHint(Qt::PreferredSize, QSizeF(10,10));
+ w00->setSizeHint(Qt::MaximumSize, QSizeF(100,100));
+ layout->addItem(w00, 0, 0);
+
+ RectWidget *w01 = new RectWidget;
+ w01->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w01->setSizeHint(Qt::PreferredSize, QSizeF(10,10));
+ w01->setSizeHint(Qt::MaximumSize, QSizeF(100,100));
+ layout->addItem(w01, 0, 1);
+
+ RectWidget *w10 = new RectWidget;
+ w10->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w10->setSizeHint(Qt::PreferredSize, QSizeF(10,10));
+ w10->setSizeHint(Qt::MaximumSize, QSizeF(100,100));
+ layout->addItem(w10, 1, 0);
+
+ RectWidget *w11 = new RectWidget;
+ w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000));
+ w11->setConstraintFunction(hfw);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(true);
+ w11->setSizePolicy(sp);
+ layout->addItem(w11, 1, 1);
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(2, 2));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(210, 110));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30100, 30100));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 20001));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20010));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 20100));
+
+ // Since 20 is somewhere between "minimum width hint" (2) and
+ // "preferred width hint" (210), it will try to do distribution by
+ // stretching them with different factors.
+ // Since column 1 has a "preferred width" of 200 it means that
+ // column 1 will be a bit wider than column 0. Thus it will also be a bit
+ // shorter than 2001, (the expected height if all columns had width=10)
+ QSizeF sh = layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1));
+ // column 1 cannot be wider than 19, which means that it must be taller than 20000/19~=1052
+ QVERIFY(sh.height() < 2000 + 1 && sh.height() > 1052 + 1);
+
+ sh = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1));
+ QVERIFY(sh.height() < 2000 + 10 && sh.height() > 1052 + 10);
+
+ sh = layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1));
+ QVERIFY(sh.height() < 2000 + 100 && sh.height() > 1052 + 100);
+
+ // the height of the hfw widget is shorter than the one to the left, which is 100, so
+ // the total height of the last row is 100 (which leaves the layout height to be 200)
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(500, -1)), QSizeF(500, 100 + 100));
+
+}
+
+void tst_QGraphicsGridLayout::widthForHeight()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ RectWidget *w00 = new RectWidget;
+ w00->setMinimumSize(1, 1);
+ w00->setPreferredSize(50, 50);
+ w00->setMaximumSize(100, 100);
+
+ layout->addItem(w00, 0, 0);
+
+ RectWidget *w01 = new RectWidget;
+ w01->setMinimumSize(1,1);
+ w01->setPreferredSize(50,50);
+ w01->setMaximumSize(100,100);
+ layout->addItem(w01, 0, 1);
+
+ RectWidget *w10 = new RectWidget;
+ w10->setMinimumSize(1,1);
+ w10->setPreferredSize(50,50);
+ w10->setMaximumSize(100,100);
+ layout->addItem(w10, 1, 0);
+
+ RectWidget *w11 = new RectWidget;
+ w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w11->setSizeHint(Qt::PreferredSize, QSizeF(50,50));
+ w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000));
+
+ // This will make sure its always square.
+ w11->setConstraintFunction(wfh);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setWidthForHeight(true);
+ w11->setSizePolicy(sp);
+ layout->addItem(w11, 1, 1);
+
+ /*
+ | 1, 50, 100 | 1, 50, 100 |
+ -----+--------------+--------------+
+ 1| | |
+ 50| | |
+ 100| | |
+ -----|--------------+--------------+
+ 1| | |
+ 50| | WFH |
+ 100| | |
+ -----------------------------------+
+ */
+
+
+ QSizeF prefSize = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1));
+ QCOMPARE(prefSize, QSizeF(50+50, 50+50));
+
+ // wfh(1): = 1
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 2)), QSizeF(1 + 1, 2));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 2)), QSizeF(50 + 50, 2));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 2)), QSizeF(100 + 100, 2));
+
+ // wfh(40) = 40
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 80)), QSizeF(1 + 40, 80));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 80)), QSizeF(50 + 50, 80));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 80)), QSizeF(100 + 100, 80));
+
+ // wfh(80) = 80
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 160)), QSizeF(1 + 80, 160));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 160)), QSizeF(50 + 80, 160));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 160)), QSizeF(100 + 100, 160));
+
+ // wfh(200) = 200
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 300)), QSizeF(1 + 200, 300));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 300)), QSizeF(50 + 200, 300));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 300)), QSizeF(100 + 200, 300));
+}
+
+void tst_QGraphicsGridLayout::heightForWidthWithSpanning()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ RectWidget *w = new RectWidget;
+ w->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000));
+ w->setConstraintFunction(hfw);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(true);
+ w->setSizePolicy(sp);
+ layout->addItem(w, 0,0,2,2);
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(1, 1));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(200, 100));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30000, 30000));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 100));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 10000));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 10000));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 10000));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 10000));
+}
+
+Q_DECLARE_METATYPE(QSizePolicy::Policy)
+void tst_QGraphicsGridLayout::spanningItem2x2_data()
+{
+ QTest::addColumn<QSizePolicy::Policy>("sizePolicy");
+ QTest::addColumn<int>("itemHeight");
+ QTest::addColumn<int>("expectedHeight");
+
+ QTest::newRow("A larger spanning item with 2 widgets with fixed policy") << QSizePolicy::Fixed << 39 << 80;
+ QTest::newRow("A larger spanning item with 2 widgets with preferred policy") << QSizePolicy::Preferred << 39 << 80;
+ QTest::newRow("An equally-sized spanning item with 2 widgets with fixed policy") << QSizePolicy::Fixed << 40 << 80;
+ QTest::newRow("An equally-sized spanning item with 2 widgets with preferred policy") << QSizePolicy::Preferred << 40 << 80;
+ QTest::newRow("A smaller spanning item with 2 widgets with fixed policy") << QSizePolicy::Fixed << 41 << 82;
+ QTest::newRow("A smaller spanning item with 2 widgets with preferred policy") << QSizePolicy::Preferred << 41 << 82;
+}
+
+void tst_QGraphicsGridLayout::spanningItem2x2()
+{
+ QFETCH(QSizePolicy::Policy, sizePolicy);
+ QFETCH(int, itemHeight);
+ QFETCH(int, expectedHeight);
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(form);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMinimumSize(80,80);
+ w1->setMaximumSize(80,80);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(80,itemHeight);
+ w2->setPreferredSize(80,itemHeight);
+ w2->setSizePolicy(QSizePolicy::Fixed, sizePolicy);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ w3->setMinimumSize(80,itemHeight);
+ w3->setPreferredSize(80,itemHeight);
+ w3->setSizePolicy(QSizePolicy::Fixed, sizePolicy);
+
+ layout->addItem(w1, 0, 0, 2, 1);
+ layout->addItem(w2, 0, 1);
+ layout->addItem(w3, 1, 1);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(160,expectedHeight));
+ if(sizePolicy == QSizePolicy::Fixed)
+ QCOMPARE(layout->maximumSize(), QSizeF(160,expectedHeight));
+ else
+ QCOMPARE(layout->maximumSize(), QSizeF(160,QWIDGETSIZE_MAX));
+}
+
+void tst_QGraphicsGridLayout::spanningItem2x3_data()
+{
+ QTest::addColumn<bool>("w1_fixed");
+ QTest::addColumn<bool>("w2_fixed");
+ QTest::addColumn<bool>("w3_fixed");
+ QTest::addColumn<bool>("w4_fixed");
+ QTest::addColumn<bool>("w5_fixed");
+
+ for(int w1 = 0; w1 < 2; w1++)
+ for(int w2 = 0; w2 < 2; w2++)
+ for(int w3 = 0; w3 < 2; w3++)
+ for(int w4 = 0; w4 < 2; w4++)
+ for(int w5 = 0; w5 < 2; w5++) {
+ QString description = QString("Fixed sizes:") + (w1?" w1":"") + (w2?" w2":"") + (w3?" w3":"") + (w4?" w4":"") + (w5?" w5":"");
+ QTest::newRow(description.toLatin1()) << (bool)w1 << (bool)w2 << (bool)w3 << (bool)w4 << (bool)w5;
+ }
+}
+
+void tst_QGraphicsGridLayout::spanningItem2x3()
+{
+ QFETCH(bool, w1_fixed);
+ QFETCH(bool, w2_fixed);
+ QFETCH(bool, w3_fixed);
+ QFETCH(bool, w4_fixed);
+ QFETCH(bool, w5_fixed);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMinimumSize(80,80);
+ w1->setMaximumSize(80,80);
+ if (w1_fixed)
+ w1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(80,48);
+ w2->setPreferredSize(80,48);
+ if (w2_fixed)
+ w2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ w3->setMinimumSize(80,30);
+ w3->setPreferredSize(80,30);
+ if (w3_fixed)
+ w3->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w4 = new QGraphicsWidget;
+ w4->setMinimumSize(80,30);
+ w4->setMaximumSize(80,30);
+ if (w4_fixed)
+ w4->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w5 = new QGraphicsWidget;
+ w5->setMinimumSize(40,24);
+ w5->setMaximumSize(40,24);
+ if (w5_fixed)
+ w5->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ layout->addItem(w1, 0, 0, 2, 1);
+ layout->addItem(w2, 0, 1);
+ layout->addItem(w3, 1, 1);
+ layout->addItem(w4, 0, 2);
+ layout->addItem(w5, 1, 2);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(240,80));
+ // Only w2 and w3 grow vertically, so when they have a fixed vertical size policy,
+ // the whole layout cannot grow vertically.
+ if (w2_fixed && w3_fixed)
+ QCOMPARE(layout->maximumSize(), QSizeF(QWIDGETSIZE_MAX,80));
+ else
+ QCOMPARE(layout->maximumSize(), QSizeF(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX));
+}
+
+void tst_QGraphicsGridLayout::spanningItem()
+{
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(form);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMinimumSize(80,80);
+ w1->setMaximumSize(80,80);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(80,38);
+ w2->setPreferredSize(80,38);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ w3->setMinimumSize(80,38);
+ w3->setPreferredSize(80,38);
+ w3->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ layout->addItem(w1, 0, 0, 2, 1);
+ layout->addItem(w2, 0, 1);
+ layout->addItem(w3, 1, 1);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(160,80));
+ QCOMPARE(layout->maximumSize(), QSizeF(160,80));
+}
+
+void tst_QGraphicsGridLayout::stretchAndHeightForWidth()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ RectWidget *w1 = new RectWidget;
+ w1->setSizeHint(Qt::MinimumSize, QSizeF(10, 10));
+ w1->setSizeHint(Qt::PreferredSize, QSizeF(100, 100));
+ w1->setSizeHint(Qt::MaximumSize, QSizeF(500, 500));
+ layout->addItem(w1, 0,0,1,1);
+
+ RectWidget *w2 = new RectWidget;
+ w2->setSizeHint(Qt::MinimumSize, QSizeF(10, 10));
+ w2->setSizeHint(Qt::PreferredSize, QSizeF(100, 100));
+ w2->setSizeHint(Qt::MaximumSize, QSizeF(500, 500));
+ layout->addItem(w2, 0,1,1,1);
+ layout->setColumnStretchFactor(1, 2);
+
+ QApplication::sendPostedEvents();
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ scene.addItem(widget);
+
+ view->show();
+
+ widget->resize(500, 100);
+ // w1 should stay at its preferred size
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(100, 0, 400, 100));
+
+
+ // only w1 has hfw
+ w1->setConstraintFunction(hfw);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(true);
+ w1->setSizePolicy(sp);
+ QApplication::sendPostedEvents();
+
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 200));
+ QCOMPARE(w2->geometry(), QRectF(100, 0, 400, 200));
+
+ // only w2 has hfw
+ w2->setConstraintFunction(hfw);
+ w2->setSizePolicy(sp);
+
+ w1->setConstraintFunction(0);
+ sp.setHeightForWidth(false);
+ w1->setSizePolicy(sp);
+ QApplication::sendPostedEvents();
+
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(100, 0, 400, 50));
+
+}
+
+void tst_QGraphicsGridLayout::testDefaultAlignment()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w = new QGraphicsWidget;
+ w->setMinimumSize(50,50);
+ w->setMaximumSize(50,50);
+ layout->addItem(w,0,0);
+
+ //Default alignment should be to the top-left
+
+ //First, check by forcing the layout to be bigger
+ layout->setMinimumSize(100,100);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ layout->setMinimumSize(-1,-1);
+
+ //Second, check by forcing the column and row to be bigger instead
+ layout->setColumnMinimumWidth(0, 100);
+ layout->setRowMinimumHeight(0, 100);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ layout->setMinimumSize(-1,-1);
+ layout->setColumnMinimumWidth(0, 0);
+ layout->setRowMinimumHeight(0, 0);
+
+
+ //Third, check by adding a larger item in the column
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(100,100);
+ w2->setMaximumSize(100,100);
+ layout->addItem(w2,1,0);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,150));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ QCOMPARE(w2->geometry(), QRectF(0,50,100,100));
+}
+QTEST_MAIN(tst_QGraphicsGridLayout)
+#include "tst_qgraphicsgridlayout.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore
new file mode 100644
index 0000000000..b766388e3e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
new file mode 100644
index 0000000000..51a4426680
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsitem.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+
+win32:!wince*: LIBS += -lUser32
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
new file mode 100644
index 0000000000..8ac1f6b5c5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -0,0 +1,11402 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <private/qgraphicsitem_p.h>
+#include <private/qgraphicsview_p.h>
+#include <private/qgraphicsscene_p.h>
+#include <QStyleOptionGraphicsItem>
+#include <QAbstractTextDocumentLayout>
+#include <QBitmap>
+#include <QCursor>
+#include <QLabel>
+#include <QDial>
+#include <QGraphicsItem>
+#include <QGraphicsScene>
+#include <QGraphicsSceneEvent>
+#include <QGraphicsView>
+#include <QGraphicsWidget>
+#include <QGraphicsProxyWidget>
+#include <QPainter>
+#include <QScrollBar>
+#include <QVBoxLayout>
+#include <QGraphicsEffect>
+#include <QInputContext>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QGraphicsLinearLayout>
+#include <float.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#include <windows.h>
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("The Graphics View doesn't get the paint events", SkipSingle);
+#else
+#define Q_CHECK_PAINTEVENTS
+#endif
+
+#if defined(Q_WS_MAC)
+// On mac (cocoa) we always get full update.
+// So check that the expected region is contained inside the actual
+#define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
+#else
+#define COMPARE_REGIONS QTRY_COMPARE
+#endif
+
+#include "../../../platformquirks.h"
+
+static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit.
+
+static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(point);
+ event.setButton(button);
+ event.setButtons(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
+ Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(point);
+ event.setButton(button);
+ event.setButtons(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(point);
+ event.setButton(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ sendMousePress(scene, point, button);
+ sendMouseRelease(scene, point, button);
+}
+
+static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
+{
+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
+ QApplication::sendEvent(scene, &keyEvent);
+}
+
+static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
+{
+ QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
+ QApplication::sendEvent(scene, &keyEvent);
+}
+
+static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
+{
+ sendKeyPress(scene, key);
+ sendKeyRelease(scene, key);
+}
+
+class EventSpy : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class EventSpy2 : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy2(QObject *watched)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ QMap<QEvent::Type, int> counts;
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ ++counts[event->type()];
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ ++counts[event->type()];
+ return false;
+ }
+};
+
+class EventTester : public QGraphicsItem
+{
+public:
+ EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), repaints(0)
+ { br = QRectF(-10, -10, 20, 20); }
+
+ void setGeometry(const QRectF &rect)
+ {
+ prepareGeometryChange();
+ br = rect;
+ update();
+ }
+
+ QRectF boundingRect() const
+ { return br; }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *)
+ {
+ hints = painter->renderHints();
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ lastExposedRect = o->exposedRect;
+ ++repaints;
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ events << event->type();
+ return QGraphicsItem::sceneEvent(event);
+ }
+
+ void reset()
+ {
+ events.clear();
+ hints = QPainter::RenderHints(0);
+ repaints = 0;
+ lastExposedRect = QRectF();
+ }
+
+ QList<QEvent::Type> events;
+ QPainter::RenderHints hints;
+ int repaints;
+ QRectF br;
+ QRectF lastExposedRect;
+ QBrush brush;
+};
+
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ ++repaints;
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+};
+
+class tst_QGraphicsItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void init();
+
+private slots:
+ void construction();
+ void constructionWithParent();
+ void destruction();
+ void deleteChildItem();
+ void scene();
+ void parentItem();
+ void setParentItem();
+ void children();
+ void flags();
+ void inputMethodHints();
+ void toolTip();
+ void visible();
+ void isVisibleTo();
+ void explicitlyVisible();
+ void enabled();
+ void explicitlyEnabled();
+ void selected();
+ void selected2();
+ void selected_group();
+ void selected_textItem();
+ void selected_multi();
+ void acceptedMouseButtons();
+ void acceptsHoverEvents();
+ void childAcceptsHoverEvents();
+ void hasFocus();
+ void pos();
+ void scenePos();
+ void matrix();
+ void sceneMatrix();
+ void setMatrix();
+ void zValue();
+ void shape();
+ void contains();
+ void collidesWith_item();
+ void collidesWith_path_data();
+ void collidesWith_path();
+ void collidesWithItemWithClip();
+ void isObscuredBy();
+ void isObscured();
+ void mapFromToParent();
+ void mapFromToScene();
+ void mapFromToItem();
+ void mapRectFromToParent_data();
+ void mapRectFromToParent();
+ void isAncestorOf();
+ void commonAncestorItem();
+ void data();
+ void type();
+ void graphicsitem_cast();
+ void hoverEventsGenerateRepaints();
+ void boundingRects_data();
+ void boundingRects();
+ void boundingRects2();
+ void sceneBoundingRect();
+ void childrenBoundingRect();
+ void childrenBoundingRectTransformed();
+ void childrenBoundingRect2();
+ void childrenBoundingRect3();
+ void childrenBoundingRect4();
+ void childrenBoundingRect5();
+ void group();
+ void setGroup();
+ void setGroup2();
+ void nestedGroups();
+ void warpChildrenIntoGroup();
+ void removeFromGroup();
+ void handlesChildEvents();
+ void handlesChildEvents2();
+ void handlesChildEvents3();
+ void filtersChildEvents();
+ void filtersChildEvents2();
+ void ensureVisible();
+ void cursor();
+ //void textControlGetterSetter();
+ void defaultItemTest_QGraphicsLineItem();
+ void defaultItemTest_QGraphicsPixmapItem();
+ void defaultItemTest_QGraphicsTextItem();
+ void defaultItemTest_QGraphicsEllipseItem();
+ void itemChange();
+ void sceneEventFilter();
+ void prepareGeometryChange();
+ void paint();
+ void deleteItemInEventHandlers();
+ void itemClipsToShape();
+ void itemClipsChildrenToShape();
+ void itemClipsChildrenToShape2();
+ void itemClipsChildrenToShape3();
+ void itemClipsChildrenToShape4();
+ void itemClipsChildrenToShape5();
+ void itemClipsTextChildToShape();
+ void itemClippingDiscovery();
+ void ancestorFlags();
+ void untransformable();
+ void contextMenuEventPropagation();
+ void itemIsMovable();
+ void boundingRegion_data();
+ void boundingRegion();
+ void itemTransform_parentChild();
+ void itemTransform_siblings();
+ void itemTransform_unrelated();
+ void opacity_data();
+ void opacity();
+ void opacity2();
+ void opacityZeroUpdates();
+ void itemStacksBehindParent();
+ void nestedClipping();
+ void nestedClippingTransforms();
+ void sceneTransformCache();
+ void tabChangesFocus();
+ void tabChangesFocus_data();
+ void cacheMode();
+ void cacheMode2();
+ void updateCachedItemAfterMove();
+ void deviceTransform_data();
+ void deviceTransform();
+ void update();
+ void setTransformProperties_data();
+ void setTransformProperties();
+ void itemUsesExtendedStyleOption();
+ void itemSendsGeometryChanges();
+ void moveItem();
+ void moveLineItem();
+ void sorting_data();
+ void sorting();
+ void itemHasNoContents();
+ void hitTestUntransformableItem();
+ void hitTestGraphicsEffectItem();
+ void focusProxy();
+ void subFocus();
+ void focusProxyDeletion();
+ void negativeZStacksBehindParent();
+ void setGraphicsEffect();
+ void panel();
+ void addPanelToActiveScene();
+ void panelWithFocusItem();
+ void activate();
+ void setActivePanelOnInactiveScene();
+ void activationOnShowHide();
+ void moveWhileDeleting();
+ void ensureDirtySceneTransform();
+ void focusScope();
+ void focusScope2();
+ void stackBefore();
+ void sceneModality();
+ void panelModality();
+ void mixedModality();
+ void modality_hover();
+ void modality_mouseGrabber();
+ void modality_clickFocus();
+ void modality_keyEvents();
+ void itemIsInFront();
+ void scenePosChange();
+ void updateMicroFocus();
+ void textItem_shortcuts();
+ void scroll();
+ void focusHandling_data();
+ void focusHandling();
+ void touchEventPropagation_data();
+ void touchEventPropagation();
+ void deviceCoordinateCache_simpleRotations();
+
+ // task specific tests below me
+ void task141694_textItemEnsureVisible();
+ void task128696_textItemEnsureMovable();
+ void ensureUpdateOnTextItem();
+ void task177918_lineItemUndetected();
+ void task240400_clickOnTextItem_data();
+ void task240400_clickOnTextItem();
+ void task243707_addChildBeforeParent();
+ void task197802_childrenVisibility();
+ void QTBUG_4233_updateCachedWithSceneRect();
+ void QTBUG_5418_textItemSetDefaultColor();
+ void QTBUG_6738_missingUpdateWithSetParent();
+ void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
+ void QT_2653_fullUpdateDiscardingOpacityUpdate();
+ void QT_2649_focusScope();
+ void sortItemsWhileAdding();
+ void doNotMarkFullUpdateIfNotInScene();
+ void itemDiesDuringDraggingOperation();
+ void QTBUG_12112_focusItem();
+ void QTBUG_13473_sceneposchange();
+ void QTBUG_16374_crashInDestructor();
+ void QTBUG_20699_focusScopeCrash();
+
+private:
+ QList<QGraphicsItem *> paintedItems;
+};
+
+void tst_QGraphicsItem::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QGraphicsItem::construction()
+{
+ for (int i = 0; i < 7; ++i) {
+ QGraphicsItem *item;
+ switch (i) {
+ case 0:
+ item = new QGraphicsEllipseItem;
+ QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 1:
+ item = new QGraphicsLineItem;
+ QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 2:
+ item = new QGraphicsPathItem;
+ QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 3:
+ item = new QGraphicsPixmapItem;
+ QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 4:
+ item = new QGraphicsPolygonItem;
+ QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 5:
+ item = new QGraphicsRectItem;
+ QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 6:
+ item = new QGraphicsTextItem;
+ QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ // This is the only item that uses an extended style option.
+ QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ break;
+ default:
+ qFatal("You broke the logic, please fix!");
+ break;
+ }
+
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+ QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
+ QVERIFY(item->children().isEmpty());
+ QVERIFY(item->isVisible());
+ QVERIFY(item->isEnabled());
+ QVERIFY(!item->isSelected());
+ QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
+ if (item->type() == QGraphicsTextItem::Type)
+ QVERIFY(item->acceptsHoverEvents());
+ else
+ QVERIFY(!item->acceptsHoverEvents());
+ QVERIFY(!item->hasFocus());
+ QCOMPARE(item->pos(), QPointF());
+ QCOMPARE(item->matrix(), QMatrix());
+ QCOMPARE(item->sceneMatrix(), QMatrix());
+ QCOMPARE(item->zValue(), qreal(0));
+ QCOMPARE(item->sceneBoundingRect(), QRectF());
+ QCOMPARE(item->shape(), QPainterPath());
+ QVERIFY(!item->contains(QPointF(0, 0)));
+ QVERIFY(!item->collidesWithItem(0));
+ QVERIFY(item->collidesWithItem(item));
+ QVERIFY(!item->collidesWithPath(QPainterPath()));
+ QVERIFY(!item->isAncestorOf(0));
+ QVERIFY(!item->isAncestorOf(item));
+ QCOMPARE(item->data(0), QVariant());
+ delete item;
+ }
+}
+
+class BoundingRectItem : public QGraphicsRectItem
+{
+public:
+ BoundingRectItem(QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100,
+ parent)
+ {}
+
+ QRectF boundingRect() const
+ {
+ QRectF tmp = QGraphicsRectItem::boundingRect();
+ foreach (QGraphicsItem *child, children())
+ tmp |= child->boundingRect(); // <- might be pure virtual
+ return tmp;
+ }
+};
+
+void tst_QGraphicsItem::constructionWithParent()
+{
+ // This test causes a crash if item1 calls item2's pure virtuals before the
+ // object has been constructed.
+ QGraphicsItem *item0 = new BoundingRectItem;
+ QGraphicsItem *item1 = new BoundingRectItem;
+ QGraphicsScene scene;
+ scene.addItem(item0);
+ scene.addItem(item1);
+ QGraphicsItem *item2 = new BoundingRectItem(item1);
+ QCOMPARE(item1->children(), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200));
+
+ item2->setParentItem(item0);
+ QCOMPARE(item0->children(), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200));
+}
+
+static int itemDeleted = 0;
+class Item : public QGraphicsRectItem
+{
+public:
+ ~Item()
+ { ++itemDeleted; }
+};
+
+void tst_QGraphicsItem::destruction()
+{
+ QCOMPARE(itemDeleted, 0);
+ {
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ delete parent;
+ QCOMPARE(itemDeleted, 1);
+ }
+ {
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ QCOMPARE(parent->children().size(), 1);
+ delete child;
+ QCOMPARE(parent->children().size(), 0);
+ delete parent;
+ QCOMPARE(itemDeleted, 2);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
+ child->setParentItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ scene.addItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ delete parent;
+ QCOMPARE(itemDeleted, 3);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ QCOMPARE(parent->children().size(), 1);
+ delete child;
+ QCOMPARE(parent->children().size(), 0);
+ delete parent;
+ QCOMPARE(itemDeleted, 4);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ scene.removeItem(parent);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+ delete parent;
+ QCOMPARE(itemDeleted, 5);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+ QCOMPARE(parent->scene(), (QGraphicsScene *)0);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ scene.removeItem(child);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+ QCOMPARE(parent->scene(), &scene);
+ QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
+ QVERIFY(parent->children().isEmpty());
+ delete parent;
+ QCOMPARE(itemDeleted, 5);
+ delete child;
+ QCOMPARE(itemDeleted, 6);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ scene.removeItem(child);
+ scene.removeItem(parent);
+ delete child;
+ delete parent;
+ QCOMPARE(itemDeleted, 7);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QGraphicsScene scene2;
+ scene2.addItem(parent);
+ delete parent;
+ QCOMPARE(itemDeleted, 8);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ QGraphicsScene scene2;
+ scene2.addItem(parent);
+ QCOMPARE(child->scene(), &scene2);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ scene2.addItem(parent);
+ QCOMPARE(child->scene(), &scene2);
+ delete parent;
+ QCOMPARE(itemDeleted, 9);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ QGraphicsScene scene2;
+ scene2.addItem(child);
+ QCOMPARE(child->scene(), &scene2);
+ delete parent;
+ QCOMPARE(itemDeleted, 9);
+ delete child;
+ QCOMPARE(itemDeleted, 10);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *root = new QGraphicsRectItem;
+ QGraphicsItem *parent = root;
+ QGraphicsItem *middleItem = 0;
+ for (int i = 0; i < 99; ++i) {
+ Item *child = new Item;
+ child->setParentItem(parent);
+ parent = child;
+ if (i == 50)
+ middleItem = parent;
+ }
+ scene.addItem(root);
+
+ QCOMPARE(scene.items().size(), 100);
+
+ QGraphicsScene scene2;
+ scene2.addItem(middleItem);
+
+ delete middleItem;
+ QCOMPARE(itemDeleted, 59);
+ }
+ QCOMPARE(itemDeleted, 109);
+ {
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsRectItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ parent->setVisible(false);
+ scene->addItem(parent);
+ QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
+ delete scene;
+ QCOMPARE(itemDeleted, 110);
+ }
+}
+
+void tst_QGraphicsItem::deleteChildItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(QRectF());
+ QGraphicsItem *child1 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child2 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child3 = new QGraphicsRectItem(rect);
+ Q_UNUSED(child3);
+ delete child1;
+ child2->setParentItem(0);
+ delete child2;
+}
+
+void tst_QGraphicsItem::scene()
+{
+ QGraphicsRectItem *item = new QGraphicsRectItem;
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+ QCOMPARE(item->scene(), (QGraphicsScene *)&scene);
+
+ QGraphicsScene scene2;
+ scene2.addItem(item);
+ QCOMPARE(item->scene(), (QGraphicsScene *)&scene2);
+
+ scene2.removeItem(item);
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+
+ delete item;
+}
+
+void tst_QGraphicsItem::parentItem()
+{
+ QGraphicsRectItem item;
+ QCOMPARE(item.parentItem(), (QGraphicsItem *)0);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
+ QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
+ item2->setParentItem(&item);
+ QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
+ item2->setParentItem(0);
+ QCOMPARE(item2->parentItem(), (QGraphicsItem *)0);
+
+ delete item2;
+}
+
+void tst_QGraphicsItem::setParentItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ QCOMPARE(item->scene(), &scene);
+
+ QGraphicsRectItem *child = new QGraphicsRectItem;
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+
+ // This implicitly adds the item to the parent's scene
+ child->setParentItem(item);
+ QCOMPARE(child->scene(), &scene);
+
+ // This just makes it a toplevel
+ child->setParentItem(0);
+ QCOMPARE(child->scene(), &scene);
+
+ // Add the child back to the parent, then remove the parent from the scene
+ child->setParentItem(item);
+ scene.removeItem(item);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+}
+
+void tst_QGraphicsItem::children()
+{
+ QGraphicsRectItem item;
+ QVERIFY(item.children().isEmpty());
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
+ QCOMPARE(item.children().size(), 1);
+ QCOMPARE(item.children().first(), (QGraphicsItem *)item2);
+ QVERIFY(item2->children().isEmpty());
+
+ delete item2;
+ QVERIFY(item.children().isEmpty());
+}
+
+void tst_QGraphicsItem::flags()
+{
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
+ QCOMPARE(item->flags(), 0);
+
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(item);
+
+ {
+ // Focus
+ item->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ QVERIFY(!item->hasFocus());
+ item->setFocus();
+ QVERIFY(!item->hasFocus());
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ QVERIFY(!item->hasFocus());
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(scene.hasFocus());
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(scene.hasFocus());
+ }
+ {
+ // Selectable
+ item->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ QVERIFY(!item->isSelected());
+
+ item->setFlag(QGraphicsItem::ItemIsSelectable, true);
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ QVERIFY(item->isSelected());
+ item->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QVERIFY(!item->isSelected());
+ }
+ {
+ // Movable
+ item->setFlag(QGraphicsItem::ItemIsMovable, false);
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(0, 0));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0); // mouse grabber is reset
+
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(10, 10));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ QCOMPARE(item->pos(), QPointF());
+
+ QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease);
+ event3.setScenePos(QPointF(10, 10));
+ event3.setButtons(0);
+ QApplication::sendEvent(&scene, &event3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ item->setFlag(QGraphicsItem::ItemIsMovable, true);
+ QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress);
+ event4.setScenePos(QPointF(0, 0));
+ event4.setButton(Qt::LeftButton);
+ event4.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove);
+ event5.setScenePos(QPointF(10, 10));
+ event5.setButton(Qt::LeftButton);
+ event5.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event5);
+ QCOMPARE(item->pos(), QPointF(10, 10));
+ }
+ {
+ QGraphicsItem* clippingParent = new QGraphicsRectItem;
+ clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+
+ QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
+ nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+
+ QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
+ QVERIFY(!child->isClipped());
+
+ child->setParentItem(clippingParent);
+ QVERIFY(child->isClipped());
+
+ child->setParentItem(nonClippingParent);
+ QVERIFY(!child->isClipped());
+ }
+}
+
+class ImhTester : public QGraphicsItem
+{
+ QRectF boundingRect() const { return QRectF(); }
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+};
+
+void tst_QGraphicsItem::inputMethodHints()
+{
+ ImhTester *item = new ImhTester;
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ item->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ QCOMPARE(item->inputMethodHints(), Qt::ImhNone);
+ ImhTester *item2 = new ImhTester;
+ item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ Qt::InputMethodHints imHints = item2->inputMethodHints();
+ imHints |= Qt::ImhHiddenText;
+ item2->setInputMethodHints(imHints);
+ QGraphicsScene scene;
+ scene.addItem(item);
+ scene.addItem(item2);
+ QGraphicsView view(&scene);
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ item->setFocus();
+ QTRY_VERIFY(item->hasFocus());
+ QCOMPARE(view.inputMethodHints(), item->inputMethodHints());
+ item2->setFocus();
+ QTRY_VERIFY(item2->hasFocus());
+ QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
+ item->setFocus();
+ QTRY_VERIFY(item->hasFocus());
+ //Focus has changed but the new item doesn't accept input method, no hints.
+ QCOMPARE(view.inputMethodHints(), 0);
+ item2->setFocus();
+ QTRY_VERIFY(item2->hasFocus());
+ QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
+ imHints = item2->inputMethodHints();
+ imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ item2->setInputMethodHints(imHints);
+ QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
+ QGraphicsProxyWidget *widget = new QGraphicsProxyWidget;
+ QLineEdit *edit = new QLineEdit;
+ edit->setEchoMode(QLineEdit::Password);
+ scene.addItem(widget);
+ widget->setFocus();
+ QTRY_VERIFY(widget->hasFocus());
+ //No widget on the proxy, so no hints
+ QCOMPARE(view.inputMethodHints(), 0);
+ widget->setWidget(edit);
+ //View should match with the line edit
+ QCOMPARE(view.inputMethodHints(), edit->inputMethodHints());
+}
+
+void tst_QGraphicsItem::toolTip()
+{
+ QString toolTip = "Qt rocks!";
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ item->setPen(QPen(Qt::red, 1));
+ item->setBrush(QBrush(Qt::blue));
+ QVERIFY(item->toolTip().isEmpty());
+ item->setToolTip(toolTip);
+ QCOMPARE(item->toolTip(), toolTip);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+ QTest::qWait(250);
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(250);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(!foundTipLabel);
+ }
+
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().center()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(250);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(foundTipLabel);
+ }
+
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(1000);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel") && widget->isVisible())
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(!foundTipLabel);
+ }
+}
+
+void tst_QGraphicsItem::visible()
+{
+ QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ QVERIFY(item->isVisible());
+ item->setVisible(false);
+ QVERIFY(!item->isVisible());
+ item->setVisible(true);
+ QVERIFY(item->isVisible());
+
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(item);
+ QVERIFY(item->isVisible());
+ QCOMPARE(scene.itemAt(0, 0), item);
+ item->setVisible(false);
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
+ item->setVisible(true);
+ QCOMPARE(scene.itemAt(0, 0), item);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), item);
+ item->setVisible(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ item->setVisible(true);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ item->setVisible(false);
+ QVERIFY(!item->hasFocus());
+ item->setVisible(true);
+ QVERIFY(!item->hasFocus());
+}
+
+void tst_QGraphicsItem::isVisibleTo()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
+ QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50));
+ QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100);
+
+ child->setParentItem(parent);
+ grandChild->setParentItem(child);
+
+ QVERIFY(grandChild->isVisible());
+ QVERIFY(grandChild->isVisibleTo(grandChild));
+ QVERIFY(grandChild->isVisibleTo(child));
+ QVERIFY(grandChild->isVisibleTo(parent));
+ QVERIFY(grandChild->isVisibleTo(0));
+ QVERIFY(child->isVisible());
+ QVERIFY(child->isVisibleTo(child));
+ QVERIFY(child->isVisibleTo(parent));
+ QVERIFY(child->isVisibleTo(0));
+ QVERIFY(parent->isVisible());
+ QVERIFY(parent->isVisibleTo(parent));
+ QVERIFY(parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+
+ // Case 1: only parent is explicitly hidden
+ parent->hide();
+
+ QVERIFY(!grandChild->isVisible());
+ QVERIFY(grandChild->isVisibleTo(grandChild));
+ QVERIFY(grandChild->isVisibleTo(child));
+ QVERIFY(grandChild->isVisibleTo(parent));
+ QVERIFY(!grandChild->isVisibleTo(0));
+ QVERIFY(!child->isVisible());
+ QVERIFY(child->isVisibleTo(child));
+ QVERIFY(child->isVisibleTo(parent));
+ QVERIFY(!child->isVisibleTo(0));
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!parent->isVisibleTo(parent));
+ QVERIFY(!parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+
+ // Case 2: only child is hidden
+ parent->show();
+ child->hide();
+
+ QVERIFY(!grandChild->isVisible());
+ QVERIFY(grandChild->isVisibleTo(grandChild));
+ QVERIFY(grandChild->isVisibleTo(child));
+ QVERIFY(!grandChild->isVisibleTo(parent));
+ QVERIFY(!grandChild->isVisibleTo(0));
+ QVERIFY(!child->isVisible());
+ QVERIFY(!child->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(parent));
+ QVERIFY(!child->isVisibleTo(0));
+ QVERIFY(parent->isVisible());
+ QVERIFY(parent->isVisibleTo(parent));
+ QVERIFY(parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+
+ // Case 3: only grand child is hidden
+ child->show();
+ grandChild->hide();
+
+ QVERIFY(!grandChild->isVisible());
+ QVERIFY(!grandChild->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(child));
+ QVERIFY(!grandChild->isVisibleTo(parent));
+ QVERIFY(!grandChild->isVisibleTo(0));
+ QVERIFY(child->isVisible());
+ QVERIFY(child->isVisibleTo(child));
+ QVERIFY(child->isVisibleTo(parent));
+ QVERIFY(child->isVisibleTo(0));
+ QVERIFY(parent->isVisible());
+ QVERIFY(parent->isVisibleTo(parent));
+ QVERIFY(parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+}
+
+void tst_QGraphicsItem::explicitlyVisible()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
+ child->setParentItem(parent);
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(child->isVisible());
+
+ parent->hide();
+
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ parent->show();
+ child->hide();
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ parent->hide();
+
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ parent->show();
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible()); // <- explicitly hidden
+
+ child->show();
+
+ QVERIFY(child->isVisible());
+
+ parent->hide();
+
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible()); // <- explicit show doesn't work
+
+ parent->show();
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(child->isVisible()); // <- no longer explicitly hidden
+
+ // ------------------- Reparenting ------------------------------
+
+ QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
+ QVERIFY(parent2->isVisible());
+
+ // Reparent implicitly hidden item to a visible parent.
+ parent->hide();
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible());
+ child->setParentItem(parent2);
+ QVERIFY(parent2->isVisible());
+ QVERIFY(child->isVisible());
+
+ // Reparent implicitly hidden item to a hidden parent.
+ child->setParentItem(parent);
+ parent2->hide();
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent explicitly hidden item to a visible parent.
+ child->hide();
+ parent->show();
+ child->setParentItem(parent);
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent explicitly hidden item to a hidden parent.
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent explicitly hidden item to a visible parent.
+ parent->show();
+ child->setParentItem(parent);
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent visible item to a hidden parent.
+ child->show();
+ parent2->hide();
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isVisible());
+ QVERIFY(!child->isVisible());
+ parent2->show();
+ QVERIFY(parent2->isVisible());
+ QVERIFY(child->isVisible());
+
+ // Reparent implicitly hidden child to root.
+ parent2->hide();
+ QVERIFY(!child->isVisible());
+ child->setParentItem(0);
+ QVERIFY(child->isVisible());
+
+ // Reparent an explicitly hidden child to root.
+ child->hide();
+ child->setParentItem(parent2);
+ parent2->show();
+ QVERIFY(!child->isVisible());
+ child->setParentItem(0);
+ QVERIFY(!child->isVisible());
+}
+
+void tst_QGraphicsItem::enabled()
+{
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ QVERIFY(item->isEnabled());
+ item->setEnabled(false);
+ QVERIFY(!item->isEnabled());
+ item->setEnabled(true);
+ QVERIFY(item->isEnabled());
+ item->setEnabled(false);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(item);
+ item->setFocus();
+ QVERIFY(!item->hasFocus());
+ item->setEnabled(true);
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ item->setEnabled(false);
+ QVERIFY(!item->hasFocus());
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ item->setEnabled(true);
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ item->setEnabled(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::explicitlyEnabled()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
+ child->setParentItem(parent);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(child->isEnabled());
+
+ parent->setEnabled(false);
+
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ parent->setEnabled(true);
+ child->setEnabled(false);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ parent->setEnabled(false);
+
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ parent->setEnabled(true);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled()); // <- explicitly disabled
+
+ child->setEnabled(true);
+
+ QVERIFY(child->isEnabled());
+
+ parent->setEnabled(false);
+
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work
+
+ parent->setEnabled(true);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(child->isEnabled()); // <- no longer explicitly disabled
+
+ // ------------------- Reparenting ------------------------------
+
+ QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
+ QVERIFY(parent2->isEnabled());
+
+ // Reparent implicitly hidden item to a enabled parent.
+ parent->setEnabled(false);
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+ child->setParentItem(parent2);
+ QVERIFY(parent2->isEnabled());
+ QVERIFY(child->isEnabled());
+
+ // Reparent implicitly hidden item to a hidden parent.
+ child->setParentItem(parent);
+ parent2->setEnabled(false);
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent explicitly hidden item to a enabled parent.
+ child->setEnabled(false);
+ parent->setEnabled(true);
+ child->setParentItem(parent);
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent explicitly hidden item to a hidden parent.
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent explicitly hidden item to a enabled parent.
+ parent->setEnabled(true);
+ child->setParentItem(parent);
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent enabled item to a hidden parent.
+ child->setEnabled(true);
+ parent2->setEnabled(false);
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isEnabled());
+ QVERIFY(!child->isEnabled());
+ parent2->setEnabled(true);
+ QVERIFY(parent2->isEnabled());
+ QVERIFY(child->isEnabled());
+
+ // Reparent implicitly hidden child to root.
+ parent2->setEnabled(false);
+ QVERIFY(!child->isEnabled());
+ child->setParentItem(0);
+ QVERIFY(child->isEnabled());
+
+ // Reparent an explicitly hidden child to root.
+ child->setEnabled(false);
+ child->setParentItem(parent2);
+ parent2->setEnabled(true);
+ QVERIFY(!child->isEnabled());
+ child->setParentItem(0);
+ QVERIFY(!child->isEnabled());
+}
+
+class SelectChangeItem : public QGraphicsRectItem
+{
+public:
+ SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); }
+ QList<bool> values;
+
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ if (change == ItemSelectedChange)
+ values << value.toBool();
+ return QGraphicsRectItem::itemChange(change, value);
+ }
+};
+
+void tst_QGraphicsItem::selected()
+{
+ SelectChangeItem *item = new SelectChangeItem;
+ item->setFlag(QGraphicsItem::ItemIsSelectable);
+ QVERIFY(!item->isSelected());
+ QVERIFY(item->values.isEmpty());
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 1);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+ item->setSelected(false);
+ QCOMPARE(item->values.size(), 2);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 3);
+ item->setEnabled(false);
+ QCOMPARE(item->values.size(), 4);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ item->setEnabled(true);
+ QCOMPARE(item->values.size(), 4);
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 5);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+ item->setVisible(false);
+ QCOMPARE(item->values.size(), 6);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ item->setVisible(true);
+ QCOMPARE(item->values.size(), 6);
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 7);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+
+ QGraphicsScene scene(-100, -100, 200, 200);
+ scene.addItem(item);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
+ item->setSelected(false);
+ QVERIFY(scene.selectedItems().isEmpty());
+ item->setSelected(true);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
+ item->setSelected(false);
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ // Interactive selection
+ QGraphicsView view(&scene);
+ view.setFixedSize(250, 250);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ qApp->processEvents();
+ qApp->processEvents();
+
+ scene.clearSelection();
+ QCOMPARE(item->values.size(), 10);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+
+ // Click inside and check that it's selected
+ QTest::mouseMove(view.viewport());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ QCOMPARE(item->values.size(), 11);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+
+ // Click outside and check that it's not selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
+ QCOMPARE(item->values.size(), 12);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+
+ SelectChangeItem *item2 = new SelectChangeItem;
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setPos(100, 0);
+ scene.addItem(item2);
+
+ // Click inside and check that it's selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ QCOMPARE(item->values.size(), 13);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+
+ // Click inside item2 and check that it's selected, and item is not
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QCOMPARE(item->values.size(), 14);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ QCOMPARE(item2->values.size(), 1);
+ QCOMPARE(item2->values.last(), true);
+ QVERIFY(item2->isSelected());
+}
+
+void tst_QGraphicsItem::selected2()
+{
+ // Selecting an item, then moving another previously caused a crash.
+ QGraphicsScene scene;
+ QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100));
+ line1->setPos(-105, 0);
+ line1->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100));
+ line2->setFlag(QGraphicsItem::ItemIsMovable);
+
+ line1->setSelected(true);
+
+ {
+ QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
+ mousePress.setScenePos(QPointF(50, 50));
+ mousePress.setButton(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &mousePress);
+ QVERIFY(mousePress.isAccepted());
+ }
+ {
+ QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove);
+ mouseMove.setScenePos(QPointF(60, 60));
+ mouseMove.setButton(Qt::LeftButton);
+ mouseMove.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &mouseMove);
+ QVERIFY(mouseMove.isAccepted());
+ }
+}
+
+void tst_QGraphicsItem::selected_group()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF());
+ QGraphicsItem *item2 = scene.addRect(QRectF());
+ item1->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF())->setParentItem(item1);
+ QGraphicsItem *leaf = scene.addRect(QRectF());
+ leaf->setFlag(QGraphicsItem::ItemIsSelectable);
+ leaf->setParentItem(item2);
+
+ QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(group->scene(), &scene);
+ group->setFlag(QGraphicsItem::ItemIsSelectable);
+ foreach (QGraphicsItem *item, scene.items()) {
+ if (item == group)
+ QVERIFY(!item->group());
+ else
+ QCOMPARE(item->group(), group);
+ }
+
+ QVERIFY(group->handlesChildEvents());
+ QVERIFY(!group->isSelected());
+ group->setSelected(false);
+ QVERIFY(!group->isSelected());
+ group->setSelected(true);
+ QVERIFY(group->isSelected());
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(item->isSelected());
+ group->setSelected(false);
+ QVERIFY(!group->isSelected());
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(!item->isSelected());
+ leaf->setSelected(true);
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(item->isSelected());
+ leaf->setSelected(false);
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(!item->isSelected());
+
+ leaf->setSelected(true);
+ QGraphicsScene scene2;
+ scene2.addItem(item1);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+}
+
+void tst_QGraphicsItem::selected_textItem()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *text = scene.addText(QLatin1String("Text"));
+ text->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ QTRY_VERIFY(!text->isSelected());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(text->mapToScene(0, 0)));
+ QTRY_VERIFY(text->isSelected());
+
+ text->setSelected(false);
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(text->mapToScene(0, 0)));
+ QTRY_VERIFY(text->isSelected());
+}
+
+void tst_QGraphicsItem::selected_multi()
+{
+ // Test multiselection behavior
+ QGraphicsScene scene;
+
+ // Create two disjoint items
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
+ QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ item1->setPos(-15, 0);
+ item2->setPos(15, 20);
+
+ // Make both items selectable
+ item1->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ // Create and show a view
+ QGraphicsView view(&scene);
+ view.show();
+ view.fitInView(scene.sceneRect());
+ qApp->processEvents();
+
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Start clicking
+ QTest::qWait(200);
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Ctrl-click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item2->isSelected());
+ QVERIFY(item1->isSelected());
+
+ // Ctrl-click on item1 again
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Ctrl-click on item2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on scene
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-click on scene
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Press on item2
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+
+ // Release on item2
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-press on item1
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ {
+ // Ctrl-move on item1
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
+ QApplication::sendEvent(view.viewport(), &event);
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ }
+
+ // Release on item1
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ item1->setFlag(QGraphicsItem::ItemIsMovable);
+ item1->setSelected(false);
+
+ // Ctrl-press on item1
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ {
+ // Ctrl-move on item1
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
+ QApplication::sendEvent(view.viewport(), &event);
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ }
+
+ // Release on item1
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+}
+
+void tst_QGraphicsItem::acceptedMouseButtons()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
+ QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ item2->setZValue(1);
+
+ item1->setFlag(QGraphicsItem::ItemIsMovable);
+ item2->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
+ QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2);
+ item2->setAcceptedMouseButtons(0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1);
+}
+
+class HoverItem : public QGraphicsRectItem
+{
+public:
+ HoverItem(const QRectF &rect)
+ : QGraphicsRectItem(rect), hoverInCount(0),
+ hoverMoveCount(0), hoverOutCount(0)
+ { }
+
+ int hoverInCount;
+ int hoverMoveCount;
+ int hoverOutCount;
+protected:
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *)
+ { ++hoverInCount; }
+
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *)
+ { ++hoverMoveCount; }
+
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
+ { ++hoverOutCount; }
+};
+
+void tst_QGraphicsItem::acceptsHoverEvents()
+{
+ QGraphicsScene scene;
+ HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
+ HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
+ scene.addItem(item1);
+ scene.addItem(item2);
+ item2->setZValue(1);
+
+ QVERIFY(!item1->acceptsHoverEvents());
+ QVERIFY(!item2->acceptsHoverEvents());
+ item1->setAcceptsHoverEvents(true);
+ item2->setAcceptsHoverEvents(true);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item2->hoverInCount, 1);
+
+ item1->setAcceptsHoverEvents(false);
+ item2->setAcceptsHoverEvents(false);
+
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item2->hoverInCount, 1);
+
+ item1->setAcceptsHoverEvents(true);
+ item2->setAcceptsHoverEvents(false);
+
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item1->hoverInCount, 1);
+ QCOMPARE(item2->hoverInCount, 1);
+}
+
+void tst_QGraphicsItem::childAcceptsHoverEvents()
+{
+ QGraphicsScene scene;
+ HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
+ HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
+
+ scene.addItem(item1);
+ scene.addItem(item2);
+ item2->setParentItem(item1);
+ item2->setAcceptHoverEvents(true);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(item2->hoverInCount, 0);
+ QCOMPARE(item2->hoverMoveCount, 0);
+ QCOMPARE(item2->hoverOutCount, 0);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 1);
+ QCOMPARE(item2->hoverMoveCount, 1);
+ QCOMPARE(item2->hoverOutCount, 0);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 1);
+ QCOMPARE(item2->hoverMoveCount, 2);
+ QCOMPARE(item2->hoverOutCount, 0);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(-7, -7));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 1);
+ QCOMPARE(item2->hoverMoveCount, 2);
+ QCOMPARE(item2->hoverOutCount, 1);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 2);
+ QCOMPARE(item2->hoverMoveCount, 3);
+ QCOMPARE(item2->hoverOutCount, 1);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20));
+ scene.addItem(item0);
+ item1->setParentItem(item0);
+ item0->setAcceptHoverEvents(true);
+
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+
+ event.setScenePos(QPointF(-15, -15));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 2);
+ QCOMPARE(item2->hoverMoveCount, 3);
+ QCOMPARE(item2->hoverOutCount, 2);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+ QCOMPARE(item0->hoverInCount, 1);
+ QCOMPARE(item0->hoverMoveCount, 1);
+ QCOMPARE(item0->hoverOutCount, 0);
+}
+
+void tst_QGraphicsItem::hasFocus()
+{
+ QGraphicsLineItem *line = new QGraphicsLineItem;
+ QVERIFY(!line->hasFocus());
+ line->setFocus();
+ QVERIFY(!line->hasFocus());
+
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(line);
+
+ line->setFocus();
+ QVERIFY(!line->hasFocus());
+ line->setFlag(QGraphicsItem::ItemIsFocusable);
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+
+ QGraphicsScene scene2;
+ QApplication::sendEvent(&scene2, &activate);
+
+ scene2.addItem(line);
+ QVERIFY(!line->hasFocus());
+
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(scene2.focusItem(), (QGraphicsItem *)0);
+
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+ line->clearFocus();
+ QVERIFY(!line->hasFocus());
+
+ QGraphicsLineItem *line2 = new QGraphicsLineItem;
+ line2->setFlag(QGraphicsItem::ItemIsFocusable);
+ scene2.addItem(line2);
+
+ line2->setFocus();
+ QVERIFY(!line->hasFocus());
+ QVERIFY(line2->hasFocus());
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+ QVERIFY(!line2->hasFocus());
+}
+
+void tst_QGraphicsItem::pos()
+{
+ QGraphicsItem *child = new QGraphicsLineItem;
+ QGraphicsItem *parent = new QGraphicsLineItem;
+
+ QCOMPARE(child->pos(), QPointF());
+ QCOMPARE(parent->pos(), QPointF());
+
+ child->setParentItem(parent);
+ child->setPos(10, 10);
+
+ QCOMPARE(child->pos(), QPointF(10, 10));
+
+ parent->setPos(10, 10);
+
+ QCOMPARE(parent->pos(), QPointF(10, 10));
+ QCOMPARE(child->pos(), QPointF(10, 10));
+
+ delete child;
+ delete parent;
+}
+
+void tst_QGraphicsItem::scenePos()
+{
+ QGraphicsItem *child = new QGraphicsLineItem;
+ QGraphicsItem *parent = new QGraphicsLineItem;
+
+ QCOMPARE(child->scenePos(), QPointF());
+ QCOMPARE(parent->scenePos(), QPointF());
+
+ child->setParentItem(parent);
+ child->setPos(10, 10);
+
+ QCOMPARE(child->scenePos(), QPointF(10, 10));
+
+ parent->setPos(10, 10);
+
+ QCOMPARE(parent->scenePos(), QPointF(10, 10));
+ QCOMPARE(child->scenePos(), QPointF(20, 20));
+
+ parent->setPos(20, 20);
+
+ QCOMPARE(parent->scenePos(), QPointF(20, 20));
+ QCOMPARE(child->scenePos(), QPointF(30, 30));
+
+ delete child;
+ delete parent;
+}
+
+void tst_QGraphicsItem::matrix()
+{
+ QGraphicsLineItem line;
+ QCOMPARE(line.matrix(), QMatrix());
+ line.setMatrix(QMatrix().rotate(90));
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.setMatrix(QMatrix().rotate(90));
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.setMatrix(QMatrix().rotate(90), true);
+ QCOMPARE(line.matrix(), QMatrix().rotate(180));
+ line.setMatrix(QMatrix().rotate(-90), true);
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.resetMatrix();
+ QCOMPARE(line.matrix(), QMatrix());
+
+ line.rotate(90);
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.rotate(90);
+ QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
+ line.resetMatrix();
+
+ line.scale(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
+ line.scale(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
+ line.resetMatrix();
+
+ line.shear(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
+ line.shear(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
+ line.resetMatrix();
+
+ line.translate(10, 10);
+ QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
+ line.translate(10, 10);
+ QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
+ line.resetMatrix();
+}
+
+void tst_QGraphicsItem::sceneMatrix()
+{
+ QGraphicsLineItem *parent = new QGraphicsLineItem;
+ QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
+
+ QCOMPARE(parent->sceneMatrix(), QMatrix());
+ QCOMPARE(child->sceneMatrix(), QMatrix());
+
+ parent->translate(10, 10);
+ QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
+ QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
+
+ child->translate(10, 10);
+ QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
+ QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
+
+ parent->rotate(90);
+ QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
+ QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
+
+ delete child;
+ delete parent;
+}
+
+void tst_QGraphicsItem::setMatrix()
+{
+ QGraphicsScene scene;
+ qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
+ QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
+ QRectF unrotatedRect(-12, -34, 56, 78);
+ QGraphicsRectItem item(unrotatedRect, 0, &scene);
+ scene.update(scene.sceneRect());
+ QApplication::instance()->processEvents();
+
+ QCOMPARE(spy.count(), 1);
+
+ item.setMatrix(QMatrix().rotate(qreal(12.34)));
+ QRectF rotatedRect = scene.sceneRect();
+ QVERIFY(unrotatedRect != rotatedRect);
+ scene.update(scene.sceneRect());
+ QApplication::instance()->processEvents();
+
+ QCOMPARE(spy.count(), 2);
+
+ item.setMatrix(QMatrix());
+
+ scene.update(scene.sceneRect());
+ QApplication::instance()->processEvents();
+
+ QCOMPARE(spy.count(), 3);
+ QList<QRectF> rlist = qVariantValue<QList<QRectF> >(spy.last().at(0));
+
+ QCOMPARE(rlist.size(), 3);
+ QCOMPARE(rlist.at(0), rotatedRect); // From item.setMatrix() (clearing rotated rect)
+ QCOMPARE(rlist.at(1), rotatedRect); // From scene.update() (updating scene rect)
+ QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
+}
+
+static QList<QGraphicsItem *> _paintedItems;
+class PainterItem : public QGraphicsItem
+{
+protected:
+ QRectF boundingRect() const
+ { return QRectF(-10, -10, 20, 20); }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
+};
+
+void tst_QGraphicsItem::zValue()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+
+ QGraphicsItem *item1 = new PainterItem;
+ QGraphicsItem *item2 = new PainterItem;
+ QGraphicsItem *item3 = new PainterItem;
+ QGraphicsItem *item4 = new PainterItem;
+ scene.addItem(item1);
+ scene.addItem(item2);
+ scene.addItem(item3);
+ scene.addItem(item4);
+ item2->setZValue(-3);
+ item4->setZValue(-2);
+ item1->setZValue(-1);
+ item3->setZValue(0);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::processEvents();
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+
+ QTRY_VERIFY(!_paintedItems.isEmpty());
+ QVERIFY((_paintedItems.size() % 4) == 0);
+ for (int i = 0; i < 3; ++i)
+ QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
+}
+
+void tst_QGraphicsItem::shape()
+{
+ QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
+
+ // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
+ // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
+ const qreal penWidthZero = qreal(0.00000001);
+
+ QPainterPathStroker ps;
+ ps.setWidth(penWidthZero);
+
+ QPainterPath path(line.line().p1());
+ path.lineTo(line.line().p2());
+ QPainterPath p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ QPen linePen;
+ linePen.setWidthF(5.0);
+ linePen.setCapStyle(Qt::RoundCap);
+ line.setPen(linePen);
+
+ ps.setCapStyle(line.pen().capStyle());
+ ps.setWidth(line.pen().widthF());
+ p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ linePen.setCapStyle(Qt::FlatCap);
+ line.setPen(linePen);
+ ps.setCapStyle(line.pen().capStyle());
+ p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ linePen.setCapStyle(Qt::SquareCap);
+ line.setPen(linePen);
+ ps.setCapStyle(line.pen().capStyle());
+ p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
+ QPainterPathStroker ps1;
+ ps1.setWidth(penWidthZero);
+ path = QPainterPath();
+ path.addRect(rect.rect());
+ p = ps1.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(rect.shape(), p);
+
+ QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
+ QPainterPathStroker ps2;
+ ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF());
+ path = QPainterPath();
+ path.addEllipse(ellipse.rect());
+ p = ps2.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(ellipse.shape(), p);
+
+ QPainterPathStroker ps3;
+ ps3.setWidth(penWidthZero);
+ p = ps3.createStroke(path);
+ p.addPath(path);
+ QGraphicsPathItem pathItem(path);
+ QCOMPARE(pathItem.shape(), p);
+
+ QRegion region(QRect(0, 0, 300, 200));
+ region = region.subtracted(QRect(50, 50, 200, 100));
+
+ QImage image(300, 200, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setClipRegion(region);
+ painter.fillRect(0, 0, 300, 200, Qt::green);
+ painter.end();
+ QPixmap pixmap = QPixmap::fromImage(image);
+
+ QGraphicsPixmapItem pixmapItem(pixmap);
+ path = QPainterPath();
+ path.addRegion(region);
+
+ {
+ QBitmap bitmap(300, 200);
+ bitmap.clear();
+ QPainter painter(&bitmap);
+ painter.setClipRegion(region);
+ painter.fillRect(0, 0, 300, 200, Qt::color1);
+ painter.end();
+
+ QBitmap bitmap2(300, 200);
+ bitmap2.clear();
+ painter.begin(&bitmap2);
+ painter.setClipPath(pixmapItem.shape());
+ painter.fillRect(0, 0, 300, 200, Qt::color1);
+ painter.end();
+
+ QCOMPARE(bitmap.toImage(), bitmap2.toImage());
+ }
+
+ QPolygonF poly;
+ poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10);
+ QGraphicsPolygonItem polygon(poly);
+ path = QPainterPath();
+ path.addPolygon(poly);
+
+ QPainterPathStroker ps4;
+ ps4.setWidth(penWidthZero);
+ p = ps4.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(polygon.shape(), p);
+}
+
+void tst_QGraphicsItem::contains()
+{
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+
+ // Rect
+ QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
+ QVERIFY(!rect.contains(QPointF(-11, -10)));
+ QVERIFY(rect.contains(QPointF(-10, -10)));
+ QVERIFY(!rect.contains(QPointF(-11, 0)));
+ QVERIFY(rect.contains(QPointF(-10, 0)));
+ QVERIFY(rect.contains(QPointF(0, -10)));
+ QVERIFY(rect.contains(QPointF(0, 0)));
+ QVERIFY(rect.contains(QPointF(9, 9)));
+
+ // Ellipse
+ QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
+ QVERIFY(!ellipse.contains(QPointF(-10, -10)));
+ QVERIFY(ellipse.contains(QPointF(-9, 0)));
+ QVERIFY(ellipse.contains(QPointF(0, -9)));
+ QVERIFY(ellipse.contains(QPointF(0, 0)));
+ QVERIFY(!ellipse.contains(QPointF(9, 9)));
+
+ // Line
+ QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
+ QVERIFY(!line.contains(QPointF(-10, 0)));
+ QVERIFY(!line.contains(QPointF(0, -10)));
+ QVERIFY(!line.contains(QPointF(10, 0)));
+ QVERIFY(!line.contains(QPointF(0, 10)));
+ QVERIFY(line.contains(QPointF(0, 0)));
+ QVERIFY(line.contains(QPointF(-9, -9)));
+ QVERIFY(line.contains(QPointF(9, 9)));
+
+ // Polygon
+ QGraphicsPolygonItem polygon(QPolygonF()
+ << QPointF(0, 0)
+ << QPointF(10, 0)
+ << QPointF(0, 10));
+ QVERIFY(polygon.contains(QPointF(1, 1)));
+ QVERIFY(polygon.contains(QPointF(4, 4)));
+ QVERIFY(polygon.contains(QPointF(1, 4)));
+ QVERIFY(polygon.contains(QPointF(4, 1)));
+ QVERIFY(!polygon.contains(QPointF(8, 8)));
+ QVERIFY(polygon.contains(QPointF(1, 8)));
+ QVERIFY(polygon.contains(QPointF(8, 1)));
+}
+
+void tst_QGraphicsItem::collidesWith_item()
+{
+ // Rectangle
+ QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
+ QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20));
+ QVERIFY(rect.collidesWithItem(&rect2));
+ QVERIFY(rect2.collidesWithItem(&rect));
+ rect2.setPos(21, 21);
+ QVERIFY(!rect.collidesWithItem(&rect2));
+ QVERIFY(!rect2.collidesWithItem(&rect));
+ rect2.setPos(-21, -21);
+ QVERIFY(!rect.collidesWithItem(&rect2));
+ QVERIFY(!rect2.collidesWithItem(&rect));
+ rect2.setPos(-17, -17);
+ QVERIFY(rect.collidesWithItem(&rect2));
+ QVERIFY(rect2.collidesWithItem(&rect));
+
+ QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
+ QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20));
+ QVERIFY(ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(ellipse2.collidesWithItem(&ellipse));
+ ellipse2.setPos(21, 21);
+ QVERIFY(!ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(!ellipse2.collidesWithItem(&ellipse));
+ ellipse2.setPos(-21, -21);
+ QVERIFY(!ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(!ellipse2.collidesWithItem(&ellipse));
+
+ ellipse2.setPos(-17, -17);
+ QVERIFY(!ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(!ellipse2.collidesWithItem(&ellipse));
+
+ {
+ QGraphicsScene scene;
+ QGraphicsRectItem rect(20, 20, 100, 100, 0, &scene);
+ QGraphicsRectItem rect2(40, 40, 50, 50, 0, &scene);
+ rect2.setZValue(1);
+ QGraphicsLineItem line(0, 0, 200, 200, 0, &scene);
+ line.setZValue(2);
+
+ QCOMPARE(scene.items().size(), 3);
+
+ QList<QGraphicsItem *> col1 = rect.collidingItems();
+ QCOMPARE(col1.size(), 2);
+ QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line));
+ QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2));
+
+ QList<QGraphicsItem *> col2 = rect2.collidingItems();
+ QCOMPARE(col2.size(), 2);
+ QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line));
+ QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect));
+
+ QList<QGraphicsItem *> col3 = line.collidingItems();
+ QCOMPARE(col3.size(), 2);
+ QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2));
+ QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect));
+ }
+}
+
+void tst_QGraphicsItem::collidesWith_path_data()
+{
+ QTest::addColumn<QPointF>("pos");
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QPainterPath>("shape");
+ QTest::addColumn<bool>("rectCollides");
+ QTest::addColumn<bool>("ellipseCollides");
+
+ QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
+
+ QPainterPath rect;
+ rect.addRect(0, 0, 20, 20);
+
+ QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
+ QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
+ QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
+}
+
+void tst_QGraphicsItem::collidesWith_path()
+{
+ QFETCH(QPointF, pos);
+ QFETCH(QMatrix, matrix);
+ QFETCH(QPainterPath, shape);
+ QFETCH(bool, rectCollides);
+ QFETCH(bool, ellipseCollides);
+
+ QGraphicsRectItem rect(QRectF(0, 0, 20, 20));
+ QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
+
+ rect.setPos(pos);
+ rect.setMatrix(matrix);
+
+ ellipse.setPos(pos);
+ ellipse.setMatrix(matrix);
+
+ QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
+
+ if (rectCollides)
+ QVERIFY(rect.collidesWithPath(mappedShape));
+ else
+ QVERIFY(!rect.collidesWithPath(mappedShape));
+
+ if (ellipseCollides)
+ QVERIFY(ellipse.collidesWithPath(mappedShape));
+ else
+ QVERIFY(!ellipse.collidesWithPath(mappedShape));
+}
+
+void tst_QGraphicsItem::collidesWithItemWithClip()
+{
+ QGraphicsScene scene;
+
+ QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100);
+ ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10);
+ ellipse2->setParentItem(ellipse);
+ QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10);
+ ellipse3->setParentItem(ellipse);
+ QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10);
+ ellipse5->setParentItem(ellipse);
+ QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10);
+
+ QVERIFY(ellipse2->collidesWithItem(ellipse3));
+ QVERIFY(ellipse3->collidesWithItem(ellipse2));
+ QVERIFY(!ellipse2->collidesWithItem(ellipse));
+ QVERIFY(!ellipse->collidesWithItem(ellipse2));
+ QVERIFY(!ellipse4->collidesWithItem(ellipse));
+ QVERIFY(!ellipse4->collidesWithItem(ellipse2));
+ QVERIFY(!ellipse4->collidesWithItem(ellipse3));
+ QVERIFY(!ellipse->collidesWithItem(ellipse4));
+ QVERIFY(!ellipse2->collidesWithItem(ellipse4));
+ QVERIFY(!ellipse3->collidesWithItem(ellipse4));
+ QVERIFY(ellipse->collidesWithItem(ellipse5));
+ QVERIFY(ellipse5->collidesWithItem(ellipse));
+}
+
+class MyItem : public QGraphicsEllipseItem
+{
+public:
+ bool isObscuredBy(const QGraphicsItem *item) const
+ {
+ const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item);
+ if (myItem) {
+ if (item->zValue() > zValue()) {
+ QRectF r = rect();
+ QPointF topMid = (r.topRight()+r.topLeft())/2;
+ QPointF botMid = (r.bottomRight()+r.bottomLeft())/2;
+ QPointF leftMid = (r.topLeft()+r.bottomLeft())/2;
+ QPointF rightMid = (r.topRight()+r.bottomRight())/2;
+
+ QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea());
+
+ if (mappedShape.contains(topMid) &&
+ mappedShape.contains(botMid) &&
+ mappedShape.contains(leftMid) &&
+ mappedShape.contains(rightMid))
+ return true;
+ else
+ return false;
+ }
+ else return false;
+ }
+ else
+ return QGraphicsItem::isObscuredBy(item);
+ }
+
+ QPainterPath opaqueArea() const
+ {
+ return shape();
+ }
+
+ enum {
+ Type = UserType+1
+ };
+ int type() const { return Type; }
+};
+
+void tst_QGraphicsItem::isObscuredBy()
+{
+ QGraphicsScene scene;
+
+ MyItem myitem1, myitem2;
+
+ myitem1.setRect(QRectF(50, 50, 40, 200));
+ myitem1.rotate(67);
+
+ myitem2.setRect(QRectF(25, 25, 20, 20));
+ myitem2.setZValue(-1.0);
+ scene.addItem(&myitem1);
+ scene.addItem(&myitem2);
+
+ QVERIFY(!myitem2.isObscuredBy(&myitem1));
+ QVERIFY(!myitem1.isObscuredBy(&myitem2));
+
+ myitem2.setRect(QRectF(-50, 85, 20, 20));
+ QVERIFY(myitem2.isObscuredBy(&myitem1));
+ QVERIFY(!myitem1.isObscuredBy(&myitem2));
+
+ myitem2.setRect(QRectF(-30, 70, 20, 20));
+ QVERIFY(!myitem2.isObscuredBy(&myitem1));
+ QVERIFY(!myitem1.isObscuredBy(&myitem2));
+
+ QGraphicsRectItem rect1, rect2;
+
+ rect1.setRect(QRectF(-40, -40, 50, 50));
+ rect1.setBrush(QBrush(Qt::red));
+ rect2.setRect(QRectF(-30, -20, 20, 20));
+ rect2.setZValue(-1.0);
+ rect2.setBrush(QBrush(Qt::blue));
+
+ QVERIFY(rect2.isObscuredBy(&rect1));
+ QVERIFY(!rect1.isObscuredBy(&rect2));
+
+ rect2.setPos(QPointF(-20, -25));
+
+ QVERIFY(!rect2.isObscuredBy(&rect1));
+ QVERIFY(!rect1.isObscuredBy(&rect2));
+
+ rect2.setPos(QPointF(-100, -100));
+
+ QVERIFY(!rect2.isObscuredBy(&rect1));
+ QVERIFY(!rect1.isObscuredBy(&rect2));
+}
+
+class OpaqueItem : public QGraphicsRectItem
+{
+protected:
+ QPainterPath opaqueArea() const
+ {
+ return shape();
+ }
+};
+
+void tst_QGraphicsItem::isObscured()
+{
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+
+ OpaqueItem *item1 = new OpaqueItem;
+ item1->setRect(0, 0, 100, 100);
+ item1->setZValue(0);
+
+ OpaqueItem *item2 = new OpaqueItem;
+ item2->setZValue(1);
+ item2->setRect(0, 0, 100, 100);
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QVERIFY(item1->isObscured());
+ QVERIFY(item1->isObscuredBy(item2));
+ QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(item1->isObscured(0, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 50, 50, 50));
+ QVERIFY(item1->isObscured(0, 50, 50, 50));
+ QVERIFY(!item2->isObscured());
+ QVERIFY(!item2->isObscuredBy(item1));
+ QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(0, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 50, 50, 50));
+ QVERIFY(!item2->isObscured(0, 50, 50, 50));
+
+ item2->moveBy(50, 0);
+
+ QVERIFY(!item1->isObscured());
+ QVERIFY(!item1->isObscuredBy(item2));
+ QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(!item1->isObscured(0, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 50, 50, 50));
+ QVERIFY(!item1->isObscured(0, 50, 50, 50));
+ QVERIFY(!item2->isObscured());
+ QVERIFY(!item2->isObscuredBy(item1));
+ QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(0, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 50, 50, 50));
+ QVERIFY(!item2->isObscured(0, 50, 50, 50));
+}
+
+void tst_QGraphicsItem::mapFromToParent()
+{
+ QPainterPath path1;
+ path1.addRect(0, 0, 200, 200);
+
+ QPainterPath path2;
+ path2.addRect(0, 0, 100, 100);
+
+ QPainterPath path3;
+ path3.addRect(0, 0, 50, 50);
+
+ QPainterPath path4;
+ path4.addRect(0, 0, 25, 25);
+
+ QGraphicsItem *item1 = new QGraphicsPathItem(path1);
+ QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1);
+ QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2);
+ QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3);
+
+ item1->setPos(10, 10);
+ item2->setPos(10, 10);
+ item3->setPos(10, 10);
+ item4->setPos(10, 10);
+
+ for (int i = 0; i < 4; ++i) {
+ QMatrix matrix;
+ matrix.rotate(i * 90);
+ matrix.translate(i * 100, -i * 100);
+ matrix.scale(2, 4);
+ item1->setMatrix(matrix);
+
+ QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
+ QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
+ QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
+ QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
+ QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
+ QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
+ QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
+ QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
+ QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
+ QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
+ QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
+ QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
+ QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
+ QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
+ QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
+ QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
+ QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
+ matrix.inverted().map(QPointF(10, -10)));
+ QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
+ QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
+ QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
+ QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
+ matrix.inverted().map(QPointF(-10, 10)));
+ QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
+ QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
+ QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
+ }
+
+ delete item1;
+}
+
+void tst_QGraphicsItem::mapFromToScene()
+{
+ QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath());
+ QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1);
+ QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2);
+ QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3);
+
+ item1->setPos(100, 100);
+ item2->setPos(100, 100);
+ item3->setPos(100, 100);
+ item4->setPos(100, 100);
+ QCOMPARE(item1->pos(), QPointF(100, 100));
+ QCOMPARE(item2->pos(), QPointF(100, 100));
+ QCOMPARE(item3->pos(), QPointF(100, 100));
+ QCOMPARE(item4->pos(), QPointF(100, 100));
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
+
+ // Rotate item1 90 degrees clockwise
+ QMatrix matrix; matrix.rotate(90);
+ item1->setMatrix(matrix);
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
+
+ // Rotate item2 90 degrees clockwise
+ item2->setMatrix(matrix);
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
+
+ // Translate item3 50 points, then rotate 90 degrees counterclockwise
+ QMatrix matrix2;
+ matrix2.translate(50, 0);
+ matrix2.rotate(-90);
+ item3->setMatrix(matrix2);
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90));
+ QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0));
+
+ delete item1;
+}
+
+void tst_QGraphicsItem::mapFromToItem()
+{
+ QGraphicsItem *item1 = new QGraphicsPathItem;
+ QGraphicsItem *item2 = new QGraphicsPathItem;
+ QGraphicsItem *item3 = new QGraphicsPathItem;
+ QGraphicsItem *item4 = new QGraphicsPathItem;
+
+ item1->setPos(-100, -100);
+ item2->setPos(100, -100);
+ item3->setPos(100, 100);
+ item4->setPos(-100, 100);
+
+ QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0));
+ QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200));
+ QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200));
+ QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
+ QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
+
+ QMatrix matrix;
+ matrix.translate(100, 100);
+ item1->setMatrix(matrix);
+
+ QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
+ QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100));
+ QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100));
+ QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100));
+ QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
+ QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
+
+ matrix.rotate(90);
+ item1->setMatrix(matrix);
+ item2->setMatrix(matrix);
+ item3->setMatrix(matrix);
+ item4->setMatrix(matrix);
+
+ QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
+ QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
+ QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200));
+ QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0));
+ QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200));
+ QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205));
+ QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5));
+ QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195));
+ QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5));
+ QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5));
+ QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195));
+ QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5));
+ QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205));
+
+ QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5));
+ QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5));
+ QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5));
+ QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5));
+ QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5));
+ QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5));
+ QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5));
+ QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5));
+
+ delete item1;
+ delete item2;
+ delete item3;
+ delete item4;
+}
+
+void tst_QGraphicsItem::mapRectFromToParent_data()
+{
+ QTest::addColumn<bool>("parent");
+ QTest::addColumn<QPointF>("parentPos");
+ QTest::addColumn<QTransform>("parentTransform");
+ QTest::addColumn<QPointF>("pos");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<QRectF>("inputRect");
+ QTest::addColumn<QRectF>("outputRect");
+
+ QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF();
+ QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("simple w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("simple w/parent parentPos") << true
+ << QPointF(50, 50) << QTransform()
+ << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("simple w/parent parentPos parentRotation") << true
+ << QPointF(50, 50) << QTransform().rotate(45)
+ << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("pos w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF(50, 50) << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10);
+ QTest::newRow("rotation w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF() << QTransform().rotate(90)
+ << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10);
+ QTest::newRow("pos rotation w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF(50, 50) << QTransform().rotate(90)
+ << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
+ QTest::newRow("pos rotation w/parent parentPos parentRotation") << true
+ << QPointF(-170, -190) << QTransform().rotate(90)
+ << QPointF(50, 50) << QTransform().rotate(90)
+ << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
+}
+
+void tst_QGraphicsItem::mapRectFromToParent()
+{
+ QFETCH(bool, parent);
+ QFETCH(QPointF, parentPos);
+ QFETCH(QTransform, parentTransform);
+ QFETCH(QPointF, pos);
+ QFETCH(QTransform, transform);
+ QFETCH(QRectF, inputRect);
+ QFETCH(QRectF, outputRect);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ rect->setPos(pos);
+ rect->setTransform(transform);
+
+ if (parent) {
+ QGraphicsRectItem *rectParent = new QGraphicsRectItem;
+ rect->setParentItem(rectParent);
+ rectParent->setPos(parentPos);
+ rectParent->setTransform(parentTransform);
+ }
+
+ // Make sure we use non-destructive transform operations (e.g., 90 degree
+ // rotations).
+ QCOMPARE(rect->mapRectToParent(inputRect), outputRect);
+ QCOMPARE(rect->mapRectFromParent(outputRect), inputRect);
+ QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect);
+ QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect);
+ QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect);
+ QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect);
+ QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect);
+ QPainterPath inputPath;
+ inputPath.addRect(inputRect);
+ QPainterPath outputPath;
+ outputPath.addRect(outputRect);
+ QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect());
+ QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect());
+}
+
+void tst_QGraphicsItem::isAncestorOf()
+{
+ QGraphicsItem *grandPa = new QGraphicsRectItem;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ QGraphicsItem *child = new QGraphicsRectItem;
+
+ QVERIFY(!parent->isAncestorOf(0));
+ QVERIFY(!child->isAncestorOf(0));
+ QVERIFY(!parent->isAncestorOf(child));
+ QVERIFY(!child->isAncestorOf(parent));
+ QVERIFY(!parent->isAncestorOf(parent));
+
+ child->setParentItem(parent);
+ parent->setParentItem(grandPa);
+
+ QVERIFY(parent->isAncestorOf(child));
+ QVERIFY(grandPa->isAncestorOf(parent));
+ QVERIFY(grandPa->isAncestorOf(child));
+ QVERIFY(!child->isAncestorOf(parent));
+ QVERIFY(!parent->isAncestorOf(grandPa));
+ QVERIFY(!child->isAncestorOf(grandPa));
+ QVERIFY(!child->isAncestorOf(child));
+ QVERIFY(!parent->isAncestorOf(parent));
+ QVERIFY(!grandPa->isAncestorOf(grandPa));
+
+ parent->setParentItem(0);
+
+ delete child;
+ delete parent;
+ delete grandPa;
+}
+
+void tst_QGraphicsItem::commonAncestorItem()
+{
+ QGraphicsItem *ancestor = new QGraphicsRectItem;
+ QGraphicsItem *grandMa = new QGraphicsRectItem;
+ QGraphicsItem *grandPa = new QGraphicsRectItem;
+ QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
+ QGraphicsItem *cousin = new QGraphicsRectItem;
+ QGraphicsItem *husband = new QGraphicsRectItem;
+ QGraphicsItem *child = new QGraphicsRectItem;
+ QGraphicsItem *wife = new QGraphicsRectItem;
+
+ child->setParentItem(husband);
+ husband->setParentItem(grandPa);
+ brotherInLaw->setParentItem(grandPa);
+ cousin->setParentItem(brotherInLaw);
+ wife->setParentItem(grandMa);
+ grandMa->setParentItem(ancestor);
+ grandPa->setParentItem(ancestor);
+
+ QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa);
+ QCOMPARE(grandMa->commonAncestorItem(0), (QGraphicsItem *)0);
+ QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor);
+ QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor);
+ QCOMPARE(grandPa->commonAncestorItem(husband), grandPa);
+ QCOMPARE(grandPa->commonAncestorItem(wife), ancestor);
+ QCOMPARE(grandMa->commonAncestorItem(husband), ancestor);
+ QCOMPARE(grandMa->commonAncestorItem(wife), grandMa);
+ QCOMPARE(wife->commonAncestorItem(grandMa), grandMa);
+ QCOMPARE(child->commonAncestorItem(cousin), grandPa);
+ QCOMPARE(cousin->commonAncestorItem(child), grandPa);
+ QCOMPARE(wife->commonAncestorItem(child), ancestor);
+ QCOMPARE(child->commonAncestorItem(wife), ancestor);
+}
+
+void tst_QGraphicsItem::data()
+{
+ QGraphicsTextItem text;
+
+ QCOMPARE(text.data(0), QVariant());
+ text.setData(0, "TextItem");
+ QCOMPARE(text.data(0), QVariant(QString("TextItem")));
+ text.setData(0, QVariant());
+ QCOMPARE(text.data(0), QVariant());
+}
+
+void tst_QGraphicsItem::type()
+{
+ QCOMPARE(int(QGraphicsItem::Type), 1);
+ QCOMPARE(int(QGraphicsPathItem::Type), 2);
+ QCOMPARE(int(QGraphicsRectItem::Type), 3);
+ QCOMPARE(int(QGraphicsEllipseItem::Type), 4);
+ QCOMPARE(int(QGraphicsPolygonItem::Type), 5);
+ QCOMPARE(int(QGraphicsLineItem::Type), 6);
+ QCOMPARE(int(QGraphicsPixmapItem::Type), 7);
+ QCOMPARE(int(QGraphicsTextItem::Type), 8);
+
+ QCOMPARE(QGraphicsPathItem().type(), 2);
+ QCOMPARE(QGraphicsRectItem().type(), 3);
+ QCOMPARE(QGraphicsEllipseItem().type(), 4);
+ QCOMPARE(QGraphicsPolygonItem().type(), 5);
+ QCOMPARE(QGraphicsLineItem().type(), 6);
+ QCOMPARE(QGraphicsPixmapItem().type(), 7);
+ QCOMPARE(QGraphicsTextItem().type(), 8);
+}
+
+void tst_QGraphicsItem::graphicsitem_cast()
+{
+ QGraphicsPathItem pathItem;
+ const QGraphicsPathItem *pPathItem = &pathItem;
+ QGraphicsRectItem rectItem;
+ const QGraphicsRectItem *pRectItem = &rectItem;
+ QGraphicsEllipseItem ellipseItem;
+ const QGraphicsEllipseItem *pEllipseItem = &ellipseItem;
+ QGraphicsPolygonItem polygonItem;
+ const QGraphicsPolygonItem *pPolygonItem = &polygonItem;
+ QGraphicsLineItem lineItem;
+ const QGraphicsLineItem *pLineItem = &lineItem;
+ QGraphicsPixmapItem pixmapItem;
+ const QGraphicsPixmapItem *pPixmapItem = &pixmapItem;
+ QGraphicsTextItem textItem;
+ const QGraphicsTextItem *pTextItem = &textItem;
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem));
+ //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem));
+ //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem));
+
+ // and some casts that _should_ fail:
+ QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem));
+ QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem));
+
+ // and this shouldn't crash
+ QGraphicsItem *ptr = 0;
+ QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr));
+ QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr));
+}
+
+void tst_QGraphicsItem::hoverEventsGenerateRepaints()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(150);
+
+ EventTester *tester = new EventTester;
+ scene.addItem(tester);
+ tester->setAcceptsHoverEvents(true);
+
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Send a hover enter event
+ QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
+ hoverEnterEvent.setScenePos(QPointF(0, 0));
+ hoverEnterEvent.setPos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &hoverEnterEvent);
+
+ // Check that we get a repaint
+ int npaints = tester->repaints;
+ qApp->processEvents();
+ qApp->processEvents();
+ QCOMPARE(tester->events.size(), 2); // enter + move
+ QCOMPARE(tester->repaints, npaints + 1);
+ QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
+
+ // Send a hover move event
+ QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove);
+ hoverMoveEvent.setScenePos(QPointF(0, 0));
+ hoverMoveEvent.setPos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &hoverMoveEvent);
+
+ // Check that we don't get a repaint
+ qApp->processEvents();
+ qApp->processEvents();
+
+ QCOMPARE(tester->events.size(), 3);
+ QCOMPARE(tester->repaints, npaints + 1);
+ QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
+
+ // Send a hover leave event
+ QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave);
+ hoverLeaveEvent.setScenePos(QPointF(-100, -100));
+ hoverLeaveEvent.setPos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &hoverLeaveEvent);
+
+ // Check that we get a repaint
+ qApp->processEvents();
+ qApp->processEvents();
+
+ QCOMPARE(tester->events.size(), 4);
+ QCOMPARE(tester->repaints, npaints + 2);
+ QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave);
+}
+
+void tst_QGraphicsItem::boundingRects_data()
+{
+ QTest::addColumn<QGraphicsItem *>("item");
+ QTest::addColumn<QRectF>("boundingRect");
+
+ QRectF rect(0, 0, 100, 100);
+ QPainterPath path;
+ path.addRect(rect);
+
+ QRectF adjustedRect(-0.5, -0.5, 101, 101);
+
+ QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect;
+ QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect;
+ QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect;
+ QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect;
+}
+
+void tst_QGraphicsItem::boundingRects()
+{
+ QFETCH(QGraphicsItem *, item);
+ QFETCH(QRectF, boundingRect);
+
+ ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1));
+ QCOMPARE(item->boundingRect(), boundingRect);
+}
+
+void tst_QGraphicsItem::boundingRects2()
+{
+ QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied)));
+ QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100));
+
+ QGraphicsLineItem line(0, 0, 100, 0);
+ line.setPen(QPen(Qt::black, 1));
+ QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1));
+}
+
+void tst_QGraphicsItem::sceneBoundingRect()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ item->setPos(100, 100);
+
+ QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100));
+
+ item->rotate(90);
+
+ QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ child->setParentItem(parent);
+ parent->setPos(100, 100);
+ child->setPos(100, 100);
+
+ QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(child->childrenBoundingRect(), QRectF());
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100));
+
+ QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ child2->setParentItem(parent);
+ child2->setPos(-100, -100);
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300));
+
+ QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ childChild->setParentItem(child);
+ childChild->setPos(500, 500);
+ child->rotate(90);
+
+ scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(30);
+
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
+}
+
+void tst_QGraphicsItem::childrenBoundingRectTransformed()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+
+ rect->rotate(45);
+ rect2->rotate(-45);
+ rect3->rotate(45);
+ rect4->rotate(-45);
+ rect5->rotate(45);
+
+ subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect2()
+{
+ QGraphicsItemGroup box;
+ QGraphicsLineItem l1(0, 0, 100, 0, &box);
+ QGraphicsLineItem l2(100, 0, 100, 100, &box);
+ QGraphicsLineItem l3(0, 0, 0, 100, &box);
+ // Make sure lines (zero with/height) are included in the childrenBoundingRect.
+ QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect3()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ // Try to mess up the cached bounding rect.
+ (void)rect2->childrenBoundingRect();
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect4()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+
+ // Try to mess up the cached bounding rect.
+ rect->childrenBoundingRect();
+ rect2->childrenBoundingRect();
+
+ rect3->setOpacity(0.0);
+ rect3->setParentItem(rect2);
+
+ QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect());
+ QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect());
+}
+
+void tst_QGraphicsItem::childrenBoundingRect5()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100));
+ child->setParentItem(parent);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+
+ // Try to mess up the cached bounding rect.
+ QRectF expectedChildrenBoundingRect = parent->boundingRect();
+ QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
+
+ // Apply some effects.
+ QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect;
+ dropShadow->setOffset(25, 25);
+ child->setGraphicsEffect(dropShadow);
+ parent->setGraphicsEffect(new QGraphicsOpacityEffect);
+
+ QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect);
+ expectedChildrenBoundingRect |= dropShadow->boundingRect();
+ QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
+}
+
+void tst_QGraphicsItem::group()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green));
+ QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue));
+ QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red));
+ parent2->setPos(-50, 50);
+ child->rotate(45);
+ child->setParentItem(parent);
+ parent->setPos(25, 25);
+ child->setPos(25, 25);
+
+ QCOMPARE(parent->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(parent2->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(child->group(), (QGraphicsItemGroup *)0);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QGraphicsItemGroup *group = new QGraphicsItemGroup;
+ group->setSelected(true);
+ scene.addItem(group);
+
+ QRectF parentSceneBoundingRect = parent->sceneBoundingRect();
+ group->addToGroup(parent);
+ QCOMPARE(parent->group(), group);
+ QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect);
+
+ QCOMPARE(parent->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(group->children().size(), 1);
+ QCOMPARE(scene.items().size(), 4);
+ QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
+
+ QTest::qWait(25);
+
+ QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
+ group->addToGroup(parent2);
+ QCOMPARE(parent2->group(), group);
+ QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect);
+
+ QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(group->children().size(), 2);
+ QCOMPARE(scene.items().size(), 4);
+ QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
+
+ QTest::qWait(25);
+
+ QList<QGraphicsItem *> newItems;
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0),
+ QBrush(QColor(rand() % 255, rand() % 255,
+ rand() % 255, rand() % 255)));
+ newItems << item;
+ item->setPos(-1000 + rand() % 2000,
+ -1000 + rand() % 2000);
+ item->rotate(rand() % 90);
+ }
+
+ view.fitInView(scene.itemsBoundingRect());
+
+ int n = 0;
+ foreach (QGraphicsItem *item, newItems) {
+ group->addToGroup(item);
+ QCOMPARE(item->group(), group);
+ if ((n++ % 100) == 0)
+ QTest::qWait(10);
+ }
+}
+
+void tst_QGraphicsItem::setGroup()
+{
+ QGraphicsItemGroup group1;
+ QGraphicsItemGroup group2;
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
+ rect->setGroup(&group1);
+ QCOMPARE(rect->group(), &group1);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1);
+ rect->setGroup(&group2);
+ QCOMPARE(rect->group(), &group2);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2);
+ rect->setGroup(0);
+ QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::setGroup2()
+{
+ QGraphicsScene scene;
+ QGraphicsItemGroup group;
+ scene.addItem(&group);
+
+ QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black);
+ rect->setTransformOriginPoint(50,50);
+ rect->setRotation(45);
+ rect->setScale(1.5);
+ rect->translate(20,20);
+ group.translate(-30,-40);
+ group.setRotation(180);
+ group.setScale(0.5);
+
+ QTransform oldSceneTransform = rect->sceneTransform();
+ rect->setGroup(&group);
+ QCOMPARE(rect->sceneTransform(), oldSceneTransform);
+
+ group.setRotation(20);
+ group.setScale(2);
+ rect->setRotation(90);
+ rect->setScale(0.8);
+
+ oldSceneTransform = rect->sceneTransform();
+ rect->setGroup(0);
+ QCOMPARE(rect->sceneTransform(), oldSceneTransform);
+}
+
+void tst_QGraphicsItem::nestedGroups()
+{
+ QGraphicsItemGroup *group1 = new QGraphicsItemGroup;
+ QGraphicsItemGroup *group2 = new QGraphicsItemGroup;
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setParentItem(rect);
+
+ group1->addToGroup(rect);
+ QCOMPARE(rect->group(), group1);
+ QCOMPARE(rect2->group(), group1);
+
+ group2->addToGroup(group1);
+ QCOMPARE(rect->group(), group1);
+ QCOMPARE(rect2->group(), group1);
+ QCOMPARE(group1->group(), group2);
+ QCOMPARE(group2->group(), (QGraphicsItemGroup *)0);
+
+ QGraphicsScene scene;
+ scene.addItem(group1);
+
+ QCOMPARE(rect->group(), group1);
+ QCOMPARE(rect2->group(), group1);
+ QCOMPARE(group1->group(), (QGraphicsItemGroup *)0);
+ QVERIFY(group2->children().isEmpty());
+
+ delete group2;
+}
+
+void tst_QGraphicsItem::warpChildrenIntoGroup()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100));
+ parentRectItem->rotate(90);
+ childRectItem->setPos(-50, -25);
+ childRectItem->setParentItem(parentRectItem);
+
+ QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
+ QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
+
+ QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100));
+ parentOfGroup->setPos(-200, -200);
+ parentOfGroup->scale(2, 2);
+
+ QGraphicsItemGroup *group = new QGraphicsItemGroup;
+ group->setPos(50, 50);
+ group->setParentItem(parentOfGroup);
+
+ QCOMPARE(group->scenePos(), QPointF(-100, -100));
+
+ group->addToGroup(childRectItem);
+
+ QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
+ QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
+}
+
+void tst_QGraphicsItem::removeFromGroup()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200));
+ rect1->setFlag(QGraphicsItem::ItemIsSelectable);
+ rect2->setFlag(QGraphicsItem::ItemIsSelectable);
+ rect1->setSelected(true);
+ rect2->setSelected(true);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ qApp->processEvents(); // index items
+ qApp->processEvents(); // emit changed
+
+ QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());
+ QVERIFY(group);
+ QCOMPARE(group->children().size(), 2);
+ qApp->processEvents(); // index items
+ qApp->processEvents(); // emit changed
+
+ scene.destroyItemGroup(group); // calls removeFromGroup.
+
+ qApp->processEvents(); // index items
+ qApp->processEvents(); // emit changed
+
+ QCOMPARE(scene.items().size(), 2);
+ QVERIFY(!rect1->group());
+ QVERIFY(!rect2->group());
+}
+
+class ChildEventTester : public QGraphicsRectItem
+{
+public:
+ ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), counter(0)
+ { }
+
+ int counter;
+
+protected:
+ void focusInEvent(QFocusEvent *event)
+ { ++counter; QGraphicsRectItem::focusInEvent(event); }
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ { ++counter; }
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *)
+ { ++counter; }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ { ++counter; }
+};
+
+void tst_QGraphicsItem::handlesChildEvents()
+{
+ ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
+ ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
+ ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
+
+ blue->setBrush(QBrush(Qt::blue));
+ red->setBrush(QBrush(Qt::red));
+ yellow->setBrush(QBrush(Qt::yellow));
+ green->setBrush(QBrush(Qt::green));
+ gray->setBrush(QBrush(Qt::gray));
+ red->setPos(50, 0);
+ yellow->setPos(50, 50);
+ green->setPos(25, 0);
+ gray->setPos(25, 25);
+ red->setParentItem(blue);
+ yellow->setParentItem(blue);
+ green->setParentItem(red);
+ gray->setParentItem(red);
+
+ QGraphicsScene scene;
+ scene.addItem(blue);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ // Pull out the items, closest item first
+ QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
+ QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
+ QCOMPARE(items.at(1), (QGraphicsItem *)gray);
+ QCOMPARE(items.at(2), (QGraphicsItem *)green);
+ QCOMPARE(items.at(3), (QGraphicsItem *)red);
+ QCOMPARE(items.at(4), (QGraphicsItem *)blue);
+
+ QCOMPARE(blue->counter, 0);
+
+ // Send events to the toplevel item
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(blue->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(blue->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 2);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(red->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(green->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
+
+ blue->setHandlesChildEvents(true);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(red->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 4);
+ QCOMPARE(red->counter, 2);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(green->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
+
+ blue->setHandlesChildEvents(false);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(red->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(green->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
+ QCOMPARE(green->counter, 4);
+}
+
+void tst_QGraphicsItem::handlesChildEvents2()
+{
+ ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10));
+ root->setHandlesChildEvents(true);
+ QVERIFY(root->handlesChildEvents());
+
+ ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
+ QVERIFY(!child->handlesChildEvents());
+
+ ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
+ ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
+ ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
+ child2->setParentItem(root);
+ QVERIFY(!child2->handlesChildEvents());
+ QVERIFY(!child3->handlesChildEvents());
+ QVERIFY(!child4->handlesChildEvents());
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
+ view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+
+ QTRY_COMPARE(root->counter, 1);
+}
+
+void tst_QGraphicsItem::handlesChildEvents3()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
+ ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
+ ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
+ scene.addItem(group2);
+
+ leaf->setFlag(QGraphicsItem::ItemIsFocusable);
+ group1->setFlag(QGraphicsItem::ItemIsFocusable);
+ group1->setHandlesChildEvents(true);
+ group2->setFlag(QGraphicsItem::ItemIsFocusable);
+ group2->setHandlesChildEvents(true);
+
+ leaf->setFocus();
+ QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus
+ QVERIFY(!group1->hasFocus());
+ QVERIFY(!group2->hasFocus());
+ QCOMPARE(leaf->counter, 0);
+ QCOMPARE(group1->counter, 0);
+ QCOMPARE(group2->counter, 1);
+
+ group1->setFocus();
+ QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus
+ QVERIFY(!leaf->hasFocus());
+ QVERIFY(!group2->hasFocus());
+ QCOMPARE(leaf->counter, 0);
+ QCOMPARE(group1->counter, 0);
+ QCOMPARE(group2->counter, 2);
+
+ group2->setFocus();
+ QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus
+ QVERIFY(!leaf->hasFocus());
+ QVERIFY(!group1->hasFocus());
+ QCOMPARE(leaf->counter, 0);
+ QCOMPARE(group1->counter, 0);
+ QCOMPARE(group2->counter, 3);
+}
+
+
+class ChildEventFilterTester : public ChildEventTester
+{
+public:
+ ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : ChildEventTester(rect, parent), filter(QEvent::None)
+ { }
+
+ QEvent::Type filter;
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
+ {
+ Q_UNUSED(item);
+ if (event->type() == filter) {
+ ++counter;
+ return true;
+ }
+ return false;
+ }
+};
+
+void tst_QGraphicsItem::filtersChildEvents()
+{
+ QGraphicsScene scene;
+ ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
+ ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
+ ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
+
+ // setup filter
+ filter->setFiltersChildEvents(true);
+ filter->filter = QEvent::GraphicsSceneMousePress;
+
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+
+ // send event to child
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
+ QCOMPARE(filter->counter, 1); // mouse press is filtered
+ QCOMPARE(root->counter, 0);
+
+ // add another filter
+ root->setFiltersChildEvents(true);
+ root->filter = QEvent::GraphicsSceneMouseRelease;
+
+ // send event to child
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(child->counter, 1);
+ QCOMPARE(filter->counter, 2); // mouse press is filtered
+ QCOMPARE(root->counter, 1); // mouse release is filtered
+
+ // reparent to another sub-graph
+ ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
+ child->setParentItem(parent);
+
+ // send event to child
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
+ QCOMPARE(parent->counter, 0);
+ QCOMPARE(filter->counter, 2);
+ QCOMPARE(root->counter, 2); // mouse release is filtered
+}
+
+void tst_QGraphicsItem::filtersChildEvents2()
+{
+ ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
+ root->setFiltersChildEvents(true);
+ root->filter = QEvent::GraphicsSceneMousePress;
+ QVERIFY(root->filtersChildEvents());
+
+ ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
+ QVERIFY(!child->filtersChildEvents());
+
+ ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
+ ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
+ ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
+
+ child2->setParentItem(root);
+ QVERIFY(!child2->filtersChildEvents());
+ QVERIFY(!child3->filtersChildEvents());
+ QVERIFY(!child4->filtersChildEvents());
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
+ view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+
+ QTRY_COMPARE(root->counter, 1);
+ QCOMPARE(child->counter, 0);
+ QCOMPARE(child2->counter, 0);
+ QCOMPARE(child3->counter, 0);
+ QCOMPARE(child4->counter, 0);
+}
+
+class CustomItem : public QGraphicsItem
+{
+public:
+ QRectF boundingRect() const
+ { return QRectF(-110, -110, 220, 220); }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ for (int x = -100; x <= 100; x += 25)
+ painter->drawLine(x, -100, x, 100);
+ for (int y = -100; y <= 100; y += 25)
+ painter->drawLine(-100, y, 100, y);
+
+ QFont font = painter->font();
+ font.setPointSize(4);
+ painter->setFont(font);
+ for (int x = -100; x < 100; x += 25) {
+ for (int y = -100; y < 100; y += 25) {
+ painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, QString("%1x%2").arg(x).arg(y));
+ }
+ }
+ }
+};
+
+void tst_QGraphicsItem::ensureVisible()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-200, -200, 400, 400);
+ QGraphicsItem *item = new CustomItem;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(300, 300);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ for (int i = 0; i < 25; ++i) {
+ view.scale(qreal(1.06), qreal(1.06));
+ QApplication::processEvents();
+ }
+
+ item->ensureVisible(-100, -100, 25, 25);
+ QTest::qWait(25);
+
+ for (int x = -100; x < 100; x += 25) {
+ for (int y = -100; y < 100; y += 25) {
+ int xmargin = rand() % 75;
+ int ymargin = rand() % 75;
+ item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
+ QApplication::processEvents();
+
+ QPolygonF viewScenePoly;
+ viewScenePoly << view.mapToScene(view.rect().topLeft())
+ << view.mapToScene(view.rect().topRight())
+ << view.mapToScene(view.rect().bottomRight())
+ << view.mapToScene(view.rect().bottomLeft());
+
+ QVERIFY(scene.items(viewScenePoly).contains(item));
+
+ QPainterPath path;
+ path.addPolygon(viewScenePoly);
+ QVERIFY(path.contains(item->mapToScene(x + 12, y + 12)));
+
+ QPolygonF viewScenePolyMinusMargins;
+ viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin))
+ << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin))
+ << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin))
+ << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin));
+
+ QPainterPath path2;
+ path2.addPolygon(viewScenePolyMinusMargins);
+ QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12)));
+ }
+ }
+
+ item->ensureVisible(100, 100, 25, 25);
+ QTest::qWait(25);
+}
+
+void tst_QGraphicsItem::cursor()
+{
+#ifndef QT_NO_CURSOR
+ QGraphicsScene scene;
+ QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
+ QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
+ item1->setPos(-100, 0);
+ item2->setPos(50, 0);
+
+ QVERIFY(!item1->hasCursor());
+ QVERIFY(!item2->hasCursor());
+
+ item1->setCursor(Qt::IBeamCursor);
+ item2->setCursor(Qt::PointingHandCursor);
+
+ QVERIFY(item1->hasCursor());
+ QVERIFY(item2->hasCursor());
+
+ item1->setCursor(QCursor());
+ item2->setCursor(QCursor());
+
+ QVERIFY(item1->hasCursor());
+ QVERIFY(item2->hasCursor());
+
+ item1->unsetCursor();
+ item2->unsetCursor();
+
+ QVERIFY(!item1->hasCursor());
+ QVERIFY(!item2->hasCursor());
+
+ item1->setCursor(Qt::IBeamCursor);
+ item2->setCursor(Qt::PointingHandCursor);
+
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ view.setFixedSize(200, 100);
+ topLevel.show();
+ QTest::mouseMove(&view, view.rect().center());
+
+ QTest::qWait(25);
+
+ QCursor cursor = view.viewport()->cursor();
+
+ {
+ QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(25);
+
+ QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
+
+ {
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center()));
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ if (!PlatformQuirks::haveMouseCursor())
+ return;
+#if !defined(Q_OS_WINCE)
+ QTest::qWait(250);
+#else
+ // Test environment does not have any cursor, therefore no shape
+ return;
+#endif
+
+ QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape());
+
+ {
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center()));
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(25);
+
+ QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
+
+ {
+ QTest::mouseMove(view.viewport(), view.rect().center());
+ QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(25);
+
+ QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
+#endif
+}
+/*
+void tst_QGraphicsItem::textControlGetterSetter()
+{
+ QGraphicsTextItem *item = new QGraphicsTextItem;
+ QVERIFY(item->textControl()->parent() == item);
+ QPointer<QTextControl> control = item->textControl();
+ delete item;
+ QVERIFY(!control);
+
+ item = new QGraphicsTextItem;
+
+ QPointer<QTextControl> oldControl = control;
+ control = new QTextControl;
+
+ item->setTextControl(control);
+ QVERIFY(item->textControl() == control);
+ QVERIFY(!control->parent());
+ QVERIFY(!oldControl);
+
+ // set some text to give it a size, to test that
+ // setTextControl (re)connects signals
+ const QRectF oldBoundingRect = item->boundingRect();
+ QVERIFY(oldBoundingRect.isValid());
+ item->setPlainText("Some text");
+ item->adjustSize();
+ QVERIFY(item->boundingRect().isValid());
+ QVERIFY(item->boundingRect() != oldBoundingRect);
+
+ // test that on setting a control the item size
+ // is adjusted
+ oldControl = control;
+ control = new QTextControl;
+ control->setPlainText("foo!");
+ item->setTextControl(control);
+ QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize());
+
+ QVERIFY(oldControl);
+ delete oldControl;
+
+ delete item;
+ QVERIFY(control);
+ delete control;
+}
+*/
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem()
+{
+ QGraphicsLineItem item;
+ QCOMPARE(item.line(), QLineF());
+ QCOMPARE(item.pen(), QPen());
+ QCOMPARE(item.shape(), QPainterPath());
+
+ item.setPen(QPen(Qt::black, 1));
+ QCOMPARE(item.pen(), QPen(Qt::black, 1));
+ item.setLine(QLineF(0, 0, 10, 0));
+ QCOMPARE(item.line(), QLineF(0, 0, 10, 0));
+ QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1));
+ QCOMPARE(item.shape().elementCount(), 11);
+
+ QPainterPath path;
+ path.moveTo(0, -0.5);
+ path.lineTo(10, -0.5);
+ path.lineTo(10.5, -0.5);
+ path.lineTo(10.5, 0.5);
+ path.lineTo(10, 0.5);
+ path.lineTo(0, 0.5);
+ path.lineTo(-0.5, 0.5);
+ path.lineTo(-0.5, -0.5);
+ path.lineTo(0, -0.5);
+ path.lineTo(0, 0);
+ path.lineTo(10, 0);
+ path.closeSubpath();
+
+ for (int i = 0; i < 11; ++i)
+ QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i)));
+}
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem()
+{
+ QGraphicsPixmapItem item;
+ QVERIFY(item.pixmap().isNull());
+ QCOMPARE(item.offset(), QPointF());
+ QCOMPARE(item.transformationMode(), Qt::FastTransformation);
+
+ QPixmap pixmap(300, 200);
+ pixmap.fill(Qt::red);
+ item.setPixmap(pixmap);
+ QCOMPARE(item.pixmap(), pixmap);
+
+ item.setTransformationMode(Qt::FastTransformation);
+ QCOMPARE(item.transformationMode(), Qt::FastTransformation);
+ item.setTransformationMode(Qt::SmoothTransformation);
+ QCOMPARE(item.transformationMode(), Qt::SmoothTransformation);
+
+ item.setOffset(-15, -15);
+ QCOMPARE(item.offset(), QPointF(-15, -15));
+ item.setOffset(QPointF(-10, -10));
+ QCOMPARE(item.offset(), QPointF(-10, -10));
+
+ QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200));
+}
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem()
+{
+ QGraphicsTextItem *text = new QGraphicsTextItem;
+ QVERIFY(!text->openExternalLinks());
+ QVERIFY(text->textCursor().isNull());
+ QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text));
+ QVERIFY(text->document() != 0);
+ QCOMPARE(text->font(), QApplication::font());
+ QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction));
+ QCOMPARE(text->textWidth(), -1.0);
+ QCOMPARE(text->toPlainText(), QString(""));
+
+ QGraphicsScene scene;
+ scene.addItem(text);
+ text->setPlainText("Hello world");
+ text->setFlag(QGraphicsItem::ItemIsMovable);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(1, 1));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(11, 11));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ }
+
+ QCOMPARE(text->pos(), QPointF(10, 10));
+
+ text->setTextInteractionFlags(Qt::NoTextInteraction);
+ QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod));
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
+ QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod);
+
+ {
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(21, 21));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ }
+
+ QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved
+}
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
+{
+ QGraphicsEllipseItem item;
+ QVERIFY(item.rect().isNull());
+ QVERIFY(item.boundingRect().isNull());
+ QVERIFY(item.shape().isEmpty());
+ QCOMPARE(item.spanAngle(), 360 * 16);
+ QCOMPARE(item.startAngle(), 0);
+
+ item.setRect(0, 0, 100, 100);
+ QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100));
+
+ item.setSpanAngle(90 * 16);
+ qFuzzyCompare(item.boundingRect().left(), qreal(50.0));
+ qFuzzyCompare(item.boundingRect().top(), qreal(0.0));
+ qFuzzyCompare(item.boundingRect().width(), qreal(50.0));
+ qFuzzyCompare(item.boundingRect().height(), qreal(50.0));
+
+ item.setPen(QPen(Qt::black, 1));
+ QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51));
+
+ item.setSpanAngle(180 * 16);
+ QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51));
+
+ item.setSpanAngle(360 * 16);
+ QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
+}
+
+class ItemChangeTester : public QGraphicsRectItem
+{
+public:
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ itemChangeReturnValue = QVariant();
+ itemSceneChangeTargetScene = 0;
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+
+ QVariant itemChangeReturnValue;
+ QGraphicsScene *itemSceneChangeTargetScene;
+
+ QList<GraphicsItemChange> changes;
+ QList<QVariant> values;
+ QList<QVariant> oldValues;
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ changes << change;
+ values << value;
+ switch (change) {
+ case QGraphicsItem::ItemPositionChange:
+ oldValues << pos();
+ break;
+ case QGraphicsItem::ItemPositionHasChanged:
+ break;
+ case QGraphicsItem::ItemMatrixChange: {
+ QVariant variant;
+ qVariantSetValue<QMatrix>(variant, matrix());
+ oldValues << variant;
+ }
+ break;
+ case QGraphicsItem::ItemTransformChange: {
+ QVariant variant;
+ qVariantSetValue<QTransform>(variant, transform());
+ oldValues << variant;
+ }
+ break;
+ case QGraphicsItem::ItemTransformHasChanged:
+ break;
+ case QGraphicsItem::ItemVisibleChange:
+ oldValues << isVisible();
+ break;
+ case QGraphicsItem::ItemVisibleHasChanged:
+ break;
+ case QGraphicsItem::ItemEnabledChange:
+ oldValues << isEnabled();
+ break;
+ case QGraphicsItem::ItemEnabledHasChanged:
+ break;
+ case QGraphicsItem::ItemSelectedChange:
+ oldValues << isSelected();
+ break;
+ case QGraphicsItem::ItemSelectedHasChanged:
+ break;
+ case QGraphicsItem::ItemParentChange:
+ oldValues << qVariantFromValue<void *>(parentItem());
+ break;
+ case QGraphicsItem::ItemParentHasChanged:
+ break;
+ case QGraphicsItem::ItemChildAddedChange:
+ oldValues << children().size();
+ break;
+ case QGraphicsItem::ItemChildRemovedChange:
+ oldValues << children().size();
+ break;
+ case QGraphicsItem::ItemSceneChange:
+ oldValues << qVariantFromValue<QGraphicsScene *>(scene());
+ if (itemSceneChangeTargetScene
+ && qVariantValue<QGraphicsScene *>(value)
+ && itemSceneChangeTargetScene != qVariantValue<QGraphicsScene *>(value)) {
+ return qVariantFromValue<QGraphicsScene *>(itemSceneChangeTargetScene);
+ }
+ return value;
+ case QGraphicsItem::ItemSceneHasChanged:
+ break;
+ case QGraphicsItem::ItemCursorChange:
+#ifndef QT_NO_CURSOR
+ oldValues << cursor();
+#endif
+ break;
+ case QGraphicsItem::ItemCursorHasChanged:
+ break;
+ case QGraphicsItem::ItemToolTipChange:
+ oldValues << toolTip();
+ break;
+ case QGraphicsItem::ItemToolTipHasChanged:
+ break;
+ case QGraphicsItem::ItemFlagsChange:
+ oldValues << quint32(flags());
+ break;
+ case QGraphicsItem::ItemFlagsHaveChanged:
+ break;
+ case QGraphicsItem::ItemZValueChange:
+ oldValues << zValue();
+ break;
+ case QGraphicsItem::ItemZValueHasChanged:
+ break;
+ case QGraphicsItem::ItemOpacityChange:
+ oldValues << opacity();
+ break;
+ case QGraphicsItem::ItemOpacityHasChanged:
+ break;
+ case QGraphicsItem::ItemScenePositionHasChanged:
+ break;
+ case QGraphicsItem::ItemRotationChange:
+ oldValues << rotation();
+ break;
+ case QGraphicsItem::ItemRotationHasChanged:
+ break;
+ case QGraphicsItem::ItemScaleChange:
+ oldValues << scale();
+ break;
+ case QGraphicsItem::ItemScaleHasChanged:
+ break;
+ case QGraphicsItem::ItemTransformOriginPointChange:
+ oldValues << transformOriginPoint();
+ break;
+ case QGraphicsItem::ItemTransformOriginPointHasChanged:
+ break;
+ }
+ return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value;
+ }
+};
+
+void tst_QGraphicsItem::itemChange()
+{
+ ItemChangeTester tester;
+ tester.itemSceneChangeTargetScene = 0;
+
+ ItemChangeTester testerHelper;
+ QVERIFY(tester.changes.isEmpty());
+ QVERIFY(tester.values.isEmpty());
+
+ int changeCount = 0;
+ {
+ // ItemEnabledChange
+ tester.itemChangeReturnValue = true;
+ tester.setEnabled(false);
+ ++changeCount;
+ ++changeCount; // HasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
+ QCOMPARE(tester.oldValues.last(), QVariant(true));
+ QCOMPARE(tester.isEnabled(), true);
+ }
+ {
+ // ItemMatrixChange / ItemTransformHasChanged
+ qVariantSetValue<QMatrix>(tester.itemChangeReturnValue, QMatrix().rotate(90));
+ tester.setMatrix(QMatrix().translate(50, 0), true);
+ ++changeCount; // notification sent too
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange));
+ QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged));
+ QCOMPARE(qVariantValue<QMatrix>(tester.values.at(tester.values.size() - 2)),
+ QMatrix().translate(50, 0));
+ QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90))));
+ QVariant variant;
+ qVariantSetValue<QMatrix>(variant, QMatrix());
+ QCOMPARE(tester.oldValues.last(), variant);
+ QCOMPARE(tester.matrix(), QMatrix().rotate(90));
+ }
+ {
+ tester.resetTransform();
+ ++changeCount;
+ ++changeCount; // notification sent too
+
+ // ItemTransformChange / ItemTransformHasChanged
+ qVariantSetValue<QTransform>(tester.itemChangeReturnValue, QTransform().rotate(90));
+ tester.translate(50, 0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged);
+ QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 2)),
+ QTransform().translate(50, 0));
+ QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 1)),
+ QTransform().rotate(90));
+ QVariant variant;
+ qVariantSetValue<QTransform>(variant, QTransform());
+ QCOMPARE(tester.oldValues.last(), variant);
+ QCOMPARE(tester.transform(), QTransform().rotate(90));
+ }
+ {
+ // ItemPositionChange / ItemPositionHasChanged
+ tester.itemChangeReturnValue = QPointF(42, 0);
+ tester.setPos(0, 42);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(QPointF()));
+ QCOMPARE(tester.pos(), QPointF(42, 0));
+ }
+ {
+ // ItemZValueChange / ItemZValueHasChanged
+ tester.itemChangeReturnValue = qreal(2.0);
+ tester.setZValue(1.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
+ QCOMPARE(tester.zValue(), qreal(2.0));
+ }
+ {
+ // ItemRotationChange / ItemRotationHasChanged
+ tester.itemChangeReturnValue = qreal(15.0);
+ tester.setRotation(10.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
+ QCOMPARE(tester.rotation(), qreal(15.0));
+ }
+ {
+ // ItemScaleChange / ItemScaleHasChanged
+ tester.itemChangeReturnValue = qreal(2.0);
+ tester.setScale(1.5);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0)));
+ QCOMPARE(tester.scale(), qreal(2.0));
+ }
+ {
+ // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged
+ tester.itemChangeReturnValue = QPointF(2.0, 2.0);
+ tester.setTransformOriginPoint(1.0, 1.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0)));
+ QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.0));
+ }
+ {
+ // ItemFlagsChange
+ tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
+ tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QCOMPARE(tester.changes.size(), changeCount); // No change
+ tester.setFlag(QGraphicsItem::ItemIsSelectable, true);
+ ++changeCount;
+ ++changeCount; // ItemFlagsHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
+ QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
+ QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
+ QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>((quint32)QGraphicsItem::ItemIsSelectable));
+ }
+ {
+ // ItemSelectedChange
+ tester.setSelected(false);
+ QCOMPARE(tester.changes.size(), changeCount); // No change :-)
+ tester.itemChangeReturnValue = true;
+ tester.setSelected(true);
+ ++changeCount;
+ ++changeCount; // ItemSelectedHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
+ QCOMPARE(tester.oldValues.last(), QVariant(false));
+ QCOMPARE(tester.isSelected(), true);
+
+ tester.itemChangeReturnValue = false;
+ tester.setSelected(true);
+
+ // the value hasn't changed to the itemChange return value
+ // bacause itemChange is never called (true -> true is a noop).
+ QCOMPARE(tester.isSelected(), true);
+ }
+ {
+ // ItemVisibleChange
+ tester.itemChangeReturnValue = false;
+ QVERIFY(tester.isVisible());
+ tester.setVisible(false);
+ ++changeCount; // ItemVisibleChange
+ ++changeCount; // ItemSelectedChange
+ ++changeCount; // ItemSelectedHasChanged
+ ++changeCount; // ItemVisibleHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false));
+ QCOMPARE(tester.isVisible(), false);
+ }
+ {
+ // ItemParentChange
+ qVariantSetValue<QGraphicsItem *>(tester.itemChangeReturnValue, 0);
+ tester.setParentItem(&testerHelper);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.oldValues.last()), (QGraphicsItem *)0);
+ QCOMPARE(tester.parentItem(), (QGraphicsItem *)0);
+ }
+ {
+ // ItemOpacityChange
+ tester.itemChangeReturnValue = 1.0;
+ tester.setOpacity(0.7);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange);
+ QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7)));
+ QCOMPARE(tester.oldValues.last().toDouble(), double(1.0));
+ QCOMPARE(tester.opacity(), qreal(1.0));
+ tester.itemChangeReturnValue = 0.7;
+ tester.setOpacity(0.7);
+ ++changeCount; // ItemOpacityChange
+ ++changeCount; // ItemOpacityHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged);
+ QCOMPARE(tester.opacity(), qreal(0.7));
+ }
+ {
+ // ItemChildAddedChange
+ tester.itemChangeReturnValue.clear();
+ testerHelper.setParentItem(&tester);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+ }
+ {
+ // ItemChildRemovedChange 1
+ testerHelper.setParentItem(0);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+
+ // ItemChildRemovedChange 1
+ ItemChangeTester *test = new ItemChangeTester;
+ test->itemSceneChangeTargetScene = 0;
+ int count = 0;
+ QGraphicsScene *scene = new QGraphicsScene;
+ scene->addItem(test);
+ count = test->changes.size();
+ //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
+ QGraphicsRectItem *child = new QGraphicsRectItem(test);
+ //We received ItemChildAddedChange
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
+ delete child;
+ child = 0;
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
+
+ ItemChangeTester *childTester = new ItemChangeTester(test);
+ //Changes contains all sceneHasChanged and so on, we don't want to test that
+ int childCount = childTester->changes.size();
+ //We received ItemChildAddedChange
+ QCOMPARE(test->changes.size(), ++count);
+ child = new QGraphicsRectItem(childTester);
+ //We received ItemChildAddedChange
+ QCOMPARE(childTester->changes.size(), ++childCount);
+ QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
+ //Delete the child of the top level with all its children
+ delete childTester;
+ //Only one removal
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ delete scene;
+ }
+ {
+ // ItemChildRemovedChange 2
+ ItemChangeTester parent;
+ ItemChangeTester *child = new ItemChangeTester;
+ child->setParentItem(&parent);
+ QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
+ delete child;
+ QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
+ }
+ {
+ // !!! Note: If this test crashes because of double-deletion, there's
+ // a bug somewhere in QGraphicsScene or QGraphicsItem.
+
+ // ItemSceneChange
+ QGraphicsScene scene;
+ QGraphicsScene scene2;
+ scene.addItem(&tester);
+ ++changeCount; // ItemSceneChange (scene)
+ ++changeCount; // ItemSceneHasChanged (scene)
+ QCOMPARE(tester.changes.size(), changeCount);
+
+ QCOMPARE(tester.scene(), &scene);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
+ // Item's old value was 0
+ // Item's current value is scene
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene);
+ scene2.addItem(&tester);
+ ++changeCount; // ItemSceneChange (0) was: (scene)
+ ++changeCount; // ItemSceneHasChanged (0)
+ ++changeCount; // ItemSceneChange (scene2) was: (0)
+ ++changeCount; // ItemSceneHasChanged (scene2)
+ QCOMPARE(tester.changes.size(), changeCount);
+
+ QCOMPARE(tester.scene(), &scene2);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
+ // Item's last old value was scene
+ // Item's last current value is 0
+
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2);
+ // Item's last old value was 0
+ // Item's last current value is scene2
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2);
+
+ scene2.removeItem(&tester);
+ ++changeCount; // ItemSceneChange (0) was: (scene2)
+ ++changeCount; // ItemSceneHasChanged (0)
+ QCOMPARE(tester.changes.size(), changeCount);
+
+ QCOMPARE(tester.scene(), (QGraphicsScene *)0);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
+ // Item's last old value was scene2
+ // Item's last current value is 0
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)0);
+
+ tester.itemSceneChangeTargetScene = &scene;
+ scene2.addItem(&tester);
+ ++changeCount; // ItemSceneChange (scene2) was: (0)
+ ++changeCount; // ItemSceneChange (scene) was: (0)
+ ++changeCount; // ItemSceneHasChanged (scene)
+ QCOMPARE(tester.values.size(), changeCount);
+
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene);
+
+ QCOMPARE(tester.scene(), &scene);
+ tester.itemSceneChangeTargetScene = 0;
+ tester.itemChangeReturnValue = QVariant();
+ scene.removeItem(&tester);
+ ++changeCount; // ItemSceneChange
+ ++changeCount; // ItemSceneHasChanged
+ QCOMPARE(tester.scene(), (QGraphicsScene *)0);
+ }
+ {
+ // ItemToolTipChange/ItemToolTipHasChanged
+ const QString toolTip(QLatin1String("I'm soo cool"));
+ const QString overridenToolTip(QLatin1String("No, you are not soo cool"));
+ tester.itemChangeReturnValue = overridenToolTip;
+ tester.setToolTip(toolTip);
+ ++changeCount; // ItemToolTipChange
+ ++changeCount; // ItemToolTipHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange);
+ QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip);
+ QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged);
+ QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip);
+ QCOMPARE(tester.toolTip(), overridenToolTip);
+ tester.itemChangeReturnValue = QVariant();
+ }
+}
+
+class EventFilterTesterItem : public QGraphicsLineItem
+{
+public:
+ QList<QEvent::Type> filteredEvents;
+ QList<QGraphicsItem *> filteredEventReceivers;
+ bool handlesSceneEvents;
+
+ QList<QEvent::Type> receivedEvents;
+
+ EventFilterTesterItem() : handlesSceneEvents(false) {}
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ filteredEvents << event->type();
+ filteredEventReceivers << watched;
+ return handlesSceneEvents;
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ return QGraphicsLineItem::sceneEvent(event);
+ }
+};
+
+void tst_QGraphicsItem::sceneEventFilter()
+{
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+
+ QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
+ QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
+ QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3"));
+ text1->setFlag(QGraphicsItem::ItemIsFocusable);
+ text2->setFlag(QGraphicsItem::ItemIsFocusable);
+ text3->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ EventFilterTesterItem *tester = new EventFilterTesterItem;
+ scene.addItem(tester);
+
+ QTRY_VERIFY(!text1->hasFocus());
+ text1->installSceneEventFilter(tester);
+ text1->setFocus();
+ QTRY_VERIFY(text1->hasFocus());
+
+ QCOMPARE(tester->filteredEvents.size(), 1);
+ QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1));
+
+ text2->installSceneEventFilter(tester);
+ text3->installSceneEventFilter(tester);
+
+ text2->setFocus();
+ text3->setFocus();
+
+ QCOMPARE(tester->filteredEvents.size(), 5);
+ QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut);
+ QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1));
+ QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2));
+ QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut);
+ QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2));
+ QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3));
+
+ text1->removeSceneEventFilter(tester);
+ text1->setFocus();
+
+ QCOMPARE(tester->filteredEvents.size(), 6);
+ QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut);
+ QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3));
+
+ tester->handlesSceneEvents = true;
+ text2->setFocus();
+
+ QCOMPARE(tester->filteredEvents.size(), 7);
+ QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2));
+
+ QVERIFY(text2->hasFocus());
+
+ //Let check if the items are correctly removed from the sceneEventFilters array
+ //to avoid stale pointers.
+ QGraphicsView gv;
+ QGraphicsScene *anotherScene = new QGraphicsScene;
+ QGraphicsTextItem *ti = anotherScene->addText("This is a test #1");
+ ti->moveBy(50, 50);
+ QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2");
+ QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
+ gv.setScene(anotherScene);
+ gv.show();
+ QTest::qWaitForWindowShown(&gv);
+ QTest::qWait(25);
+ ti->installSceneEventFilter(ti2);
+ ti3->installSceneEventFilter(ti);
+ delete ti2;
+ //we souldn't crash
+ QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
+ QTest::qWait(30);
+ delete ti;
+}
+
+class GeometryChanger : public QGraphicsItem
+{
+public:
+ void changeGeometry()
+ { prepareGeometryChange(); }
+};
+
+void tst_QGraphicsItem::prepareGeometryChange()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
+ ((GeometryChanger *)item)->changeGeometry();
+ QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
+ }
+}
+
+
+class PaintTester : public QGraphicsRectItem
+{
+public:
+ PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));}
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w)
+ {
+ widget = w;
+ painted++;
+ }
+
+ QWidget* widget;
+ int painted;
+};
+
+void tst_QGraphicsItem::paint()
+{
+ QGraphicsScene scene;
+
+ PaintTester paintTester;
+ scene.addItem(&paintTester);
+
+ QGraphicsView view(&scene);
+
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+#ifdef Q_OS_WIN32
+ //we try to switch the desktop: if it fails, we skip the test
+ if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
+ QSKIP("The Graphics View doesn't get the paint events", SkipSingle);
+ }
+#endif
+
+ QTRY_COMPARE(paintTester.widget, view.viewport());
+
+ view.hide();
+
+ QGraphicsScene scene2;
+ QGraphicsView view2(&scene2);
+ view2.show();
+ QTest::qWaitForWindowShown(&view2);
+ QTest::qWait(25);
+
+ PaintTester tester2;
+ scene2.addItem(&tester2);
+ qApp->processEvents();
+
+ //First show one paint
+ QTRY_COMPARE(tester2.painted, 1);
+
+ //nominal case, update call paint
+ tester2.update();
+ qApp->processEvents();
+ QTRY_VERIFY(tester2.painted == 2);
+
+ //we remove the item from the scene, number of updates is still the same
+ tester2.update();
+ scene2.removeItem(&tester2);
+ qApp->processEvents();
+ QTRY_VERIFY(tester2.painted == 2);
+
+ //We re-add the item, the number of paint should increase
+ scene2.addItem(&tester2);
+ tester2.update();
+ qApp->processEvents();
+ QTRY_VERIFY(tester2.painted == 3);
+}
+
+class HarakiriItem : public QGraphicsRectItem
+{
+public:
+ HarakiriItem(int harakiriPoint)
+ : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint)
+ { dead = 0; }
+
+ static int dead;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ if (harakiri == 0) {
+ // delete unsupported since 4.5
+ /*
+ dead = 1;
+ delete this;
+ */
+ }
+ }
+
+ void advance(int n)
+ {
+ if (harakiri == 1 && n == 0) {
+ // delete unsupported
+ /*
+ dead = 1;
+ delete this;
+ */
+ }
+ if (harakiri == 2 && n == 1) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+protected:
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
+ {
+ if (harakiri == 3) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dragEnterEvent(event);
+ }
+
+ void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dragLeaveEvent(event);
+ }
+
+ void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dragMoveEvent(event);
+ }
+
+ void dropEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dropEvent(event);
+ }
+
+ void focusInEvent(QFocusEvent *)
+ {
+ if (harakiri == 4) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void focusOutEvent(QFocusEvent *)
+ {
+ if (harakiri == 5) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *)
+ {
+ if (harakiri == 6) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
+ {
+ if (harakiri == 7) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *)
+ {
+ if (harakiri == 8) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void inputMethodEvent(QInputMethodEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::inputMethodEvent(event);
+ }
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery query) const
+ {
+ // ??
+ return QGraphicsRectItem::inputMethodQuery(query);
+ }
+
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ // deletion not supported
+ return QGraphicsRectItem::itemChange(change, value);
+ }
+
+ void keyPressEvent(QKeyEvent *)
+ {
+ if (harakiri == 9) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void keyReleaseEvent(QKeyEvent *)
+ {
+ if (harakiri == 10) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 11) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 12) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 13) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 14) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ // deletion not supported
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ // deletion not supported
+ return QGraphicsRectItem::sceneEventFilter(watched, event);
+ }
+
+ void wheelEvent(QGraphicsSceneWheelEvent *)
+ {
+ if (harakiri == 16) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+private:
+ int harakiri;
+};
+
+int HarakiriItem::dead;
+
+void tst_QGraphicsItem::deleteItemInEventHandlers()
+{
+ for (int i = 0; i < 17; ++i) {
+ QGraphicsScene scene;
+ HarakiriItem *item = new HarakiriItem(i);
+ item->setAcceptsHoverEvents(true);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ scene.addItem(item);
+
+ item->installSceneEventFilter(item); // <- ehey!
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ qApp->processEvents();
+ qApp->processEvents();
+
+ if (!item->dead)
+ scene.advance();
+
+ if (!item->dead) {
+ QContextMenuEvent event(QContextMenuEvent::Other,
+ view.mapFromScene(item->scenePos()));
+ QCoreApplication::sendEvent(view.viewport(), &event);
+ }
+ if (!item->dead)
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20)));
+ if (!item->dead)
+ item->setFocus();
+ if (!item->dead)
+ item->clearFocus();
+ if (!item->dead)
+ item->setFocus();
+ if (!item->dead)
+ QTest::keyPress(view.viewport(), Qt::Key_A);
+ if (!item->dead)
+ QTest::keyRelease(view.viewport(), Qt::Key_A);
+ if (!item->dead)
+ QTest::keyPress(view.viewport(), Qt::Key_A);
+ if (!item->dead)
+ QTest::keyRelease(view.viewport(), Qt::Key_A);
+ }
+}
+
+class ItemPaintsOutsideShape : public QGraphicsItem
+{
+public:
+ QRectF boundingRect() const
+ {
+ return QRectF(0, 0, 100, 100);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->fillRect(-50, -50, 200, 200, Qt::red);
+ painter->fillRect(0, 0, 100, 100, Qt::blue);
+ }
+};
+
+void tst_QGraphicsItem::itemClipsToShape()
+{
+ QGraphicsItem *clippedItem = new ItemPaintsOutsideShape;
+ clippedItem->setFlag(QGraphicsItem::ItemClipsToShape);
+
+ QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape;
+ unclippedItem->setPos(200, 0);
+
+ QGraphicsScene scene(-50, -50, 400, 200);
+ scene.addItem(clippedItem);
+ scene.addItem(unclippedItem);
+
+ QImage image(400, 200, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(45, 100), QRgb(0));
+ QCOMPARE(image.pixel(100, 45), QRgb(0));
+ QCOMPARE(image.pixel(155, 100), QRgb(0));
+ QCOMPARE(image.pixel(45, 155), QRgb(0));
+ QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba());
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
+
+ QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
+ ellipse->setParentItem(rect);
+
+ QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
+ clippedEllipse->setParentItem(ellipse);
+
+ QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
+ clippedEllipse2->setParentItem(clippedEllipse);
+
+ QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
+ clippedEllipse3->setParentItem(clippedEllipse);
+
+ QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
+ ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
+
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba());
+ QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba());
+ QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba());
+ QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba());
+ QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba());
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape2()
+{
+ QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10));
+ QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100));
+ QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80));
+
+ child1->setParentItem(parent);
+ child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ child2->setParentItem(child1);
+
+ parent->setBrush(Qt::blue);
+ child1->setBrush(Qt::green);
+ child2->setBrush(Qt::red);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ QCOMPARE(scene.itemAt(5, 5), (QGraphicsItem *)parent);
+ QCOMPARE(scene.itemAt(15, 5), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(5, 15), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(60, 60), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(140, 60), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(60, 140), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(140, 140), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(75, 75), (QGraphicsItem *)child2);
+ QCOMPARE(scene.itemAt(75, 100), (QGraphicsItem *)child1);
+ QCOMPARE(scene.itemAt(100, 75), (QGraphicsItem *)child1);
+
+#if 1
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
+ QCOMPARE(image.pixel(5, 10), QRgb(0));
+ QCOMPARE(image.pixel(10, 5), QRgb(0));
+ QCOMPARE(image.pixel(40, 40), QRgb(0));
+ QCOMPARE(image.pixel(90, 40), QRgb(0));
+ QCOMPARE(image.pixel(40, 90), QRgb(0));
+ QCOMPARE(image.pixel(95, 95), QRgb(0));
+ QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba());
+ QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba());
+ QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba());
+ QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba());
+#else
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(5000);
+#endif
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape3()
+{
+ // Construct a scene with nested children, each 50 pixels offset from the elder.
+ // Set a top-level clipping flag
+ QGraphicsScene scene;
+ QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 );
+ QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 );
+ QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 );
+ child->setParentItem(parent);
+ grandchild->setParentItem(child);
+ child->setPos( 50, 50 );
+ grandchild->setPos( 50, 50 );
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)parent);
+ QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)child);
+ QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
+ QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
+
+ // Move child to fully overlap the parent. The grandchild should
+ // now occupy two-thirds of the scene
+ child->prepareGeometryChange();
+ child->setPos( 0, 0 );
+
+ QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)child);
+ QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)grandchild);
+ QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
+ QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
+}
+
+class MyProxyWidget : public QGraphicsProxyWidget
+{
+public:
+ MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent)
+ {
+ painted = false;
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ painted = true;
+ }
+ bool painted;
+};
+
+void tst_QGraphicsItem::itemClipsChildrenToShape4()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget * outerWidget = new QGraphicsWidget();
+ outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+ MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget);
+ QLabel * label = new QLabel();
+ label->setText("Welcome back my friends to the show that never ends...");
+ innerWidget->setWidget(label);
+ view.resize(300, 300);
+ scene.addItem(outerWidget);
+ outerWidget->resize( 200, 100 );
+ scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath*
+ //now the label is shown
+ outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false );
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+ QTRY_COMPARE(innerWidget->painted, true);
+}
+
+//#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
+static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename)
+{
+ image->fill(0);
+ QPainter painter(image);
+ scene->render(&painter);
+ painter.end();
+#ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
+ image->save(filename);
+#else
+ Q_UNUSED(filename);
+#endif
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape5()
+{
+ class ParentItem : public QGraphicsRectItem
+ {
+ public:
+ ParentItem(qreal x, qreal y, qreal width, qreal height)
+ : QGraphicsRectItem(x, y, width, height) {}
+
+ QPainterPath shape() const
+ {
+ QPainterPath path;
+ path.addRect(50, 50, 200, 200);
+ return path;
+ }
+ };
+
+ ParentItem *parent = new ParentItem(0, 0, 300, 300);
+ parent->setBrush(Qt::blue);
+ parent->setOpacity(0.5);
+
+ const QRegion parentRegion(0, 0, 300, 300);
+ const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200);
+ QRegion childRegion;
+ QRegion grandChildRegion;
+
+ QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
+ topLeftChild->setBrush(Qt::red);
+ topLeftChild->setParentItem(parent);
+ childRegion += QRect(0, 0, 100, 100);
+
+ QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100);
+ topRightChild->setBrush(Qt::red);
+ topRightChild->setParentItem(parent);
+ topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ topRightChild->setPos(200, 0);
+ childRegion += QRect(200, 0, 100, 100);
+
+ QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100);
+ topRightGrandChild->setBrush(Qt::green);
+ topRightGrandChild->setParentItem(topRightChild);
+ topRightGrandChild->setPos(-40, 40);
+ grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100);
+
+ QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
+ bottomLeftChild->setBrush(Qt::red);
+ bottomLeftChild->setParentItem(parent);
+ bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape);
+ bottomLeftChild->setPos(0, 200);
+ childRegion += QRect(0, 200, 100, 100);
+
+ QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160);
+ bottomLeftGrandChild->setBrush(Qt::green);
+ bottomLeftGrandChild->setParentItem(bottomLeftChild);
+ bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape);
+ bottomLeftGrandChild->setPos(0, -60);
+ grandChildRegion += QRect(0, 200 - 60, 160, 160);
+
+ QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100);
+ bottomRightChild->setBrush(Qt::red);
+ bottomRightChild->setParentItem(parent);
+ bottomRightChild->setPos(200, 200);
+ childRegion += QRect(200, 200, 100, 100);
+
+ QPoint controlPoints[17] = {
+ QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) ,
+ QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) ,
+ QPoint(150, 150),
+ QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205),
+ QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295),
+ };
+
+ const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200);
+ const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+ QImage sceneImage(300, 300, QImage::Format_ARGB32);
+
+#define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \
+ for (int i = 0; i < 17; ++i) { \
+ QPoint controlPoint = controlPoints[i]; \
+ QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \
+ if (pRegion.contains(controlPoint)) \
+ QVERIFY(qBlue(pixel) != 0); \
+ else \
+ QVERIFY(qBlue(pixel) == 0); \
+ if (cRegion.contains(controlPoint)) \
+ QVERIFY(qRed(pixel) != 0); \
+ else \
+ QVERIFY(qRed(pixel) == 0); \
+ if (gRegion.contains(controlPoint)) \
+ QVERIFY(qGreen(pixel) != 0); \
+ else \
+ QVERIFY(qGreen(pixel) == 0); \
+ }
+
+ const QList<QGraphicsItem *> children = parent->childItems();
+ const int childrenCount = children.count();
+
+ for (int i = 0; i < 5; ++i) {
+ QString clipString;
+ QString childString;
+ switch (i) {
+ case 0:
+ // All children stacked in front.
+ childString = QLatin1String("ChildrenInFront.png");
+ foreach (QGraphicsItem *child, children)
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
+ break;
+ case 1:
+ // All children stacked behind.
+ childString = QLatin1String("ChildrenBehind.png");
+ foreach (QGraphicsItem *child, children)
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
+ break;
+ case 2:
+ // First half of the children behind, second half in front.
+ childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png");
+ for (int j = 0; j < childrenCount; ++j) {
+ QGraphicsItem *child = children.at(j);
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2));
+ }
+ break;
+ case 3:
+ // First half of the children in front, second half behind.
+ childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png");
+ for (int j = 0; j < childrenCount; ++j) {
+ QGraphicsItem *child = children.at(j);
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2));
+ }
+ break;
+ case 4:
+ // Child2 and child4 behind, rest in front.
+ childString = QLatin1String("Child2And4Behind_RestInFront.png");
+ for (int j = 0; j < childrenCount; ++j) {
+ QGraphicsItem *child = children.at(j);
+ if (j == 1 || j == 3)
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
+ else
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
+ }
+ break;
+ default:
+ qFatal("internal error");
+ }
+
+ // Nothing is clipped.
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ parent->setFlag(QGraphicsItem::ItemClipsToShape, false);
+ clipString = QLatin1String("nothingClipped_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion);
+
+ // Parent clips children to shape.
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ clipString = QLatin1String("parentClipsChildrenToShape_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion);
+
+ // Parent clips itself and children to shape.
+ parent->setFlag(QGraphicsItem::ItemClipsToShape);
+ clipString = QLatin1String("parentClipsItselfAndChildrenToShape_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion);
+
+ // Parent clips itself to shape.
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ clipString = QLatin1String("parentClipsItselfToShape_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion);
+ }
+}
+
+void tst_QGraphicsItem::itemClipsTextChildToShape()
+{
+ // Construct a scene with a rect that clips its children, with one text
+ // child that has text that exceeds the size of the rect.
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black);
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels.");
+ text->setParentItem(rect);
+
+ // Render this scene to a transparent image.
+ QRectF sr = scene.itemsBoundingRect();
+ QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ scene.render(&painter);
+
+ // Erase the area immediately underneath the rect.
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5),
+ Qt::transparent);
+ painter.end();
+
+ // Check that you get a truly transparent image back (i.e., the text was
+ // clipped away, so there should be no trails left after erasing only the
+ // rect's area).
+ QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
+ emptyImage.fill(0);
+ QCOMPARE(image, emptyImage);
+}
+
+void tst_QGraphicsItem::itemClippingDiscovery()
+{
+ // A simple scene with an ellipse parent and two rect children, one a
+ // child of the other.
+ QGraphicsScene scene;
+ QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100);
+ QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100);
+ QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100);
+ leftRectItem->setParentItem(clipItem);
+ rightRectItem->setParentItem(clipItem);
+
+ // The rects item are both visible at these points.
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)leftRectItem);
+ QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)rightRectItem);
+
+ // The ellipse clips the rects now.
+ clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ // The rect items are no longer visible at these points.
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ if (sizeof(qreal) != sizeof(double))
+ QSKIP("This fails due to internal rounding errors", SkipSingle);
+ QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::ancestorFlags()
+{
+ QGraphicsItem *level1 = new QGraphicsRectItem;
+ QGraphicsItem *level21 = new QGraphicsRectItem;
+ level21->setParentItem(level1);
+ QGraphicsItem *level22 = new QGraphicsRectItem;
+ level22->setParentItem(level1);
+ QGraphicsItem *level31 = new QGraphicsRectItem;
+ level31->setParentItem(level21);
+ QGraphicsItem *level32 = new QGraphicsRectItem;
+ level32->setParentItem(level21);
+
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 1) Root level sets a flag
+ level1->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 2) Root level set it again
+ level1->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 3) Root level unsets a flag
+ level1->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 4) Child item sets a flag
+ level21->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 5) Parent item sets a flag
+ level1->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 6) Child item unsets a flag
+ level21->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 7) Parent item unsets a flag
+ level21->setHandlesChildEvents(true);
+ level1->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparent the child to root
+ level21->setParentItem(0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparent the child to level1 again.
+ level1->setHandlesChildEvents(true);
+ level21->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparenting level31 back to level1.
+ level31->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparenting level31 back to level21.
+ level31->setParentItem(0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ level31->setParentItem(level21);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Level1 doesn't handle child events
+ level1->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Nobody handles child events
+ level21->setHandlesChildEvents(false);
+
+ for (int i = 0; i < 2; ++i) {
+ QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
+ : QGraphicsItem::ItemIgnoresTransformations;
+ int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
+ : QGraphicsItemPrivate::AncestorIgnoresTransformations;
+
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 1) Root level sets a flag
+ level1->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 2) Root level set it again
+ level1->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 3) Root level unsets a flag
+ level1->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 4) Child item sets a flag
+ level21->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 5) Parent item sets a flag
+ level1->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 6) Child item unsets a flag
+ level21->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 7) Parent item unsets a flag
+ level21->setFlag(flag, true);
+ level1->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparent the child to root
+ level21->setParentItem(0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparent the child to level1 again.
+ level1->setFlag(flag, true);
+ level21->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparenting level31 back to level1.
+ level31->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparenting level31 back to level21.
+ level31->setParentItem(0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ level31->setParentItem(level21);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Level1 doesn't handle child events
+ level1->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Nobody handles child events
+ level21->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+ }
+
+ delete level1;
+}
+
+void tst_QGraphicsItem::untransformable()
+{
+ QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
+ item1->setZValue(1);
+ item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item1->rotate(45);
+ ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red);
+
+ QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
+ item2->setParentItem(item1);
+ item2->rotate(45);
+ item2->setPos(100, 0);
+ ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green);
+
+ QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
+ item3->setParentItem(item2);
+ item3->setPos(100, 0);
+ ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue);
+
+ QGraphicsScene scene(-500, -500, 1000, 1000);
+ scene.addItem(item1);
+
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ view.resize(300, 300);
+ topLevel.show();
+ view.scale(8, 8);
+ view.centerOn(0, 0);
+
+// Painting with the DiagCrossPattern is really slow on Mac
+// when zoomed out. (The test times out). Task to fix is 155567.
+#if !defined(Q_WS_MAC) || 1
+ view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
+#endif
+
+ QTest::qWaitForWindowShown(&view);
+
+ for (int i = 0; i < 10; ++i) {
+ QPoint center = view.viewport()->rect().center();
+ QCOMPARE(view.itemAt(center), item1);
+ QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1);
+ QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1);
+ QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1);
+ QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1);
+
+ center += QPoint(70, 70);
+ QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2);
+ QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2);
+ QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2);
+ QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2);
+
+ center += QPoint(0, 100);
+ QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3);
+ QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3);
+ QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3);
+ QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3);
+
+ view.scale(0.5, 0.5);
+ view.rotate(13);
+ view.shear(qreal(0.01), qreal(0.01));
+ view.translate(10, 10);
+ QTest::qWait(25);
+ }
+}
+
+class ContextMenuItem : public QGraphicsRectItem
+{
+public:
+ ContextMenuItem()
+ : ignoreEvent(true), gotEvent(false), eventWasAccepted(false)
+ { }
+ bool ignoreEvent;
+ bool gotEvent;
+ bool eventWasAccepted;
+protected:
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+ {
+ gotEvent = true;
+ eventWasAccepted = event->isAccepted();
+ if (ignoreEvent)
+ event->ignore();
+ }
+};
+
+void tst_QGraphicsItem::contextMenuEventPropagation()
+{
+ ContextMenuItem *bottomItem = new ContextMenuItem;
+ bottomItem->setRect(0, 0, 100, 100);
+ ContextMenuItem *topItem = new ContextMenuItem;
+ topItem->setParentItem(bottomItem);
+ topItem->setRect(0, 0, 100, 100);
+
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ view.show();
+ view.resize(200, 200);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
+ view.viewport()->mapToGlobal(QPoint(10, 10)));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+
+ scene.addItem(bottomItem);
+ topItem->ignoreEvent = true;
+ bottomItem->ignoreEvent = true;
+
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+ QCOMPARE(topItem->gotEvent, true);
+ QCOMPARE(topItem->eventWasAccepted, true);
+ QCOMPARE(bottomItem->gotEvent, true);
+ QCOMPARE(bottomItem->eventWasAccepted, true);
+
+ topItem->ignoreEvent = false;
+ topItem->gotEvent = false;
+ bottomItem->gotEvent = false;
+
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ QCOMPARE(topItem->gotEvent, true);
+ QCOMPARE(bottomItem->gotEvent, false);
+ QCOMPARE(topItem->eventWasAccepted, true);
+}
+
+void tst_QGraphicsItem::itemIsMovable()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100);
+ rect->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QGraphicsScene scene;
+ scene.addItem(rect);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(0, 0));
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButtons(Qt::LeftButton);
+ event.setScenePos(QPointF(10, 10));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(10, 10));
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButtons(Qt::RightButton);
+ event.setScenePos(QPointF(20, 20));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(10, 10));
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButtons(Qt::LeftButton);
+ event.setScenePos(QPointF(30, 30));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(30, 30));
+}
+
+class ItemAddScene : public QGraphicsScene
+{
+ Q_OBJECT
+public:
+ ItemAddScene()
+ {
+ QTimer::singleShot(500, this, SLOT(newTextItem()));
+ }
+
+public slots:
+ void newTextItem()
+ {
+ // Add a text item
+ QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0, this);
+ item->setPos(.0, .0);
+ item->show();
+ }
+};
+
+void tst_QGraphicsItem::task141694_textItemEnsureVisible()
+{
+ ItemAddScene scene;
+ scene.setSceneRect(-1000, -1000, 2000, 2000);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ view.ensureVisible(-1000, -1000, 5, 5);
+ int hscroll = view.horizontalScrollBar()->value();
+ int vscroll = view.verticalScrollBar()->value();
+
+ QTest::qWait(10);
+
+ // This should not cause the view to scroll
+ QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll);
+ QCOMPARE(view.verticalScrollBar()->value(), vscroll);
+}
+
+void tst_QGraphicsItem::task128696_textItemEnsureMovable()
+{
+ QGraphicsTextItem *item = new QGraphicsTextItem;
+ item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ item->setPlainText("abc de\nf ghi\n j k l");
+
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+
+ QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress);
+ event1.setScenePos(QPointF(0, 0));
+ event1.setButton(Qt::LeftButton);
+ event1.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(10, 10));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ QCOMPARE(item->pos(), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::task177918_lineItemUndetected()
+{
+ QGraphicsScene scene;
+ QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10);
+ QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0));
+
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemBoundingRect).isEmpty());
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemBoundingRect).isEmpty());
+}
+
+void tst_QGraphicsItem::task240400_clickOnTextItem_data()
+{
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<int>("textFlags");
+ QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction);
+ QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction);
+ QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction);
+ QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
+ << int(Qt::TextEditorInteraction);
+ QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction);
+ QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction);
+ QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction);
+ QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
+ << int(Qt::NoTextInteraction);
+}
+
+void tst_QGraphicsItem::task240400_clickOnTextItem()
+{
+ QFETCH(int, flags);
+ QFETCH(int, textFlags);
+
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsTextItem *item = scene.addText("Hello");
+ item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
+ item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
+ bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable);
+ QVERIFY(textFlags ? focusable : !focusable);
+
+ int column = item->textCursor().columnNumber();
+ QCOMPARE(column, 0);
+
+ QVERIFY(!item->hasFocus());
+
+ // Click in the top-left corner of the item
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (flags || textFlags)
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ else
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (textFlags)
+ QVERIFY(item->hasFocus());
+ else
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!scene.mouseGrabberItem());
+ bool selectable = (flags & QGraphicsItem::ItemIsSelectable);
+ QVERIFY(selectable ? item->isSelected() : !item->isSelected());
+
+ // Now click in the middle and check that the cursor moved.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(item->sceneBoundingRect().center());
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (flags || textFlags)
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ else
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(item->sceneBoundingRect().center());
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (textFlags)
+ QVERIFY(item->hasFocus());
+ else
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!scene.mouseGrabberItem());
+
+ QVERIFY(selectable ? item->isSelected() : !item->isSelected());
+
+ //
+ if (textFlags & Qt::TextEditorInteraction)
+ QVERIFY(item->textCursor().columnNumber() > column);
+ else
+ QCOMPARE(item->textCursor().columnNumber(), 0);
+}
+
+class TextItem : public QGraphicsSimpleTextItem
+{
+public:
+ TextItem(const QString& text) : QGraphicsSimpleTextItem(text)
+ {
+ updates = 0;
+ }
+
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
+ {
+ updates++;
+ QGraphicsSimpleTextItem::paint(painter, option, widget);
+ }
+
+ int updates;
+};
+
+void tst_QGraphicsItem::ensureUpdateOnTextItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+ TextItem *text1 = new TextItem(QLatin1String("123"));
+ scene.addItem(text1);
+ qApp->processEvents();
+ QTRY_COMPARE(text1->updates,1);
+
+ //same bouding rect but we have to update
+ text1->setText(QLatin1String("321"));
+ qApp->processEvents();
+ QTRY_COMPARE(text1->updates,2);
+}
+
+void tst_QGraphicsItem::task243707_addChildBeforeParent()
+{
+ // Task reports that adding the child before the parent leads to an
+ // inconsistent internal state that can cause a crash. This test shows
+ // one such crash.
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
+ scene.addItem(widget2);
+ QVERIFY(!widget2->parentItem());
+ scene.addItem(widget);
+ QVERIFY(!widget->commonAncestorItem(widget2));
+ QVERIFY(!widget2->commonAncestorItem(widget));
+}
+
+void tst_QGraphicsItem::task197802_childrenVisibility()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem item(QRectF(0,0,20,20));
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item);
+ scene.addItem(&item);
+
+ //freshly created: both visible
+ QVERIFY(item.isVisible());
+ QVERIFY(item2->isVisible());
+
+ //hide child: parent visible, child not
+ item2->hide();
+ QVERIFY(item.isVisible());
+ QVERIFY(!item2->isVisible());
+
+ //hide parent: parent and child invisible
+ item.hide();
+ QVERIFY(!item.isVisible());
+ QVERIFY(!item2->isVisible());
+
+ //ask to show the child: parent and child invisible anyways
+ item2->show();
+ QVERIFY(!item.isVisible());
+ QVERIFY(!item2->isVisible());
+
+ //show the parent: both parent and child visible
+ item.show();
+ QVERIFY(item.isVisible());
+ QVERIFY(item2->isVisible());
+
+ delete item2;
+}
+
+void tst_QGraphicsItem::boundingRegion_data()
+{
+ QTest::addColumn<QLineF>("line");
+ QTest::addColumn<qreal>("granularity");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<QRegion>("expectedRegion");
+
+ QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform()
+ << QRegion(QRect(0, 0, 10, 10));
+#if 0
+ {
+ QRegion r;
+ r += QRect(0, 0, 6, 2);
+ r += QRect(0, 2, 8, 2);
+ r += QRect(0, 4, 10, 2);
+ r += QRect(2, 6, 8, 2);
+ r += QRect(4, 8, 6, 2);
+ QTest::newRow("(0, 0, 10, 10) | 0.5 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.5) << QTransform() << r;
+ }
+ {
+ QRegion r;
+ r += QRect(0, 0, 4, 1); r += QRect(0, 1, 5, 1); r += QRect(0, 2, 6, 1);
+ r += QRect(0, 3, 7, 1); r += QRect(1, 4, 7, 1); r += QRect(2, 5, 7, 1);
+ r += QRect(3, 6, 7, 1); r += QRect(4, 7, 6, 1); r += QRect(5, 8, 5, 1);
+ r += QRect(6, 9, 4, 1);
+ QTest::newRow("(0, 0, 10, 10) | 1.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(1.0) << QTransform() << r;
+ }
+#endif
+ QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform()
+ << QRegion(QRect(0, 0, 10, 1));
+ QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform()
+ << QRegion(QRect(0, 0, 10, 1));
+ QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform()
+ << QRegion(QRect(0, 0, 10, 1));
+ QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform()
+ << QRegion(QRect(0, 0, 1, 10));
+ QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform()
+ << QRegion(QRect(0, 0, 1, 10));
+ QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform()
+ << QRegion(QRect(0, 0, 1, 10));
+}
+
+void tst_QGraphicsItem::boundingRegion()
+{
+ QFETCH(QLineF, line);
+ QFETCH(qreal, granularity);
+ QFETCH(QTransform, transform);
+ QFETCH(QRegion, expectedRegion);
+
+ QGraphicsLineItem item(line);
+ QCOMPARE(item.boundingRegionGranularity(), qreal(0.0));
+ item.setBoundingRegionGranularity(granularity);
+ QCOMPARE(item.boundingRegionGranularity(), granularity);
+ QCOMPARE(item.boundingRegion(transform), expectedRegion);
+}
+
+void tst_QGraphicsItem::itemTransform_parentChild()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
+ child->setParentItem(parent);
+ child->setPos(10, 10);
+ child->scale(2, 2);
+ child->rotate(90);
+
+ QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30));
+ QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::itemTransform_siblings()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *brother = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *sister = scene.addRect(0, 0, 100, 100);
+ parent->scale(10, 5);
+ parent->rotate(-180);
+ parent->shear(2, 3);
+
+ brother->setParentItem(parent);
+ sister->setParentItem(parent);
+
+ brother->setPos(10, 10);
+ brother->scale(2, 2);
+ brother->rotate(90);
+ sister->setPos(10, 10);
+ sister->scale(2, 2);
+ sister->rotate(90);
+
+ QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::itemTransform_unrelated()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100);
+ stranger1->setPos(10, 10);
+ stranger1->scale(2, 2);
+ stranger1->rotate(90);
+ stranger2->setPos(10, 10);
+ stranger2->scale(2, 2);
+ stranger2->rotate(90);
+
+ QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::opacity_data()
+{
+ QTest::addColumn<qreal>("p_opacity");
+ QTest::addColumn<int>("p_opacityFlags");
+ QTest::addColumn<qreal>("c1_opacity");
+ QTest::addColumn<int>("c1_opacityFlags");
+ QTest::addColumn<qreal>("c2_opacity");
+ QTest::addColumn<int>("c2_opacityFlags");
+ QTest::addColumn<qreal>("p_effectiveOpacity");
+ QTest::addColumn<qreal>("c1_effectiveOpacity");
+ QTest::addColumn<qreal>("c2_effectiveOpacity");
+ QTest::addColumn<qreal>("c3_effectiveOpacity");
+
+ // Modify the opacity and see how it propagates
+ QTest::newRow("A: 1.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("B: 0.5 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
+ QTest::newRow("C: 0.5 0 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.1) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05);
+ QTest::newRow("D: 0.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
+
+ // Parent doesn't propagate to children - now modify the opacity and see how it propagates
+ int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
+ QTest::newRow("E: 1.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("F: 0.5 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("G: 0.5 2 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(0.1) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1);
+ QTest::newRow("H: 0.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+
+ // Child ignores parent - now modify the opacity and see how it propagates
+ flags = QGraphicsItem::ItemIgnoresParentOpacity;
+ QTest::newRow("I: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << flags << qreal(1.0) << 0
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("J: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.5) << flags << qreal(0.5) << 0
+ << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25);
+ QTest::newRow("K: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.2) << 0 << qreal(0.2) << flags << qreal(0.2) << 0
+ << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04);
+ QTest::newRow("L: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(0.0) << flags << qreal(0.0) << 0
+ << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
+
+ // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates
+ flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
+ QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
+ << qreal(1.0) << flags // c1 (no prop)
+ << qreal(1.0) << 0 // c2
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
+ << qreal(1.0) << flags // c1 (no prop)
+ << qreal(1.0) << 0 // c2
+ << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
+ << qreal(0.5) << flags // c1 (no prop)
+ << qreal(1.0) << 0 // c2
+ << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
+ << qreal(0.5) << flags // c1 (no prop)
+ << qreal(0.5) << 0 // c2
+ << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
+ QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
+ << qreal(0.5) << flags // c1 (no prop)
+ << qreal(0.5) << 0 // c2
+ << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5);
+}
+
+void tst_QGraphicsItem::opacity()
+{
+ QFETCH(qreal, p_opacity);
+ QFETCH(int, p_opacityFlags);
+ QFETCH(qreal, p_effectiveOpacity);
+ QFETCH(qreal, c1_opacity);
+ QFETCH(int, c1_opacityFlags);
+ QFETCH(qreal, c1_effectiveOpacity);
+ QFETCH(qreal, c2_opacity);
+ QFETCH(int, c2_opacityFlags);
+ QFETCH(qreal, c2_effectiveOpacity);
+ QFETCH(qreal, c3_effectiveOpacity);
+
+ QGraphicsRectItem *p = new QGraphicsRectItem;
+ QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
+ QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
+ QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
+
+ QCOMPARE(p->opacity(), qreal(1.0));
+ QCOMPARE(p->effectiveOpacity(), qreal(1.0));
+ int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
+ QVERIFY(!(p->flags() & opacityMask));
+
+ p->setOpacity(p_opacity);
+ c1->setOpacity(c1_opacity);
+ c2->setOpacity(c2_opacity);
+ p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags));
+ c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags));
+ c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags));
+
+ QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags);
+ QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags);
+ QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags);
+ QCOMPARE(p->opacity(), p_opacity);
+ QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity);
+ QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity);
+ QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity);
+ QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity);
+}
+
+void tst_QGraphicsItem::opacity2()
+{
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ MyGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints >= 1);
+
+#define RESET_REPAINT_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.repaints = 0;
+
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(0.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 0);
+
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(1.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+
+ RESET_REPAINT_COUNTERS
+
+ parent->setOpacity(0.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 0);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 0);
+
+ RESET_REPAINT_COUNTERS
+
+ parent->setOpacity(1.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+
+ grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(0.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 1);
+
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(0.0); // Already 0.0; no change.
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 0);
+ QCOMPARE(parent->repaints, 0);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 0);
+}
+
+void tst_QGraphicsItem::opacityZeroUpdates()
+{
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+
+ child->setPos(10, 10);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ MyGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ view.reset();
+ parent->setOpacity(0.0);
+
+ QTest::qWait(20);
+
+ // transforming items bounding rect to view coordinates
+ const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
+ .mapRect(child->boundingRect()).toRect();
+ const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toRect();
+
+ QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+
+ COMPARE_REGIONS(view.paintedRegion, expectedRegion);
+}
+
+class StacksBehindParentHelper : public QGraphicsRectItem
+{
+public:
+ StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ paintedItems->append(this);
+ }
+
+private:
+ QList<QGraphicsItem *> *paintedItems;
+};
+
+void tst_QGraphicsItem::itemStacksBehindParent()
+{
+ StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
+ StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
+
+ StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
+ StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
+
+ parent1->setData(0, "parent1");
+ child11->setData(0, "child11");
+ grandChild111->setData(0, "grandChild111");
+ child12->setData(0, "child12");
+ grandChild121->setData(0, "grandChild121");
+ parent2->setData(0, "parent2");
+ child21->setData(0, "child21");
+ grandChild211->setData(0, "grandChild211");
+ child22->setData(0, "child22");
+ grandChild221->setData(0, "grandChild221");
+
+ // Disambiguate siblings
+ parent1->setZValue(1);
+ child11->setZValue(1);
+ child21->setZValue(1);
+
+ QGraphicsScene scene;
+ scene.addItem(parent1);
+ scene.addItem(parent2);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!paintedItems.isEmpty());
+ QTest::qWait(100);
+ paintedItems.clear();
+ view.viewport()->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << grandChild111 << child11
+ << grandChild121 << child12 << parent1
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+ QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << parent1 << child12 << grandChild121
+ << child11 << grandChild111);
+
+ child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ scene.update();
+ paintedItems.clear();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << grandChild121 << child12 << parent1
+ << grandChild111 << child11
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child11 << grandChild111
+ << parent1 << child12 << grandChild121);
+
+ child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ paintedItems.clear();
+ scene.update();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << parent1 << grandChild111 << child11
+ << grandChild121 << child12
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child12 << grandChild121
+ << child11 << grandChild111 << parent1);
+}
+
+class ClippingAndTransformsScene : public QGraphicsScene
+{
+public:
+ QList<QGraphicsItem *> drawnItems;
+protected:
+ void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
+ const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
+ {
+ drawnItems.clear();
+ for (int i = 0; i < numItems; ++i)
+ drawnItems << items[i];
+ QGraphicsScene::drawItems(painter, numItems, items, options, widget);
+ }
+};
+
+void tst_QGraphicsItem::nestedClipping()
+{
+ ClippingAndTransformsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ root->setBrush(QColor(0, 0, 255));
+ root->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ l1->setParentItem(root);
+ l1->setPos(-50, 0);
+ l1->setBrush(QColor(255, 0, 0));
+ l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
+ l2->setParentItem(l1);
+ l2->setPos(50, 50);
+ l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ l2->setBrush(QColor(255, 255, 0));
+ QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25));
+ l3->setParentItem(l2);
+ l3->setBrush(QColor(0, 255, 0));
+ l3->setPos(50 - 12, -12);
+
+ scene.addItem(root);
+
+ root->setData(0, "root");
+ l1->setData(0, "l1");
+ l2->setData(0, "l2");
+ l3->setData(0, "l3");
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+
+ QList<QGraphicsItem *> expected;
+ expected << root << l1 << l2 << l3;
+ QTRY_COMPARE(scene.drawnItems, expected);
+
+ QImage image(200, 200, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+
+ // Check transparent areas
+ QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255));
+ QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
+ QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
+ QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
+#if 0
+ // Enable this to compare if the test starts failing.
+ image.save("nestedClipping_reference.png");
+#endif
+}
+
+class TransformDebugItem : public QGraphicsRectItem
+{
+public:
+ TransformDebugItem()
+ : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
+ {
+ setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ }
+
+ QTransform x;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget = 0)
+ {
+ x = painter->worldTransform();
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+};
+
+void tst_QGraphicsItem::nestedClippingTransforms()
+{
+ TransformDebugItem *rootClipper = new TransformDebugItem;
+ rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ TransformDebugItem *child = new TransformDebugItem;
+ child->setParentItem(rootClipper);
+ child->setPos(2, 2);
+ TransformDebugItem *grandChildClipper = new TransformDebugItem;
+ grandChildClipper->setParentItem(child);
+ grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ grandChildClipper->setPos(4, 4);
+ TransformDebugItem *greatGrandChild = new TransformDebugItem;
+ greatGrandChild->setPos(2, 2);
+ greatGrandChild->setParentItem(grandChildClipper);
+ TransformDebugItem *grandChildClipper2 = new TransformDebugItem;
+ grandChildClipper2->setParentItem(child);
+ grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ grandChildClipper2->setPos(8, 8);
+ TransformDebugItem *greatGrandChild2 = new TransformDebugItem;
+ greatGrandChild2->setPos(2, 2);
+ greatGrandChild2->setParentItem(grandChildClipper2);
+ TransformDebugItem *grandChildClipper3 = new TransformDebugItem;
+ grandChildClipper3->setParentItem(child);
+ grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ grandChildClipper3->setPos(12, 12);
+ TransformDebugItem *greatGrandChild3 = new TransformDebugItem;
+ greatGrandChild3->setPos(2, 2);
+ greatGrandChild3->setParentItem(grandChildClipper3);
+
+ QGraphicsScene scene;
+ scene.addItem(rootClipper);
+
+ QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter p(&image);
+ scene.render(&p);
+ p.end();
+
+ QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1));
+ QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1));
+ QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1));
+ QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1));
+ QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1));
+ QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1));
+ QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1));
+ QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1));
+}
+
+void tst_QGraphicsItem::sceneTransformCache()
+{
+ // Test that an item's scene transform is updated correctly when the
+ // parent is transformed.
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
+ rect2->setParentItem(rect);
+ rect2->rotate(90);
+ rect->translate(0, 50);
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ rect->translate(0, 100);
+ QTransform x;
+ x.translate(0, 150);
+ x.rotate(90);
+ QCOMPARE(rect2->sceneTransform(), x);
+
+ scene.removeItem(rect);
+
+ //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
+ //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
+ //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive
+ //with a child (rect6) that will be cached then it will take the freeSlot (ex rect4) and put it his transform. But if rect4 is
+ //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new
+ //value of rect6 so rect6 transform will be wrong.
+ QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100);
+ rect3->setPos(QPointF(10,10));
+
+ rect4->setParentItem(rect3);
+ rect4->setPos(QPointF(10,10));
+
+ QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20));
+
+ scene.removeItem(rect4);
+ //rect4 transform is local only
+ QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
+
+ QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100);
+ rect5->setPos(QPointF(20,20));
+
+ rect6->setParentItem(rect5);
+ rect6->setPos(QPointF(10,10));
+ //test if rect6 transform is ok
+ QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
+
+ scene.addItem(rect4);
+
+ QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
+ //test if rect6 transform is still correct
+ QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
+}
+
+void tst_QGraphicsItem::tabChangesFocus_data()
+{
+ QTest::addColumn<bool>("tabChangesFocus");
+ QTest::newRow("tab changes focus") << true;
+ QTest::newRow("tab doesn't change focus") << false;
+}
+
+void tst_QGraphicsItem::tabChangesFocus()
+{
+ QFETCH(bool, tabChangesFocus);
+
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText("Hello");
+ item->setTabChangesFocus(tabChangesFocus);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ item->setFocus();
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QDial *dial2 = new QDial;
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(2000);
+
+ QTRY_VERIFY(scene.isActive());
+
+ dial1->setFocus();
+ QTest::qWait(15);
+ QTRY_VERIFY(dial1->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTest::qWait(15);
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTest::qWait(15);
+
+ if (tabChangesFocus) {
+ QTRY_VERIFY(!view->hasFocus());
+ QTRY_VERIFY(!item->hasFocus());
+ QTRY_VERIFY(dial2->hasFocus());
+ } else {
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+ QCOMPARE(item->toPlainText(), QString("\tHello"));
+ }
+}
+
+void tst_QGraphicsItem::cacheMode()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ QGraphicsView view(&scene);
+ view.resize(150, 150);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ // Increase the probability of window activation
+ // not causing another repaint of test items.
+ QTest::qWait(50);
+
+ EventTester *tester = new EventTester;
+ EventTester *testerChild = new EventTester;
+ testerChild->setParentItem(tester);
+ EventTester *testerChild2 = new EventTester;
+ testerChild2->setParentItem(testerChild);
+ testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ scene.addItem(tester);
+ QTest::qWait(10);
+
+ for (int i = 0; i < 2; ++i) {
+ // No visual change.
+ QTRY_COMPARE(tester->repaints, 1);
+ QCOMPARE(testerChild->repaints, 1);
+ QCOMPARE(testerChild2->repaints, 1);
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ testerChild->setCacheMode(QGraphicsItem::NoCache);
+ testerChild2->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 1);
+ QCOMPARE(testerChild->repaints, 1);
+ QCOMPARE(testerChild2->repaints, 1);
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(25);
+ }
+
+ // The first move causes a repaint as the item is painted into its pixmap.
+ // (Only occurs if the item has previously been painted without cache).
+ tester->setPos(10, 10);
+ testerChild->setPos(10, 10);
+ testerChild2->setPos(10, 10);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Consecutive moves should not repaint.
+ tester->setPos(20, 20);
+ testerChild->setPos(20, 20);
+ testerChild2->setPos(20, 20);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Translating does not result in a repaint.
+ tester->translate(10, 10);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Rotating results in a repaint.
+ tester->rotate(45);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 3);
+ QCOMPARE(testerChild->repaints, 3);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Change to ItemCoordinateCache (triggers repaint).
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
+ testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
+ testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 4);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Rotating items with ItemCoordinateCache doesn't cause a repaint.
+ tester->rotate(22);
+ testerChild->rotate(22);
+ testerChild2->rotate(22);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 4);
+ QTRY_COMPARE(testerChild->repaints, 4);
+ QTRY_COMPARE(testerChild2->repaints, 3);
+ tester->resetTransform();
+ testerChild->resetTransform();
+ testerChild2->resetTransform();
+
+ // Explicit update causes a repaint.
+ tester->update(0, 0, 5, 5);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 5);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Updating outside the item's bounds does not cause a repaint.
+ tester->update(10, 10, 5, 5);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 5);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Resizing an item should cause a repaint of that item. (because of
+ // autosize).
+ tester->setGeometry(QRectF(-15, -15, 30, 30));
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 6);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Set fixed size.
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
+ testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
+ testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
+ QTest::qWait(20);
+ QTRY_COMPARE(tester->repaints, 7);
+ QCOMPARE(testerChild->repaints, 5);
+ QCOMPARE(testerChild2->repaints, 4);
+
+ // Resizing the item should cause a repaint.
+ testerChild->setGeometry(QRectF(-15, -15, 30, 30));
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 7);
+ QCOMPARE(testerChild->repaints, 6);
+ QCOMPARE(testerChild2->repaints, 4);
+
+ // Scaling the view does not cause a repaint.
+ view.scale(0.7, 0.7);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 7);
+ QCOMPARE(testerChild->repaints, 6);
+ QCOMPARE(testerChild2->repaints, 4);
+
+ // Switch to device coordinate cache.
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 8);
+ QCOMPARE(testerChild->repaints, 7);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Scaling the view back should cause repaints for two of the items.
+ view.setTransform(QTransform());
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 9);
+ QCOMPARE(testerChild->repaints, 8);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Rotating the base item (perspective) should repaint two items.
+ tester->setTransform(QTransform().rotate(10, Qt::XAxis));
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 10);
+ QCOMPARE(testerChild->repaints, 9);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Moving the middle item should case a repaint even if it's a move,
+ // because the parent is rotated with a perspective.
+ testerChild->setPos(1, 1);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 11);
+ QTRY_COMPARE(testerChild->repaints, 10);
+ QTRY_COMPARE(testerChild2->repaints, 5);
+ tester->resetTransform();
+
+ // Make a huge item
+ tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
+ QTRY_COMPARE(tester->repaints, 12);
+ QTRY_COMPARE(testerChild->repaints, 11);
+ QTRY_COMPARE(testerChild2->repaints, 5);
+
+ // Move the large item - will cause a repaint as the
+ // cache is clipped.
+ tester->setPos(5, 0);
+ QTRY_COMPARE(tester->repaints, 13);
+ QTRY_COMPARE(testerChild->repaints, 11);
+ QTRY_COMPARE(testerChild2->repaints, 5);
+
+ // Hiding and showing should invalidate the cache
+ tester->hide();
+ QTest::qWait(25);
+ tester->show();
+ QTRY_COMPARE(tester->repaints, 14);
+ QTRY_COMPARE(testerChild->repaints, 12);
+ QTRY_COMPARE(testerChild2->repaints, 6);
+}
+
+void tst_QGraphicsItem::cacheMode2()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ QGraphicsView view(&scene);
+ view.resize(150, 150);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ // Increase the probability of window activation
+ // not causing another repaint of test items.
+ QTest::qWait(50);
+
+ EventTester *tester = new EventTester;
+ scene.addItem(tester);
+ QTest::qWait(10);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from NoCache to NoCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from NoCache to DeviceCoordinateCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from DeviceCoordinateCache to NoCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from NoCache to ItemCoordinateCache (repaint)
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 2);
+
+ // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 2);
+
+ // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint)
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100));
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 3);
+
+ // Switching from ItemCoordinateCache to NoCache (repaint)
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 4);
+
+ // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 4);
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 5);
+
+ // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 6);
+}
+
+void tst_QGraphicsItem::updateCachedItemAfterMove()
+{
+ // A simple item that uses ItemCoordinateCache
+ EventTester *tester = new EventTester;
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ // Add to a scene, show in a view, ensure it's painted and reset its
+ // repaint counter.
+ QGraphicsScene scene;
+ scene.addItem(tester);
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTest::qWait(12);
+ QTRY_VERIFY(tester->repaints > 0);
+ tester->repaints = 0;
+
+ // Move the item, should not cause repaints
+ tester->setPos(10, 0);
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 0);
+
+ // Move then update, should cause one repaint
+ tester->setPos(20, 0);
+ tester->update();
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 1);
+
+ // Hiding the item doesn't cause a repaint
+ tester->hide();
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 1);
+
+ // Moving a hidden item doesn't cause a repaint
+ tester->setPos(30, 0);
+ tester->update();
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 1);
+}
+
+class Track : public QGraphicsRectItem
+{
+public:
+ Track(const QRectF &rect)
+ : QGraphicsRectItem(rect)
+ {
+ setAcceptHoverEvents(true);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
+ }
+
+protected:
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+ {
+ p = event->pos();
+ sp = event->widget()->mapFromGlobal(event->screenPos());
+ update();
+ }
+private:
+ QPointF p;
+ QPoint sp;
+};
+
+void tst_QGraphicsItem::deviceTransform_data()
+{
+ QTest::addColumn<bool>("untransformable1");
+ QTest::addColumn<bool>("untransformable2");
+ QTest::addColumn<bool>("untransformable3");
+ QTest::addColumn<qreal>("rotation1");
+ QTest::addColumn<qreal>("rotation2");
+ QTest::addColumn<qreal>("rotation3");
+ QTest::addColumn<QTransform>("deviceX");
+ QTest::addColumn<QPointF>("mapResult1");
+ QTest::addColumn<QPointF>("mapResult2");
+ QTest::addColumn<QPointF>("mapResult3");
+
+ QTest::newRow("nil") << false << false << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform()
+ << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350);
+ QTest::newRow("deviceX rot 90") << false << false << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350);
+ QTest::newRow("deviceX rot 90 100") << true << false << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
+ QTest::newRow("deviceX rot 90 010") << false << true << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350);
+ QTest::newRow("deviceX rot 90 001") << false << false << true
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350);
+ QTest::newRow("deviceX rot 90 111") << true << true << true
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
+ QTest::newRow("deviceX rot 90 101") << true << false << true
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
+}
+
+void tst_QGraphicsItem::deviceTransform()
+{
+ QFETCH(bool, untransformable1);
+ QFETCH(bool, untransformable2);
+ QFETCH(bool, untransformable3);
+ QFETCH(qreal, rotation1);
+ QFETCH(qreal, rotation2);
+ QFETCH(qreal, rotation3);
+ QFETCH(QTransform, deviceX);
+ QFETCH(QPointF, mapResult1);
+ QFETCH(QPointF, mapResult2);
+ QFETCH(QPointF, mapResult3);
+
+ QGraphicsScene scene;
+ Track *rect1 = new Track(QRectF(0, 0, 100, 100));
+ Track *rect2 = new Track(QRectF(0, 0, 100, 100));
+ Track *rect3 = new Track(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect1);
+ rect3->setParentItem(rect2);
+ rect1->setPos(100, 100);
+ rect2->setPos(100, 100);
+ rect3->setPos(100, 100);
+ rect1->rotate(rotation1);
+ rect2->rotate(rotation2);
+ rect3->rotate(rotation3);
+ rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1);
+ rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2);
+ rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3);
+ rect1->setBrush(Qt::red);
+ rect2->setBrush(Qt::green);
+ rect3->setBrush(Qt::blue);
+ scene.addItem(rect1);
+
+ QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1);
+ QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2);
+ QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
+}
+
+void tst_QGraphicsItem::update()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+ QWidget topLevel;
+ MyGraphicsView view(&scene,&topLevel);
+
+ topLevel.resize(300, 300);
+ topLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ QTest::qWait(100); // Make sure all pending updates are processed.
+ item->repaints = 0;
+
+ item->update(); // Item marked as dirty
+ scene.update(); // Entire scene marked as dirty
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+
+ // Make sure the dirty state from the previous update is reset so that
+ // the item don't think it is already dirty and discards this update.
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 2);
+
+ // Make sure a partial update doesn't cause a full update to be discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(QRectF(0, 0, 5, 5));
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toAlignedRect();
+ QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure update requests outside the bounding rect are discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+
+ // Make sure the area occupied by an item is repainted when hiding it.
+ view.reset();
+ item->repaints = 0;
+ item->update(); // Full update; all sub-sequent update requests are discarded.
+ item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure item is repainted when shown (after being hidden).
+ view.reset();
+ item->repaints = 0;
+ item->show();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ item->repaints = 0;
+ item->hide();
+ qApp->processEvents();
+ view.reset();
+ const QPointF originalPos = item->pos();
+ item->setPos(5000, 5000);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+ qApp->processEvents();
+
+ item->setPos(originalPos);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+ item->show();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+ item->setPos(originalPos + QPoint(50, 50));
+ viewPrivate->updateAll();
+ QVERIFY(viewPrivate->fullUpdatePending);
+ QTest::qWait(50);
+ item->repaints = 0;
+ view.reset();
+ item->setPos(originalPos);
+ QTest::qWait(50);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
+
+ // Make sure moving a parent item triggers an update on the children
+ // (even though the parent itself is outside the viewport).
+ QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
+ parent->setPos(-400, 0);
+ item->setParentItem(parent);
+ item->setPos(400, 0);
+ scene.addItem(parent);
+ QTest::qWait(50);
+ itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toAlignedRect();
+ expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ view.reset();
+ item->repaints = 0;
+ parent->translate(-400, 0);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+ view.reset();
+ item->repaints = 0;
+ parent->translate(400, 0);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsItem::setTransformProperties_data()
+{
+ QTest::addColumn<QPointF>("origin");
+ QTest::addColumn<qreal>("rotation");
+ QTest::addColumn<qreal>("scale");
+
+ QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
+
+ QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
+
+ QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
+ << qreal(-2578.2)
+ << qreal(1.0);
+
+ QTest::newRow("Scale") << QPointF() << qreal(0.0)
+ << qreal(6);
+
+ QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
+}
+
+/**
+ * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
+ */
+#define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
+
+void tst_QGraphicsItem::setTransformProperties()
+{
+ QFETCH(QPointF,origin);
+ QFETCH(qreal,rotation);
+ QFETCH(qreal,scale);
+
+ QTransform result;
+ result.translate(origin.x(), origin.y());
+ result.rotate(rotation, Qt::ZAxis);
+ result.scale(scale, scale);
+ result.translate(-origin.x(), -origin.y());
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ item->setRotation(rotation);
+ item->setScale(scale);
+ item->setTransformOriginPoint(origin);
+
+ QCOMPARE(item->rotation(), rotation);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ //Change the rotation Z
+ item->setRotation(45);
+ QTransform result2;
+ result2.translate(origin.x(), origin.y());
+ result2.rotate(45);
+ result2.scale(scale, scale);
+ result2.translate(-origin.x(), -origin.y());
+
+ QCOMPARE(item->rotation(), 45.);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result2, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ // calling setTransform() and setPos should change the sceneTransform
+ item->setTransform(result);
+ item->setPos(100, -150.5);
+
+ QCOMPARE(item->rotation(), 45.);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+ QCOMPARE(result, item->transform());
+
+ QTransform result3(result);
+
+ result3.translate(origin.x(), origin.y());
+ result3.rotate(45);
+ result3.scale(scale, scale);
+ result3.translate(-origin.x(), -origin.y());
+
+ result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
+
+ QCOMPARE(result3, item->sceneTransform());
+
+ //-----------------------------------------------------
+ // setting the propertiees should be the same as setting a transform
+ {//with center origin on the matrix
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setRotation(rotation);
+ item1->setScale(scale);
+ item1->setTransformOriginPoint(origin);
+
+ item2->setTransform(result);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+}
+
+class MyStyleOptionTester : public QGraphicsRectItem
+{
+public:
+ MyStyleOptionTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), startTrack(false)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ if (startTrack) {
+ //Doesn't use the extended style option so the exposed rect is the boundingRect
+ if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
+ QCOMPARE(option->exposedRect, boundingRect());
+ QCOMPARE(option->matrix, QMatrix());
+ } else {
+ QVERIFY(option->exposedRect != QRect());
+ QVERIFY(option->exposedRect != boundingRect());
+ QCOMPARE(option->matrix, sceneTransform().toAffine());
+ }
+ }
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+ bool startTrack;
+};
+
+void tst_QGraphicsItem::itemUsesExtendedStyleOption()
+{
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsPixmapItem item;
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
+ QCOMPARE(item.flags(), 0);
+
+ //We now test the content of the style option
+ MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
+ scene.addItem(rect);
+ rect->setPos(200, 200);
+ QWidget topLevel;
+ QGraphicsView view(&scene, &topLevel);
+ topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ rect->startTrack = false;
+ topLevel.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(60);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(60);
+ rect->startTrack = false;
+ rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
+ QTest::qWait(60);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(60);
+}
+
+void tst_QGraphicsItem::itemSendsGeometryChanges()
+{
+ ItemChangeTester item;
+ item.setFlags(0);
+ item.clear();
+
+ QTransform x = QTransform().rotate(45);
+ QPointF pos(10, 10);
+ qreal o(0.5);
+ qreal r(10.0);
+ qreal s(1.5);
+ QPointF origin(1.0, 1.0);
+ item.setTransform(x);
+ item.setPos(pos);
+ item.setRotation(r);
+ item.setScale(s);
+ item.setTransformOriginPoint(origin);
+ QCOMPARE(item.transform(), x);
+ QCOMPARE(item.pos(), pos);
+ QCOMPARE(item.rotation(), r);
+ QCOMPARE(item.scale(), s);
+ QCOMPARE(item.transformOriginPoint(), origin);
+ QCOMPARE(item.changes.size(), 0);
+
+ item.setOpacity(o);
+ QCOMPARE(item.changes.size(), 2); // opacity
+
+ item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(item.changes.size(), 4); // flags
+ item.setTransform(QTransform());
+ item.setPos(QPointF());
+ QCOMPARE(item.changes.size(), 8); // transform + pos
+ QCOMPARE(item.transform(), QTransform());
+ QCOMPARE(item.pos(), QPointF());
+ QCOMPARE(item.opacity(), o);
+ item.setRotation(0.0);
+ item.setScale(1.0);
+ item.setTransformOriginPoint(0.0, 0.0);
+ QCOMPARE(item.changes.size(), 14); // rotation + scale + origin
+ QCOMPARE(item.rotation(), qreal(0.0));
+ QCOMPARE(item.scale(), qreal(1.0));
+ QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0));
+
+ QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemOpacityChange
+ << QGraphicsItem::ItemOpacityHasChanged
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemTransformChange
+ << QGraphicsItem::ItemTransformHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged
+ << QGraphicsItem::ItemRotationChange
+ << QGraphicsItem::ItemRotationHasChanged
+ << QGraphicsItem::ItemScaleChange
+ << QGraphicsItem::ItemScaleHasChanged
+ << QGraphicsItem::ItemTransformOriginPointChange
+ << QGraphicsItem::ItemTransformOriginPointHasChanged);
+}
+
+// Make sure we update moved items correctly.
+void tst_QGraphicsItem::moveItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+#define RESET_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.reset();
+
+ scene.addItem(parent);
+ QTest::qWait(100);
+
+ RESET_COUNTERS
+
+ // Item's boundingRect: (-10, -10, 20, 20).
+ QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toAlignedRect()
+ .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
+
+ parent->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
+ parentDeviceBoundingRect.translate(20, 20);
+ expectedParentRegion += parentDeviceBoundingRect; // new position
+ COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
+
+ RESET_COUNTERS
+
+ child->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
+ COMPARE_REGIONS(view.paintedRegion, expectedChildRegion);
+
+ RESET_COUNTERS
+
+ grandChild->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
+ COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion);
+
+ RESET_COUNTERS
+
+ parent->translate(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ expectedParentRegion.translate(20, 20);
+ expectedParentRegion += expectedChildRegion.translated(20, 20);
+ expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
+ COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
+}
+
+void tst_QGraphicsItem::moveLineItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 200, 200);
+ QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0);
+ item->setPos(50, 50);
+ scene.addItem(item);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(200);
+ view.reset();
+
+ QRectF brect = item->boundingRect();
+ // Do same adjustments as in qgraphicsscene.cpp
+ if (!brect.width())
+ brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
+ if (!brect.height())
+ brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001));
+ const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(brect).toAlignedRect();
+ QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing
+
+ // Make sure the calculated region is correct.
+ item->update();
+ QTest::qWait(10);
+ QTRY_COMPARE(view.paintedRegion, expectedRegion);
+ view.reset();
+
+ // Old position: (50, 50)
+ item->setPos(50, 100);
+ expectedRegion += expectedRegion.translated(0, 50);
+ QTest::qWait(10);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsItem::sorting_data()
+{
+ QTest::addColumn<int>("index");
+
+ QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
+ QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
+}
+
+void tst_QGraphicsItem::sorting()
+{
+ if (PlatformQuirks::isAutoMaximizing())
+ QSKIP("Skipped because Platform is auto maximizing", SkipAll);
+
+ _paintedItems.clear();
+
+ QGraphicsScene scene;
+ QGraphicsItem *grid[100][100];
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 100; ++y) {
+ PainterItem *item = new PainterItem;
+ item->setPos(x * 25, y * 25);
+ item->setData(0, QString("%1x%2").arg(x).arg(y));
+ grid[x][y] = item;
+ scene.addItem(item);
+ }
+ }
+
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.resize(120, 100);
+ view.setFrameStyle(0);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+#if defined(Q_WS_MAC)
+ // There's no difference between repaint and update on the Mac,
+ // so we have to process events here to make sure we get the event.
+ QTest::qWait(100);
+#endif
+
+ QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
+ << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
+ << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
+ << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
+ << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
+ << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
+ << item1 << item2);
+}
+
+void tst_QGraphicsItem::itemHasNoContents()
+{
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item2->setParentItem(item1);
+ item2->setPos(50, 50);
+ item1->setFlag(QGraphicsItem::ItemHasNoContents);
+ item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!_paintedItems.isEmpty());
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+#ifdef Q_WS_MAC
+ // There's no difference between update() and repaint() on the Mac,
+ // so we have to process events here to make sure we get the event.
+ QTest::qWait(10);
+#endif
+
+ QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
+}
+
+void tst_QGraphicsItem::hitTestUntransformableItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ // Confuse the BSP with dummy items.
+ QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100, -100);
+ scene.addItem(dummy);
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *parent = dummy;
+ dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100 + i, -100 + i);
+ dummy->setParentItem(parent);
+ }
+
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
+ item1->setPos(-200, -200);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
+ item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item2->setPos(200, 200);
+
+ QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
+ item3->setParentItem(item2);
+ item3->setPos(80, 80);
+
+ scene.addItem(item1);
+ QTest::qWait(100);
+
+ QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QTest::qWait(100);
+
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
+}
+
+void tst_QGraphicsItem::hitTestGraphicsEffectItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+
+ QWidget toplevel;
+
+ QGraphicsView view(&scene, &toplevel);
+ toplevel.resize(300, 300);
+ toplevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&toplevel);
+#endif
+ QTest::qWait(100);
+
+ // Confuse the BSP with dummy items.
+ QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100, -100);
+ scene.addItem(dummy);
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *parent = dummy;
+ dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100 + i, -100 + i);
+ dummy->setParentItem(parent);
+ }
+
+ const QRectF itemBoundingRect(0, 0, 20, 20);
+ EventTester *item1 = new EventTester;
+ item1->br = itemBoundingRect;
+ item1->setPos(-200, -200);
+ item1->brush = Qt::red;
+
+ EventTester *item2 = new EventTester;
+ item2->br = itemBoundingRect;
+ item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item2->setPos(200, 200);
+ item2->brush = Qt::green;
+
+ EventTester *item3 = new EventTester;
+ item3->br = itemBoundingRect;
+ item3->setParentItem(item2);
+ item3->setPos(80, 80);
+ item3->brush = Qt::blue;
+
+ scene.addItem(item1);
+ QTest::qWait(100);
+
+ item1->repaints = 0;
+ item2->repaints = 0;
+ item3->repaints = 0;
+
+ // Apply shadow effect to the entire sub-tree.
+ QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
+ shadow->setOffset(-20, -20);
+ item1->setGraphicsEffect(shadow);
+ QTest::qWait(50);
+
+ // Make sure all visible items are repainted.
+ QCOMPARE(item1->repaints, 1);
+ QCOMPARE(item2->repaints, 1);
+ QCOMPARE(item3->repaints, 1);
+
+ // Make sure an item doesn't respond to a click on its shadow.
+ QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
+ QVERIFY(items.isEmpty());
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QTest::qWait(100);
+
+ items = scene.items(QPointF(75, 75));
+ QVERIFY(items.isEmpty());
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
+}
+
+void tst_QGraphicsItem::focusProxy()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!item->focusProxy());
+
+ QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocusProxy(item2);
+ QCOMPARE(item->focusProxy(), item2);
+
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ // Try to make a focus chain loop
+ QString err;
+ QTextStream stream(&err);
+ stream << "QGraphicsItem::setFocusProxy: "
+ << (void*)item << " is already in the focus proxy chain" << flush;
+ QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
+ item2->setFocusProxy(item); // fails
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+
+ // Try to assign self as focus proxy
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
+ item->setFocusProxy(item); // fails
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+
+ // Reset the focus proxy
+ item->setFocusProxy(0);
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ // Test deletion
+ item->setFocusProxy(item2);
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ delete item2;
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+
+ // Test event delivery
+ item2 = scene.addRect(0, 0, 10, 10);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocusProxy(item2);
+ item->clearFocus();
+
+ EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
+ EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
+ EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
+ EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
+ QCOMPARE(focusInSpy.count(), 0);
+ QCOMPARE(focusOutSpy.count(), 0);
+ QCOMPARE(focusInSpy2.count(), 0);
+ QCOMPARE(focusOutSpy2.count(), 0);
+
+ item->setFocus();
+ QCOMPARE(focusInSpy.count(), 0);
+ QCOMPARE(focusInSpy2.count(), 1);
+ item->clearFocus();
+ QCOMPARE(focusOutSpy.count(), 0);
+ QCOMPARE(focusOutSpy2.count(), 1);
+
+ // Test two items proxying one item.
+ QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
+ item3->setFlag(QGraphicsItem::ItemIsFocusable);
+ item3->setFocusProxy(item2); // item and item3 use item2 as proxy
+
+ QCOMPARE(item->focusProxy(), item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+ QCOMPARE(item3->focusProxy(), item2);
+ delete item2;
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+ QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::subFocus()
+{
+ // Construct a text item that's not part of a scene (yet)
+ // and has no parent. Setting focus on it will not make
+ // the item gain input focus; that requires a scene. But
+ // it does set subfocus, indicating that the item wishes
+ // to gain focus later.
+ QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QVERIFY(!text->hasFocus());
+ text->setFocus();
+ QVERIFY(!text->hasFocus());
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
+
+ // Add a sibling.
+ QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
+ text2->setTextInteractionFlags(Qt::TextEditorInteraction);
+ text2->setPos(30, 30);
+
+ // Add both items to a scene and check that it's text that
+ // got input focus.
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(text);
+ scene.addItem(text2);
+ QVERIFY(text->hasFocus());
+
+ text->setData(0, "text");
+ text2->setData(0, "text2");
+
+ // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
+ // other item and see that it gains input focus.
+ scene.removeItem(text2);
+ text2->setFocus();
+ scene.addItem(text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ text2->setParentItem(text);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ QVERIFY(!text->hasFocus());
+ QVERIFY(text2->hasFocus());
+
+ // Remove both items from the scene, restore subfocus and
+ // readd them. Now the subfocus should kick in and give
+ // text2 focus.
+ scene.removeItem(text);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
+ text2->setFocus();
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ scene.addItem(text);
+
+ // Hiding and showing text should pass focus to text2.
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QVERIFY(text2->hasFocus());
+
+ // Subfocus should repropagate to root when reparenting.
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
+ QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
+ rect3->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ text->setData(0, "text");
+ text2->setData(0, "text2");
+ rect->setData(0, "rect");
+ rect2->setData(0, "rect2");
+ rect3->setData(0, "rect3");
+
+ rect3->setFocus();
+ QVERIFY(!rect3->hasFocus());
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
+ rect->setParentItem(text2);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
+ QVERIFY(!rect->hasFocus());
+ QVERIFY(!rect2->hasFocus());
+ QVERIFY(rect3->hasFocus());
+
+ delete rect2;
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::focusProxyDeletion()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+
+ delete rect2;
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+
+ rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ delete rect; // don't crash
+
+ rect = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QGraphicsScene *scene = new QGraphicsScene;
+ scene->addItem(rect);
+ scene->addItem(rect2);
+ delete rect2;
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+
+ rect2 = new QGraphicsRectItem;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+ scene->addItem(rect2);
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+ delete rect; // don't crash
+
+ rect = new QGraphicsRectItem;
+ rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+ scene->addItem(rect);
+ scene->addItem(rect2);
+ rect->setFocusProxy(rect2);
+ delete scene; // don't crash
+}
+
+void tst_QGraphicsItem::negativeZStacksBehindParent()
+{
+ QGraphicsRectItem rect;
+ QCOMPARE(rect.zValue(), qreal(0.0));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(-1);
+ QCOMPARE(rect.zValue(), qreal(-1.0));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(0);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(-1);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+ rect.setZValue(0);
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+ rect.setZValue(-1);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+}
+
+void tst_QGraphicsItem::setGraphicsEffect()
+{
+ // Check that we don't have any effect by default.
+ QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
+ QVERIFY(!item->graphicsEffect());
+
+ // SetGet check.
+ QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
+
+ // Ensure the existing effect is deleted when setting a new one.
+ QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
+ item->setGraphicsEffect(shadowEffect);
+ QVERIFY(!blurEffect);
+ QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
+ blurEffect = new QGraphicsBlurEffect;
+
+ // Ensure the effect is uninstalled when setting it on a new target.
+ QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
+ anotherItem->setGraphicsEffect(blurEffect);
+ item->setGraphicsEffect(blurEffect);
+ QVERIFY(!anotherItem->graphicsEffect());
+ QVERIFY(!shadowEffect);
+
+ // Ensure the existing effect is deleted when deleting the item.
+ delete item;
+ QVERIFY(!blurEffect);
+ delete anotherItem;
+
+ // Ensure the effect is uninstalled when deleting it
+ item = new QGraphicsRectItem(0, 0, 10, 10);
+ blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ delete blurEffect;
+ QVERIFY(!item->graphicsEffect());
+
+ // Ensure the existing effect is uninstalled and deleted when setting a null effect
+ blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ item->setGraphicsEffect(0);
+ QVERIFY(!item->graphicsEffect());
+ QVERIFY(!blurEffect);
+
+ delete item;
+}
+
+void tst_QGraphicsItem::panel()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *panel1 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel2 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel3 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel4 = new QGraphicsRectItem;
+ QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
+ QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
+ panel1->setFlag(QGraphicsItem::ItemIsPanel);
+ panel2->setFlag(QGraphicsItem::ItemIsPanel);
+ panel3->setFlag(QGraphicsItem::ItemIsPanel);
+ panel4->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(panel1);
+ scene.addItem(panel2);
+ scene.addItem(panel3);
+ scene.addItem(panel4);
+ scene.addItem(notPanel1);
+ scene.addItem(notPanel2);
+
+ EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
+ EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
+ EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
+
+ QCOMPARE(spy_activate_panel1.count(), 0);
+ QCOMPARE(spy_deactivate_panel1.count(), 0);
+ QCOMPARE(spy_activate_panel2.count(), 0);
+ QCOMPARE(spy_deactivate_panel2.count(), 0);
+ QCOMPARE(spy_activate_panel3.count(), 0);
+ QCOMPARE(spy_deactivate_panel3.count(), 0);
+ QCOMPARE(spy_activate_panel4.count(), 0);
+ QCOMPARE(spy_deactivate_panel4.count(), 0);
+ QCOMPARE(spy_activate_notPanel1.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel1.count(), 0);
+ QCOMPARE(spy_activate_notPanel2.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 0);
+
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!scene.isActive());
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+
+ // No previous activation, so the scene is active.
+ QVERIFY(scene.isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
+ QVERIFY(panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(!notPanel1->isActive());
+ QVERIFY(!notPanel2->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 0);
+ QCOMPARE(spy_activate_panel1.count(), 1);
+ QCOMPARE(spy_activate_panel2.count(), 0);
+ QCOMPARE(spy_activate_panel3.count(), 0);
+ QCOMPARE(spy_activate_panel4.count(), 0);
+
+ // Switch back to scene.
+ scene.setActivePanel(0);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(notPanel1->isActive());
+ QVERIFY(notPanel2->isActive());
+ QCOMPARE(spy_activate_notPanel1.count(), 1);
+ QCOMPARE(spy_activate_notPanel2.count(), 1);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(!notPanel1->isActive());
+ QVERIFY(!notPanel2->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 1);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 1);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(notPanel1->isActive());
+ QVERIFY(notPanel2->isActive());
+ QCOMPARE(spy_activate_notPanel1.count(), 2);
+ QCOMPARE(spy_activate_notPanel2.count(), 2);
+
+ // Switch to panel1
+ scene.setActivePanel(panel1);
+ QVERIFY(panel1->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 2);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 2);
+ QCOMPARE(spy_activate_panel1.count(), 2);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!panel1->isActive());
+ QCOMPARE(spy_deactivate_panel1.count(), 2);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(panel1->isActive());
+ QCOMPARE(spy_activate_panel1.count(), 3);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!scene.activePanel());
+ scene.setActivePanel(0);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(!panel1->isActive());
+}
+
+void tst_QGraphicsItem::panelWithFocusItem()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsRectItem *parentPanel = new QGraphicsRectItem;
+ QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel);
+ parentPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ parentPanelFocusItem->setFocus();
+ scene.addItem(parentPanel);
+
+ QVERIFY(parentPanel->isActive());
+ QVERIFY(parentPanelFocusItem->hasFocus());
+ QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+ QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+
+ QGraphicsRectItem *childPanel = new QGraphicsRectItem;
+ QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel);
+ childPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ childPanelFocusItem->setFocus();
+
+ QVERIFY(!childPanelFocusItem->hasFocus());
+ QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+ QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+
+ childPanel->setParentItem(parentPanel);
+
+ QVERIFY(!parentPanel->isActive());
+ QVERIFY(!parentPanelFocusItem->hasFocus());
+ QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+ QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+
+ QVERIFY(childPanel->isActive());
+ QVERIFY(childPanelFocusItem->hasFocus());
+ QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+ QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+
+ childPanel->hide();
+
+ QVERIFY(parentPanel->isActive());
+ QVERIFY(parentPanelFocusItem->hasFocus());
+ QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+ QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+}
+
+void tst_QGraphicsItem::addPanelToActiveScene()
+{
+ QGraphicsScene scene;
+ QVERIFY(!scene.isActive());
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ scene.addItem(rect);
+ QVERIFY(!rect->isActive());
+ scene.removeItem(rect);
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(scene.isActive());
+ scene.addItem(rect);
+ QVERIFY(rect->isActive());
+ scene.removeItem(rect);
+
+ rect->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(rect);
+ QVERIFY(rect->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ scene.addItem(rect2);
+ QVERIFY(rect->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
+}
+
+void tst_QGraphicsItem::activate()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
+ QVERIFY(!rect->isActive());
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+
+ // Non-panel item (active when scene is active).
+ QVERIFY(rect->isActive());
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ QGraphicsRectItem *rect3 = new QGraphicsRectItem;
+ rect3->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Test normal activation.
+ QVERIFY(!rect2->isActive());
+ scene.addItem(rect2);
+ QVERIFY(rect2->isActive()); // first panel item is activated
+ scene.addItem(rect3);
+ QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
+ rect3->setActive(true);
+ QVERIFY(rect3->isActive());
+ scene.removeItem(rect3);
+ QVERIFY(!rect3->isActive()); // no panel is active anymore
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+ scene.addItem(rect3);
+ QVERIFY(rect3->isActive()); // second panel item is activated
+
+ // Test pending activation.
+ scene.removeItem(rect3);
+ rect2->setActive(true);
+ QVERIFY(rect2->isActive()); // first panel item is activated
+ rect3->setActive(true);
+ QVERIFY(!rect3->isActive()); // not active (yet)
+ scene.addItem(rect3);
+ QVERIFY(rect3->isActive()); // now becomes active
+
+ // Test pending deactivation.
+ scene.removeItem(rect3);
+ rect3->setActive(false);
+ scene.addItem(rect3);
+ QVERIFY(!rect3->isActive()); // doesn't become active
+
+ // Child of panel activation.
+ rect3->setActive(true);
+ QGraphicsRectItem *rect4 = new QGraphicsRectItem;
+ rect4->setFlag(QGraphicsItem::ItemIsPanel);
+ QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
+ QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
+ scene.addItem(rect4);
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
+ scene.removeItem(rect4);
+ rect6->setActive(true);
+ scene.addItem(rect4);
+ QVERIFY(rect4->isActive());
+ QVERIFY(rect5->isActive());
+ QVERIFY(rect6->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
+ scene.removeItem(rect4); // no active panel
+ rect6->setActive(false);
+ scene.addItem(rect4);
+ QVERIFY(!rect4->isActive());
+ QVERIFY(!rect5->isActive());
+ QVERIFY(!rect6->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+
+ // Controlling auto-activation when the scene changes activation.
+ rect4->setActive(true);
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!scene.isActive());
+ QVERIFY(!rect4->isActive());
+ rect4->setActive(false);
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(scene.isActive());
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!rect4->isActive());
+}
+
+void tst_QGraphicsItem::setActivePanelOnInactiveScene()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF());
+ QGraphicsRectItem *panel = scene.addRect(QRectF());
+ panel->setFlag(QGraphicsItem::ItemIsPanel);
+
+ EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
+ EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
+ EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
+ EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
+ EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
+
+ scene.setActivePanel(panel);
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+ QCOMPARE(itemActivateSpy.count(), 0);
+ QCOMPARE(itemDeactivateSpy.count(), 0);
+ QCOMPARE(panelActivateSpy.count(), 0);
+ QCOMPARE(panelDeactivateSpy.count(), 0);
+ QCOMPARE(sceneActivationChangeSpy.count(), 0);
+}
+
+void tst_QGraphicsItem::activationOnShowHide()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
+ rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ rootPanel->setActive(true);
+
+ QGraphicsRectItem *subPanel = new QGraphicsRectItem;
+ subPanel->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Reparenting onto an active panel auto-activates the child panel.
+ subPanel->setParentItem(rootPanel);
+ QVERIFY(subPanel->isActive());
+ QVERIFY(!rootPanel->isActive());
+
+ // Hiding an active child panel will reactivate the parent panel.
+ subPanel->hide();
+ QVERIFY(rootPanel->isActive());
+
+ // Showing a child panel will auto-activate it.
+ subPanel->show();
+ QVERIFY(subPanel->isActive());
+ QVERIFY(!rootPanel->isActive());
+
+ // Adding an unrelated panel doesn't affect activation.
+ QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
+ otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(otherPanel);
+ QVERIFY(subPanel->isActive());
+
+ // Showing an unrelated panel doesn't affect activation.
+ otherPanel->hide();
+ otherPanel->show();
+ QVERIFY(subPanel->isActive());
+
+ // Add a non-panel item.
+ QGraphicsRectItem *otherItem = new QGraphicsRectItem;
+ scene.addItem(otherItem);
+ otherItem->setActive(true);
+ QVERIFY(otherItem->isActive());
+
+ // Reparent a panel onto an active non-panel item.
+ subPanel->setParentItem(otherItem);
+ QVERIFY(subPanel->isActive());
+
+ // Showing a child panel of a non-panel item will activate it.
+ subPanel->hide();
+ QVERIFY(!subPanel->isActive());
+ QVERIFY(otherItem->isActive());
+ subPanel->show();
+ QVERIFY(subPanel->isActive());
+
+ // Hiding a toplevel active panel will pass activation back
+ // to the non-panel items.
+ rootPanel->setActive(true);
+ rootPanel->hide();
+ QVERIFY(!rootPanel->isActive());
+ QVERIFY(otherItem->isActive());
+}
+
+class MoveWhileDying : public QGraphicsRectItem
+{
+public:
+ MoveWhileDying(QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(parent)
+ { }
+ ~MoveWhileDying()
+ {
+ foreach (QGraphicsItem *c, childItems()) {
+ foreach (QGraphicsItem *cc, c->childItems()) {
+ cc->moveBy(10, 10);
+ }
+ c->moveBy(10, 10);
+ }
+ if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
+ }
+};
+
+void tst_QGraphicsItem::moveWhileDeleting()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ MoveWhileDying *silly = new MoveWhileDying(rect);
+ QGraphicsRectItem *child = new QGraphicsRectItem(silly);
+ scene.addItem(rect);
+ delete rect; // don't crash!
+
+ rect = new QGraphicsRectItem;
+ silly = new MoveWhileDying(rect);
+ child = new QGraphicsRectItem(silly);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(125);
+
+ delete rect;
+
+ rect = new QGraphicsRectItem;
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ silly = new MoveWhileDying(rect);
+ child = new QGraphicsRectItem(silly);
+
+ QTest::qWait(125);
+
+ delete rect;
+
+ rect = new MoveWhileDying;
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ child = new QGraphicsRectItem(rect);
+ silly = new MoveWhileDying(child);
+
+ QTest::qWait(125);
+
+ delete rect;
+}
+
+class MyRectItem : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {
+
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ }
+ void move()
+ {
+ setPos(-100,-100);
+ topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
+ }
+public:
+ QGraphicsItem *topLevel;
+ QBrush brush;
+};
+
+
+void tst_QGraphicsItem::ensureDirtySceneTransform()
+{
+ QGraphicsScene scene;
+
+ MyRectItem *topLevel = new MyRectItem;
+ topLevel->setGeometry(0, 0, 100, 100);
+ topLevel->setPos(-50, -50);
+ topLevel->brush = QBrush(QColor(Qt::black));
+ scene.addItem(topLevel);
+
+ MyRectItem *parent = new MyRectItem;
+ parent->topLevel = topLevel;
+ parent->setGeometry(0, 0, 100, 100);
+ parent->setPos(0, 0);
+ parent->brush = QBrush(QColor(Qt::magenta));
+ parent->setObjectName("parent");
+ scene.addItem(parent);
+
+ MyRectItem *child = new MyRectItem(parent);
+ child->setGeometry(0, 0, 80, 80);
+ child->setPos(10, 10);
+ child->setObjectName("child");
+ child->brush = QBrush(QColor(Qt::blue));
+
+ MyRectItem *child2 = new MyRectItem(parent);
+ child2->setGeometry(0, 0, 80, 80);
+ child2->setPos(15, 15);
+ child2->setObjectName("child2");
+ child2->brush = QBrush(QColor(Qt::green));
+
+ MyRectItem *child3 = new MyRectItem(parent);
+ child3->setGeometry(0, 0, 80, 80);
+ child3->setPos(20, 20);
+ child3->setObjectName("child3");
+ child3->brush = QBrush(QColor(Qt::gray));
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ //We move the parent
+ parent->move();
+ QApplication::processEvents();
+
+ //We check if all items moved
+ QCOMPARE(child->pos(), QPointF(10, 10));
+ QCOMPARE(child2->pos(), QPointF(15, 15));
+ QCOMPARE(child3->pos(), QPointF(20, 20));
+
+ QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
+ QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
+ QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
+
+ QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
+ QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
+ QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
+}
+
+void tst_QGraphicsItem::focusScope()
+{
+ // ItemIsFocusScope is an internal feature (for now).
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *scope3 = new QGraphicsRectItem;
+ scope3->setData(0, "scope3");
+ scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope3->setFocus();
+ QVERIFY(!scope3->focusScopeItem());
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+
+ QGraphicsRectItem *scope2 = new QGraphicsRectItem;
+ scope2->setData(0, "scope2");
+ scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope2->setFocus();
+ QVERIFY(!scope2->focusScopeItem());
+ scope3->setParentItem(scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+
+ QGraphicsRectItem *scope1 = new QGraphicsRectItem;
+ scope1->setData(0, "scope1");
+ scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope1->setFocus();
+ QVERIFY(!scope1->focusScopeItem());
+ scope2->setParentItem(scope1);
+
+ QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+
+ scene.addItem(scope1);
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+
+ QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+
+ QVERIFY(scope3->hasFocus());
+
+ scope3->hide();
+ QVERIFY(scope2->hasFocus());
+ scope2->hide();
+ QVERIFY(scope1->hasFocus());
+ scope2->show();
+ QVERIFY(scope2->hasFocus());
+ scope3->show();
+ QVERIFY(scope3->hasFocus());
+ scope1->hide();
+ QVERIFY(!scope3->hasFocus());
+ scope1->show();
+ QVERIFY(scope3->hasFocus());
+ scope3->clearFocus();
+ QVERIFY(scope2->hasFocus());
+ scope2->clearFocus();
+ QVERIFY(scope1->hasFocus());
+ scope2->hide();
+ scope2->show();
+ QVERIFY(!scope2->hasFocus());
+ QVERIFY(scope1->hasFocus());
+ scope2->setFocus();
+ QVERIFY(scope2->hasFocus());
+ scope3->setFocus();
+ QVERIFY(scope3->hasFocus());
+
+ QGraphicsRectItem *rect4 = new QGraphicsRectItem;
+ rect4->setData(0, "rect4");
+ rect4->setParentItem(scope3);
+
+ QGraphicsRectItem *rect5 = new QGraphicsRectItem;
+ rect5->setData(0, "rect5");
+ rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ rect5->setFocus();
+ rect5->setParentItem(rect4);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
+ QVERIFY(rect5->hasFocus());
+
+ rect4->setParentItem(0);
+ QVERIFY(rect5->hasFocus());
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
+ QVERIFY(!scope3->hasFocus());
+
+ QGraphicsRectItem *rectA = new QGraphicsRectItem;
+ QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
+ scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scopeA->setFocus();
+ QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
+ scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scopeB->setFocus();
+
+ scene.addItem(rectA);
+ QVERIFY(rect5->hasFocus());
+ QVERIFY(!scopeB->hasFocus());
+
+ scopeA->setFocus();
+ QVERIFY(scopeB->hasFocus());
+ QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
+}
+
+void tst_QGraphicsItem::focusScope2()
+{
+ QGraphicsRectItem *child1 = new QGraphicsRectItem;
+ child1->setFlags(QGraphicsItem::ItemIsFocusable);
+ child1->setFocus();
+ QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1);
+
+ QGraphicsRectItem *child2 = new QGraphicsRectItem;
+ child2->setFlags(QGraphicsItem::ItemIsFocusable);
+
+ QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem;
+ rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ rootFocusScope->setFocus();
+ QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope);
+
+ child1->setParentItem(rootFocusScope);
+ child2->setParentItem(rootFocusScope);
+
+ QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1);
+ QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1);
+
+ QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem;
+ siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable);
+ siblingChild1->setFocus();
+
+ QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem;
+ siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable);
+
+ QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem;
+ siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+
+ siblingChild1->setParentItem(siblingFocusScope);
+ siblingChild2->setParentItem(siblingFocusScope);
+
+ QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1);
+ QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
+
+ QGraphicsItem *root = new QGraphicsRectItem;
+ rootFocusScope->setParentItem(root);
+ siblingFocusScope->setParentItem(root);
+
+ QCOMPARE(root->focusItem(), (QGraphicsItem *)child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QEvent activate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &activate);
+ scene.setFocus();
+
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1);
+
+ // You cannot set focus on a descendant of a focus scope directly;
+ // this will only change the scope's focus scope item pointer. If
+ // you want to give true input focus, you must set it directly on
+ // the scope itself
+ siblingChild2->setFocus();
+ QVERIFY(!siblingChild2->hasFocus());
+ QVERIFY(!siblingChild2->focusItem());
+ QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
+ QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
+
+ // Set focus on the scope; focus is forwarded to the focus scope item.
+ siblingFocusScope->setFocus();
+ QVERIFY(siblingChild2->hasFocus());
+ QVERIFY(siblingChild2->focusItem());
+ QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
+ QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2);
+}
+
+void tst_QGraphicsItem::stackBefore()
+{
+ QGraphicsRectItem parent;
+ QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child1->setData(0, "child1");
+ child2->setData(0, "child2");
+ child3->setData(0, "child3");
+ child4->setData(0, "child4");
+
+ // Remove and append
+ child2->setParentItem(0);
+ child2->setParentItem(&parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1); // 2134
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2); // 2134
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1); // 2341
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // 2341
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0); // 1234
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child4->stackBefore(child1); // 4123
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
+ child4->setZValue(1); // 1234 (4123)
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child3->stackBefore(child1); // 3124 (4312)
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
+ child4->setZValue(0); // 4312
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
+
+ // Make them all toplevels
+ child1->setParentItem(0);
+ child2->setParentItem(0);
+ child3->setParentItem(0);
+ child4->setParentItem(0);
+
+ QGraphicsScene scene;
+ scene.addItem(child1);
+ scene.addItem(child2);
+ scene.addItem(child3);
+ scene.addItem(child4);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
+ (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+
+ // Remove and append
+ scene.removeItem(child2);
+ scene.addItem(child2);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1); // 2134
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2); // 2134
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1); // 2341
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // 2341
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0); // 1234
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child4->stackBefore(child1); // 4123
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
+ child4->setZValue(1); // 1234 (4123)
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child3->stackBefore(child1); // 3124 (4312)
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
+ child4->setZValue(0); // 4312
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
+}
+
+void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
+{
+ EventTester *tester = new EventTester;
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ QGraphicsScene scene;
+ scene.addItem(tester);
+ scene.setSceneRect(-100, -100, 200, 200); // contains the tester item
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+ QTRY_COMPARE(tester->repaints, 1);
+
+ scene.update(); // triggers "updateAll" optimization
+ qApp->processEvents();
+ qApp->processEvents(); // in 4.6 only one processEvents is necessary
+
+ QCOMPARE(tester->repaints, 1);
+
+ scene.update(); // triggers "updateAll" optimization
+ tester->update();
+ qApp->processEvents();
+ qApp->processEvents(); // in 4.6 only one processEvents is necessary
+
+ QCOMPARE(tester->repaints, 2);
+}
+
+void tst_QGraphicsItem::sceneModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Scene modality, also test multiple scene modal items
+ leftChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
+
+ // Click inside left child
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent, event goes to modal child
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Left parent enters scene modality.
+ leftParent->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Click inside left child.
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent.
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Now both left parent and child are scene modal. Left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Click inside left child
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent, event goes to modal child
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Right child enters scene modality, only left child is blocked.
+ rightChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+}
+
+void tst_QGraphicsItem::panelModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Left Child enters panel modality, only left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Left parent enter panel modality, nothing is blocked.
+ leftParent->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Left child enters panel modality, left parent is blocked again.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ leftParent->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Left and right child enter panel modality, both parents are blocked.
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+}
+
+void tst_QGraphicsItem::mixedModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Left Child enters panel modality, only left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Left parent enters scene modality, which blocks everything except the child.
+ leftParent->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Right child enters panel modality (changes nothing).
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Left parent leaves modality. Right child is unblocked.
+ leftParent->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Right child "upgrades" its modality to scene modal. Left child is blocked.
+ // Right parent is unaffected.
+ rightChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // "downgrade" right child back to panel modal, left child is unblocked
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+}
+
+void tst_QGraphicsItem::modality_hover()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setAcceptHoverEvents(true);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setAcceptHoverEvents(true);
+ rect2->setPos(50, 50);
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ rect2->setData(0, "rect2");
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ sendMouseMove(&scene, QPointF(75, 75));
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+
+ sendMouseMove(&scene, QPointF(75, 75));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
+
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
+ // actually move
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+}
+
+void tst_QGraphicsItem::modality_mouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsMovable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsMovable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ {
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // releasing goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
+ sendMouseClick(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost to rect2 when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // rect1 does *not* re-grab when rect2 is no longer modal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // release goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+ {
+ // repeat the test using PanelModal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ rect1Spy.counts.clear();
+ rect2Spy.counts.clear();
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // releasing goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
+ sendMouseClick(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost to rect2 when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // rect1 does *not* re-grab when rect2 is no longer modal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // release goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+
+ {
+ // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
+ // meaning normal grabbing should work
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ rect1Spy.counts.clear();
+ rect2Spy.counts.clear();
+
+ QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
+ rect3->setFlag(QGraphicsItem::ItemIsPanel);
+ rect3->setFlag(QGraphicsItem::ItemIsMovable);
+ rect3->setPos(150, 50);
+ rect3->setData(0, "rect3");
+
+ EventSpy2 rect3Spy(&scene, rect3);
+
+ // pressing mouse on rect3 starts implicit grab
+ sendMousePress(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab is *not* lost when rect1 is modally shadowed by rect2
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // releasing goes to rect3
+ sendMouseRelease(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect3 starts implicit grab
+ sendMousePress(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab is not lost
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab stays on rect3
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // release goes to rect3
+ sendMouseRelease(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+}
+
+void tst_QGraphicsItem::modality_clickFocus()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ QEvent windowActivateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &windowActivateEvent);
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ // activate rect1, it should not get focus
+ rect1->setActive(true);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+
+ // focus stays unset when rect2 becomes modal
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect1 should not set it's focus item
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect2 gives it focus
+ rect2->setActive(true);
+ sendMouseClick(&scene, QPointF(75, 75));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect1 does *not* give it focus
+ rect1->setActive(true);
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+
+ // focus doesn't change when leaving modality either
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+
+ // click on rect1, it should get focus now
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+}
+
+void tst_QGraphicsItem::modality_keyEvents()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
+ rect1child->setParentItem(rect1);
+ rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1child->setData(0, "rect1child1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
+ rect2child->setParentItem(rect2);
+ rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2child->setData(0, "rect2child1");
+
+ QEvent windowActivateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &windowActivateEvent);
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect1childSpy(&scene, rect1child);
+ EventSpy2 rect2Spy(&scene, rect2);
+ EventSpy2 rect2childSpy(&scene, rect2child);
+
+ // activate rect1 and give it rect1child focus
+ rect1->setActive(true);
+ rect1child->setFocus();
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // focus stays on rect1child when rect2 becomes modal
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // but key events to rect1child should be neither delivered nor propagated
+ sendKeyClick(&scene, Qt::Key_A);
+ sendKeyClick(&scene, Qt::Key_S);
+ sendKeyClick(&scene, Qt::Key_D);
+ sendKeyClick(&scene, Qt::Key_F);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
+
+ // change to panel modality, rect1child1 keeps focus
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // still no key events
+ sendKeyClick(&scene, Qt::Key_J);
+ sendKeyClick(&scene, Qt::Key_K);
+ sendKeyClick(&scene, Qt::Key_L);
+ sendKeyClick(&scene, Qt::Key_Semicolon);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
+}
+
+void tst_QGraphicsItem::itemIsInFront()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = new QGraphicsRectItem;
+ rect1->setData(0, "rect1");
+ scene.addItem(rect1);
+
+ QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1);
+ rect1child1->setZValue(1);
+ rect1child1->setData(0, "rect1child1");
+
+ QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1);
+ rect1child2->setParentItem(rect1);
+ rect1child2->setData(0, "rect1child2");
+
+ QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1);
+ rect1child1_1->setData(0, "rect1child1_1");
+
+ QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1);
+ rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ rect1child1_2->setData(0, "rect1child1_2");
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setData(0, "rect2");
+ scene.addItem(rect2);
+
+ QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2);
+ rect2child1->setData(0, "rect2child1");
+
+ QCOMPARE(qt_closestItemFirst(rect1, rect1), false);
+ QCOMPARE(qt_closestItemFirst(rect1, rect2), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false);
+}
+
+class ScenePosChangeTester : public ItemChangeTester
+{
+public:
+ ScenePosChangeTester()
+ { }
+ ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent)
+ { }
+};
+
+void tst_QGraphicsItem::scenePosChange()
+{
+ ScenePosChangeTester* root = new ScenePosChangeTester;
+ ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
+ ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
+ ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
+ ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
+
+ child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+ grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+
+ QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
+ QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // ignore uninteresting changes
+ child1->clear();
+ child2->clear();
+ grandChild1->clear();
+ grandChild2->clear();
+
+ // move whole tree
+ root->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+
+ // move subtree
+ child2->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
+
+ // reparent
+ grandChild2->setParentItem(child1);
+ child1->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
+
+ // change flags
+ grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+ grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
+ QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
+ child1->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
+
+ // remove
+ scene.removeItem(grandChild1);
+ delete grandChild2; grandChild2 = 0;
+ QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
+ root->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+
+ root->setX(1);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+
+ root->setY(1);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : nbUpdates(0) {}
+ ~MyInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+
+ bool isComposing() const { return false; }
+
+ void update() { nbUpdates++; }
+
+ bool nbUpdates;
+};
+
+class MyInputWidget : public QGraphicsWidget
+{
+public:
+ MyInputWidget()
+ {
+ setFlag(QGraphicsItem::ItemIsFocusable, true);
+ setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ }
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ {
+ event->accept();
+ }
+
+ void doUpdateMicroFocus()
+ {
+ if (QWidget *fw = QApplication::focusWidget()) {
+ if (scene()) {
+ for (int i = 0 ; i < scene()->views().count() ; ++i) {
+ if (scene()->views().at(i) == fw) {
+ if (QInputContext *inputContext = fw->inputContext()) {
+ inputContext->update();
+ }
+ }
+ }
+ }
+ }
+ }
+};
+
+void tst_QGraphicsItem::updateMicroFocus()
+{
+#if defined Q_OS_WIN || defined Q_OS_MAC
+ QSKIP("QTBUG-9578", SkipAll);
+#endif
+ QGraphicsScene scene;
+ QWidget parent;
+ QGridLayout layout;
+ parent.setLayout(&layout);
+ QGraphicsView view(&scene);
+ QGraphicsView view2(&scene);
+ layout.addWidget(&view, 0, 0);
+ layout.addWidget(&view2, 0, 1);
+ MyInputContext *ic = new MyInputContext;
+ qApp->setInputContext(ic);
+ MyInputWidget input;
+ input.setPos(0, 0);
+ input.resize(150, 150);
+ scene.addItem(&input);
+ input.setFocus();
+ parent.show();
+ view.setFocus();
+ qApp->setAutoSipEnabled(true);
+ QApplication::setActiveWindow(&parent);
+ QTest::qWaitForWindowShown(&parent);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&parent));
+ //We reset the number of updates that happened previously (initialisation)
+ ic->nbUpdates = 0;
+ input.doUpdateMicroFocus();
+ QApplication::processEvents();
+ QTRY_COMPARE(ic->nbUpdates, 1);
+}
+
+void tst_QGraphicsItem::textItem_shortcuts()
+{
+ QWidget w;
+ QVBoxLayout l;
+ w.setLayout(&l);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ l.addWidget(&view);
+ QPushButton b("Push Me");
+ l.addWidget(&b);
+
+ QGraphicsTextItem *item = scene.addText("Troll Text");
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+
+ item->setFocus();
+ QTRY_VERIFY(item->hasFocus());
+ QVERIFY(item->textCursor().selectedText().isEmpty());
+
+ // Shortcut should work (select all)
+ QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
+ QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
+ QTextCursor tc = item->textCursor();
+ tc.clearSelection();
+ item->setTextCursor(tc);
+ QVERIFY(item->textCursor().selectedText().isEmpty());
+
+ // Shortcut should also work if the text item has the focus and another widget
+ // has the same shortcut.
+ b.setShortcut(QKeySequence("CTRL+A"));
+ QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
+ QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
+}
+
+void tst_QGraphicsItem::scroll()
+{
+ // Create two overlapping rectangles in the scene:
+ // +-------+
+ // | | <- item1
+ // | +-------+
+ // | | |
+ // +---| | <- item2
+ // | |
+ // +-------+
+
+ EventTester *item1 = new EventTester;
+ item1->br = QRectF(0, 0, 200, 200);
+ item1->brush = Qt::red;
+ item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+
+ EventTester *item2 = new EventTester;
+ item2->br = QRectF(0, 0, 200, 200);
+ item2->brush = Qt::blue;
+ item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+ item2->setPos(100, 100);
+
+ QGraphicsScene scene(0, 0, 300, 300);
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ MyGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ view.reset();
+ item1->reset();
+ item2->reset();
+
+ const QRectF item1BoundingRect = item1->boundingRect();
+ const QRectF item2BoundingRect = item2->boundingRect();
+
+ // Scroll item1:
+ // Item1 should get full exposure
+ // Item2 should get exposure for the part that overlaps item1.
+ item1->scroll(0, -10);
+ QTRY_VERIFY(view.repaints > 0);
+ QCOMPARE(item1->lastExposedRect, item1BoundingRect);
+
+ QRectF expectedItem2Expose = item2BoundingRect;
+ // NB! Adjusted by 2 pixels for antialiasing
+ expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2));
+ QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
+
+ // Enable ItemCoordinateCache on item1.
+ view.reset();
+ item1->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTRY_VERIFY(view.repaints > 0);
+ view.reset();
+ item1->reset();
+ item2->reset();
+
+ // Scroll item1:
+ // Item1 should only get expose for the newly exposed area (accelerated scroll).
+ // Item2 should get exposure for the part that overlaps item1.
+ item1->scroll(0, -10, QRectF(50, 50, 100, 100));
+ QTRY_VERIFY(view.repaints > 0);
+ QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10));
+
+ expectedItem2Expose = item2BoundingRect;
+ // NB! Adjusted by 2 pixels for antialiasing
+ expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2));
+ QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
+}
+
+Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag);
+
+void tst_QGraphicsItem::focusHandling_data()
+{
+ QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag");
+ QTest::addColumn<bool>("useStickyFocus");
+ QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus
+
+ QTest::newRow("Focus goes through.")
+ << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1;
+
+ QTest::newRow("Focus goes through, even with sticky scene.")
+ << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1;
+
+ QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).")
+ << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0;
+
+ QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).")
+ << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2;
+
+ QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.")
+ << QGraphicsItem::ItemStopsFocusHandling << false << 2;
+
+ QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).")
+ << QGraphicsItem::ItemStopsFocusHandling << true << 2;
+}
+
+void tst_QGraphicsItem::focusHandling()
+{
+ QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag);
+ QFETCH(bool, useStickyFocus);
+ QFETCH(int, expectedFocusItem);
+
+ class MyItem : public QGraphicsRectItem
+ {
+ public:
+ MyItem() : QGraphicsRectItem(0, 0, 100, 100) {}
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush());
+ }
+ };
+
+ QGraphicsRectItem *noFocusOnTop = new MyItem;
+ noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ noFocusOnTop->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *focusableUnder = new MyItem;
+ focusableUnder->setBrush(Qt::blue);
+ focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable);
+ focusableUnder->setPos(50, 50);
+
+ QGraphicsRectItem *itemWithFocus = new MyItem;
+ itemWithFocus->setBrush(Qt::black);
+ itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable);
+ itemWithFocus->setPos(250, 10);
+
+ QGraphicsScene scene(-50, -50, 400, 400);
+ scene.addItem(noFocusOnTop);
+ scene.addItem(focusableUnder);
+ scene.addItem(itemWithFocus);
+ scene.setStickyFocus(useStickyFocus);
+
+ noFocusOnTop->setFlag(focusFlag);
+ focusableUnder->stackBefore(noFocusOnTop);
+ itemWithFocus->setFocus();
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+ QVERIFY(itemWithFocus->hasFocus());
+
+ const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center());
+ const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint);
+ QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop));
+
+ sendMousePress(&scene, mousePressPoint);
+
+ switch (expectedFocusItem) {
+ case 0:
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0));
+ break;
+ case 1:
+ QCOMPARE(scene.focusItem(), focusableUnder);
+ break;
+ case 2:
+ QCOMPARE(scene.focusItem(), itemWithFocus);
+ break;
+ }
+
+ // Sanity check - manually setting the focus must work regardless of our
+ // focus handling flags:
+ focusableUnder->setFocus();
+ QCOMPARE(scene.focusItem(), focusableUnder);
+}
+
+void tst_QGraphicsItem::touchEventPropagation_data()
+{
+ QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag");
+ QTest::addColumn<int>("expectedCount");
+
+ QTest::newRow("ItemIsPanel")
+ << QGraphicsItem::ItemIsPanel << 0;
+ QTest::newRow("ItemStopsClickFocusPropagation")
+ << QGraphicsItem::ItemStopsClickFocusPropagation << 1;
+ QTest::newRow("ItemStopsFocusHandling")
+ << QGraphicsItem::ItemStopsFocusHandling << 1;
+}
+
+void tst_QGraphicsItem::touchEventPropagation()
+{
+ QFETCH(QGraphicsItem::GraphicsItemFlag, flag);
+ QFETCH(int, expectedCount);
+
+ class Testee : public QGraphicsRectItem
+ {
+ public:
+ int touchBeginEventCount;
+
+ Testee()
+ : QGraphicsRectItem(0, 0, 100, 100)
+ , touchBeginEventCount(0)
+ {
+ setAcceptTouchEvents(true);
+ setFlag(QGraphicsItem::ItemIsFocusable, false);
+ }
+
+ bool sceneEvent(QEvent *ev)
+ {
+ if (ev->type() == QEvent::TouchBegin)
+ ++touchBeginEventCount;
+
+ return QGraphicsRectItem::sceneEvent(ev);
+ }
+ };
+
+ Testee *touchEventReceiver = new Testee;
+ QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect());
+
+ QGraphicsScene scene;
+ scene.addItem(topMost);
+ scene.addItem(touchEventReceiver);
+
+ topMost->setAcceptTouchEvents(true);
+ topMost->setZValue(FLT_MAX);
+ topMost->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ topMost->setFlag(flag, true);
+
+ QGraphicsView view(&scene);
+ view.setSceneRect(touchEventReceiver->boundingRect());
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(touchEventReceiver->touchBeginEventCount, 0);
+
+ QTouchEvent::TouchPoint tp(0);
+ tp.setState(Qt::TouchPointPressed);
+ tp.setScenePos(view.sceneRect().center());
+ tp.setLastScenePos(view.sceneRect().center());
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints << tp;
+
+ sendMousePress(&scene, tp.scenePos());
+ QTouchEvent touchBegin(QEvent::TouchBegin, QTouchEvent::TouchScreen, Qt::NoModifier, Qt::TouchPointPressed, touchPoints);
+
+ qApp->sendEvent(&scene, &touchBegin);
+ QCOMPARE(touchEventReceiver->touchBeginEventCount, expectedCount);
+}
+
+void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations()
+{
+ // Make sure we don't invalidate the cache when applying simple
+ // (90, 180, 270, 360) rotation transforms to the item.
+ QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200);
+ item->setBrush(Qt::red);
+ item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 300, 200);
+ scene.addItem(item);
+
+ MyGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache();
+ QVERIFY(itemCache);
+ QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key;
+
+ // Trigger an update and verify that the cache is unchanged.
+ QPixmapCache::Key oldKey = currentKey;
+ view.reset();
+ view.viewport()->update();
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QCOMPARE(currentKey, oldKey);
+
+ // Check 90, 180, 270 and 360 degree rotations.
+ for (int angle = 90; angle <= 360; angle += 90) {
+ // Rotate item and verify that the cache was invalidated.
+ oldKey = currentKey;
+ view.reset();
+ QTransform transform;
+ transform.translate(150, 100);
+ transform.rotate(angle);
+ transform.translate(-150, -100);
+ item->setTransform(transform);
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QVERIFY(currentKey != oldKey);
+
+ // IMPORTANT PART:
+ // Trigger an update and verify that the cache is unchanged.
+ oldKey = currentKey;
+ view.reset();
+ view.viewport()->update();
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QCOMPARE(currentKey, oldKey);
+ }
+
+ // 45 degree rotation.
+ oldKey = currentKey;
+ view.reset();
+ QTransform transform;
+ transform.translate(150, 100);
+ transform.rotate(45);
+ transform.translate(-150, -100);
+ item->setTransform(transform);
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QVERIFY(currentKey != oldKey);
+
+ // Trigger an update and verify that the cache was invalidated.
+ // We should always invalidate the cache for non-trivial transforms.
+ oldKey = currentKey;
+ view.reset();
+ view.viewport()->update();
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QVERIFY(currentKey != oldKey);
+}
+
+void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
+{
+ struct Item : public QGraphicsTextItem
+ {
+ int painted;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
+ {
+ painted++;
+ QGraphicsTextItem::paint(painter, opt, wid);
+ }
+ };
+
+ Item *i = new Item;
+ i->painted = 0;
+ i->setPlainText("I AM A TROLL");
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ scene.addItem(i);
+ QApplication::processEvents();
+ QTRY_VERIFY(i->painted);
+ QApplication::processEvents();
+
+ i->painted = 0;
+ QColor col(Qt::red);
+ i->setDefaultTextColor(col);
+ QApplication::processEvents();
+ QTRY_COMPARE(i->painted, 1); //check that changing the color force an update
+
+ i->painted = false;
+ QImage image(400, 200, QImage::Format_RGB32);
+ image.fill(0);
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+ QCOMPARE(i->painted, 1);
+
+ int numRedPixel = 0;
+ QRgb rgb = col.rgb();
+ for (int y = 0; y < image.height(); ++y) {
+ for (int x = 0; x < image.width(); ++x) {
+ // Because of antialiasing we allow a certain range of errors here.
+ QRgb pixel = image.pixel(x, y);
+ if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
+ qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
+ qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
+ if (++numRedPixel >= 10) {
+ return;
+ }
+ }
+ }
+ }
+ QCOMPARE(numRedPixel, -1); //color not found, FAIL!
+
+ i->painted = 0;
+ i->setDefaultTextColor(col);
+ QApplication::processEvents();
+ QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242)
+}
+
+void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
+{
+ // In all 3 test cases below the reparented item should disappear
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *child2 = new EventTester(parent);
+ EventTester *child3 = new EventTester(parent);
+ EventTester *child4 = new EventTester(parent);
+
+ child->setPos(10, 10);
+ child2->setPos(20, 20);
+ child3->setPos(30, 30);
+ child4->setPos(40, 40);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ MyGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ // test case #1
+ view.reset();
+ child2->setVisible(false);
+ child2->setParentItem(child);
+
+ QTRY_VERIFY(view.repaints == 1);
+
+ // test case #2
+ view.reset();
+ child3->setOpacity(0.0);
+ child3->setParentItem(child);
+
+ QTRY_VERIFY(view.repaints == 1);
+
+ // test case #3
+ view.reset();
+ child4->setParentItem(child);
+ child4->setVisible(false);
+
+ QTRY_VERIFY(view.repaints == 1);
+}
+
+void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ MyGraphicsView view(&scene);
+
+ EventTester *parentGreen = new EventTester();
+ parentGreen->setGeometry(QRectF(20, 20, 100, 100));
+ parentGreen->brush = Qt::green;
+
+ EventTester *childYellow = new EventTester(parentGreen);
+ childYellow->setGeometry(QRectF(10, 10, 50, 50));
+ childYellow->brush = Qt::yellow;
+
+ scene.addItem(parentGreen);
+
+ childYellow->setOpacity(0.0);
+ parentGreen->setOpacity(0.0);
+
+ // set any of the flags below to trigger a fullUpdate to reproduce the bug:
+ // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
+ parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ if (PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.reset();
+
+ parentGreen->setOpacity(1.0);
+
+ QTRY_COMPARE(view.repaints, 1);
+
+ view.reset();
+ childYellow->repaints = 0;
+
+ childYellow->setOpacity(1.0);
+
+ QTRY_COMPARE(view.repaints, 1);
+ QTRY_COMPARE(childYellow->repaints, 1);
+}
+
+void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ MyGraphicsView view(&scene);
+ MyGraphicsView origView(&scene);
+
+ EventTester *parentGreen = new EventTester();
+ parentGreen->setGeometry(QRectF(20, 20, 100, 100));
+ parentGreen->brush = Qt::green;
+
+ EventTester *childYellow = new EventTester(parentGreen);
+ childYellow->setGeometry(QRectF(10, 10, 50, 50));
+ childYellow->brush = Qt::yellow;
+
+ scene.addItem(parentGreen);
+
+ origView.show();
+ QTest::qWaitForWindowShown(&origView);
+ origView.setGeometry(origView.width() + 20, 20,
+ origView.width(), origView.height());
+
+ parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ origView.reset();
+ childYellow->setOpacity(0.0);
+
+ QTRY_COMPARE(origView.repaints, 1);
+
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ view.reset();
+ origView.reset();
+
+ childYellow->setOpacity(1.0);
+
+ QTRY_COMPARE(origView.repaints, 1);
+ QTRY_COMPARE(view.repaints, 1);
+}
+
+void tst_QGraphicsItem::QT_2649_focusScope()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+
+ QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
+ subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
+ subFocusItem->setFocus();
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+
+ QGraphicsRectItem *scope = new QGraphicsRectItem;
+ scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope->setFocus();
+ subFocusItem->setParentItem(scope);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+
+ QGraphicsRectItem *rootItem = new QGraphicsRectItem;
+ rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
+ scope->setParentItem(rootItem);
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+
+ scene->addItem(rootItem);
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(scene, &windowActivate);
+ scene->setFocus();
+
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(subFocusItem->hasFocus());
+
+ scope->hide();
+
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(!subFocusItem->hasFocus());
+
+ scope->show();
+
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(subFocusItem->hasFocus());
+
+ // This should not crash
+ scope->hide();
+ delete scene;
+}
+
+class MyGraphicsItemWithItemChange : public QGraphicsWidget
+{
+public:
+ MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {}
+
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ if (change == QGraphicsItem::ItemSceneHasChanged) {
+ foreach (QGraphicsView *view, scene()->views()) {
+ //We trigger a sort of unindexed items in the BSP
+ view->sceneRect();
+ }
+ }
+ return QGraphicsWidget::itemChange(change, value);
+ }
+};
+
+void tst_QGraphicsItem::sortItemsWhileAdding()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget grandGrandParent;
+ grandGrandParent.resize(200, 200);
+ scene.addItem(&grandGrandParent);
+ QGraphicsWidget grandParent;
+ grandParent.resize(200, 200);
+ QGraphicsWidget parent(&grandParent);
+ parent.resize(200, 200);
+ MyGraphicsItemWithItemChange item(&parent);
+ grandParent.setParentItem(&grandGrandParent);
+}
+
+void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
+{
+ struct Item : public QGraphicsTextItem
+ {
+ int painted;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
+ {
+ painted++;
+ QGraphicsTextItem::paint(painter, opt, wid);
+ }
+ };
+ QGraphicsScene scene;
+ MyGraphicsView view(&scene);
+ Item *item = new Item;
+ item->painted = 0;
+ item->setPlainText("Grandparent");
+ Item *item2 = new Item;
+ item2->setPlainText("parent");
+ item2->painted = 0;
+ Item *item3 = new Item;
+ item3->setPlainText("child");
+ item3->painted = 0;
+ QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect;
+ effect->setOpacity(0.5);
+ item2->setGraphicsEffect(effect);
+ item3->setParentItem(item2);
+ item2->setParentItem(item);
+ scene.addItem(item);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(view.repaints, 1);
+ QTRY_COMPARE(item->painted, 1);
+ QTRY_COMPARE(item2->painted, 1);
+ QTRY_COMPARE(item3->painted, 1);
+ item2->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(item->painted, 2);
+ QTRY_COMPARE(item2->painted, 2);
+ QTRY_COMPARE(item3->painted, 2);
+ item2->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(item->painted, 3);
+ QTRY_COMPARE(item2->painted, 3);
+ QTRY_COMPARE(item3->painted, 3);
+}
+
+void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ item->setAcceptDrops(true);
+ scene.addItem(item);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+ QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
+ dragEnter.setScenePos(item->boundingRect().center());
+ QApplication::sendEvent(&scene, &dragEnter);
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
+ event.setScenePos(item->boundingRect().center());
+ QApplication::sendEvent(&scene, &event);
+ QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == item);
+ delete item;
+ QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
+}
+
+void tst_QGraphicsItem::QTBUG_12112_focusItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
+ item1->setFlag(QGraphicsItem::ItemIsFocusable);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item1->setFocus();
+ scene.addItem(item2);
+ scene.addItem(item1);
+
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+ QVERIFY(item1->focusItem());
+ QVERIFY(!item2->focusItem());
+
+ item2->setFocus();
+ QVERIFY(!item1->focusItem());
+ QVERIFY(item2->focusItem());
+}
+
+void tst_QGraphicsItem::QTBUG_13473_sceneposchange()
+{
+ ScenePosChangeTester* parent = new ScenePosChangeTester;
+ ScenePosChangeTester* child = new ScenePosChangeTester(parent);
+
+ // parent's disabled ItemSendsGeometryChanges flag must not affect
+ // child's scene pos change notifications
+ parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
+ child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ // ignore uninteresting changes
+ parent->clear();
+ child->clear();
+
+ // move
+ parent->moveBy(1.0, 1.0);
+ QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+
+ // transform
+ parent->setTransform(QTransform::fromScale(0.5, 0.5));
+ QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
+}
+
+class MyGraphicsWidget : public QGraphicsWidget {
+Q_OBJECT
+public:
+ MyGraphicsWidget()
+ : QGraphicsWidget(0)
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
+ QLatin1String wiseWords("AZ BUKI VEDI");
+ QString sentence(wiseWords);
+ QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < words.count(); ++i) {
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
+ QLabel *label = new QLabel(words.at(i));
+ proxy->setWidget(label);
+ proxy->setFocusPolicy(Qt::StrongFocus);
+ proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ if (i%2 == 0)
+ proxy->setVisible(false);
+ proxy->setFocus();
+ lay->addItem(proxy);
+ }
+ setLayout(lay);
+ }
+
+};
+
+class MyWidgetWindow : public QGraphicsWidget
+{
+public:
+ MyWidgetWindow()
+ : QGraphicsWidget(0, Qt::Window)
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
+ MyGraphicsWidget *widget = new MyGraphicsWidget();
+ lay->addItem(widget);
+ setLayout(lay);
+ }
+};
+
+void tst_QGraphicsItem::QTBUG_16374_crashInDestructor()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ MyWidgetWindow win;
+ scene.addItem(&win);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+}
+
+void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsPixmapItem fs;
+ fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
+ scene.addItem(&fs);
+ QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs);
+ fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
+ QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs);
+ fi2->setFlags(QGraphicsItem::ItemIsFocusable);
+ QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2);
+ fi->setFlags(QGraphicsItem::ItemIsFocusable);
+ fs.setFocus();
+ fi->setFocus();
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ fi->setParentItem(fi2);
+ fi->setFocus();
+ fs.setFocus();
+ fi->setParentItem(fs2);
+ fi->setFocus();
+ fs2->setFocus();
+ fs.setFocus();
+ fi->setParentItem(fi2);
+ fi->setFocus();
+ fs.setFocus();
+}
+
+QTEST_MAIN(tst_QGraphicsItem)
+#include "tst_qgraphicsitem.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore
new file mode 100644
index 0000000000..fe9fe0b8ec
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsitemanimation
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro
new file mode 100644
index 0000000000..5d723da32e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicsitemanimation.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
new file mode 100644
index 0000000000..f7cf393253
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qgraphicsitemanimation.h>
+#include <QtCore/qtimeline.h>
+#include <QtGui/qmatrix.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QGraphicsItemAnimation : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void construction();
+ void linearMove();
+ void linearRotation();
+ void checkReturnedLists();
+ void overwriteValueForStep();
+ void setTimeLine();
+};
+
+void tst_QGraphicsItemAnimation::construction()
+{
+ QGraphicsItemAnimation animation;
+ QVERIFY(!animation.item());
+ QVERIFY(!animation.timeLine());
+ QCOMPARE(animation.posAt(0), QPointF());
+ QCOMPARE(animation.posAt(0.5), QPointF());
+ QCOMPARE(animation.posAt(1), QPointF());
+ QCOMPARE(animation.matrixAt(0), QMatrix());
+ QCOMPARE(animation.matrixAt(0.5), QMatrix());
+ QCOMPARE(animation.matrixAt(1), QMatrix());
+ QCOMPARE(animation.rotationAt(0), qreal(0.0));
+ QCOMPARE(animation.rotationAt(0.5), qreal(0.0));
+ QCOMPARE(animation.rotationAt(1), qreal(0.0));
+ QCOMPARE(animation.xTranslationAt(0), qreal(0.0));
+ QCOMPARE(animation.xTranslationAt(0.5), qreal(0.0));
+ QCOMPARE(animation.xTranslationAt(1), qreal(0.0));
+ QCOMPARE(animation.yTranslationAt(0), qreal(0.0));
+ QCOMPARE(animation.yTranslationAt(0.5), qreal(0.0));
+ QCOMPARE(animation.yTranslationAt(1), qreal(0.0));
+ QCOMPARE(animation.verticalScaleAt(0), qreal(1.0));
+ QCOMPARE(animation.horizontalScaleAt(0), qreal(1.0));
+ QCOMPARE(animation.verticalShearAt(0), qreal(0.0));
+ QCOMPARE(animation.horizontalShearAt(0), qreal(0.0));
+ animation.clear(); // don't crash
+}
+
+void tst_QGraphicsItemAnimation::linearMove()
+{
+ QGraphicsItemAnimation animation;
+
+ for (int i = 0; i <= 10; ++i) {
+ QCOMPARE(animation.posAt(i / 10.0).x(), qreal(0));
+ QCOMPARE(animation.posAt(i / 10.0).y(), qreal(0));
+ }
+
+ animation.setPosAt(1, QPointF(10, -10));
+
+ for (int i = 0; i <= 10; ++i) {
+ QCOMPARE(animation.posAt(i / 10.0).x(), qreal(i));
+ QCOMPARE(animation.posAt(i / 10.0).y(), qreal(-i));
+ }
+
+ animation.setPosAt(2, QPointF(10, -10));
+
+ QCOMPARE(animation.posAt(11).x(), qreal(10));
+}
+
+void tst_QGraphicsItemAnimation::linearRotation()
+{
+ QGraphicsItemAnimation animation;
+ animation.setRotationAt(1, 1);
+
+ for (int i = 0; i <= 10; ++i)
+ QCOMPARE(animation.rotationAt(i / 10.0), qreal(i / 10.0));
+}
+
+void tst_QGraphicsItemAnimation::checkReturnedLists()
+{
+ QGraphicsItemAnimation animation;
+
+ animation.setPosAt(1.0, QPointF(10, -10));
+ animation.setPosAt(0.5, QPointF(5, -5));
+
+ animation.setRotationAt(0.3, 2.3);
+ animation.setTranslationAt(0.3, 15, 15);
+ animation.setScaleAt(0.3, 2.5, 1.8);
+ animation.setShearAt(0.3, 5, 5);
+
+ QCOMPARE(animation.posList().at(0), (QPair<qreal, QPointF>(0.5, QPointF(5, -5))));
+ QCOMPARE(animation.posList().at(1), (QPair<qreal, QPointF>(1.0, QPointF(10, -10))));
+ QCOMPARE(animation.rotationList().at(0), (QPair<qreal, qreal>(0.3, 2.3)));
+ QCOMPARE(animation.translationList().at(0), (QPair<qreal, QPointF>(0.3, QPointF(15, 15))));
+ QCOMPARE(animation.scaleList().at(0), (QPair<qreal, QPointF>(0.3, QPointF(2.5, 1.8))));
+ QCOMPARE(animation.shearList().at(0), (QPair<qreal, QPointF>(0.3, QPointF(5, 5))));
+
+ QCOMPARE(animation.posList().size(), 2);
+ QCOMPARE(animation.rotationList().size(), 1);
+ QCOMPARE(animation.translationList().size(), 1);
+ QCOMPARE(animation.scaleList().size(), 1);
+ QCOMPARE(animation.shearList().size(), 1);
+}
+
+void tst_QGraphicsItemAnimation::overwriteValueForStep()
+{
+ QGraphicsItemAnimation animation;
+
+ for (int i=0; i<3; i++){
+ animation.setPosAt(0.3, QPointF(3, -3.1));
+ animation.setRotationAt(0.3, 2.3);
+ animation.setTranslationAt(0.3, 15, 15);
+ animation.setScaleAt(0.3, 2.5, 1.8);
+ animation.setShearAt(0.3, 5, 5);
+
+ QCOMPARE(animation.posList().size(), 1);
+ QCOMPARE(animation.rotationList().size(), 1);
+ QCOMPARE(animation.translationList().size(), 1);
+ QCOMPARE(animation.scaleList().size(), 1);
+ QCOMPARE(animation.shearList().size(), 1);
+ }
+}
+
+void tst_QGraphicsItemAnimation::setTimeLine()
+{
+ QGraphicsItemAnimation animation;
+ QCOMPARE(animation.timeLine(), (QTimeLine *)0);
+
+ QPointer<QTimeLine> line1 = new QTimeLine;
+ animation.setTimeLine(line1);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)line1);
+ animation.setTimeLine(line1);
+ QVERIFY(line1);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)line1);
+
+ animation.setTimeLine(0);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)0);
+ QVERIFY(!line1);
+
+ QTimeLine *line2 = new QTimeLine;
+ animation.setTimeLine(line2);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)line2);
+
+ delete line2;
+ QCOMPARE(animation.timeLine(), (QTimeLine *)0);
+}
+
+QTEST_MAIN(tst_QGraphicsItemAnimation)
+#include "tst_qgraphicsitemanimation.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore b/tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore
new file mode 100644
index 0000000000..b3b27f68a1
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicslayout
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro b/tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro
new file mode 100644
index 0000000000..ea176c98fe
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qlayout.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicslayout.cpp
+DEFINES += QT_USE_USING_NAMESPACE
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
new file mode 100644
index 0000000000..3eac04e4e5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
@@ -0,0 +1,992 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+#include <math.h>
+
+//TESTED_CLASS=QGraphicsLayout
+//TESTED_FILES=
+
+class tst_QGraphicsLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QGraphicsLayout();
+ virtual ~tst_QGraphicsLayout();
+
+private slots:
+ void sizeHints();
+ void compressLayoutRequest();
+ void automaticReparenting();
+ void verifyActivate();
+ void invalidate();
+ void constructors();
+ void alternativeLayoutItems();
+ void ownership();
+};
+
+tst_QGraphicsLayout::tst_QGraphicsLayout()
+{
+}
+
+tst_QGraphicsLayout::~tst_QGraphicsLayout()
+{
+}
+
+void tst_QGraphicsLayout::sizeHints()
+{
+
+ QGraphicsView view;
+ QGraphicsScene scene;
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(window);
+ lout->setContentsMargins(0,0,0,0);
+ QGraphicsWidget *gw = new QGraphicsWidget(window);
+ gw->setMinimumSize(QSizeF(10,10));
+ gw->setPreferredSize(QSizeF(100,100));
+ gw->setMaximumSize(QSizeF(500,500));
+ lout->addItem(gw);
+ QCOMPARE(lout->effectiveSizeHint(Qt::MinimumSize), gw->effectiveSizeHint(Qt::MinimumSize));
+ QCOMPARE(lout->effectiveSizeHint(Qt::PreferredSize), gw->effectiveSizeHint(Qt::PreferredSize));
+ QCOMPARE(lout->effectiveSizeHint(Qt::MaximumSize), gw->effectiveSizeHint(Qt::MaximumSize));
+
+}
+
+enum FunctionType {
+ SetGeometry = 0,
+ Invalidate,
+ NumFunctionTypes
+};
+
+
+
+class TestGraphicsWidget : public QGraphicsWidget {
+public:
+ TestGraphicsWidget(QGraphicsWidget *parent = 0) : QGraphicsWidget(parent)
+ { }
+
+ bool event(QEvent *e) {
+ ++(m_eventCount[int(e->type())]);
+ return QGraphicsWidget::event(e);
+ }
+
+ int eventCount(QEvent::Type type) {
+ return m_eventCount.value(int(type));
+ }
+
+ void clearEventCount() {
+ m_eventCount.clear();
+ }
+
+ void clearCounters() {
+ m_eventCount.clear();
+ functionCount.clear();
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ QGraphicsWidget::setGeometry(rect);
+ ++(functionCount[SetGeometry]);
+ }
+
+ void callUpdateGeometry()
+ {
+ // updateGeometry() is protected
+ QGraphicsWidget::updateGeometry();
+ }
+ QMap<FunctionType, int> functionCount;
+private:
+ QMap<int, int> m_eventCount;
+};
+
+void tst_QGraphicsLayout::compressLayoutRequest()
+{
+ QGraphicsView view;
+ QGraphicsScene scene;
+ TestGraphicsWidget *tw = new TestGraphicsWidget();
+ scene.addItem(tw);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(tw);
+ for (int i = 0; i < 4; ++i) {
+ QGraphicsWidget *gw = new QGraphicsWidget(tw);
+ gw->setPreferredSize(QSizeF(50, 50));
+ lout->addItem(gw);
+ }
+ QApplication::processEvents();
+ QCOMPARE(tw->eventCount(QEvent::LayoutRequest), 1);
+}
+
+void tst_QGraphicsLayout::automaticReparenting()
+{
+ QGraphicsView view;
+ QGraphicsScene scene;
+ {
+ QGraphicsWidget *w = new QGraphicsWidget();
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(w);
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+ scene.addItem(w);
+ QCOMPARE(w1->parentWidget(), w);
+ delete w;
+ }
+ {
+ QGraphicsWidget *w = new QGraphicsWidget();
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(w);
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+ scene.addItem(w);
+ QCOMPARE(w1->parentWidget(), w);
+
+ QGraphicsWidget *ww = new QGraphicsWidget();
+ QGraphicsLinearLayout *l1 = new QGraphicsLinearLayout(ww);
+#if !defined(Q_OS_MAC) && defined(QT_DEBUG)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ l1->addItem(w1);
+ QCOMPARE(w1->parentWidget(), ww);
+ delete w;
+ }
+
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ view.show();
+ QGraphicsLinearLayout *l1 = new QGraphicsLinearLayout();
+ QGraphicsWidget *w1 = new QGraphicsWidget();
+ l1->addItem(w1);
+ QGraphicsWidget *w2 = new QGraphicsWidget();
+ l1->addItem(w2);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(0));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(0));
+ scene.addItem(w1);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(0));
+ window->setLayout(l1);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window));
+
+ // Sublayouts
+ QGraphicsLinearLayout *l2 = new QGraphicsLinearLayout();
+ QGraphicsWidget *w3 = new QGraphicsWidget();
+ l2->addItem(w3);
+ QGraphicsWidget *w4 = new QGraphicsWidget();
+ l2->addItem(w4);
+ QGraphicsLinearLayout *l3 = new QGraphicsLinearLayout();
+ l2->addItem(l3);
+ QGraphicsWidget *window2 = new QGraphicsWidget();
+ scene.addItem(window2);
+ window2->setLayout(l2);
+
+ QCOMPARE(w3->parentItem(), static_cast<QGraphicsItem*>(window2));
+ QCOMPARE(w4->parentItem(), static_cast<QGraphicsItem*>(window2));
+
+ // graphics item with another parent
+ QGraphicsLinearLayout *l5 = new QGraphicsLinearLayout();
+ l5->addItem(w1);
+ l5->addItem(w2);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window));
+ QGraphicsLinearLayout *l4 = new QGraphicsLinearLayout();
+ l4->addItem(l5);
+ QGraphicsWidget *window3 = new QGraphicsWidget();
+ scene.addItem(window3);
+ window3->setLayout(l4);
+
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window3));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window3));
+}
+
+class TestLayout : public QGraphicsLinearLayout
+{
+ public:
+ TestLayout(QGraphicsLayoutItem *parent = 0)
+ : QGraphicsLinearLayout(parent)
+ {
+ setContentsMargins(0,0,0,0);
+ setSpacing(0);
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ ++(functionCount[SetGeometry]);
+ QGraphicsLinearLayout::setGeometry(rect);
+ }
+
+ void invalidate()
+ {
+ ++(functionCount[Invalidate]);
+ QGraphicsLinearLayout::invalidate();
+ }
+
+ void clearCounters() {
+ functionCount.clear();
+ }
+
+ QMap<FunctionType, int> functionCount;
+};
+
+void tst_QGraphicsLayout::verifyActivate()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ TestLayout *lout = new TestLayout(window);
+ QGraphicsWidget *w = new QGraphicsWidget();
+ lout->addItem(w);
+ window->setLayout(lout);
+
+ QCOMPARE(lout->functionCount[SetGeometry], 0);
+ window->setVisible(false);
+ QCOMPARE(lout->functionCount[SetGeometry], 0);
+ window->setVisible(true);
+ // on polish or the first time a widget is shown, the widget is resized.
+ QCOMPARE(lout->functionCount[SetGeometry], 1);
+
+}
+
+static void clearAllCounters(TestGraphicsWidget *widget)
+{
+ if (!widget)
+ return;
+ widget->clearCounters();
+ TestLayout *layout = static_cast<TestLayout *>(widget->layout());
+ if (layout) {
+ layout->clearCounters();
+ for (int i = layout->count() - 1; i >=0; --i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ if (item->isLayout()) {
+ // ### Not used ATM
+ //TestLayout *lay = static_cast<TestLayout*>(static_cast<QGraphicsLayout*>(item));
+ //clearAllCounters(lay);
+ } else {
+ TestGraphicsWidget *wid = static_cast<TestGraphicsWidget *>(item);
+ clearAllCounters(wid);
+ }
+ }
+ }
+}
+
+static void activateAndReset(TestGraphicsWidget *widget)
+{
+ QApplication::sendPostedEvents();
+ QApplication::processEvents();
+ if (widget->layout())
+ widget->layout()->activate();
+ clearAllCounters(widget);
+}
+
+
+void tst_QGraphicsLayout::invalidate()
+{
+ QGraphicsLayout::setInstantInvalidatePropagation(true);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ TestGraphicsWidget *a = new TestGraphicsWidget;
+ a->setData(0, QString("a"));
+ scene.addItem(a);
+ TestLayout *alay = new TestLayout(a);
+ TestGraphicsWidget *b = new TestGraphicsWidget;
+ b->setData(0, QString("b"));
+ alay->addItem(b);
+ TestLayout *blay = new TestLayout(b);
+ TestGraphicsWidget *e = new TestGraphicsWidget;
+ e->setData(0, QString("e"));
+ blay->addItem(e);
+
+
+ TestGraphicsWidget *c = new TestGraphicsWidget;
+ c->setData(0, QString("c"));
+ alay->addItem(c);
+ TestLayout *clay = new TestLayout(c);
+ TestGraphicsWidget *f = new TestGraphicsWidget;
+ f->setData(0, QString("f"));
+ clay->addItem(f);
+
+ TestGraphicsWidget *d = new TestGraphicsWidget;
+ d->setData(0, QString("d"));
+ alay->addItem(d);
+ TestLayout *dlay = new TestLayout(d);
+ TestGraphicsWidget *g = new TestGraphicsWidget;
+ g->setData(0, QString("g"));
+ dlay->addItem(g);
+
+ view.show();
+
+ {
+ clearAllCounters(a);
+
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::processEvents();
+
+ alay->activate();
+ QCOMPARE(alay->isActivated(), true);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), true);
+ }
+
+ {
+ clearAllCounters(a);
+ e->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), false);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), true);
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ // should only invalidate ascendants of e
+ QCOMPARE(blay->functionCount[Invalidate], 1);
+ QCOMPARE(alay->functionCount[Invalidate], 1);
+ // not siblings
+ QCOMPARE(clay->functionCount[Invalidate], 0);
+ QCOMPARE(dlay->functionCount[Invalidate], 0);
+
+ QApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+ }
+
+
+ {
+ activateAndReset(a);
+ f->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // Since nothing really changed, blay and dlay don't need
+ // to be resized.
+ QCOMPARE(blay->functionCount[SetGeometry], 0);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 0);
+
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+
+ QCOMPARE(a->size(), QSizeF(150, 50));
+ }
+
+ {
+ activateAndReset(a);
+ f->setPreferredSize(QSizeF(60,50));
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ QVERIFY(e->size().width() < f->size().width());
+ QVERIFY(g->size().width() < f->size().width());
+ }
+
+ {
+ // resize f so much that it'll force a resize of the top widget
+ // this will currently generate two setGeometry() calls on the child layout
+ // of the top widget.
+ activateAndReset(a);
+ f->setPreferredSize(QSizeF());
+ f->setMinimumSize(QSizeF(200,50));
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+
+ /* well, ideally one call to setGeometry(), but it will currently
+ * get two calls to setGeometry():
+ * 1. The first LayoutRequest will call activate() - that will call
+ * setGeometry() on the layout. This geometry will be based on
+ * the widget geometry which is not correct at this moment.
+ * (it is still 150 wide)
+ * 2. Next, we check if the widget is top level, and then we call
+ * parentWidget->resize(parentWidget->size());
+ * This will be adjusted to be minimum 200 pixels wide.
+ * The new size will then be propagated down to the layout
+ *
+ */
+ QCOMPARE(alay->functionCount[SetGeometry], 2);
+
+ QCOMPARE(b->functionCount[SetGeometry], 2);
+ QCOMPARE(c->functionCount[SetGeometry], 2);
+ QCOMPARE(d->functionCount[SetGeometry], 2);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ QVERIFY(e->size().width() < f->size().width());
+ QVERIFY(g->size().width() < f->size().width());
+ }
+
+ {
+ f->setPreferredSize(QSizeF());
+ f->setMinimumSize(QSizeF());
+ a->adjustSize();
+ activateAndReset(a);
+ // update two different leaf widgets,
+ // eventCount and functionCount should never be >= 2
+ e->callUpdateGeometry();
+ g->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), false);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), false);
+
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 1);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 0);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 0);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ }
+
+ QGraphicsLayout::setInstantInvalidatePropagation(false);
+}
+
+class Layout : public QGraphicsLayout
+{
+public:
+ Layout(QGraphicsLayoutItem *parentItem = 0) : QGraphicsLayout(parentItem) {}
+
+ void setGeometry(const QRectF &rect)
+ {
+ QGraphicsLayout::setGeometry(rect);
+ }
+
+ int count() const {
+ return 0;
+ }
+
+ QGraphicsLayoutItem *itemAt(int index) const {
+ Q_UNUSED(index);
+ return 0;
+ }
+
+ void removeAt(int index)
+ {
+ Q_UNUSED(index);
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ Q_UNUSED(constraint);
+ Q_UNUSED(which);
+ return QSizeF(100,100);
+ }
+
+};
+
+void tst_QGraphicsLayout::constructors()
+{
+ // Strange test, but see the fix that was with this submit
+ QVector<Layout*> layouts;
+ for (int pass = 0; pass < 5; ++pass) {
+ Layout *lay = new Layout();
+ layouts << lay;
+ qreal left, top, right, bottom;
+ lay->getContentsMargins(&left, &top, &right, &bottom);
+ // Test if the style defaults are sane (should always be ints)
+ double intpart;
+ QVERIFY(modf(left, &intpart) == 0.0);
+ QVERIFY(modf(top, &intpart) == 0.0);
+ QVERIFY(modf(right, &intpart) == 0.0);
+ QVERIFY(modf(bottom, &intpart) == 0.0);
+
+ lay->setContentsMargins(1, 2, 4, 8);
+ lay->getContentsMargins(&left, &top, &right, &bottom);
+
+ QCOMPARE(int(left), 1);
+ QCOMPARE(int(top), 2);
+ QCOMPARE(int(right), 4);
+ QCOMPARE(int(bottom), 8);
+ }
+
+ qDeleteAll(layouts);
+}
+
+class AnimatedLayoutItem : public QGraphicsLayoutItem {
+public:
+ AnimatedLayoutItem(QGraphicsRectItem *item)
+ : QGraphicsLayoutItem()
+ {
+ setGraphicsItem(item);
+ }
+
+ void setGeometry(const QRectF &geom);
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ inline QGraphicsRectItem *rectItem() {
+ return static_cast<QGraphicsRectItem *>(graphicsItem());
+ }
+
+ QRectF m_geom;
+private:
+ AnimatedLayoutItem() {}
+};
+
+void AnimatedLayoutItem::setGeometry(const QRectF &geom)
+{
+ QGraphicsLayoutItem::setGeometry(geom);
+}
+
+QSizeF AnimatedLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF & /* constraint */) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+class AnimatedLayout : public QObject, public QGraphicsLinearLayout {
+ Q_OBJECT
+public:
+ AnimatedLayout(QGraphicsWidget *widget) : QGraphicsLinearLayout(widget), m_timeline(500, this)
+ {
+ connect(&m_timeline, SIGNAL(valueChanged(qreal)), this, SLOT(valueChanged(qreal)));
+ }
+
+ void setGeometry(const QRectF &geom) {
+ fromGeoms.clear();
+ toGeoms.clear();
+ for (int i = 0; i < count(); ++i) {
+ fromGeoms << itemAt(i)->geometry();
+ }
+
+ QGraphicsLinearLayout::setGeometry(geom);
+
+ for (int i = 0; i < count(); ++i) {
+ toGeoms << itemAt(i)->geometry();
+ }
+ m_timeline.start();
+ }
+
+private slots:
+ void valueChanged(qreal value) {
+ for (int i = 0; i < fromGeoms.count(); ++i) {
+ QGraphicsLayoutItem *li = itemAt(i);
+ QRectF from = fromGeoms.at(i);
+ QRectF to = toGeoms.at(i);
+
+ QRectF geom(from.topLeft() + (to.topLeft() - from.topLeft()) * value,
+ from.size() + (to.size() - from.size()) * value);
+ static_cast<QGraphicsRectItem*>(li->graphicsItem())->setRect(geom);
+ }
+ }
+private:
+ QTimeLine m_timeline;
+ QVector<QRectF> fromGeoms;
+ QVector<QRectF> toGeoms;
+};
+
+
+void tst_QGraphicsLayout::alternativeLayoutItems()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget;
+ scene.addItem(window);
+ AnimatedLayout *lout = new AnimatedLayout(window);
+ lout->setContentsMargins(0, 0, 0, 0);
+ lout->setSpacing(0);
+
+ QGraphicsRectItem *item1 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li1 = new AnimatedLayoutItem(item1);
+ lout->addItem(li1);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li2 = new AnimatedLayoutItem(item2);
+ lout->addItem(li2);
+
+ QGraphicsRectItem *item3 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li3 = new AnimatedLayoutItem(item3);
+ lout->addItem(li3);
+
+ window->setLayout(lout);
+
+ window->setGeometry(0, 0, 99, 99);
+ view.setSceneRect(QRectF(-10, -10, 110, 110));
+ view.resize(150, 150);
+ view.show();
+
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li1->graphicsItem())->rect(), QRectF( 0, 0, 33, 99));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li2->graphicsItem())->rect(), QRectF(33, 0, 33, 99));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li3->graphicsItem())->rect(), QRectF(66, 0, 33, 99));
+
+ lout->setOrientation(Qt::Vertical);
+
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li1->graphicsItem())->rect(), QRectF(0, 0, 99, 33));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li2->graphicsItem())->rect(), QRectF(0, 33, 99, 33));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li3->graphicsItem())->rect(), QRectF(0, 66, 99, 33));
+
+}
+
+class CustomLayoutItem : public QGraphicsLayoutItem {
+public:
+ CustomLayoutItem(QSet<QGraphicsLayoutItem*> *destructedSet)
+ : QGraphicsLayoutItem()
+ {
+ m_destructedSet = destructedSet;
+ setOwnedByLayout(true);
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ ~CustomLayoutItem() {
+ m_destructedSet->insert(this);
+ }
+private:
+ QSet<QGraphicsLayoutItem*> *m_destructedSet;
+};
+
+QSizeF CustomLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF & /* constraint */) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+class CustomGraphicsWidget : public QGraphicsWidget {
+public:
+ CustomGraphicsWidget(QSet<QGraphicsLayoutItem*> *destructedSet = 0)
+ : QGraphicsWidget()
+ {
+ m_destructedSet = destructedSet;
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * = 0)
+ {
+ const QRect r = option->rect.adjusted(0, 0, -1, -1);
+ painter->drawLine(r.topLeft(), r.bottomRight());
+ painter->drawLine(r.bottomLeft(), r.topRight());
+ painter->drawRect(r);
+ }
+
+ ~CustomGraphicsWidget() {
+ if (m_destructedSet)
+ m_destructedSet->insert(this);
+ }
+private:
+ QSet<QGraphicsLayoutItem*> *m_destructedSet;
+};
+
+QSizeF CustomGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF & /* constraint */) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+static bool compareSets(const QSet<QGraphicsLayoutItem*> &actual, const QSet<QGraphicsLayoutItem*> &expected)
+{
+ if (actual != expected) {
+ qDebug() << "actual:" << actual << "expected:" << expected;
+ return false;
+ }
+ return true;
+}
+
+class CustomLayout : public QGraphicsLayout
+{
+public :
+CustomLayout(QGraphicsLayoutItem *parent)
+ : QGraphicsLayout(parent)
+{
+}
+
+
+~CustomLayout()
+{
+}
+
+int count() const
+{
+ return items.count();
+}
+
+QGraphicsLayoutItem* itemAt(int index) const
+{
+ return items.at(index);
+}
+
+
+void removeAt(int index)
+{
+ items.removeAt(index);
+}
+
+void addItem(QGraphicsLayoutItem *item)
+{
+ insertItem(items.count(), item);
+}
+
+void insertItem(int index, QGraphicsLayoutItem *item)
+{
+ index = qBound(0, index, items.count());
+
+ item->setParentLayoutItem(this);
+
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ updateParentWidget(widget);
+
+
+ if (index == items.count()) {
+ items.append(item);
+ } else {
+ items.insert(index, item);
+ }
+
+ updateGeometry();
+ activate();
+}
+
+void updateParentWidget(QGraphicsWidget *item)
+{
+ QGraphicsLayoutItem *parentItem = parentLayoutItem();
+ while (parentItem && parentItem->isLayout()) {
+ parentItem = parentItem->parentLayoutItem();
+ }
+
+ if (parentItem) {
+ item->setParentItem(static_cast<QGraphicsWidget*>(parentItem));
+ }
+}
+
+QSizeF sizeHint(Qt::SizeHint /* which */, const QSizeF & /* constraint */) const
+{
+ return QSizeF(50,50);
+}
+
+QList<QGraphicsLayoutItem*> items;
+
+};
+
+void tst_QGraphicsLayout::ownership()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+ QSet<QGraphicsLayoutItem*> destructedSet;
+ CustomLayoutItem *li1 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li1);
+ CustomLayoutItem *li2 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li2);
+ CustomLayoutItem *li3 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li3);
+ destructedSet.clear();
+
+ delete lay;
+ QSet<QGraphicsLayoutItem*> expected;
+ expected << li1 << li2 << li3;
+ QVERIFY(compareSets(destructedSet, expected));
+ }
+
+ {
+ QGraphicsWidget *window = new QGraphicsWidget;
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+ QSet<QGraphicsLayoutItem*> destructedSet;
+ CustomGraphicsWidget *li1 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li1);
+ CustomGraphicsWidget *li2 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li2);
+ CustomGraphicsWidget *li3 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li3);
+ window->setLayout(lay);
+ scene.addItem(window);
+
+ destructedSet.clear();
+ window->setLayout(0);
+ QVERIFY(destructedSet.count() == 0);
+ delete window;
+ }
+
+ {
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+
+ CustomGraphicsWidget *li1 = new CustomGraphicsWidget;
+ lay->addItem(li1);
+
+ QGraphicsLinearLayout *li2 = new QGraphicsLinearLayout;
+ CustomGraphicsWidget *li2_1 = new CustomGraphicsWidget;
+ li2->addItem(li2_1);
+ CustomGraphicsWidget *li2_2 = new CustomGraphicsWidget;
+ li2->addItem(li2_2);
+ CustomGraphicsWidget *li2_3 = new CustomGraphicsWidget;
+ li2->addItem(li2_3);
+ lay->addItem(li2);
+
+ CustomGraphicsWidget *li3 = new CustomGraphicsWidget;
+ lay->addItem(li3);
+
+ window->setLayout(lay);
+ scene.addItem(window);
+ view.resize(500, 200);
+ view.show();
+
+ for (int i = li2->count(); i > 0; --i) {
+ QCOMPARE(li2->count(), i);
+ delete li2->itemAt(0);
+ }
+
+ for (int i = lay->count(); i > 0; --i) {
+ QCOMPARE(lay->count(), i);
+ delete lay->itemAt(0);
+ }
+
+ delete window;
+ }
+
+ {
+ QGraphicsWidget *top = new QGraphicsWidget;
+ QGraphicsWidget *w = new QGraphicsWidget;
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ CustomLayout *layout = new CustomLayout(top);
+ layout->addItem(w);
+ layout->addItem(w2);
+ top->setLayout(layout);
+ delete top;
+ //don't crash after that.
+ }
+}
+
+QTEST_MAIN(tst_QGraphicsLayout)
+#include "tst_qgraphicslayout.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore
new file mode 100644
index 0000000000..55a8d18acb
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicslayoutitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro
new file mode 100644
index 0000000000..ed9adf87fd
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicslayoutitem.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp
new file mode 100644
index 0000000000..a8b6c0854e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicslayoutitem.h>
+#include <float.h>
+#include <limits.h>
+
+class tst_QGraphicsLayoutItem : public QObject {
+Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicslayoutitem();
+
+ void contentsRect();
+ void effectiveSizeHint_data();
+ void effectiveSizeHint();
+ void getContentsMargins();
+ void isLayout_data();
+ void isLayout();
+ void maximumSize();
+ void minimumSize();
+ void parentLayoutItem_data();
+ void parentLayoutItem();
+ void preferredSize();
+ void setMaximumSize_data();
+ void setMaximumSize();
+ void setMinimumSize_data();
+ void setMinimumSize();
+ void setPreferredSize_data();
+ void setPreferredSize();
+ void setSizePolicy_data();
+ void setPreferredSize2();
+ void setSizePolicy();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsLayoutItem : public QGraphicsLayoutItem {
+public:
+ SubQGraphicsLayoutItem(QGraphicsLayoutItem *par = 0, bool layout = false)
+ : QGraphicsLayoutItem(par, layout), updateGeometryCalled(0)
+ {}
+
+ // QGraphicsLayoutItem::geometry is a pure virtual function
+ QRectF geometry() const
+ { return QRectF(); }
+
+ // QGraphicsLayoutItem::setGeometry is a pure virtual function
+ void setGeometry(QRectF const& rect)
+ { Q_UNUSED(rect); }
+
+ // QGraphicsLayoutItem::sizeHint is a pure virtual function
+ QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+ { Q_UNUSED(which); Q_UNUSED(constraint); return QSizeF(); }
+
+ void updateGeometry()
+ { updateGeometryCalled++; QGraphicsLayoutItem::updateGeometry(); }
+ int updateGeometryCalled;
+
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsLayoutItem::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsLayoutItem::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsLayoutItem::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsLayoutItem::cleanup()
+{
+}
+
+void tst_QGraphicsLayoutItem::qgraphicslayoutitem()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ layoutItem.contentsRect();
+ layoutItem.effectiveSizeHint(Qt::MinimumSize);
+ layoutItem.geometry();
+ QCOMPARE(layoutItem.isLayout(), false);
+ layoutItem.maximumSize();
+ layoutItem.minimumSize();
+ QCOMPARE(layoutItem.parentLayoutItem(), (QGraphicsLayoutItem*)0);
+ layoutItem.preferredSize();
+ layoutItem.sizePolicy();
+ layoutItem.sizeHint(Qt::MinimumSize);
+}
+
+// QRectF contentsRect() const public
+void tst_QGraphicsLayoutItem::contentsRect()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QRectF f = layoutItem.contentsRect();
+ QCOMPARE(f, QRectF(QPoint(), QSizeF(0, 0)));
+}
+Q_DECLARE_METATYPE(Qt::SizeHint)
+void tst_QGraphicsLayoutItem::effectiveSizeHint_data()
+{
+ QTest::addColumn<Qt::SizeHint>("sizeHint");
+ QTest::addColumn<QSizeF>("constraint");
+ for (int i = 0; i < 15; ++i) {
+ QTestData &data = QTest::newRow(QString("%1").arg(i).toLatin1());
+ switch(i % 5) {
+ case 0: data << Qt::MinimumSize; break;
+ case 1: data << Qt::PreferredSize; break;
+ case 2: data << Qt::MaximumSize; break;
+ case 3: data << Qt::MinimumDescent; break;
+ case 4: data << Qt::NSizeHints; break;
+ }
+ switch(i % 3) {
+ case 0: data << QSizeF(-1, -1); break;
+ case 1: data << QSizeF(0, 0); break;
+ case 2: data << QSizeF(10, 10); break;
+ }
+ }
+}
+
+// QSizeF effectiveSizeHint(Qt::SizeHint which, QSizeF const& constraint = QSize()) const public
+void tst_QGraphicsLayoutItem::effectiveSizeHint()
+{
+ QFETCH(Qt::SizeHint, sizeHint);
+ QFETCH(QSizeF, constraint);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF r = layoutItem.effectiveSizeHint(sizeHint, constraint);
+ if (constraint.width() != -1)
+ QCOMPARE(r.width(), constraint.width());
+ if (constraint.height() != -1)
+ QCOMPARE(r.height(), constraint.height());
+}
+
+// void getContentsMargins(qreal* left, qreal* top, qreal* right, qreal* bottom) const public
+void tst_QGraphicsLayoutItem::getContentsMargins()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ qreal left;
+ qreal top;
+ qreal right;
+ qreal bottom;
+ layoutItem.getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(left, (qreal)0);
+ QCOMPARE(top, (qreal)0);
+ QCOMPARE(right, (qreal)0);
+ QCOMPARE(bottom, (qreal)0);
+}
+
+void tst_QGraphicsLayoutItem::isLayout_data()
+{
+ QTest::addColumn<bool>("isLayout");
+ QTest::newRow("no") << false;
+ QTest::newRow("yes") << true;
+}
+
+// bool isLayout() const public
+void tst_QGraphicsLayoutItem::isLayout()
+{
+ QFETCH(bool, isLayout);
+ SubQGraphicsLayoutItem layoutItem(0, isLayout);
+ QCOMPARE(layoutItem.isLayout(), isLayout);
+}
+
+// QSizeF maximumSize() const public
+void tst_QGraphicsLayoutItem::maximumSize()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QCOMPARE(layoutItem.maximumSize(), QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+ // layoutItem.effectiveSizeHint(Qt::MaximumSize);
+}
+
+// QSizeF minimumSize() const public
+void tst_QGraphicsLayoutItem::minimumSize()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QCOMPARE(layoutItem.minimumSize(), QSizeF(0, 0));
+ // layoutItem.effectiveSizeHint(Qt::MinimumSize);
+}
+
+void tst_QGraphicsLayoutItem::parentLayoutItem_data()
+{
+ QTest::addColumn<bool>("parent");
+ QTest::newRow("no") << false;
+ QTest::newRow("yes") << true;
+}
+
+// QGraphicsLayoutItem* parentLayoutItem() const public
+void tst_QGraphicsLayoutItem::parentLayoutItem()
+{
+ QFETCH(bool, parent);
+ SubQGraphicsLayoutItem parentLayout;
+ SubQGraphicsLayoutItem layoutItem(parent ? &parentLayout : 0);
+ QCOMPARE(layoutItem.parentLayoutItem(), static_cast<QGraphicsLayoutItem*>( parent ? &parentLayout : 0));
+}
+
+// QSizeF preferredSize() const public
+void tst_QGraphicsLayoutItem::preferredSize()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QCOMPARE(layoutItem.preferredSize(), QSizeF(0, 0));
+ // layoutItem.effectiveSizeHint(Qt::PreferredSize));
+}
+
+void tst_QGraphicsLayoutItem::setMaximumSize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QSizeF>("outputSize");
+ QTest::newRow("-1") << QSizeF(-1, -1) << QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ QTest::newRow("0") << QSizeF(0, 0) << QSizeF(0, 0);
+ QTest::newRow("10") << QSizeF(10, 10) << QSizeF(10, 10);
+}
+
+// void setMaximumSize(QSizeF const& size) public
+void tst_QGraphicsLayoutItem::setMaximumSize()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(QSizeF, outputSize);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF oldSize = layoutItem.maximumSize();
+ layoutItem.setMaximumSize(size);
+ if (size.isValid())
+ QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
+ else
+ QVERIFY(!layoutItem.updateGeometryCalled);
+ layoutItem.setMinimumSize(1, 1);
+
+ QVERIFY(layoutItem.maximumSize().width() <= outputSize.width());
+ QVERIFY(layoutItem.maximumSize().height() <= outputSize.height());
+ QVERIFY(layoutItem.minimumSize().width() <= outputSize.width());
+ QVERIFY(layoutItem.minimumSize().height() <= outputSize.height());
+ QVERIFY(layoutItem.preferredSize().width() <= outputSize.width());
+ QVERIFY(layoutItem.preferredSize().height() <= outputSize.height());
+}
+
+void tst_QGraphicsLayoutItem::setMinimumSize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QSizeF>("outputSize");
+ QTest::newRow("-1") << QSizeF(-1, -1) << QSizeF(0, 0);
+ QTest::newRow("0") << QSizeF(0, 0) << QSizeF(0, 0);
+ QTest::newRow("10") << QSizeF(10, 10) << QSizeF(10, 10);
+}
+
+// void setMinimumSize(QSizeF const& size) public
+void tst_QGraphicsLayoutItem::setMinimumSize()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(QSizeF, outputSize);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF oldSize = layoutItem.minimumSize();
+
+ layoutItem.setMinimumSize(size);
+ if (size.isValid()) {
+ QEXPECT_FAIL("0", "updateGeometry() is called when it doesn't have to be.", Continue);
+ QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
+ } else {
+ QVERIFY(!layoutItem.updateGeometryCalled);
+ }
+ layoutItem.setMaximumSize(5, 5);
+ QEXPECT_FAIL("10", "layoutItem.maximumSize().width() < size.width()", Abort);
+ QVERIFY(layoutItem.maximumSize().width() >= size.width());
+ QVERIFY(layoutItem.maximumSize().height() >= size.height());
+ QVERIFY(layoutItem.minimumSize().width() >= size.width());
+ QVERIFY(layoutItem.minimumSize().height() >= size.height());
+ QVERIFY(layoutItem.preferredSize().width() >= size.width());
+ QVERIFY(layoutItem.preferredSize().height() >= size.height());
+}
+
+void tst_QGraphicsLayoutItem::setPreferredSize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("-1") << QSizeF(-1, -1);
+ QTest::newRow("0") << QSizeF(0, 0);
+ QTest::newRow("10") << QSizeF(10, 10);
+}
+
+// void setPreferredSize(QSizeF const& size) public
+void tst_QGraphicsLayoutItem::setPreferredSize()
+{
+ QFETCH(QSizeF, size);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF oldSize = layoutItem.preferredSize();
+ layoutItem.setPreferredSize(size);
+ if (size.isValid())
+ QCOMPARE(layoutItem.preferredSize(), size);
+
+ if (size.isValid()) {
+ QEXPECT_FAIL("0", "updateGeometry() is called when it doesn't have to be.", Continue);
+ QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
+ } else {
+ QVERIFY(!layoutItem.updateGeometryCalled);
+ }
+}
+
+void tst_QGraphicsLayoutItem::setPreferredSize2()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ layoutItem.setPreferredSize(QSizeF(30, -1));
+ QCOMPARE(layoutItem.preferredWidth(), qreal(30));
+}
+
+void tst_QGraphicsLayoutItem::setSizePolicy_data()
+{
+ QTest::addColumn<QSizePolicy>("policy");
+ QTest::newRow("default") << QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, QSizePolicy::DefaultType);
+ QTest::newRow("rand") << QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+}
+
+// void setSizePolicy(QSizePolicy const& policy) public
+void tst_QGraphicsLayoutItem::setSizePolicy()
+{
+ QFETCH(QSizePolicy, policy);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizePolicy defaultPolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType);
+ QCOMPARE(layoutItem.sizePolicy(), defaultPolicy);
+
+ layoutItem.setSizePolicy(policy);
+ QCOMPARE(layoutItem.sizePolicy(), policy);
+ QCOMPARE(layoutItem.updateGeometryCalled, (defaultPolicy == policy) ? 0 : 1);
+}
+
+QTEST_MAIN(tst_QGraphicsLayoutItem)
+#include "tst_qgraphicslayoutitem.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore
new file mode 100644
index 0000000000..95c7dac979
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicslinearlayout
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
new file mode 100644
index 0000000000..1f7ff0cc6e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicslinearlayout.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
new file mode 100644
index 0000000000..873a711127
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
@@ -0,0 +1,1650 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicslinearlayout.h>
+#include <qgraphicsproxywidget.h>
+#include <qgraphicswidget.h>
+#include <qgraphicsscene.h>
+#include <qgraphicsview.h>
+#include <qapplication.h>
+#include <qplastiquestyle.h>
+
+class tst_QGraphicsLinearLayout : public QObject {
+Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicslinearlayout_data();
+ void qgraphicslinearlayout();
+
+ void alignment_data();
+ void alignment();
+ void count_data();
+ void count();
+ void dump_data();
+ void dump();
+ void geometry_data();
+ void geometry();
+ void insertItem_data();
+ void insertItem();
+ void insertStretch_data();
+ void insertStretch();
+ void invalidate_data();
+ void invalidate();
+ void itemAt_data();
+ void itemAt();
+ void itemAt_visualOrder();
+ void orientation_data();
+ void orientation();
+ void removeAt_data();
+ void removeAt();
+ void removeItem_data();
+ void removeItem();
+ void setGeometry_data();
+ void setGeometry();
+ void setSpacing_data();
+ void setSpacing();
+ void setItemSpacing_data();
+ void setItemSpacing();
+ void itemSpacing();
+ void setStretchFactor_data();
+ void setStretchFactor();
+ void testStretch();
+ void defaultStretchFactors_data();
+ void defaultStretchFactors();
+ void sizeHint_data();
+ void sizeHint();
+ void updateGeometry();
+ void layoutDirection();
+ void removeLayout();
+ void avoidRecursionInInsertItem();
+ void styleInfoLeak();
+ void testAlignmentInLargerLayout();
+ void testOffByOneInLargerLayout();
+ void testDefaultAlignment();
+ void combineSizePolicies();
+
+ // Task specific tests
+ void task218400_insertStretchCrash();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsLinearLayout : public QGraphicsLinearLayout {
+public:
+ SubQGraphicsLinearLayout(Qt::Orientation orientation = Qt::Horizontal) : QGraphicsLinearLayout(orientation),
+ graphicsSceneResize(0),
+ layoutRequest(0),
+ layoutDirectionChange(0)
+ { }
+
+ void widgetEvent(QEvent *e)
+ {
+ switch (e->type()) {
+ case QEvent::GraphicsSceneResize:
+ graphicsSceneResize++;
+ break;
+ case QEvent::LayoutRequest:
+ layoutRequest++;
+ break;
+ case QEvent::LayoutDirectionChange:
+ layoutDirectionChange++;
+ break;
+ default:
+ break;
+ }
+
+ QGraphicsLinearLayout::widgetEvent(e);
+ }
+
+ int graphicsSceneResize;
+ int layoutRequest;
+ int layoutDirectionChange;
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsLinearLayout::initTestCase()
+{
+ // since the style will influence the results, we have to ensure
+ // that the tests are run using the same style on all platforms
+#if defined (Q_WS_WINCE)
+ QApplication::setStyle(new QWindowsStyle);
+#else
+ QApplication::setStyle(new QPlastiqueStyle);
+#endif
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsLinearLayout::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsLinearLayout::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsLinearLayout::cleanup()
+{
+}
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0, const QBrush &brush = QBrush()) : QGraphicsWidget(parent){ m_brush = brush;}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->setBrush(m_brush);
+ painter->drawRoundRect(rect());
+ }
+
+ void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
+ m_sizeHints[which] = size;
+ updateGeometry();
+ }
+
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const {
+ if (m_sizeHints[which].isValid()) {
+ return m_sizeHints[which];
+ }
+ return QGraphicsWidget::sizeHint(which, constraint);
+ }
+
+ QSizeF m_sizeHints[Qt::NSizeHints];
+ QBrush m_brush;
+};
+
+
+Q_DECLARE_METATYPE(Qt::Orientation)
+void tst_QGraphicsLinearLayout::qgraphicslinearlayout_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::newRow("vertical") << Qt::Vertical;
+ QTest::newRow("horizontal") << Qt::Horizontal;
+}
+
+void tst_QGraphicsLinearLayout::qgraphicslinearlayout()
+{
+ QFETCH(Qt::Orientation, orientation);
+ SubQGraphicsLinearLayout layout(orientation);
+ QVERIFY(layout.isLayout());
+
+ qApp->processEvents();
+ QCOMPARE(layout.graphicsSceneResize, 0);
+ QCOMPARE(layout.layoutRequest, 0);
+ QCOMPARE(layout.layoutDirectionChange, 0);
+
+ layout.setOrientation(Qt::Vertical);
+ layout.orientation();
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert null item");
+ QCOMPARE(layout.count(), 0);
+ layout.addItem(0);
+ QCOMPARE(layout.count(), 0);
+ layout.addStretch(0);
+ QCOMPARE(layout.count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert null item");
+ layout.insertItem(0, 0);
+ layout.insertStretch(0, 0);
+ layout.removeItem(0);
+ QCOMPARE(layout.count(), 0);
+ layout.setSpacing(0);
+ layout.spacing();
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::setStretchFactor: cannot assign a stretch factor to a null item");
+ layout.setStretchFactor(0, 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::setStretchFactor: cannot return a stretch factor for a null item");
+ layout.stretchFactor(0);
+ layout.setAlignment(0, Qt::AlignHCenter);
+ QCOMPARE(layout.alignment(0), 0);
+ layout.setGeometry(QRectF());
+ layout.geometry();
+ QCOMPARE(layout.count(), 0);
+ layout.invalidate();
+ layout.sizeHint(Qt::MinimumSize, QSizeF());
+}
+
+Q_DECLARE_METATYPE(Qt::AlignmentFlag)
+void tst_QGraphicsLinearLayout::alignment_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<QSize>("newSize");
+ QTest::newRow("h-defaultsize") << Qt::Horizontal << QSize();
+ QTest::newRow("v-defaultsize") << Qt::Vertical << QSize();
+ QTest::newRow("h-300") << Qt::Horizontal << QSize(300,100);
+ QTest::newRow("v-300") << Qt::Vertical << QSize(100, 300);
+}
+
+void tst_QGraphicsLinearLayout::alignment()
+{
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(QSize, newSize);
+
+ //if (alignment == Qt::AlignAbsolute)
+ // QApplication::setLayoutDirection(Qt::RightToLeft);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.setSceneRect(0, 0, 320, 240);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(orientation));
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+
+ static const Qt::Alignment alignmentsToTest[] = {
+ (Qt::Alignment)0,
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter,
+ Qt::AlignTop,
+ Qt::AlignBottom,
+ Qt::AlignVCenter,
+ Qt::AlignCenter,
+ (Qt::Alignment)0,
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter,
+ Qt::AlignTop,
+ Qt::AlignBottom,
+ Qt::AlignVCenter,
+ Qt::AlignCenter
+ };
+
+ int i;
+ bool addWidget = true;
+ for (size_t i = 0; i < sizeof(alignmentsToTest)/sizeof(Qt::Alignment); ++i) {
+ QGraphicsLayoutItem *loutItem;
+ Qt::Alignment align = alignmentsToTest[i];
+ if (!align && i > 0)
+ addWidget = false;
+ if (addWidget)
+ loutItem = new RectWidget(widget, QBrush(Qt::blue));
+ else {
+ SubQGraphicsLinearLayout *lay = new SubQGraphicsLinearLayout(Qt::Vertical);
+ lay->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType);
+ lay->setContentsMargins(0,0,0,0);
+ QGraphicsWidget *w = new RectWidget(widget, QBrush(Qt::red));
+ if (align) {
+ w->setMinimumSize(QSizeF(10,10));
+ w->setMaximumSize(QSizeF(10,10));
+ } else {
+ w->setMinimumSize(QSizeF(50,50));
+ w->setMaximumSize(QSizeF(50,50));
+ }
+ lay->addItem(w);
+ loutItem = lay;
+ }
+ if (align) {
+ loutItem->setMinimumSize(QSizeF(10,10));
+ loutItem->setMaximumSize(QSizeF(10,10));
+ } else {
+ loutItem->setMinimumSize(QSizeF(50,50));
+ loutItem->setMaximumSize(QSizeF(50,50));
+ }
+ layout.addItem(loutItem);
+ layout.setAlignment(loutItem, align);
+
+ }
+ layout.setContentsMargins(0,0,0,0);
+ int spacing = 1;
+ layout.setSpacing(spacing);
+ if (newSize.isValid())
+ widget->resize(newSize);
+ view.show();
+ widget->show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ int x = 0;
+ int y = 0;
+ for (i = 0; i < layout.count(); ++i) {
+ QGraphicsLayoutItem *item = layout.itemAt(i);
+ Qt::Alignment align = layout.alignment(item);
+
+ int w = 10;
+ int h = 10;
+ switch(align) {
+ case Qt::AlignLeft:
+ break;
+ case Qt::AlignRight:
+ if (orientation == Qt::Vertical)
+ x += 40;
+ break;
+ case Qt::AlignHCenter:
+ if (orientation == Qt::Vertical)
+ x += 20;
+ break;
+ case Qt::AlignTop:
+ break;
+ case Qt::AlignBottom:
+ if (orientation == Qt::Horizontal)
+ y += 40;
+ break;
+ case Qt::AlignVCenter:
+ if (orientation == Qt::Horizontal)
+ y += 20;
+ break;
+ case Qt::AlignCenter:
+ if (orientation == Qt::Horizontal)
+ y += 20;
+ else
+ x += 20;
+ break;
+ case 0:
+ w = 50;
+ h = 50;
+ break;
+ default:
+ break;
+ }
+ QRectF expectedGeometry(x, y, w, h);
+ QCOMPARE(item->geometry(), expectedGeometry);
+ if (orientation == Qt::Horizontal) {
+ x += w;
+ y = 0;
+ x += spacing;
+ } else {
+ x = 0;
+ y += h;
+ y += spacing;
+ }
+ }
+}
+
+void tst_QGraphicsLinearLayout::count_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::newRow("0, 0") << 0 << 0;
+ QTest::newRow("0, 5") << 0 << 5;
+ QTest::newRow("5, 0") << 5 << 0;
+ QTest::newRow("5, 5") << 5 << 5;
+}
+
+// int count() const public
+void tst_QGraphicsLinearLayout::count()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+
+ SubQGraphicsLinearLayout layout;
+ QCOMPARE(layout.count(), 0);
+
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ QCOMPARE(layout.count(), itemCount);
+
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+ QCOMPARE(layout.count(), itemCount + layoutCount);
+
+ // see also removeAt()
+}
+
+void tst_QGraphicsLinearLayout::dump_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ for (int i = -1; i < 3; ++i) {
+ QTest::newRow(QString("%1, 0, 0").arg(i).toLatin1()) << 0 << 0;
+ QTest::newRow(QString("%1, 0, 5").arg(i).toLatin1()) << 5 << 5;
+ QTest::newRow(QString("%1, 5, 0").arg(i).toLatin1()) << 5 << 5;
+ QTest::newRow(QString("%1, 5, 5").arg(i).toLatin1()) << 5 << 5;
+ }
+}
+
+// void dump(int indent = 0) const public
+void tst_QGraphicsLinearLayout::dump()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+}
+
+void tst_QGraphicsLinearLayout::geometry_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("itemSpacing");
+ QTest::addColumn<int>("spacing");
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<QRectF>("rect");
+
+ QTest::newRow("null") << 0 << 0 << 0 << 0 << Qt::Horizontal << QRectF();
+
+ QTest::newRow("one item") << 1 << 0 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 10, 10);
+ QTest::newRow("one layout") << 0 << 1 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 10, 10);
+ QTest::newRow("two h") << 1 << 1 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 20, 10);
+ QTest::newRow("two v") << 1 << 1 << 0 << 0 << Qt::Vertical << QRectF(0, 0, 10, 20);
+
+ QTest::newRow("two w/itemspacing") << 1 << 1 << 5 << 0 << Qt::Horizontal << QRectF(0, 0, 25, 10);
+ QTest::newRow("two w/spacing") << 1 << 1 << 8 << 0 << Qt::Horizontal << QRectF(0, 0, 28, 10);
+
+ QTest::newRow("two w/itemspacing v") << 1 << 1 << 5 << 0 << Qt::Vertical << QRectF(0, 0, 10, 25);
+ QTest::newRow("two w/spacing v") << 1 << 1 << 8 << 0 << Qt::Vertical << QRectF(0, 0, 10, 28);
+}
+
+// QRectF geometry() const public
+void tst_QGraphicsLinearLayout::geometry()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, itemSpacing);
+ QFETCH(int, spacing);
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(QRectF, rect);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(orientation));
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+
+ for (int i = 0; i < layout.count(); ++i) {
+ QGraphicsLayoutItem *item = layout.itemAt(i);
+ item->setMaximumSize(10, 10);
+ item->setMinimumSize(10, 10);
+ }
+ layout.setItemSpacing(0, itemSpacing);
+ layout.setSpacing(spacing);
+ layout.setContentsMargins(0, 0, 0, 0);
+
+ widget->show();
+ view.show();
+ QApplication::processEvents();
+ QCOMPARE(layout.geometry(), rect);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::insertItem_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("insertItemAt");
+ QTest::addColumn<bool>("isWidget");
+ for (int i = -1; i < 4; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ QTest::newRow(QString("0, 0, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 0 << i << (bool)j;
+ QTest::newRow(QString("1, 0, %1 %2").arg(i).arg(j).toLatin1()) << 1 << 0 << i << (bool)j;
+ QTest::newRow(QString("0, 1, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 1 << i << (bool)j;
+ QTest::newRow(QString("2, 2, %1 %2").arg(i).arg(j).toLatin1()) << 2 << 2 << i << (bool)j;
+ }
+ }
+}
+
+// void insertItem(int index, QGraphicsLayoutItem* item) public
+void tst_QGraphicsLinearLayout::insertItem()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, insertItemAt);
+ QFETCH(bool, isWidget);
+ if (insertItemAt > layoutCount + itemCount)
+ return;
+
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+
+ QGraphicsLayoutItem *item = 0;
+ if (isWidget)
+ item = new QGraphicsWidget;
+ else
+ item = new SubQGraphicsLinearLayout;
+
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ layout.insertItem(insertItemAt, item);
+ QCOMPARE(layout.count(), itemCount + layoutCount + 1);
+
+ if (insertItemAt >= 0 && (itemCount + layoutCount >= 0)) {
+ QCOMPARE(layout.itemAt(insertItemAt), item);
+ }
+
+ layout.activate();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ if (!isWidget && layout.count() == 1)
+ QCOMPARE(oldSizeHint.width(), newSizeHint.width());
+ else if (itemCount + layoutCount > 0)
+ QVERIFY(oldSizeHint.width() < newSizeHint.width());
+}
+
+void tst_QGraphicsLinearLayout::insertStretch_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("insertItemAt");
+ QTest::addColumn<int>("stretch");
+ for (int i = -1; i < 4; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ QTest::newRow(QString("0, 0, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 0 << i << j;
+ QTest::newRow(QString("1, 0, %1 %2").arg(i).arg(j).toLatin1()) << 1 << 0 << i << j;
+ QTest::newRow(QString("0, 1, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 1 << i << j;
+ QTest::newRow(QString("2, 2, %1 %2").arg(i).arg(j).toLatin1()) << 2 << 2 << i << j;
+ }
+ }
+}
+
+// void insertStretch(int index, int stretch = 1) public
+void tst_QGraphicsLinearLayout::insertStretch()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, insertItemAt);
+ QFETCH(int, stretch);
+ if (insertItemAt > layoutCount + itemCount)
+ return;
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ scene.addItem(widget);
+
+ QList<QGraphicsWidget *>items;
+ QGraphicsWidget *item = 0;
+ for (int i = 0; i < itemCount; ++i) {
+ item = new RectWidget;
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ layout->addItem(item);
+ }
+ for (int i = 0; i < layoutCount; ++i) {
+ item = new RectWidget;
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ SubQGraphicsLinearLayout *sublayout = new SubQGraphicsLinearLayout;
+ sublayout->addItem(item);
+ layout->addItem(sublayout);
+ }
+ widget->setLayout(layout);
+ layout->insertStretch(insertItemAt, stretch);
+ QCOMPARE(layout->count(), itemCount + layoutCount);
+
+ layout->activate();
+ view.show();
+ widget->show();
+
+ int prevStretch = -2;
+ int prevWidth = -2;
+ widget->resize((layoutCount + itemCount) * 25 + 25, 25);
+ for (int i = 0; i < layout->count(); ++i) {
+ if (QGraphicsLayoutItem *item = layout->itemAt(i)) {
+ if (prevStretch != -2) {
+ if (layout->stretchFactor(item) >= prevStretch) {
+ QVERIFY(item->geometry().width() >= prevWidth);
+ } else {
+ QVERIFY(item->geometry().width() < prevWidth);
+ }
+ }
+ prevStretch = layout->stretchFactor(item);
+ prevWidth = (int)(item->geometry().width());
+ }
+ }
+
+ //QTest::qWait(1000);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::invalidate_data()
+{
+ QTest::addColumn<int>("count");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+ QTest::newRow("3") << 3;
+}
+
+// void invalidate() public
+void tst_QGraphicsLinearLayout::invalidate()
+{
+ QFETCH(int, count);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ layout.setContentsMargins(0, 0, 0, 0);
+ view.show();
+ widget->show();
+ //QTest::qWait(1000);
+ QTest::qWaitForWindowShown(&view);
+ qApp->processEvents();
+ layout.layoutRequest = 0;
+
+ layout.setContentsMargins(1, 2, 3, 4);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(layout.layoutRequest, 1);
+
+ layout.setOrientation(Qt::Vertical);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(layout.layoutRequest, 2);
+
+ for (int i = 0; i < count; ++i)
+ layout.invalidate(); // Event is compressed, should only get one layoutrequest
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(layout.layoutRequest, count ? 3 : 2);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::itemAt_data()
+{
+ QTest::addColumn<int>("index");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+}
+
+// QGraphicsLayoutItem* itemAt(int index) const public
+void tst_QGraphicsLinearLayout::itemAt()
+{
+ // see also the insertItem() etc tests
+ QFETCH(int, index);
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < 3; ++i)
+ layout.addItem(new QGraphicsWidget);
+
+ QVERIFY(layout.itemAt(index) != 0);
+}
+
+void tst_QGraphicsLinearLayout::itemAt_visualOrder()
+{
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout;
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ l->addItem(w3);
+
+ QGraphicsWidget *w0 = new QGraphicsWidget;
+ l->insertItem(0, w0);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ l->insertItem(2, w2);
+
+ QCOMPARE(l->itemAt(0), static_cast<QGraphicsLayoutItem*>(w0));
+ QCOMPARE(l->itemAt(1), static_cast<QGraphicsLayoutItem*>(w1));
+ QCOMPARE(l->itemAt(2), static_cast<QGraphicsLayoutItem*>(w2));
+ QCOMPARE(l->itemAt(3), static_cast<QGraphicsLayoutItem*>(w3));
+}
+
+void tst_QGraphicsLinearLayout::orientation_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::newRow("vertical") << Qt::Vertical;
+ QTest::newRow("horizontal") << Qt::Horizontal;
+}
+
+// Qt::Orientation orientation() const public
+void tst_QGraphicsLinearLayout::orientation()
+{
+ QFETCH(Qt::Orientation, orientation);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ Qt::Orientation initialOrientation = (orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(initialOrientation));
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ layout.setContentsMargins(0, 0, 0, 0);
+ int i;
+ int itemCount = 3;
+ for (i = 0; i < itemCount; ++i)
+ layout.addItem(new RectWidget);
+ QCOMPARE(layout.orientation(), initialOrientation);
+ QList<qreal> positions;
+
+ view.show();
+ widget->show();
+ qApp->processEvents();
+
+ for (i = 0; i < itemCount; ++i) {
+ QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
+ qreal pos;
+ if (initialOrientation == Qt::Horizontal)
+ pos = item->pos().x();
+ else
+ pos = item->pos().y();
+ positions.append(pos);
+
+ }
+
+ layout.setOrientation(orientation);
+ QCOMPARE(layout.orientation(), orientation);
+ // important to resize to preferredsize when orientation is switched
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ qApp->processEvents();
+ for (i = 0; i < positions.count(); ++i) {
+ QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
+ if (initialOrientation == Qt::Horizontal)
+ QCOMPARE(item->pos().y(), positions.at(i));
+ else
+ QCOMPARE(item->pos().x(), positions.at(i));
+ }
+}
+
+void tst_QGraphicsLinearLayout::removeAt_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("removeItemAt");
+ QTest::addColumn<Qt::Orientation>("orientation");
+ for (int i = -1; i < 4; ++i) {
+ for (int k = 0; k < 2; ++k) {
+ Qt::Orientation orientation = (k == 0) ? Qt::Vertical : Qt::Horizontal;
+ QTest::newRow(QString("0, 0, %1").arg(i).toLatin1()) << 0 << 0 << i << orientation;
+ QTest::newRow(QString("1, 0, %1").arg(i).toLatin1()) << 1 << 0 << i << orientation;
+ QTest::newRow(QString("0, 1, %1").arg(i).toLatin1()) << 0 << 1 << i << orientation;
+ QTest::newRow(QString("2, 2, %1").arg(i).toLatin1()) << 2 << 2 << i << orientation;
+ }
+ }
+}
+
+// void removeAt(int index) public
+void tst_QGraphicsLinearLayout::removeAt()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, removeItemAt);
+ QFETCH(Qt::Orientation, orientation);
+ if (removeItemAt >= layoutCount + itemCount)
+ return;
+
+ SubQGraphicsLinearLayout layout(orientation);
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+
+ QGraphicsLayoutItem *w = 0;
+ if (removeItemAt >= 0 && removeItemAt < layout.count())
+ w = layout.itemAt(removeItemAt);
+ if (w) {
+ QGraphicsLayoutItem *wParent = w->parentLayoutItem();
+ QCOMPARE(wParent, static_cast<QGraphicsLayoutItem *>(&layout));
+ layout.removeAt(removeItemAt);
+ wParent = w->parentLayoutItem();
+ QCOMPARE(wParent, static_cast<QGraphicsLayoutItem *>(0));
+ delete w;
+ }
+ QCOMPARE(layout.count(), itemCount + layoutCount - (w ? 1 : 0));
+
+ layout.activate();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ if (orientation == Qt::Horizontal)
+ QVERIFY(oldSizeHint.width() >= newSizeHint.width());
+ else
+ QVERIFY(oldSizeHint.height() >= newSizeHint.height());
+}
+
+void tst_QGraphicsLinearLayout::removeItem_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("removeItemAt");
+ for (int i = -1; i < 4; ++i) {
+ QTest::newRow(QString("0, 0, %1").arg(i).toLatin1()) << 0 << 0 << i;
+ QTest::newRow(QString("1, 0, %1").arg(i).toLatin1()) << 1 << 0 << i;
+ QTest::newRow(QString("0, 1, %1").arg(i).toLatin1()) << 0 << 1 << i;
+ QTest::newRow(QString("2, 2, %1").arg(i).toLatin1()) << 2 << 2 << i;
+ }
+}
+
+// void removeItem(QGraphicsLayoutItem* item) public
+void tst_QGraphicsLinearLayout::removeItem()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, removeItemAt);
+ if (removeItemAt >= layoutCount + itemCount)
+ return;
+
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+
+ QGraphicsLayoutItem *w = 0;
+ if (removeItemAt >= 0 && removeItemAt < layout.count())
+ w = layout.itemAt(removeItemAt);
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ if (w) {
+ layout.removeItem(w);
+ delete w;
+ }
+ QCOMPARE(layout.count(), itemCount + layoutCount - (w ? 1 : 0));
+
+ layout.activate();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ QVERIFY(oldSizeHint.width() >= newSizeHint.width());
+}
+
+void tst_QGraphicsLinearLayout::setGeometry_data()
+{
+ QTest::addColumn<QRectF>("rect");
+ QTest::newRow("null") << QRectF();
+ QTest::newRow("small") << QRectF(0, 0, 10, 10);
+}
+
+// void setGeometry(QRectF const& rect) public
+void tst_QGraphicsLinearLayout::setGeometry()
+{
+ QFETCH(QRectF, rect);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ layout.setContentsMargins(0, 0, 0, 0);
+ layout.setMaximumSize(100, 100);
+ view.show();
+ widget->show();
+ QApplication::processEvents();
+ widget->setGeometry(rect);
+ QCOMPARE(layout.geometry(), rect);
+ // see also geometry()
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::setSpacing_data()
+{
+ QTest::addColumn<qreal>("spacing");
+ QTest::newRow("0") << (qreal)0;
+ QTest::newRow("5") << (qreal)5;
+ QTest::newRow("3.3") << (qreal)3.3;
+ QTest::newRow("-4.3") << (qreal)4.3;
+}
+
+// void setSpacing(qreal spacing) public
+void tst_QGraphicsLinearLayout::setSpacing()
+{
+ QFETCH(qreal, spacing);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ layout.setContentsMargins(0, 0, 0, 0);
+
+ qreal oldSpacing = layout.spacing();
+ if (oldSpacing != -1) {
+ for (int i = 0; i < 3; ++i)
+ layout.addItem(new QGraphicsWidget);
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize);
+
+ layout.setSpacing(spacing);
+ QCOMPARE(layout.spacing(), spacing);
+
+ view.show();
+ widget->show();
+ QApplication::processEvents();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize);
+
+ QCOMPARE(oldSizeHint.width() - oldSpacing * 2, newSizeHint.width() - spacing * 2);
+ } else {
+ QSKIP("This style uses non-uniform spacings (layoutSpacingImplementation() is reimplemented)", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::setItemSpacing_data()
+{
+ QTest::addColumn<int>("index");
+ QTest::addColumn<int>("spacing");
+
+ QTest::newRow("0 at 0") << 0 << 0;
+ QTest::newRow("10 at 0") << 0 << 10;
+ QTest::newRow("10 at 1") << 1 << 10;
+ QTest::newRow("10 at the end") << 4 << 10;
+}
+
+void tst_QGraphicsLinearLayout::setItemSpacing()
+{
+ QFETCH(int, index);
+ QFETCH(int, spacing);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ for (int i = 0; i < 5; ++i) {
+ QGraphicsWidget *w = new QGraphicsWidget;
+ layout->addItem(w);
+ }
+ QSizeF oldSizeHint = layout->sizeHint(Qt::PreferredSize);
+ qreal oldSpacing = 0;
+ if (index < layout->count() - 1)
+ oldSpacing = layout->spacing();
+ else
+ spacing = 0;
+
+ layout->setItemSpacing(index, spacing);
+ view.show();
+ QApplication::processEvents();
+ QSizeF newSizeHint = layout->sizeHint(Qt::PreferredSize);
+ if (oldSpacing >= 0) {
+ QCOMPARE(newSizeHint.width() - spacing, oldSizeHint.width() - oldSpacing);
+ } else {
+ QSKIP("This style uses non-uniform spacings (layoutSpacingImplementation() is reimplemented)", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::itemSpacing()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ for (int i = 0; i < 5; ++i) {
+ QGraphicsWidget *w = new QGraphicsWidget;
+ layout->addItem(w);
+ }
+
+ // Check defaults
+ qreal defaultSpacing = layout->spacing();
+ if (defaultSpacing >= 0) {
+ QCOMPARE(layout->itemSpacing(0), defaultSpacing);
+ } else {
+ // all widgets are the same, so the spacing should be uniform
+ QCOMPARE(layout->itemSpacing(0), layout->itemSpacing(1));
+ }
+
+ layout->setItemSpacing(1, 42);
+ QCOMPARE(layout->itemSpacing(1), qreal(42));
+
+ // try to unset
+ layout->setItemSpacing(1, -1);
+ QCOMPARE(layout->itemSpacing(1), defaultSpacing);
+
+ delete widget;
+}
+
+/**
+ * The stretch factors are not applied linearly, but they are used together with both the preferred size, maximum size to form the
+ * internal effective stretch factor.
+ * There is only need to apply stretch factors if the size of the layout is different than the layouts preferred size.
+ * (If the size of the layout is the preferred size, then all items should get their preferred sizes.
+ * However, imagine this use case:
+ * Layout
+ * +----------+----------+----------+
+ * name | A | B | C |
+ * stretch | 1 | 2 | 3 |
+ * sizehints|[5,10,50] |[5,10,50] |[5,10,50] |
+ * +----------+----------+----------+
+ *
+ * layout->resize(120, h)
+ *
+ * In QLayout, C would become 50, B would become 50 and A would get 20. When scaling a layout this would give a jerky feeling, since
+ * the item with the highest stretch factor will first resize. When that has reached its maximum the next candidate for stretch will
+ * resize, and finally, item with the lowest stretch factor will resize.
+ * In QGraphicsLinearLayout we try to scale all items so that they all reach their maximum at the same time. This means that
+ * their relative sizes are not proportional to their stretch factors.
+ */
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(qreal)
+
+void tst_QGraphicsLinearLayout::setStretchFactor_data()
+{
+ QTest::addColumn<qreal>("totalSize");
+ QTest::addColumn<IntList>("stretches");
+
+ QTest::newRow(QString("60 [1,2]").toLatin1()) << qreal(60.0) << (IntList() << 1 << 2);
+ QTest::newRow(QString("60 [1,2,3]").toLatin1()) << qreal(60.0) << (IntList() << 1 << 2 << 3);
+ QTest::newRow(QString("120 [1,2,3,6]").toLatin1()) << qreal(120.0) << (IntList() << 1 << 2 << 3 << 6);
+}
+
+// void setStretchFactor(QGraphicsLayoutItem* item, int stretch) public
+void tst_QGraphicsLinearLayout::setStretchFactor()
+{
+ QFETCH(qreal, totalSize);
+ QFETCH(IntList, stretches);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ layout.setContentsMargins(0, 0, 0, 0);
+ layout.setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+
+ int i;
+ for (i = 0; i < stretches.count(); ++i) {
+ QGraphicsWidget *item = new RectWidget(widget);
+ item->setMinimumSize(5,5);
+ item->setPreferredSize(10,5);
+ item->setMaximumSize(50,5);
+ layout.addItem(item);
+ layout.setStretchFactor(item, stretches.at(i));
+ }
+
+ widget->resize(totalSize, 10);
+ QApplication::processEvents();
+
+ view.show();
+ widget->show();
+
+ qreal firstStretch = -1;
+ qreal firstExtent = -1.;
+ qreal sumExtent = 0;
+ for (i = 0; i < stretches.count(); ++i) {
+ QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
+ qreal extent = item->size().width();
+ qreal stretch = (qreal)stretches.at(i);
+ if (firstStretch != -1 && firstExtent != -1) {
+ // The resulting widths does not correspond linearly to the stretch factors.
+ if (stretch == firstStretch)
+ QCOMPARE(extent, firstExtent);
+ else if (stretch > firstStretch)
+ QVERIFY(extent > firstExtent);
+ else
+ QVERIFY(extent < firstExtent);
+ } else {
+ firstStretch = (qreal)stretch;
+ firstExtent = extent;
+ }
+ sumExtent+= extent;
+ }
+ QCOMPARE(sumExtent, totalSize);
+
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::testStretch()
+{
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ Q_UNUSED(view);
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+
+ scene.addItem(form);
+ form->setMinimumSize(600, 600);
+ form->setMaximumSize(600, 600);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Horizontal, form);
+ QGraphicsWidget *w1 = new RectWidget;
+ w1->setPreferredSize(100,100);
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QGraphicsWidget *w2 = new RectWidget;
+ w2->setPreferredSize(200,200);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addItem(w1);
+ layout->addStretch(2);
+ layout->addItem(w2);
+ QCOMPARE(layout->count(), 2);
+ QVERIFY(layout->itemAt(0) == w1);
+ QVERIFY(layout->itemAt(1) == w2);
+ layout->activate();
+
+ //view->setSceneRect(-50, -50, 800, 800);
+ //view->show();
+ //QTest::qWaitForWindowShown(view);
+ //QTest::qWait(5000);
+ QCOMPARE(form->geometry().size(), QSizeF(600,600));
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(400, 0, 200, 200));
+}
+
+void tst_QGraphicsLinearLayout::defaultStretchFactors_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<IntList>("preferredSizeHints");
+ QTest::addColumn<IntList>("stretches");
+ QTest::addColumn<IntList>("ignoreFlag");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<IntList>("expectedSizes");
+
+ QTest::newRow("hor") << Qt::Horizontal << 3
+ << (IntList() << 20 << 40 << 60)
+ << (IntList())
+ << (IntList())
+ << QSizeF()
+ << (IntList() << 20 << 40 << 60);
+
+ QTest::newRow("ver") << Qt::Vertical << 3
+ << (IntList() << 20 << 40 << 60)
+ << (IntList())
+ << (IntList())
+ << QSizeF()
+ << (IntList() << 20 << 40 << 60);
+
+ QTest::newRow("hor,ignore123") << Qt::Horizontal << 3
+ << (IntList() << 20 << 40 << 60)
+ << (IntList())
+ << (IntList() << 1 << 1 << 1)
+ << QSizeF()
+ << (IntList() << 0 << 0 << 0);
+
+ QTest::newRow("hor,ignore23") << Qt::Horizontal << 3
+ << (IntList() << 10 << 10 << 10)
+ << (IntList())
+ << (IntList() << 0 << 1 << 1)
+ << QSizeF(200, 50)
+ << (IntList()); //### stretches are not linear.
+
+ QTest::newRow("hor,ignore2") << Qt::Horizontal << 3
+ << (IntList() << 10 << 10 << 10)
+ << (IntList())
+ << (IntList() << 0 << 1 << 0)
+ << QSizeF()
+ << (IntList() << 10 << 0 << 10);
+
+}
+
+void tst_QGraphicsLinearLayout::defaultStretchFactors()
+{
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(int, count);
+ QFETCH(IntList, preferredSizeHints);
+ QFETCH(IntList, stretches);
+ QFETCH(IntList, ignoreFlag);
+ QFETCH(QSizeF, newSize);
+ QFETCH(IntList, expectedSizes);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout(orientation);
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < count; ++i) {
+ RectWidget *item = new RectWidget(widget);
+ layout->addItem(item);
+ if (preferredSizeHints.value(i, -1) >= 0) {
+ item->setSizeHint(Qt::PreferredSize, QSizeF(preferredSizeHints.at(i), preferredSizeHints.at(i)));
+ }
+ if (stretches.value(i, -1) >= 0) {
+ layout->setStretchFactor(item, stretches.at(i));
+ }
+ if (ignoreFlag.value(i, 0) != 0) {
+ QSizePolicy sp = item->sizePolicy();
+ if (orientation == Qt::Horizontal)
+ sp.setHorizontalPolicy(QSizePolicy::Policy(sp.horizontalPolicy() | QSizePolicy::IgnoreFlag));
+ else
+ sp.setVerticalPolicy(QSizePolicy::Policy(sp.verticalPolicy() | QSizePolicy::IgnoreFlag));
+ item->setSizePolicy(sp);
+ }
+ }
+
+ QApplication::processEvents();
+
+ widget->show();
+ view.show();
+ view.resize(400,300);
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::processEvents();
+ for (i = 0; i < count; ++i) {
+ QSizeF itemSize = layout->itemAt(i)->geometry().size();
+ if (orientation == Qt::Vertical)
+ itemSize.transpose();
+ if (i < expectedSizes.count())
+ QCOMPARE(itemSize.width(), qreal(expectedSizes.at(i)));
+ }
+
+ delete widget;
+}
+
+Q_DECLARE_METATYPE(Qt::SizeHint)
+void tst_QGraphicsLinearLayout::sizeHint_data()
+{
+ QTest::addColumn<Qt::SizeHint>("which");
+ QTest::addColumn<QSizeF>("constraint");
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<qreal>("layoutMargin");
+ QTest::addColumn<QSizeF>("sizeHint");
+
+ QTest::newRow("minimumSize") << Qt::MinimumSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(30, 10);
+ QTest::newRow("preferredSize") << Qt::PreferredSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(75, 25);
+ QTest::newRow("maximumSize") << Qt::MaximumSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(150, 50);
+ QTest::newRow("minimumSize, spacing=3") << Qt::MinimumSize << QSizeF() << qreal(3.0) << qreal(0.0) << QSizeF(30 + 2*3, 10);
+ QTest::newRow("minimumSize, spacing=3, layoutMargin=10") << Qt::MinimumSize << QSizeF() << qreal(3.0) << qreal(10.0) << QSizeF(30 + 2*3 + 2*10, 10 + 2*10);
+ QTest::newRow("minimumSize, spacing=0, layoutMargin=7") << Qt::MinimumSize << QSizeF() << qreal(0.0) << qreal(7.0) << QSizeF(30 + 0 + 2*7, 10 + 2*7);
+}
+
+// QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint) const public
+void tst_QGraphicsLinearLayout::sizeHint()
+{
+ QFETCH(Qt::SizeHint, which);
+ QFETCH(QSizeF, constraint);
+ QFETCH(qreal, spacing);
+ QFETCH(qreal, layoutMargin);
+ QFETCH(QSizeF, sizeHint);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ layout.setContentsMargins(layoutMargin, layoutMargin, layoutMargin, layoutMargin);
+ layout.setSpacing(spacing);
+ for (int i = 0; i < 3; ++i) {
+ QGraphicsWidget *item = new QGraphicsWidget(widget);
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ layout.addItem(item);
+ }
+ QApplication::processEvents();
+ QCOMPARE(layout.sizeHint(which, constraint), sizeHint);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::updateGeometry()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(100, 40);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ layout->addItem(w1);
+ scene.addItem(window);
+ window->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ QCOMPARE(w1->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout));
+ QCOMPARE(layout->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(window));
+
+ view.show();
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(100, 50));
+ w1->setMinimumSize(110, 60);
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(110, 60));
+ QApplication::processEvents();
+
+ {
+ delete window;
+ window = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout2a = new SubQGraphicsLinearLayout;
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(110, 50);
+ layout2a->addItem(w1);
+ SubQGraphicsLinearLayout *layout2 = new SubQGraphicsLinearLayout;
+ layout2->addItem(layout2a);
+ layout2->setContentsMargins(1, 1, 1, 1);
+ layout2a->setContentsMargins(1, 1, 1, 1);
+ window->setLayout(layout2);
+ QApplication::processEvents();
+ QCOMPARE(w1->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout2a));
+ QCOMPARE(layout2a->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout2));
+ QCOMPARE(layout2->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(window));
+ QCOMPARE(window->size().toSize(), QSize(114, 54));
+ QApplication::processEvents();
+ w1->setMinimumSize(120, 60);
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(124, 64));
+ }
+
+ {
+ delete window;
+ window = new QGraphicsWidget(0, Qt::Window);
+ scene.addItem(window);
+ window->show();
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(100, 50);
+ SubQGraphicsLinearLayout *layout2a = new SubQGraphicsLinearLayout;
+ layout2a->addItem(w1);
+ SubQGraphicsLinearLayout *layout2 = new SubQGraphicsLinearLayout;
+ layout2->addItem(layout2a);
+ layout2a->setContentsMargins(1, 1, 1, 1);
+ window->setLayout(layout2);
+ QApplication::processEvents();
+ qreal left, top, right, bottom;
+ layout2->getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(window->size().toSize(), QSize(102 +left + right, 52 + top + bottom));
+ }
+
+ {
+ delete window;
+ window = new QGraphicsWidget(0, Qt::Window);
+ scene.addItem(window);
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(100, 50);
+ window->setLayout(0);
+ SubQGraphicsLinearLayout *layout2a = new SubQGraphicsLinearLayout;
+ layout2a->addItem(w1);
+ SubQGraphicsLinearLayout *layout2 = new SubQGraphicsLinearLayout;
+ layout2->addItem(layout2a);
+ window->resize(200, 80);
+ window->setLayout(layout2);
+ window->show();
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(200, 80));
+ }
+
+}
+
+void tst_QGraphicsLinearLayout::layoutDirection()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->setContentsMargins(1, 2, 3, 4);
+ layout->setSpacing(6);
+
+ RectWidget *w1 = new RectWidget;
+ w1->setPreferredSize(20, 20);
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->addItem(w1);
+ RectWidget *w2 = new RectWidget;
+ w2->setPreferredSize(20, 20);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->addItem(w2);
+
+ scene.addItem(window);
+ window->setLayout(layout);
+ view.show();
+ window->resize(50, 20);
+ window->setLayoutDirection(Qt::LeftToRight);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().left(), 1.0);
+ QCOMPARE(w1->geometry().right(), 21.0);
+ QCOMPARE(w2->geometry().left(), 27.0);
+ QCOMPARE(w2->geometry().right(), 47.0);
+
+ window->setLayoutDirection(Qt::RightToLeft);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().right(), 49.0);
+ QCOMPARE(w1->geometry().left(), 29.0);
+ QCOMPARE(w2->geometry().right(), 23.0);
+ QCOMPARE(w2->geometry().left(), 3.0);
+
+ delete window;
+}
+
+void tst_QGraphicsLinearLayout::removeLayout()
+{
+ QGraphicsScene scene;
+ RectWidget *textEdit = new RectWidget;
+ RectWidget *pushButton = new RectWidget;
+ scene.addItem(textEdit);
+ scene.addItem(pushButton);
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->addItem(textEdit);
+ layout->addItem(pushButton);
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout(layout);
+ scene.addItem(form);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(20);
+
+ QRectF r1 = textEdit->geometry();
+ QRectF r2 = pushButton->geometry();
+ form->setLayout(0);
+ //documentation of QGraphicsWidget::setLayout:
+ //If layout is 0, the widget is left without a layout. Existing subwidgets' geometries will remain unaffected.
+ QCOMPARE(textEdit->geometry(), r1);
+ QCOMPARE(pushButton->geometry(), r2);
+}
+
+void tst_QGraphicsLinearLayout::avoidRecursionInInsertItem()
+{
+ QGraphicsWidget window(0, Qt::Window);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(&window);
+ QCOMPARE(layout->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert itself");
+ layout->insertItem(0, layout);
+ QCOMPARE(layout->count(), 0);
+}
+
+void tst_QGraphicsLinearLayout::styleInfoLeak()
+{
+ QGraphicsLinearLayout layout;
+ layout.spacing();
+}
+
+void tst_QGraphicsLinearLayout::task218400_insertStretchCrash()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsWidget *a = scene->addWidget(new QWidget);
+ QGraphicsWidget *b = scene->addWidget(new QWidget);
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->addItem(a);
+ layout->addItem(b);
+ layout->insertStretch(0); // inserts gap in item grid in the layout engine
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout(layout); // crash
+}
+
+void tst_QGraphicsLinearLayout::testAlignmentInLargerLayout()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsWidget *form = new QGraphicsWidget;
+ scene->addItem(form);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, form);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0,0,0,0);
+
+ QGraphicsWidget *a = new QGraphicsWidget;
+ a->setMaximumSize(100,100);
+ layout->addItem(a);
+
+ QCOMPARE(form->maximumSize(), QSizeF(100,100));
+ QCOMPARE(layout->maximumSize(), QSizeF(100,100));
+ layout->setMinimumSize(QSizeF(200,200));
+ layout->setMaximumSize(QSizeF(200,200));
+
+ layout->setAlignment(a, Qt::AlignCenter);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(50,50,100,100));
+
+ layout->setAlignment(a, Qt::AlignRight | Qt::AlignBottom);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(100,100,100,100));
+
+ layout->setAlignment(a, Qt::AlignHCenter | Qt::AlignTop);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(50,0,100,100));
+
+ QGraphicsWidget *b = new QGraphicsWidget;
+ b->setMaximumSize(100,100);
+ layout->addItem(b);
+
+ layout->setAlignment(a, Qt::AlignCenter);
+ layout->setAlignment(b, Qt::AlignCenter);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(50,0,100,100));
+ QCOMPARE(b->geometry(), QRectF(50,100,100,100));
+
+ layout->setAlignment(a, Qt::AlignRight | Qt::AlignBottom);
+ layout->setAlignment(b, Qt::AlignLeft | Qt::AlignTop);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(100,0,100,100));
+ QCOMPARE(b->geometry(), QRectF(0,100,100,100));
+}
+
+void tst_QGraphicsLinearLayout::testOffByOneInLargerLayout() {
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsWidget *form = new QGraphicsWidget;
+ scene->addItem(form);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, form);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0,0,0,0);
+
+ QGraphicsWidget *a = new QGraphicsWidget;
+ QGraphicsWidget *b = new QGraphicsWidget;
+ a->setMaximumSize(100,100);
+ b->setMaximumSize(100,100);
+ layout->addItem(a);
+ layout->addItem(b);
+
+ layout->setAlignment(a, Qt::AlignRight | Qt::AlignBottom);
+ layout->setAlignment(b, Qt::AlignLeft | Qt::AlignTop);
+ layout->setMinimumSize(QSizeF(101,201));
+ layout->setMaximumSize(QSizeF(101,201));
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(1,0.5,100,100));
+ QCOMPARE(b->geometry(), QRectF(0,100.5,100,100));
+
+ layout->setMinimumSize(QSizeF(100,200));
+ layout->setMaximumSize(QSizeF(100,200));
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(b->geometry(), QRectF(0,100,100,100));
+
+ layout->setMinimumSize(QSizeF(99,199));
+ layout->setMaximumSize(QSizeF(99,199));
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(0,0,99,99.5));
+ QCOMPARE(b->geometry(), QRectF(0,99.5,99,99.5));
+}
+void tst_QGraphicsLinearLayout::testDefaultAlignment()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w = new QGraphicsWidget;
+ w->setMinimumSize(50,50);
+ w->setMaximumSize(50,50);
+ layout->addItem(w);
+
+ //Default alignment should be to the top-left
+ QCOMPARE(layout->alignment(w), 0);
+
+ //First, check by forcing the layout to be bigger
+ layout->setMinimumSize(100,100);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ layout->setMinimumSize(-1,-1);
+
+ //Second, check by adding a larger item in the column
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(100,100);
+ w2->setMaximumSize(100,100);
+ layout->addItem(w2);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,150));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ QCOMPARE(w2->geometry(), QRectF(0,50,100,100));
+}
+
+void tst_QGraphicsLinearLayout::combineSizePolicies()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Horizontal, widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMaximumSize(200,200);
+ w1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ layout->addItem(w1);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setPreferredSize(50,50);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->addItem(w2);
+ QCOMPARE(layout->maximumHeight(), qreal(200));
+
+ // now remove the fixed vertical size policy, and set instead the maximum height to 50
+ // this should in effect give the same maximumHeight
+ w2->setMaximumHeight(50);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ QCOMPARE(layout->maximumHeight(), qreal(200));
+}
+
+QTEST_MAIN(tst_QGraphicsLinearLayout)
+#include "tst_qgraphicslinearlayout.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro b/tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro
new file mode 100644
index 0000000000..5232ec8372
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += widgets
+QT += core-private
+
+SOURCES += tst_qgraphicsobject.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp b/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp
new file mode 100644
index 0000000000..85e36b74b2
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsitem.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qstyleoption.h>
+#include <private/qobject_p.h>
+
+class tst_QGraphicsObject : public QObject {
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void pos();
+ void x();
+ void y();
+ void z();
+ void opacity();
+ void enabled();
+ void visible();
+ void deleted();
+};
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsObject::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsObject::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsObject::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsObject::cleanup()
+{
+}
+
+
+class MyGraphicsObject : public QGraphicsObject
+{
+public:
+ MyGraphicsObject() : QGraphicsObject() {}
+ virtual QRectF boundingRect() const { return QRectF(); }
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+};
+
+void tst_QGraphicsObject::pos()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setPos(10, 10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ QVERIFY(object.pos() == QPointF(10,10));
+
+ object.setPos(10, 10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ object.setProperty("pos", QPointF(0, 0));
+ QCOMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("pos") == QPointF(0,0));
+
+ object.setProperty("pos", QPointF(10, 0));
+ QCOMPARE(xSpy.count(), 3);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("pos") == QPointF(10,0));
+
+ object.setProperty("pos", QPointF(10, 10));
+ QCOMPARE(xSpy.count(), 3);
+ QCOMPARE(ySpy.count(), 3);
+ QVERIFY(object.property("pos") == QPointF(10, 10));
+}
+
+void tst_QGraphicsObject::x()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setX(10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 0);
+
+ QVERIFY(object.pos() == QPointF(10, 0));
+ QVERIFY(object.x() == 10);
+
+ object.setX(10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 0);
+
+ object.setProperty("x", 0);
+ QCOMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 0);
+ QVERIFY(object.property("x") == 0);
+}
+
+void tst_QGraphicsObject::y()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setY(10);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 1);
+
+ QVERIFY(object.pos() == QPointF(0, 10));
+ QVERIFY(object.y() == 10);
+
+ object.setY(10);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 1);
+
+ object.setProperty("y", 0);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("y") == 0);
+}
+
+void tst_QGraphicsObject::z()
+{
+ MyGraphicsObject object;
+ QSignalSpy zSpy(&object, SIGNAL(zChanged()));
+ QVERIFY(object.zValue() == 0);
+ object.setZValue(10);
+ QCOMPARE(zSpy.count(), 1);
+
+ QVERIFY(object.zValue() == 10);
+
+ object.setZValue(10);
+ QCOMPARE(zSpy.count(), 1);
+
+ object.setProperty("z", 0);
+ QCOMPARE(zSpy.count(), 2);
+ QVERIFY(object.property("z") == 0);
+}
+
+void tst_QGraphicsObject::opacity()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(opacityChanged()));
+ QVERIFY(object.opacity() == 1.);
+ object.setOpacity(0);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.opacity() == 0.);
+
+ object.setOpacity(0);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("opacity", .5);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("opacity") == .5);
+}
+
+void tst_QGraphicsObject::enabled()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(enabledChanged()));
+ QVERIFY(object.isEnabled() == true);
+ object.setEnabled(false);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.isEnabled() == false);
+
+ object.setEnabled(false);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("enabled", true);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("enabled") == true);
+}
+
+void tst_QGraphicsObject::visible()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(visibleChanged()));
+ QVERIFY(object.isVisible() == true);
+ object.setVisible(false);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.isVisible() == false);
+
+ object.setVisible(false);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("visible", true);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("visible") == true);
+}
+
+class DeleteTester : public QGraphicsObject
+{
+public:
+ DeleteTester(bool *w, bool *pw, QGraphicsItem *parent = 0)
+ : QGraphicsObject(parent), wasDeleted(w), parentWasDeleted(pw)
+ { }
+
+ ~DeleteTester()
+ {
+ *wasDeleted = QObjectPrivate::get(this)->wasDeleted;
+ if (QGraphicsItem *p = parentItem()) {
+ if (QGraphicsObject *o = p->toGraphicsObject())
+ *parentWasDeleted = QObjectPrivate::get(o)->wasDeleted;
+ }
+ }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0)
+ { }
+ QRectF boundingRect() const
+ { return QRectF(); }
+
+ bool *wasDeleted;
+ bool *parentWasDeleted;
+};
+
+void tst_QGraphicsObject::deleted()
+{
+ bool item1_parentWasDeleted = false;
+ bool item1_wasDeleted = false;
+ bool item2_parentWasDeleted = false;
+ bool item2_wasDeleted = false;
+ DeleteTester *item1 = new DeleteTester(&item1_wasDeleted, &item1_parentWasDeleted);
+ DeleteTester *item2 = new DeleteTester(&item2_wasDeleted, &item2_parentWasDeleted, item1);
+ Q_UNUSED(item2);
+ delete item1;
+
+ QVERIFY(!item1_wasDeleted); // destructor not called yet
+ QVERIFY(!item1_parentWasDeleted); // no parent
+ QVERIFY(!item2_wasDeleted); // destructor not called yet
+ QVERIFY(item2_parentWasDeleted);
+}
+
+QTEST_MAIN(tst_QGraphicsObject)
+#include "tst_qgraphicsobject.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore
new file mode 100644
index 0000000000..1e92419fd0
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicspixmapitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro
new file mode 100644
index 0000000000..6b1ad34057
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicspixmapitem.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp
new file mode 100644
index 0000000000..b2dccb0b09
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsscene.h>
+#include <qgraphicsitem.h>
+
+class tst_QGraphicsPixmapItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicspixmapitem_data();
+ void qgraphicspixmapitem();
+ void boundingRect_data();
+ void boundingRect();
+ void contains_data();
+ void contains();
+ void isObscuredBy_data();
+ void isObscuredBy();
+ void offset_data();
+ void offset();
+ void opaqueArea_data();
+ void opaqueArea();
+ void pixmap_data();
+ void pixmap();
+ void setPixmap_data();
+ void setPixmap();
+ void setShapeMode_data();
+ void setShapeMode();
+ void setTransformationMode_data();
+ void setTransformationMode();
+ void shape_data();
+ void shape();
+ void extension_data();
+ void extension();
+ void setExtension_data();
+ void setExtension();
+ void supportsExtension_data();
+ void supportsExtension();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsPixmapItem : public QGraphicsPixmapItem
+{
+public:
+ enum Extension {
+ UserExtension = QGraphicsItem::UserExtension
+ };
+ SubQGraphicsPixmapItem(QGraphicsItem *parent = 0) : QGraphicsPixmapItem(parent)
+ {
+ }
+
+ SubQGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0) : QGraphicsPixmapItem(pixmap, parent)
+ {
+ }
+
+ QVariant call_extension(QVariant const& variant) const
+ { return SubQGraphicsPixmapItem::extension(variant); }
+
+ void call_setExtension(Extension extension, QVariant const& variant)
+ { return SubQGraphicsPixmapItem::setExtension((QGraphicsItem::Extension)extension, variant); }
+
+ bool call_supportsExtension(Extension extension) const
+ { return SubQGraphicsPixmapItem::supportsExtension((QGraphicsItem::Extension)extension); }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsPixmapItem::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsPixmapItem::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsPixmapItem::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsPixmapItem::cleanup()
+{
+}
+
+void tst_QGraphicsPixmapItem::qgraphicspixmapitem_data()
+{
+}
+
+void tst_QGraphicsPixmapItem::qgraphicspixmapitem()
+{
+ SubQGraphicsPixmapItem item;
+ item.boundingRect();
+ item.contains(QPoint());
+ item.isObscuredBy(0);
+ item.opaqueArea();
+ //item.paint();
+ QCOMPARE(item.offset(), QPointF());
+ QCOMPARE(item.pixmap(), QPixmap());
+ QCOMPARE(item.shapeMode(), QGraphicsPixmapItem::MaskShape);
+ QCOMPARE(item.transformationMode(), Qt::FastTransformation);
+ item.setOffset(0, 0);
+ item.setOffset(QPointF(0, 0));
+ item.setPixmap(QPixmap());
+ item.setShapeMode(QGraphicsPixmapItem::MaskShape);
+ item.setTransformationMode(Qt::FastTransformation);
+ item.shape();
+ item.type();
+ item.call_extension(QVariant());
+ item.call_setExtension(SubQGraphicsPixmapItem::UserExtension, QVariant());
+ item.call_supportsExtension(SubQGraphicsPixmapItem::UserExtension);
+}
+
+void tst_QGraphicsPixmapItem::boundingRect_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QRectF>("boundingRect");
+ QTest::newRow("null") << QPixmap() << QRectF();
+ QTest::newRow("10x10") << QPixmap(10, 10) << QRectF(0, 0, 10, 10);
+}
+
+// public QRectF boundingRect() const
+void tst_QGraphicsPixmapItem::boundingRect()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QRectF, boundingRect);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.boundingRect(), boundingRect);
+}
+
+void tst_QGraphicsPixmapItem::contains_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<bool>("contains");
+ QTest::newRow("null") << QPixmap() << QPointF() << false;
+ QTest::newRow("10x10, 100x100") << QPixmap(10, 10) << QPointF(100, 100) << false;
+ QTest::newRow("10x10, 5x5") << QPixmap(10, 10) << QPointF(5, 5) << true;
+ QTest::newRow("border-1") << QPixmap(10, 10) << QPointF(10.5, 10.5) << false;
+ QTest::newRow("border-2") << QPixmap(10, 10) << QPointF(-0.5, -0.5) << false;
+}
+
+// public bool contains(QPointF const& point) const
+void tst_QGraphicsPixmapItem::contains()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPointF, point);
+ QFETCH(bool, contains);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.contains(point), contains);
+}
+
+void tst_QGraphicsPixmapItem::isObscuredBy_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPixmap>("otherPixmap");
+ QTest::addColumn<bool>("isObscuredBy");
+ QTest::newRow("null") << QPixmap() << QPixmap() << false;
+ QTest::newRow("(10, 10) vs. (5, 5)") << QPixmap(10, 10) << QPixmap(5, 5) << false;
+ QTest::newRow("(5, 5) vs. (10, 10)") << QPixmap(5, 5) << QPixmap(10, 10) << true;
+ QTest::newRow("(10, 10) vs. (10, 10)") << QPixmap(10, 10) << QPixmap(10, 10) << false;
+ QTest::newRow("(9, 9) vs. (10, 10)") << QPixmap(8, 8) << QPixmap(10, 10) << true;
+ QTest::newRow("(10, 10) vs. (9, 9)") << QPixmap(10, 10) << QPixmap(8, 8) << false;
+}
+
+// public bool isObscuredBy(QGraphicsItem const* item) const
+void tst_QGraphicsPixmapItem::isObscuredBy()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPixmap, otherPixmap);
+ QFETCH(bool, isObscuredBy);
+ pixmap.fill();
+ otherPixmap.fill();
+
+ SubQGraphicsPixmapItem *item = new SubQGraphicsPixmapItem(pixmap);
+ SubQGraphicsPixmapItem *otherItem = new SubQGraphicsPixmapItem(otherPixmap);
+
+ item->setOffset(-pixmap.width() / 2.0, -pixmap.height() / 2.0);
+ otherItem->setOffset(-otherPixmap.width() / 2.0, -otherPixmap.height() / 2.0);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+ scene.addItem(otherItem);
+ otherItem->setZValue(1);
+
+ QCOMPARE(item->isObscuredBy(otherItem), isObscuredBy);
+}
+
+void tst_QGraphicsPixmapItem::offset_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPointF>("offset");
+ QTest::newRow("null") << QPixmap() << QPointF();
+ QTest::newRow("10x10, 1x1") << QPixmap(10, 10) << QPointF(1, 1);
+}
+
+// public QPointF offset() const
+void tst_QGraphicsPixmapItem::offset()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPointF, offset);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ item.setOffset(offset);
+ QCOMPARE(item.offset(), offset);
+
+ // ### test actual painting and compare pixmap with offseted one?
+}
+
+Q_DECLARE_METATYPE(QPainterPath)
+void tst_QGraphicsPixmapItem::opaqueArea_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPainterPath>("opaqueArea");
+ QTest::newRow("null") << QPixmap() << QPainterPath();
+ // Currently QGraphicsPixmapItem just calls QGraphicsItem test there
+}
+
+// public QPainterPath opaqueArea() const
+void tst_QGraphicsPixmapItem::opaqueArea()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPainterPath, opaqueArea);
+
+ SubQGraphicsPixmapItem item;
+ QCOMPARE(item.opaqueArea(), opaqueArea);
+}
+
+void tst_QGraphicsPixmapItem::pixmap_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::newRow("null") << QPixmap();
+ QTest::newRow("10x10") << QPixmap(10, 10);
+}
+
+// public QPixmap pixmap() const
+void tst_QGraphicsPixmapItem::pixmap()
+{
+ QFETCH(QPixmap, pixmap);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.pixmap(), pixmap);
+}
+
+void tst_QGraphicsPixmapItem::setPixmap_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::newRow("null") << QPixmap();
+ QTest::newRow("10x10") << QPixmap(10, 10);
+}
+
+// public void setPixmap(QPixmap const& pixmap)
+void tst_QGraphicsPixmapItem::setPixmap()
+{
+ QFETCH(QPixmap, pixmap);
+
+ SubQGraphicsPixmapItem item;
+ item.setPixmap(pixmap);
+ QCOMPARE(item.pixmap(), pixmap);
+}
+
+Q_DECLARE_METATYPE(QGraphicsPixmapItem::ShapeMode)
+void tst_QGraphicsPixmapItem::setShapeMode_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QGraphicsPixmapItem::ShapeMode>("mode");
+ QTest::newRow("MaskShape") << QPixmap() << QGraphicsPixmapItem::MaskShape;
+ QTest::newRow("BoundingRectShape") << QPixmap() << QGraphicsPixmapItem::BoundingRectShape;
+ QTest::newRow("HeuristicMaskShape") << QPixmap() << QGraphicsPixmapItem::HeuristicMaskShape;
+}
+
+// public void setShapeMode(QGraphicsPixmapItem::ShapeMode mode)
+void tst_QGraphicsPixmapItem::setShapeMode()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QGraphicsPixmapItem::ShapeMode, mode);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ item.setShapeMode(mode);
+ QCOMPARE(item.shapeMode(), mode);
+}
+
+Q_DECLARE_METATYPE(Qt::TransformationMode)
+void tst_QGraphicsPixmapItem::setTransformationMode_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<Qt::TransformationMode>("mode");
+ QTest::newRow("FastTransformation") << QPixmap() << Qt::FastTransformation;
+ QTest::newRow("SmoothTransformation") << QPixmap() << Qt::SmoothTransformation;
+}
+
+// public void setTransformationMode(Qt::TransformationMode mode)
+void tst_QGraphicsPixmapItem::setTransformationMode()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(Qt::TransformationMode, mode);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ item.setTransformationMode(mode);
+ QCOMPARE(item.transformationMode(), mode);
+}
+
+void tst_QGraphicsPixmapItem::shape_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPainterPath>("shape");
+ QTest::newRow("null") << QPixmap() << QPainterPath();
+ // ### what does a normal shape look like?
+}
+
+// public QPainterPath shape() const
+void tst_QGraphicsPixmapItem::shape()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPainterPath, shape);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.shape(), shape);
+}
+
+Q_DECLARE_METATYPE(SubQGraphicsPixmapItem::Extension)
+Q_DECLARE_METATYPE(QVariant)
+void tst_QGraphicsPixmapItem::extension_data()
+{
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QVariant>("extension");
+ QTest::newRow("null") << QVariant() << QVariant();
+}
+
+// protected QVariant extension(QVariant const& variant) const
+void tst_QGraphicsPixmapItem::extension()
+{
+ QFETCH(QVariant, variant);
+ QFETCH(QVariant, extension);
+
+ SubQGraphicsPixmapItem item;
+ QCOMPARE(item.call_extension(variant), extension);
+}
+
+void tst_QGraphicsPixmapItem::setExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPixmapItem::Extension>("extension");
+ QTest::addColumn<QVariant>("variant");
+ QTest::newRow("null") << SubQGraphicsPixmapItem::UserExtension << QVariant();
+}
+
+// protected void setExtension(QGraphicsItem::Extension extension, QVariant const& variant)
+void tst_QGraphicsPixmapItem::setExtension()
+{
+ QFETCH(SubQGraphicsPixmapItem::Extension, extension);
+ QFETCH(QVariant, variant);
+
+ SubQGraphicsPixmapItem item;
+ item.call_setExtension(extension, variant);
+}
+
+void tst_QGraphicsPixmapItem::supportsExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPixmapItem::Extension>("extension");
+ QTest::addColumn<bool>("supportsExtension");
+ QTest::newRow("null") << SubQGraphicsPixmapItem::UserExtension << false;
+}
+
+// protected bool supportsExtension(QGraphicsItem::Extension extension) const
+void tst_QGraphicsPixmapItem::supportsExtension()
+{
+ QFETCH(SubQGraphicsPixmapItem::Extension, extension);
+ QFETCH(bool, supportsExtension);
+
+ SubQGraphicsPixmapItem item;
+ QCOMPARE(item.call_supportsExtension(extension), supportsExtension);
+}
+
+QTEST_MAIN(tst_QGraphicsPixmapItem)
+#include "tst_qgraphicspixmapitem.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore
new file mode 100644
index 0000000000..595076024b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicspolygonitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro
new file mode 100644
index 0000000000..2aa16751e6
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicspolygonitem.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp
new file mode 100644
index 0000000000..061b3eda81
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsitem.h>
+
+Q_DECLARE_METATYPE(QPolygonF)
+
+class tst_QGraphicsPolygonItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicspolygonitem_data();
+ void qgraphicspolygonitem();
+ void boundingRect_data();
+ void boundingRect();
+ void contains_data();
+ void contains();
+ void fillRule_data();
+ void fillRule();
+ void isObscuredBy_data();
+ void isObscuredBy();
+ void opaqueArea_data();
+ void opaqueArea();
+ void polygon_data();
+ void polygon();
+ void shape_data();
+ void shape();
+ void extension_data();
+ void extension();
+ void setExtension_data();
+ void setExtension();
+ void supportsExtension_data();
+ void supportsExtension();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsPolygonItem : public QGraphicsPolygonItem
+{
+public:
+ enum Extension {
+ UserExtension = QGraphicsItem::UserExtension
+ };
+
+ SubQGraphicsPolygonItem(QGraphicsItem *parent = 0) : QGraphicsPolygonItem(parent)
+ {
+ }
+
+ SubQGraphicsPolygonItem(const QPolygonF &polygon, QGraphicsItem *parent = 0) : QGraphicsPolygonItem(polygon, parent)
+ {
+ }
+
+ QVariant call_extension(QVariant const& variant) const
+ { return SubQGraphicsPolygonItem::extension(variant); }
+
+ void call_setExtension(SubQGraphicsPolygonItem::Extension extension, QVariant const& variant)
+ { return SubQGraphicsPolygonItem::setExtension((QGraphicsItem::Extension)extension, variant); }
+
+ bool call_supportsExtension(SubQGraphicsPolygonItem::Extension extension) const
+ { return SubQGraphicsPolygonItem::supportsExtension((QGraphicsItem::Extension)extension); }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsPolygonItem::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsPolygonItem::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsPolygonItem::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsPolygonItem::cleanup()
+{
+}
+
+void tst_QGraphicsPolygonItem::qgraphicspolygonitem_data()
+{
+}
+
+void tst_QGraphicsPolygonItem::qgraphicspolygonitem()
+{
+ SubQGraphicsPolygonItem item;
+
+ item.boundingRect();
+ item.contains(QPoint());
+ item.isObscuredBy(0);
+ item.opaqueArea();
+ //item.paint();
+ item.shape();
+ item.type();
+ item.call_extension(QVariant());
+ item.call_setExtension(SubQGraphicsPolygonItem::UserExtension, QVariant());
+ item.call_supportsExtension(SubQGraphicsPolygonItem::UserExtension);
+ item.fillRule();
+ item.polygon();
+ item.setFillRule(Qt::OddEvenFill);
+ item.setPolygon(QPolygonF());
+}
+
+void tst_QGraphicsPolygonItem::boundingRect_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QRectF>("boundingRect");
+ QTest::newRow("null") << QPolygonF() << QRectF();
+ QPolygonF example;
+ example << QPointF(10.4, 20.5) << QPointF(20.2, 30.2);
+ QTest::newRow("example") << example << example.boundingRect();
+ // ### set pen width?
+}
+
+// public QRectF boundingRect() const
+void tst_QGraphicsPolygonItem::boundingRect()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QRectF, boundingRect);
+
+ SubQGraphicsPolygonItem item(polygon);
+ QCOMPARE(item.boundingRect(), boundingRect);
+}
+
+void tst_QGraphicsPolygonItem::contains_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<bool>("contains");
+ QTest::newRow("null") << QPolygonF() << QPointF() << false;
+}
+
+// public bool contains(QPointF const& point) const
+void tst_QGraphicsPolygonItem::contains()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QPointF, point);
+ QFETCH(bool, contains);
+
+ SubQGraphicsPolygonItem item(polygon);
+
+ QCOMPARE(item.contains(point), contains);
+}
+
+Q_DECLARE_METATYPE(Qt::FillRule)
+void tst_QGraphicsPolygonItem::fillRule_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<Qt::FillRule>("fillRule");
+ QTest::newRow("OddEvenFill") << QPolygonF() << Qt::OddEvenFill;
+ QTest::newRow("WindingFill") << QPolygonF() << Qt::WindingFill;
+}
+
+// public Qt::FillRule fillRule() const
+void tst_QGraphicsPolygonItem::fillRule()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(Qt::FillRule, fillRule);
+
+ SubQGraphicsPolygonItem item(polygon);
+
+ item.setFillRule(fillRule);
+ QCOMPARE(item.fillRule(), fillRule);
+ // ### Check that the painting is different?
+}
+
+void tst_QGraphicsPolygonItem::isObscuredBy_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QPolygonF>("otherPolygon");
+ QTest::addColumn<bool>("isObscuredBy");
+ QTest::newRow("null") << QPolygonF() << QPolygonF() << false;
+ //QTest::newRow("ontop-inside") << QPixmap(10, 10) << QPixmap(5, 5) << false;
+ //QTest::newRow("ontop-larger") << QPixmap(10, 10) << QPixmap(11, 11) << true;
+}
+
+// public bool isObscuredBy(QGraphicsItem const* item) const
+void tst_QGraphicsPolygonItem::isObscuredBy()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QPolygonF, otherPolygon);
+ QFETCH(bool, isObscuredBy);
+ SubQGraphicsPolygonItem item(polygon);
+ SubQGraphicsPolygonItem otherItem(otherPolygon);
+ QCOMPARE(item.isObscuredBy(&otherItem), isObscuredBy);
+}
+
+Q_DECLARE_METATYPE(QPainterPath)
+void tst_QGraphicsPolygonItem::opaqueArea_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QPainterPath>("opaqueArea");
+ QTest::newRow("null") << QPolygonF() << QPainterPath();
+ // Currently QGraphicsPolygonItem just calls QGraphicsItem test there
+}
+
+// public QPainterPath opaqueArea() const
+void tst_QGraphicsPolygonItem::opaqueArea()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QPainterPath, opaqueArea);
+
+ SubQGraphicsPolygonItem item(polygon);
+ QCOMPARE(item.opaqueArea(), opaqueArea);
+}
+
+void tst_QGraphicsPolygonItem::polygon_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::newRow("null") << QPolygonF();
+ QPolygonF example;
+ example << QPointF(10.4, 20.5) << QPointF(20.2, 30.2);
+ QTest::newRow("example") << example;
+}
+
+// public QPolygonF polygon() const
+void tst_QGraphicsPolygonItem::polygon()
+{
+ QFETCH(QPolygonF, polygon);
+
+ SubQGraphicsPolygonItem item;
+ item.setPolygon(polygon);
+ QCOMPARE(item.polygon(), polygon);
+}
+
+void tst_QGraphicsPolygonItem::shape_data()
+{
+ QTest::addColumn<QPainterPath>("shape");
+ QTest::newRow("null") << QPainterPath();
+ // ### what should a normal shape look like?
+}
+
+// public QPainterPath shape() const
+void tst_QGraphicsPolygonItem::shape()
+{
+ QFETCH(QPainterPath, shape);
+
+ SubQGraphicsPolygonItem item;
+ QCOMPARE(item.shape(), shape);
+}
+
+Q_DECLARE_METATYPE(QVariant)
+void tst_QGraphicsPolygonItem::extension_data()
+{
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QVariant>("extension");
+ QTest::newRow("null") << QVariant() << QVariant();
+}
+
+// protected QVariant extension(QVariant const& variant) const
+void tst_QGraphicsPolygonItem::extension()
+{
+ QFETCH(QVariant, variant);
+ QFETCH(QVariant, extension);
+
+ SubQGraphicsPolygonItem item;
+
+ QCOMPARE(item.call_extension(variant), extension);
+}
+
+Q_DECLARE_METATYPE(SubQGraphicsPolygonItem::Extension)
+void tst_QGraphicsPolygonItem::setExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPolygonItem::Extension>("extension");
+ QTest::addColumn<QVariant>("variant");
+ QTest::newRow("null") << SubQGraphicsPolygonItem::Extension() << QVariant();
+}
+
+// protected void setExtension(SubQGraphicsPolygonItem::Extension extension, QVariant const& variant)
+void tst_QGraphicsPolygonItem::setExtension()
+{
+ QFETCH(SubQGraphicsPolygonItem::Extension, extension);
+ QFETCH(QVariant, variant);
+
+ SubQGraphicsPolygonItem item;
+ item.call_setExtension(extension, variant);
+}
+
+void tst_QGraphicsPolygonItem::supportsExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPolygonItem::Extension>("extension");
+ QTest::addColumn<bool>("supportsExtension");
+ QTest::newRow("null") << SubQGraphicsPolygonItem::Extension() << false;
+}
+
+// protected bool supportsExtension(SubQGraphicsPolygonItem::Extension extension) const
+void tst_QGraphicsPolygonItem::supportsExtension()
+{
+ QFETCH(SubQGraphicsPolygonItem::Extension, extension);
+ QFETCH(bool, supportsExtension);
+
+ SubQGraphicsPolygonItem item;
+ QCOMPARE(item.call_supportsExtension(extension), supportsExtension);
+}
+
+QTEST_MAIN(tst_QGraphicsPolygonItem)
+#include "tst_qgraphicspolygonitem.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore
new file mode 100644
index 0000000000..530452478b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsproxywidget
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
new file mode 100644
index 0000000000..a649ae1a3c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicsproxywidget.cpp
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
new file mode 100644
index 0000000000..78c545e25a
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -0,0 +1,3649 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+#include <private/qgraphicsproxywidget_p.h>
+#include <private/qlayoutengine_p.h> // qSmartMin functions...
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+#include <QMacStyle>
+#endif
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#endif
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton)
+{
+ QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+/*
+ Notes:
+
+ 1) The proxy and the widget geometries are linked.
+ proxy resize => widget resize => stop (no livelock)
+ widget resize => proxy resize => stop (no livelock)
+
+ 2) As far as possible, the properties are linked.
+ proxy enable => widget enable => stop
+ widget disabled => proxy disabled => stop
+
+ 3) Windowed state is linked
+ Windowed proxy state => windowed widget state => stop
+ Windowed widget state => windowed proxy state => stop
+*/
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QObject *receiver)
+ {
+ receiver->installEventFilter(this);
+ }
+
+ QMap<QEvent::Type, int> counts;
+
+protected:
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ ++counts[event->type()];
+ return false;
+ }
+};
+
+class tst_QGraphicsProxyWidget : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicsproxywidget_data();
+ void qgraphicsproxywidget();
+ void paint();
+ void paint_2();
+ void setWidget_data();
+ void setWidget();
+ void eventFilter_data();
+ void eventFilter();
+ void focusInEvent_data();
+ void focusInEvent();
+ void focusInEventNoWidget();
+ void focusNextPrevChild_data();
+ void focusNextPrevChild();
+ void focusOutEvent_data();
+ void focusOutEvent();
+#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+ void hoverEnterLeaveEvent_data();
+ void hoverEnterLeaveEvent();
+#endif
+ void hoverMoveEvent_data();
+ void hoverMoveEvent();
+ void keyPressEvent_data();
+ void keyPressEvent();
+ void keyReleaseEvent_data();
+ void keyReleaseEvent();
+ void mouseDoubleClickEvent_data();
+ void mouseDoubleClickEvent();
+ void mousePressReleaseEvent_data();
+ void mousePressReleaseEvent();
+ void resizeEvent_data();
+ void resizeEvent();
+ void paintEvent();
+ void wheelEvent();
+ void sizeHint_data();
+ void sizeHint();
+ void sizePolicy();
+ void minimumSize();
+ void maximumSize();
+ void scrollUpdate();
+ void setWidget_simple();
+ void setWidget_ownership();
+ void resize_simple_data();
+ void resize_simple();
+ void symmetricMove();
+ void symmetricResize();
+ void symmetricEnabled();
+ void symmetricVisible();
+ void tabFocus_simpleWidget();
+ void tabFocus_simpleTwoWidgets();
+ void tabFocus_complexWidget();
+ void tabFocus_complexTwoWidgets();
+ void setFocus_simpleWidget();
+ void setFocus_simpleTwoWidgets();
+ void setFocus_complexTwoWidgets();
+ void popup_basic();
+ void popup_subwidget();
+#if !defined(QT_NO_CURSOR) && (!defined(Q_OS_WINCE) || defined(GWES_ICONCURS))
+ void changingCursor_basic();
+#endif
+ void tooltip_basic();
+ void childPos_data();
+ void childPos();
+ void autoShow();
+ void windowOpacity();
+ void stylePropagation();
+ void palettePropagation();
+ void fontPropagation();
+ void dontCrashWhenDie();
+ void createProxyForChildWidget();
+ void actionsContextMenu();
+ void actionsContextMenu_data();
+ void deleteProxyForChildWidget();
+ void bypassGraphicsProxyWidget_data();
+ void bypassGraphicsProxyWidget();
+ void dragDrop();
+ void windowFlags_data();
+ void windowFlags();
+ void comboboxWindowFlags();
+ void updateAndDelete();
+ void inputMethod();
+ void clickFocus();
+ void windowFrameMargins();
+ void QTBUG_6986_sendMouseEventToAlienWidget();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsProxyWidget : public QGraphicsProxyWidget
+{
+
+public:
+ SubQGraphicsProxyWidget(QGraphicsItem *parent = 0) : QGraphicsProxyWidget(parent),
+ paintCount(0), keyPress(0), focusOut(0)
+ {}
+
+ bool call_eventFilter(QObject* object, QEvent* event)
+ { return SubQGraphicsProxyWidget::eventFilter(object, event); }
+
+ void call_focusInEvent(QFocusEvent* event)
+ { return SubQGraphicsProxyWidget::focusInEvent(event); }
+
+ bool call_focusNextPrevChild(bool next)
+ { return SubQGraphicsProxyWidget::focusNextPrevChild(next); }
+
+ void call_focusOutEvent(QFocusEvent* event)
+ { return SubQGraphicsProxyWidget::focusOutEvent(event); }
+
+ void call_hideEvent(QHideEvent* event)
+ { return SubQGraphicsProxyWidget::hideEvent(event); }
+
+ void call_hoverEnterEvent(QGraphicsSceneHoverEvent* event)
+ { return SubQGraphicsProxyWidget::hoverEnterEvent(event); }
+
+ void call_hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
+ { return SubQGraphicsProxyWidget::hoverLeaveEvent(event); }
+
+ void call_hoverMoveEvent(QGraphicsSceneHoverEvent* event)
+ { return SubQGraphicsProxyWidget::hoverMoveEvent(event); }
+
+ void call_keyPressEvent(QKeyEvent* event)
+ { return SubQGraphicsProxyWidget::keyPressEvent(event); }
+
+ void call_keyReleaseEvent(QKeyEvent* event)
+ { return SubQGraphicsProxyWidget::keyReleaseEvent(event); }
+
+ void call_mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mouseDoubleClickEvent(event); }
+
+ void call_mouseMoveEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mouseMoveEvent(event); }
+
+ void call_mousePressEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mousePressEvent(event); }
+
+ void call_mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mouseReleaseEvent(event); }
+
+ void call_resizeEvent(QGraphicsSceneResizeEvent* event)
+ { return SubQGraphicsProxyWidget::resizeEvent(event); }
+
+ QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+ { return SubQGraphicsProxyWidget::sizeHint(which, constraint); }
+
+ void call_showEvent(QShowEvent* event)
+ { return SubQGraphicsProxyWidget::showEvent(event); }
+
+ void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) {
+ paintCount++;
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ }
+
+ void focusOutEvent(QFocusEvent *event)
+ {
+ focusOut++;
+ QGraphicsProxyWidget::focusOutEvent(event);
+ }
+
+ bool eventFilter(QObject *object, QEvent *event) {
+ if (event->type() == QEvent::KeyPress && object == widget())
+ keyPress++;
+ return QGraphicsProxyWidget::eventFilter(object, event);
+ }
+ int paintCount;
+ int keyPress;
+ int focusOut;
+};
+
+class WheelWidget : public QWidget
+{
+public:
+ WheelWidget() : wheelEventCalled(false) { setFocusPolicy(Qt::WheelFocus); }
+
+ virtual void wheelEvent(QWheelEvent *event) { event->accept(); wheelEventCalled = true; }
+
+ bool wheelEventCalled;
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsProxyWidget::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsProxyWidget::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsProxyWidget::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsProxyWidget::cleanup()
+{
+}
+
+void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data()
+{
+}
+
+void tst_QGraphicsProxyWidget::qgraphicsproxywidget()
+{
+ SubQGraphicsProxyWidget proxy;
+ proxy.paint(0, 0, 0);
+ proxy.setWidget(0);
+ QVERIFY(proxy.type() == QGraphicsProxyWidget::Type);
+ QVERIFY(!proxy.widget());
+ QEvent event(QEvent::None);
+ proxy.call_eventFilter(0, &event);
+ QFocusEvent focusEvent(QEvent::FocusIn);
+ focusEvent.ignore();
+ proxy.call_focusInEvent(&focusEvent);
+ QCOMPARE(focusEvent.isAccepted(), false);
+ QCOMPARE(proxy.call_focusNextPrevChild(false), false);
+ QCOMPARE(proxy.call_focusNextPrevChild(true), false);
+ proxy.call_focusOutEvent(&focusEvent);
+ QHideEvent hideEvent;
+ proxy.call_hideEvent(&hideEvent);
+ QGraphicsSceneHoverEvent hoverEvent;
+ proxy.call_hoverEnterEvent(&hoverEvent);
+ proxy.call_hoverLeaveEvent(&hoverEvent);
+ proxy.call_hoverMoveEvent(&hoverEvent);
+ QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier);
+ proxy.call_keyPressEvent(&keyEvent);
+ proxy.call_keyReleaseEvent(&keyEvent);
+ QGraphicsSceneMouseEvent mouseEvent;
+ proxy.call_mouseDoubleClickEvent(&mouseEvent);
+ proxy.call_mouseMoveEvent(&mouseEvent);
+ proxy.call_mousePressEvent(&mouseEvent);
+ proxy.call_mouseReleaseEvent(&mouseEvent);
+ QGraphicsSceneResizeEvent resizeEvent;
+ proxy.call_resizeEvent(&resizeEvent);
+ QShowEvent showEvent;
+ proxy.call_showEvent(&showEvent);
+ proxy.call_sizeHint(Qt::PreferredSize, QSizeF());
+}
+
+// public void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget)
+void tst_QGraphicsProxyWidget::paint()
+{
+ SubQGraphicsProxyWidget proxy;
+ proxy.paint(0, 0, 0);
+}
+
+class MyProxyWidget : public QGraphicsProxyWidget
+{
+public:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ // Make sure QGraphicsProxyWidget::paint does not modify the render hints set on the painter.
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
+ | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
+ const QPainter::RenderHints oldRenderHints = painter->renderHints();
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ QCOMPARE(painter->renderHints(), oldRenderHints);
+ }
+};
+
+void tst_QGraphicsProxyWidget::paint_2()
+{
+ MyProxyWidget *proxyWidget = new MyProxyWidget;
+ proxyWidget->setWidget(new QLineEdit);
+
+ QGraphicsScene scene;
+ scene.addItem(proxyWidget);
+ scene.setSceneRect(scene.itemsBoundingRect());
+
+ // Trigger repaint.
+ QPixmap pixmap(scene.sceneRect().toRect().size());
+ QPainter painter(&pixmap);
+ scene.render(&painter);
+}
+
+void tst_QGraphicsProxyWidget::setWidget_data()
+{
+ QTest::addColumn<bool>("widgetExists");
+ QTest::addColumn<bool>("insertWidget");
+ QTest::addColumn<bool>("hasParent");
+ QTest::addColumn<bool>("proxyHasParent");
+
+ QTest::newRow("setWidget(0)") << false << false << false << false;
+ QTest::newRow("setWidget(widget)") << false << true << false << false;
+ QTest::newRow("setWidget(widgetWParent)") << false << true << true << false;
+ QTest::newRow("setWidget(1), setWidget(0)") << true << false << false << false;
+ QTest::newRow("setWidget(1), setWidget(widget)") << true << true << false << false;
+ QTest::newRow("setWidget(1), setWidget(widgetWParent)") << true << true << true << false;
+ QTest::newRow("p setWidget(0)") << false << false << false << true;
+ QTest::newRow("p setWidget(widget)") << false << true << false << true;
+ QTest::newRow("p setWidget(widgetWParent)") << false << true << true << true;
+ QTest::newRow("p setWidget(1), setWidget(0)") << true << false << false << true;
+ QTest::newRow("p setWidget(1), setWidget(widget)") << true << true << false << true;
+ QTest::newRow("p setWidget(1), setWidget(widgetWParent)") << true << true << true << true;
+}
+
+// public void setWidget(QWidget* widget)
+void tst_QGraphicsProxyWidget::setWidget()
+{
+ QFETCH(bool, widgetExists);
+ QFETCH(bool, insertWidget);
+ QFETCH(bool, hasParent);
+ QFETCH(bool, proxyHasParent);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QPointer<SubQGraphicsProxyWidget> proxy = new SubQGraphicsProxyWidget;
+ SubQGraphicsProxyWidget parentProxy;
+ scene.addItem(proxy);
+ scene.addItem(&parentProxy);
+ if (proxyHasParent)
+ proxy->setParent(&parentProxy);
+ QPointer<QWidget> existingSubWidget = new QWidget;
+ proxy->setVisible(false);
+ proxy->setEnabled(false);
+
+ if (widgetExists) {
+ existingSubWidget->setAttribute(Qt::WA_QuitOnClose, true);
+ proxy->setWidget(existingSubWidget);
+ }
+
+ QWidget *widget = new QWidget;
+#ifndef QT_NO_CURSOR
+ widget->setCursor(Qt::IBeamCursor);
+#endif
+ widget->setPalette(QPalette(Qt::magenta));
+ widget->setLayoutDirection(Qt::RightToLeft);
+ QCleanlooksStyle cleanlooksStyle;
+ widget->setStyle(&cleanlooksStyle);
+ widget->setFont(QFont("Times"));
+ widget->setVisible(true);
+ QApplication::setActiveWindow(widget);
+ widget->activateWindow();
+ widget->setEnabled(true);
+ widget->resize(325, 241);
+ widget->setMinimumSize(100, 200);
+ widget->setMaximumSize(1000, 2000);
+ widget->setFocusPolicy(Qt::TabFocus);
+ widget->setContentsMargins(10, 29, 19, 81);
+ widget->setFocus(Qt::TabFocusReason);
+ widget->setAcceptDrops(true);
+ QTRY_VERIFY(widget->hasFocus());
+ QVERIFY(widget->isActiveWindow());
+
+ QWidget parentWidget;
+ if (hasParent)
+ widget->setParent(&parentWidget);
+
+ QWidget *subWidget = insertWidget ? widget : 0;
+ bool shouldBeInsertable = !hasParent && subWidget;
+ if (shouldBeInsertable)
+ subWidget->setAttribute(Qt::WA_QuitOnClose, true);
+
+ proxy->setWidget(subWidget);
+
+ if (shouldBeInsertable) {
+ QCOMPARE(proxy->widget(), subWidget);
+ QVERIFY(subWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ QVERIFY(!subWidget->testAttribute(Qt::WA_QuitOnClose));
+ QCOMPARE(proxy->acceptHoverEvents(), true);
+#ifndef QT_NO_CURSOR
+ QVERIFY(proxy->hasCursor());
+
+ // These should match
+ QCOMPARE(proxy->cursor().shape(), widget->cursor().shape());
+#endif
+ //###QCOMPARE(proxy->palette(), widget->palette());
+ QCOMPARE(proxy->layoutDirection(), widget->layoutDirection());
+ QCOMPARE(proxy->style(), widget->style());
+ QCOMPARE(proxy->isVisible(), widget->isVisible());
+ QCOMPARE(proxy->isEnabled(), widget->isEnabled());
+ QVERIFY(proxy->flags() & QGraphicsItem::ItemIsFocusable);
+ QCOMPARE(proxy->effectiveSizeHint(Qt::MinimumSize).toSize(),
+ qSmartMinSize(widget));
+ QCOMPARE(proxy->minimumSize().toSize(),
+ qSmartMinSize(widget) );
+ QCOMPARE(proxy->maximumSize().toSize(), QSize(1000, 2000));
+ QCOMPARE(proxy->effectiveSizeHint(Qt::PreferredSize).toSize(),
+ qSmartMinSize(widget));
+ QCOMPARE(proxy->size().toSize(), widget->size());
+ QCOMPARE(proxy->rect().toRect(), widget->rect());
+ QCOMPARE(proxy->focusPolicy(), Qt::WheelFocus);
+ QVERIFY(proxy->acceptDrops());
+ QCOMPARE(proxy->acceptsHoverEvents(), true); // to get widget enter events
+ int left, top, right, bottom;
+ widget->getContentsMargins(&left, &top, &right, &bottom);
+ qreal rleft, rtop, rright, rbottom;
+ proxy->getContentsMargins(&rleft, &rtop, &rright, &rbottom);
+ QCOMPARE((qreal)left, rleft);
+ QCOMPARE((qreal)top, rtop);
+ QCOMPARE((qreal)right, rright);
+ QCOMPARE((qreal)bottom, rbottom);
+ } else {
+ // proxy shouldn't mess with the widget if it can't insert it.
+ QCOMPARE(proxy->widget(), (QWidget*)0);
+ QCOMPARE(proxy->acceptHoverEvents(), false);
+ if (subWidget) {
+ QVERIFY(!subWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ QVERIFY(subWidget->testAttribute(Qt::WA_QuitOnClose));
+ // reset
+ subWidget->setAttribute(Qt::WA_QuitOnClose, false);
+ }
+ }
+
+ if (widgetExists) {
+ QCOMPARE(existingSubWidget->parent(), static_cast<QObject*>(0));
+ QVERIFY(!existingSubWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ QVERIFY(!existingSubWidget->testAttribute(Qt::WA_QuitOnClose));
+ }
+
+ if (hasParent)
+ widget->setParent(0);
+
+ delete widget;
+ if (shouldBeInsertable)
+ QVERIFY(!proxy);
+ delete existingSubWidget;
+ if (!shouldBeInsertable) {
+ QVERIFY(proxy);
+ delete proxy;
+ }
+ QVERIFY(!proxy);
+}
+
+Q_DECLARE_METATYPE(QEvent::Type)
+void tst_QGraphicsProxyWidget::eventFilter_data()
+{
+ QTest::addColumn<QEvent::Type>("eventType");
+ QTest::addColumn<bool>("fromObject"); // big grin evil
+ QTest::newRow("none") << QEvent::None << false;
+ for (int i = 0; i < 2; ++i) {
+ bool fromObject = (i == 0);
+ QTest::newRow(QString("resize %1").arg(fromObject).toLatin1()) << QEvent::Resize << fromObject;
+ QTest::newRow(QString("move %1").arg(fromObject).toLatin1()) << QEvent::Move << fromObject;
+ QTest::newRow(QString("hide %1").arg(fromObject).toLatin1()) << QEvent::Hide << fromObject;
+ QTest::newRow(QString("show %1").arg(fromObject).toLatin1()) << QEvent::Show << fromObject;
+ QTest::newRow(QString("enabled %1").arg(fromObject).toLatin1()) << QEvent::EnabledChange << fromObject;
+ QTest::newRow(QString("focusIn %1").arg(fromObject).toLatin1()) << QEvent::FocusIn << fromObject;
+ QTest::newRow(QString("focusOut %1").arg(fromObject).toLatin1()) << QEvent::FocusOut << fromObject;
+ QTest::newRow(QString("keyPress %1").arg(fromObject).toLatin1()) << QEvent::KeyPress << fromObject;
+ }
+}
+
+// protected bool eventFilter(QObject* object, QEvent* event)
+void tst_QGraphicsProxyWidget::eventFilter()
+{
+ QFETCH(QEvent::Type, eventType);
+ QFETCH(bool, fromObject);
+
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ scene.addItem(proxy);
+
+ QWidget *widget = new QWidget(0, Qt::FramelessWindowHint);
+ widget->setFocusPolicy(Qt::TabFocus);
+ widget->resize(10, 10);
+ widget->show();
+ proxy->setWidget(widget);
+ proxy->show();
+
+ // mirror whatever is happening to the widget
+ // don't get in a loop
+ switch (eventType) {
+ case QEvent::None: {
+ QEvent event(QEvent::None);
+ proxy->call_eventFilter(widget, &event);
+ break;
+ }
+ case QEvent::Resize: {
+ QSize oldSize = widget->size();
+ QSize newSize = QSize(100, 100);
+ if (fromObject) {
+ widget->resize(newSize);
+ } else {
+ proxy->resize(newSize);
+ }
+ QCOMPARE(proxy->size().toSize(), newSize);
+ QCOMPARE(widget->size(), newSize);
+ break;
+ }
+ case QEvent::Move: {
+ QPoint oldPoint = widget->pos();
+ QPoint newPoint = QPoint(100, 100);
+ if (fromObject) {
+ widget->move(newPoint);
+ } else {
+ proxy->setPos(newPoint);
+ }
+ QCOMPARE(proxy->pos().toPoint(), newPoint);
+ QCOMPARE(widget->pos(), newPoint);
+ break;
+ }
+ case QEvent::Hide: {
+ // A hide event can only come from a widget
+ if (fromObject) {
+ widget->setFocus(Qt::TabFocusReason);
+ widget->hide();
+ } else {
+ QHideEvent event;
+ proxy->call_eventFilter(widget, &event);
+ }
+ QCOMPARE(proxy->isVisible(), false);
+ break;
+ }
+ case QEvent::Show: {
+ // A show event can either come from a widget or somewhere else
+ widget->hide();
+ if (fromObject) {
+ widget->show();
+ } else {
+ QShowEvent event;
+ proxy->call_eventFilter(widget, &event);
+ }
+ QCOMPARE(proxy->isVisible(), true);
+ break;
+ }
+ case QEvent::EnabledChange: {
+ widget->setEnabled(false);
+ proxy->setEnabled(false);
+ if (fromObject) {
+ widget->setEnabled(true);
+ QCOMPARE(proxy->isEnabled(), true);
+ widget->setEnabled(false);
+ QCOMPARE(proxy->isEnabled(), false);
+ } else {
+ QEvent event(QEvent::EnabledChange);
+ proxy->call_eventFilter(widget, &event);
+ // match the widget not the event
+ QCOMPARE(proxy->isEnabled(), false);
+ }
+ break;
+ }
+ case QEvent::FocusIn: {
+ if (fromObject) {
+ widget->setFocus(Qt::TabFocusReason);
+ QVERIFY(proxy->hasFocus());
+ }
+ break;
+ }
+ case QEvent::FocusOut: {
+ widget->setFocus(Qt::TabFocusReason);
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(widget->hasFocus());
+ if (fromObject) {
+ widget->clearFocus();
+ QVERIFY(!proxy->hasFocus());
+ }
+ break;
+ }
+ case QEvent::KeyPress: {
+ if (fromObject) {
+ QTest::keyPress(widget, Qt::Key_A, Qt::NoModifier);
+ } else {
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
+ proxy->call_eventFilter(widget, &event);
+ }
+ QCOMPARE(proxy->keyPress, 1);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void tst_QGraphicsProxyWidget::focusInEvent_data()
+{
+ QTest::addColumn<bool>("widgetHasFocus");
+ QTest::addColumn<bool>("widgetCanHaveFocus");
+ QTest::newRow("no focus, can't get") << false << false;
+ QTest::newRow("no focus, can get") << false << true;
+ QTest::newRow("has focus, can't get") << true << false;
+ QTest::newRow("has focus, can get") << true << true;
+ // ### add test for widget having a focusNextPrevChild
+}
+
+// protected void focusInEvent(QFocusEvent* event)
+void tst_QGraphicsProxyWidget::focusInEvent()
+{
+ // ### This test is just plain old broken
+ QFETCH(bool, widgetHasFocus);
+ QFETCH(bool, widgetCanHaveFocus);
+
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setEnabled(true);
+ scene.addItem(proxy);
+ proxy->setVisible(true);
+
+ QWidget *widget = new QWidget;
+ widget->resize(100, 100);
+ if (widgetCanHaveFocus)
+ widget->setFocusPolicy(Qt::WheelFocus);
+ widget->show();
+
+ if (widgetHasFocus)
+ widget->setFocus(Qt::TabFocusReason);
+
+ proxy->setWidget(widget);
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
+
+ // ### This test is just plain old broken - sending a focus in event
+ // does not cause items to gain input focus. The widget has focus
+ // because the proxy has focus, not because it got this event.
+
+ QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
+ event.ignore();
+ proxy->call_focusInEvent(&event);
+ QTRY_COMPARE(widget->hasFocus(), widgetCanHaveFocus);
+}
+
+void tst_QGraphicsProxyWidget::focusInEventNoWidget()
+{
+ QGraphicsView view;
+ QGraphicsScene scene(&view);
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setEnabled(true);
+ scene.addItem(proxy);
+ proxy->setVisible(true);
+ view.show();
+
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
+ QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
+ event.ignore();
+ //should not crash
+ proxy->call_focusInEvent(&event);
+}
+
+void tst_QGraphicsProxyWidget::focusNextPrevChild_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("hasScene");
+ QTest::addColumn<bool>("next");
+ QTest::addColumn<bool>("focusNextPrevChild");
+
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ for (int k = 0; k < 2; ++k) {
+ bool next = (i == 0);
+ bool hasWidget = (j == 0);
+ bool hasScene = (k == 0);
+ bool result = hasScene && hasWidget;
+ QString name = QString("Forward: %1, hasWidget: %2, hasScene: %3, result: %4").arg(next).arg(hasWidget).arg(hasScene).arg(result);
+ QTest::newRow(name.toLatin1()) << hasWidget << hasScene << next << result;
+ }
+ }
+ }
+}
+
+// protected bool focusNextPrevChild(bool next)
+void tst_QGraphicsProxyWidget::focusNextPrevChild()
+{
+ QFETCH(bool, next);
+ QFETCH(bool, focusNextPrevChild);
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, hasScene);
+
+ // If a widget has its own focusNextPrevChild we need to respect it
+ // otherwise respect the scene
+ // Respect the widget over the scene!
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+
+ QLabel *widget = new QLabel;
+ // I can't believe designer adds this much junk!
+ widget->setText("<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\"> <p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.slashdot.org\"><span style=\" text-decoration: underline; color:#0000ff;\">old</span></a> foo <a href=\"http://www.reddit.org\"><span style=\" text-decoration: underline; color:#0000ff;\">new</span></a></p></body></html>");
+ widget->setTextInteractionFlags(Qt::TextBrowserInteraction);
+
+ if (hasWidget)
+ proxy->setWidget(widget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+ if (hasScene) {
+ scene.addItem(proxy);
+ proxy->show();
+
+ // widget should take precedence over scene so make scene.focusNextPrevChild return false
+ // so we know that a true can only come from the widget
+ if (!(hasWidget && hasScene)) {
+ QGraphicsTextItem *item = new QGraphicsTextItem("Foo");
+ item->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ scene.addItem(item);
+ item->setPos(50, 40);
+ }
+ scene.setFocusItem(proxy);
+ QVERIFY(proxy->hasFocus());
+ }
+
+ QCOMPARE(proxy->call_focusNextPrevChild(next), focusNextPrevChild);
+
+ if (!hasScene)
+ delete proxy;
+}
+
+void tst_QGraphicsProxyWidget::focusOutEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("call");
+ QTest::newRow("no widget, focus to other widget") << false << false;
+ QTest::newRow("no widget, focusOutCalled") << false << true;
+ QTest::newRow("widget, focus to other widget") << true << false;
+ QTest::newRow("widget, focusOutCalled") << true << true;
+}
+
+// protected void focusOutEvent(QFocusEvent* event)
+void tst_QGraphicsProxyWidget::focusOutEvent()
+{
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, call);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ scene.addItem(proxy);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ view.activateWindow();
+ view.setFocus();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.isVisible());
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ QWidget *widget = new QWidget;
+ widget->setFocusPolicy(Qt::WheelFocus);
+ if (hasWidget)
+ proxy->setWidget(widget);
+ proxy->show();
+ proxy->setFocus();
+ QVERIFY(proxy->hasFocus());
+ QEXPECT_FAIL("widget, focus to other widget", "Widget should have focus but doesn't", Continue);
+ QEXPECT_FAIL("widget, focusOutCalled", "Widget should have focus but doesn't", Continue);
+ QCOMPARE(widget->hasFocus(), hasWidget);
+
+ if (!call) {
+ QWidget *other = new QLineEdit(&view);
+ other->show();
+ QApplication::processEvents();
+ QTRY_VERIFY(other->isVisible());
+ other->setFocus();
+ QTRY_VERIFY(other->hasFocus());
+ qApp->processEvents();
+ QTRY_COMPARE(proxy->hasFocus(), false);
+ QVERIFY(proxy->focusOut);
+ QCOMPARE(widget->hasFocus(), false);
+ } else {
+ {
+ /*
+ ### Test doesn't make sense
+ QFocusEvent focusEvent(QEvent::FocusOut);
+ proxy->call_focusOutEvent(&focusEvent);
+ QCOMPARE(focusEvent.isAccepted(), hasWidget);
+ qApp->processEvents();
+ QCOMPARE(proxy->paintCount, hasWidget ? 1 : 0);
+ */
+ }
+ {
+ /*
+ ### Test doesn't make sense
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ QFocusEvent focusEvent(QEvent::FocusOut);
+ proxy->call_focusOutEvent(&focusEvent);
+ QCOMPARE(focusEvent.isAccepted(), hasWidget);
+ qApp->processEvents();
+ QCOMPARE(proxy->paintCount, 0);
+ */
+ }
+ }
+}
+
+class EventLogger : public QWidget
+{
+public:
+ EventLogger() : QWidget(), enterCount(0), leaveCount(0), moveCount(0),
+ hoverEnter(0), hoverLeave(0), hoverMove(0)
+ {
+ installEventFilter(this);
+ }
+
+ void enterEvent(QEvent *event)
+ {
+ enterCount++;
+ QWidget::enterEvent(event);
+ }
+
+ void leaveEvent(QEvent *event )
+ {
+ leaveCount++;
+ QWidget::leaveEvent(event);
+ }
+
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ event->setAccepted(true);
+ moveCount++;
+ QWidget::mouseMoveEvent(event);
+ }
+
+ int enterCount;
+ int leaveCount;
+ int moveCount;
+
+ int hoverEnter;
+ int hoverLeave;
+ int hoverMove;
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::HoverEnter:
+ hoverEnter++;
+ break;
+ case QEvent::HoverLeave:
+ hoverLeave++;
+ break;
+ case QEvent::HoverMove:
+ hoverMove++;
+ break;
+ default:
+ break;
+ }
+ return QWidget::eventFilter(object, event);
+ }
+};
+
+// protected void hoverEnterEvent(QGraphicsSceneHoverEvent* event)
+#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("hoverEnabled");
+ QTest::newRow("widget, no hover") << true << false;
+ QTest::newRow("no widget, no hover") << false << false;
+ QTest::newRow("widget, hover") << true << true;
+ QTest::newRow("no widget, hover") << false << true;
+}
+
+void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
+{
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, hoverEnabled);
+
+ // proxy should translate this into events that the widget would expect
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ //do not let the window manager move the window while we are moving the mouse on it
+ view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ EventLogger *widget = new EventLogger;
+ widget->resize(50, 50);
+ widget->setAttribute(Qt::WA_Hover, hoverEnabled);
+ widget->setMouseTracking(true);
+ view.resize(100, 100);
+ if (hasWidget)
+ proxy->setWidget(widget);
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ QTest::qWait(30);
+ QTest::mouseMove(&view, QPoint(10, 10));
+ QTest::qWait(30);
+
+ // in
+ QTest::mouseMove(&view, QPoint(50, 50));
+ QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), hasWidget ? true : false);
+ // ### this attribute isn't supported
+ QCOMPARE(widget->enterCount, hasWidget ? 1 : 0);
+ QCOMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
+ // does not work on all platforms
+ //QCOMPARE(widget->moveCount, 0);
+
+ // out
+ QTest::mouseMove(&view, QPoint(10, 10));
+ // QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), false);
+ // ### this attribute isn't supported
+ QTRY_COMPARE(widget->leaveCount, hasWidget ? 1 : 0);
+ QTRY_COMPARE(widget->hoverLeave, (hasWidget && hoverEnabled) ? 1 : 0);
+ // does not work on all platforms
+ //QCOMPARE(widget->moveCount, 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+#endif
+
+void tst_QGraphicsProxyWidget::hoverMoveEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("hoverEnabled");
+ QTest::addColumn<bool>("mouseTracking");
+ QTest::addColumn<bool>("mouseDown");
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ for (int k = 0; k < 2; ++k) {
+ for (int l = 0; l < 2; ++l) {
+ bool hasWidget = (i == 0);
+ bool hoverEnabled = (j == 0);
+ bool mouseTracking = (k == 0);
+ bool mouseDown = (l == 0);
+ QString name = QString("hasWidget:%1, hover:%2, mouseTracking:%3, mouseDown: %4").arg(hasWidget).arg(hoverEnabled).arg(mouseTracking).arg(mouseDown);
+ QTest::newRow(name.toLatin1()) << hasWidget << hoverEnabled << mouseTracking << mouseDown;
+ }
+ }
+ }
+ }
+}
+
+// protected void hoverMoveEvent(QGraphicsSceneHoverEvent* event)
+void tst_QGraphicsProxyWidget::hoverMoveEvent()
+{
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, hoverEnabled);
+ QFETCH(bool, mouseTracking);
+ QFETCH(bool, mouseDown);
+
+ QSKIP("Ambiguous test...", SkipAll);
+
+ // proxy should translate the move events to what the widget would expect
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ EventLogger *widget = new EventLogger;
+ widget->resize(50, 50);
+ widget->setAttribute(Qt::WA_Hover, hoverEnabled);
+ if (mouseTracking)
+ widget->setMouseTracking(true);
+ view.resize(100, 100);
+ if (hasWidget)
+ proxy->setWidget(widget);
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+
+ // in
+ QTest::mouseMove(&view, QPoint(50, 50));
+ QTest::qWait(12);
+
+ if (mouseDown)
+ QTest::mousePress(view.viewport(), Qt::LeftButton);
+
+ // move a little bit
+ QTest::mouseMove(&view, QPoint(60, 60));
+ QTRY_COMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
+ QCOMPARE(widget->moveCount, (hasWidget && mouseTracking) || (hasWidget && mouseDown) ? 1 : 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::keyPressEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void keyPressEvent(QKeyEvent* event)
+void tst_QGraphicsProxyWidget::keyPressEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ view.viewport()->setFocus();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+
+ QLineEdit *widget = new QLineEdit;
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::keyPress(view.viewport(), 'x');
+
+ QTRY_COMPARE(widget->text(), hasWidget ? QString("x") : QString());
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::keyReleaseEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void keyReleaseEvent(QKeyEvent* event)
+void tst_QGraphicsProxyWidget::keyReleaseEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ QPushButton *widget = new QPushButton;
+ QSignalSpy spy(widget, SIGNAL(clicked()));
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::keyPress(view.viewport(), Qt::Key_Space);
+ QTRY_COMPARE(spy.count(), 0);
+ QTest::keyRelease(view.viewport(), Qt::Key_Space);
+ QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::mouseDoubleClickEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+void tst_QGraphicsProxyWidget::mouseDoubleClickEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ QLineEdit *widget = new QLineEdit;
+ widget->setText("foo");
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+
+ QTRY_COMPARE(widget->selectedText(), hasWidget ? QString("foo") : QString());
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::mousePressReleaseEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void mousePressEvent(QGraphicsSceneMouseEvent* event)
+void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ QPushButton *widget = new QPushButton;
+ QSignalSpy spy(widget, SIGNAL(clicked()));
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTRY_COMPARE(spy.count(), 0);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::resizeEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void resizeEvent(QGraphicsSceneResizeEvent* event)
+void tst_QGraphicsProxyWidget::resizeEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ if (hasWidget)
+ proxy.setWidget(widget);
+
+ QSize newSize(100, 100);
+ QGraphicsSceneResizeEvent event;
+ event.setOldSize(QSize(10, 10));
+ event.setNewSize(newSize);
+ proxy.call_resizeEvent(&event);
+ if (hasWidget)
+ QCOMPARE(widget->size(), newSize);
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::paintEvent()
+{
+ //we test that calling update on a widget inside a QGraphicsView is triggering a repaint
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.isActiveWindow());
+
+ SubQGraphicsProxyWidget proxy;
+
+ QWidget *w = new QWidget;
+ //showing the widget here seems to create a bug in Graphics View
+ //this bug prevents the widget from being updated
+
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ QApplication::processEvents();
+ QTest::qWait(30);
+ proxy.setWidget(w);
+ scene.addItem(&proxy);
+
+ //make sure we flush all the paint events
+ QTRY_VERIFY(proxy.paintCount > 1);
+ QTest::qWait(30);
+ proxy.paintCount = 0;
+
+ w->update();
+ QTRY_COMPARE(proxy.paintCount, 1); //the widget should have been painted now
+}
+
+
+void tst_QGraphicsProxyWidget::wheelEvent()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ WheelWidget *wheelWidget = new WheelWidget();
+ wheelWidget->setFixedSize(400, 400);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(wheelWidget);
+ proxy->setVisible(true);
+
+ QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel);
+ event.setScenePos(QPoint(50, 50));
+ event.setAccepted(false);
+ wheelWidget->wheelEventCalled = false;
+
+ QApplication::sendEvent(&scene, &event);
+
+ QVERIFY(event.isAccepted());
+ QVERIFY(wheelWidget->wheelEventCalled);
+}
+
+Q_DECLARE_METATYPE(Qt::SizeHint)
+void tst_QGraphicsProxyWidget::sizeHint_data()
+{
+ QTest::addColumn<Qt::SizeHint>("which");
+ QTest::addColumn<QSizeF>("constraint");
+ QTest::addColumn<QSizeF>("sizeHint");
+ QTest::addColumn<bool>("hasWidget");
+
+ for (int i = 0; i < 2; ++i) {
+ bool hasWidget = (i == 0);
+ // ### What should these do?
+ QTest::newRow("min") << Qt::MinimumSize << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("pre") << Qt::PreferredSize << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("max") << Qt::MaximumSize << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("mindes") << Qt::MinimumDescent << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("nsize") << Qt::NSizeHints << QSizeF() << QSizeF() << hasWidget;
+ }
+}
+
+// protected QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+void tst_QGraphicsProxyWidget::sizeHint()
+{
+ QFETCH(Qt::SizeHint, which);
+ QFETCH(QSizeF, constraint);
+ QFETCH(QSizeF, sizeHint);
+ QFETCH(bool, hasWidget);
+ QSKIP("Broken test", SkipAll);
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ if (hasWidget)
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.call_sizeHint(which, constraint), sizeHint);
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::sizePolicy()
+{
+ for (int p = 0; p < 2; ++p) {
+ bool hasWidget = (p == 0 ? true : false);
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ QSizePolicy proxyPol(QSizePolicy::Maximum, QSizePolicy::Expanding);
+ proxy.setSizePolicy(proxyPol);
+ QSizePolicy widgetPol(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ widget->setSizePolicy(widgetPol);
+
+ QCOMPARE(proxy.sizePolicy(), proxyPol);
+ QCOMPARE(widget->sizePolicy(), widgetPol);
+ if (hasWidget) {
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.sizePolicy(), widgetPol);
+ } else {
+ QCOMPARE(proxy.sizePolicy(), proxyPol);
+ }
+ QCOMPARE(widget->sizePolicy(), widgetPol);
+
+ proxy.setSizePolicy(widgetPol);
+ widget->setSizePolicy(proxyPol);
+ if (hasWidget)
+ QCOMPARE(proxy.sizePolicy(), proxyPol);
+ else
+ QCOMPARE(proxy.sizePolicy(), widgetPol);
+ }
+}
+
+void tst_QGraphicsProxyWidget::minimumSize()
+{
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ QSize minSize(50, 50);
+ widget->setMinimumSize(minSize);
+ proxy.resize(30, 30);
+ widget->resize(30,30);
+ QCOMPARE(proxy.size(), QSizeF(30, 30));
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.size().toSize(), minSize);
+ QCOMPARE(proxy.minimumSize().toSize(), minSize);
+ widget->setMinimumSize(70, 70);
+ QCOMPARE(proxy.minimumSize(), QSizeF(70, 70));
+ QCOMPARE(proxy.size(), QSizeF(70, 70));
+}
+
+void tst_QGraphicsProxyWidget::maximumSize()
+{
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ QSize maxSize(150, 150);
+ widget->setMaximumSize(maxSize);
+ proxy.resize(200, 200);
+ widget->resize(200,200);
+ QCOMPARE(proxy.size(), QSizeF(200, 200));
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.size().toSize(), maxSize);
+ QCOMPARE(proxy.maximumSize().toSize(), maxSize);
+ widget->setMaximumSize(70, 70);
+ QCOMPARE(proxy.maximumSize(), QSizeF(70, 70));
+ QCOMPARE(proxy.size(), QSizeF(70, 70));
+}
+
+class View : public QGraphicsView
+{
+public:
+ View(QGraphicsScene *scene, QWidget *parent = 0)
+ : QGraphicsView(scene, parent), npaints(0)
+ { }
+ QRegion paintEventRegion;
+ int npaints;
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ ++npaints;
+ paintEventRegion += event->region();
+ QGraphicsView::paintEvent(event);
+ }
+};
+
+class ScrollWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ScrollWidget() : npaints(0)
+ {
+ resize(200, 200);
+ }
+ QRegion paintEventRegion;
+ int npaints;
+
+public slots:
+ void updateScroll()
+ {
+ update(0, 0, 200, 10);
+ scroll(0, 10, QRect(0, 0, 100, 20));
+ }
+
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ ++npaints;
+ paintEventRegion += event->region();
+ QPainter painter(this);
+ painter.fillRect(event->rect(), Qt::blue);
+ }
+};
+
+void tst_QGraphicsProxyWidget::scrollUpdate()
+{
+ ScrollWidget *widget = new ScrollWidget;
+
+ QGraphicsScene scene;
+ scene.addWidget(widget);
+
+ View view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.npaints >= 1);
+ QTest::qWait(20);
+ widget->paintEventRegion = QRegion();
+ widget->npaints = 0;
+ view.paintEventRegion = QRegion();
+ view.npaints = 0;
+ QTimer::singleShot(0, widget, SLOT(updateScroll()));
+ QTRY_COMPARE(view.npaints, 2);
+ // QRect(0, 0, 200, 12) is the first update, expanded (-2, -2, 2, 2)
+ // QRect(0, 12, 102, 10) is the scroll update, expanded (-2, -2, 2, 2),
+ // intersected with the above update.
+ QCOMPARE(view.paintEventRegion.rects(),
+ QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
+ QCOMPARE(widget->npaints, 2);
+ QCOMPARE(widget->paintEventRegion.rects(),
+ QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
+}
+
+void tst_QGraphicsProxyWidget::setWidget_simple()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+
+ QVERIFY(lineEdit->testAttribute(Qt::WA_DontShowOnScreen));
+ // Size hints
+ // ### size hints are tested in a different test
+ // QCOMPARE(proxy.effectiveSizeHint(Qt::MinimumSize).toSize(), lineEdit->minimumSizeHint());
+ // QCOMPARE(proxy.effectiveSizeHint(Qt::MaximumSize).toSize(), lineEdit->maximumSize());
+ // QCOMPARE(proxy.effectiveSizeHint(Qt::PreferredSize).toSize(), lineEdit->sizeHint());
+ QCOMPARE(proxy.size().toSize(), lineEdit->minimumSizeHint().expandedTo(lineEdit->size()));
+ QRect rect = lineEdit->rect();
+ rect.setSize(rect.size().expandedTo(lineEdit->minimumSizeHint()));
+ QCOMPARE(proxy.rect().toRect(), rect);
+
+ // Properties
+ // QCOMPARE(proxy.focusPolicy(), lineEdit->focusPolicy());
+ // QCOMPARE(proxy.palette(), lineEdit->palette());
+#ifndef QT_NO_CURSOR
+ QCOMPARE(proxy.cursor().shape(), lineEdit->cursor().shape());
+#endif
+ QCOMPARE(proxy.layoutDirection(), lineEdit->layoutDirection());
+ QCOMPARE(proxy.style(), lineEdit->style());
+ QCOMPARE(proxy.font(), lineEdit->font());
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+}
+
+void tst_QGraphicsProxyWidget::setWidget_ownership()
+{
+ QPointer<QLineEdit> lineEdit = new QLineEdit;
+ QPointer<QLineEdit> lineEdit2 = new QLineEdit;
+ QVERIFY(lineEdit);
+ {
+ // Create a proxy and transfer ownership to it
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(lineEdit);
+ QCOMPARE(proxy.widget(), (QWidget *)lineEdit);
+
+ // Remove the widget without destroying it.
+ proxy.setWidget(0);
+ QVERIFY(!proxy.widget());
+ QVERIFY(lineEdit);
+
+ // Assign the widget again and switch to another widget.
+ proxy.setWidget(lineEdit);
+ proxy.setWidget(lineEdit2);
+ QCOMPARE(proxy.widget(), (QWidget *)lineEdit2);
+
+ // Assign the first widget, and destroy the proxy.
+ proxy.setWidget(lineEdit);
+ }
+ QVERIFY(!lineEdit);
+ QVERIFY(lineEdit2);
+
+ QGraphicsScene scene;
+ QPointer<QGraphicsProxyWidget> proxy = scene.addWidget(lineEdit2);
+
+ delete lineEdit2;
+ QVERIFY(!proxy);
+}
+
+void tst_QGraphicsProxyWidget::resize_simple_data()
+{
+ QTest::addColumn<QSizeF>("size");
+
+ QTest::newRow("200, 200") << QSizeF(200, 200);
+#if !defined(QT_ARCH_ARM) && !defined(Q_OS_WINCE)
+ QTest::newRow("1000, 1000") << QSizeF(1000, 1000);
+ // Since 4.5, 10000x10000 runs out of memory.
+ // QTest::newRow("10000, 10000") << QSizeF(10000, 10000);
+#endif
+}
+
+void tst_QGraphicsProxyWidget::resize_simple()
+{
+ QFETCH(QSizeF, size);
+
+ QGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ widget->setGeometry(0, 0, (int)size.width(), (int)size.height());
+ proxy.setWidget(widget);
+ widget->show();
+ QCOMPARE(widget->pos(), QPoint());
+
+ // The proxy resizes itself, the line edit follows
+ proxy.resize(size);
+ QCOMPARE(proxy.size(), size);
+ QCOMPARE(proxy.size().toSize(), widget->size());
+
+ // The line edit resizes itself, the proxy follows (no loopback/live lock)
+ QSize doubleSize = size.toSize() * 2;
+ widget->resize(doubleSize);
+ QCOMPARE(widget->size(), doubleSize);
+ QCOMPARE(widget->size(), proxy.size().toSize());
+}
+
+void tst_QGraphicsProxyWidget::symmetricMove()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ proxy.setPos(10, 10);
+ QCOMPARE(proxy.pos(), QPointF(10, 10));
+ QCOMPARE(lineEdit->pos(), QPoint(10, 10));
+
+ lineEdit->move(5, 5);
+ QCOMPARE(proxy.pos(), QPointF(5, 5));
+ QCOMPARE(lineEdit->pos(), QPoint(5, 5));
+}
+
+void tst_QGraphicsProxyWidget::symmetricResize()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ proxy.resize(256, 256);
+ QCOMPARE(proxy.size(), QSizeF(256, 256));
+ QCOMPARE(lineEdit->size(), QSize(256, 256));
+
+ lineEdit->resize(512, 512);
+ QCOMPARE(proxy.size(), QSizeF(512, 512));
+ QCOMPARE(lineEdit->size(), QSize(512, 512));
+}
+
+void tst_QGraphicsProxyWidget::symmetricVisible()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+
+ proxy.hide();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ proxy.show();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ lineEdit->hide();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ lineEdit->show();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ }
+
+void tst_QGraphicsProxyWidget::symmetricEnabled()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ proxy.setEnabled(false);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ proxy.setEnabled(true);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ lineEdit->setEnabled(false);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ lineEdit->setEnabled(true);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_simpleWidget()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!leftDial->hasFocus());
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QTRY_VERIFY(rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(!rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QTRY_VERIFY(leftDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_simpleTwoWidgets()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QLineEdit *edit2 = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+ QGraphicsProxyWidget *editProxy2 = scene.addWidget(edit2);
+ editProxy2->show();
+ editProxy2->setPos(0, editProxy->rect().height() * 1.1);
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+ EventSpy eventSpy2(edit2);
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab into second line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(editProxy2->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(!editProxy2->hasFocus());
+ QVERIFY(!edit2->hasFocus());
+ QVERIFY(rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(editProxy2->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QVERIFY(!rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(!editProxy2->hasFocus());
+ QVERIFY(!edit2->hasFocus());
+ QVERIFY(!rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 2);
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(leftDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_complexWidget()
+{
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(edit2);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit1);
+ EventSpy eventSpy2(edit2);
+ EventSpy eventSpyBox(box);
+
+ // Tab into group box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(box->hasFocus());
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit1->hasFocus();
+ QVERIFY(!box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit2->hasFocus();
+ QVERIFY(!edit1->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ rightDial->hasFocus();
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!rightDial->hasFocus());
+ edit2->hasFocus();
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ edit1->hasFocus();
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+
+ // Backtab into line box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit1->hasFocus());
+ box->hasFocus();
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!box->hasFocus());
+ leftDial->hasFocus();
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_complexTwoWidgets()
+{
+ // ### add event spies to this test.
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QFontComboBox *fontComboBox = new QFontComboBox;
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(fontComboBox);
+ vlayout->addWidget(edit2);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QLineEdit *edit1_2 = new QLineEdit;
+ edit1_2->setText("QLineEdit 1_2");
+ QLineEdit *edit2_2 = new QLineEdit;
+ edit2_2->setText("QLineEdit 2_2");
+ QFontComboBox *fontComboBox2 = new QFontComboBox;
+ vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1_2);
+ vlayout->addWidget(fontComboBox2);
+ vlayout->addWidget(edit2_2);
+
+ QGroupBox *box_2 = new QGroupBox("QGroupBox 2");
+ box_2->setCheckable(true);
+ box_2->setChecked(true);
+ box_2->setLayout(vlayout);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+
+ QGraphicsProxyWidget *proxy_2 = scene.addWidget(box_2);
+ proxy_2->setPos(proxy->boundingRect().width() * 1.2, 0);
+ proxy_2->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->setRenderHint(QPainter::Antialiasing);
+ view->rotate(45);
+ view->scale(0.5, 0.5);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit1);
+ EventSpy eventSpy2(edit2);
+ EventSpy eventSpy3(fontComboBox);
+ EventSpy eventSpy1_2(edit1_2);
+ EventSpy eventSpy2_2(edit2_2);
+ EventSpy eventSpy2_3(fontComboBox2);
+ EventSpy eventSpyBox(box);
+
+ // Tab into group box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(box->hasFocus());
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit1->hasFocus();
+ QVERIFY(!box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab to the font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ fontComboBox->hasFocus();
+ QVERIFY(!edit2->hasFocus());
+ QCOMPARE(eventSpy3.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy3.counts[QEvent::FocusOut], 0);
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Tab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit2->hasFocus();
+ QVERIFY(!edit1->hasFocus());
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
+ QCOMPARE(eventSpy3.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Tab into right box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ box_2->hasFocus();
+
+ // Tab into right top line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!box_2->hasFocus());
+ edit1_2->hasFocus();
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit1_2->hasFocus());
+ fontComboBox2->hasFocus();
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusOut], 0);
+
+ // Tab into right bottom line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit1_2->hasFocus());
+ edit2_2->hasFocus();
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ rightDial->hasFocus();
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!rightDial->hasFocus());
+ edit2_2->hasFocus();
+
+ // Backtab into the right font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2_2->hasFocus());
+ fontComboBox2->hasFocus();
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2_2->hasFocus());
+ edit1_2->hasFocus();
+
+ // Backtab into line box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit1_2->hasFocus());
+ box_2->hasFocus();
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!rightDial->hasFocus());
+ edit2->hasFocus();
+
+ // Backtab into the font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ fontComboBox->hasFocus();
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!fontComboBox->hasFocus());
+ edit1->hasFocus();
+
+ // Backtab into line box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit1->hasFocus());
+ box->hasFocus();
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!box->hasFocus());
+ leftDial->hasFocus();
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::setFocus_simpleWidget()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+
+ // Calling setFocus for the line edit when the view doesn't have input
+ // focus does not steal focus from the dial. The edit, proxy and scene
+ // have focus but only in their own little space.
+ edit->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(leftDial->hasFocus());
+
+ // Clearing focus is a local operation.
+ edit->clearFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(!view->hasFocus());
+ QVERIFY(leftDial->hasFocus());
+
+ view->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ scene.clearFocus();
+ QVERIFY(!scene.hasFocus());
+
+ edit->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(editProxy->hasFocus());
+
+ // Symmetry
+ editProxy->clearFocus();
+ QVERIFY(!edit->hasFocus());
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::setFocus_simpleTwoWidgets()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+ QLineEdit *edit2 = new QLineEdit;
+ QGraphicsProxyWidget *edit2Proxy = scene.addWidget(edit2);
+ edit2Proxy->show();
+ edit2Proxy->setPos(editProxy->boundingRect().width() * 1.01, 0);
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+
+ view->setFocus();
+ QVERIFY(!edit->hasFocus());
+
+ edit->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(editProxy->hasFocus());
+
+ edit2->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QVERIFY(edit2Proxy->hasFocus());
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::setFocus_complexTwoWidgets()
+{
+ // ### add event spies to this test.
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(edit2);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QLineEdit *edit1_2 = new QLineEdit;
+ edit1_2->setText("QLineEdit 1_2");
+ QLineEdit *edit2_2 = new QLineEdit;
+ edit2_2->setText("QLineEdit 2_2");
+ vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1_2);
+ vlayout->addWidget(edit2_2);
+
+ QGroupBox *box_2 = new QGroupBox("QGroupBox 2");
+ box_2->setCheckable(true);
+ box_2->setChecked(true);
+ box_2->setLayout(vlayout);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+
+ QGraphicsProxyWidget *proxy_2 = scene.addWidget(box_2);
+ proxy_2->setPos(proxy->boundingRect().width() * 1.2, 0);
+ proxy_2->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit1);
+ EventSpy eventSpy2(edit2);
+ EventSpy eventSpyBox(box);
+ EventSpy eventSpy_2(edit1_2);
+ EventSpy eventSpy2_2(edit2_2);
+ EventSpy eventSpyBox_2(box_2);
+
+ view->setFocus();
+
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 0);
+
+ edit1->setFocus();
+ QApplication::processEvents();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit1->hasFocus());
+ QVERIFY(!box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 0);
+
+ edit2_2->setFocus();
+ QApplication::processEvents();
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(!box_2->hasFocus());
+ QVERIFY(edit2_2->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
+
+ box->setFocus();
+ QApplication::processEvents();
+ QVERIFY(!edit2_2->hasFocus());
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusOut], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusOut], 0);
+
+ edit2_2->setFocus();
+ QApplication::processEvents();
+ QVERIFY(edit2_2->hasFocus());
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(!box->hasFocus());
+ QVERIFY(!box_2->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusOut], 0);
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::popup_basic()
+{
+ // ProxyWidget should automatically create proxy's when the widget creates a child
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsView view(scene);
+ view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ view.setGeometry(0, 100, 480, 500);
+ view.show();
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ QComboBox *box = new QComboBox;
+ box->setGeometry(0, 0, 320, 40);
+ box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
+ << "thursday" << "saturday" << "sunday");
+ QCOMPARE(proxy->childItems().count(), 0);
+ proxy->setWidget(box);
+ proxy->show();
+ scene->addItem(proxy);
+
+ QCOMPARE(box->pos(), QPoint());
+ QCOMPARE(proxy->pos(), QPointF());
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(125);
+ QApplication::processEvents();
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+
+ QTRY_COMPARE(box->pos(), QPoint());
+
+ QCOMPARE(proxy->childItems().count(), 1);
+ QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0];
+ QVERIFY(child->isWidget());
+ QVERIFY(child->widget());
+ QStyleOptionComboBox opt;
+ opt.initFrom(box);
+ opt.editable = box->isEditable();
+ if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
+ QSKIP("Does not work due to SH_Combobox_Popup", SkipAll);
+ QCOMPARE(child->widget()->parent(), static_cast<QObject*>(box));
+
+ QTRY_COMPARE(proxy->pos(), QPointF(box->pos()));
+ QCOMPARE(child->x(), qreal(box->x()));
+ QCOMPARE(child->y(), qreal(box->rect().bottom()));
+#ifndef Q_OS_WIN
+ // The popup's coordinates on Windows are in global space,
+ // regardless.
+ QCOMPARE(child->widget()->x(), box->x());
+ QCOMPARE(child->widget()->y(), box->rect().bottom());
+ QCOMPARE(child->geometry().toRect(), child->widget()->geometry());
+#endif
+ QTest::qWait(12);
+}
+
+void tst_QGraphicsProxyWidget::popup_subwidget()
+{
+ QGroupBox *groupBox = new QGroupBox;
+ groupBox->setTitle("GroupBox");
+ groupBox->setCheckable(true);
+
+ QComboBox *box = new QComboBox;
+ box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
+ << "thursday" << "saturday" << "sunday");
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QLineEdit("QLineEdit"));
+ layout->addWidget(box);
+ layout->addWidget(new QLineEdit("QLineEdit"));
+ groupBox->setLayout(layout);
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *groupBoxProxy = scene.addWidget(groupBox);
+ groupBox->show();
+ groupBox->move(10000, 10000);
+ QCOMPARE(groupBox->pos(), QPoint(10000, 10000));
+ QCOMPARE(groupBoxProxy->pos(), QPointF(10000, 10000));
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ box->showPopup();
+
+ QVERIFY(!groupBoxProxy->childItems().isEmpty());
+
+ QStyleOptionComboBox opt;
+ opt.initFrom(box);
+ opt.editable = box->isEditable();
+ if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
+ QSKIP("Does not work due to SH_Combobox_Popup", SkipAll);
+ QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(groupBoxProxy->childItems())[0];
+ QWidget *popup = child->widget();
+ QCOMPARE(popup->parent(), static_cast<QObject*>(box));
+ QCOMPARE(popup->x(), box->mapToGlobal(QPoint()).x());
+ QCOMPARE(popup->y(), QRect(box->mapToGlobal(QPoint()), box->size()).bottom());
+ QCOMPARE(popup->size(), child->size().toSize());
+}
+
+#if !defined(QT_NO_CURSOR) && (!defined(Q_OS_WINCE) || defined(GWES_ICONCURS))
+void tst_QGraphicsProxyWidget::changingCursor_basic()
+{
+ // Confirm that mouse events are working properly by checking that
+ // when moving the mouse over a line edit it will change the cursor into the I
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ QLineEdit *widget = new QLineEdit;
+ proxy->setWidget(widget);
+ proxy->show();
+ scene.addItem(proxy);
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+ QTRY_VERIFY(view.isActiveWindow());
+
+ // in
+ QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ sendMouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+
+ // out
+ QTest::mouseMove(view.viewport(), QPoint(1, 1));
+ sendMouseMove(view.viewport(), QPoint(1, 1));
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
+}
+#endif
+
+void tst_QGraphicsProxyWidget::tooltip_basic()
+{
+ QString toolTip = "Qt rocks!";
+ QString toolTip2 = "Qt rocks even more!";
+
+ QPushButton *button = new QPushButton("button");
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget;
+ QGraphicsProxyWidgetPrivate *proxyd = static_cast<QGraphicsProxyWidgetPrivate *>(QGraphicsItemPrivate::get(proxy));
+ proxy->setWidget(button);
+ proxyd->lastWidgetUnderMouse = button; // force widget under mouse
+
+ QVERIFY(button->toolTip().isEmpty());
+ QVERIFY(proxy->toolTip().isEmpty());
+ // Check that setting the tooltip on the proxy also set it on the widget
+ proxy->setToolTip(toolTip);
+ QCOMPARE(proxy->toolTip(), toolTip);
+ QCOMPARE(button->toolTip(), toolTip);
+ // Check that setting the tooltip on the widget also set it on the proxy
+ button->setToolTip(toolTip2);
+ QCOMPARE(proxy->toolTip(), toolTip2);
+ QCOMPARE(button->toolTip(), toolTip2);
+
+ QGraphicsScene scene;
+ scene.addItem(proxy);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(350);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(!foundTipLabel);
+ }
+
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.mapFromScene(proxy->boundingRect().center()),
+ view.viewport()->mapToGlobal(view.mapFromScene(proxy->boundingRect().center())));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(350);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(foundTipLabel);
+ }
+}
+
+void tst_QGraphicsProxyWidget::childPos_data()
+{
+ QTest::addColumn<bool>("moveCombo");
+ QTest::addColumn<QPoint>("comboPos");
+ QTest::addColumn<QPointF>("proxyPos");
+ QTest::addColumn<QPointF>("menuPos");
+
+ QTest::newRow("0") << true << QPoint() << QPointF() << QPointF();
+ QTest::newRow("1") << true << QPoint(10, 0) << QPointF(10, 0) << QPointF();
+ QTest::newRow("2") << true << QPoint(100, 0) << QPointF(100, 0) << QPointF();
+ QTest::newRow("3") << true << QPoint(1000, 0) << QPointF(1000, 0) << QPointF();
+ QTest::newRow("4") << true << QPoint(10000, 0) << QPointF(10000, 0) << QPointF();
+ QTest::newRow("5") << true << QPoint(-10000, 0) << QPointF(-10000, 0) << QPointF();
+ QTest::newRow("6") << true << QPoint(-1000, 0) << QPointF(-1000, 0) << QPointF();
+ QTest::newRow("7") << true << QPoint(-100, 0) << QPointF(-100, 0) << QPointF();
+ QTest::newRow("8") << true << QPoint(-10, 0) << QPointF(-10, 0) << QPointF();
+ QTest::newRow("0-") << false << QPoint() << QPointF() << QPointF();
+ QTest::newRow("1-") << false << QPoint(10, 0) << QPointF(10, 0) << QPointF();
+ QTest::newRow("2-") << false << QPoint(100, 0) << QPointF(100, 0) << QPointF();
+ QTest::newRow("3-") << false << QPoint(1000, 0) << QPointF(1000, 0) << QPointF();
+ QTest::newRow("4-") << false << QPoint(10000, 0) << QPointF(10000, 0) << QPointF();
+ QTest::newRow("5-") << false << QPoint(-10000, 0) << QPointF(-10000, 0) << QPointF();
+ QTest::newRow("6-") << false << QPoint(-1000, 0) << QPointF(-1000, 0) << QPointF();
+ QTest::newRow("7-") << false << QPoint(-100, 0) << QPointF(-100, 0) << QPointF();
+ QTest::newRow("8-") << false << QPoint(-10, 0) << QPointF(-10, 0) << QPointF();
+}
+
+void tst_QGraphicsProxyWidget::childPos()
+{
+#ifdef Q_OS_IRIX
+ QSKIP("This test is not reliable on IRIX.", SkipAll);
+#endif
+ QFETCH(bool, moveCombo);
+ QFETCH(QPoint, comboPos);
+ QFETCH(QPointF, proxyPos);
+ QFETCH(QPointF, menuPos);
+
+ QGraphicsScene scene;
+
+ QComboBox *box = new QComboBox;
+ box->addItem("Item 1");
+ box->addItem("Item 2");
+ box->addItem("Item 3");
+ box->addItem("Item 4");
+
+ if (moveCombo)
+ box->move(comboPos);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+ QVERIFY(proxy->isVisible());
+ QVERIFY(box->isVisible());
+
+ if (!moveCombo)
+ proxy->setPos(proxyPos);
+
+ QCOMPARE(proxy->pos(), proxyPos);
+ QCOMPARE(box->pos(), comboPos);
+
+ for (int i = 0; i < 2; ++i) {
+ box->showPopup();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ QWidget *menu = 0;
+ foreach (QObject *child, box->children()) {
+ if ((menu = qobject_cast<QWidget *>(child)))
+ break;
+ }
+ QVERIFY(menu);
+ QVERIFY(menu->isVisible());
+ QVERIFY(menu->testAttribute(Qt::WA_DontShowOnScreen));
+
+ QCOMPARE(proxy->childItems().size(), 1);
+ QGraphicsProxyWidget *proxyChild = 0;
+ foreach (QGraphicsItem *child, proxy->childItems()) {
+ if (child->isWidget() && (proxyChild = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))))
+ break;
+ }
+ QVERIFY(proxyChild);
+ QVERIFY(proxyChild->isVisible());
+ qreal expectedXPosition = 0.0;
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+ // The Mac style wants the popup to show up at QPoint(4 - 11, 1).
+ // See QMacStyle::subControlRect SC_ComboBoxListBoxPopup.
+ if (qobject_cast<QMacStyle *>(QApplication::style()))
+ expectedXPosition = qreal(4 - 11);
+#endif
+ QCOMPARE(proxyChild->pos().x(), expectedXPosition);
+ menu->hide();
+ }
+}
+
+void tst_QGraphicsProxyWidget::autoShow()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsProxyWidget *proxy1 = scene.addWidget(new QPushButton("Button1"));
+
+ QPushButton *button2 = new QPushButton("Button2");
+ button2->hide();
+ QGraphicsProxyWidget *proxy2 = new QGraphicsProxyWidget();
+ proxy2->setWidget(button2);
+ scene.addItem(proxy2);
+
+ view.show();
+ QApplication::processEvents();
+
+ QCOMPARE(proxy1->isVisible(), true);
+ QCOMPARE(proxy2->isVisible(), false);
+
+}
+
+Q_DECLARE_METATYPE(QList<QRectF>)
+void tst_QGraphicsProxyWidget::windowOpacity()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QWidget *widget = new QWidget;
+ widget->resize(100, 100);
+ QGraphicsProxyWidget *proxy = scene.addWidget(widget);
+ proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::sendPostedEvents();
+ QTRY_VERIFY(view.isActiveWindow());
+
+ qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
+ QSignalSpy signalSpy(&scene, SIGNAL(changed(const QList<QRectF> &)));
+
+ EventSpy eventSpy(widget);
+ QVERIFY(widget->isVisible());
+
+ widget->setWindowOpacity(0.5);
+ QApplication::processEvents();
+
+ // Make sure setWindowOpacity triggers an update on the scene,
+ // and not on the widget or the proxy itself. The entire proxy needs an update
+ // in case it has a window decoration. Update: QGraphicsItem::CacheMode is
+ // disabled on platforms without alpha channel support in QPixmap (e.g.,
+ // X11 without XRender).
+ int paints = 0;
+#ifdef Q_WS_X11
+ paints = !X11->use_xrender;
+#endif
+ QTRY_COMPARE(eventSpy.counts[QEvent::UpdateRequest], 0);
+ QTRY_COMPARE(eventSpy.counts[QEvent::Paint], paints);
+
+ QCOMPARE(signalSpy.count(), 1);
+ const QList<QVariant> arguments = signalSpy.takeFirst();
+ const QList<QRectF> updateRects = qvariant_cast<QList<QRectF> >(arguments.at(0));
+ QCOMPARE(updateRects.size(), 1);
+ QCOMPARE(updateRects.at(0), proxy->sceneBoundingRect());
+}
+
+void tst_QGraphicsProxyWidget::stylePropagation()
+{
+ QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
+
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(edit);
+
+ EventSpy editSpy(edit);
+ EventSpy proxySpy(&proxy);
+
+ // Widget to proxy
+ QCOMPARE(proxy.style(), QApplication::style());
+ edit->setStyle(windowsStyle);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 1);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 1);
+ QCOMPARE(proxy.style(), (QStyle *)windowsStyle);
+ edit->setStyle(0);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 2);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 2);
+ QCOMPARE(proxy.style(), QApplication::style());
+ QCOMPARE(edit->style(), QApplication::style());
+ QVERIFY(windowsStyle); // not deleted
+
+ // Proxy to widget
+ proxy.setStyle(windowsStyle);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 3);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 3);
+ QCOMPARE(edit->style(), (QStyle *)windowsStyle);
+ proxy.setStyle(0);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 4);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 4);
+ QCOMPARE(proxy.style(), QApplication::style());
+ QCOMPARE(edit->style(), QApplication::style());
+ QVERIFY(windowsStyle); // not deleted
+
+ delete windowsStyle;
+}
+
+void tst_QGraphicsProxyWidget::palettePropagation()
+{
+ // Construct a palette with an unlikely setup
+ QPalette lineEditPalette = QApplication::palette("QLineEdit");
+ QPalette palette = lineEditPalette;
+ palette.setBrush(QPalette::Text, Qt::red);
+
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(edit);
+
+ EventSpy editSpy(edit);
+ EventSpy proxySpy(&proxy);
+
+ // Widget to proxy (no change)
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ edit->setPalette(palette);
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 1);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 0);
+ QVERIFY(edit->testAttribute(Qt::WA_SetPalette));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(proxy.palette(), QPalette());
+ edit->setPalette(QPalette());
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 2);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 0);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(proxy.palette(), QPalette());
+
+ // Proxy to widget
+ proxy.setPalette(palette);
+ QVERIFY(proxy.testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 3);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 1);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(edit->palette(), palette);
+ QCOMPARE(edit->palette(), proxy.palette());
+ QCOMPARE(edit->palette().color(QPalette::Text), QColor(Qt::red));
+ proxy.setPalette(QPalette());
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 4);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 2);
+ QCOMPARE(edit->palette(), lineEditPalette);
+}
+
+void tst_QGraphicsProxyWidget::fontPropagation()
+{
+ // Construct a font with an unlikely setup
+ QGraphicsScene scene;
+ QFont lineEditFont = QApplication::font("QLineEdit");
+ QFont font = lineEditFont;
+ font.setPointSize(43);
+
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(edit);
+
+ scene.addItem(&proxy);
+ EventSpy editSpy(edit);
+ EventSpy proxySpy(&proxy);
+
+ // Widget to proxy (no change)
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ edit->setFont(font);
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 1);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 0);
+ QVERIFY(edit->testAttribute(Qt::WA_SetFont));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
+ QCOMPARE(proxy.font(), lineEditFont);
+ edit->setFont(QFont());
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 2);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 0);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
+ QCOMPARE(proxy.font(), lineEditFont);
+
+ // Proxy to widget
+ proxy.setFont(font);
+ QApplication::processEvents(); // wait for QEvent::Polish
+ QVERIFY(proxy.testAttribute(Qt::WA_SetFont));
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 3);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 1);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ QCOMPARE(edit->font(), font);
+ QCOMPARE(edit->font(), proxy.font());
+ QCOMPARE(edit->font().pointSize(), 43);
+ proxy.setFont(QFont());
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 4);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 2);
+ QCOMPARE(edit->font(), lineEditFont);
+
+ proxy.setFont(font);
+ QLineEdit *edit2 = new QLineEdit;
+ proxy.setWidget(edit2);
+ delete edit;
+ QCOMPARE(edit2->font().pointSize(), 43);
+}
+
+class MainWidget : public QMainWindow
+{
+Q_OBJECT
+public:
+ MainWidget() : QMainWindow() {
+ view = new QGraphicsView(this);
+ scene = new QGraphicsScene(this);
+ item = new QGraphicsWidget();
+ widget = new QGraphicsProxyWidget(item);
+ layout = new QGraphicsLinearLayout(item);
+ layout->addItem(widget);
+ item->setLayout(layout);
+ button = new QPushButton("Push me");
+ widget->setWidget(button);
+ setCentralWidget(view);
+ scene->addItem(item);
+ view->setScene(scene);
+ scene->setFocusItem(item);
+ layout->activate();
+ }
+ QGraphicsView* view;
+ QGraphicsScene* scene;
+ QGraphicsWidget * item;
+ QGraphicsLinearLayout * layout;
+ QGraphicsProxyWidget * widget;
+ QPushButton * button;
+};
+
+void tst_QGraphicsProxyWidget::dontCrashWhenDie()
+{
+ MainWidget *w = new MainWidget();
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ QTest::qWait(100);
+ QTest::mouseMove(w->view->viewport(), w->view->mapFromScene(w->widget->mapToScene(w->widget->boundingRect().center())));
+ delete w->item;
+
+ QApplication::processEvents();
+ delete w;
+}
+
+void tst_QGraphicsProxyWidget::createProxyForChildWidget()
+{
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QCheckBox *checkbox = new QCheckBox("QCheckBox");
+ QVBoxLayout *vlayout = new QVBoxLayout;
+
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(edit2);
+ vlayout->addWidget(checkbox);
+ vlayout->insertStretch(-1);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(box);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ QVERIFY(window.graphicsProxyWidget() == 0);
+ QVERIFY(checkbox->graphicsProxyWidget() == 0);
+
+ QGraphicsProxyWidget *windowProxy = scene.addWidget(&window);
+ QGraphicsView view(&scene);
+ view.show();
+ view.resize(500,500);
+
+ QVERIFY(window.graphicsProxyWidget() == windowProxy);
+ QVERIFY(box->graphicsProxyWidget() == 0);
+ QVERIFY(checkbox->graphicsProxyWidget() == 0);
+
+ QPointer<QGraphicsProxyWidget> checkboxProxy = windowProxy->createProxyForChildWidget(checkbox);
+
+ QGraphicsProxyWidget *boxProxy = box->graphicsProxyWidget();
+
+ QVERIFY(boxProxy);
+ QVERIFY(checkbox->graphicsProxyWidget() == checkboxProxy);
+ QVERIFY(checkboxProxy->parentItem() == boxProxy);
+ QVERIFY(boxProxy->parentItem() == windowProxy);
+
+ QVERIFY(checkboxProxy->mapToScene(QPointF()) == checkbox->mapTo(&window, QPoint()));
+ QVERIFY(checkboxProxy->size() == checkbox->size());
+ QVERIFY(boxProxy->size() == box->size());
+
+ window.resize(500,500);
+ QVERIFY(windowProxy->size() == QSize(500,500));
+ QVERIFY(checkboxProxy->mapToScene(QPointF()) == checkbox->mapTo(&window, QPoint()));
+ QVERIFY(checkboxProxy->size() == checkbox->size());
+ QVERIFY(boxProxy->size() == box->size());
+
+ QTest::qWait(10);
+
+
+ QSignalSpy spy(checkbox, SIGNAL(clicked()));
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
+ QTRY_COMPARE(spy.count(), 0);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
+ QTRY_COMPARE(spy.count(), 1);
+
+
+
+ boxProxy->setWidget(0);
+
+ QVERIFY(checkbox->graphicsProxyWidget() == 0);
+ QVERIFY(box->graphicsProxyWidget() == 0);
+ QVERIFY(checkboxProxy == 0);
+
+ delete boxProxy;
+}
+
+class ContextMenuWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ContextMenuWidget()
+ : embeddedPopup(false),
+ gotContextMenuEvent(false)
+ { }
+ bool embeddedPopup;
+ bool gotContextMenuEvent;
+protected:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::ContextMenu)
+ QTimer::singleShot(0, this, SLOT(checkMenu()));
+ return QWidget::event(event);
+ }
+ void contextMenuEvent(QContextMenuEvent *)
+ {
+ gotContextMenuEvent = true;
+ }
+
+private slots:
+ void checkMenu()
+ {
+ if (qFindChild<QMenu *>(this))
+ embeddedPopup = true;
+ hide();
+ }
+};
+
+void tst_QGraphicsProxyWidget::actionsContextMenu_data()
+{
+ QTest::addColumn<bool>("actionsContextMenu");
+ QTest::addColumn<bool>("hasFocus");
+
+ QTest::newRow("without actionsContextMenu and with focus") << false << true;
+ QTest::newRow("without actionsContextMenu and without focus") << false << false;
+ QTest::newRow("with actionsContextMenu and focus") << true << true;
+ QTest::newRow("with actionsContextMenu without focus") << true << false;
+}
+
+void tst_QGraphicsProxyWidget::actionsContextMenu()
+{
+ QFETCH(bool, hasFocus);
+ QFETCH(bool, actionsContextMenu);
+
+ ContextMenuWidget *widget = new ContextMenuWidget;
+ if (actionsContextMenu) {
+ widget->addAction(new QAction("item 1", widget));
+ widget->addAction(new QAction("item 2", widget));
+ widget->addAction(new QAction("item 3", widget));
+ widget->setContextMenuPolicy(Qt::ActionsContextMenu);
+ }
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ view.setFocus();
+ QTRY_VERIFY(view.hasFocus());
+
+ if (hasFocus)
+ scene.addWidget(widget)->setFocus();
+ else
+ scene.addWidget(widget)->clearFocus();
+
+ QApplication::processEvents();
+
+ QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse,
+ view.viewport()->rect().center(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().center()));
+ contextMenuEvent.accept();
+ qApp->sendEvent(view.viewport(), &contextMenuEvent);
+
+ if (hasFocus) {
+ if (actionsContextMenu) {
+ //actionsContextMenu embedded popup but no contextMenuEvent (widget has focus)
+ QVERIFY(widget->embeddedPopup);
+ QVERIFY(!widget->gotContextMenuEvent);
+ } else {
+ //no embedded popup but contextMenuEvent (widget has focus)
+ QVERIFY(!widget->embeddedPopup);
+ QVERIFY(widget->gotContextMenuEvent);
+ }
+ } else {
+ //qgraphicsproxywidget doesn't have the focus, the widget must not receive any contextMenuEvent and must not create any QMenu
+ QVERIFY(!widget->embeddedPopup);
+ QVERIFY(!widget->gotContextMenuEvent);
+ }
+
+}
+
+
+void tst_QGraphicsProxyWidget::deleteProxyForChildWidget()
+{
+ QDialog dialog;
+ dialog.resize(320, 120);
+ dialog.move(80, 40);
+
+ QGraphicsScene scene;
+ scene.setSceneRect(QRectF(0, 0, 640, 480));
+ QGraphicsView view(&scene);
+ QComboBox *combo = new QComboBox;
+ combo->addItems(QStringList() << "red" << "green" << "blue" << "white" << "black" << "yellow" << "cyan" << "magenta");
+ dialog.setLayout(new QVBoxLayout);
+ dialog.layout()->addWidget(combo);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(&dialog);
+ view.show();
+
+ proxy->setWidget(0);
+ //just don't crash
+ QApplication::processEvents();
+ delete combo;
+}
+
+void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data()
+{
+ QTest::addColumn<bool>("bypass");
+
+ QTest::newRow("autoembed") << false;
+ QTest::newRow("bypass") << true;
+}
+
+void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
+{
+ QFETCH(bool, bypass);
+
+ QWidget *widget = new QWidget;
+ widget->resize(100, 100);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(widget);
+
+ QCOMPARE(proxy->widget(), widget);
+ QVERIFY(proxy->childItems().isEmpty());
+
+ Qt::WindowFlags flags;
+ flags |= Qt::Dialog;
+ if (bypass)
+ flags |= Qt::BypassGraphicsProxyWidget;
+ QFileDialog *dialog = new QFileDialog(widget, flags);
+ dialog->setOption(QFileDialog::DontUseNativeDialog, true);
+ dialog->show();
+
+ QCOMPARE(proxy->childItems().size(), bypass ? 0 : 1);
+ if (!bypass)
+ QCOMPARE(((QGraphicsProxyWidget *)proxy->childItems().first())->widget(), (QWidget *)dialog);
+
+ dialog->hide();
+ QApplication::processEvents();
+ delete dialog;
+ delete widget;
+}
+
+static void makeDndEvent(QGraphicsSceneDragDropEvent *event, QGraphicsView *view, const QPointF &pos)
+{
+ event->setScenePos(pos);
+ event->setScreenPos(view->mapToGlobal(view->mapFromScene(pos)));
+ event->setButtons(Qt::LeftButton);
+ event->setModifiers(0);
+ event->setPossibleActions(Qt::CopyAction);
+ event->setProposedAction(Qt::CopyAction);
+ event->setDropAction(Qt::CopyAction);
+ event->setWidget(view->viewport());
+ event->setSource(view->viewport());
+ event->ignore();
+}
+
+void tst_QGraphicsProxyWidget::dragDrop()
+{
+ QPushButton *button = new QPushButton; // acceptDrops(false)
+ QLineEdit *edit = new QLineEdit; // acceptDrops(true)
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *buttonProxy = scene.addWidget(button);
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ QVERIFY(buttonProxy->acceptDrops());
+ QVERIFY(editProxy->acceptDrops());
+
+ button->setGeometry(0, 0, 100, 50);
+ edit->setGeometry(0, 60, 100, 50);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ QMimeData data;
+ data.setText("hei");
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragEnter);
+ makeDndEvent(&event, &view, QPointF(50, 25));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
+ makeDndEvent(&event, &view, QPointF(50, 25));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(!event.isAccepted());
+ }
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
+ makeDndEvent(&event, &view, QPointF(50, 75));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDrop);
+ makeDndEvent(&event, &view, QPointF(50, 75));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(edit->text(), QString("hei"));
+}
+
+void tst_QGraphicsProxyWidget::windowFlags_data()
+{
+ QTest::addColumn<int>("proxyFlags");
+ QTest::addColumn<int>("widgetFlags");
+ QTest::addColumn<int>("resultingProxyFlags");
+ QTest::addColumn<int>("resultingWidgetFlags");
+
+ QTest::newRow("proxy(0) widget(0)") << 0 << 0 << 0 << int(Qt::Window);
+ QTest::newRow("proxy(window)") << int(Qt::Window) << 0 << int(Qt::Window) << int(Qt::Window);
+ QTest::newRow("proxy(window) widget(window)") << int(Qt::Window) << int(Qt::Window) << int(Qt::Window) << int(Qt::Window);
+ QTest::newRow("proxy(0) widget(window)") << int(0) << int(Qt::Window) << int(0) << int(Qt::Window);
+}
+
+void tst_QGraphicsProxyWidget::windowFlags()
+{
+ QFETCH(int, proxyFlags);
+ QFETCH(int, widgetFlags);
+ QFETCH(int, resultingProxyFlags);
+ QFETCH(int, resultingWidgetFlags);
+ Qt::WindowFlags proxyWFlags = Qt::WindowFlags(proxyFlags);
+ Qt::WindowFlags widgetWFlags = Qt::WindowFlags(widgetFlags);
+ Qt::WindowFlags resultingProxyWFlags = Qt::WindowFlags(resultingProxyFlags);
+ Qt::WindowFlags resultingWidgetWFlags = Qt::WindowFlags(resultingWidgetFlags);
+
+ QGraphicsProxyWidget proxy(0, proxyWFlags);
+ QVERIFY((proxy.windowFlags() & proxyWFlags) == proxyWFlags);
+
+ QWidget *widget = new QWidget(0, widgetWFlags);
+ QVERIFY((widget->windowFlags() & widgetWFlags) == widgetWFlags);
+
+ proxy.setWidget(widget);
+
+ if (resultingProxyFlags == 0)
+ QVERIFY(!proxy.windowFlags());
+ else
+ QVERIFY((proxy.windowFlags() & resultingProxyWFlags) == resultingProxyWFlags);
+ QVERIFY((widget->windowFlags() & resultingWidgetWFlags) == resultingWidgetWFlags);
+}
+
+void tst_QGraphicsProxyWidget::comboboxWindowFlags()
+{
+ QComboBox *comboBox = new QComboBox;
+ comboBox->addItem("Item 1");
+ comboBox->addItem("Item 2");
+ comboBox->addItem("Item 3");
+ QWidget *embedWidget = comboBox;
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *proxy = scene.addWidget(embedWidget);
+ proxy->setWindowFlags(Qt::Window);
+ QVERIFY(embedWidget->isWindow());
+ QVERIFY(proxy->isWindow());
+
+ comboBox->showPopup();
+
+ QCOMPARE(proxy->childItems().size(), 1);
+ QGraphicsItem *popupProxy = proxy->childItems().first();
+ QVERIFY(popupProxy->isWindow());
+ QVERIFY((static_cast<QGraphicsWidget *>(popupProxy)->windowFlags() & Qt::Popup) == Qt::Popup);
+}
+
+void tst_QGraphicsProxyWidget::updateAndDelete()
+{
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *proxy = scene.addWidget(new QPushButton("Hello World"));
+ View view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTRY_VERIFY(view.npaints > 0);
+
+ const QRect itemDeviceBoundingRect = proxy->deviceTransform(view.viewportTransform())
+ .mapRect(proxy->boundingRect()).toRect();
+ const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+
+ view.npaints = 0;
+ view.paintEventRegion = QRegion();
+
+ // Update and hide.
+ proxy->update();
+ proxy->hide();
+ QTRY_COMPARE(view.npaints, 1);
+ QCOMPARE(view.paintEventRegion, expectedRegion);
+
+ proxy->show();
+ QTest::qWait(50);
+ view.npaints = 0;
+ view.paintEventRegion = QRegion();
+
+ // Update and delete.
+ proxy->update();
+ delete proxy;
+ QTRY_COMPARE(view.npaints, 1);
+ QCOMPARE(view.paintEventRegion, expectedRegion);
+}
+
+class InputMethod_LineEdit : public QLineEdit
+{
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::InputMethod)
+ ++inputMethodEvents;
+ return QLineEdit::event(e);
+ }
+public:
+ int inputMethodEvents;
+};
+
+void tst_QGraphicsProxyWidget::inputMethod()
+{
+ QGraphicsScene scene;
+
+ // check that the proxy is initialized with the correct input method sensitivity
+ for (int i = 0; i < 2; ++i)
+ {
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setAttribute(Qt::WA_InputMethodEnabled, !!i);
+ QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit);
+ QCOMPARE(!!(proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod), !!i);
+ }
+
+ // check that input method events are only forwarded to widgets with focus
+ for (int i = 0; i < 2; ++i)
+ {
+ InputMethod_LineEdit *lineEdit = new InputMethod_LineEdit;
+ lineEdit->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit);
+
+ if (i)
+ lineEdit->setFocus();
+
+ lineEdit->inputMethodEvents = 0;
+ QInputMethodEvent event;
+ qApp->sendEvent(proxy, &event);
+ QCOMPARE(lineEdit->inputMethodEvents, i);
+ }
+
+ scene.clear();
+ QGraphicsView view(&scene);
+ QWidget *w = new QWidget;
+ w->setLayout(new QVBoxLayout(w));
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setEchoMode(QLineEdit::Password);
+ w->layout()->addWidget(lineEdit);
+ lineEdit->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QGraphicsProxyWidget *proxy = scene.addWidget(w);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!(proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod));
+ lineEdit->setFocus();
+ QVERIFY((proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod));
+}
+
+void tst_QGraphicsProxyWidget::clickFocus()
+{
+ QGraphicsScene scene;
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QGraphicsProxyWidget *proxy = scene.addWidget(new QLineEdit);
+
+ QGraphicsView view(&scene);
+
+ {
+ EventSpy proxySpy(proxy);
+ EventSpy widgetSpy(proxy->widget());
+
+ view.setFrameStyle(0);
+ view.resize(300, 300);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
+
+ QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center());
+ // Spontaneous mouse click sets focus on a clickable widget.
+ for (int retry = 0; retry < 50 && !proxy->hasFocus(); retry++)
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1);
+
+ scene.setFocusItem(0);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 1);
+
+ // Non-spontaneous mouse click sets focus if the widget has been clicked before
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(lineEditCenter);
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 2);
+ }
+ }
+
+ scene.setFocusItem(0);
+ proxy->setWidget(new QLineEdit); // resets focusWidget
+
+ {
+ QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center());
+ EventSpy proxySpy(proxy);
+ EventSpy widgetSpy(proxy->widget());
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
+
+ // Non-spontaneous mouse click does not set focus on the embedded widget.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(lineEditCenter);
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 0);
+ }
+
+ scene.setFocusItem(0);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
+
+ // Spontaneous click on non-clickable widget does not give focus.
+ proxy->widget()->setFocusPolicy(Qt::NoFocus);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+
+ // Multiple clicks should only result in one FocusIn.
+ proxy->widget()->setFocusPolicy(Qt::StrongFocus);
+ scene.setFocusItem(0);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(proxy->widget()->hasFocus());
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1);
+ }
+}
+
+void tst_QGraphicsProxyWidget::windowFrameMargins()
+{
+ // Make sure the top margin is non-zero when passing Qt::Window.
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(0, Qt::Window);
+
+ qreal left, top, right, bottom;
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+
+ proxy->setWidget(new QPushButton("testtest"));
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+
+ QGraphicsScene scene;
+ scene.addItem(proxy);
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+
+ proxy->unsetWindowFrameMargins();
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+}
+
+class HoverButton : public QPushButton
+{
+public:
+ HoverButton(QWidget *parent = 0) : QPushButton(parent), hoverLeaveReceived(false)
+ {}
+
+ bool hoverLeaveReceived;
+
+ bool event(QEvent* e)
+ {
+ if(QEvent::HoverLeave == e->type())
+ hoverLeaveReceived = true;
+ return QPushButton::event(e);
+ }
+};
+
+class Scene : public QGraphicsScene
+{
+Q_OBJECT
+public:
+ Scene() {
+ QWidget *background = new QWidget;
+ background->setGeometry(0, 0, 500, 500);
+ hoverButton = new HoverButton;
+ hoverButton->setParent(background);
+ hoverButton->setText("Second button");
+ hoverButton->setGeometry(10, 10, 200, 50);
+ addWidget(background);
+
+ QPushButton *hideButton = new QPushButton("I'm a button with a very very long text");
+ hideButton->setGeometry(10, 10, 400, 50);
+ topButton = addWidget(hideButton);
+ connect(hideButton, SIGNAL(clicked()), this, SLOT(hideButton()));
+ topButton->setFocus();
+ }
+
+ QGraphicsProxyWidget *topButton;
+ HoverButton *hoverButton;
+
+public slots:
+ void hideButton() {
+ QCursor::setPos(600,600);
+ topButton->hide();
+ }
+};
+
+void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
+{
+#if defined(Q_OS_MAC) || defined(Q_OS_WIN) || defined(QT_NO_CURSOR)
+ QSKIP("Test case unstable on this platform", SkipAll);
+#endif
+ QGraphicsView view;
+ Scene scene;
+ view.setScene(&scene);
+ view.resize(600, 600);
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), &view);
+ QCursor::setPos(view.mapToGlobal(view.mapFromScene(scene.topButton->boundingRect().center())));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.topButton->scenePos()));
+ QTRY_COMPARE(scene.hoverButton->hoverLeaveReceived, true);
+}
+
+QTEST_MAIN(tst_QGraphicsProxyWidget)
+#include "tst_qgraphicsproxywidget.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore
new file mode 100644
index 0000000000..df1097ad74
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsscene
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg b/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg
new file mode 100644
index 0000000000..8581d322ba
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data b/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data
new file mode 100644
index 0000000000..8ff3feebb1
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc b/tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc
new file mode 100644
index 0000000000..cac10bef82
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>Ash_European.jpg</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
new file mode 100644
index 0000000000..75b4d84fb4
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
@@ -0,0 +1,20 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsscene.cpp
+RESOURCES += images.qrc
+win32:!wince*: LIBS += -lUser32
+
+!wince*:DEFINES += SRCDIR=\\\"$$PWD\\\"
+DEFINES += QT_NO_CAST_TO_ASCII
+
+wince* {
+ rootFiles.files = Ash_European.jpg graphicsScene_selection.data
+ rootFiles.path = .
+ renderFiles.files = testData\\render\\*
+ renderFiles.path = testData\\render
+ DEPLOYMENT += rootFiles renderFiles
+ DEFINES += SRCDIR=\\\".\\\"
+}
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png
new file mode 100644
index 0000000000..526b897c1c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png
new file mode 100644
index 0000000000..83563872c1
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png
new file mode 100644
index 0000000000..a929621bca
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png
new file mode 100644
index 0000000000..aeaf20ae41
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png
new file mode 100644
index 0000000000..ed80dba118
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png
new file mode 100644
index 0000000000..9b401b41c7
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png
new file mode 100644
index 0000000000..1c5969870d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png
new file mode 100644
index 0000000000..3592744bda
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png
new file mode 100644
index 0000000000..ab15e7228b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png
new file mode 100644
index 0000000000..82e25762fa
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png
new file mode 100644
index 0000000000..934ee4679b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png
new file mode 100644
index 0000000000..aced485c75
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png
new file mode 100644
index 0000000000..5df8ab0612
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png
new file mode 100644
index 0000000000..bb04881763
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png
new file mode 100644
index 0000000000..907dec647d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png
new file mode 100644
index 0000000000..d37313c06d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png
new file mode 100644
index 0000000000..9fbafe48d5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png
new file mode 100644
index 0000000000..1d0253796e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png
new file mode 100644
index 0000000000..bcfda9968b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png
new file mode 100644
index 0000000000..b443a4f991
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png
new file mode 100644
index 0000000000..e6922e0920
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png
new file mode 100644
index 0000000000..a74f218876
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png
new file mode 100644
index 0000000000..6c51907a6d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png
new file mode 100644
index 0000000000..0a37133e31
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png
new file mode 100644
index 0000000000..edc7dc9ce6
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png
new file mode 100644
index 0000000000..e37051f7d2
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png
new file mode 100644
index 0000000000..a185d14ebd
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png
new file mode 100644
index 0000000000..42e07f11ea
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
new file mode 100644
index 0000000000..9ac1573b2a
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -0,0 +1,4710 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#if defined(Q_OS_WINCE)
+#include <ceconfig.h>
+#endif
+
+#include <QtGui>
+#include <QtWidgets>
+#include <private/qgraphicsscene_p.h>
+#include <private/qgraphicssceneindex_p.h>
+#include <math.h>
+#include "../../../gui/painting/qpathclipper/pathcompare.h"
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#include <windows.h>
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("The Graphics View doesn't get the paint events", SkipSingle);
+#else
+#define Q_CHECK_PAINTEVENTS
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+Q_DECLARE_METATYPE(Qt::AspectRatioMode)
+Q_DECLARE_METATYPE(Qt::ItemSelectionMode)
+
+static const int randomX[] = {276, 40, 250, 864, -56, 426, 855, 825, 184, 955, -798, -804, 773,
+ 282, 489, 686, 780, -220, 50, 749, -856, -205, 81, 492, -819, 518,
+ 895, 57, -559, 788, -965, 68, -442, -247, -339, -648, 292, 891,
+ -865, 462, 864, 673, 640, 523, 194, 500, -727, 307, -243, 320,
+ -545, 415, 448, 341, -619, 652, 892, -16, -14, -659, -101, -934,
+ 532, 356, 824, 132, 160, 130, 104, 886, -179, -174, 543, -644, 60,
+ -470, -354, -728, 689, 682, -587, -694, -221, -741, 37, 372, -289,
+ 741, -300, 858, -320, 729, -602, -956, -544, -403, 203, 398, 284,
+ -972, -572, -946, 81, 51, -403, -580, 867, 546, 565, -580, -484,
+ 659, 982, -518, -976, 423, -800, 659, -297, 712, 938, -19, -16,
+ 824, -252, 197, 321, -837, 824, 136, 226, -980, -909, -826, -479,
+ -835, -503, -828, -901, -810, -641, -548, -179, 194, 749, -296, 539,
+ -37, -599, -235, 121, 35, -230, -915, 789, 764, -622, -382, -90, -701,
+ 676, -407, 998, 267, 913, 817, -748, -370, -162, -797, 19, -556, 933,
+ -670, -101, -765, -941, -17, 360, 31, 960, 509, 933, -35, 974, -924,
+ -734, 589, 963, 724, 794, 843, 16, -272, -811, 721, 99, -122, 216,
+ -404, 158, 787, -443, -437, -337, 383, -342, 538, -641, 791, 637,
+ -848, 397, 820, 109, 11, 45, 809, 591, 933, 961, 625, -140, -592,
+ -694, -969, 317, 293, 777, -18, -282, 835, -455, -708, -407, -204,
+ 748, 347, -501, -545, 292, -362, 176, 546, -573, -38, -854, -395,
+ 560, -624, -940, -971, 66, -910, 782, 985};
+
+static const int randomY[] = {603, 70, -318, 843, 450, -637, 199, -527, 407, 964, -54, 620, -207,
+ -736, -700, -476, -706, -142, 837, 621, 522, -98, 232, 292, -267, 900,
+ 615, -356, -415, 783, 290, 462, -857, -314, 677, 36, 772, 424, -72,
+ -121, 547, -533, 537, -656, 289, 508, 914, 601, 434, 588, -779, -714,
+ -368, 628, -276, 432, -1, -929, 638, -36, 253, -922, -943, 979, -34,
+ -268, -193, 601, 686, -330, 165, 98, 75, -691, -605, 617, 773, 617,
+ 619, 238, -42, -405, 17, 384, -472, -846, 520, 110, 591, -217, 936,
+ -373, 731, 734, 810, 961, 881, 939, 379, -905, -137, 437, 298, 688,
+ -71, -204, 573, -120, -821, 489, -722, -926, 529, -113, -243, 543,
+ 868, -301, -781, -549, -842, -489, -80, -910, -928, 51, -91, 324,
+ 204, -92, 867, 723, 248, 709, -357, 591, -365, -379, 266, -649, -95,
+ 205, 551, 355, -631, 79, -186, 795, -7, -225, 46, -410, 665, -874,
+ -618, 845, -548, 443, 471, -644, 606, -607, 59, -619, 288, -244, 529,
+ 690, 349, -738, -611, -879, -642, 801, -178, 823, -748, -552, -247,
+ -223, -408, 651, -62, 949, -795, 171, -107, -210, -207, -842, -86,
+ 436, 528, 366, -178, 245, -695, 665, 613, -948, 667, -620, -979, -949,
+ 905, 181, -412, -467, -437, -774, 750, -10, 54, 205, -674, -290, -924,
+ -361, -463, 912, -702, 622, -542, 220, 115, 832, 451, -38, -952, -230,
+ -588, 864, 234, 225, -303, 493, 246, 153, 338, -378, 377, -819, 140, 136,
+ 467, -849, -326, -533, 166, 252, -994, -699, 904, -566, 621, -752};
+
+class HoverItem : public QGraphicsRectItem
+{
+public:
+ HoverItem()
+ : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), isHovered(false)
+ { setAcceptsHoverEvents(true); }
+
+ bool isHovered;
+
+protected:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ isHovered = (option->state & QStyle::State_MouseOver);
+
+ painter->setOpacity(0.75);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(Qt::darkGray);
+ painter->drawRoundRect(boundingRect().adjusted(3, 3, -3, -3), Qt::darkGray);
+ painter->setPen(Qt::black);
+ if (isHovered) {
+ painter->setBrush(QColor(Qt::blue).light(120));
+ } else {
+ painter->setBrush(Qt::gray);
+ }
+ painter->drawRoundRect(boundingRect().adjusted(0, 0, -5, -5));
+ }
+};
+
+class EventSpy : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class tst_QGraphicsScene : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void construction();
+ void sceneRect();
+ void itemIndexMethod();
+ void bspTreeDepth();
+ void itemsBoundingRect_data();
+ void itemsBoundingRect();
+ void items();
+ void items_QPointF_data();
+ void items_QPointF();
+ void items_QRectF();
+ void items_QRectF_2_data();
+ void items_QRectF_2();
+ void items_QPolygonF();
+ void items_QPolygonF_2();
+ void items_QPainterPath();
+ void items_QPainterPath_2();
+ void selection();
+ void selectionChanged();
+ void selectionChanged2();
+ void addItem();
+ void addEllipse();
+ void addLine();
+ void addPath();
+ void addPixmap();
+ void addRect();
+ void addText();
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+ void removeItem();
+#endif
+ void clear();
+ void focusItem();
+ void focusItemLostFocus();
+ void setFocusItem();
+ void setFocusItem_inactive();
+ void mouseGrabberItem();
+ void hoverEvents_siblings();
+ void hoverEvents_parentChild();
+ void createItemGroup();
+ void mouseEventPropagation();
+ void mouseEventPropagation_ignore();
+ void mouseEventPropagation_focus();
+ void mouseEventPropagation_doubleclick();
+ void mouseEventPropagation_mouseMove();
+#ifndef QT_NO_DRAGANDDROP
+ void dragAndDrop_simple();
+ void dragAndDrop_disabledOrInvisible();
+ void dragAndDrop_propagate();
+#endif
+ void render_data();
+ void render();
+ void renderItemsWithNegativeWidthOrHeight();
+ void contextMenuEvent();
+ void contextMenuEvent_ItemIgnoresTransformations();
+ void update();
+ void update2();
+ void views();
+ void event();
+ void eventsToDisabledItems();
+ void exposedRect();
+ void tabFocus_emptyScene();
+ void tabFocus_sceneWithFocusableItems();
+ void tabFocus_sceneWithFocusWidgets();
+ void tabFocus_sceneWithNestedFocusWidgets();
+ void style();
+ void sorting_data();
+ void sorting();
+ void changedSignal_data();
+ void changedSignal();
+ void stickyFocus_data();
+ void stickyFocus();
+ void sendEvent();
+ void inputMethod_data();
+ void inputMethod();
+ void dispatchHoverOnPress();
+ void initialFocus_data();
+ void initialFocus();
+ void polishItems();
+ void polishItems2();
+ void isActive();
+ void siblingIndexAlwaysValid();
+ void removeFullyTransparentItem();
+ void zeroScale();
+
+ // task specific tests below me
+ void task139710_bspTreeCrash();
+ void task139782_containsItemBoundingRect();
+ void task176178_itemIndexMethodBreaksSceneRect();
+ void task160653_selectionChanged();
+ void task250680_childClip();
+ void taskQTBUG_5904_crashWithDeviceCoordinateCache();
+ void taskQT657_paintIntoCacheWithTransparentParts();
+ void taskQTBUG_7863_paintIntoCacheWithTransparentParts();
+ void taskQT_3674_doNotCrash();
+ void taskQTBUG_15977_renderWithDeviceCoordinateCache();
+ void taskQTBUG_16401_focusItem();
+};
+
+void tst_QGraphicsScene::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QGraphicsScene::construction()
+{
+ QGraphicsScene scene;
+ QCOMPARE(scene.itemsBoundingRect(), QRectF());
+ QVERIFY(scene.items().isEmpty());
+ QVERIFY(scene.items(QPointF()).isEmpty());
+ QVERIFY(scene.items(QRectF()).isEmpty());
+ QVERIFY(scene.items(QPolygonF()).isEmpty());
+ QVERIFY(scene.items(QPainterPath()).isEmpty());
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::collidingItems: cannot find collisions for null item");
+ QVERIFY(scene.collidingItems(0).isEmpty());
+ QVERIFY(!scene.itemAt(QPointF()));
+ QVERIFY(scene.selectedItems().isEmpty());
+ QVERIFY(!scene.focusItem());
+}
+
+void tst_QGraphicsScene::sceneRect()
+{
+ QGraphicsScene scene;
+ QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF)));
+ QCOMPARE(scene.sceneRect(), QRectF());
+ QCOMPARE(sceneRectChanged.count(), 0);
+
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ item->setPos(-5, -5);
+ QCOMPARE(sceneRectChanged.count(), 0);
+
+ QCOMPARE(scene.itemAt(0, 0), item);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ QCOMPARE(sceneRectChanged.count(), 0);
+ QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 10, 10));
+ QCOMPARE(sceneRectChanged.count(), 1);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ item->setPos(0, 0);
+ QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15));
+ QCOMPARE(sceneRectChanged.count(), 2);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ scene.setSceneRect(-100, -100, 10, 10);
+ QCOMPARE(sceneRectChanged.count(), 3);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ QCOMPARE(scene.itemAt(0, 0), item);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10));
+ item->setPos(10, 10);
+ QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10));
+ QCOMPARE(sceneRectChanged.count(), 3);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ scene.setSceneRect(QRectF());
+
+ QCOMPARE(scene.itemAt(10, 10), item);
+ QCOMPARE(scene.itemAt(20, 20), (QGraphicsItem *)0);
+ QCOMPARE(sceneRectChanged.count(), 4);
+ QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 25, 25));
+ QCOMPARE(sceneRectChanged.count(), 5);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+}
+
+void tst_QGraphicsScene::itemIndexMethod()
+{
+ QGraphicsScene scene;
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
+
+#ifdef QT_ARCH_ARM
+ const int minY = -500;
+ const int maxY = 500;
+ const int minX = -500;
+ const int maxX = 500;
+#else
+ const int minY = -1000;
+ const int maxY = 2000;
+ const int minX = -1000;
+ const int maxX = 2000;
+#endif
+
+ QList<QGraphicsItem *> items;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100) {
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ item->setPos(x, y);
+ QCOMPARE(scene.itemAt(x, y), item);
+ items << item;
+ }
+ }
+
+ int n = 0;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ QCOMPARE(scene.itemAt(x, y), items.at(n++));
+ }
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::NoIndex);
+
+ n = 0;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ QCOMPARE(scene.itemAt(x, y), items.at(n++));
+ }
+
+ scene.setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
+
+ n = 0;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ QCOMPARE(scene.itemAt(x, y), items.at(n++));
+ }
+}
+
+void tst_QGraphicsScene::bspTreeDepth()
+{
+ QGraphicsScene scene;
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
+ QCOMPARE(scene.bspTreeDepth(), 0);
+ scene.setBspTreeDepth(1);
+ QCOMPARE(scene.bspTreeDepth(), 1);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::setBspTreeDepth: invalid depth -1 ignored; must be >= 0");
+ scene.setBspTreeDepth(-1);
+ QCOMPARE(scene.bspTreeDepth(), 1);
+}
+
+void tst_QGraphicsScene::items()
+{
+#ifdef QT_ARCH_ARM
+ const int minY = -500;
+ const int maxY = 500;
+ const int minX = -500;
+ const int maxX = 500;
+#else
+ const int minY = -1000;
+ const int maxY = 2000;
+ const int minX = -1000;
+ const int maxX = 2000;
+#endif
+
+ {
+ QGraphicsScene scene;
+
+ QList<QGraphicsItem *> items;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ items << scene.addRect(QRectF(0, 0, 10, 10));
+ }
+ QCOMPARE(scene.items().size(), items.size());
+ scene.itemAt(0, 0); // trigger indexing
+
+ scene.removeItem(items.at(5));
+ delete items.at(5);
+ QVERIFY(!scene.items().contains(0));
+ delete items.at(7);
+ QVERIFY(!scene.items().contains(0));
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsLineItem *l1 = scene.addLine(-5, 0, 5, 0);
+ QGraphicsLineItem *l2 = scene.addLine(0, -5, 0, 5);
+ QVERIFY(!l1->sceneBoundingRect().intersects(l2->sceneBoundingRect()));
+ QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect()));
+ QList<QGraphicsItem *> items;
+ items<<l1<<l2;
+ QCOMPARE(scene.items().size(), items.size());
+ QVERIFY(scene.items(-1, -1, 2, 2).contains(l1));
+ QVERIFY(scene.items(-1, -1, 2, 2).contains(l2));
+ }
+}
+
+void tst_QGraphicsScene::itemsBoundingRect_data()
+{
+ QTest::addColumn<QList<QRectF> >("rects");
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QRectF>("boundingRect");
+
+ QMatrix transformationMatrix;
+ transformationMatrix.translate(50, -50);
+ transformationMatrix.scale(2, 2);
+ transformationMatrix.rotate(90);
+
+ QTest::newRow("none")
+ << QList<QRectF>()
+ << QMatrix()
+ << QRectF();
+ QTest::newRow("{{0, 0, 10, 10}}")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QMatrix()
+ << QRectF(0, 0, 10, 10);
+ QTest::newRow("{{-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
+ << QMatrix()
+ << QRectF(-10, -10, 10, 10);
+ QTest::newRow("{{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
+ << QMatrix()
+ << QRectF(-1000, -1000, 1000, 1000);
+ QTest::newRow("transformed {{0, 0, 10, 10}}")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << transformationMatrix
+ << QRectF(30, -50, 20, 20);
+ QTest::newRow("transformed {{-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
+ << transformationMatrix
+ << QRectF(50, -70, 20, 20);
+ QTest::newRow("transformed {{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
+ << transformationMatrix
+ << QRectF(50, -2050, 2000, 2000);
+
+ QList<QRectF> all;
+ for (int i = 0; i < 256; ++i)
+ all << QRectF(randomX[i], randomY[i], 10, 10);
+ QTest::newRow("all")
+ << all
+ << QMatrix()
+ << QRectF(-980, -994, 1988, 1983);
+ QTest::newRow("transformed all")
+ << all
+ << transformationMatrix
+ << QRectF(-1928, -2010, 3966, 3976);
+}
+
+void tst_QGraphicsScene::itemsBoundingRect()
+{
+ QFETCH(QList<QRectF>, rects);
+ QFETCH(QMatrix, matrix);
+ QFETCH(QRectF, boundingRect);
+
+ QGraphicsScene scene;
+
+ foreach (QRectF rect, rects) {
+ QPainterPath path;
+ path.addRect(rect);
+ scene.addPath(path)->setMatrix(matrix);
+ }
+
+ QCOMPARE(scene.itemsBoundingRect(), boundingRect);
+}
+
+void tst_QGraphicsScene::items_QPointF_data()
+{
+ QTest::addColumn<QList<QRectF> >("items");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<QList<int> >("itemsAtPoint");
+
+ QTest::newRow("empty")
+ << QList<QRectF>()
+ << QPointF()
+ << QList<int>();
+ QTest::newRow("1")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(0, 0)
+ << (QList<int>() << 0);
+ QTest::newRow("2")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(5, 5)
+ << (QList<int>() << 0);
+ QTest::newRow("3")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(9.9, 9.9)
+ << (QList<int>() << 0);
+ QTest::newRow("3.5")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(10, 10)
+ << QList<int>();
+ QTest::newRow("4")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(9.9, 9.9, 10, 10))
+ << QPointF(9.9, 9.9)
+ << (QList<int>() << 1 << 0);
+ QTest::newRow("4.5")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(10, 10, 10, 10))
+ << QPointF(10, 10)
+ << (QList<int>() << 1);
+ QTest::newRow("5")
+ << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10))
+ << QPointF(10, 10)
+ << (QList<int>() << 1 << 0);
+ QTest::newRow("6")
+ << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10) << QRectF(0, 0, 20, 30))
+ << QPointF(10, 10)
+ << (QList<int>() << 2 << 1 << 0);
+}
+
+void tst_QGraphicsScene::items_QPointF()
+{
+ QFETCH(QList<QRectF>, items);
+ QFETCH(QPointF, point);
+ QFETCH(QList<int>, itemsAtPoint);
+
+ QGraphicsScene scene;
+
+ int n = 0;
+ QList<QGraphicsItem *> addedItems;
+ foreach(QRectF rect, items) {
+ QPainterPath path;
+ path.addRect(0, 0, rect.width(), rect.height());
+
+ QGraphicsItem *item = scene.addPath(path);
+ item->setZValue(n++);
+ item->setPos(rect.topLeft());
+ addedItems << item;
+ }
+
+ QList<int> itemIndexes;
+ foreach (QGraphicsItem *item, scene.items(point))
+ itemIndexes << addedItems.indexOf(item);
+
+ QCOMPARE(itemIndexes, itemsAtPoint);
+}
+
+void tst_QGraphicsScene::items_QRectF()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
+ QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
+ QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
+ QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
+
+ item1->setZValue(0);
+ item2->setZValue(1);
+ item3->setZValue(2);
+ item4->setZValue(3);
+
+ QCOMPARE(scene.items(QRectF(-10, -10, 10, 10)), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(QRectF(10, -10, 10, 10)), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(QRectF(10, 10, 10, 10)), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(QRectF(-10, 10, 10, 10)), QList<QGraphicsItem *>() << item4);
+ QCOMPARE(scene.items(QRectF(-10, -10, 1, 1)), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(QRectF(10, -10, 1, 1)), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(QRectF(10, 10, 1, 1)), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(QRectF(-10, 10, 1, 1)), QList<QGraphicsItem *>() << item4);
+
+ QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList<QGraphicsItem *>() << item2 << item1);
+ QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList<QGraphicsItem *>() << item4 << item3);
+
+ item1->setZValue(3);
+ item2->setZValue(2);
+ item3->setZValue(1);
+ item4->setZValue(0);
+
+ QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList<QGraphicsItem *>() << item3 << item4);
+}
+
+void tst_QGraphicsScene::items_QRectF_2_data()
+{
+ QTest::addColumn<QRectF>("ellipseRect");
+ QTest::addColumn<QRectF>("sceneRect");
+ QTest::addColumn<Qt::ItemSelectionMode>("selectionMode");
+ QTest::addColumn<bool>("contained");
+ QTest::addColumn<bool>("containedRotated");
+
+ // None of the rects contain the ellipse's shape nor bounding rect
+ QTest::newRow("1") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("2") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("3") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("4") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("5") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("6") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("7") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("8") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("9") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("10") << QRectF(0, 0, 100, 100) << QRectF(0, 50, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("11") << QRectF(0, 0, 100, 100) << QRectF(50, 0, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("12") << QRectF(0, 0, 100, 100) << QRectF(50, 50, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("13") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("14") << QRectF(0, 0, 100, 100) << QRectF(0, 50, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("15") << QRectF(0, 0, 100, 100) << QRectF(50, 0, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("16") << QRectF(0, 0, 100, 100) << QRectF(50, 50, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("17") << QRectF(0, 0, 100, 100) << QRectF(-50, -50, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("18") << QRectF(0, 0, 100, 100) << QRectF(0, -50, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("19") << QRectF(0, 0, 100, 100) << QRectF(-50, 0, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("20") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("21") << QRectF(0, 0, 100, 100) << QRectF(-50, -50, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("22") << QRectF(0, 0, 100, 100) << QRectF(0, -50, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("23") << QRectF(0, 0, 100, 100) << QRectF(-50, 0, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+
+ // The rect is the same as the ellipse's bounding rect
+ QTest::newRow("24") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+
+ // None intersects with the item's shape, but they all intersects with the
+ // item's bounding rect.
+ QTest::newRow("25") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::IntersectsItemShape << false << false;
+ QTest::newRow("26") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::IntersectsItemShape << false << true;
+ QTest::newRow("27") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::IntersectsItemShape << false << false;
+ QTest::newRow("28") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::IntersectsItemShape << false << false;
+ QTest::newRow("29") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::IntersectsItemBoundingRect << true << true;
+ QTest::newRow("30") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::IntersectsItemBoundingRect << true << true;
+ QTest::newRow("31") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::IntersectsItemBoundingRect << true << false;
+ QTest::newRow("32") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::IntersectsItemBoundingRect << true << false;
+
+ // This rect does not contain the shape nor the bounding rect
+ QTest::newRow("33") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("34") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::ContainsItemBoundingRect << false << false;
+
+ // It will, however, intersect with both
+ QTest::newRow("35") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::IntersectsItemShape << true << true;
+ QTest::newRow("36") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::IntersectsItemBoundingRect << true << true;
+
+ // A rect that contains the whole ellipse will both contain and intersect
+ // with both the ellipse's shape and bounding rect.
+ QTest::newRow("37") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::IntersectsItemBoundingRect << true << true;
+ QTest::newRow("38") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::IntersectsItemShape << true << true;
+ QTest::newRow("39") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::ContainsItemBoundingRect << true << false;
+ QTest::newRow("40") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::ContainsItemShape << true << false;
+
+ // A rect that is fully contained within the ellipse will intersect only
+ QTest::newRow("41") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("42") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("43") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::IntersectsItemShape << true << true;
+ QTest::newRow("44") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::IntersectsItemBoundingRect << true << true;
+}
+
+void tst_QGraphicsScene::items_QRectF_2()
+{
+ QFETCH(QRectF, ellipseRect);
+ QFETCH(QRectF, sceneRect);
+ QFETCH(Qt::ItemSelectionMode, selectionMode);
+ QFETCH(bool, contained);
+ QFETCH(bool, containedRotated);
+
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addEllipse(ellipseRect);
+
+ QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), contained);
+ item->rotate(45);
+ QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), containedRotated);
+}
+
+void tst_QGraphicsScene::items_QPolygonF()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
+ QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
+ QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
+ QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
+
+ item1->setZValue(0);
+ item2->setZValue(1);
+ item3->setZValue(2);
+ item4->setZValue(3);
+
+ QPolygonF poly1(item1->boundingRect());
+ QPolygonF poly2(item2->boundingRect());
+ QPolygonF poly3(item3->boundingRect());
+ QPolygonF poly4(item4->boundingRect());
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(poly3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(poly4), QList<QGraphicsItem *>() << item4);
+
+ poly1 = QPolygonF(QRectF(-10, -10, 1, 1));
+ poly2 = QPolygonF(QRectF(10, -10, 1, 1));
+ poly3 = QPolygonF(QRectF(10, 10, 1, 1));
+ poly4 = QPolygonF(QRectF(-10, 10, 1, 1));
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(poly3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(poly4), QList<QGraphicsItem *>() << item4);
+
+ poly1 = QPolygonF(QRectF(-10, -10, 40, 10));
+ poly2 = QPolygonF(QRectF(-10, 10, 40, 10));
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item2 << item1);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item4 << item3);
+
+ item1->setZValue(3);
+ item2->setZValue(2);
+ item3->setZValue(1);
+ item4->setZValue(0);
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item3 << item4);
+}
+
+void tst_QGraphicsScene::items_QPolygonF_2()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
+
+ // None of the rects contain the ellipse's shape nor bounding rect
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+
+ // None intersects with the item's shape, but they all intersects with the
+ // item's bounding rect.
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QCOMPARE(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ // This rect does not contain the shape nor the bounding rect
+ QVERIFY(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::ContainsItemBoundingRect).isEmpty());
+
+ // It will, however, intersect with both
+ QCOMPARE(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ // A rect that contains the whole ellipse will both contain and intersect
+ // with both the ellipse's shape and bounding rect.
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::ContainsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::ContainsItemBoundingRect).first(), ellipse);
+}
+
+void tst_QGraphicsScene::items_QPainterPath()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
+ QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
+ QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
+ QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
+
+ item1->setZValue(0);
+ item2->setZValue(1);
+ item3->setZValue(2);
+ item4->setZValue(3);
+
+ QPainterPath path1; path1.addEllipse(item1->boundingRect());
+ QPainterPath path2; path2.addEllipse(item2->boundingRect());
+ QPainterPath path3; path3.addEllipse(item3->boundingRect());
+ QPainterPath path4; path4.addEllipse(item4->boundingRect());
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(path3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(path4), QList<QGraphicsItem *>() << item4);
+
+ path1 = QPainterPath(); path1.addEllipse(QRectF(-10, -10, 1, 1));
+ path2 = QPainterPath(); path2.addEllipse(QRectF(10, -10, 1, 1));
+ path3 = QPainterPath(); path3.addEllipse(QRectF(10, 10, 1, 1));
+ path4 = QPainterPath(); path4.addEllipse(QRectF(-10, 10, 1, 1));
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(path3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(path4), QList<QGraphicsItem *>() << item4);
+
+ path1 = QPainterPath(); path1.addRect(QRectF(-10, -10, 40, 10));
+ path2 = QPainterPath(); path2.addRect(QRectF(-10, 10, 40, 10));
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item2 << item1);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item4 << item3);
+
+ item1->setZValue(3);
+ item2->setZValue(2);
+ item3->setZValue(1);
+ item4->setZValue(0);
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item3 << item4);
+}
+
+void tst_QGraphicsScene::items_QPainterPath_2()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
+
+ QPainterPath p1; p1.addRect(QRectF(1, 1, 10, 10));
+ QPainterPath p2; p2.addRect(QRectF(1, 89, 10, 10));
+ QPainterPath p3; p3.addRect(QRectF(89, 1, 10, 10));
+ QPainterPath p4; p4.addRect(QRectF(89, 89, 10, 10));
+
+ // None of the rects contain the ellipse's shape nor bounding rect
+ QVERIFY(scene.items(p1, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p2, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p3, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p4, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p1, Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(p2, Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(p3, Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(p4, Qt::ContainsItemBoundingRect).isEmpty());
+
+ // None intersects with the item's shape, but they all intersects with the
+ // item's bounding rect.
+ QVERIFY(scene.items(p1, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(p2, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(p3, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(p4, Qt::IntersectsItemShape).isEmpty());
+ QCOMPARE(scene.items(p1, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p2, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p3, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p4, Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ QPainterPath p5;
+ p5.addRect(QRectF(5, 5, 90, 90));
+
+ // This rect does not contain the shape nor the bounding rect
+ QVERIFY(scene.items(p5, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p5, Qt::ContainsItemBoundingRect).isEmpty());
+
+ // It will, however, intersect with both
+ QCOMPARE(scene.items(p5, Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(p5, Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ QPainterPath p6;
+ p6.addRect(QRectF(-5, -5, 110, 110));
+
+ // A rect that contains the whole ellipse will both contain and intersect
+ // with both the ellipse's shape and bounding rect.
+ QCOMPARE(scene.items(p6, Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(p6, Qt::ContainsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(p6, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p6, Qt::ContainsItemBoundingRect).first(), ellipse);
+}
+
+void tst_QGraphicsScene::selection()
+{
+ // ### This test is difficult to make work for all platforms; instead, a
+ // hand crafted data set would make it stable. Its behavior is thoroughly
+ // covered by other tests. Todo: Fix this test.
+
+ /*
+ QGraphicsScene scene;
+ QMap<QGraphicsItem *, int> itemIndexes;
+ for (int i = 0; i < 256; ++i) {
+ QPainterPath path;
+ path.addRect(randomX[i], randomY[i], 25, 25);
+
+ QGraphicsPathItem *pathItem = scene.addPath(path);
+ pathItem->setFlag(QGraphicsItem::ItemIsSelectable);
+ itemIndexes.insert(pathItem, i);
+ }
+
+#if 0
+ // Write data
+ QFile::remove("graphicsScene_selection.data");
+ QFile file("graphicsScene_selection.data");
+ if (!file.open(QFile::WriteOnly))
+ QFAIL("Unable to generate data file graphicsScene_selection.data");
+ QDataStream stream(&file);
+ for (qreal y = -1000; y < 1000; y += 33) {
+ for (qreal x = -1000; x < 1000; x += 33) {
+ for (qreal size = 1; size < 200; size += 33) {
+ QPainterPath path;
+ path.addRect(QRectF(x, y, size, size));
+ scene.setSelectionArea(path);
+ QCOMPARE(scene.selectionArea(), path);
+
+ QList<int> indexes;
+ foreach (QGraphicsItem *item, scene.selectedItems())
+ indexes << itemIndexes.value(item);
+
+ stream << x << y << size << indexes;
+ }
+ }
+ }
+#else
+ // Read data
+ QFile file("graphicsScene_selection.data");
+ if (!file.open(QFile::ReadOnly))
+ QFAIL("Unable to load data file graphicsScene_selection.data");
+
+ QDataStream stream(&file);
+
+ while (!stream.atEnd()) {
+ QList<int> expectedIndexes;
+
+ qreal x, y, size;
+ stream >> x >> y >> size >> expectedIndexes;
+
+ QPainterPath path;
+ path.addRect(QRectF(x, y, size, size));
+ scene.setSelectionArea(path);
+ QCOMPARE(scene.selectionArea(), path);
+
+ QList<int> indexes;
+ foreach (QGraphicsItem *item, scene.selectedItems())
+ indexes << itemIndexes.value(item);
+
+ qSort(indexes);
+ qSort(expectedIndexes);
+
+ QCOMPARE(indexes, expectedIndexes);
+
+ scene.clearSelection();
+ QVERIFY(scene.selectedItems().isEmpty());
+ }
+#endif
+ */
+}
+
+class CustomView : public QGraphicsView
+{
+public:
+ CustomView() : repaints(0)
+ { }
+
+ int repaints;
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ ++repaints;
+ QGraphicsView::paintEvent(event);
+ }
+};
+
+void tst_QGraphicsScene::selectionChanged()
+{
+ QGraphicsScene scene(0, 0, 1000, 1000);
+ QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QCOMPARE(spy.count(), 0);
+
+ QPainterPath path;
+ path.addRect(scene.sceneRect());
+ QCOMPARE(scene.selectionArea(), QPainterPath());
+ scene.setSelectionArea(path);
+ QCOMPARE(scene.selectionArea(), path);
+ QCOMPARE(spy.count(), 0); // selection didn't change
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ QGraphicsItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QCOMPARE(spy.count(), 0); // selection didn't change
+
+ rect->setSelected(true);
+ QVERIFY(!rect->isSelected());
+ QCOMPARE(spy.count(), 0); // selection didn't change, item isn't selectable
+
+ rect->setFlag(QGraphicsItem::ItemIsSelectable);
+ rect->setSelected(true);
+ QVERIFY(rect->isSelected());
+ QCOMPARE(spy.count(), 1); // selection changed
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
+
+ rect->setSelected(false);
+ QVERIFY(!rect->isSelected());
+ QCOMPARE(spy.count(), 2); // selection changed
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ QGraphicsEllipseItem *parentItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
+ QGraphicsEllipseItem *childItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100), parentItem);
+ QGraphicsEllipseItem *grandChildItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100), childItem);
+ grandChildItem->setFlag(QGraphicsItem::ItemIsSelectable);
+ grandChildItem->setSelected(true);
+ grandChildItem->setSelected(false);
+ grandChildItem->setSelected(true);
+ scene.addItem(parentItem);
+
+ QCOMPARE(spy.count(), 3); // the grandchild was added, so the selection changed once
+
+ scene.removeItem(parentItem);
+ QCOMPARE(spy.count(), 4); // the grandchild was removed, so the selection changed
+
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 5); // the rect was reselected, so the selection changed
+
+ scene.clearSelection();
+ QCOMPARE(spy.count(), 6); // the scene selection was cleared
+
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 7); // the rect was reselected, so the selection changed
+
+ rect->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QCOMPARE(spy.count(), 8); // the rect was unselected, so the selection changed
+
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 8); // the rect is not longer selectable, so the selection does not change
+
+
+ rect->setFlag(QGraphicsItem::ItemIsSelectable, true);
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 9); // the rect is again selectable, so the selection changed
+
+ delete rect;
+ QCOMPARE(spy.count(), 10); // a selected item was deleted; selection changed
+}
+
+void tst_QGraphicsScene::selectionChanged2()
+{
+ QGraphicsScene scene;
+ QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+
+ QGraphicsItem *item1 = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *item2 = scene.addRect(100, 100, 100, 100);
+ item1->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QCOMPARE(spy.count(), 0);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ QCOMPARE(spy.count(), 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(150, 150));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(QPointF(150, 150));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+ QCOMPARE(spy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ event.setModifiers(Qt::ControlModifier);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+ QCOMPARE(spy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QGraphicsScene::addItem()
+{
+ Q_CHECK_PAINTEVENTS
+ {
+ // 1) Create item, then scene, then add item
+ QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ QGraphicsScene scene;
+
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ qApp->processEvents();
+ view.repaints = 0;
+
+ scene.addItem(path);
+
+ // Adding an item should always issue a repaint.
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
+ QVERIFY(view.repaints > 0);
+ view.repaints = 0;
+
+ QCOMPARE(scene.itemAt(0, 0), path);
+
+ QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ path2->setPos(100, 100);
+
+ QCOMPARE(scene.itemAt(0, 0), path);
+ QCOMPARE(scene.itemAt(100, 100), (QGraphicsItem *)0);
+ scene.addItem(path2);
+
+ // Adding an item should always issue a repaint.
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
+ QVERIFY(view.repaints > 0);
+
+ QCOMPARE(scene.itemAt(100, 100), path2);
+ }
+ {
+ // 2) Create scene, then item, then add item
+ QGraphicsScene scene;
+ QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ scene.addItem(path);
+
+ QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ path2->setPos(100, 100);
+ scene.addItem(path2);
+
+ QCOMPARE(scene.itemAt(0, 0), path);
+ QCOMPARE(scene.itemAt(100, 100), path2);
+ }
+}
+
+void tst_QGraphicsScene::addEllipse()
+{
+ QGraphicsScene scene;
+ QGraphicsEllipseItem *ellipse = scene.addEllipse(QRectF(-10, -10, 20, 20),
+ QPen(Qt::red), QBrush(Qt::blue));
+ QCOMPARE(ellipse->pos(), QPointF());
+ QCOMPARE(ellipse->pen(), QPen(Qt::red));
+ QCOMPARE(ellipse->brush(), QBrush(Qt::blue));
+ QCOMPARE(ellipse->rect(), QRectF(-10, -10, 20, 20));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addLine()
+{
+ QGraphicsScene scene;
+ QPen pen(Qt::red);
+ pen.setWidthF(1.0);
+ QGraphicsLineItem *line = scene.addLine(QLineF(-10, -10, 20, 20),
+ pen);
+ QCOMPARE(line->pos(), QPointF());
+ QCOMPARE(line->pen(), pen);
+ QCOMPARE(line->line(), QLineF(-10, -10, 20, 20));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)line);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)line);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)line);
+}
+
+void tst_QGraphicsScene::addPath()
+{
+ QGraphicsScene scene;
+ QPainterPath p;
+ p.addEllipse(QRectF(-10, -10, 20, 20));
+ p.addEllipse(QRectF(-10, 20, 20, 20));
+
+ QGraphicsPathItem *path = scene.addPath(p, QPen(Qt::red), QBrush(Qt::blue));
+ QCOMPARE(path->pos(), QPointF());
+ QCOMPARE(path->pen(), QPen(Qt::red));
+ QCOMPARE(path->path(), p);
+ QCOMPARE(path->brush(), QBrush(Qt::blue));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 30), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(-9.9, 30), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(9.9, 30), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 20.1), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 39.9), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-10, 20), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, 20), (QGraphicsItem *)0);
+if (sizeof(qreal) != sizeof(double))
+ QWARN("Skipping test because of rounding errors when qreal != double");
+else
+ QCOMPARE(scene.itemAt(-10, 30), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10.1, 30), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addPixmap()
+{
+ QGraphicsScene scene;
+ QPixmap pix(":/Ash_European.jpg");
+ QGraphicsPixmapItem *pixmap = scene.addPixmap(pix);
+
+ QCOMPARE(pixmap->pos(), QPointF());
+ QCOMPARE(pixmap->pixmap(), pix);
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(pix.width() - 1, 0), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(0, pix.height() - 1), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(pix.width() - 1, pix.height() - 1), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(-1, -1), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(pix.width() - 1, -1), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-1, pix.height() - 1), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(pix.width(), pix.height()), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, pix.height()), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(pix.width(), 0), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addRect()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(QRectF(-10, -10, 20, 20),
+ QPen(Qt::red), QBrush(Qt::blue));
+ QCOMPARE(rect->pos(), QPointF());
+ QCOMPARE(rect->pen(), QPen(Qt::red));
+ QCOMPARE(rect->brush(), QBrush(Qt::blue));
+ QCOMPARE(rect->rect(), QRectF(-10, -10, 20, 20));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addText()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *text = scene.addText("Qt", QFont());
+ QCOMPARE(text->pos(), QPointF());
+ QCOMPARE(text->toPlainText(), QString("Qt"));
+ QCOMPARE(text->font(), QFont());
+}
+
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+void tst_QGraphicsScene::removeItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ QCOMPARE(scene.itemAt(0, 0), item); // forces indexing
+ scene.removeItem(item);
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
+ delete item;
+
+ QGraphicsItem *item2 = scene.addRect(QRectF(0, 0, 10, 10));
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+ QCOMPARE(scene.itemAt(0, 0), item2);
+
+ // Removing a selected item
+ QVERIFY(scene.selectedItems().isEmpty());
+ item2->setSelected(true);
+ QVERIFY(scene.selectedItems().contains(item2));
+ scene.removeItem(item2);
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ // Check that we are in a state that can receive paint events
+ // (i.e., not logged out on Windows).
+ Q_CHECK_PAINTEVENTS
+
+ // Removing a hovered item
+ HoverItem *hoverItem = new HoverItem;
+ scene.addItem(hoverItem);
+ scene.setSceneRect(-50, -50, 100, 100);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(150, 150);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::mouseMove(view.viewport(), QPoint(-1, -1));
+ {
+ QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &moveEvent);
+ }
+ qApp->processEvents(); // update
+ qApp->processEvents(); // draw
+ QVERIFY(!hoverItem->isHovered);
+
+ {
+ QTest::qWait(250);
+ QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
+ QTest::qWait(10);
+ QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos()), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &moveEvent);
+ }
+ qApp->processEvents(); // update
+ qApp->processEvents(); // draw
+ QVERIFY(hoverItem->isHovered);
+
+ scene.removeItem(hoverItem);
+ hoverItem->setAcceptsHoverEvents(false);
+ scene.addItem(hoverItem);
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
+ QVERIFY(!hoverItem->isHovered);
+}
+#endif
+
+void tst_QGraphicsScene::focusItem()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QVERIFY(!scene.focusItem());
+ QGraphicsItem *item = scene.addText("Qt");
+ QVERIFY(!scene.focusItem());
+ item->setFocus();
+ QVERIFY(!scene.focusItem());
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!scene.focusItem());
+ item->setFocus();
+ QCOMPARE(scene.focusItem(), item);
+
+ QFocusEvent focusOut(QEvent::FocusOut);
+ QApplication::sendEvent(&scene, &focusOut);
+
+ QVERIFY(!scene.focusItem());
+
+ QFocusEvent focusIn(QEvent::FocusIn);
+ QApplication::sendEvent(&scene, &focusIn);
+ QCOMPARE(scene.focusItem(), item);
+
+ QGraphicsItem *item2 = scene.addText("Qt");
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ QCOMPARE(scene.focusItem(), item);
+
+ item2->setFocus();
+ QCOMPARE(scene.focusItem(), item2);
+ item->setFocus();
+ QCOMPARE(scene.focusItem(), item);
+
+ item2->setFocus();
+ QCOMPARE(scene.focusItem(), item2);
+ QApplication::sendEvent(&scene, &focusOut);
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!scene.focusItem());
+ QApplication::sendEvent(&scene, &focusIn);
+ QCOMPARE(scene.focusItem(), item2);
+
+ QApplication::sendEvent(&scene, &focusOut);
+
+ QVERIFY(!scene.focusItem());
+ scene.removeItem(item2);
+ delete item2;
+
+ QApplication::sendEvent(&scene, &focusIn);
+ QVERIFY(!scene.focusItem());
+}
+
+class FocusItem : public QGraphicsTextItem
+{
+protected:
+ void focusOutEvent(QFocusEvent *)
+ {
+ QVERIFY(!scene()->focusItem());
+ }
+};
+
+void tst_QGraphicsScene::focusItemLostFocus()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ FocusItem *item = new FocusItem;
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ scene.addItem(item);
+
+ item->setFocus();
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
+ item->clearFocus();
+}
+
+class ClearTestItem : public QGraphicsRectItem
+{
+public:
+ ClearTestItem(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
+ ~ClearTestItem() { qDeleteAll(items); }
+ QList<QGraphicsItem *> items;
+};
+
+void tst_QGraphicsScene::clear()
+{
+ QGraphicsScene scene;
+ scene.clear();
+ QVERIFY(scene.items().isEmpty());
+ scene.addRect(0, 0, 100, 100);
+ QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
+ scene.clear();
+ QVERIFY(scene.items().isEmpty());
+ QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
+
+ ClearTestItem *firstItem = new ClearTestItem;
+ QGraphicsItem *secondItem = new QGraphicsRectItem;
+ firstItem->items += secondItem;
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ scene.addItem(firstItem);
+ scene.addItem(secondItem);
+ QCOMPARE(scene.items().at(0), (QGraphicsItem*)firstItem);
+ QCOMPARE(scene.items().at(1), secondItem);
+
+ ClearTestItem *thirdItem = new ClearTestItem(firstItem);
+ QGraphicsItem *forthItem = new QGraphicsRectItem(firstItem);
+ thirdItem->items += forthItem;
+
+ // must not crash even if firstItem deletes secondItem
+ scene.clear();
+ QVERIFY(scene.items().isEmpty());
+}
+
+void tst_QGraphicsScene::setFocusItem()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsItem *item = scene.addText("Qt");
+ QVERIFY(!scene.focusItem());
+ QVERIFY(!scene.hasFocus());
+ scene.setFocusItem(item);
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!scene.focusItem());
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ for (int i = 0; i < 3; ++i) {
+ scene.setFocusItem(item);
+ QVERIFY(scene.hasFocus());
+ QCOMPARE(scene.focusItem(), item);
+ QVERIFY(item->hasFocus());
+ }
+
+ QGraphicsItem *item2 = scene.addText("Qt");
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ scene.setFocusItem(item2);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ scene.setFocusItem(item);
+ QVERIFY(item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.clearFocus();
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.setFocusItem(0);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.setFocus();
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+}
+
+void tst_QGraphicsScene::setFocusItem_inactive()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addText("Qt");
+ QVERIFY(!scene.focusItem());
+ QVERIFY(!scene.hasFocus());
+ scene.setFocusItem(item);
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!scene.focusItem());
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ for (int i = 0; i < 3; ++i) {
+ scene.setFocusItem(item);
+ QCOMPARE(scene.focusItem(), item);
+ QVERIFY(!item->hasFocus());
+ }
+
+}
+
+
+void tst_QGraphicsScene::mouseGrabberItem()
+{
+ QGraphicsScene scene;
+ QVERIFY(!scene.mouseGrabberItem());
+
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ item->setZValue(1);
+
+ QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ item2->setFlag(QGraphicsItem::ItemIsMovable);
+ item2->setZValue(0);
+
+ for (int i = 0; i < 3; ++i) {
+ item->setPos(0, 0);
+ item2->setPos(0, 0);
+ item->setZValue((i & 1) ? 0 : 1);
+ item2->setZValue((i & 1) ? 1 : 0);
+ QGraphicsItem *topMostItem = (i & 1) ? item2 : item;
+
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ pressEvent.setScreenPos(QPoint(100, 100));
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(scene.mouseGrabberItem(), topMostItem);
+
+ for (int i = 0; i < 1000; ++i) {
+ QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
+ moveEvent.setButtons(Qt::LeftButton);
+ moveEvent.setScenePos(QPointF(i * 10, i * 10));
+ moveEvent.setScreenPos(QPoint(100 + i * 10, 100 + i * 10));
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), topMostItem);
+
+ // Geometrical changes should not affect the mouse grabber.
+ item->setZValue(rand() % 500);
+ item2->setZValue(rand() % 500);
+ item->setPos(rand() % 50000, rand() % 50000);
+ item2->setPos(rand() % 50000, rand() % 50000);
+ }
+
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+ releaseEvent.setScenePos(QPointF(10000, 10000));
+ releaseEvent.setScreenPos(QPoint(1000000, 1000000));
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QVERIFY(!scene.mouseGrabberItem());
+ }
+
+ // Structural change: deleting the mouse grabber
+ item->setPos(0, 0);
+ item->setZValue(1);
+ item2->setPos(0, 0);
+ item2->setZValue(0);
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ pressEvent.setScreenPos(QPoint(100, 100));
+
+ QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
+ moveEvent.setButtons(Qt::LeftButton);
+ moveEvent.setScenePos(QPointF(0, 0));
+ moveEvent.setScreenPos(QPoint(100, 100));
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), item);
+ item->setVisible(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(scene.mouseGrabberItem(), item2);
+ item2->setVisible(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ item2->setVisible(true);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), item2);
+ scene.removeItem(item2);
+ delete item2;
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::hoverEvents_siblings()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+ QGraphicsItem *lastItem = 0;
+ QList<HoverItem *> items;
+ for (int i = 0; i < 15; ++i) {
+ QGraphicsItem *item = new HoverItem;
+ scene.addItem(item);
+ items << (HoverItem *)item;
+ if (lastItem) {
+ item->setPos(lastItem->pos() + QPointF(sin(i / 3.0) * 17, cos(i / 3.0) * 17));
+ }
+ item->setZValue(i);
+ lastItem = item;
+ }
+
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing, true);
+#if defined(Q_OS_WINCE)
+ view.setMinimumSize(230, 200);
+#else
+ view.setMinimumSize(400, 300);
+#endif
+ view.rotate(10);
+ view.scale(1.7, 1.7);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ qApp->setActiveWindow(&view);
+ view.activateWindow();
+ QTest::qWait(70);
+
+ QCursor::setPos(view.mapToGlobal(QPoint(-5, -5)));
+
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ QTest::qWait(50);
+
+ for (int j = 1; j >= 0; --j) {
+ int i = j ? 0 : 14;
+ forever {
+ if (j)
+ QVERIFY(!items.at(i)->isHovered);
+ else
+ QVERIFY(!items.at(i)->isHovered);
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+
+ QTRY_VERIFY(items.at(i)->isHovered);
+ if (j && i > 0)
+ QVERIFY(!items.at(i - 1)->isHovered);
+ if (!j && i < 14)
+ QVERIFY(!items.at(i + 1)->isHovered);
+ i += j ? 1 : -1;
+ if ((j && i == 15) || (!j && i == -1))
+ break;
+ }
+
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+ }
+}
+
+void tst_QGraphicsScene::hoverEvents_parentChild()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+ QGraphicsItem *lastItem = 0;
+ QList<HoverItem *> items;
+ for (int i = 0; i < 15; ++i) {
+ QGraphicsItem *item = new HoverItem;
+ scene.addItem(item);
+ items << (HoverItem *)item;
+ if (lastItem) {
+ item->setParentItem(lastItem);
+ item->setPos(sin(i / 3.0) * 17, cos(i / 3.0) * 17);
+ }
+ lastItem = item;
+ }
+
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing, true);
+#if defined(Q_OS_WINCE)
+ view.setMinimumSize(230, 200);
+#else
+ view.setMinimumSize(400, 300);
+#endif
+ view.rotate(10);
+ view.scale(1.7, 1.7);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(70);
+
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ for (int j = 1; j >= 0; --j) {
+ int i = j ? 0 : 14;
+ forever {
+ if (j) {
+ QVERIFY(!items.at(i)->isHovered);
+ } else {
+ if (i == 14)
+ QVERIFY(!items.at(13)->isHovered);
+ }
+ mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+
+ QTRY_VERIFY(items.at(i)->isHovered);
+ if (i < 14)
+ QVERIFY(!items.at(i + 1)->isHovered);
+ i += j ? 1 : -1;
+ if ((j && i == 15) || (!j && i == -1))
+ break;
+ }
+
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+ }
+}
+
+void tst_QGraphicsScene::createItemGroup()
+{
+ QGraphicsScene scene;
+
+ QList<QGraphicsItem *> children1;
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+
+ QList<QGraphicsItem *> children2;
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+
+ QList<QGraphicsItem *> children3;
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+
+ // All items in children1 are children of parent1
+ QGraphicsItem *parent1 = scene.addRect(QRectF(-10, -10, 20, 20));
+ foreach (QGraphicsItem *item, children1)
+ item->setParentItem(parent1);
+
+ QGraphicsItemGroup *group = scene.createItemGroup(children1);
+ QCOMPARE(group->parentItem(), parent1);
+ QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children1.first()->parentItem(), parent1);
+ group = scene.createItemGroup(children1);
+ QCOMPARE(group->parentItem(), parent1);
+ QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children1.first()->parentItem(), parent1);
+
+ // All items in children2 are children of parent2
+ QGraphicsItem *parent2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ foreach (QGraphicsItem *item, children2)
+ item->setParentItem(parent2);
+
+ // Now make parent2 a child of parent1, so all children2 are also children
+ // of parent1.
+ parent2->setParentItem(parent1);
+
+ // The children2 group should still have parent2 as their common ancestor.
+ group = scene.createItemGroup(children2);
+ QCOMPARE(group->parentItem(), parent2);
+ QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children2.first()->parentItem(), parent2);
+
+ // But the set of both children2 and children1 share only parent1.
+ group = scene.createItemGroup(children2 + children1);
+ QCOMPARE(group->parentItem(), parent1);
+ QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children1.first()->parentItem(), parent1);
+ QCOMPARE(children2.first()->parentItem(), parent1);
+
+ // Fixup the parent-child chain
+ foreach (QGraphicsItem *item, children2)
+ item->setParentItem(parent2);
+
+ // These share no common parent
+ group = scene.createItemGroup(children3);
+ QCOMPARE(group->parentItem(), (QGraphicsItem *)0);
+ scene.destroyItemGroup(group);
+
+ // Make children3 children of parent3
+ QGraphicsItem *parent3 = scene.addRect(QRectF(-10, -10, 20, 20));
+ foreach (QGraphicsItem *item, children3)
+ item->setParentItem(parent3);
+
+ // These should have parent3 as a parent
+ group = scene.createItemGroup(children3);
+ QCOMPARE(group->parentItem(), parent3);
+ scene.destroyItemGroup(group);
+
+ // Now make them all children of parent1
+ parent3->setParentItem(parent1);
+
+ group = scene.createItemGroup(children3);
+ QCOMPARE(group->parentItem(), parent3);
+ scene.destroyItemGroup(group);
+
+ group = scene.createItemGroup(children2);
+ QCOMPARE(group->parentItem(), parent2);
+ scene.destroyItemGroup(group);
+
+ group = scene.createItemGroup(children1);
+ QCOMPARE(group->parentItem(), parent1);
+ scene.destroyItemGroup(group);
+
+ QGraphicsItemGroup *emptyGroup = scene.createItemGroup(QList<QGraphicsItem *>());
+ QCOMPARE(emptyGroup->children(), QList<QGraphicsItem *>());
+ QVERIFY(!emptyGroup->parentItem());
+ QCOMPARE(emptyGroup->scene(), &scene);
+}
+
+class EventTester : public QGraphicsEllipseItem
+{
+public:
+ EventTester()
+ : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false)
+ { }
+
+ bool ignoreMouse;
+ QList<QEvent::Type> eventTypes;
+
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ eventTypes << QEvent::Type(event->type());
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ if (ignoreMouse) {
+ event->ignore();
+ return true;
+ }
+ default:
+ break;
+ }
+
+ return QGraphicsEllipseItem::sceneEvent(event);
+ }
+};
+
+void tst_QGraphicsScene::mouseEventPropagation()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ EventTester *c = new EventTester;
+ EventTester *d = new EventTester;
+ b->setParentItem(a);
+ c->setParentItem(b);
+ d->setParentItem(c);
+
+ a->setFlag(QGraphicsItem::ItemIsMovable);
+ b->setFlag(QGraphicsItem::ItemIsMovable);
+ c->setFlag(QGraphicsItem::ItemIsMovable);
+ d->setFlag(QGraphicsItem::ItemIsMovable);
+
+ a->setData(0, "A");
+ b->setData(0, "B");
+ c->setData(0, "C");
+ d->setData(0, "D");
+
+ // scene -> a -> b -> c -> d
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(a);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
+ moveEvent.setButton(Qt::LeftButton);
+ moveEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(0, 0));
+
+ // Send a press
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 2);
+ QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(c->eventTypes.size(), 0);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
+
+ // Send a move
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(d->eventTypes.size(), 3);
+ QCOMPARE(d->eventTypes.at(2), QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(c->eventTypes.size(), 0);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
+
+ // Send a release
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(d->eventTypes.at(3), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(d->eventTypes.at(4), QEvent::UngrabMouse);
+ QCOMPARE(c->eventTypes.size(), 0);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ d->setAcceptedMouseButtons(Qt::RightButton);
+
+ // Send a press
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 2);
+ QCOMPARE(c->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Send another press, with a button that isn't actually accepted
+ QApplication::sendEvent(&scene, &pressEvent);
+ pressEvent.setButton(Qt::RightButton);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 3);
+ QCOMPARE(c->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Send a move
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 4);
+ QCOMPARE(c->eventTypes.at(3), QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Send a release
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 6);
+ QCOMPARE(c->eventTypes.at(4), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(c->eventTypes.at(5), QEvent::UngrabMouse);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Disabled items eat events. c should not get this.
+ d->setEnabled(false);
+ d->setAcceptedMouseButtons(Qt::RightButton);
+
+ // Send a right press. This disappears in d.
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 6);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Send a left press. This goes to c.
+ pressEvent.setButton(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 8);
+ QCOMPARE(c->eventTypes.at(6), QEvent::GrabMouse);
+ QCOMPARE(c->eventTypes.at(7), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Clicking outside the items removes the mouse grabber
+}
+
+void tst_QGraphicsScene::mouseEventPropagation_ignore()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ EventTester *c = new EventTester;
+ EventTester *d = new EventTester;
+ b->setParentItem(a);
+ c->setParentItem(b);
+ d->setParentItem(c);
+
+ a->setFlags(QGraphicsItem::ItemIsMovable);
+ b->setFlags(QGraphicsItem::ItemIsMovable);
+ c->setFlags(QGraphicsItem::ItemIsMovable);
+ d->setFlags(QGraphicsItem::ItemIsMovable);
+
+ // scene -> a -> b -> c -> d
+ QGraphicsScene scene;
+ scene.addItem(a);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+
+ b->ignoreMouse = true;
+ c->ignoreMouse = true;
+ d->ignoreMouse = true;
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(a->eventTypes.size(), 2);
+ QCOMPARE(a->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(a->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 3);
+ QCOMPARE(b->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(b->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.at(2), QEvent::UngrabMouse);
+ QCOMPARE(c->eventTypes.size(), 3);
+ QCOMPARE(c->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(c->eventTypes.at(2), QEvent::UngrabMouse);
+ QCOMPARE(d->eventTypes.size(), 3);
+ QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(d->eventTypes.at(2), QEvent::UngrabMouse);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)a);
+
+ a->ignoreMouse = true;
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(a->eventTypes.size(), 3);
+ QCOMPARE(a->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 3);
+ QCOMPARE(c->eventTypes.size(), 3);
+ QCOMPARE(d->eventTypes.size(), 3);
+
+ QVERIFY(!pressEvent.isAccepted());
+}
+
+void tst_QGraphicsScene::mouseEventPropagation_focus()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ EventTester *c = new EventTester;
+ EventTester *d = new EventTester;
+ b->setParentItem(a);
+ c->setParentItem(b);
+ d->setParentItem(c);
+
+ a->setFlag(QGraphicsItem::ItemIsMovable);
+ b->setFlag(QGraphicsItem::ItemIsMovable);
+ c->setFlag(QGraphicsItem::ItemIsMovable);
+ d->setFlag(QGraphicsItem::ItemIsMovable);
+
+ // scene -> a -> b -> c -> d
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(a);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+
+ a->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!a->hasFocus());
+
+ QApplication::sendEvent(&scene, &pressEvent);
+
+ QVERIFY(a->hasFocus());
+ QCOMPARE(a->eventTypes.size(), 1);
+ QCOMPARE(a->eventTypes.first(), QEvent::FocusIn);
+ QCOMPARE(d->eventTypes.size(), 2);
+ QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+}
+
+void tst_QGraphicsScene::mouseEventPropagation_doubleclick()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ a->setFlags(QGraphicsItem::ItemIsMovable);
+ b->setFlags(QGraphicsItem::ItemIsMovable);
+
+ a->setPos(-50, 0);
+ b->setPos(50, 0);
+
+ QGraphicsScene scene;
+ scene.addItem(a);
+ scene.addItem(b);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent doubleClickEvent(QEvent::GraphicsSceneMouseDoubleClick);
+ doubleClickEvent.setButton(Qt::LeftButton);
+ doubleClickEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(0, 0));
+
+ // Send press to A
+ pressEvent.setScenePos(a->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(a->eventTypes.size(), 2);
+ QCOMPARE(a->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(a->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+
+ // Send release to A
+ releaseEvent.setScenePos(a->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(a->eventTypes.size(), 4);
+ QCOMPARE(a->eventTypes.at(2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(a->eventTypes.at(3), QEvent::UngrabMouse);
+
+ // Send doubleclick to B
+ doubleClickEvent.setScenePos(b->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &doubleClickEvent);
+ QCOMPARE(a->eventTypes.size(), 4);
+ QCOMPARE(b->eventTypes.size(), 2);
+ QCOMPARE(b->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(b->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+
+ // Send release to B
+ releaseEvent.setScenePos(b->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(a->eventTypes.size(), 4);
+ QCOMPARE(b->eventTypes.size(), 4);
+ QCOMPARE(b->eventTypes.at(2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(b->eventTypes.at(3), QEvent::UngrabMouse);
+}
+
+class Scene : public QGraphicsScene
+{
+public:
+ QList<QPointF> mouseMovePoints;
+
+protected:
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+ {
+ mouseMovePoints << event->scenePos();
+ }
+};
+
+void tst_QGraphicsScene::mouseEventPropagation_mouseMove()
+{
+ Scene scene;
+ scene.addRect(QRectF(5, 0, 12, 12));
+ scene.addRect(QRectF(15, 0, 12, 12))->setAcceptsHoverEvents(true);
+ for (int i = 0; i < 30; ++i) {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(QPointF(i, 5));
+ QApplication::sendEvent(&scene, &event);
+ }
+
+ QCOMPARE(scene.mouseMovePoints.size(), 30);
+ for (int i = 0; i < 30; ++i)
+ QCOMPARE(scene.mouseMovePoints.at(i), QPointF(i, 5));
+}
+
+class DndTester : public QGraphicsEllipseItem
+{
+public:
+ DndTester(const QRectF &rect)
+ : QGraphicsEllipseItem(rect), lastEvent(0),
+ ignoresDragEnter(false), ignoresDragMove(false)
+
+ {
+ }
+
+ ~DndTester()
+ {
+ delete lastEvent;
+ }
+
+ QGraphicsSceneDragDropEvent *lastEvent;
+ QList<QEvent::Type> eventList;
+ bool ignoresDragEnter;
+ bool ignoresDragMove;
+
+protected:
+ void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ event->setAccepted(!ignoresDragEnter);
+ if (!ignoresDragEnter)
+ event->setDropAction(Qt::IgnoreAction);
+ eventList << event->type();
+ }
+
+ void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ event->setAccepted(!ignoresDragMove);
+ eventList << event->type();
+ }
+
+ void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ eventList << event->type();
+ }
+
+ void dropEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ eventList << event->type();
+ }
+
+private:
+ void storeLastEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ delete lastEvent;
+ lastEvent = new QGraphicsSceneDragDropEvent(event->type());
+ lastEvent->setScenePos(event->scenePos());
+ lastEvent->setScreenPos(event->screenPos());
+ lastEvent->setButtons(event->buttons());
+ lastEvent->setModifiers(event->modifiers());
+ lastEvent->setPossibleActions(event->possibleActions());
+ lastEvent->setProposedAction(event->proposedAction());
+ lastEvent->setDropAction(event->dropAction());
+ lastEvent->setMimeData(event->mimeData());
+ lastEvent->setWidget(event->widget());
+ lastEvent->setSource(event->source());
+ }
+};
+
+#ifndef QT_NO_DRAGANDDROP
+void tst_QGraphicsScene::dragAndDrop_simple()
+{
+ DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(100, 100);
+
+ QMimeData mimeData;
+
+ // Initial drag enter for the scene
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragEnter);
+ QVERIFY(dragEnter.isAccepted());
+ QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
+
+ {
+ // Move outside the item
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ }
+ {
+ // Move inside the item without setAcceptDrops
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 0);
+ }
+ item->setAcceptDrops(true);
+ {
+ // Move inside the item with setAcceptDrops
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 2);
+ QCOMPARE(item->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
+ }
+ {
+ // Another move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->mapToScene(5, 5)), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
+ }
+ {
+ // Move outside the item
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 4);
+ QCOMPARE(item->eventList.at(3), QEvent::GraphicsSceneDragLeave);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::CopyAction);
+ }
+ {
+ // Move inside the item again
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 6);
+ QCOMPARE(item->eventList.at(4), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item->eventList.at(5), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
+ }
+ {
+ // Drop inside the item
+ QDropEvent drop(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &drop);
+ QVERIFY(drop.isAccepted());
+ QCOMPARE(drop.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 7);
+ QCOMPARE(item->eventList.at(6), QEvent::GraphicsSceneDrop);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(drop.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(drop.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::CopyAction);
+ }
+}
+
+void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
+{
+ DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
+ item->setAcceptDrops(true);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(100, 100);
+
+ QMimeData mimeData;
+
+ // Initial drag enter for the scene
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragEnter);
+ QVERIFY(dragEnter.isAccepted());
+ QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
+ {
+ // Move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 2);
+ QCOMPARE(item->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ }
+ {
+ // Move outside the item
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ }
+
+ // Now disable the item
+ item->setEnabled(false);
+ QVERIFY(!item->isEnabled());
+ QVERIFY(item->isVisible());
+
+ {
+ // Move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ }
+
+ // Reenable it, and make it invisible
+ item->setEnabled(true);
+ item->setVisible(false);
+ QVERIFY(item->isEnabled());
+ QVERIFY(!item->isVisible());
+
+ {
+ // Move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ }
+
+ // Dummy drop event to keep the Mac from crashing.
+ QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dropEvent);
+}
+
+void tst_QGraphicsScene::dragAndDrop_propagate()
+{
+ DndTester *item1 = new DndTester(QRectF(-10, -10, 20, 20));
+ DndTester *item2 = new DndTester(QRectF(0, 0, 20, 20));
+ item1->setAcceptDrops(true);
+ item2->setAcceptDrops(true);
+ item2->ignoresDragMove = true;
+ item2->ignoresDragEnter = false;
+ item2->setZValue(1);
+
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(100, 100);
+
+ QMimeData mimeData;
+
+ // Initial drag enter for the scene
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragEnter);
+ QVERIFY(dragEnter.isAccepted());
+ QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
+
+ {
+ // Move outside the items
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QVERIFY(item1->eventList.isEmpty());
+ QVERIFY(item2->eventList.isEmpty());
+ }
+ {
+ // Move inside item1
+ QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item1->eventList.size(), 2);
+ QCOMPARE(item1->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item1->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ }
+
+ {
+ // Move into the intersection item1-item2
+ QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted()); // move does not propagate, (ignoresDragMove = true)
+ QCOMPARE(item1->eventList.size(), 3);
+ QCOMPARE(item1->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ QCOMPARE(item2->eventList.size(), 2);
+ QCOMPARE(item2->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item2->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ }
+ {
+ // Move into the item2
+ QDragMoveEvent dragMove(view.mapFromScene(15, 15), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item1->eventList.size(), 3);
+ QCOMPARE(item2->eventList.size(), 3);
+ QCOMPARE(item2->eventList.at(2), QEvent::GraphicsSceneDragMove);
+ }
+ {
+ // Move inside item1
+ QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item1->eventList.size(), 5);
+ QCOMPARE(item1->eventList.at(3), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item1->eventList.at(4), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item2->eventList.size(), 4);
+ QCOMPARE(item2->eventList.at(3), QEvent::GraphicsSceneDragLeave);
+ }
+
+ {
+ item2->ignoresDragEnter = true;
+ // Move into the intersection item1-item2
+ QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted()); // dragEnter propagates down to item1, which then accepts the move event.
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item1->eventList.size(), 6);
+ QCOMPARE(item1->eventList.at(5), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item2->eventList.size(), 5);
+ QCOMPARE(item2->eventList.at(4), QEvent::GraphicsSceneDragEnter);
+ }
+
+ {
+ item2->ignoresDragEnter = false;
+ // Drop on the intersection item1-item2
+ QDropEvent drop(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &drop);
+ QVERIFY(drop.isAccepted());
+ QCOMPARE(drop.dropAction(), Qt::CopyAction);
+
+ QCOMPARE(item1->eventList.size(), 7);
+ QCOMPARE(item1->eventList.at(6), QEvent::GraphicsSceneDrop);
+ QCOMPARE(item2->eventList.size(), 5);
+ }
+
+ // Dummy drop event to keep the Mac from crashing.
+ QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dropEvent);
+}
+#endif
+
+void tst_QGraphicsScene::render_data()
+{
+ QTest::addColumn<QRectF>("targetRect");
+ QTest::addColumn<QRectF>("sourceRect");
+ QTest::addColumn<Qt::AspectRatioMode>("aspectRatioMode");
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QPainterPath>("clip");
+
+ QPainterPath clip_rect;
+ clip_rect.addRect(50, 100, 200, 150);
+
+ QPainterPath clip_ellipse;
+ clip_ellipse.addEllipse(100,50,150,200);
+
+ QTest::newRow("all-all-untransformed") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-topleft-untransformed") << QRectF(0, 0, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-topright-untransformed") << QRectF(150, 0, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-bottomleft-untransformed") << QRectF(0, 150, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-bottomright-untransformed") << QRectF(150, 150, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topleft-all-untransformed") << QRectF() << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topright-all-untransformed") << QRectF() << QRectF(0, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomleft-all-untransformed") << QRectF() << QRectF(-10, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomright-all-untransformed") << QRectF() << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topleft-topleft-untransformed") << QRectF(0, 0, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topright-topleft-untransformed") << QRectF(150, 0, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomleft-topleft-untransformed") << QRectF(0, 150, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomright-topleft-untransformed") << QRectF(150, 150, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("top-topleft-untransformed") << QRectF(0, 0, 300, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottom-topleft-untransformed") << QRectF(0, 150, 300, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("left-topleft-untransformed") << QRectF(0, 0, 150, 300) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("right-topleft-untransformed") << QRectF(150, 0, 150, 300) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("top-bottomright-untransformed") << QRectF(0, 0, 300, 150) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottom-bottomright-untransformed") << QRectF(0, 150, 300, 150) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("left-bottomright-untransformed") << QRectF(0, 0, 150, 300) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("right-bottomright-untransformed") << QRectF(150, 0, 150, 300) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-all-45-deg-right") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().rotate(-45) << QPainterPath();
+ QTest::newRow("all-all-45-deg-left") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().rotate(45) << QPainterPath();
+ QTest::newRow("all-all-scale-2x") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().scale(2, 2) << QPainterPath();
+ QTest::newRow("all-all-translate-50-0") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().translate(50, 0) << QPainterPath();
+ QTest::newRow("all-all-translate-0-50") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().translate(0, 50) << QPainterPath();
+ QTest::newRow("all-all-untransformed-clip-rect") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix() << clip_rect;
+ QTest::newRow("all-all-untransformed-clip-ellipse") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix() << clip_ellipse;
+}
+
+void tst_QGraphicsScene::render()
+{
+ QFETCH(QRectF, targetRect);
+ QFETCH(QRectF, sourceRect);
+ QFETCH(Qt::AspectRatioMode, aspectRatioMode);
+ QFETCH(QMatrix, matrix);
+ QFETCH(QPainterPath, clip);
+
+ QPixmap pix(30, 30);
+ pix.fill(Qt::blue);
+
+ QGraphicsView view;
+ QGraphicsScene scene(&view);
+ scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::white));
+ scene.addEllipse(QRectF(-2, -7, 4, 4), QPen(Qt::black), QBrush(Qt::yellow))->setZValue(1);
+ QGraphicsPixmapItem *item = scene.addPixmap(pix);
+ item->setZValue(2);
+ item->setOffset(QPointF(3, 3));
+ view.show();
+
+ scene.setSceneRect(scene.itemsBoundingRect());
+
+ QImage bigImage(300, 300, QImage::Format_RGB32);
+ bigImage.fill(0);
+ QPainter painter(&bigImage);
+ painter.setPen(Qt::lightGray);
+ for (int i = 0; i <= 300; i += 25) {
+ painter.drawLine(0, i, 300, i);
+ painter.drawLine(i, 0, i, 300);
+ }
+ painter.setPen(QPen(Qt::darkGray, 2));
+ painter.drawLine(0, 150, 300, 150);
+ painter.drawLine(150, 0, 150, 300);
+ painter.setMatrix(matrix);
+ if (!clip.isEmpty()) painter.setClipPath(clip);
+ scene.render(&painter, targetRect, sourceRect, aspectRatioMode);
+ painter.end();
+
+ const QString renderPath = QLatin1String(SRCDIR) + "/testData/render";
+ QString fileName = renderPath + QString("/%1.png").arg(QTest::currentDataTag());
+ QImage original(fileName);
+ QVERIFY(!original.isNull());
+
+ // Compare
+ int wrongPixels = 0;
+ for (int y = 0; y < original.height(); ++y) {
+ for (int x = 0; x < original.width(); ++x) {
+ if (bigImage.pixel(x, y) != original.pixel(x, y))
+ ++wrongPixels;
+ }
+ }
+
+ // This is a pixmap compare test - because of rounding errors on diverse
+ // platforms, and especially because tests are compiled in release mode,
+ // we set a 95% acceptance threshold for comparing images. This number may
+ // have to be adjusted if this test fails.
+ qreal threshold = 0.95;
+ qreal similarity = (1 - (wrongPixels / qreal(original.width() * original.height())));
+ if (similarity < threshold) {
+#if 1
+ // fail
+ QLabel *expectedLabel = new QLabel;
+ expectedLabel->setPixmap(QPixmap::fromImage(original));
+
+ QLabel *newLabel = new QLabel;
+ newLabel->setPixmap(QPixmap::fromImage(bigImage));
+
+ QGridLayout *gridLayout = new QGridLayout;
+ gridLayout->addWidget(new QLabel(tr("MISMATCH: %1").arg(QTest::currentDataTag())), 0, 0, 1, 2);
+ gridLayout->addWidget(new QLabel(tr("Current")), 1, 0);
+ gridLayout->addWidget(new QLabel(tr("Expected")), 1, 1);
+ gridLayout->addWidget(expectedLabel, 2, 1);
+ gridLayout->addWidget(newLabel, 2, 0);
+
+ QWidget widget;
+ widget.setLayout(gridLayout);
+ widget.show();
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QFAIL("Images are not identical.");
+#else
+ // generate
+ qDebug() << "Updating" << QTest::currentDataTag() << ":" << bigImage.save(fileName, "png");
+#endif
+ }
+}
+
+void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight()
+{
+ QGraphicsScene scene(0, 0, 150, 150);
+
+ // Add item with negative width.
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, -150, 50);
+ item1->setBrush(Qt::red);
+ item1->setPos(150, 50);
+ scene.addItem(item1);
+
+ // Add item with negative height.
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 50, -150);
+ item2->setBrush(Qt::blue);
+ item2->setPos(50, 150);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setFrameStyle(QFrame::NoFrame);
+ view.resize(150, 150);
+ view.show();
+ QCOMPARE(view.viewport()->size(), QSize(150, 150));
+
+ QImage expected(view.viewport()->size(), QImage::Format_RGB32);
+ view.viewport()->render(&expected);
+
+ // Make sure the scene background is the same as the viewport background.
+ scene.setBackgroundBrush(view.viewport()->palette().brush(view.viewport()->backgroundRole()));
+ QImage actual(150, 150, QImage::Format_RGB32);
+ QPainter painter(&actual);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(actual, expected);
+}
+
+void tst_QGraphicsScene::contextMenuEvent()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocus();
+
+ QVERIFY(item->hasFocus());
+ QVERIFY(scene.hasFocus());
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.activateWindow();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ view.centerOn(item);
+
+ {
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, view.viewport()->rect().center(),
+ view.mapToGlobal(view.viewport()->rect().center()));
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(item->eventTypes.last(), QEvent::GraphicsSceneContextMenu);
+ }
+}
+
+class ContextMenuItem : public QGraphicsRectItem
+{
+public:
+ ContextMenuItem() : QGraphicsRectItem(0, 0, 100, 100)
+ { setBrush(Qt::red); }
+
+protected:
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
+ { /* just accept */ }
+};
+
+void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ ContextMenuItem *item = new ContextMenuItem;
+ item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ scene.addItem(item);
+
+ QWidget topLevel;
+ QGraphicsView view(&scene, &topLevel);
+ view.resize(200, 200);
+ topLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWaitForWindowShown(&topLevel);
+
+ {
+ QPoint pos(50, 50);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QPoint pos(150, 150);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+ }
+ view.scale(1.5, 1.5);
+ {
+ QPoint pos(25, 25);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QPoint pos(55, 55);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+ }
+}
+
+void tst_QGraphicsScene::update()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
+ scene.addItem(rect);
+ qApp->processEvents();
+ rect->setPos(-100, -100);
+
+ // This function forces indexing
+ scene.itemAt(0, 0);
+
+ qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
+ QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
+
+ // We update the scene.
+ scene.update();
+
+ // This function forces a purge, which will post an update signal
+ scene.itemAt(0, 0);
+
+ // This will process the pending update
+ QApplication::instance()->processEvents();
+
+ // Check that the update region is correct
+ QCOMPARE(spy.count(), 1);
+ QRectF region;
+ foreach (QRectF rectF, qVariantValue<QList<QRectF> >(spy.at(0).at(0)))
+ region |= rectF;
+ QCOMPARE(region, QRectF(-100, -100, 200, 200));
+}
+
+void tst_QGraphicsScene::update2()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-200, -200, 200, 200);
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints >= 1);
+ view.repaints = 0;
+
+ // Make sure QGraphicsScene::update only requires one event-loop iteration
+ // before the view is updated.
+ scene.update();
+ qApp->processEvents();
+ QTRY_COMPARE(view.repaints, 1);
+ view.repaints = 0;
+
+ // The same for partial scene updates.
+ scene.update(QRectF(-100, -100, 100, 100));
+ qApp->processEvents();
+ QCOMPARE(view.repaints, 1);
+}
+
+void tst_QGraphicsScene::views()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QCOMPARE(scene.views().size(), 1);
+ QCOMPARE(scene.views().at(0), &view);
+
+ QGraphicsView view1(&scene);
+ QCOMPARE(scene.views().size(), 2);
+ QVERIFY(scene.views().contains(&view1));
+
+ view.setScene(0);
+ QCOMPARE(scene.views().size(), 1);
+ QCOMPARE(scene.views().at(0), &view1);
+
+ QGraphicsView *view2 = new QGraphicsView(&scene);
+ QCOMPARE(scene.views().size(), 2);
+ QCOMPARE(scene.views().at(0), &view1);
+ QCOMPARE(scene.views().at(1), view2);
+
+ delete view2;
+
+ QCOMPARE(scene.views().size(), 1);
+ QCOMPARE(scene.views().at(0), &view1);
+}
+
+class CustomScene : public QGraphicsScene
+{
+public:
+ CustomScene() : gotTimerEvent(false)
+ { startTimer(10); }
+
+ bool gotTimerEvent;
+protected:
+ void timerEvent(QTimerEvent *)
+ {
+ gotTimerEvent = true;
+ }
+};
+
+void tst_QGraphicsScene::event()
+{
+ // Test that QGraphicsScene properly propagates events to QObject.
+ CustomScene scene;
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(scene.gotTimerEvent);
+}
+
+class DisabledItemTester : public QGraphicsRectItem
+{
+public:
+ DisabledItemTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent)
+ { }
+
+ QList<QEvent::Type> receivedSceneEvents;
+ QList<QEvent::Type> receivedSceneEventFilters;
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ receivedSceneEventFilters << event->type();
+ return QGraphicsRectItem::sceneEventFilter(watched, event);
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ receivedSceneEvents << event->type();
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+};
+
+void tst_QGraphicsScene::eventsToDisabledItems()
+{
+ QGraphicsScene scene;
+
+ DisabledItemTester *item1 = new DisabledItemTester(QRectF(-50, -50, 100, 100));
+ DisabledItemTester *item2 = new DisabledItemTester(QRectF(-50, -50, 100, 100));
+ item1->setZValue(1); // on top
+
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ item1->installSceneEventFilter(item2);
+
+ QVERIFY(item1->receivedSceneEvents.isEmpty());
+ QVERIFY(item2->receivedSceneEvents.isEmpty());
+ QVERIFY(item1->receivedSceneEventFilters.isEmpty());
+ QVERIFY(item2->receivedSceneEventFilters.isEmpty());
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+
+ // First item2 receives a scene event filter. Then item1 receives the
+ // actual event. Finally the event propagates to item2. So both items
+ // should have received the event, and item1 also got the filter.
+ QCOMPARE(item1->receivedSceneEvents.size(), 3);
+ QCOMPARE(item2->receivedSceneEvents.size(), 3);
+ QCOMPARE(item1->receivedSceneEventFilters.size(), 0);
+ QCOMPARE(item2->receivedSceneEventFilters.size(), 3);
+
+ item1->receivedSceneEvents.clear();
+ item1->receivedSceneEventFilters.clear();
+ item2->receivedSceneEvents.clear();
+ item2->receivedSceneEventFilters.clear();
+
+ item1->setEnabled(false); // disable the topmost item, eat mouse events
+
+ event.setButton(Qt::LeftButton);
+ event.setAccepted(false);
+ QApplication::sendEvent(&scene, &event);
+
+ // Check that only item1 received anything - it only got the filter.
+ QCOMPARE(item1->receivedSceneEvents.size(), 0);
+ QCOMPARE(item2->receivedSceneEvents.size(), 0);
+ QCOMPARE(item1->receivedSceneEventFilters.size(), 0);
+ QCOMPARE(item2->receivedSceneEventFilters.size(), 3);
+}
+
+class ExposedPixmapItem : public QGraphicsPixmapItem
+{
+public:
+ ExposedPixmapItem(QGraphicsItem *item = 0)
+ : QGraphicsPixmapItem(item)
+ { }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ exposed = option->exposedRect;
+ }
+
+ QRectF exposed;
+};
+
+void tst_QGraphicsScene::exposedRect()
+{
+ ExposedPixmapItem *item = new ExposedPixmapItem;
+ item->setPixmap(QPixmap(":/Ash_European.jpg"));
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QCOMPARE(item->exposed, QRectF());
+
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ QPainter painter(&image);
+
+ scene.render(&painter);
+ QCOMPARE(item->exposed, item->boundingRect());
+
+ painter.rotate(180);
+ painter.translate(100, 100);
+
+ scene.render(&painter);
+ QCOMPARE(item->exposed, item->boundingRect());
+}
+
+void tst_QGraphicsScene::tabFocus_emptyScene()
+{
+ QGraphicsScene scene;
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWait(125);
+
+ dial1->setFocus();
+ QVERIFY(dial1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QVERIFY(!dial1->hasFocus());
+ QVERIFY(view->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QVERIFY(!view->hasFocus());
+ QVERIFY(dial2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QVERIFY(!dial2->hasFocus());
+ QVERIFY(view->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QVERIFY(dial1->hasFocus());
+ QVERIFY(!dial2->hasFocus());
+}
+
+void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText("Qt rocks!");
+ item->setTabChangesFocus(true);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QVERIFY(item->flags() & QGraphicsItem::ItemIsFocusable);
+ item->setFocus();
+ item->clearFocus();
+
+ QGraphicsTextItem *item2 = scene.addText("Trolltech rocks!");
+ item2->setTabChangesFocus(true);
+ item2->setTextInteractionFlags(Qt::TextEditorInteraction);
+ item2->setPos(0, item->boundingRect().bottom());
+ QVERIFY(item2->flags() & QGraphicsItem::ItemIsFocusable);
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ dial1->setFocus();
+ QTRY_VERIFY(dial1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(dial2->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(dial1->hasFocus());
+
+ // If the item requests input focus, it can only ensure that the scene
+ // sets focus on itself, but the scene cannot request focus from any view.
+ item->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QVERIFY(item->hasFocus());
+
+ view->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+
+ // Check that everyone loses focus when the widget is hidden.
+ widget.hide();
+ QTest::qWait(15);
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!item->hasFocus());
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ // Check that the correct item regains focus.
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(scene.isActive());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+ QVERIFY(item->hasFocus());
+}
+
+class FocusWidget : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ FocusWidget(QGraphicsItem *parent = 0)
+ : QGraphicsWidget(parent), tabs(0), backTabs(0)
+ {
+ setFocusPolicy(Qt::StrongFocus);
+ resize(100, 100);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ if (option->state & QStyle::State_HasFocus) {
+ painter->fillRect(rect(), Qt::blue);
+ }
+ painter->setBrush(Qt::green);
+ painter->drawEllipse(rect());
+ if (option->state & QStyle::State_HasFocus) {
+ painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(rect().adjusted(5, 5, -5, -5));
+ }
+ }
+
+ int tabs;
+ int backTabs;
+
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *k = static_cast<QKeyEvent *>(event);
+ if (k->key() == Qt::Key_Tab)
+ ++tabs;
+ if (k->key() == Qt::Key_Backtab)
+ ++backTabs;
+ }
+ return QGraphicsWidget::sceneEvent(event);
+ }
+
+ void focusInEvent(QFocusEvent *)
+ { update(); }
+ void focusOutEvent(QFocusEvent *)
+ { update(); }
+};
+
+void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets()
+{
+ QGraphicsScene scene;
+
+ FocusWidget *widget1 = new FocusWidget;
+ FocusWidget *widget2 = new FocusWidget;
+ widget2->setPos(widget1->boundingRect().right(), 0);
+ scene.addItem(widget1);
+ scene.addItem(widget2);
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->setRenderHint(QPainter::Antialiasing);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ dial1->setFocus();
+ QTRY_VERIFY(dial1->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QCOMPARE(widget1->tabs, 0);
+ QVERIFY(widget1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget1->tabs, 1);
+ QTRY_VERIFY(widget2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget2->tabs, 1);
+ QTRY_VERIFY(dial2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget2->backTabs, 1);
+ QTRY_VERIFY(widget1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget1->backTabs, 1);
+ QTRY_VERIFY(dial1->hasFocus());
+
+ widget1->setFocus();
+ view->viewport()->setFocus();
+ widget.hide();
+ QTest::qWait(15);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QTRY_VERIFY(widget1->hasFocus());
+}
+
+void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets()
+{
+ QGraphicsScene scene;
+
+ FocusWidget *widget1 = new FocusWidget;
+ FocusWidget *widget1_1 = new FocusWidget;
+ FocusWidget *widget1_2 = new FocusWidget;
+ widget1_1->setParentItem(widget1);
+ widget1_1->scale(0.5, 0.5);
+ widget1_1->setPos(0, widget1->boundingRect().height() / 2);
+ widget1_2->setParentItem(widget1);
+ widget1_2->scale(0.5, 0.5);
+ widget1_2->setPos(widget1->boundingRect().width() / 2, widget1->boundingRect().height() / 2);
+
+ FocusWidget *widget2 = new FocusWidget;
+ widget2->setPos(widget1->boundingRect().right(), 0);
+
+ widget1->setData(0, "widget1");
+ widget1_1->setData(0, "widget1_1");
+ widget1_2->setData(0, "widget1_2");
+ widget2->setData(0, "widget2");
+
+ scene.addItem(widget1);
+ scene.addItem(widget2);
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->setRenderHint(QPainter::Antialiasing);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+
+ dial1->setFocus();
+ QTRY_VERIFY(dial1->hasFocus());
+
+ EventSpy focusInSpy_1(widget1, QEvent::FocusIn);
+ EventSpy focusOutSpy_1(widget1, QEvent::FocusOut);
+ EventSpy focusInSpy_1_1(widget1_1, QEvent::FocusIn);
+ EventSpy focusOutSpy_1_1(widget1_1, QEvent::FocusOut);
+ EventSpy focusInSpy_1_2(widget1_2, QEvent::FocusIn);
+ EventSpy focusOutSpy_1_2(widget1_2, QEvent::FocusOut);
+ EventSpy focusInSpy_2(widget2, QEvent::FocusIn);
+ EventSpy focusOutSpy_2(widget2, QEvent::FocusOut);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget1->hasFocus());
+ QCOMPARE(focusInSpy_1.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1->hasFocus());
+ QVERIFY(widget1_1->hasFocus());
+ QCOMPARE(focusOutSpy_1.count(), 1);
+ QCOMPARE(focusInSpy_1_1.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_1->hasFocus());
+ QVERIFY(widget1_2->hasFocus());
+ QCOMPARE(focusOutSpy_1_1.count(), 1);
+ QCOMPARE(focusInSpy_1_2.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_2->hasFocus());
+ QVERIFY(widget2->hasFocus());
+ QCOMPARE(focusOutSpy_1_2.count(), 1);
+ QCOMPARE(focusInSpy_2.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget2->hasFocus());
+ QVERIFY(dial2->hasFocus());
+ QCOMPARE(focusOutSpy_2.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget2->hasFocus());
+ QCOMPARE(focusInSpy_2.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget2->hasFocus());
+ QTRY_VERIFY(widget1_2->hasFocus());
+ QCOMPARE(focusOutSpy_2.count(), 2);
+ QCOMPARE(focusInSpy_1_2.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_2->hasFocus());
+ QTRY_VERIFY(widget1_1->hasFocus());
+ QCOMPARE(focusOutSpy_1_2.count(), 2);
+ QCOMPARE(focusInSpy_1_1.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_1->hasFocus());
+ QTRY_VERIFY(widget1->hasFocus());
+ QCOMPARE(focusOutSpy_1_1.count(), 2);
+ QCOMPARE(focusInSpy_1.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1->hasFocus());
+ QTRY_VERIFY(dial1->hasFocus());
+ QCOMPARE(focusOutSpy_1.count(), 2);
+
+ widget1->setFocus();
+ view->viewport()->setFocus();
+ widget.hide();
+ QTest::qWait(12);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget1->hasFocus());
+}
+
+void tst_QGraphicsScene::style()
+{
+ QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
+
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *proxy = scene.addWidget(edit);
+
+ EventSpy sceneSpy(&scene, QEvent::StyleChange);
+ EventSpy proxySpy(proxy, QEvent::StyleChange);
+ EventSpy editSpy(edit, QEvent::StyleChange);
+
+ QCOMPARE(scene.style(), QApplication::style());
+
+ scene.setStyle(windowsStyle);
+ QCOMPARE(sceneSpy.count(), 1);
+ QCOMPARE(proxySpy.count(), 1);
+ QCOMPARE(editSpy.count(), 1);
+ QCOMPARE(scene.style(), (QStyle *)windowsStyle);
+ QCOMPARE(proxy->style(), (QStyle *)windowsStyle);
+ QCOMPARE(edit->style(), (QStyle *)windowsStyle);
+
+ scene.setStyle(0);
+ QCOMPARE(sceneSpy.count(), 2);
+ QCOMPARE(proxySpy.count(), 2);
+ QCOMPARE(editSpy.count(), 2);
+ QCOMPARE(scene.style(), QApplication::style());
+ QCOMPARE(proxy->style(), QApplication::style());
+ QCOMPARE(edit->style(), QApplication::style());
+ QVERIFY(!windowsStyle); // deleted
+}
+
+void tst_QGraphicsScene::task139710_bspTreeCrash()
+{
+ // create a scene with 2000 items
+ QGraphicsScene scene(0, 0, 1000, 1000);
+
+ for (int i = 0; i < 2; ++i) {
+ // trigger delayed item indexing
+ qApp->processEvents();
+ scene.setSceneRect(0, 0, 10000, 10000);
+
+ // delete all items in the scene - pointers are now likely to be recycled
+ foreach (QGraphicsItem *item, scene.items()) {
+ scene.removeItem(item);
+ delete item;
+ }
+
+ // add 1000 more items - the BSP tree is now resized
+ for (int i = 0; i < 1000; ++i) {
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 200, 200));
+ item->setPos(qrand() % 10000, qrand() % 10000);
+ }
+
+ // trigger delayed item indexing for the first 1000 items
+ qApp->processEvents();
+
+ // add 1000 more items - the BSP tree is now resized
+ for (int i = 0; i < 1000; ++i) {
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 200, 200));
+ item->setPos(qrand() % 10000, qrand() % 10000);
+ }
+
+ // get items from the BSP tree and use them. there was junk in the tree
+ // the second time this happened.
+ foreach (QGraphicsItem *item, scene.items(QRectF(0, 0, 1000, 1000)))
+ item->moveBy(0, 0);
+ }
+}
+
+void tst_QGraphicsScene::task139782_containsItemBoundingRect()
+{
+ // The item in question has a scene bounding rect of (10, 10, 50, 50)
+ QGraphicsScene scene(0.0, 0.0, 200.0, 200.0);
+ QGraphicsRectItem *item = new QGraphicsRectItem(0.0, 0.0, 50.0, 50.0, 0, &scene);
+ item->setPos(10.0, 10.0);
+
+ // The (0, 0, 50, 50) scene rect should not include the item's bounding rect
+ QVERIFY(!scene.items(QRectF(0.0, 0.0, 50.0, 50.0), Qt::ContainsItemBoundingRect).contains(item));
+
+ // The (9, 9, 500, 500) scene rect _should_ include the item's bounding rect
+ QVERIFY(scene.items(QRectF(9.0, 9.0, 500.0, 500.0), Qt::ContainsItemBoundingRect).contains(item));
+
+ // The (25, 25, 5, 5) scene rect should not include the item's bounding rect
+ QVERIFY(!scene.items(QRectF(25.0, 25.0, 5.0, 5.0), Qt::ContainsItemBoundingRect).contains(item));
+}
+
+void tst_QGraphicsScene::task176178_itemIndexMethodBreaksSceneRect()
+{
+ QGraphicsScene scene;
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ rect->setRect(0,0,100,100);
+ scene.addItem(rect);
+ QCOMPARE(scene.sceneRect(), rect->rect());
+}
+
+void tst_QGraphicsScene::task160653_selectionChanged()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ scene.addItem(new QGraphicsRectItem(0, 0, 20, 20));
+ scene.addItem(new QGraphicsRectItem(30, 30, 20, 20));
+ foreach (QGraphicsItem *item, scene.items()) {
+ item->setFlags(
+ item->flags() | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
+ item->setSelected(true);
+ }
+ QVERIFY(scene.items().size() > 1);
+ QCOMPARE(scene.items().size(), scene.selectedItems().size());
+
+ QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QGraphicsView view(&scene);
+ QTest::mouseClick(
+ view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.items().first()->scenePos()));
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QGraphicsScene::task250680_childClip()
+{
+ QGraphicsRectItem *clipper = new QGraphicsRectItem;
+ clipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ clipper->setPen(QPen(Qt::green));
+ clipper->setRect(200, 200, 640, 480);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem(clipper);
+ rect->setPen(QPen(Qt::red));
+ rect->setBrush(QBrush(QColor(255, 0, 0, 75)));
+ rect->setPos(320, 240);
+ rect->setRect(-25, -25, 50, 50);
+
+ QGraphicsScene scene;
+ scene.addItem(clipper);
+
+ QPainterPath path;
+ path.addRect(-25, -25, 50, 50);
+ QVERIFY(QPathCompare::comparePaths(rect->clipPath().simplified(), path));
+
+ QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
+ rect->rotate(45);
+ QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
+}
+
+void tst_QGraphicsScene::sorting_data()
+{
+ QTest::addColumn<bool>("cache");
+
+ QTest::newRow("Normal sorting") << false;
+ QTest::newRow("Cached sorting") << true;
+}
+
+void tst_QGraphicsScene::sorting()
+{
+ QFETCH(bool, cache);
+
+ QGraphicsScene scene;
+ scene.setSortCacheEnabled(cache);
+
+ QGraphicsRectItem *t_1 = new QGraphicsRectItem(0, 0, 50, 50);
+ QGraphicsRectItem *c_1 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
+ QGraphicsRectItem *c_1_1 = new QGraphicsRectItem(0, 0, 30, 30, c_1);
+ QGraphicsRectItem *c_1_1_1 = new QGraphicsRectItem(0, 0, 20, 20, c_1_1);
+ QGraphicsRectItem *c_1_2 = new QGraphicsRectItem(0, 0, 30, 30, c_1);
+ QGraphicsRectItem *c_2 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
+ QGraphicsRectItem *c_2_1 = new QGraphicsRectItem(0, 0, 30, 30, c_2);
+ QGraphicsRectItem *c_2_1_1 = new QGraphicsRectItem(0, 0, 20, 20, c_2_1);
+ QGraphicsRectItem *c_2_2 = new QGraphicsRectItem(0, 0, 30, 30, c_2);
+ t_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+
+ c_1->setPos(23, 18);
+ c_1_1->setPos(24, 28);
+ c_1_1_1->setPos(-16, 16);
+ c_1_2->setPos(-16, 28);
+ c_1_2->setZValue(1);
+ c_2->setPos(-23, 18);
+ c_2->setZValue(1);
+ c_2_1->setPos(24, 28);
+ c_2_1_1->setPos(-16, 16);
+ c_2_2->setPos(-16, 28);
+ c_2_2->setZValue(1);
+
+ c_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_1_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_1_1_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_1_2->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2_1_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2_2->setFlag(QGraphicsItem::ItemIsMovable);
+
+ t_1->setData(0, "t_1");
+ c_1->setData(0, "c_1");
+ c_1_1->setData(0, "c_1_1");
+ c_1_1_1->setData(0, "c_1_1_1");
+ c_1_2->setData(0, "c_1_2");
+ c_2->setData(0, "c_2");
+ c_2_1->setData(0, "c_2_1");
+ c_2_1_1->setData(0, "c_2_1_1");
+ c_2_2->setData(0, "c_2_2");
+
+ scene.addItem(t_1);
+
+ foreach (QGraphicsItem *item, scene.items())
+ item->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ // QGraphicsView view(&scene);
+ // view.setDragMode(QGraphicsView::RubberBandDrag);
+ // view.show();
+
+ qDebug() << "items: {";
+ foreach (QGraphicsItem *item, scene.items(32, 31, 4, 55))
+ qDebug() << "\t" << item->data(0).toString();
+ qDebug() << "}";
+
+ QCOMPARE(scene.items(32, 31, 4, 55),
+ QList<QGraphicsItem *>()
+ << c_1_2 << c_1_1_1 << c_1 << t_1);
+ QCOMPARE(scene.items(-53, 47, 136, 3),
+ QList<QGraphicsItem *>()
+ << c_2_2 << c_2_1 << c_2 << c_1_2 << c_1_1 << c_1 << t_1);
+ QCOMPARE(scene.items(-23, 79, 104, 3),
+ QList<QGraphicsItem *>()
+ << c_2_1_1 << c_1_1_1);
+ QCOMPARE(scene.items(-26, -3, 92, 79),
+ QList<QGraphicsItem *>()
+ << c_2_2 << c_2_1_1 << c_2_1 << c_2
+ << c_1_2 << c_1_1_1 << c_1_1 << c_1
+ << t_1);
+}
+
+class ChangedListener : public QObject
+{
+ Q_OBJECT
+public:
+ QList<QList<QRectF> > changes;
+
+public slots:
+ void changed(const QList<QRectF> &dirty)
+ {
+ changes << dirty;
+ }
+};
+
+void tst_QGraphicsScene::changedSignal_data()
+{
+ QTest::addColumn<bool>("withView");
+
+ QTest::newRow("without view") << false;
+ QTest::newRow("with view") << true;
+}
+
+void tst_QGraphicsScene::changedSignal()
+{
+ QFETCH(bool, withView);
+ QGraphicsScene scene;
+ ChangedListener cl;
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+
+ QGraphicsView *view = 0;
+ if (withView)
+ view = new QGraphicsView(&scene);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 10, 10);
+ scene.addItem(rect);
+
+ QCOMPARE(cl.changes.size(), 0);
+ QTRY_COMPARE(cl.changes.size(), 1);
+ QCOMPARE(cl.changes.at(0).size(), 1);
+ QCOMPARE(cl.changes.at(0).first(), QRectF(0, 0, 10, 10));
+
+ rect->setPos(20, 0);
+
+ QCOMPARE(cl.changes.size(), 1);
+ qApp->processEvents();
+ QCOMPARE(cl.changes.size(), 2);
+ QCOMPARE(cl.changes.at(1).size(), 2);
+ QCOMPARE(cl.changes.at(1).first(), QRectF(0, 0, 10, 10));
+ QCOMPARE(cl.changes.at(1).last(), QRectF(20, 0, 10, 10));
+
+ QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
+
+ if (withView)
+ delete view;
+}
+
+void tst_QGraphicsScene::stickyFocus_data()
+{
+ QTest::addColumn<bool>("sticky");
+ QTest::newRow("sticky") << true;
+ QTest::newRow("not sticky") << false;
+}
+
+void tst_QGraphicsScene::stickyFocus()
+{
+ QFETCH(bool, sticky);
+
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsTextItem *text = scene.addText("Hei");
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ text->setFocus();
+
+ scene.setStickyFocus(sticky);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(-10, -10)); // outside item
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+
+ QCOMPARE(text->hasFocus(), sticky);
+}
+
+void tst_QGraphicsScene::sendEvent()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText(QString());
+ EventSpy *spy = new EventSpy(&scene, item, QEvent::User);
+ QCOMPARE(spy->count(), 0);
+ QEvent event(QEvent::User);
+ scene.sendEvent(item, &event);
+ QCOMPARE(spy->count(), 1);
+}
+
+void tst_QGraphicsScene::inputMethod_data()
+{
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<bool>("callFocusItem");
+ QTest::newRow("0") << 0 << false;
+ QTest::newRow("1") << (int)QGraphicsItem::ItemAcceptsInputMethod << false;
+ QTest::newRow("2") << (int)QGraphicsItem::ItemIsFocusable << false;
+ QTest::newRow("3") <<
+ (int)(QGraphicsItem::ItemAcceptsInputMethod|QGraphicsItem::ItemIsFocusable) << true;
+}
+
+class InputMethodTester : public QGraphicsRectItem
+{
+ void inputMethodEvent(QInputMethodEvent *) { ++eventCalls; }
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const { ++queryCalls; return QVariant(); }
+public:
+ int eventCalls;
+ mutable int queryCalls;
+};
+
+class TestInputContext : public QInputContext
+{
+public:
+ TestInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {
+ ++resetCalls;
+ sendEvent(QInputMethodEvent()); }
+
+ bool isComposing() const { return false; }
+
+ int resetCalls;
+};
+
+void tst_QGraphicsScene::inputMethod()
+{
+ QFETCH(int, flags);
+ QFETCH(bool, callFocusItem);
+
+ InputMethodTester *item = new InputMethodTester;
+ item->setFlags((QGraphicsItem::GraphicsItemFlags)flags);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ TestInputContext *inputContext = new TestInputContext;
+ qApp->setInputContext(inputContext);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ view.setFocus();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ inputContext->resetCalls = 0;
+ scene.addItem(item);
+ QInputMethodEvent event;
+
+ scene.setFocusItem(item);
+ QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item);
+ QCOMPARE(inputContext->resetCalls, 0);
+
+ item->eventCalls = 0;
+ qApp->sendEvent(&scene, &event);
+ QCOMPARE(item->eventCalls, callFocusItem ? 1 : 0);
+
+ item->queryCalls = 0;
+ scene.inputMethodQuery((Qt::InputMethodQuery)0);
+ QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0);
+
+ scene.setFocusItem(0);
+ // the input context is reset twice, once because an item has lost focus and again because
+ // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
+ QCOMPARE(inputContext->resetCalls, callFocusItem ? 2 : 0);
+ QCOMPARE(item->eventCalls, callFocusItem ? 2 : 0); // verify correct delivery of "reset" event
+ QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected
+
+ item->eventCalls = 0;
+ qApp->sendEvent(&scene, &event);
+ QCOMPARE(item->eventCalls, 0);
+
+ item->queryCalls = 0;
+ scene.inputMethodQuery((Qt::InputMethodQuery)0);
+ QCOMPARE(item->queryCalls, 0);
+}
+
+void tst_QGraphicsScene::dispatchHoverOnPress()
+{
+ QGraphicsScene scene;
+ EventTester *tester1 = new EventTester;
+ tester1->setAcceptHoverEvents(true);
+ EventTester *tester2 = new EventTester;
+ tester2->setAcceptHoverEvents(true);
+ tester2->setPos(30, 30);
+ scene.addItem(tester1);
+ scene.addItem(tester2);
+
+ tester1->eventTypes.clear();
+ tester2->eventTypes.clear();
+
+ {
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
+ me.setButton(Qt::LeftButton);
+ me.setButtons(Qt::LeftButton);
+ QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
+ me2.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverEnter
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ tester1->eventTypes.clear();
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ }
+ {
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
+ me.setScenePos(QPointF(30, 30));
+ me.setButton(Qt::LeftButton);
+ me.setButtons(Qt::LeftButton);
+ QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
+ me2.setScenePos(QPointF(30, 30));
+ me2.setButton(Qt::LeftButton);
+ tester1->eventTypes.clear();
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ qDebug() << tester1->eventTypes;
+ QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverLeave);
+ QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverEnter
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ tester2->eventTypes.clear();
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ }
+}
+
+void tst_QGraphicsScene::initialFocus_data()
+{
+ QTest::addColumn<bool>("activeScene");
+ QTest::addColumn<bool>("explicitSetFocus");
+ QTest::addColumn<bool>("isPanel");
+ QTest::addColumn<bool>("shouldHaveFocus");
+
+ QTest::newRow("inactive scene, normal item") << false << false << false << false;
+ QTest::newRow("inactive scene, panel item") << false << false << true << false;
+ QTest::newRow("inactive scene, normal item, explicit focus") << false << true << false << true;
+ QTest::newRow("inactive scene, panel, explicit focus") << false << true << true << true;
+ QTest::newRow("active scene, normal item") << true << false << false << false;
+ QTest::newRow("active scene, panel item") << true << false << true << false;
+ QTest::newRow("active scene, normal item, explicit focus") << true << true << false << true;
+ QTest::newRow("active scene, panel, explicit focus") << true << true << true << true;
+}
+
+void tst_QGraphicsScene::initialFocus()
+{
+ QFETCH(bool, activeScene);
+ QFETCH(bool, explicitSetFocus);
+ QFETCH(bool, isPanel);
+ QFETCH(bool, shouldHaveFocus);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ rect->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!rect->hasFocus());
+
+ if (isPanel)
+ rect->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Setting focus on an item before adding to the scene will ensure
+ // it gets focus when the scene is activated.
+ if (explicitSetFocus)
+ rect->setFocus();
+
+ QGraphicsScene scene;
+ QVERIFY(!scene.isActive());
+
+ if (activeScene) {
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+ }
+
+ scene.addItem(rect);
+
+ if (!activeScene) {
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+ }
+
+ QCOMPARE(rect->hasFocus(), shouldHaveFocus);
+}
+
+class PolishItem : public QGraphicsTextItem
+{
+public:
+ PolishItem(QGraphicsItem *parent = 0)
+ : QGraphicsTextItem(parent), polished(false), deleteChildrenInPolish(true), addChildrenInPolish(false) { }
+
+ bool polished;
+ bool deleteChildrenInPolish;
+ bool addChildrenInPolish;
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant& value)
+ {
+ if (change == ItemVisibleChange) {
+ polished = true;
+ if (deleteChildrenInPolish)
+ qDeleteAll(childItems());
+ if (addChildrenInPolish) {
+ for (int i = 0; i < 10; ++i)
+ new PolishItem(this);
+ }
+ }
+ return QGraphicsItem::itemChange(change, value);
+ }
+};
+
+void tst_QGraphicsScene::polishItems()
+{
+ QGraphicsScene scene;
+ PolishItem *parent = new PolishItem;
+ scene.addItem(parent);
+ PolishItem *child = new PolishItem(parent);
+ Q_UNUSED(child)
+ // test that QGraphicsScenePrivate::_q_polishItems() doesn't crash
+ QMetaObject::invokeMethod(&scene,"_q_polishItems");
+}
+
+void tst_QGraphicsScene::polishItems2()
+{
+ QGraphicsScene scene;
+ PolishItem *item = new PolishItem;
+ item->addChildrenInPolish = true;
+ item->deleteChildrenInPolish = true;
+ // These children should be deleted in the polish.
+ for (int i = 0; i < 20; ++i)
+ new PolishItem(item);
+ scene.addItem(item);
+
+ // Wait for the polish event to be delivered.
+ QVERIFY(!item->polished);
+ QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
+ QVERIFY(item->polished);
+
+ // We deleted the children we added above, but we also
+ // added 10 new children. These should be polished in the next
+ // event loop iteration.
+ QList<QGraphicsItem *> children = item->childItems();
+ QCOMPARE(children.count(), 10);
+ foreach (QGraphicsItem *child, children)
+ QVERIFY(!static_cast<PolishItem *>(child)->polished);
+
+ QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
+ foreach (QGraphicsItem *child, children)
+ QVERIFY(static_cast<PolishItem *>(child)->polished);
+}
+
+void tst_QGraphicsScene::isActive()
+{
+ QGraphicsScene scene1;
+ QVERIFY(!scene1.isActive());
+ QGraphicsScene scene2;
+ QVERIFY(!scene2.isActive());
+
+ {
+ QWidget toplevel1;
+ QHBoxLayout *layout = new QHBoxLayout;
+ toplevel1.setLayout(layout);
+ QGraphicsView *view1 = new QGraphicsView(&scene1);
+ QGraphicsView *view2 = new QGraphicsView(&scene2);
+ layout->addWidget(view1);
+ layout->addWidget(view2);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+
+ view1->setVisible(false);
+
+ toplevel1.show();
+ QApplication::setActiveWindow(&toplevel1);
+ QTest::qWaitForWindowShown(&toplevel1);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel1);
+
+ QVERIFY(!scene1.isActive()); //it is hidden;
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view2->hide();
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ toplevel1.hide();
+ QTest::qWait(50);
+ QTRY_VERIFY(!scene1.isActive());
+ QTRY_VERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ toplevel1.show();
+ QApplication::setActiveWindow(&toplevel1);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel1);
+
+ QTRY_VERIFY(scene1.isActive());
+ QTRY_VERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view2->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+ }
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+
+ {
+ QWidget toplevel2;
+ QHBoxLayout *layout = new QHBoxLayout;
+ toplevel2.setLayout(layout);
+ QGraphicsView *view1 = new QGraphicsView(&scene1);
+ QGraphicsView *view2 = new QGraphicsView();
+ layout->addWidget(view1);
+ layout->addWidget(view2);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ toplevel2.show();
+ QApplication::setActiveWindow(&toplevel2);
+ QTest::qWaitForWindowShown(&toplevel2);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel2);
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view2->setScene(&scene2);
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view1->setScene(&scene2);
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->hide();
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->setScene(&scene1);
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view2->hide();
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ QGraphicsView topLevelView;
+ topLevelView.show();
+ QApplication::setActiveWindow(&topLevelView);
+ topLevelView.setFocus();
+ QTest::qWaitForWindowShown(&topLevelView);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&topLevelView));
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ topLevelView.setScene(&scene1);
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view2->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view1->hide();
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ QApplication::setActiveWindow(&toplevel2);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel2);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+ }
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ {
+ QWidget toplevel3;
+ QHBoxLayout *layout = new QHBoxLayout;
+ toplevel3.setLayout(layout);
+ QGraphicsView *view1 = new QGraphicsView(&scene1);
+ QGraphicsView *view2 = new QGraphicsView(&scene2);
+ layout->addWidget(view1);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+
+ toplevel3.show();
+ QApplication::setActiveWindow(&toplevel3);
+ QTest::qWaitForWindowShown(&toplevel3);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel3);
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ layout->addWidget(view2);
+ QApplication::processEvents();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view1->setParent(0);
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+ delete view1;
+ }
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+}
+
+void tst_QGraphicsScene::siblingIndexAlwaysValid()
+{
+ QGraphicsScene scene;
+
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ parent->setZValue(350);
+ parent->setGeometry(0, 0, 100, 100);
+ QGraphicsWidget *parent2 = new QGraphicsWidget;
+ parent2->setGeometry(10, 10, 50, 50);
+ QGraphicsWidget *child = new QGraphicsWidget(parent2);
+ child->setGeometry(15, 15, 25, 25);
+ child->setZValue(150);
+ //Both are top level
+ scene.addItem(parent);
+ scene.addItem(parent2);
+
+ //Then we make the child a top level
+ child->setParentItem(0);
+
+ //This is trigerred by a repaint...
+ QGraphicsScenePrivate::get(&scene)->index->estimateTopLevelItems(QRectF(), Qt::AscendingOrder);
+
+ delete child;
+
+ //If there are in the list that's bad, we crash...
+ QVERIFY(!QGraphicsScenePrivate::get(&scene)->topLevelItems.contains(static_cast<QGraphicsItem *>(child)));
+
+ //Other case
+ QGraphicsScene scene2;
+ // works with bsp tree index
+ scene2.setItemIndexMethod(QGraphicsScene::NoIndex);
+
+ QGraphicsView view2(&scene2);
+
+ // first add the blue rect
+ QGraphicsRectItem* const item1 = new QGraphicsRectItem(QRect( 10, 10, 10, 10 ));
+ item1->setPen(QColor(Qt::blue));
+ item1->setBrush(Qt::blue);
+ scene2.addItem(item1);
+
+ // then add the red rect
+ QGraphicsRectItem* const item2 = new QGraphicsRectItem(5, 5, 10, 10);
+ item2->setPen(QColor(Qt::red));
+ item2->setBrush(Qt::red);
+ scene2.addItem(item2);
+
+ // now the blue one is visible on top of the red one -> swap them (important for the bug)
+ item1->setZValue(1.0);
+ item2->setZValue(0.0);
+
+ view2.show();
+
+ // handle events as a real life app would do
+ QApplication::processEvents();
+
+ // now delete the red rect
+ delete item2;
+
+ // handle events as a real life app would do
+ QApplication::processEvents();
+
+ //We should not crash
+
+}
+
+void tst_QGraphicsScene::removeFullyTransparentItem()
+{
+ QGraphicsScene scene;
+
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ parent->setFlag(QGraphicsItem::ItemHasNoContents);
+
+ QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
+ child->setParentItem(parent);
+
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // NB! The parent has the ItemHasNoContents flag set, which means
+ // the parent itself doesn't generate any update requests, only the
+ // child can possibly trigger an update. Also note that the child
+ // is removed before processing events.
+ view.repaints = 0;
+ parent->setOpacity(0);
+ QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
+ scene.removeItem(child);
+ QVERIFY(!scene.items().contains(child));
+ QTRY_VERIFY(view.repaints > 0);
+
+ // Re-add child. There's nothing new to display (child is still
+ // effectively hidden), so it shouldn't trigger an update.
+ view.repaints = 0;
+ child->setParentItem(parent);
+ QVERIFY(scene.items().contains(child));
+ QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
+ QApplication::processEvents();
+ QCOMPARE(view.repaints, 0);
+
+ // Nothing is visible on the screen, removing child item shouldn't trigger an update.
+ scene.removeItem(child);
+ QApplication::processEvents();
+ QCOMPARE(view.repaints, 0);
+ delete child;
+}
+
+void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rectItem = scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));
+
+ rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ QPixmap pixmap(100,200);
+ QPainter painter(&pixmap);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+ // No crash, then it passed!
+}
+
+void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts()
+{
+ // Test using DeviceCoordinateCache and opaque item
+ QWidget *w = new QWidget();
+ w->setPalette(QColor(0, 0, 255));
+ w->setGeometry(0, 0, 50, 50);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ QGraphicsProxyWidget *proxy = scene->addWidget(w);
+ proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ proxy->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ proxy->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
+
+ QTransform t = proxy->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(proxy->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++)
+ QCOMPARE(qAlpha(im.pixel(i, j)), 255);
+ }
+
+ delete w;
+}
+
+void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
+{
+ // Test using DeviceCoordinateCache and semi-transparent item
+ {
+ QGraphicsRectItem *backItem = new QGraphicsRectItem(0, 0, 100, 100);
+ backItem->setBrush(QColor(255, 255, 0));
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
+ rectItem->setBrush(QColor(0, 0, 255, 125));
+ rectItem->setParentItem(backItem);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ scene->addItem(backItem);
+ rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ backItem->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ rectItem->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
+
+ QTransform t = rectItem->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++) {
+ QCOMPARE(qAlpha(im.pixel(i, j)), 125);
+ }
+ }
+
+ delete view;
+ }
+
+ // Test using ItemCoordinateCache and opaque item
+ {
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
+ rectItem->setBrush(QColor(0, 0, 255));
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ scene->addItem(rectItem);
+ rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ rectItem->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ rectItem->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
+
+ QTransform t = rectItem->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++)
+ QCOMPARE(qAlpha(im.pixel(i, j)), 255);
+ }
+
+ delete view;
+ }
+
+ // Test using ItemCoordinateCache and semi-transparent item
+ {
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
+ rectItem->setBrush(QColor(0, 0, 255, 125));
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ scene->addItem(rectItem);
+ rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ rectItem->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ rectItem->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
+
+ QTransform t = rectItem->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++)
+ QCOMPARE(qAlpha(im.pixel(i, j)), 125);
+ }
+
+ delete view;
+ }
+}
+
+void tst_QGraphicsScene::taskQT_3674_doNotCrash()
+{
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.resize(200, 200);
+
+ QPixmap pixmap(view.size());
+ QPainter painter(&pixmap);
+ view.render(&painter);
+ painter.end();
+
+ scene.addItem(new QGraphicsWidget);
+ scene.setBackgroundBrush(Qt::green);
+
+ QApplication::processEvents();
+ QApplication::processEvents();
+}
+
+void tst_QGraphicsScene::zeroScale()
+{
+ //should not crash
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 100, 100);
+ QGraphicsView view(&scene);
+
+ ChangedListener cl;
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+
+ QGraphicsRectItem *rect1 = new QGraphicsRectItem(0, 0, 0.0000001, 0.00000001);
+ scene.addItem(rect1);
+ rect1->setRotation(82);
+ rect1->setScale(0.00000001);
+
+ QApplication::processEvents();
+ QTRY_COMPARE(cl.changes.count(), 1);
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem(-0.0000001, -0.0000001, 0.0000001, 0.0000001);
+ rect2->setScale(0.00000001);
+ scene.addItem(rect2);
+ rect1->setPos(20,20);
+ QApplication::processEvents();
+ QTRY_COMPARE(cl.changes.count(), 2);
+}
+
+void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ rect->setPen(Qt::NoPen);
+ rect->setBrush(Qt::red);
+ rect->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ QImage image(100, 100, QImage::Format_RGB32);
+ QPainter p(&image);
+ scene.render(&p);
+ p.end();
+
+ QImage expected(100, 100, QImage::Format_RGB32);
+ p.begin(&expected);
+ p.fillRect(expected.rect(), Qt::red);
+ p.end();
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QGraphicsScene::taskQTBUG_16401_focusItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ rect->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+
+ QVERIFY(!scene.focusItem());
+
+ rect->setFocus();
+ QCOMPARE(scene.focusItem(), rect);
+ QFocusEvent focusOut(QEvent::FocusOut);
+ QApplication::sendEvent(&view, &focusOut);
+ QVERIFY(!scene.focusItem());
+ QFocusEvent focusIn(QEvent::FocusIn);
+ QApplication::sendEvent(&view, &focusIn);
+ QCOMPARE(scene.focusItem(), rect);
+
+ rect->clearFocus();
+ QVERIFY(!scene.focusItem());
+ QApplication::sendEvent(&view, &focusOut);
+ QVERIFY(!scene.focusItem());
+ QApplication::sendEvent(&view, &focusIn);
+ QVERIFY(!scene.focusItem());
+}
+
+QTEST_MAIN(tst_QGraphicsScene)
+#include "tst_qgraphicsscene.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
new file mode 100644
index 0000000000..5e61034d7c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+requires(contains(QT_CONFIG,private_tests))
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicssceneindex.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
new file mode 100644
index 0000000000..7507701267
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qgraphicsscene.h>
+#include <private/qgraphicsscenebsptreeindex_p.h>
+#include <private/qgraphicssceneindex_p.h>
+#include <private/qgraphicsscenelinearindex_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QGraphicsSceneIndex : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void customIndex_data();
+ void customIndex();
+ void scatteredItems_data();
+ void scatteredItems();
+ void overlappedItems_data();
+ void overlappedItems();
+ void movingItems_data();
+ void movingItems();
+ void connectedToSceneRectChanged();
+ void items();
+ void removeItems();
+ void clear();
+
+private:
+ void common_data();
+ QGraphicsSceneIndex *createIndex(const QString &name);
+};
+
+void tst_QGraphicsSceneIndex::initTestCase()
+{
+}
+
+void tst_QGraphicsSceneIndex::common_data()
+{
+ QTest::addColumn<QString>("indexMethod");
+
+ QTest::newRow("BSP") << QString("bsp");
+ QTest::newRow("Linear") << QString("linear");
+}
+
+QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod)
+{
+ QGraphicsSceneIndex *index = 0;
+ QGraphicsScene *scene = new QGraphicsScene();
+ if (indexMethod == "bsp")
+ index = new QGraphicsSceneBspTreeIndex(scene);
+
+ if (indexMethod == "linear")
+ index = new QGraphicsSceneLinearIndex(scene);
+
+ return index;
+}
+
+void tst_QGraphicsSceneIndex::customIndex_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::customIndex()
+{
+#if 0
+ QFETCH(QString, indexMethod);
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+
+ QGraphicsScene scene;
+ scene.setSceneIndex(index);
+
+ scene.addRect(0, 0, 30, 40);
+ QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1);
+#endif
+}
+
+void tst_QGraphicsSceneIndex::scatteredItems_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::scatteredItems()
+{
+ QFETCH(QString, indexMethod);
+
+ QGraphicsScene scene;
+#if 1
+ scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex);
+#else
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+ scene.setSceneIndex(index);
+#endif
+
+ for (int i = 0; i < 10; ++i)
+ scene.addRect(i*50, i*50, 40, 35);
+
+ QCOMPARE(scene.items(QPointF(5, 5)).count(), 1);
+ QCOMPARE(scene.items(QPointF(55, 55)).count(), 1);
+ QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0);
+
+ QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1);
+ QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10);
+ QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0);
+}
+
+void tst_QGraphicsSceneIndex::overlappedItems_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::overlappedItems()
+{
+ QFETCH(QString, indexMethod);
+
+ QGraphicsScene scene;
+#if 1
+ scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex);
+#else
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+ scene.setSceneIndex(index);
+#endif
+
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ scene.addRect(i*50, j*50, 200, 200);
+
+ QCOMPARE(scene.items(QPointF(5, 5)).count(), 1);
+ QCOMPARE(scene.items(QPointF(55, 55)).count(), 4);
+ QCOMPARE(scene.items(QPointF(105, 105)).count(), 9);
+ QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0);
+
+ QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100);
+ QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0);
+ QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16);
+ QCOMPARE(scene.items(QRectF(0, 0, 100, 100)).count(), 4);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 100)).count(), 2);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10);
+}
+
+void tst_QGraphicsSceneIndex::movingItems_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::movingItems()
+{
+ QFETCH(QString, indexMethod);
+
+ QGraphicsScene scene;
+#if 1
+ scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex);
+#else
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+ scene.setSceneIndex(index);
+#endif
+
+ for (int i = 0; i < 10; ++i)
+ scene.addRect(i*50, i*50, 40, 35);
+
+ QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10);
+ QCOMPARE(scene.items(QPointF(5, 5)).count(), 2);
+ QCOMPARE(scene.items(QPointF(-1, -1)).count(), 0);
+ QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2);
+
+ box->setPos(10, 10);
+ QCOMPARE(scene.items(QPointF(9, 9)).count(), 1);
+ QCOMPARE(scene.items(QPointF(15, 15)).count(), 2);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1);
+
+ box->setPos(-5, -5);
+ QCOMPARE(scene.items(QPointF(-1, -1)).count(), 1);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2);
+
+ QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11);
+}
+
+void tst_QGraphicsSceneIndex::connectedToSceneRectChanged()
+{
+
+ class MyScene : public QGraphicsScene
+ {
+ public:
+ using QGraphicsScene::receivers;
+ };
+
+ MyScene scene; // Uses QGraphicsSceneBspTreeIndex by default.
+ QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1);
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex); // QGraphicsSceneLinearIndex
+ QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1);
+}
+
+void tst_QGraphicsSceneIndex::items()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(0, 0, 10, 10);
+ QGraphicsItem *item2 = scene.addRect(10, 10, 10, 10);
+ QCOMPARE(scene.items().size(), 2);
+
+ // Move from unindexed items into bsp tree.
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 2);
+
+ // Add untransformable item.
+ QGraphicsItem *item3 = new QGraphicsRectItem(QRectF(20, 20, 10, 10));
+ item3->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ scene.addItem(item3);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Move from unindexed items into untransformable items.
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Move from untransformable items into unindexed items.
+ item3->setFlag(QGraphicsItem::ItemIgnoresTransformations, false);
+ QCOMPARE(scene.items().size(), 3);
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Make all items untransformable.
+ item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item3->setParentItem(item2);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Move from unindexed items into untransformable items.
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 3);
+}
+
+class RectWidget : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option */, QWidget * /* widget */)
+ {
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ }
+public:
+ QBrush brush;
+};
+
+void tst_QGraphicsSceneIndex::removeItems()
+{
+ QGraphicsScene scene;
+
+ RectWidget *parent = new RectWidget;
+ parent->brush = QBrush(QColor(Qt::magenta));
+ parent->setGeometry(250, 250, 400, 400);
+
+ RectWidget *widget = new RectWidget(parent);
+ widget->brush = QBrush(QColor(Qt::blue));
+ widget->setGeometry(10, 10, 200, 200);
+
+ RectWidget *widgetChild1 = new RectWidget(widget);
+ widgetChild1->brush = QBrush(QColor(Qt::green));
+ widgetChild1->setGeometry(20, 20, 100, 100);
+
+ RectWidget *widgetChild2 = new RectWidget(widgetChild1);
+ widgetChild2->brush = QBrush(QColor(Qt::yellow));
+ widgetChild2->setGeometry(25, 25, 50, 50);
+
+ scene.addItem(parent);
+
+ QGraphicsView view(&scene);
+ view.resize(600, 600);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ QApplication::processEvents();
+
+ scene.removeItem(widgetChild1);
+
+ delete widgetChild1;
+
+ //We move the parent
+ scene.items(295, 295, 50, 50);
+
+ //This should not crash
+}
+
+void tst_QGraphicsSceneIndex::clear()
+{
+ class MyItem : public QGraphicsItem
+ {
+ public:
+ MyItem(QGraphicsItem *parent = 0) : QGraphicsItem(parent), numPaints(0) {}
+ int numPaints;
+ protected:
+ QRectF boundingRect() const { return QRectF(0, 0, 10, 10); }
+ void paint(QPainter * /* painter */, const QStyleOptionGraphicsItem *, QWidget *)
+ { ++numPaints; }
+ };
+
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 100, 100);
+ scene.addItem(new MyItem);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(250);
+ scene.clear();
+
+ // Make sure the index is re-generated after QGraphicsScene::clear();
+ // otherwise no items will be painted.
+ MyItem *item = new MyItem;
+ scene.addItem(item);
+ qApp->processEvents();
+ QTRY_COMPARE(item->numPaints, 1);
+}
+
+QTEST_MAIN(tst_QGraphicsSceneIndex)
+#include "tst_qgraphicssceneindex.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro b/tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro
new file mode 100644
index 0000000000..de7f01f36f
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicstransform.cpp
+CONFIG += parallel_test
+
+linux-*:contains(QT_CONFIG,release):DEFINES+=MAY_HIT_QTBUG_20661
diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
new file mode 100644
index 0000000000..7d5a9578ad
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsitem.h>
+#include <qgraphicstransform.h>
+
+class tst_QGraphicsTransform : public QObject {
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void scale();
+ void rotation();
+ void rotation3d_data();
+ void rotation3d();
+ void rotation3dArbitraryAxis_data();
+ void rotation3dArbitraryAxis();
+
+private:
+ QString toString(QTransform const&);
+};
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsTransform::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsTransform::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsTransform::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsTransform::cleanup()
+{
+}
+
+static QTransform transform2D(const QGraphicsTransform& t)
+{
+ QMatrix4x4 m;
+ t.applyTo(&m);
+ return m.toTransform();
+}
+
+void tst_QGraphicsTransform::scale()
+{
+ QGraphicsScale scale;
+
+ // check initial conditions
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(10, 10, 0));
+
+ QMatrix4x4 t;
+ scale.applyTo(&t);
+
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(scale), QTransform());
+
+ scale.setXScale(10);
+ scale.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
+
+ QTransform res;
+ res.scale(10, 1);
+
+ QCOMPARE(transform2D(scale), res);
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(100, 10));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(scale).map(QPointF(11, 10)), QPointF(20, 10));
+
+ scale.setYScale(2);
+ scale.setZScale(4.5);
+ scale.setOrigin(QVector3D(1, 2, 3));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(2));
+ QCOMPARE(scale.zScale(), qreal(4.5));
+ QCOMPARE(scale.origin(), QVector3D(1, 2, 3));
+
+ QMatrix4x4 t2;
+ scale.applyTo(&t2);
+
+ QCOMPARE(t2.map(QVector3D(4, 5, 6)), QVector3D(31, 8, 16.5));
+
+ // Because the origin has a non-zero z, mapping (4, 5) in 2D
+ // will introduce a projective component into the result.
+ QTransform t3 = t2.toTransform();
+ QCOMPARE(t3.map(QPointF(4, 5)), QPointF(31 / t3.m33(), 8 / t3.m33()));
+}
+
+// QMatrix4x4 uses float internally, whereas QTransform uses qreal.
+// This can lead to issues with qFuzzyCompare() where it uses double
+// precision to compare values that have no more than float precision
+// after conversion from QMatrix4x4 to QTransform. The following
+// definitions correct for the difference.
+static inline bool fuzzyCompare(qreal p1, qreal p2)
+{
+ // increase delta on small machines using float instead of double
+ if (sizeof(qreal) == sizeof(float))
+ return (qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2)));
+ else
+ return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
+}
+
+static bool fuzzyCompare(const QTransform& t1, const QTransform& t2)
+{
+ return fuzzyCompare(t1.m11(), t2.m11()) &&
+ fuzzyCompare(t1.m12(), t2.m12()) &&
+ fuzzyCompare(t1.m13(), t2.m13()) &&
+ fuzzyCompare(t1.m21(), t2.m21()) &&
+ fuzzyCompare(t1.m22(), t2.m22()) &&
+ fuzzyCompare(t1.m23(), t2.m23()) &&
+ fuzzyCompare(t1.m31(), t2.m31()) &&
+ fuzzyCompare(t1.m32(), t2.m32()) &&
+ fuzzyCompare(t1.m33(), t2.m33());
+}
+
+static inline bool fuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ bool ok = true;
+ for (int y = 0; y < 4; ++y)
+ for (int x = 0; x < 4; ++x)
+ ok &= fuzzyCompare(m1(y, x), m2(y, x));
+ return ok;
+}
+
+void tst_QGraphicsTransform::rotation()
+{
+ QGraphicsRotation rotation;
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
+ QCOMPARE(rotation.angle(), (qreal)0);
+
+ rotation.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(10, 10, 0));
+ QCOMPARE(rotation.angle(), (qreal)0);
+
+ QMatrix4x4 t;
+ rotation.applyTo(&t);
+
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(rotation), QTransform());
+
+ rotation.setAngle(40);
+ rotation.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
+ QCOMPARE(rotation.angle(), (qreal)40);
+
+ QTransform res;
+ res.rotate(40);
+
+ QVERIFY(fuzzyCompare(transform2D(rotation), res));
+
+ rotation.setOrigin(QVector3D(10, 10, 0));
+ rotation.setAngle(90);
+ QCOMPARE(transform2D(rotation).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(rotation).map(QPointF(20, 10)), QPointF(10, 20));
+
+ rotation.setOrigin(QVector3D(0, 0, 0));
+ rotation.setAngle(qQNaN());
+ QCOMPARE(transform2D(rotation).map(QPointF(20, 10)), QPointF(20, 10));
+}
+
+Q_DECLARE_METATYPE(Qt::Axis);
+void tst_QGraphicsTransform::rotation3d_data()
+{
+ QTest::addColumn<Qt::Axis>("axis");
+ QTest::addColumn<qreal>("angle");
+
+ for (int angle = 0; angle <= 360; angle++) {
+ QTest::newRow("test rotation on X") << Qt::XAxis << qreal(angle);
+ QTest::newRow("test rotation on Y") << Qt::YAxis << qreal(angle);
+ QTest::newRow("test rotation on Z") << Qt::ZAxis << qreal(angle);
+ }
+}
+
+void tst_QGraphicsTransform::rotation3d()
+{
+ QFETCH(Qt::Axis, axis);
+ QFETCH(qreal, angle);
+
+ QGraphicsRotation rotation;
+ rotation.setAxis(axis);
+
+ QMatrix4x4 t;
+ rotation.applyTo(&t);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setAngle(angle);
+
+ // QGraphicsRotation uses a correct mathematical rotation in 3D.
+ // QTransform's Qt::YAxis rotation is inverted from the mathematical
+ // version of rotation. We correct for that here.
+ QTransform expected;
+ if (axis == Qt::YAxis && angle != 180.)
+ expected.rotate(-angle, axis);
+ else
+ expected.rotate(angle, axis);
+
+ QVERIFY(fuzzyCompare(transform2D(rotation), expected));
+
+ // Check that "rotation" produces the 4x4 form of the 3x3 matrix.
+ // i.e. third row and column are 0 0 1 0.
+ t.setToIdentity();
+ rotation.applyTo(&t);
+ QMatrix4x4 r(expected);
+ if (sizeof(qreal) == sizeof(float) && angle == 268) {
+ // This test fails, on only this angle, when qreal == float
+ // because the deg2rad value in QTransform is not accurate
+ // enough to match what QMatrix4x4 is doing.
+ } else {
+ QVERIFY(fuzzyCompare(t, r));
+ }
+
+ //now let's check that a null vector will not change the transform
+ rotation.setAxis(QVector3D(0, 0, 0));
+ rotation.setOrigin(QVector3D(10, 10, 0));
+
+ t.setToIdentity();
+ rotation.applyTo(&t);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setAngle(angle);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setOrigin(QVector3D(0, 0, 0));
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+}
+
+QByteArray labelForTest(QVector3D const& axis, int angle) {
+ return QString("rotation of %1 on (%2, %3, %4)")
+ .arg(angle)
+ .arg(axis.x())
+ .arg(axis.y())
+ .arg(axis.z())
+ .toLatin1();
+}
+
+void tst_QGraphicsTransform::rotation3dArbitraryAxis_data()
+{
+ QTest::addColumn<QVector3D>("axis");
+ QTest::addColumn<qreal>("angle");
+
+ QVector3D axis1 = QVector3D(1.0f, 1.0f, 1.0f);
+ QVector3D axis2 = QVector3D(2.0f, -3.0f, 0.5f);
+ QVector3D axis3 = QVector3D(-2.0f, 0.0f, -0.5f);
+ QVector3D axis4 = QVector3D(0.0001f, 0.0001f, 0.0001f);
+ QVector3D axis5 = QVector3D(0.01f, 0.01f, 0.01f);
+
+ for (int angle = 0; angle <= 360; angle++) {
+ QTest::newRow(labelForTest(axis1, angle).constData()) << axis1 << qreal(angle);
+ QTest::newRow(labelForTest(axis2, angle).constData()) << axis2 << qreal(angle);
+ QTest::newRow(labelForTest(axis3, angle).constData()) << axis3 << qreal(angle);
+ QTest::newRow(labelForTest(axis4, angle).constData()) << axis4 << qreal(angle);
+ QTest::newRow(labelForTest(axis5, angle).constData()) << axis5 << qreal(angle);
+ }
+}
+
+void tst_QGraphicsTransform::rotation3dArbitraryAxis()
+{
+ QFETCH(QVector3D, axis);
+ QFETCH(qreal, angle);
+
+ QGraphicsRotation rotation;
+ rotation.setAxis(axis);
+
+ QMatrix4x4 t;
+ rotation.applyTo(&t);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setAngle(angle);
+
+ // Compute the expected answer using QMatrix4x4 and a projection.
+ // These two steps are performed in one hit by QGraphicsRotation.
+ QMatrix4x4 exp;
+ exp.rotate(angle, axis);
+ QTransform expected = exp.toTransform(1024.0f);
+
+#if defined(MAY_HIT_QTBUG_20661)
+ // These failures possibly relate to the float vs qreal issue mentioned
+ // in the comment above fuzzyCompare().
+ if (sizeof(qreal) == sizeof(double)) {
+ QEXPECT_FAIL("rotation of 120 on (1, 1, 1)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 240 on (1, 1, 1)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 120 on (0.01, 0.01, 0.01)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 240 on (0.01, 0.01, 0.01)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 120 on (0.0001, 0.0001, 0.0001)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 240 on (0.0001, 0.0001, 0.0001)", "QTBUG-20661", Abort);
+ }
+#endif
+
+ QTransform actual = transform2D(rotation);
+ QVERIFY2(fuzzyCompare(actual, expected), qPrintable(
+ QString("\nactual: %1\n"
+ "expected: %2")
+ .arg(toString(actual))
+ .arg(toString(expected))
+ ));
+
+ // Check that "rotation" produces the 4x4 form of the 3x3 matrix.
+ // i.e. third row and column are 0 0 1 0.
+ t.setToIdentity();
+ rotation.applyTo(&t);
+ QMatrix4x4 r(expected);
+ QVERIFY(qFuzzyCompare(t, r));
+}
+
+QString tst_QGraphicsTransform::toString(QTransform const& t)
+{
+ return QString("[ [ %1 %2 %3 ]; [ %4 %5 %6 ]; [ %7 %8 %9 ] ]")
+ .arg(t.m11())
+ .arg(t.m12())
+ .arg(t.m13())
+ .arg(t.m21())
+ .arg(t.m22())
+ .arg(t.m23())
+ .arg(t.m31())
+ .arg(t.m32())
+ .arg(t.m33())
+ ;
+}
+
+
+QTEST_MAIN(tst_QGraphicsTransform)
+#include "tst_qgraphicstransform.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsview/.gitignore
new file mode 100644
index 0000000000..c8182c9e0d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsview
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
new file mode 100644
index 0000000000..9f32522546
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicsview.cpp tst_qgraphicsview_2.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
new file mode 100644
index 0000000000..0a404cab46
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -0,0 +1,4558 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qgraphicsitem.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qgraphicswidget.h>
+#include <qgraphicsproxywidget.h>
+
+#include <math.h>
+
+#include <QtWidgets/QLabel>
+#if !defined(QT_NO_STYLE_MOTIF)
+#include <QtWidgets/QMotifStyle>
+#endif
+#if !defined(QT_NO_STYLE_WINDOWS)
+#include <QtWidgets/QWindowsStyle>
+#endif
+#if !defined(QT_NO_STYLE_PLASTIQUE)
+#include <QtWidgets/QPlastiqueStyle>
+#endif
+#include <QtGui/QPainterPath>
+#include <QtWidgets/QRubberBand>
+#include <QtWidgets/QScrollBar>
+#include <QtWidgets/QStyleOption>
+#include <QtWidgets/QBoxLayout>
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QInputContext>
+#include <QtWidgets/QDesktopWidget>
+#include <private/qgraphicsview_p.h>
+#include "../../../platformquirks.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QPolygonF)
+Q_DECLARE_METATYPE(QRectF)
+Q_DECLARE_METATYPE(Qt::ScrollBarPolicy)
+
+#ifdef Q_WS_MAC
+//On mac we get full update. So check that the expected region is contained inside the actual
+#define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
+#else
+#define COMPARE_REGIONS QCOMPARE
+#endif
+
+static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseButtonPress, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
+{
+ QTest::mouseMove(widget, point);
+ QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
+ QApplication::sendEvent(widget, &event);
+ QApplication::processEvents();
+}
+
+static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseButtonRelease, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+class EventSpy : public QObject
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+ void reset() { _count = 0; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class tst_QGraphicsView : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void construction();
+ void renderHints();
+ void alignment();
+ void interactive();
+ void scene();
+ void setScene();
+ void deleteScene();
+ void sceneRect();
+ void sceneRect_growing();
+ void setSceneRect();
+ void viewport();
+ void dragMode_scrollHand();
+ void dragMode_rubberBand();
+ void rubberBandSelectionMode();
+ void backgroundBrush();
+ void foregroundBrush();
+ void matrix();
+ void matrix_convenience();
+ void matrix_combine();
+ void centerOnPoint();
+ void centerOnItem();
+ void ensureVisibleRect();
+ void fitInView();
+ void itemsAtPoint();
+ void itemsInRect();
+ void itemsInRect_cosmeticAdjust_data();
+ void itemsInRect_cosmeticAdjust();
+ void itemsInPoly();
+ void itemsInPath();
+ void itemAt();
+ void itemAt2();
+ void mapToScene();
+ void mapToScenePoint();
+ void mapToSceneRect_data();
+ void mapToSceneRect();
+ void mapToScenePoly();
+ void mapToScenePath();
+ void mapFromScenePoint();
+ void mapFromSceneRect();
+ void mapFromScenePoly();
+ void mapFromScenePath();
+ void sendEvent();
+ void wheelEvent();
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+ void cursor();
+ void cursor2();
+#endif
+ void transformationAnchor();
+ void resizeAnchor();
+ void viewportUpdateMode();
+ void viewportUpdateMode2();
+#ifndef QT_NO_DRAGANDDROP
+ void acceptDrops();
+#endif
+ void optimizationFlags();
+ void optimizationFlags_dontSavePainterState();
+ void optimizationFlags_dontSavePainterState2_data();
+ void optimizationFlags_dontSavePainterState2();
+ void levelOfDetail_data();
+ void levelOfDetail();
+ void scrollBarRanges_data();
+ void scrollBarRanges();
+ void acceptMousePressEvent();
+ void replayMouseMove();
+ void itemsUnderMouse();
+ void embeddedViews();
+ void scrollAfterResize_data();
+ void scrollAfterResize();
+ void moveItemWhileScrolling_data();
+ void moveItemWhileScrolling();
+ void centerOnDirtyItem();
+ void mouseTracking();
+ void mouseTracking2();
+ void mouseTracking3();
+ void render();
+ void exposeRegion();
+ void update_data();
+ void update();
+ void update2_data();
+ void update2();
+ void update_ancestorClipsChildrenToShape();
+ void update_ancestorClipsChildrenToShape2();
+ void inputMethodSensitivity();
+ void inputContextReset();
+ void indirectPainting();
+ void compositionModeInDrawBackground();
+
+ // task specific tests below me
+ void task172231_untransformableItems();
+ void task180429_mouseReleaseDragMode();
+ void task187791_setSceneCausesUpdate();
+ void task186827_deleteReplayedItem();
+ void task207546_focusCrash();
+ void task210599_unsetDragWhileDragging();
+ void task236394_sendShortcutOverrideEvent();
+ void task239729_noViewUpdate_data();
+ void task239729_noViewUpdate();
+ void task239047_fitInViewSmallViewport();
+ void task245469_itemsAtPointWithClip();
+ void task253415_reconnectUpdateSceneOnSceneChanged();
+#ifndef Q_OS_WINCE
+ void task255529_transformationAnchorMouseAndViewportMargins();
+#endif
+ void task259503_scrollingArtifacts();
+ void QTBUG_4151_clipAndIgnore_data();
+ void QTBUG_4151_clipAndIgnore();
+ void QTBUG_5859_exposedRect();
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+ void QTBUG_7438_cursor();
+#endif
+ void hoverLeave();
+ void QTBUG_16063_microFocusRect();
+
+public slots:
+ void dummySlot() {}
+};
+
+void tst_QGraphicsView::initTestCase()
+{
+#ifdef Q_OS_WINCE_WM
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QGraphicsView::construction()
+{
+ QGraphicsView view;
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
+ QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
+ QVERIFY(view.isInteractive());
+ QVERIFY(!view.scene());
+ QCOMPARE(view.sceneRect(), QRectF());
+ QVERIFY(view.viewport());
+ QCOMPARE(view.viewport()->metaObject()->className(), "QWidget");
+ QCOMPARE(view.matrix(), QMatrix());
+ QVERIFY(view.items().isEmpty());
+ QVERIFY(view.items(QPoint()).isEmpty());
+ QVERIFY(view.items(QRect()).isEmpty());
+ QVERIFY(view.items(QPolygon()).isEmpty());
+ QVERIFY(view.items(QPainterPath()).isEmpty());
+ QVERIFY(!view.itemAt(QPoint()));
+ QCOMPARE(view.mapToScene(QPoint()), QPointF());
+ QCOMPARE(view.mapToScene(QRect()), QPolygonF());
+ QCOMPARE(view.mapToScene(QPolygon()), QPolygonF());
+ QCOMPARE(view.mapFromScene(QPointF()), QPoint());
+ QPolygon poly;
+ poly << QPoint() << QPoint() << QPoint() << QPoint();
+ QCOMPARE(view.mapFromScene(QRectF()), poly);
+ QCOMPARE(view.mapFromScene(QPolygonF()), QPolygon());
+ QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
+ QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+}
+
+class TestItem : public QGraphicsItem
+{
+public:
+ QRectF boundingRect() const
+ { return QRectF(-10, -10, 20, 20); }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { hints = painter->renderHints(); painter->drawRect(boundingRect()); }
+
+ bool sceneEvent(QEvent *event)
+ {
+ events << event->type();
+ return QGraphicsItem::sceneEvent(event);
+ }
+
+ QList<QEvent::Type> events;
+ QPainter::RenderHints hints;
+};
+
+void tst_QGraphicsView::renderHints()
+{
+ QGraphicsView view;
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
+ view.setRenderHint(QPainter::TextAntialiasing, false);
+ QCOMPARE(view.renderHints(), 0);
+ view.setRenderHint(QPainter::Antialiasing, false);
+ QCOMPARE(view.renderHints(), 0);
+ view.setRenderHint(QPainter::TextAntialiasing, true);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
+ view.setRenderHint(QPainter::Antialiasing);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing);
+ view.setRenderHints(0);
+ QCOMPARE(view.renderHints(), 0);
+
+ TestItem *item = new TestItem;
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ view.setScene(&scene);
+
+ view.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+
+ QCOMPARE(item->hints, 0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.repaint();
+ QTRY_COMPARE(item->hints, view.renderHints());
+
+ view.setRenderHints(QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+ QCOMPARE(view.renderHints(), QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+
+ view.repaint();
+ QTRY_COMPARE(item->hints, view.renderHints());
+}
+
+void tst_QGraphicsView::alignment()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-10, -10, 20, 20));
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ Qt::Alignment alignment = 0;
+ switch (i) {
+ case 0:
+ alignment |= Qt::AlignLeft;
+ break;
+ case 1:
+ alignment |= Qt::AlignHCenter;
+ break;
+ case 2:
+ default:
+ alignment |= Qt::AlignRight;
+ break;
+ }
+ switch (j) {
+ case 0:
+ alignment |= Qt::AlignTop;
+ break;
+ case 1:
+ alignment |= Qt::AlignVCenter;
+ break;
+ case 2:
+ default:
+ alignment |= Qt::AlignBottom;
+ break;
+ }
+ view.setAlignment(alignment);
+ QCOMPARE(view.alignment(), alignment);
+
+ for (int k = 0; k < 3; ++k) {
+ view.resize(100 + k * 25, 100 + k * 25);
+ QApplication::processEvents();
+ }
+ }
+ }
+}
+
+void tst_QGraphicsView::interactive()
+{
+ TestItem *item = new TestItem;
+ item->setFlags(QGraphicsItem::ItemIsMovable);
+ QCOMPARE(item->events.size(), 0);
+
+ QGraphicsScene scene(-200, -200, 400, 400);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.setFixedSize(300, 300);
+ QCOMPARE(item->events.size(), 0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.activateWindow();
+
+ QApplication::processEvents();
+ QTRY_COMPARE(item->events.size(), 1); // activate
+
+ QPoint itemPoint = view.mapFromScene(item->scenePos());
+
+ QVERIFY(view.itemAt(itemPoint));
+
+ for (int i = 0; i < 100; ++i) {
+ sendMousePress(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), i * 5 + 3);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
+ sendMouseRelease(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), i * 5 + 5);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
+ QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, itemPoint, view.mapToGlobal(itemPoint));
+ QApplication::sendEvent(view.viewport(), &contextEvent);
+ QCOMPARE(item->events.size(), i * 5 + 6);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ }
+
+ view.setInteractive(false);
+
+ for (int i = 0; i < 100; ++i) {
+ sendMousePress(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), 501);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ sendMouseRelease(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), 501);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, itemPoint, view.mapToGlobal(itemPoint));
+ QApplication::sendEvent(view.viewport(), &contextEvent);
+ QCOMPARE(item->events.size(), 501);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ }
+}
+
+void tst_QGraphicsView::scene()
+{
+ QGraphicsView view;
+ QVERIFY(!view.scene());
+ view.setScene(0);
+ QVERIFY(!view.scene());
+
+ {
+ QGraphicsScene scene;
+ view.setScene(&scene);
+ QCOMPARE(view.scene(), &scene);
+ }
+
+ QCOMPARE(view.scene(), (QGraphicsScene *)0);
+}
+
+void tst_QGraphicsView::setScene()
+{
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.sceneRect(), scene.sceneRect());
+
+ QVERIFY(view.horizontalScrollBar()->isVisible());
+ QVERIFY(view.verticalScrollBar()->isVisible());
+ QVERIFY(!view.horizontalScrollBar()->isHidden());
+ QVERIFY(!view.verticalScrollBar()->isHidden());
+
+ view.setScene(0);
+
+ QTest::qWait(25);
+
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
+ QVERIFY(!view.verticalScrollBar()->isVisible());
+ QVERIFY(!view.horizontalScrollBar()->isHidden());
+ QVERIFY(!view.verticalScrollBar()->isHidden());
+
+ QCOMPARE(view.sceneRect(), QRectF());
+}
+
+void tst_QGraphicsView::deleteScene()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsView view1(scene);
+ view1.show();
+ QGraphicsView view2(scene);
+ view2.show();
+ QGraphicsView view3(scene);
+ view3.show();
+ delete scene;
+ QCOMPARE(view1.scene(), (QGraphicsScene *)0);
+ QCOMPARE(view2.scene(), (QGraphicsScene *)0);
+ QCOMPARE(view3.scene(), (QGraphicsScene *)0);
+}
+
+void tst_QGraphicsView::sceneRect()
+{
+ QGraphicsView view;
+ QCOMPARE(view.sceneRect(), QRectF());
+
+ view.setSceneRect(QRectF(-100, -100, 200, 200));
+ QCOMPARE(view.sceneRect(), QRectF(-100, -100, 200, 200));
+ view.setSceneRect(-100, -100, 200, 200);
+ QCOMPARE(view.sceneRect(), QRectF(-100, -100, 200, 200));
+
+ view.setSceneRect(QRectF());
+ QCOMPARE(view.sceneRect(), QRectF());
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF(-100, -100, 100, 100));
+
+ view.setScene(&scene);
+
+ QCOMPARE(view.sceneRect(), QRectF(-100, -100, 100, 100));
+ item->moveBy(-100, -100);
+ QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
+ item->moveBy(100, 100);
+ QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
+
+ view.setScene(0);
+ view.setSceneRect(QRectF());
+ QCOMPARE(view.sceneRect(), QRectF());
+}
+
+void tst_QGraphicsView::sceneRect_growing()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ for (int i = 0; i < 100; ++i)
+ scene.addText(QString("(0, %1)").arg((i - 50) * 20))->setPos(0, (i - 50) * 20);
+
+ QGraphicsView view(&scene, &toplevel);
+ view.setFixedSize(200, 200);
+ toplevel.show();
+
+ int size = 200;
+ scene.setSceneRect(-size, -size, size * 2, size * 2);
+ QCOMPARE(view.sceneRect(), scene.sceneRect());
+
+ QTest::qWait(25);
+
+ QPointF topLeft = view.mapToScene(0, 0);
+
+ for (int i = 0; i < 5; ++i) {
+ size *= 2;
+ scene.setSceneRect(-size, -size, size * 2, size * 2);
+
+ QApplication::processEvents();
+
+ QCOMPARE(view.sceneRect(), scene.sceneRect());
+ QCOMPARE(view.mapToScene(0, 0), topLeft);
+ view.setSceneRect(-size, -size, size * 2, size * 2);
+ QCOMPARE(view.mapToScene(0, 0), topLeft);
+ view.setSceneRect(QRectF());
+ }
+}
+
+void tst_QGraphicsView::setSceneRect()
+{
+ QRectF rect1(-100, -100, 200, 200);
+ QRectF rect2(-300, -300, 150, 150);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ scene.setSceneRect(rect1);
+ QCOMPARE(scene.sceneRect(), rect1);
+ QCOMPARE(view.sceneRect(), rect1);
+
+ scene.setSceneRect(rect2);
+ QCOMPARE(scene.sceneRect(), rect2);
+ QCOMPARE(view.sceneRect(), rect2);
+
+ view.setSceneRect(rect1);
+ QCOMPARE(scene.sceneRect(), rect2);
+ QCOMPARE(view.sceneRect(), rect1);
+
+ view.setSceneRect(rect2);
+ QCOMPARE(scene.sceneRect(), rect2);
+ QCOMPARE(view.sceneRect(), rect2);
+
+ scene.setSceneRect(rect1);
+ QCOMPARE(scene.sceneRect(), rect1);
+ QCOMPARE(view.sceneRect(), rect2);
+
+ // extreme transformations will max out the scrollbars' ranges.
+ view.setSceneRect(-2000000, -2000000, 4000000, 4000000);
+ view.scale(9000, 9000);
+ QCOMPARE(view.horizontalScrollBar()->minimum(), INT_MIN);
+ QCOMPARE(view.horizontalScrollBar()->maximum(), INT_MAX);
+ QCOMPARE(view.verticalScrollBar()->minimum(), INT_MIN);
+ QCOMPARE(view.verticalScrollBar()->maximum(), INT_MAX);
+}
+
+void tst_QGraphicsView::viewport()
+{
+ QGraphicsScene scene;
+ scene.addText("GraphicsView");
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport() != 0);
+
+ view.show();
+ QTest::qWait(25);
+
+ QPointer<QWidget> widget = new QWidget;
+ view.setViewport(widget);
+ QCOMPARE(view.viewport(), (QWidget *)widget);
+
+ view.show();
+ QTest::qWait(25);
+
+ view.setViewport(0);
+ QVERIFY(widget.isNull());
+ QVERIFY(view.viewport() != 0);
+ QVERIFY(view.viewport() != widget);
+
+ view.show();
+ QTest::qWait(25);
+}
+
+void tst_QGraphicsView::dragMode_scrollHand()
+{
+ for (int j = 0; j < 2; ++j) {
+ QGraphicsView view;
+ QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.setFixedSize(100, 100);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ view.setInteractive(j ? false : true);
+
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-100, -100, 5, 5));
+ scene.addRect(QRectF(95, -100, 5, 5));
+ scene.addRect(QRectF(95, 95, 5, 5));
+ QGraphicsItem *item = scene.addRect(QRectF(-100, 95, 5, 5));
+ item->setFlag(QGraphicsItem::ItemIsSelectable);
+ item->setSelected(true);
+ QVERIFY(item->isSelected());
+ QVERIFY(!view.scene());
+
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+
+ for (int i = 0; i < 2; ++i) {
+ // ScrollHandDrag
+#ifndef QT_NO_CURSOR
+ Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
+#endif
+ int horizontalScrollBarValue = view.horizontalScrollBar()->value();
+ int verticalScrollBarValue = view.verticalScrollBar()->value();
+ {
+ // Press
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QApplication::processEvents();
+
+ QTRY_VERIFY(item->isSelected());
+
+ for (int k = 0; k < 4; ++k) {
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::ClosedHandCursor);
+#endif
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(10, 0),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QVERIFY(item->isSelected());
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QVERIFY(item->isSelected());
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
+ }
+
+ {
+ // Release
+ QMouseEvent event(QEvent::MouseButtonRelease,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QApplication::processEvents();
+
+ QTRY_VERIFY(item->isSelected());
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
+#endif
+
+ // Check that items are not unselected because of a scroll hand drag.
+ QVERIFY(item->isSelected());
+
+ // Check that a click will still unselect the item.
+ {
+ // Press
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+ {
+ // Release
+ QMouseEvent event(QEvent::MouseButtonRelease,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ if (view.isInteractive()) {
+ if (view.scene()) {
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ } else {
+ QVERIFY(item->isSelected());
+ }
+ } else {
+ QVERIFY(item->isSelected());
+ }
+
+ view.setScene(&scene);
+ }
+ }
+}
+
+void tst_QGraphicsView::dragMode_rubberBand()
+{
+ QGraphicsView view;
+ QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.show();
+
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-100, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF(75, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF(75, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF(-100, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ view.setDragMode(QGraphicsView::RubberBandDrag);
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ for (int i = 0; i < 2; ++i) {
+ // RubberBandDrag
+#ifndef QT_NO_CURSOR
+ Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
+#endif
+ int horizontalScrollBarValue = view.horizontalScrollBar()->value();
+ int verticalScrollBarValue = view.verticalScrollBar()->value();
+ {
+ // Press
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
+#endif
+
+ QApplication::processEvents();
+
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(100, 0),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+
+ // We don't use QRubberBand as of 4.3; the band is drawn internally.
+ QVERIFY(!qFindChild<QRubberBand *>(&view));
+
+ QTest::qWait(25);
+
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(100, 100),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+
+ QTest::qWait(25);
+
+ {
+ // Release
+ QMouseEvent event(QEvent::MouseButtonRelease,
+ view.viewport()->rect().center() + QPoint(100, 100),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
+#endif
+
+ QTest::qWait(25);
+
+ if (view.scene())
+ QCOMPARE(scene.selectedItems().size(), 1);
+
+ view.setScene(&scene);
+ view.centerOn(0, 0);
+ }
+}
+
+void tst_QGraphicsView::rubberBandSelectionMode()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(QRectF(10, 10, 80, 80));
+ rect->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QGraphicsView view(&scene, &toplevel);
+ QCOMPARE(view.rubberBandSelectionMode(), Qt::IntersectsItemShape);
+ view.setDragMode(QGraphicsView::RubberBandDrag);
+ view.resize(120, 120);
+ toplevel.show();
+
+ // Disable mouse tracking to prevent the window system from sending mouse
+ // move events to the viewport while we are synthesizing events. If
+ // QGraphicsView gets a mouse move event with no buttons down, it'll
+ // terminate the rubber band.
+ view.viewport()->setMouseTracking(false);
+
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
+ sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
+ sendMouseRelease(view.viewport(), QPoint(), Qt::LeftButton);
+
+ view.setRubberBandSelectionMode(Qt::ContainsItemShape);
+ QCOMPARE(view.rubberBandSelectionMode(), Qt::ContainsItemShape);
+ sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
+ sendMouseMove(view.viewport(), view.viewport()->rect().bottomRight(),
+ Qt::LeftButton, Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
+}
+
+void tst_QGraphicsView::backgroundBrush()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ scene.setBackgroundBrush(Qt::blue);
+ QCOMPARE(scene.backgroundBrush(), QBrush(Qt::blue));
+
+ view.show();
+ QTest::qWait(25);
+
+ scene.setBackgroundBrush(QBrush());
+ QCOMPARE(scene.backgroundBrush(), QBrush());
+ QTest::qWait(25);
+
+ QRadialGradient gradient(0, 0, 10);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient);
+
+ QCOMPARE(scene.backgroundBrush(), QBrush(gradient));
+ QTest::qWait(25);
+}
+
+void tst_QGraphicsView::foregroundBrush()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ scene.setForegroundBrush(Qt::blue);
+ QCOMPARE(scene.foregroundBrush(), QBrush(Qt::blue));
+
+ view.show();
+ QTest::qWait(25);
+
+ scene.setForegroundBrush(QBrush());
+ QCOMPARE(scene.foregroundBrush(), QBrush());
+ QTest::qWait(25);
+
+ QRadialGradient gradient(0, 0, 10);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setForegroundBrush(gradient);
+
+ QCOMPARE(scene.foregroundBrush(), QBrush(gradient));
+ QTest::qWait(25);
+
+ for (int i = 0; i < 50; ++i) {
+ QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
+ gradient.setColorAt(0, Qt::transparent);
+ gradient.setColorAt(0.5, Qt::black);
+ gradient.setColorAt(1, Qt::transparent);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setForegroundBrush(gradient);
+
+ QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
+ gradient2.setColorAt(0, Qt::transparent);
+ gradient2.setColorAt(0.5, Qt::black);
+ gradient2.setColorAt(1, Qt::transparent);
+ gradient2.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient2);
+
+ QRadialGradient gradient3(view.rect().center() + QPoint(int(sin(i / 1.85) * 10), int(cos(i / 1.85) * 10)), 10);
+ gradient3.setColorAt(0, Qt::transparent);
+ gradient3.setColorAt(0.5, Qt::black);
+ gradient3.setColorAt(1, Qt::transparent);
+ gradient3.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient3);
+
+ QApplication::processEvents();
+ }
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ for (int i = -500; i < 500; i += 10) {
+ view.centerOn(i, 0);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ for (int i = -500; i < 500; i += 10) {
+ view.centerOn(0, i);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+}
+
+void tst_QGraphicsView::matrix()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ // Show rendering of background with no scene
+ for (int i = 0; i < 50; ++i) {
+ view.rotate(5);
+ QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
+ gradient.setColorAt(0, Qt::transparent);
+ gradient.setColorAt(0.5, Qt::black);
+ gradient.setColorAt(1, Qt::transparent);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setForegroundBrush(gradient);
+ QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
+ gradient2.setColorAt(0, Qt::transparent);
+ gradient2.setColorAt(0.5, Qt::black);
+ gradient2.setColorAt(1, Qt::transparent);
+ gradient2.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient2);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ }
+
+ // Test transformation extremes, see if they cause crashes
+ {
+ QGraphicsScene scene;
+ scene.addText("GraphicsView rotated clockwise");
+
+ QGraphicsView view(&scene);
+ view.show();
+ for (int i = 0; i < 160; ++i) {
+ view.rotate(18);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ /*
+ // These cause a crash
+ for (int i = 0; i < 40; ++i) {
+ view.shear(1.2, 1.2);
+ QTest::qWait(20);
+ }
+ for (int i = 0; i < 40; ++i) {
+ view.shear(-1.2, -1.2);
+ QTest::qWait(20);
+ }
+ */
+ for (int i = 0; i < 20; ++i) {
+ view.scale(1.2, 1.2);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ for (int i = 0; i < 20; ++i) {
+ view.scale(0.6, 0.6);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ }
+}
+
+void tst_QGraphicsView::matrix_convenience()
+{
+ QGraphicsView view;
+ QCOMPARE(view.matrix(), QMatrix());
+
+ // Check the convenience functions
+ view.rotate(90);
+ QCOMPARE(view.matrix(), QMatrix().rotate(90));
+ view.scale(2, 2);
+ QCOMPARE(view.matrix(), QMatrix().scale(2, 2) * QMatrix().rotate(90));
+ view.shear(1.2, 1.2);
+ QCOMPARE(view.matrix(), QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
+ view.translate(1, 1);
+ QCOMPARE(view.matrix(), QMatrix().translate(1, 1) * QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
+}
+
+void tst_QGraphicsView::matrix_combine()
+{
+ // Check matrix combining
+ QGraphicsView view;
+ QCOMPARE(view.matrix(), QMatrix());
+ view.setMatrix(QMatrix().rotate(90), true);
+ view.setMatrix(QMatrix().rotate(90), true);
+ view.setMatrix(QMatrix().rotate(90), true);
+ view.setMatrix(QMatrix().rotate(90), true);
+ QCOMPARE(view.matrix(), QMatrix());
+
+ view.resetMatrix();
+ QCOMPARE(view.matrix(), QMatrix());
+ view.setMatrix(QMatrix().rotate(90), false);
+ view.setMatrix(QMatrix().rotate(90), false);
+ view.setMatrix(QMatrix().rotate(90), false);
+ view.setMatrix(QMatrix().rotate(90), false);
+ QCOMPARE(view.matrix(), QMatrix().rotate(90));
+}
+
+void tst_QGraphicsView::centerOnPoint()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ scene.addEllipse(QRectF(-100, -100, 50, 50));
+ scene.addEllipse(QRectF(50, -100, 50, 50));
+ scene.addEllipse(QRectF(-100, 50, 50, 50));
+ scene.addEllipse(QRectF(50, 50, 50, 50));
+
+ QGraphicsView view(&scene, &toplevel);
+ view.setSceneRect(-400, -400, 800, 800);
+ view.setFixedSize(100, 100);
+ toplevel.show();
+
+ int tolerance = 5;
+
+ for (int i = 0; i < 3; ++i) {
+ for (int y = -100; y < 100; y += 23) {
+ for (int x = -100; x < 100; x += 23) {
+ view.centerOn(x, y);
+ QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
+
+ // Fuzzy compare
+ if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
+ || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
+ QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
+ .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
+ QFAIL(qPrintable(error));
+ }
+
+ QApplication::processEvents();
+ }
+ }
+
+ view.rotate(13);
+ view.scale(1.5, 1.5);
+ view.shear(1.25, 1.25);
+ }
+}
+
+void tst_QGraphicsView::centerOnItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *items[4];
+ items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[0]->setPos(-100, -100);
+ items[1]->setPos(100, -100);
+ items[2]->setPos(-100, 100);
+ items[3]->setPos(100, 100);
+
+ QGraphicsView view(&scene);
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ int tolerance = 7;
+
+ for (int x = 0; x < 3; ++x) {
+ for (int i = 0; i < 4; ++i) {
+ QApplication::processEvents();
+ view.centerOn(items[i]);
+
+ QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
+ qreal x = items[i]->pos().x();
+ qreal y = items[i]->pos().y();
+
+ // Fuzzy compare
+ if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
+ || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
+ QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
+ .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
+ QFAIL(qPrintable(error));
+ }
+
+ QApplication::processEvents();
+ }
+
+ view.rotate(13);
+ view.scale(1.5, 1.5);
+ view.shear(1.25, 1.25);
+ }
+}
+
+void tst_QGraphicsView::ensureVisibleRect()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ QGraphicsItem *items[4];
+ items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::green));
+ items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::red));
+ items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
+ items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
+ scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
+ scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
+ items[0]->setPos(-100, -100);
+ items[1]->setPos(100, -100);
+ items[2]->setPos(-100, 100);
+ items[3]->setPos(100, 100);
+
+ QGraphicsItem *icon = scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::gray));
+
+ QGraphicsView view(&scene, &toplevel);
+ view.setSceneRect(-500, -500, 1000, 1000);
+ view.setFixedSize(250, 250);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+
+ for (int y = -100; y < 100; y += 25) {
+ for (int x = -100; x < 100; x += 13) {
+
+ icon->setPos(x, y);
+
+ switch (x & 3) {
+ case 0:
+ view.centerOn(-500, -500);
+ break;
+ case 1:
+ view.centerOn(500, -500);
+ break;
+ case 2:
+ view.centerOn(-500, 500);
+ break;
+ case 3:
+ default:
+ view.centerOn(500, 500);
+ break;
+ }
+
+ QVERIFY(!view.viewport()->rect().contains(view.mapFromScene(x, y)));
+
+ for (int margin = 10; margin < 60; margin += 15) {
+ view.ensureVisible(x, y, 0, 0, margin, margin);
+
+ QRect viewRect = view.viewport()->rect();
+ QPoint viewPoint = view.mapFromScene(x, y);
+
+ QVERIFY(viewRect.contains(viewPoint));
+ QVERIFY(qAbs(viewPoint.x() - viewRect.left()) >= margin -1);
+ QVERIFY(qAbs(viewPoint.x() - viewRect.right()) >= margin -1);
+ QVERIFY(qAbs(viewPoint.y() - viewRect.top()) >= margin -1);
+ QVERIFY(qAbs(viewPoint.y() - viewRect.bottom()) >= margin -1);
+
+ QApplication::processEvents();
+ }
+ }
+ view.rotate(5);
+ view.scale(1.05, 1.05);
+ view.translate(30, -30);
+ }
+}
+
+void tst_QGraphicsView::fitInView()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *items[4];
+ items[0] = scene.addEllipse(QRectF(-25, -25, 100, 20), QPen(Qt::black), QBrush(Qt::green));
+ items[1] = scene.addEllipse(QRectF(-25, -25, 20, 100), QPen(Qt::black), QBrush(Qt::red));
+ items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
+ items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
+ scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
+ scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
+ items[0]->setPos(-100, -100);
+ items[1]->setPos(100, -100);
+ items[2]->setPos(-100, 100);
+ items[3]->setPos(100, 100);
+
+ items[0]->rotate(30);
+ items[1]->rotate(-30);
+
+#if defined(Q_OS_WINCE)
+ //Is the standard scrollbar size
+ int scrollbarSize = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent) - 13;
+#endif
+
+ QGraphicsView view(&scene);
+ view.setSceneRect(-400, -400, 800, 800);
+
+#if defined(Q_OS_WINCE)
+ //We need to take in account the scrollbar size for the WindowsMobilStyle
+ view.setFixedSize(400 + scrollbarSize, 200 + scrollbarSize);
+#else
+ view.setFixedSize(400, 200);
+#endif
+
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+
+ view.show();
+ view.fitInView(scene.itemsBoundingRect(), Qt::IgnoreAspectRatio);
+ qApp->processEvents();
+
+ // Sampled coordinates.
+ QVERIFY(!view.itemAt(45, 41));
+ QVERIFY(!view.itemAt(297, 44));
+ QVERIFY(!view.itemAt(359, 143));
+ QCOMPARE(view.itemAt(79, 22), items[0]);
+ QCOMPARE(view.itemAt(329, 41), items[1]);
+ QCOMPARE(view.itemAt(38, 158), items[2]);
+ QCOMPARE(view.itemAt(332, 160), items[3]);
+
+ view.fitInView(items[0], Qt::IgnoreAspectRatio);
+ qApp->processEvents();
+
+ QCOMPARE(view.itemAt(19, 13), items[0]);
+ QCOMPARE(view.itemAt(91, 47), items[0]);
+ QCOMPARE(view.itemAt(202, 94), items[0]);
+ QCOMPARE(view.itemAt(344, 161), items[0]);
+ QVERIFY(!view.itemAt(236, 54));
+ QVERIFY(!view.itemAt(144, 11));
+ QVERIFY(!view.itemAt(29, 69));
+ QVERIFY(!view.itemAt(251, 167));
+
+ view.fitInView(items[0], Qt::KeepAspectRatio);
+ qApp->processEvents();
+
+ QCOMPARE(view.itemAt(325, 170), items[0]);
+ QCOMPARE(view.itemAt(206, 74), items[0]);
+ QCOMPARE(view.itemAt(190, 115), items[0]);
+ QCOMPARE(view.itemAt(55, 14), items[0]);
+ QVERIFY(!view.itemAt(109, 4));
+ QVERIFY(!view.itemAt(244, 68));
+ QVERIFY(!view.itemAt(310, 125));
+ QVERIFY(!view.itemAt(261, 168));
+
+ view.fitInView(items[0], Qt::KeepAspectRatioByExpanding);
+ qApp->processEvents();
+
+ QCOMPARE(view.itemAt(18, 10), items[0]);
+ QCOMPARE(view.itemAt(95, 4), items[0]);
+ QCOMPARE(view.itemAt(279, 175), items[0]);
+ QCOMPARE(view.itemAt(359, 170), items[0]);
+ QVERIFY(!view.itemAt(370, 166));
+ QVERIFY(!view.itemAt(136, 7));
+ QVERIFY(!view.itemAt(31, 44));
+ QVERIFY(!view.itemAt(203, 153));
+}
+
+void tst_QGraphicsView::itemsAtPoint()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
+
+ QGraphicsView view;
+ QVERIFY(view.items(0, 0).isEmpty());
+
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QList<QGraphicsItem *> items = view.items(view.viewport()->rect().center());
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+}
+
+void tst_QGraphicsView::itemsInRect()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
+
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
+
+ QGraphicsView view;
+ QVERIFY(view.items(QRect(-100, -100, 200, 200)).isEmpty());
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QPoint centerPoint = view.viewport()->rect().center();
+ QRect leftRect = view.mapFromScene(-30, -10, 20, 20).boundingRect();
+ QRect rightRect = view.mapFromScene(30, -10, 20, 20).boundingRect();
+
+ QList<QGraphicsItem *> items = view.items(leftRect);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+
+ items = view.items(rightRect);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(7));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(6));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(5));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(4));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+}
+
+class CountPaintItem : public QGraphicsRectItem
+{
+public:
+ int numPaints;
+
+ CountPaintItem(const QRectF &rect)
+ : QGraphicsRectItem(rect), numPaints(0)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ ++numPaints;
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+};
+
+void tst_QGraphicsView::itemsInRect_cosmeticAdjust_data()
+{
+ QTest::addColumn<QRect>("updateRect");
+ QTest::addColumn<int>("numPaints");
+ QTest::addColumn<bool>("adjustForAntialiasing");
+
+ // Aliased.
+ QTest::newRow("nil") << QRect() << 1 << false;
+ QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << false;
+ QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << false;
+ QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << false;
+ QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << false;
+ QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 0 << false;
+ QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 0 << false;
+ QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 0 << false;
+ QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 0 << false;
+
+ // Anti-aliased.
+ QTest::newRow("nil") << QRect() << 1 << true;
+ QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << true;
+ QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << true;
+ QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << true;
+ QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << true;
+ QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 1 << true;
+ QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 1 << true;
+ QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 1 << true;
+ QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 1 << true;
+ QTest::newRow("0, 0, 300, 98") << QRect(0, 0, 300, 98) << 0 << false;
+ QTest::newRow("0, 0, 98, 300") << QRect(0, 0, 98, 300) << 0 << false;
+ QTest::newRow("202, 0, 98, 300") << QRect(202, 0, 98, 300) << 0 << false;
+ QTest::newRow("0, 202, 300, 98") << QRect(0, 202, 300, 98) << 0 << false;
+}
+
+void tst_QGraphicsView::itemsInRect_cosmeticAdjust()
+{
+ QFETCH(QRect, updateRect);
+ QFETCH(int, numPaints);
+ QFETCH(bool, adjustForAntialiasing);
+
+ QGraphicsScene scene(-100, -100, 200, 200);
+ CountPaintItem *rect = new CountPaintItem(QRectF(-50, -50, 100, 100));
+ scene.addItem(rect);
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !adjustForAntialiasing);
+ view.setRenderHint(QPainter::Antialiasing, adjustForAntialiasing);
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.setFrameStyle(0);
+ view.resize(300, 300);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(rect->numPaints > 0);
+
+ rect->numPaints = 0;
+ if (updateRect.isNull())
+ view.viewport()->update();
+ else
+ view.viewport()->update(updateRect);
+ qApp->processEvents();
+ QTRY_COMPARE(rect->numPaints, numPaints);
+}
+
+void tst_QGraphicsView::itemsInPoly()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
+
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
+
+ QGraphicsView view;
+ QVERIFY(view.items(QPolygon()).isEmpty());
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QPoint centerPoint = view.viewport()->rect().center();
+ QPolygon leftPoly = view.mapFromScene(QRectF(-30, -10, 20, 20));
+ QPolygon rightPoly = view.mapFromScene(QRectF(30, -10, 20, 20));
+
+ QList<QGraphicsItem *> items = view.items(leftPoly);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+
+ items = view.items(rightPoly);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(7));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(6));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(5));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(4));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+}
+
+void tst_QGraphicsView::itemsInPath()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
+
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
+
+ QGraphicsView view;
+ QVERIFY(view.items(QPainterPath()).isEmpty());
+ view.setScene(&scene);
+ view.translate(100, 400);
+ view.rotate(22.3);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QPoint centerPoint = view.viewport()->rect().center();
+ QPainterPath leftPath;
+ leftPath.addEllipse(QRect(view.mapFromScene(-30, -10), QSize(20, 20)));
+
+ QPainterPath rightPath;
+ rightPath.addEllipse(QRect(view.mapFromScene(30, -10), QSize(20, 20)));
+
+ QList<QGraphicsItem *> items = view.items(leftPath);
+
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+
+ items = view.items(rightPath);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(7));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(6));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(5));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(4));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+}
+
+void tst_QGraphicsView::itemAt()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
+
+ QGraphicsView view;
+ QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
+
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
+ QGraphicsItem* item = view.itemAt(view.viewport()->rect().center());
+ QVERIFY(item);
+ QCOMPARE(item->zValue(), qreal(3));
+}
+
+void tst_QGraphicsView::itemAt2()
+{
+ // test precision of the itemAt() function with items that are smaller
+ // than 1 pixel.
+ QGraphicsScene scene(0, 0, 100, 100);
+
+ // Add a 0.5x0.5 item at position 0 on the scene, top-left corner at -0.25, -0.25.
+ QGraphicsItem *item = scene.addRect(QRectF(-0.25, -0.25, 0.5, 0.5), QPen(Qt::black, 0.1));
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.setRenderHint(QPainter::Antialiasing);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QPoint itemViewPoint = view.mapFromScene(item->scenePos());
+
+ for (int i = 0; i < 3; ++i) {
+ QVERIFY(view.itemAt(itemViewPoint));
+ QVERIFY(!view.items(itemViewPoint).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, 0)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, -1)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
+ item->moveBy(0.1, 0);
+ }
+
+ // Here
+ QVERIFY(view.itemAt(itemViewPoint));
+ QVERIFY(!view.items(itemViewPoint).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
+
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+ // Not here
+ QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, 0)));
+ QVERIFY(view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
+ QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, -1)));
+ QVERIFY(view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
+}
+
+void tst_QGraphicsView::mapToScene()
+{
+ // Uncomment the commented-out code to see what's going on. It doesn't
+ // affect the test; it just slows it down.
+
+ QGraphicsScene scene;
+ scene.addPixmap(QPixmap("3D-Qt-1-2.png"));
+
+ QWidget topLevel;
+ QGraphicsView view(&topLevel);
+ view.setScene(&scene);
+ view.setSceneRect(-500, -500, 1000, 1000);
+#if defined(Q_OS_WINCE)
+ QSize viewSize(200,200);
+#else
+ QSize viewSize(300,300);
+#endif
+
+ view.setFixedSize(viewSize);
+ topLevel.show();
+ QApplication::processEvents();
+ QVERIFY(view.isVisible());
+ QCOMPARE(view.size(), viewSize);
+
+ // First once without setting the scene rect
+#ifdef QT_ARCH_ARM
+ const int step = 20;
+#else
+ const int step = 1;
+#endif
+
+ for (int x = 0; x < view.width(); x += step) {
+ for (int y = 0; y < view.height(); y += step) {
+ QCOMPARE(view.mapToScene(QPoint(x, y)),
+ QPointF(view.horizontalScrollBar()->value() + x,
+ view.verticalScrollBar()->value() + y));
+ }
+ }
+
+ for (int sceneRectHeight = 250; sceneRectHeight < 1000; sceneRectHeight += 250) {
+ for (int sceneRectWidth = 250; sceneRectWidth < 1000; sceneRectWidth += 250) {
+ view.setSceneRect(QRectF(-int(sceneRectWidth / 2), -int(sceneRectHeight / 2),
+ sceneRectWidth, sceneRectHeight));
+ QApplication::processEvents();
+
+ int hmin = view.horizontalScrollBar()->minimum();
+ int hmax = view.horizontalScrollBar()->maximum();
+ int hstep = (hmax - hmin) / 3;
+ int vmin = view.verticalScrollBar()->minimum();
+ int vmax = view.verticalScrollBar()->maximum();
+ int vstep = (vmax - vmin) / 3;
+
+ for (int hscrollValue = hmin; hscrollValue < hmax; hscrollValue += hstep) {
+ for (int vscrollValue = vmin; vscrollValue < vmax; vscrollValue += vstep) {
+
+ view.horizontalScrollBar()->setValue(hscrollValue);
+ view.verticalScrollBar()->setValue(vscrollValue);
+ QApplication::processEvents();
+
+ int h = view.horizontalScrollBar()->value();
+ int v = view.verticalScrollBar()->value();
+
+ for (int x = 0; x < view.width(); x += step) {
+ for (int y = 0; y < view.height(); y += step) {
+ QCOMPARE(view.mapToScene(QPoint(x, y)), QPointF(h + x, v + y));
+ QCOMPARE(view.mapFromScene(QPointF(h + x, v + y)), QPoint(x, y));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void tst_QGraphicsView::mapToScenePoint()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.setFixedSize(117, 117);
+ view.show();
+ QPoint center = view.viewport()->rect().center();
+ QCOMPARE(view.mapToScene(center + QPoint(10, 0)),
+ view.mapToScene(center) + QPointF(0, -10));
+}
+
+void tst_QGraphicsView::mapToSceneRect_data()
+{
+ QTest::addColumn<QRect>("viewRect");
+ QTest::addColumn<QPolygonF>("scenePoly");
+ QTest::addColumn<qreal>("rotation");
+
+ QTest::newRow("nil") << QRect() << QPolygonF() << qreal(0);
+ QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1) << QPolygonF(QRectF(0, 0, 1, 1)) << qreal(0);
+ QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10) << QPolygonF(QRectF(0, 0, 10, 10)) << qreal(0);
+ QTest::newRow("nil") << QRect() << QPolygonF() << qreal(90);
+ QPolygonF p;
+ p << QPointF(0, 0) << QPointF(0, -1) << QPointF(1, -1) << QPointF(1, 0) << QPointF(0, 0);
+ QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1)
+ << p
+ << qreal(90);
+ p.clear();
+ p << QPointF(0, 0) << QPointF(0, -10) << QPointF(10, -10) << QPointF(10, 0) << QPointF(0, 0);
+ QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10)
+ << p
+ << qreal(90);
+}
+
+void tst_QGraphicsView::mapToSceneRect()
+{
+ QFETCH(QRect, viewRect);
+ QFETCH(QPolygonF, scenePoly);
+ QFETCH(qreal, rotation);
+
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(25, -25, 50, 50);
+ QGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ view.setFixedSize(200, 200);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.show();
+
+ view.rotate(rotation);
+
+ QPolygonF poly = view.mapToScene(viewRect);
+ if (!poly.isEmpty())
+ poly << poly[0];
+
+ QCOMPARE(poly, scenePoly);
+}
+
+void tst_QGraphicsView::mapToScenePoly()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.translate(100, 100);
+ view.setFixedSize(117, 117);
+ view.show();
+ QPoint center = view.viewport()->rect().center();
+ QRect rect(center + QPoint(10, 0), QSize(10, 10));
+
+ QPolygon poly;
+ poly << rect.topLeft();
+ poly << rect.topRight();
+ poly << rect.bottomRight();
+ poly << rect.bottomLeft();
+
+ QPolygonF poly2;
+ poly2 << view.mapToScene(rect.topLeft());
+ poly2 << view.mapToScene(rect.topRight());
+ poly2 << view.mapToScene(rect.bottomRight());
+ poly2 << view.mapToScene(rect.bottomLeft());
+
+ QCOMPARE(view.mapToScene(poly), poly2);
+}
+
+void tst_QGraphicsView::mapToScenePath()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.setSceneRect(-300, -300, 600, 600);
+ view.translate(10, 10);
+ view.setFixedSize(300, 300);
+ view.show();
+ QPoint center = view.viewport()->rect().center();
+ QRect rect(QPoint(10, 0), QSize(10, 10));
+
+ QPainterPath path;
+ path.addRect(rect);
+
+ QPainterPath path2;
+ path2.addRect(rect.translated(view.horizontalScrollBar()->value() - 10,
+ view.verticalScrollBar()->value() - 10));
+ QCOMPARE(view.mapToScene(path), path2);
+}
+
+void tst_QGraphicsView::mapFromScenePoint()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.scale(10, 10);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.show();
+
+ QPoint mapped = view.mapFromScene(0, 0);
+ QPoint center = view.viewport()->rect().center();
+ if (qAbs(mapped.x() - center.x()) >= 2
+ || qAbs(mapped.y() - center.y()) >= 2) {
+ QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
+ .arg(mapped.x()).arg(mapped.y()).arg(center.x()).arg(center.y());
+ QFAIL(qPrintable(error));
+ }
+ }
+ {
+ QWidget toplevel;
+
+ QGraphicsScene scene(0, 0, 200, 200);
+ scene.addRect(QRectF(0, 0, 200, 200), QPen(Qt::black, 1));
+ QGraphicsView view(&scene, &toplevel);
+ view.ensurePolished();
+ view.resize(view.sizeHint());
+ toplevel.show();
+
+ QCOMPARE(view.mapFromScene(0, 0), QPoint(0, 0));
+ QCOMPARE(view.mapFromScene(0.4, 0.4), QPoint(0, 0));
+ QCOMPARE(view.mapFromScene(0.5, 0.5), QPoint(1, 1));
+ QCOMPARE(view.mapFromScene(0.9, 0.9), QPoint(1, 1));
+ QCOMPARE(view.mapFromScene(1.0, 1.0), QPoint(1, 1));
+ QCOMPARE(view.mapFromScene(100, 100), QPoint(100, 100));
+ QCOMPARE(view.mapFromScene(100.5, 100.5), QPoint(101, 101));
+ QCOMPARE(view.mapToScene(0, 0), QPointF(0, 0));
+ QCOMPARE(view.mapToScene(1, 1), QPointF(1, 1));
+ QCOMPARE(view.mapToScene(100, 100), QPointF(100, 100));
+ }
+}
+
+void tst_QGraphicsView::mapFromSceneRect()
+{
+ QGraphicsScene scene;
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ view.rotate(90);
+ view.setFixedSize(200, 200);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ topLevel.show();
+ QTest::qWait(25);
+
+ QPolygon polygon;
+ polygon << QPoint(98, 98);
+ polygon << QPoint(98, 108);
+ polygon << QPoint(88, 108);
+ polygon << QPoint(88, 98);
+
+
+ QPolygon viewPolygon = view.mapFromScene(0, 0, 10, 10);
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY(qAbs(viewPolygon[i].x() - polygon[i].x()) < 3);
+ QVERIFY(qAbs(viewPolygon[i].y() - polygon[i].y()) < 3);
+ }
+
+ QPoint pt = view.mapFromScene(QPointF());
+ QPolygon p;
+ p << pt << pt << pt << pt;
+ QCOMPARE(view.mapFromScene(QRectF()), p);
+}
+
+void tst_QGraphicsView::mapFromScenePoly()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.setFixedSize(200, 200);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.show();
+
+ QPolygonF polygon;
+ polygon << QPoint(0, 0);
+ polygon << QPoint(10, 0);
+ polygon << QPoint(10, 10);
+ polygon << QPoint(0, 10);
+
+ QPolygon polygon2;
+ polygon2 << QPoint(98, 98);
+ polygon2 << QPoint(98, 108);
+ polygon2 << QPoint(88, 108);
+ polygon2 << QPoint(88, 98);
+
+ QPolygon viewPolygon = view.mapFromScene(polygon);
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY(qAbs(viewPolygon[i].x() - polygon2[i].x()) < 3);
+ QVERIFY(qAbs(viewPolygon[i].y() - polygon2[i].y()) < 3);
+ }
+}
+
+void tst_QGraphicsView::mapFromScenePath()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.setFixedSize(200, 200);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.show();
+
+ QPolygonF polygon;
+ polygon << QPoint(0, 0);
+ polygon << QPoint(10, 0);
+ polygon << QPoint(10, 10);
+ polygon << QPoint(0, 10);
+ QPainterPath path;
+ path.addPolygon(polygon);
+
+ QPolygon polygon2;
+ polygon2 << QPoint(98, 98);
+ polygon2 << QPoint(98, 108);
+ polygon2 << QPoint(88, 108);
+ polygon2 << QPoint(88, 98);
+ QPainterPath path2;
+ path2.addPolygon(polygon2);
+
+ QPolygonF pathPoly = view.mapFromScene(path).toFillPolygon();
+ QPolygonF path2Poly = path2.toFillPolygon();
+
+ for (int i = 0; i < pathPoly.size(); ++i) {
+ QVERIFY(qAbs(pathPoly[i].x() - path2Poly[i].x()) < 3);
+ QVERIFY(qAbs(pathPoly[i].y() - path2Poly[i].y()) < 3);
+ }
+}
+
+void tst_QGraphicsView::sendEvent()
+{
+ QGraphicsScene scene;
+
+ TestItem *item = new TestItem;
+ scene.addItem(item);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTest::qWait(20);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ item->setFocus();
+
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->events.size(), 2);
+ QCOMPARE(item->events.last(), QEvent::FocusIn);
+
+ QPoint itemPoint = view.mapFromScene(item->scenePos());
+ sendMousePress(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), 4);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
+
+ QMouseEvent mouseMoveEvent(QEvent::MouseMove, itemPoint, view.viewport()->mapToGlobal(itemPoint),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &mouseMoveEvent);
+ QCOMPARE(item->events.size(), 5);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneMouseMove);
+
+ QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, itemPoint,
+ view.viewport()->mapToGlobal(itemPoint),
+ Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &mouseReleaseEvent);
+ QCOMPARE(item->events.size(), 7);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
+
+ QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Space, 0);
+ QApplication::sendEvent(view.viewport(), &keyPress);
+ QCOMPARE(item->events.size(), 9);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::ShortcutOverride);
+ QCOMPARE(item->events.last(), QEvent::KeyPress);
+}
+
+class MouseWheelScene : public QGraphicsScene
+{
+public:
+ Qt::Orientation orientation;
+
+ void wheelEvent(QGraphicsSceneWheelEvent *event)
+ {
+ orientation = event->orientation();
+ QGraphicsScene::wheelEvent(event);
+ }
+};
+
+void tst_QGraphicsView::wheelEvent()
+{
+ // Create a scene with an invalid orientation.
+ MouseWheelScene scene;
+ scene.orientation = Qt::Orientation(-1);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ widget->setGeometry(0, 0, 400, 400);
+ widget->setFocusPolicy(Qt::WheelFocus);
+
+ EventSpy spy(widget, QEvent::GraphicsSceneWheel);
+ QCOMPARE(spy.count(), 0);
+
+ scene.addItem(widget);
+
+ // Assign a view.
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTest::qWait(20);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+
+ // Send a wheel event with horizontal orientation.
+ {
+ QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
+ view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
+ 120, 0, 0, Qt::Horizontal);
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(scene.orientation, Qt::Horizontal);
+ }
+
+ // Send a wheel event with vertical orientation.
+ {
+ QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
+ view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
+ 120, 0, 0, Qt::Vertical);
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(scene.orientation, Qt::Vertical);
+ }
+
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(widget->hasFocus());
+}
+
+// Qt/CE does not have regular cursor support.
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+void tst_QGraphicsView::cursor()
+{
+ if (PlatformQuirks::haveMouseCursor())
+ QSKIP("The Platform does not have regular cursor support", SkipAll);
+
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setCursor(Qt::IBeamCursor);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(400, 400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+
+ sendMouseMove(view.viewport(), QPoint(5, 5));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+}
+#endif
+
+// Qt/CE does not have regular cursor support.
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+void tst_QGraphicsView::cursor2()
+{
+ if (PlatformQuirks::haveMouseCursor())
+ QSKIP("The Platform does not have regular cursor support", SkipAll);
+
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setCursor(Qt::IBeamCursor);
+ item->setZValue(1);
+
+ QGraphicsItem *item2 = scene.addRect(QRectF(-20, -20, 40, 40));
+ item2->setZValue(0);
+
+ QGraphicsView view(&scene);
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ view.setFixedSize(400, 400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+
+ view.setDragMode(QGraphicsView::NoDrag);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ item2->setCursor(Qt::SizeAllCursor);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+}
+#endif
+
+void tst_QGraphicsView::transformationAnchor()
+{
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
+
+ QGraphicsView view(&scene);
+
+ for (int i = 0; i < 2; ++i) {
+ view.resize(100, 100);
+ view.show();
+
+ if (i == 0) {
+ QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
+ } else {
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ }
+ view.centerOn(0, 0);
+ view.horizontalScrollBar()->setValue(100);
+ QApplication::processEvents();
+
+ QPointF center = view.mapToScene(view.viewport()->rect().center());
+
+ view.scale(10, 10);
+
+ QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
+
+ if (i == 0) {
+ qreal slack = 3;
+ QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
+ QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
+ } else {
+ qreal slack = qreal(0.3);
+ QVERIFY(qAbs(newCenter.x() - center.x() / 10) < slack);
+ QVERIFY(qAbs(newCenter.y() - center.y() / 10) < slack);
+ }
+ }
+}
+
+void tst_QGraphicsView::resizeAnchor()
+{
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
+
+ QGraphicsView view(&scene);
+
+ for (int i = 0; i < 2; ++i) {
+ view.resize(100, 100);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ if (i == 0) {
+ QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
+ } else {
+ view.setResizeAnchor(QGraphicsView::AnchorViewCenter);
+ }
+ view.centerOn(0, 0);
+ QTest::qWait(25);
+
+ QPointF f = view.mapToScene(50, 50);
+ QPointF center = view.mapToScene(view.viewport()->rect().center());
+
+ QApplication::processEvents();
+
+ for (int size = 200; size <= 400; size += 25) {
+ view.resize(size, size);
+ if (i == 0) {
+ QTRY_COMPARE(view.mapToScene(50, 50), f);
+ QTRY_VERIFY(view.mapToScene(view.viewport()->rect().center()) != center);
+ } else {
+ QTRY_VERIFY(view.mapToScene(50, 50) != f);
+
+ QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
+ int slack = 3;
+ QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
+ QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
+ }
+ QApplication::processEvents();
+ }
+ }
+}
+
+class CustomView : public QGraphicsView
+{
+ Q_OBJECT
+public:
+ CustomView(QGraphicsScene *s = 0) : QGraphicsView(s) {}
+ CustomView(QGraphicsScene *s, QWidget *parent)
+ : QGraphicsView(s, parent) {}
+ QList<QRegion> lastUpdateRegions;
+ bool painted;
+
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ lastUpdateRegions << event->region();
+ painted = true;
+ QGraphicsView::paintEvent(event);
+ }
+};
+
+void tst_QGraphicsView::viewportUpdateMode()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ scene.setBackgroundBrush(Qt::red);
+
+ CustomView view;
+ QDesktopWidget desktop;
+ view.setFixedSize(QSize(500, 500).boundedTo(desktop.availableGeometry().size())); // 500 is too big for all common smartphones
+ view.setScene(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::MinimalViewportUpdate);
+
+ // Show the view, and initialize our test.
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
+ view.lastUpdateRegions.clear();
+
+ // Issue two scene updates.
+ scene.update(QRectF(0, 0, 10, 10));
+ scene.update(QRectF(20, 0, 10, 10));
+ QTest::qWait(50);
+
+ // The view gets two updates for the update scene updates.
+ QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QCOMPARE(view.lastUpdateRegions.last().rects().size(), 2);
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(14, 14));
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(1).size(), QSize(14, 14));
+#endif
+
+ // Set full update mode.
+ view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::FullViewportUpdate);
+ view.lastUpdateRegions.clear();
+
+ // Issue two scene updates.
+ scene.update(QRectF(0, 0, 10, 10));
+ scene.update(QRectF(20, 0, 10, 10));
+ qApp->processEvents();
+ qApp->processEvents();
+
+ // The view gets one full viewport update for the update scene updates.
+ QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), view.viewport()->size());
+ view.lastUpdateRegions.clear();
+
+ // Set smart update mode
+ view.setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::SmartViewportUpdate);
+
+ // Issue 100 mini-updates
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < 10; ++j) {
+ scene.update(QRectF(i * 3, j * 3, 1, 1));
+ }
+ }
+ qApp->processEvents();
+ qApp->processEvents();
+
+ // The view gets one bounding rect update.
+ QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(32, 32));
+
+ // Set no update mode
+ view.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::NoViewportUpdate);
+
+ // Issue two scene updates.
+ view.lastUpdateRegions.clear();
+ TestItem item;
+ scene.addItem(&item);
+ item.moveBy(10, 10);
+ scene.update(QRectF(0, 0, 10, 10));
+ scene.update(QRectF(20, 0, 10, 10));
+ qApp->processEvents();
+ qApp->processEvents();
+
+ // The view should not get any painting calls from the scene updates
+ QCOMPARE(view.lastUpdateRegions.size(), 0);
+}
+
+void tst_QGraphicsView::viewportUpdateMode2()
+{
+ QWidget toplevel;
+
+ // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
+ QGraphicsScene dummyScene;
+ CustomView view(0, &toplevel);
+ view.painted = false;
+ view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view.setScene(&dummyScene);
+ view.ensurePolished(); // make sure we get the right content margins
+ int left, top, right, bottom;
+ view.getContentsMargins(&left, &top, &right, &bottom);
+ view.resize(200 + left + right, 200 + top + bottom);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+ QTest::qWait(50);
+ QTRY_VERIFY(view.painted);
+ const QRect viewportRect = view.viewport()->rect();
+ QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
+
+#if defined QT_BUILD_INTERNAL
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+
+ QRect boundingRect;
+ const QRect rect1(0, 0, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect1));
+ QVERIFY(!viewPrivate->fullUpdatePending);
+ boundingRect |= rect1;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ const QRect rect2(50, 50, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect2));
+ QVERIFY(!viewPrivate->fullUpdatePending);
+ boundingRect |= rect2;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ const QRect rect3(190, 190, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect3));
+ QVERIFY(viewPrivate->fullUpdatePending);
+ boundingRect |= rect3;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ view.lastUpdateRegions.clear();
+ viewPrivate->processPendingUpdates();
+ QTest::qWait(50);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ // Note that we adjust by 2 for antialiasing.
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(boundingRect.adjusted(-2, -2, 2, 2) & viewportRect));
+#endif
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void tst_QGraphicsView::acceptDrops()
+{
+ QGraphicsView view;
+
+ // Excepted default behavior.
+ QVERIFY(view.acceptDrops());
+ QVERIFY(view.viewport()->acceptDrops());
+
+ // Excepted behavior with no drops.
+ view.setAcceptDrops(false);
+ QVERIFY(!view.acceptDrops());
+ QVERIFY(!view.viewport()->acceptDrops());
+
+ // Setting a widget with drops on a QGraphicsView without drops.
+ QWidget *widget = new QWidget;
+ widget->setAcceptDrops(true);
+ view.setViewport(widget);
+ QVERIFY(!view.acceptDrops());
+ QVERIFY(!view.viewport()->acceptDrops());
+
+ // Switching the view to accept drops.
+ view.setAcceptDrops(true);
+ QVERIFY(view.acceptDrops());
+ QVERIFY(view.viewport()->acceptDrops());
+
+ // Setting a widget with no drops on a QGraphicsView with drops.
+ widget = new QWidget;
+ widget->setAcceptDrops(false);
+ view.setViewport(widget);
+ QVERIFY(view.viewport()->acceptDrops());
+ QVERIFY(view.acceptDrops());
+
+ // Switching the view to not accept drops.
+ view.setAcceptDrops(false);
+ QVERIFY(!view.viewport()->acceptDrops());
+}
+#endif
+
+void tst_QGraphicsView::optimizationFlags()
+{
+ QGraphicsView view;
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlag(QGraphicsView::DontClipPainter);
+ QVERIFY(view.optimizationFlags() & QGraphicsView::DontClipPainter);
+ view.setOptimizationFlag(QGraphicsView::DontClipPainter, false);
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
+ QVERIFY(view.optimizationFlags() & QGraphicsView::DontSavePainterState);
+ view.setOptimizationFlag(QGraphicsView::DontSavePainterState, false);
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
+ QVERIFY(view.optimizationFlags() & QGraphicsView::DontAdjustForAntialiasing);
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, false);
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
+ | QGraphicsView::DontClipPainter);
+ QCOMPARE(view.optimizationFlags(), QGraphicsView::OptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
+ | QGraphicsView::DontClipPainter));
+}
+
+class MessUpPainterItem : public QGraphicsRectItem
+{
+public:
+ MessUpPainterItem(const QRectF &rect) : QGraphicsRectItem(rect), dirtyPainter(false)
+ { }
+
+ bool dirtyPainter;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ dirtyPainter = (painter->pen().width() != 0);
+ painter->setPen(QPen(Qt::black, 1.0));
+ }
+};
+
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ MyGraphicsView(QGraphicsScene * scene) : QGraphicsView(scene)
+ { }
+
+ void drawBackground(QPainter * painter, const QRectF & rect) {
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ painter->drawRect(rect);
+ }
+
+ void drawItems (QPainter * painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[]) {
+ if (!(optimizationFlags() & QGraphicsView::DontSavePainterState))
+ QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_SourceOver);
+ else
+ QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_Source);
+ QGraphicsView::drawItems(painter,numItems,items,options);
+ }
+};
+
+void tst_QGraphicsView::optimizationFlags_dontSavePainterState()
+{
+ MessUpPainterItem *parent = new MessUpPainterItem(QRectF(0, 0, 100, 100));
+ MessUpPainterItem *child = new MessUpPainterItem(QRectF(0, 0, 100, 100));
+ child->setParentItem(parent);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.viewport()->repaint();
+
+ QVERIFY(!parent->dirtyPainter);
+ QVERIFY(!child->dirtyPainter);
+
+ view.setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ view.viewport()->repaint();
+
+#ifdef Q_WS_MAC
+ // Repaint on Mac OS X actually does require spinning the event loop.
+ QTest::qWait(100);
+#endif
+ QVERIFY(!parent->dirtyPainter);
+ QVERIFY(child->dirtyPainter);
+
+ MyGraphicsView painter(&scene);
+ painter.show();
+ QTest::qWaitForWindowShown(&painter);
+
+ MyGraphicsView painter2(&scene);
+ painter2.setOptimizationFlag(QGraphicsView::DontSavePainterState,true);
+ painter2.show();
+ QTest::qWaitForWindowShown(&painter2);
+}
+
+void tst_QGraphicsView::optimizationFlags_dontSavePainterState2_data()
+{
+ QTest::addColumn<bool>("savePainter");
+ QTest::addColumn<bool>("indirectPainting");
+ QTest::newRow("With painter state protection, without indirect painting") << true << false;
+ QTest::newRow("Without painter state protection, without indirect painting") << false << false;
+ QTest::newRow("With painter state protectionm, with indirect painting") << true << true;
+ QTest::newRow("Without painter state protection, with indirect painting") << false << true;
+}
+
+void tst_QGraphicsView::optimizationFlags_dontSavePainterState2()
+{
+ QFETCH(bool, savePainter);
+ QFETCH(bool, indirectPainting);
+
+ class MyScene : public QGraphicsScene
+ {
+ public:
+ void drawBackground(QPainter *p, const QRectF &)
+ { transformInDrawBackground = p->worldTransform(); opacityInDrawBackground = p->opacity(); }
+
+ void drawForeground(QPainter *p, const QRectF &)
+ { transformInDrawForeground = p->worldTransform(); opacityInDrawForeground = p->opacity(); }
+
+ QTransform transformInDrawBackground;
+ QTransform transformInDrawForeground;
+ qreal opacityInDrawBackground;
+ qreal opacityInDrawForeground;
+ };
+
+ MyScene scene;
+ // Add transformed dummy items to make sure the painter's worldTransform() is changed in drawItems.
+ scene.addRect(0, 0, 20, 20)->setTransform(QTransform::fromScale(2, 2));
+ scene.addRect(50, 50, 20, 20)->setTransform(QTransform::fromTranslate(200, 200));
+
+ foreach (QGraphicsItem *item, scene.items())
+ item->setOpacity(0.6);
+
+ CustomView view(&scene);
+ if (!savePainter)
+ view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting, indirectPainting);
+ view.rotate(45);
+ view.scale(1.5, 1.5);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ // Make sure the view is repainted; otherwise the tests below will fail.
+ view.viewport()->repaint();
+ QTest::qWait(200);
+ QVERIFY(view.painted);
+
+ // Make sure the painter's world transform is preserved after drawItems.
+ QTransform expectedTransform = view.viewportTransform();
+ QVERIFY(!expectedTransform.isIdentity());
+ QCOMPARE(scene.transformInDrawForeground, expectedTransform);
+ QCOMPARE(scene.transformInDrawBackground, expectedTransform);
+
+ qreal expectedOpacity = 1.0;
+ QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
+ QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
+
+ // Trigger more painting, this time from QGraphicsScene::render.
+ QImage image(scene.sceneRect().size().toSize(), QImage::Format_RGB32);
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+
+ expectedTransform = QTransform();
+ QCOMPARE(scene.transformInDrawForeground, expectedTransform);
+ QCOMPARE(scene.transformInDrawBackground, expectedTransform);
+ QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
+ QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
+
+ // Trigger more painting with another opacity on the painter.
+ painter.begin(&image);
+ painter.setOpacity(0.4);
+ expectedOpacity = 0.4;
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(scene.transformInDrawForeground, expectedTransform);
+ QCOMPARE(scene.transformInDrawBackground, expectedTransform);
+ QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
+ QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
+}
+
+class LodItem : public QGraphicsRectItem
+{
+public:
+ LodItem(const QRectF &rect) : QGraphicsRectItem(rect), lastLod(-42)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *viewport)
+ {
+ lastLod = option->levelOfDetailFromTransform(painter->worldTransform());
+ QGraphicsRectItem::paint(painter, option, viewport);
+ }
+
+ qreal lastLod;
+};
+
+void tst_QGraphicsView::levelOfDetail_data()
+{
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<qreal>("lod");
+
+ QTest::newRow("1:4, 1:4") << QTransform().scale(0.25, 0.25) << qreal(0.25);
+ QTest::newRow("1:2, 1:4") << QTransform().scale(0.5, 0.25) << qreal(::sqrt(0.125));
+ QTest::newRow("4:1, 1:2") << QTransform().scale(0.25, 0.5) << qreal(::sqrt(0.125));
+
+ QTest::newRow("1:2, 1:2") << QTransform().scale(0.5, 0.5) << qreal(0.5);
+ QTest::newRow("1:1, 1:2") << QTransform().scale(1, 0.5) << qreal(::sqrt(0.5));
+ QTest::newRow("2:1, 1:1") << QTransform().scale(0.5, 1) << qreal(::sqrt(0.5));
+
+ QTest::newRow("1:1, 1:1") << QTransform().scale(1, 1) << qreal(1.0);
+ QTest::newRow("2:1, 1:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
+ QTest::newRow("1:1, 2:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
+ QTest::newRow("2:1, 2:1") << QTransform().scale(2, 2) << qreal(2.0);
+ QTest::newRow("2:1, 4:1") << QTransform().scale(2, 4) << qreal(::sqrt(8.0));
+ QTest::newRow("4:1, 2:1") << QTransform().scale(4, 2) << qreal(::sqrt(8.0));
+ QTest::newRow("4:1, 4:1") << QTransform().scale(4, 4) << qreal(4.0);
+}
+
+void tst_QGraphicsView::levelOfDetail()
+{
+ QFETCH(QTransform, transform);
+ QFETCH(qreal, lod);
+
+ LodItem *item = new LodItem(QRectF(0, 0, 100, 100));
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_COMPARE(item->lastLod, qreal(1));
+
+ view.setTransform(transform);
+
+ QTRY_COMPARE(item->lastLod, lod);
+}
+
+// Moved to tst_qgraphicsview_2.cpp
+extern void _scrollBarRanges_data();
+
+void tst_QGraphicsView::scrollBarRanges_data()
+{
+ _scrollBarRanges_data();
+}
+
+void tst_QGraphicsView::scrollBarRanges()
+{
+ QFETCH(QSize, viewportSize);
+ QFETCH(QRectF, sceneRect);
+ QFETCH(QTransform, transform);
+ QFETCH(Qt::ScrollBarPolicy, hbarpolicy);
+ QFETCH(Qt::ScrollBarPolicy, vbarpolicy);
+ QFETCH(int, hmin);
+ QFETCH(int, hmax);
+ QFETCH(int, vmin);
+ QFETCH(int, vmax);
+ QFETCH(bool, useMotif);
+ QFETCH(bool, useStyledPanel);
+
+ QGraphicsScene scene(sceneRect);
+ scene.addRect(sceneRect, QPen(Qt::blue), QBrush(QColor(Qt::green)));
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing);
+ view.setTransform(transform);
+ view.setFrameStyle(useStyledPanel ? QFrame::StyledPanel : QFrame::NoFrame);
+
+ if (useMotif) {
+#if !defined(QT_NO_STYLE_MOTIF)
+ view.setStyle(new QMotifStyle);
+#else
+ QSKIP("No Motif style compiled.", SkipSingle);
+#endif
+ } else {
+#if defined(Q_OS_WINCE)
+ view.setStyle(new QWindowsStyle);
+#elif !defined(QT_NO_STYLE_PLASTIQUE)
+ view.setStyle(new QPlastiqueStyle);
+#endif
+ }
+ view.setStyleSheet(" "); // enables style propagation ;-)
+
+ int adjust = 0;
+ if (useStyledPanel)
+ adjust = view.style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
+ view.resize(viewportSize + QSize(adjust, adjust));
+
+ view.setHorizontalScrollBarPolicy(hbarpolicy);
+ view.setVerticalScrollBarPolicy(vbarpolicy);
+
+ view.show();
+
+ QCOMPARE(view.horizontalScrollBar()->minimum(), hmin);
+ QCOMPARE(view.verticalScrollBar()->minimum(), vmin);
+ QCOMPARE(view.horizontalScrollBar()->maximum(), hmax);
+ QCOMPARE(view.verticalScrollBar()->maximum(), vmax);
+}
+
+class TestView : public QGraphicsView
+{
+public:
+ TestView(QGraphicsScene *scene)
+ : QGraphicsView(scene), accepted(false)
+ { }
+
+ bool accepted;
+
+protected:
+ void mousePressEvent(QMouseEvent *event)
+ {
+ QGraphicsView::mousePressEvent(event);
+ accepted = event->isAccepted();
+ }
+};
+
+void tst_QGraphicsView::acceptMousePressEvent()
+{
+ QGraphicsScene scene;
+
+ TestView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().center()),
+ Qt::LeftButton, 0, 0);
+ event.setAccepted(false);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!view.accepted);
+
+ scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
+
+ qApp->processEvents(); // ensure scene rect is updated
+
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(view.accepted);
+}
+
+void tst_QGraphicsView::replayMouseMove()
+{
+ // An empty scene in a view. The view will send the events to the scene in
+ // any case. Note that the view doesn't have to be shown - the mouse event
+ // sending functions below send the events directly to the viewport.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ EventSpy sceneSpy(&scene, QEvent::GraphicsSceneMouseMove);
+ EventSpy viewSpy(view.viewport(), QEvent::MouseMove);
+
+ sendMousePress(view.viewport(), view.viewport()->rect().center());
+
+ // One mouse event should be translated into one scene event.
+ for (int i = 0; i < 3; ++i) {
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton));
+ QCOMPARE(viewSpy.count(), i + 1);
+ QCOMPARE(sceneSpy.count(), i + 1);
+ }
+
+ // When the view is transformed, the view should get no more events. But
+ // the scene should get replays.
+ for (int i = 0; i < 3; ++i) {
+ view.rotate(10);
+ QCOMPARE(viewSpy.count(), 3);
+ QCOMPARE(sceneSpy.count(), 3 + i + 1);
+ }
+
+ // When the view is scrolled, the view should get no more events. But the
+ // scene should get replays.
+ for (int i = 0; i < 3; ++i) {
+ view.horizontalScrollBar()->setValue((i + 1) * 10);
+ QCOMPARE(viewSpy.count(), 3);
+ QCOMPARE(sceneSpy.count(), 6 + i + 1);
+ }
+}
+
+void tst_QGraphicsView::itemsUnderMouse()
+{
+ QGraphicsScene scene;
+ QGraphicsProxyWidget w;
+ w.setWidget(new QPushButton("W"));
+ w.resize(50,50);
+ QGraphicsProxyWidget w2(&w);
+ w2.setWidget(new QPushButton("W2"));
+ w2.resize(50,50);
+ QGraphicsProxyWidget w3(&w2);
+ w3.setWidget(new QPushButton("W3"));
+ w3.resize(50,50);
+ w.setZValue(150);
+ w2.setZValue(50);
+ w3.setZValue(0);
+ scene.addItem(&w);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
+ static_cast<QGraphicsItem *>(&w3));
+ w2.setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
+ QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
+ static_cast<QGraphicsItem *>(&w3));
+}
+
+class QGraphicsTextItem_task172231 : public QGraphicsTextItem
+{
+public:
+ QGraphicsTextItem_task172231(const QString & text, QGraphicsItem * parent = 0)
+ : QGraphicsTextItem(text, parent) {}
+ QRectF exposedRect;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ exposedRect = option->exposedRect;
+ QGraphicsTextItem::paint(painter, option, widget);
+ }
+};
+
+void tst_QGraphicsView::task172231_untransformableItems()
+{
+ // check fix in QGraphicsView::paintEvent()
+
+ QGraphicsScene scene;
+
+ QGraphicsTextItem_task172231 *text =
+ new QGraphicsTextItem_task172231("abcdefghijklmnopqrstuvwxyz");
+ text->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ scene.addItem(text);
+
+ QGraphicsView view(&scene);
+
+ view.scale(2, 1);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ QRectF origExposedRect = text->exposedRect;
+
+ view.resize(int(0.75 * view.width()), view.height());
+ qApp->processEvents();
+
+ QCOMPARE(text->exposedRect, origExposedRect);
+
+ // notice that the fix also goes into QGraphicsView::render()
+ // and QGraphicsScene::render(), but in duplicated code that
+ // is pending a refactoring, so for now we omit autotesting
+ // these functions separately
+}
+
+class MousePressReleaseScene : public QGraphicsScene
+{
+public:
+ MousePressReleaseScene()
+ : presses(0), releases(0)
+ { }
+ int presses;
+ int releases;
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ { ++presses; QGraphicsScene::mousePressEvent(event); }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+ { ++releases; QGraphicsScene::mouseReleaseEvent(event); }
+};
+
+void tst_QGraphicsView::task180429_mouseReleaseDragMode()
+{
+ MousePressReleaseScene scene;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ sendMousePress(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 1);
+ QCOMPARE(scene.releases, 0);
+ sendMouseRelease(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 1);
+ QCOMPARE(scene.releases, 1);
+
+ view.setDragMode(QGraphicsView::RubberBandDrag);
+ sendMousePress(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 2);
+ QCOMPARE(scene.releases, 1);
+ sendMouseRelease(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 2);
+ QCOMPARE(scene.releases, 2);
+}
+
+void tst_QGraphicsView::task187791_setSceneCausesUpdate()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ EventSpy updateSpy(view.viewport(), QEvent::Paint);
+ QCOMPARE(updateSpy.count(), 0);
+
+ view.setScene(0);
+ QApplication::processEvents();
+ QTRY_COMPARE(updateSpy.count(), 1);
+ view.setScene(&scene);
+ QApplication::processEvents();
+ QTRY_COMPARE(updateSpy.count(), 2);
+}
+
+class MouseMoveCounter : public QGraphicsView
+{
+public:
+ MouseMoveCounter() : mouseMoves(0)
+ { }
+ int mouseMoves;
+protected:
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ ++mouseMoves;
+ QGraphicsView::mouseMoveEvent(event);
+ foreach (QGraphicsItem *item, scene()->items()) {
+ scene()->removeItem(item);
+ delete item;
+ }
+ scene()->addRect(0, 0, 50, 50);
+ scene()->addRect(0, 0, 100, 100);
+ }
+};
+
+void tst_QGraphicsView::task186827_deleteReplayedItem()
+{
+ // make sure the mouse is not over the window, causing spontaneous mouse moves
+ QCursor::setPos(1, 1);
+
+ QGraphicsScene scene;
+ scene.addRect(0, 0, 50, 50);
+ scene.addRect(0, 0, 100, 100);
+
+ MouseMoveCounter view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.viewport()->setMouseTracking(true);
+
+ QCOMPARE(view.mouseMoves, 0);
+ {
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+ QCOMPARE(view.mouseMoves, 1);
+ QTest::qWait(25);
+ QTRY_COMPARE(view.mouseMoves, 1);
+ QTest::qWait(25);
+ {
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+ QCOMPARE(view.mouseMoves, 2);
+ QTest::qWait(15);
+}
+
+void tst_QGraphicsView::task207546_focusCrash()
+{
+ class _Widget : public QWidget
+ {
+ public:
+ bool focusNextPrevChild(bool next) { return QWidget::focusNextPrevChild(next); }
+ } widget;
+
+ widget.setLayout(new QVBoxLayout());
+ QGraphicsView *gr1 = new QGraphicsView(&widget);
+ QGraphicsView *gr2 = new QGraphicsView(&widget);
+ widget.layout()->addWidget(gr1);
+ widget.layout()->addWidget(gr2);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ widget.activateWindow();
+ QApplication::setActiveWindow(&widget);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&widget));
+ widget.focusNextPrevChild(true);
+ QCOMPARE(static_cast<QWidget *>(gr2), widget.focusWidget());
+}
+
+void tst_QGraphicsView::task210599_unsetDragWhileDragging()
+{
+ QGraphicsScene scene(0, 0, 400, 400);
+ QGraphicsView view(&scene);
+ view.setGeometry(0, 0, 200, 200);
+ view.show();
+
+ QPoint origPos = QPoint(100, 100);
+ QPoint step1Pos = QPoint(100, 110);
+ QPoint step2Pos = QPoint(100, 120);
+
+ // Enable and do a drag
+ {
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+ QMouseEvent press(QEvent::MouseButtonPress, origPos, Qt::LeftButton, 0, 0);
+ QMouseEvent move(QEvent::MouseMove, step1Pos, Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &press);
+ QApplication::sendEvent(view.viewport(), &move);
+ }
+
+ // unset drag and release mouse, inverse order
+ {
+ view.setDragMode(QGraphicsView::NoDrag);
+ QMouseEvent release(QEvent::MouseButtonRelease, step1Pos, Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &release);
+ }
+
+ QPoint basePos = view.mapFromScene(0, 0);
+
+ // reset drag, and move mouse without holding button down.
+ {
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+ QMouseEvent move(QEvent::MouseMove, step2Pos, Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &move);
+ }
+
+ // Check that no draggin has occurred...
+ QCOMPARE(basePos, view.mapFromScene(0, 0));
+}
+
+void tst_QGraphicsView::task236394_sendShortcutOverrideEvent()
+{
+ QGraphicsView view;
+ view.show();
+ QKeyEvent event(QEvent::ShortcutOverride, Qt::Key_A, 0, QString("A"));
+ QApplication::sendEvent(&view, &event);
+}
+
+class ChangedListener : public QObject
+{
+ Q_OBJECT
+public:
+ QList<QList<QRectF> > changes;
+
+public slots:
+ void changed(const QList<QRectF> &dirty)
+ {
+ changes << dirty;
+ }
+};
+
+void tst_QGraphicsView::task239729_noViewUpdate_data()
+{
+ QTest::addColumn<bool>("a");
+
+ QTest::newRow("a") << false;
+ QTest::newRow("b") << true;
+}
+
+void tst_QGraphicsView::task239729_noViewUpdate()
+{
+ QFETCH(bool, a);
+ // The scene's changed signal is connected to something that isn't a view.
+ QGraphicsScene scene;
+ ChangedListener cl;
+ QGraphicsView *view = 0;
+
+ if (a) {
+ view = new QGraphicsView(&scene);
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+ } else {
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+ view = new QGraphicsView(&scene);
+ }
+
+ EventSpy spy(view->viewport(), QEvent::Paint);
+ QCOMPARE(spy.count(), 0);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+
+ QTRY_VERIFY(spy.count() >= 1);
+ spy.reset();
+ scene.update();
+ QApplication::processEvents();
+ QTRY_COMPARE(spy.count(), 1);
+
+ delete view;
+}
+
+void tst_QGraphicsView::task239047_fitInViewSmallViewport()
+{
+ // Ensure that with a small viewport, fitInView doesn't mirror the
+ // scene.
+ QWidget widget;
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene, &widget);
+ view->resize(3, 3);
+ QCOMPARE(view->size(), QSize(3, 3));
+ widget.show();
+ view->fitInView(0, 0, 100, 100);
+ QPointF topLeft = view->mapToScene(0, 0);
+ QPointF bottomRight = view->mapToScene(100, 100);
+ QVERIFY(bottomRight.x() > topLeft.x());
+ QVERIFY(bottomRight.y() > topLeft.y());
+
+ view->fitInView(0, 0, 0, 100);
+
+ // Don't crash
+ view->scale(0, 0);
+ view->fitInView(0, 0, 100, 100);
+}
+
+void tst_QGraphicsView::task245469_itemsAtPointWithClip()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *child = new QGraphicsRectItem(40, 40, 20, 20, parent);
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsView view(&scene);
+ view.resize(150,150);
+ view.rotate(90);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QList<QGraphicsItem *> itemsAtCenter = view.items(view.viewport()->rect().center());
+ QCOMPARE(itemsAtCenter, (QList<QGraphicsItem *>() << child << parent));
+
+ QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1)));
+ QList<QGraphicsItem *> itemsAtCenter2 = scene.items(p);
+ QCOMPARE(itemsAtCenter2, itemsAtCenter);
+}
+
+static QGraphicsView *createSimpleViewAndScene()
+{
+ QGraphicsView *view = new QGraphicsView;
+ QGraphicsScene *scene = new QGraphicsScene;
+ view->setScene(scene);
+
+ view->setBackgroundBrush(Qt::blue);
+
+ QGraphicsRectItem *rect = scene->addRect(0, 0, 10, 10);
+ rect->setBrush(Qt::red);
+ rect->setPen(Qt::NoPen);
+ return view;
+}
+
+class SpyItem : public QGraphicsRectItem
+{
+public:
+ SpyItem()
+ : QGraphicsRectItem(QRectF(0, 0, 100, 100))
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ transform = painter->transform();
+ }
+
+ QTransform transform;
+};
+
+void tst_QGraphicsView::embeddedViews()
+{
+ QGraphicsView *v1 = createSimpleViewAndScene();
+ QGraphicsView *v2 = createSimpleViewAndScene();
+
+ QGraphicsProxyWidget *proxy = v1->scene()->addWidget(v2);
+
+ SpyItem *item = new SpyItem;
+ v2->scene()->addItem(item);
+
+ proxy->translate(5, 5);
+
+ QImage actual(64, 64, QImage::Format_ARGB32_Premultiplied);
+ actual.fill(0);
+ v1->QWidget::render(&actual);
+ QTransform a = item->transform;
+
+ v2->QWidget::render(&actual);
+ QTransform b = item->transform;
+
+ QVERIFY(a == b);
+ delete v1;
+}
+
+void tst_QGraphicsView::scrollAfterResize_data()
+{
+ QTest::addColumn<bool>("reverse");
+ QTest::addColumn<QTransform>("x1");
+ QTest::addColumn<QTransform>("x2");
+ QTest::addColumn<QTransform>("x3");
+
+#if !defined(QT_NO_STYLE_PLASTIQUE)
+ QPlastiqueStyle style;
+#elif !defined(QT_NO_STYLE_WINDOWS)
+ QWindowsStyle style;
+#else
+ QCommonStyle style;
+#endif
+
+ int frameWidth = style.pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int extent = style.pixelMetric(QStyle::PM_ScrollBarExtent);
+ int inside = style.styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
+ int viewportWidth = 300;
+ int scrollBarIndent = viewportWidth - extent - (inside ? 4 : 2)*frameWidth;
+
+ QTest::newRow("normal") << false
+ << QTransform()
+ << QTransform()
+ << QTransform().translate(-10, 0);
+ QTest::newRow("reverse") << true
+ << QTransform().translate(scrollBarIndent, 0)
+ << QTransform().translate(scrollBarIndent + 100, 0)
+ << QTransform().translate(scrollBarIndent + 110, 0);
+}
+
+void tst_QGraphicsView::scrollAfterResize()
+{
+ QFETCH(bool, reverse);
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QFETCH(QTransform, x3);
+
+#if !defined(QT_NO_STYLE_PLASTIQUE)
+ QPlastiqueStyle style;
+#elif !defined(QT_NO_STYLE_WINDOWS)
+ QWindowsStyle style;
+#else
+ QCommonStyle style;
+#endif
+ QWidget toplevel;
+
+ QGraphicsView view(&toplevel);
+ view.setStyle(&style);
+ if (reverse)
+ view.setLayoutDirection(Qt::RightToLeft);
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.resize(300, 300);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+ view.horizontalScrollBar()->setValue(0);
+ view.verticalScrollBar()->setValue(0);
+ QCOMPARE(view.viewportTransform(), x1);
+ view.resize(400, 300);
+ QCOMPARE(view.viewportTransform(), x2);
+ view.horizontalScrollBar()->setValue(10);
+ QCOMPARE(view.viewportTransform(), x3);
+}
+
+void tst_QGraphicsView::moveItemWhileScrolling_data()
+{
+ QTest::addColumn<bool>("adjustForAntialiasing");
+ QTest::addColumn<bool>("changedConnected");
+
+ QTest::newRow("no adjust") << false << false;
+ QTest::newRow("adjust") << true << false;
+ QTest::newRow("no adjust changedConnected") << false << true;
+ QTest::newRow("adjust changedConnected") << true << true;
+}
+
+void tst_QGraphicsView::moveItemWhileScrolling()
+{
+ QFETCH(bool, adjustForAntialiasing);
+ QFETCH(bool, changedConnected);
+
+ class MoveItemScrollView : public QGraphicsView
+ {
+ public:
+ MoveItemScrollView()
+ {
+ setWindowFlags(Qt::X11BypassWindowManagerHint);
+ setScene(new QGraphicsScene(0, 0, 1000, 1000));
+ rect = scene()->addRect(0, 0, 10, 10);
+ rect->setPos(50, 50);
+ painted = false;
+ }
+ QRegion lastPaintedRegion;
+ QGraphicsItem *rect;
+ bool painted;
+ void waitForPaintEvent()
+ {
+ QTimer::singleShot(2000, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+ }
+ protected:
+ QEventLoop eventLoop;
+ void paintEvent(QPaintEvent *event)
+ {
+ painted = true;
+ lastPaintedRegion = event->region();
+ QGraphicsView::paintEvent(event);
+ if (eventLoop.isRunning())
+ eventLoop.quit();
+ }
+ };
+
+ MoveItemScrollView view;
+ view.setFrameStyle(0);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ if (!adjustForAntialiasing)
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
+ view.resize(200, 200);
+ view.painted = false;
+ view.show();
+ if (changedConnected)
+ QObject::connect(view.scene(), SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+ QTRY_VERIFY(view.painted);
+ view.painted = false;
+ view.lastPaintedRegion = QRegion();
+ view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10);
+ view.rect->moveBy(0, 10);
+ view.waitForPaintEvent();
+ QTRY_VERIFY(view.painted);
+
+ QRegion expectedRegion;
+ expectedRegion += QRect(0, 0, 200, 200);
+ expectedRegion -= QRect(0, 0, 190, 200);
+ int a = adjustForAntialiasing ? 2 : 1;
+ expectedRegion += QRect(40, 50, 10, 10).adjusted(-a, -a, a, a);
+ expectedRegion += QRect(40, 60, 10, 10).adjusted(-a, -a, a, a);
+#ifdef Q_OS_MAC
+ QEXPECT_FAIL("", "This will fail with Cocoa because paint events are not send in the order expected by graphicsview", Continue);
+#endif
+ COMPARE_REGIONS(view.lastPaintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsView::centerOnDirtyItem()
+{
+ QWidget toplevel;
+
+ QGraphicsView view(&toplevel);
+ toplevel.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
+ view.resize(200, 200);
+
+ QGraphicsScene *scene = new QGraphicsScene;
+ view.setScene(scene);
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 10, 10);
+ item->setBrush(Qt::red);
+ scene->addItem(item);
+ view.centerOn(item);
+
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+ QTest::qWait(50);
+
+ QImage before(view.viewport()->size(), QImage::Format_ARGB32);
+ view.viewport()->render(&before);
+
+ item->setPos(20, 0);
+ view.centerOn(item);
+
+ QTest::qWait(50);
+
+ QImage after(view.viewport()->size(), QImage::Format_ARGB32);
+ view.viewport()->render(&after);
+
+ QCOMPARE(before, after);
+}
+
+void tst_QGraphicsView::mouseTracking()
+{
+ // Mouse tracking should only be automatically enabled if items either accept hover events
+ // or have a cursor set. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure mouse tracking is disabled by default.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setupViewport/setScene.
+ QGraphicsView view;
+ QWidget *viewport = new QWidget;
+ viewport->setMouseTracking(true);
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items that accept hover events.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // QGraphicsWidget implicitly accepts hover if it has window decoration.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ scene.addItem(widget);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ // Enable window decoraton.
+ widget->setWindowFlags(Qt::Window | Qt::WindowTitleHint);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items with a cursor set.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+#ifndef QT_NO_CURSOR
+ item->setCursor(Qt::CrossCursor);
+#endif
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+#ifndef QT_NO_CURSOR
+ item->setCursor(Qt::CrossCursor);
+#endif
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we propagate mouse tracking to all views.
+ {
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view1(&scene);
+ QGraphicsView view2(&scene);
+ QGraphicsView view3(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+#ifndef QT_NO_CURSOR
+ item->setCursor(Qt::CrossCursor);
+#endif
+ scene.addItem(item);
+
+ QVERIFY(view1.viewport()->hasMouseTracking());
+ QVERIFY(view2.viewport()->hasMouseTracking());
+ QVERIFY(view3.viewport()->hasMouseTracking());
+ }
+}
+
+void tst_QGraphicsView::mouseTracking2()
+{
+ // Make sure mouse move events propagates to the scene when
+ // mouse tracking is explicitly enabled on the view,
+ // even when all items ignore hover events / use default cursor.
+
+ QGraphicsScene scene;
+ scene.addRect(0, 0, 100, 100);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ view.viewport()->setMouseTracking(true); // Explicitly enable mouse tracking.
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ EventSpy spy(&scene, QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(spy.count(), 0);
+ QMouseEvent event(QEvent::MouseMove,view.viewport()->rect().center(), Qt::NoButton,
+ Qt::MouseButtons(Qt::NoButton), 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QGraphicsView::mouseTracking3()
+{
+ // Mouse tracking should be automatically enabled if AnchorUnderMouse is used for
+ // view transform or resize. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure we enable mouse tracking when using AnchorUnderMouse for view transformation.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we enable mouse tracking when using AnchorUnderMouse for view resizing.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setViewport/setScene (transformation anchor).
+ QGraphicsView view;
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ QWidget *viewport = new QWidget;
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setViewport/setScene (resize anchor).
+ QGraphicsView view;
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ QWidget *viewport = new QWidget;
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we don't disable mouse tracking when adding an item (transformation anchor).
+ { // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+
+ QGraphicsView view;
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ view.setScene(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we don't disable mouse tracking when adding an item (resize anchor).
+ { // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+
+ QGraphicsView view;
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ view.setScene(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+}
+
+class RenderTester : public QGraphicsRectItem
+{
+public:
+ RenderTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), paints(0)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ ++paints;
+ }
+
+ int paints;
+};
+
+void tst_QGraphicsView::render()
+{
+ // ### This test can be much more thorough - see QGraphicsScene::render.
+ QGraphicsScene scene;
+ CustomView view(&scene);
+ view.setFrameStyle(0);
+ view.resize(200, 200);
+ view.painted = false;
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+ QTRY_VERIFY(view.painted > 0);
+
+ RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50));
+ RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50));
+ RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50));
+ RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50));
+ scene.addItem(r1);
+ scene.addItem(r2);
+ scene.addItem(r3);
+ scene.addItem(r4);
+
+ qApp->processEvents();
+
+ QTRY_COMPARE(r1->paints, 1);
+ QCOMPARE(r2->paints, 1);
+ QCOMPARE(r3->paints, 1);
+ QCOMPARE(r4->paints, 1);
+
+ QPixmap pix(200, 200);
+ pix.fill(Qt::transparent);
+ QPainter painter(&pix);
+ view.render(&painter);
+ painter.end();
+
+ QCOMPARE(r1->paints, 2);
+ QCOMPARE(r2->paints, 2);
+ QCOMPARE(r3->paints, 2);
+ QCOMPARE(r4->paints, 2);
+}
+
+void tst_QGraphicsView::exposeRegion()
+{
+ RenderTester *item = new RenderTester(QRectF(0, 0, 20, 20));
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ item->paints = 0;
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(item->paints > 0);
+
+ item->paints = 0;
+ view.lastUpdateRegions.clear();
+
+ // Update a small area in the viewport's topLeft() and bottomRight().
+ // (the boundingRect() of this area covers the entire viewport).
+ QWidget *viewport = view.viewport();
+ QRegion expectedExposeRegion = QRect(0, 0, 5, 5);
+ expectedExposeRegion += QRect(viewport->rect().bottomRight() - QPoint(5, 5), QSize(5, 5));
+ viewport->update(expectedExposeRegion);
+ QApplication::processEvents();
+
+ // Make sure it triggers correct repaint on the view.
+ QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
+ COMPARE_REGIONS(view.lastUpdateRegions.at(0), expectedExposeRegion);
+
+ // Make sure the item didn't get any repaints.
+#ifndef Q_OS_MAC
+ QCOMPARE(item->paints, 0);
+#endif
+}
+
+void tst_QGraphicsView::update_data()
+{
+ // In view.viewport() coordinates. (viewport rect: QRect(0, 0, 200, 200))
+ QTest::addColumn<QRect>("updateRect");
+ QTest::newRow("empty") << QRect();
+ QTest::newRow("outside left") << QRect(-200, 0, 100, 100);
+ QTest::newRow("outside right") << QRect(400, 0 ,100, 100);
+ QTest::newRow("outside top") << QRect(0, -200, 100, 100);
+ QTest::newRow("outside bottom") << QRect(0, 400, 100, 100);
+ QTest::newRow("partially inside left") << QRect(-50, 0, 100, 100);
+ QTest::newRow("partially inside right") << QRect(-150, 0, 100, 100);
+ QTest::newRow("partially inside top") << QRect(0, -150, 100, 100);
+ QTest::newRow("partially inside bottom") << QRect(0, 150, 100, 100);
+ QTest::newRow("on topLeft edge") << QRect(-100, -100, 100, 100);
+ QTest::newRow("on topRight edge") << QRect(200, -100, 100, 100);
+ QTest::newRow("on bottomRight edge") << QRect(200, 200, 100, 100);
+ QTest::newRow("on bottomLeft edge") << QRect(-200, 200, 100, 100);
+ QTest::newRow("inside topLeft") << QRect(-99, -99, 100, 100);
+ QTest::newRow("inside topRight") << QRect(199, -99, 100, 100);
+ QTest::newRow("inside bottomRight") << QRect(199, 199, 100, 100);
+ QTest::newRow("inside bottomLeft") << QRect(-199, 199, 100, 100);
+ QTest::newRow("large1") << QRect(50, -100, 100, 400);
+ QTest::newRow("large2") << QRect(-100, 50, 400, 100);
+ QTest::newRow("large3") << QRect(-100, -100, 400, 400);
+ QTest::newRow("viewport rect") << QRect(0, 0, 200, 200);
+}
+
+void tst_QGraphicsView::update()
+{
+ QFETCH(QRect, updateRect);
+
+ // some window manager resize the toplevel to max screen size
+ // so we must make our view a child (no layout!) of a dummy toplevel
+ // to ensure that it's really 200x200 pixels
+ QWidget toplevel;
+
+ // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
+ QGraphicsScene dummyScene;
+ CustomView view(0, &toplevel);
+ view.setScene(&dummyScene);
+ view.ensurePolished(); // must ensure polished to get content margins right
+ int left, top, right, bottom;
+ view.getContentsMargins(&left, &top, &right, &bottom);
+ view.resize(200 + left + right, 200 + top + bottom);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+
+
+ QApplication::setActiveWindow(&toplevel);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&toplevel));
+
+ const QRect viewportRect = view.viewport()->rect();
+ QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
+
+#if defined QT_BUILD_INTERNAL
+ const bool intersects = updateRect.intersects(viewportRect);
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+ QTRY_COMPARE(viewPrivate->updateRect(updateRect), intersects);
+ QApplication::processEvents();
+
+ view.lastUpdateRegions.clear();
+ viewPrivate->processPendingUpdates();
+ QVERIFY(viewPrivate->dirtyRegion.isEmpty());
+ QVERIFY(viewPrivate->dirtyBoundingRect.isEmpty());
+ QApplication::processEvents();
+ if (!intersects) {
+ QTRY_VERIFY(view.lastUpdateRegions.isEmpty());
+ } else {
+ QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
+ QTRY_COMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect) & viewportRect);
+ }
+ QTRY_VERIFY(!viewPrivate->fullUpdatePending);
+#endif
+}
+
+void tst_QGraphicsView::update2_data()
+{
+ QTest::addColumn<qreal>("penWidth");
+ QTest::addColumn<bool>("antialiasing");
+ QTest::addColumn<bool>("changedConnected");
+
+ // Anti-aliased.
+ QTest::newRow("pen width: 0.0, antialiasing: true") << qreal(0.0) << true << false;
+ QTest::newRow("pen width: 1.5, antialiasing: true") << qreal(1.5) << true << false;
+ QTest::newRow("pen width: 2.0, antialiasing: true") << qreal(2.0) << true << false;
+ QTest::newRow("pen width: 3.0, antialiasing: true") << qreal(3.0) << true << false;
+
+ // Aliased.
+ QTest::newRow("pen width: 0.0, antialiasing: false") << qreal(0.0) << false << false;
+ QTest::newRow("pen width: 1.5, antialiasing: false") << qreal(1.5) << false << false;
+ QTest::newRow("pen width: 2.0, antialiasing: false") << qreal(2.0) << false << false;
+ QTest::newRow("pen width: 3.0, antialiasing: false") << qreal(3.0) << false << false;
+
+ // changed() connected
+ QTest::newRow("pen width: 0.0, antialiasing: false, changed") << qreal(0.0) << false << true;
+ QTest::newRow("pen width: 1.5, antialiasing: true, changed") << qreal(1.5) << true << true;
+ QTest::newRow("pen width: 2.0, antialiasing: false, changed") << qreal(2.0) << false << true;
+ QTest::newRow("pen width: 3.0, antialiasing: true, changed") << qreal(3.0) << true << true;
+}
+
+void tst_QGraphicsView::update2()
+{
+ QFETCH(qreal, penWidth);
+ QFETCH(bool, antialiasing);
+ QFETCH(bool, changedConnected);
+
+ // Create a rect item.
+ const QRectF rawItemRect(-50.4, -50.3, 100.2, 100.1);
+ CountPaintItem *rect = new CountPaintItem(rawItemRect);
+ QPen pen;
+ pen.setWidthF(penWidth);
+ rect->setPen(pen);
+
+ // Add item to a scene.
+ QGraphicsScene scene(-100, -100, 200, 200);
+ if (changedConnected)
+ QObject::connect(&scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
+
+ scene.addItem(rect);
+
+ // Create a view on the scene.
+ CustomView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !antialiasing);
+ view.setRenderHint(QPainter::Antialiasing, antialiasing);
+ view.setFrameStyle(0);
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view) ;
+ QTRY_VERIFY(rect->numPaints > 0);
+
+ // Calculate expected update region for the rect.
+ QRectF expectedItemBoundingRect = rawItemRect;
+ const qreal halfPenWidth = penWidth / qreal(2.0);
+ expectedItemBoundingRect.adjust(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
+ QCOMPARE(rect->boundingRect(), expectedItemBoundingRect);
+
+ QRect expectedItemDeviceBoundingRect = rect->deviceTransform(view.viewportTransform())
+ .mapRect(expectedItemBoundingRect).toAlignedRect();
+ if (antialiasing)
+ expectedItemDeviceBoundingRect.adjust(-2, -2, 2, 2);
+ else
+ expectedItemDeviceBoundingRect.adjust(-1, -1, 1, 1);
+ const QRegion expectedUpdateRegion(expectedItemDeviceBoundingRect);
+
+ // Reset.
+ rect->numPaints = 0;
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ rect->update();
+ QTRY_VERIFY(view.painted);
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), expectedUpdateRegion);
+#endif
+}
+
+void tst_QGraphicsView::update_ancestorClipsChildrenToShape()
+{
+ QGraphicsScene scene(-150, -150, 300, 300);
+
+ /*
+ Add three rects:
+
+ +------------------+
+ | child |
+ | +--------------+ |
+ | | parent | |
+ | | +-----------+ |
+ | | |grandParent| |
+ | | +-----------+ |
+ | +--------------+ |
+ +------------------+
+
+ ... where both the parent and the grand parent clips children to shape.
+ */
+ QApplication::processEvents(); // Get rid of pending update.
+
+ QGraphicsRectItem *grandParent = static_cast<QGraphicsRectItem *>(scene.addRect(0, 0, 50, 50));
+ grandParent->setBrush(Qt::black);
+ grandParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
+ parent->setBrush(QColor(0, 0, 255, 125));
+ parent->setParentItem(grandParent);
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
+ child->setBrush(QColor(255, 0, 0, 125));
+ child->setParentItem(parent);
+
+ CustomView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.painted);
+
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ // Call child->update() and make sure the updated area is within the ancestors' clip.
+ QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
+ expected &= grandParent->deviceTransform(view.viewportTransform()).mapRect(grandParent->boundingRect());
+
+ child->update();
+ QTRY_VERIFY(view.painted);
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
+#endif
+}
+
+void tst_QGraphicsView::update_ancestorClipsChildrenToShape2()
+{
+ QGraphicsScene scene(-150, -150, 300, 300);
+
+ /*
+ Add two rects:
+
+ +------------------+
+ | child |
+ | +--------------+ |
+ | | parent | |
+ | | | |
+ | | | |
+ | | | |
+ | +--------------+ |
+ +------------------+
+
+ ... where the parent has no contents and clips the child to shape.
+ */
+ QApplication::processEvents(); // Get rid of pending update.
+
+ QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
+ parent->setBrush(QColor(0, 0, 255, 125));
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ parent->setFlag(QGraphicsItem::ItemHasNoContents);
+
+ QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
+ child->setBrush(QColor(255, 0, 0, 125));
+ child->setParentItem(parent);
+
+ CustomView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.painted);
+
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ // Call child->update() and make sure the updated area is within its parent's clip.
+ QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
+ expected &= parent->deviceTransform(view.viewportTransform()).mapRect(parent->boundingRect());
+
+ child->update();
+ QTRY_VERIFY(view.painted);
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
+#endif
+
+ QTest::qWait(50);
+
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ // Invalidate the parent's geometry and trigger an update.
+ // The update area should be clipped to the parent's bounding rect for 'normal' items,
+ // but in this case the item has no contents (ItemHasNoContents) and its geometry
+ // is invalidated, which means we cannot clip the child update. So, the expected
+ // area is exactly the same as the child's bounding rect (adjusted for antialiasing).
+ parent->setRect(parent->rect().adjusted(-10, -10, -10, -10));
+ expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
+ expected.adjust(-2, -2, 2, 2); // Antialiasing
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
+#endif
+}
+
+class FocusItem : public QGraphicsRectItem
+{
+public:
+ FocusItem() : QGraphicsRectItem(0, 0, 20, 20) {
+ m_viewHasIMEnabledInFocusInEvent = false;
+ }
+
+ void focusInEvent(QFocusEvent * /* event */)
+ {
+ QGraphicsView *view = scene()->views().first();
+ m_viewHasIMEnabledInFocusInEvent = view->testAttribute(Qt::WA_InputMethodEnabled);
+ }
+
+ bool m_viewHasIMEnabledInFocusInEvent;
+};
+
+void tst_QGraphicsView::inputMethodSensitivity()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ FocusItem *item = new FocusItem;
+
+ view.setAttribute(Qt::WA_InputMethodEnabled, true);
+
+ scene.addItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.removeItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ scene.addItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.removeItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.addItem(item);
+ scene.setFocusItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.removeItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ scene.addItem(item);
+ scene.setFocusItem(item);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+
+ // introduce another item that is focusable but does not accept input methods
+ FocusItem *item2 = new FocusItem;
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ scene.addItem(item2);
+ scene.setFocusItem(item2);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
+
+ scene.setFocusItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ view.setScene(0);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ view.setScene(&scene);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ scene.setFocusItem(item2);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
+
+ view.setScene(0);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
+
+ scene.setFocusItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ view.setScene(&scene);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+}
+
+class InputContextTester : public QInputContext
+{
+ Q_OBJECT
+public:
+ QString identifierName() { return QString(); }
+ bool isComposing() const { return false; }
+ QString language() { return QString(); }
+ void reset() { ++resets; }
+ int resets;
+};
+
+void tst_QGraphicsView::inputContextReset()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
+
+ InputContextTester *inputContext = new InputContextTester;
+ qApp->setInputContext(inputContext);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ QGraphicsItem *item1 = new QGraphicsRectItem;
+ item1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
+
+ inputContext->resets = 0;
+ scene.addItem(item1);
+ QCOMPARE(inputContext->resets, 0);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(item1);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)item1);
+ QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
+ QCOMPARE(inputContext->resets, 0);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(0);
+ // the input context is reset twice, once because an item has lost focus and again because
+ // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
+ QCOMPARE(inputContext->resets, 2);
+
+ // introduce another item that is focusable but does not accept input methods
+ QGraphicsItem *item2 = new QGraphicsRectItem;
+ item2->setFlags(QGraphicsItem::ItemIsFocusable);
+ scene.addItem(item2);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(item2);
+ QCOMPARE(inputContext->resets, 0);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(item1);
+ QCOMPARE(inputContext->resets, 0);
+
+ // test changing between between items that accept input methods.
+ item2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
+ scene.setFocusItem(item2);
+ QCOMPARE(inputContext->resets, 1);
+}
+
+void tst_QGraphicsView::indirectPainting()
+{
+ class MyScene : public QGraphicsScene
+ { public:
+ MyScene() : QGraphicsScene(), drawCount(0) {}
+ void drawItems(QPainter *, int, QGraphicsItem **, const QStyleOptionGraphicsItem *, QWidget *)
+ { ++drawCount; }
+ int drawCount;
+ };
+
+ MyScene scene;
+ QGraphicsItem *item = scene.addRect(0, 0, 50, 50);
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(100);
+
+ scene.drawCount = 0;
+ item->setPos(20, 20);
+ QApplication::processEvents();
+ QTRY_VERIFY(scene.drawCount > 0);
+}
+
+void tst_QGraphicsView::compositionModeInDrawBackground()
+{
+ class MyView : public QGraphicsView
+ { public:
+ MyView(QGraphicsScene *scene) : QGraphicsView(scene),
+ painted(false), compositionMode(QPainter::CompositionMode_SourceOver) {}
+ bool painted;
+ QPainter::CompositionMode compositionMode;
+ void drawBackground(QPainter *painter, const QRectF &)
+ {
+ compositionMode = painter->compositionMode();
+ painted = true;
+ }
+ };
+
+ QGraphicsScene dummy;
+ MyView view(&dummy);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Make sure the painter's composition mode is SourceOver in drawBackground.
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
+
+ view.painted = false;
+ view.setCacheMode(QGraphicsView::CacheBackground);
+ view.viewport()->update();
+
+ // Make sure the painter's composition mode is SourceOver in drawBackground
+ // with background cache enabled.
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
+}
+void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
+{
+ QGraphicsView view;
+ QGraphicsView dummyView;
+ view.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
+ view.resize(200, 200);
+
+ QGraphicsScene scene1;
+ QObject::connect(&scene1, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
+ view.setScene(&scene1);
+
+ QTest::qWait(12);
+
+ QGraphicsScene scene2;
+ QObject::connect(&scene2, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
+ view.setScene(&scene2);
+
+ QTest::qWait(12);
+
+ bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList<QRectF>)), &view, 0);
+ QVERIFY(wasConnected2);
+}
+
+// Qt/CE does not implement mouse tracking at this point.
+#ifndef Q_OS_WINCE
+void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
+{
+ QGraphicsScene scene(-100, -100, 200, 200);
+ scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
+
+ class VpGraphicsView: public QGraphicsView
+ {
+ public:
+ VpGraphicsView(QGraphicsScene *scene, QWidget *parent=0)
+ : QGraphicsView(scene, parent)
+ {
+ setViewportMargins(8, 16, 12, 20);
+ setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ setMouseTracking(true);
+ }
+ };
+
+ VpGraphicsView view(&scene);
+ view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(50);
+ QPoint mouseViewPos(20, 20);
+ sendMouseMove(view.viewport(), mouseViewPos);
+
+ QPointF mouseScenePos = view.mapToScene(mouseViewPos);
+ view.setTransform(QTransform().scale(5, 5).rotate(5, Qt::ZAxis), true);
+
+ QPointF newMouseScenePos = view.mapToScene(mouseViewPos);
+
+ qreal slack = 1;
+ QVERIFY(qAbs(newMouseScenePos.x() - mouseScenePos.x()) < slack);
+ QVERIFY(qAbs(newMouseScenePos.y() - mouseScenePos.y()) < slack);
+}
+#endif
+
+void tst_QGraphicsView::task259503_scrollingArtifacts()
+{
+ QGraphicsScene scene(0, 0, 800, 600);
+
+ QGraphicsRectItem card;
+ card.setRect(0, 0, 50, 50);
+ card.setPen(QPen(Qt::darkRed));
+ card.setBrush(QBrush(Qt::cyan));
+ card.setZValue(2.0);
+ card.setPos(300, 300);
+ scene.addItem(&card);
+
+ class SAGraphicsView: public QGraphicsView
+ {
+ public:
+ SAGraphicsView(QGraphicsScene *scene)
+ : QGraphicsView(scene)
+ , itSTimeToTest(false)
+ {
+ setViewportUpdateMode( QGraphicsView::MinimalViewportUpdate );
+ resize(QSize(640, 480));
+ }
+
+ QRegion updateRegion;
+ bool itSTimeToTest;
+
+ void paintEvent(QPaintEvent *event)
+ {
+ QGraphicsView::paintEvent(event);
+
+ if (itSTimeToTest)
+ {
+// qDebug() << event->region();
+// qDebug() << updateRegion;
+ QEXPECT_FAIL("", "The event region doesn't include the original item position region. See QTBUG-4416", Continue);
+ QCOMPARE(event->region(), updateRegion);
+ }
+ }
+ };
+
+ SAGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ int hsbValue = view.horizontalScrollBar()->value();
+ view.horizontalScrollBar()->setValue(hsbValue / 2);
+ QTest::qWait(10);
+ view.horizontalScrollBar()->setValue(0);
+ QTest::qWait(10);
+
+ QRect itemDeviceBoundingRect = card.deviceTransform(view.viewportTransform()).mapRect(card.boundingRect()).toRect();
+ itemDeviceBoundingRect.adjust(-2, -2, 2, 2);
+ view.updateRegion = itemDeviceBoundingRect;
+ view.updateRegion += itemDeviceBoundingRect.translated(-100, 0);
+ view.itSTimeToTest = true;
+ card.setPos(200, 300);
+ QTest::qWait(10);
+}
+
+void tst_QGraphicsView::QTBUG_4151_clipAndIgnore_data()
+{
+ QTest::addColumn<bool>("clip");
+ QTest::addColumn<bool>("ignoreTransformations");
+ QTest::addColumn<int>("numItems");
+
+ QTest::newRow("none") << false << false << 3;
+ QTest::newRow("clip") << true << false << 3;
+ QTest::newRow("ignore") << false << true << 3;
+ QTest::newRow("clip+ignore") << true << true << 3;
+}
+
+void tst_QGraphicsView::QTBUG_4151_clipAndIgnore()
+{
+ QFETCH(bool, clip);
+ QFETCH(bool, ignoreTransformations);
+ QFETCH(int, numItems);
+
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 50, 50), 0);
+ QGraphicsRectItem *child = new QGraphicsRectItem(QRectF(-10, -10, 40, 40), parent);
+ QGraphicsRectItem *ignore = new QGraphicsRectItem(QRectF(60, 60, 50, 50), 0);
+
+ if (clip)
+ parent->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
+ if (ignoreTransformations)
+ ignore->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ parent->setBrush(Qt::red);
+ child->setBrush(QColor(0, 0, 255, 128));
+ ignore->setBrush(Qt::green);
+
+ scene.addItem(parent);
+ scene.addItem(ignore);
+
+ QGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.resize(75, 75);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.activateWindow();
+
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+ QCOMPARE(view.items(view.rect()).size(), numItems);
+}
+
+void tst_QGraphicsView::QTBUG_5859_exposedRect()
+{
+ class CustomScene : public QGraphicsScene
+ {
+ public:
+ CustomScene(const QRectF &rect) : QGraphicsScene(rect) { }
+ void drawBackground(QPainter * /* painter */, const QRectF &rect)
+ { lastBackgroundExposedRect = rect; }
+ QRectF lastBackgroundExposedRect;
+ };
+
+ class CustomRectItem : public QGraphicsRectItem
+ {
+ public:
+ CustomRectItem(const QRectF &rect) : QGraphicsRectItem(rect)
+ { setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); }
+ void paint(QPainter * /* painter */, const QStyleOptionGraphicsItem *option, QWidget * /* widget */ = 0)
+ { lastExposedRect = option->exposedRect; }
+ QRectF lastExposedRect;
+ };
+
+ CustomScene scene(QRectF(0,0,50,50));
+
+ CustomRectItem item(scene.sceneRect());
+
+ scene.addItem(&item);
+
+ QGraphicsView view(&scene);
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.scale(4.15, 4.15);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ view.viewport()->repaint(10,10,20,20);
+ QApplication::processEvents();
+
+ QCOMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect);
+}
+
+// Qt/CE does not have regular cursor support.
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+void tst_QGraphicsView::QTBUG_7438_cursor()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(400, 400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMousePress(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseRelease(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+}
+#endif
+
+class GraphicsItemWithHover : public QGraphicsRectItem
+{
+public:
+ GraphicsItemWithHover()
+ : receivedEnterEvent(false), receivedLeaveEvent(false),
+ enterWidget(0), leaveWidget(0)
+ {
+ setRect(0, 0, 100, 100);
+ setAcceptHoverEvents(true);
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::GraphicsSceneHoverEnter) {
+ receivedEnterEvent = true;
+ enterWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
+ } else if (event->type() == QEvent::GraphicsSceneHoverLeave) {
+ receivedLeaveEvent = true;
+ leaveWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
+ }
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ bool receivedEnterEvent;
+ bool receivedLeaveEvent;
+ QWidget *enterWidget;
+ QWidget *leaveWidget;
+};
+
+void tst_QGraphicsView::hoverLeave()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ GraphicsItemWithHover *item = new GraphicsItemWithHover;
+ scene.addItem(item);
+
+ // move the cursor out of the way
+ QCursor::setPos(1,1);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QPoint pos = view.viewport()->mapToGlobal(view.mapFromScene(item->mapToScene(10, 10)));
+ QCursor::setPos(pos);
+ QTest::qWait(200);
+ QVERIFY(item->receivedEnterEvent);
+ QCOMPARE(item->enterWidget, view.viewport());
+
+ QCursor::setPos(1,1);
+ QTest::qWait(200);
+ QVERIFY(item->receivedLeaveEvent);
+ QCOMPARE(item->leaveWidget, view.viewport());
+}
+
+class IMItem : public QGraphicsRectItem
+{
+public:
+ IMItem(QGraphicsItem *parent = 0):
+ QGraphicsRectItem(QRectF(0, 0, 20, 20), parent)
+ {
+ setFlag(QGraphicsItem::ItemIsFocusable, true);
+ setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ }
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const
+ {
+ return mf;
+ }
+
+ static QRectF mf;
+};
+
+QRectF IMItem::mf(1.5, 1.6, 10, 10);
+
+void tst_QGraphicsView::QTBUG_16063_microFocusRect()
+{
+ QGraphicsScene scene;
+ IMItem *item = new IMItem();
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+
+ view.setFixedSize(40, 40);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ scene.setFocusItem(item);
+ view.setFocus();
+ QRectF mfv = view.inputMethodQuery(Qt::ImMicroFocus).toRectF();
+ QCOMPARE(mfv, IMItem::mf.translated(-view.mapToScene(view.sceneRect().toRect()).boundingRect().topLeft()));
+}
+
+QTEST_MAIN(tst_QGraphicsView)
+#include "tst_qgraphicsview.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp
new file mode 100644
index 0000000000..122ffbc875
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp
@@ -0,0 +1,976 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QSize>
+#include <QRectF>
+#include <QTransform>
+
+#ifdef Q_OS_WINCE
+#include <qguifunctions_wince.h>
+
+bool qt_wince_is_high_dpi() {
+ HDC deviceContext = GetDC(0);
+ int dpi = GetDeviceCaps(deviceContext, LOGPIXELSX);
+ ReleaseDC(0, deviceContext);
+ if ((dpi < 1000) && (dpi > 0))
+ return dpi > 96;
+ else
+ return false;
+}
+#endif
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+Q_DECLARE_METATYPE(Qt::ScrollBarPolicy)
+
+static void _scrollBarRanges_data_1(int offset)
+{
+ // No motif, flat frame
+ QTest::newRow("1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << offset << false << false;
+ QTest::newRow("3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << (100 + offset) << false << false;
+ QTest::newRow("4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset -50) << -100 << (-100 + offset) << false << false;
+ QTest::newRow("6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset -50) << -100 << offset << false << false;
+ QTest::newRow("7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 1) << 0 << offset + 1 << false << false;
+ QTest::newRow("8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << offset + 1 << false << false;
+ QTest::newRow("9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << (100 + offset + 1) << false << false;
+ QTest::newRow("10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset) << -101 << (-100 + offset) << false << false;
+ QTest::newRow("11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset + -50) << -101 << (-100 + offset) << false << false;
+ QTest::newRow("12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset -50) << (-101) << offset << false << false;
+ QTest::newRow("13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16) << 0 << (offset + 16) << false << false;
+ QTest::newRow("14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (offset + 16) << false << false;
+ QTest::newRow("15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (100 + offset + 16) << false << false;
+ QTest::newRow("16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset) << (-100 - 16 ) << (-100 + offset) << false << false;
+ QTest::newRow("17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset -50) << (-100 - 16) << (-100 + offset) << false << false;
+ QTest::newRow("18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset -50) << (-100 - 16) << offset << false << false;
+ QTest::newRow("1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset) << 0 << (100 + offset) << false << false;
+ QTest::newRow("2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (100 + offset) << false << false;
+ QTest::newRow("3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (300 + offset) << false << false;
+ QTest::newRow("4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset) << -200 << (-100 + offset) << false << false;
+ QTest::newRow("5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (-100 + offset) << false << false;
+ QTest::newRow("6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (100 + offset) << false << false;
+ QTest::newRow("1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << false << false;
+ QTest::newRow("3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << false << false;
+ QTest::newRow("4 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << false << false;
+ QTest::newRow("6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << false << false;
+ QTest::newRow("7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << false << false;
+ QTest::newRow("8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << false << false;
+ QTest::newRow("9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << false << false;
+ QTest::newRow("10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << false << false;
+ QTest::newRow("11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << false << false;
+ QTest::newRow("12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << false << false;
+ QTest::newRow("13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << false << false;
+ QTest::newRow("14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << false << false;
+ QTest::newRow("15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << false << false;
+ QTest::newRow("17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << false << false;
+ QTest::newRow("18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << false << false;
+ QTest::newRow("1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << false << false;
+ QTest::newRow("2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << false << false;
+ QTest::newRow("3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << false << false;
+ QTest::newRow("4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << false << false;
+ QTest::newRow("5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << false << false;
+ QTest::newRow("6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << false << false;
+ QTest::newRow("1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 16 << 0 << 16 << false << false;
+ QTest::newRow("2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << 16 << false << false;
+ QTest::newRow("3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16) << -100 << (-100 + 16) << false << false;
+ QTest::newRow("5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << (-100 + 16) << false << false;
+ QTest::newRow("6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << 16 << false << false;
+ QTest::newRow("7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 17 << 0 << 17 << false << false;
+ QTest::newRow("8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (17+50) << 0 << 17 << false << false;
+ QTest::newRow("9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 67 << 0 << 117 << false << false;
+ QTest::newRow("10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16) << -101 << (-100 + 16) << false << false;
+ QTest::newRow("11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << (-100 + 16) << false << false;
+ QTest::newRow("12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << 16 << false << false;
+ QTest::newRow("13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 32 << 0 << 32 << false << false;
+ QTest::newRow("14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << 32 << false << false;
+ QTest::newRow("15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << (100 + 32) << false << false;
+ QTest::newRow("16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16) << (-100 - 16) << (-100 + 16) << false << false;
+ QTest::newRow("17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << (-100 + 16) << false << false;
+ QTest::newRow("18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << 16 << false << false;
+ QTest::newRow("1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (300 + 16) << false << false;
+ QTest::newRow("4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16) << -200 << (-100 + 16) << false << false;
+ QTest::newRow("5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (-100 + 16) << false << false;
+ QTest::newRow("6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (100 + 16) << false << false;
+}
+
+static void _scrollBarRanges_data_2(int offset)
+{
+ // Motif, flat frame
+ QTest::newRow("Motif, 1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << offset << true << false;
+ QTest::newRow("Motif, 3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << offset << true << false;
+ QTest::newRow("Motif, 7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << offset + 1 << 0 << offset + 1 << true << false;
+ QTest::newRow("Motif, 8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << offset + 1 << true << false;
+ QTest::newRow("Motif, 9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << (100 + offset + 1) << true << false;
+ QTest::newRow("Motif, 10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset) << -101 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << -101 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << (-101) << offset << true << false;
+ QTest::newRow("Motif, 13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16) << 0 << (offset + 16) << true << false;
+ QTest::newRow("Motif, 14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (offset + 16) << true << false;
+ QTest::newRow("Motif, 15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (100 + offset + 16) << true << false;
+ QTest::newRow("Motif, 16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset) << (-100 - 16) << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << offset << true << false;
+ QTest::newRow("Motif, 1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset) << 0 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (300 + offset) << true << false;
+ QTest::newRow("Motif, 4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset) << -200 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << true << false;
+ QTest::newRow("Motif, 4 No ScrollBars") << QSize(100, 100) << QRectF(-100, -100, 100, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << true << false;
+ QTest::newRow("Motif, 7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << true << false;
+ QTest::newRow("Motif, 8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << true << false;
+ QTest::newRow("Motif, 9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << true << false;
+ QTest::newRow("Motif, 10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << true << false;
+ QTest::newRow("Motif, 11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << true << false;
+ QTest::newRow("Motif, 12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << true << false;
+ QTest::newRow("Motif, 13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << true << false;
+ QTest::newRow("Motif, 14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << true << false;
+ QTest::newRow("Motif, 15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << true << false;
+ QTest::newRow("Motif, 17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << true << false;
+ QTest::newRow("Motif, 18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << true << false;
+ QTest::newRow("Motif, 1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << true << false;
+ QTest::newRow("Motif, 2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << true << false;
+ QTest::newRow("Motif, 3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << true << false;
+ QTest::newRow("Motif, 4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << true << false;
+ QTest::newRow("Motif, 5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << true << false;
+ QTest::newRow("Motif, 6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << true << false;
+ QTest::newRow("Motif, 1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 16 << 0 << 16 << true << false;
+ QTest::newRow("Motif, 2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << 16 << true << false;
+ QTest::newRow("Motif, 3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16) << -100 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << 16 << true << false;
+ QTest::newRow("Motif, 7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 17 << 0 << 17 << true << false;
+ QTest::newRow("Motif, 8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 17 << true << false;
+ QTest::newRow("Motif, 9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 117 << true << false;
+ QTest::newRow("Motif, 10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16) << -101 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << 16 << true << false;
+ QTest::newRow("Motif, 13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 32 << 0 << 32 << true << false;
+ QTest::newRow("Motif, 14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << 32 << true << false;
+ QTest::newRow("Motif, 15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << (100 + 32) << true << false;
+ QTest::newRow("Motif, 16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16) << (-100 - 16) << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << 16 << true << false;
+ QTest::newRow("Motif, 1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (300 + 16) << true << false;
+ QTest::newRow("Motif, 4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16) << -200 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (100 + 16) << true << false;
+}
+
+static void _scrollBarRanges_data_3(int offset)
+{
+ // No motif, styled panel
+ QTest::newRow("Styled, 1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << offset << false << true;
+ QTest::newRow("Styled, 3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << offset << false << true;
+ QTest::newRow("Styled, 7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << offset + 1 << 0 << offset + 1 << false << true;
+ QTest::newRow("Styled, 8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << offset + 1 << false << true;
+ QTest::newRow("Styled, 9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << (100 + offset + 1) << false << true;
+ QTest::newRow("Styled, 10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset) << -101 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << -101 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << (-101) << offset << false << true;
+ QTest::newRow("Styled, 13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16) << 0 << (offset + 16) << false << true;
+ QTest::newRow("Styled, 14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (offset + 16) << false << true;
+ QTest::newRow("Styled, 15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (100 + offset + 16) << false << true;
+ QTest::newRow("Styled, 16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset) << (-100 - 16) << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << offset << false << true;
+ QTest::newRow("Styled, 1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset) << 0 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (300 + offset) << false << true;
+ QTest::newRow("Styled, 4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset) << -200 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << false << true;
+ QTest::newRow("Styled, 4 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << false << true;
+ QTest::newRow("Styled, 7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << false << true;
+ QTest::newRow("Styled, 8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << false << true;
+ QTest::newRow("Styled, 9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << false << true;
+ QTest::newRow("Styled, 10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << false << true;
+ QTest::newRow("Styled, 11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << false << true;
+ QTest::newRow("Styled, 12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << false << true;
+ QTest::newRow("Styled, 13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << false << true;
+ QTest::newRow("Styled, 14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << false << true;
+ QTest::newRow("Styled, 15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << false << true;
+ QTest::newRow("Styled, 17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << false << true;
+ QTest::newRow("Styled, 18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << false << true;
+ QTest::newRow("Styled, 1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << false << true;
+ QTest::newRow("Styled, 2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << false << true;
+ QTest::newRow("Styled, 3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << false << true;
+ QTest::newRow("Styled, 4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << false << true;
+ QTest::newRow("Styled, 5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << false << true;
+ QTest::newRow("Styled, 6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << false << true;
+ QTest::newRow("Styled, 1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 16 << 0 << 16 << false << true;
+ QTest::newRow("Styled, 2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << 16 << false << true;
+ QTest::newRow("Styled, 3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16) << -100 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << 16 << false << true;
+ QTest::newRow("Styled, 7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 17 << 0 << 17 << false << true;
+ QTest::newRow("Styled, 8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 17 << false << true;
+ QTest::newRow("Styled, 9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 117 << false << true;
+ QTest::newRow("Styled, 10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16) << -101 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << 16 << false << true;
+ QTest::newRow("Styled, 13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 32 << 0 << 32 << false << true;
+ QTest::newRow("Styled, 14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << 32 << false << true;
+ QTest::newRow("Styled, 15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << (100 + 32) << false << true;
+ QTest::newRow("Styled, 16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16) << (-100 - 16) << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << 16 << false << true;
+ QTest::newRow("Styled, 1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (300 + 16) << false << true;
+ QTest::newRow("Styled, 4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16) << -200 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (100 + 16) << false << true;
+}
+
+static void _scrollBarRanges_data_4(int offset)
+{
+ // Motif, styled panel
+ QTest::newRow("Motif, Styled, 1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 4) << 0 << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 4) << 0 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset + 4 - 50) << -100 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset + 4 - 50) << -100 << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 1 + 4) << 0 << (offset + 1 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1 + 4) << 0 << (offset + 1 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1 + 4) << 0 << (100 + offset + 1 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset + 4) << -101 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset + 4 - 50) << -101 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset + 4 - 50) << (-101) << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16 + 4) << 0 << (offset + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16 + 4) << 0 << (offset + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16 + 4) << 0 << (100 + offset + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset + 4) << (-100 - 16) << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset + 4 - 50) << (-100 - 16) << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset + 4 - 50) << (-100 - 16) << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset + 4) << 0 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset + 4) << 0 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset + 4) << 0 << (300 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset + 4) << -200 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset + 4) << -200 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset + 4) << -200 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 4 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << true << true;
+ QTest::newRow("Motif, Styled, 8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << true << true;
+ QTest::newRow("Motif, Styled, 9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << true << true;
+ QTest::newRow("Motif, Styled, 10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << true << true;
+ QTest::newRow("Motif, Styled, 14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << true << true;
+ QTest::newRow("Motif, Styled, 15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << true << true;
+ QTest::newRow("Motif, Styled, 16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << true << true;
+ QTest::newRow("Motif, Styled, 17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << true << true;
+ QTest::newRow("Motif, Styled, 18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << true << true;
+ QTest::newRow("Motif, Styled, 1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << true << true;
+ QTest::newRow("Motif, Styled, 4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (16 + 4) << 0 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16 + 4) << 0 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16 + 4) << 0 << (100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16 + 4) << -100 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16 + 4 - 50) << -100 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16 + 4 - 50) << -100 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (17 + 4) << 0 << (17 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117 + 4 - 50) << 0 << (17 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117 + 4 - 50) << 0 << (117 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16 + 4) << -101 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16 + 4 - 50) << -101 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16 + 4 - 50) << -101 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (32 + 4) << 0 << (32 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32 + 4) << 0 << (32 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32 + 4) << 0 << (100 + 32 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16 + 4) << (-100 - 16) << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16 + 4 - 50) << (-100 - 16) << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16 + 4 - 50) << (-100 - 16) << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16 + 4) << 0 << (100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16 + 4) << 0 << (100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16 + 4) << 0 << (300 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16 + 4) << -200 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16 + 4) << -200 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16 + 4) << -200 << (100 + 16 + 4) << true << true;
+}
+
+void _scrollBarRanges_data()
+{
+ QTest::addColumn<QSize>("viewportSize");
+ QTest::addColumn<QRectF>("sceneRect");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<Qt::ScrollBarPolicy>("hbarpolicy");
+ QTest::addColumn<Qt::ScrollBarPolicy>("vbarpolicy");
+ QTest::addColumn<int>("hmin");
+ QTest::addColumn<int>("hmax");
+ QTest::addColumn<int>("vmin");
+ QTest::addColumn<int>("vmax");
+ QTest::addColumn<bool>("useMotif");
+ QTest::addColumn<bool>("useStyledPanel");
+
+ int offset = 16;
+#ifdef Q_OS_WINCE
+ if (qt_wince_is_high_dpi())
+ offset *= 2;
+#endif
+
+ _scrollBarRanges_data_1(offset);
+ _scrollBarRanges_data_2(offset);
+ _scrollBarRanges_data_3(offset);
+ _scrollBarRanges_data_4(offset);
+}
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore b/tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore
new file mode 100644
index 0000000000..ae39b803e5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicswidget
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro b/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
new file mode 100644
index 0000000000..330076eafc
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicswidget.cpp
+
+
+mac*:CONFIG+=insignificant_test
+qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test # QTBUG-20778 unstable on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
new file mode 100644
index 0000000000..c983016a20
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -0,0 +1,3361 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicswidget.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qstyleoption.h>
+#include <qgraphicslinearlayout.h>
+#include <qcleanlooksstyle.h>
+#include <qlineedit.h>
+#include <qboxlayout.h>
+#include <qaction.h>
+#include <qwidgetaction.h>
+#include "../../../platformquirks.h"
+
+
+class EventSpy : public QObject
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class tst_QGraphicsWidget : public QObject {
+Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicswidget();
+
+ void activation();
+ void boundingRect_data();
+ void boundingRect();
+ void dumpFocusChain_data();
+ void dumpFocusChain();
+ void focusWidget_data();
+ void focusWidget();
+ void focusWidget2();
+ void focusWidget3();
+ void focusPolicy_data();
+ void focusPolicy();
+ void font_data();
+ void font();
+ void fontPropagation();
+ void fontChangedEvent();
+ void fontPropagationWidgetItemWidget();
+ void fontPropagationSceneChange();
+ void geometry_data();
+ void geometry();
+ void geometryChanged();
+ void width();
+ void height();
+ void getContentsMargins_data();
+ void getContentsMargins();
+ void initStyleOption_data();
+ void initStyleOption();
+ void layout_data();
+ void layout();
+ void layoutDirection_data();
+ void layoutDirection();
+ void paint_data();
+ void paint();
+ void palettePropagation();
+ void parentWidget_data();
+ void parentWidget();
+ void resize_data();
+ void resize();
+ void setAttribute_data();
+ void setAttribute();
+ void setStyle_data();
+ void setStyle();
+ void setTabOrder_data();
+ void setTabOrder();
+ void setTabOrderAndReparent();
+ void topLevelWidget_data();
+ void topLevelWidget();
+ void unsetLayoutDirection_data();
+ void unsetLayoutDirection();
+ void focusNextPrevChild_data();
+ void focusNextPrevChild();
+ void verifyFocusChain();
+ void updateFocusChainWhenChildDie();
+ void sizeHint_data();
+ void sizeHint();
+ void consistentPosSizeGeometry_data();
+ void consistentPosSizeGeometry();
+ void setSizes_data();
+ void setSizes();
+ void closePopupOnOutsideClick();
+ void defaultSize();
+ void explicitMouseGrabber();
+ void implicitMouseGrabber();
+ void doubleClickAfterExplicitMouseGrab();
+ void popupMouseGrabber();
+ void windowFlags_data();
+ void windowFlags();
+ void shortcutsDeletion();
+ void painterStateProtectionOnWindowFrame();
+ void ensureClipping();
+ void widgetSendsGeometryChanges();
+ void respectHFW();
+ void addChildInpolishEvent();
+ void polishEvent();
+ void polishEvent2();
+ void autoFillBackground();
+ void initialShow();
+ void initialShow2();
+ void itemChangeEvents();
+ void itemSendGeometryPosChangesDeactivated();
+
+ void fontPropagatesResolveToChildren();
+ void fontPropagatesResolveToGrandChildren();
+ void fontPropagatesResolveInParentChange();
+ void fontPropagatesResolveViaNonWidget();
+ void fontPropagatesResolveFromScene();
+
+ // Task fixes
+ void task236127_bspTreeIndexFails();
+ void task243004_setStyleCrash();
+ void task250119_shortcutContext();
+ void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
+ void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
+};
+
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
+{
+ QTest::mouseMove(widget, point);
+ QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsWidget : public QGraphicsWidget {
+public:
+ SubQGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags windowFlags = 0)
+ : QGraphicsWidget(parent, windowFlags), eventCount(0)
+ { }
+
+ void initStyleOption(QStyleOption *option)
+ { QGraphicsWidget::initStyleOption(option); }
+
+ void call_changeEvent(QEvent* event)
+ { return QGraphicsWidget::changeEvent(event); }
+
+ bool call_event(QEvent *e)
+ { return event(e); }
+
+ void call_focusInEvent(QFocusEvent* event)
+ { return QGraphicsWidget::focusInEvent(event); }
+
+ bool call_focusNextPrevChild(bool next)
+ { return QGraphicsWidget::focusNextPrevChild(next); }
+
+ void call_focusOutEvent(QFocusEvent* event)
+ { return QGraphicsWidget::focusOutEvent(event); }
+
+ void call_hideEvent(QHideEvent* event)
+ { return QGraphicsWidget::hideEvent(event); }
+
+ QVariant call_itemChange(QGraphicsItem::GraphicsItemChange change, QVariant const& value)
+ { return QGraphicsWidget::itemChange(change, value); }
+
+ void call_moveEvent(QGraphicsSceneMoveEvent* event)
+ { return QGraphicsWidget::moveEvent(event); }
+
+ void call_polishEvent()
+ { return QGraphicsWidget::polishEvent(); }
+
+ QVariant call_propertyChange(QString const& propertyName, QVariant const& value)
+ { return QGraphicsWidget::propertyChange(propertyName, value); }
+
+ void call_resizeEvent(QGraphicsSceneResizeEvent* event)
+ { return QGraphicsWidget::resizeEvent(event); }
+
+ bool call_sceneEvent(QEvent* event)
+ { return QGraphicsWidget::sceneEvent(event); }
+
+ void call_showEvent(QShowEvent* event)
+ { return QGraphicsWidget::showEvent(event); }
+
+ QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+ { return QGraphicsWidget::sizeHint(which, constraint); }
+
+ void call_updateGeometry()
+ { return QGraphicsWidget::updateGeometry(); }
+
+ int eventCount;
+ Qt::LayoutDirection m_painterLayoutDirection;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ m_painterLayoutDirection = painter->layoutDirection();
+ QGraphicsWidget::paint(painter, option, widget);
+ if (hasFocus()) {
+ painter->setPen(Qt::DotLine);
+ painter->drawRect(rect());
+ }
+ //painter->drawText(QPointF(0,15), data(0).toString());
+ }
+
+protected:
+ bool event(QEvent *event)
+ {
+ eventCount++;
+ return QGraphicsWidget::event(event);
+ }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsWidget::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsWidget::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsWidget::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsWidget::cleanup()
+{
+}
+
+class SizeHinter : public QGraphicsWidget
+{
+public:
+ SizeHinter(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0,
+ const QSizeF &min = QSizeF(5,5),
+ const QSizeF &pref = QSizeF(50, 50),
+ const QSizeF &max = QSizeF(500, 500))
+ : QGraphicsWidget(parent, wFlags)
+ {
+ m_sizes[Qt::MinimumSize] = min;
+ m_sizes[Qt::PreferredSize] = pref;
+ m_sizes[Qt::MaximumSize] = max;
+
+ }
+ void setSizeHint(Qt::SizeHint which, const QSizeF &newSizeHint)
+ {
+ m_sizes[which] = newSizeHint;
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ Q_UNUSED(constraint);
+ return m_sizes[which];
+ }
+private:
+ QSizeF m_sizes[4];
+};
+
+void tst_QGraphicsWidget::qgraphicswidget()
+{
+ SubQGraphicsWidget widget;
+ QVERIFY(widget.isVisible());
+
+ QVERIFY(!widget.isWindow());
+ QCOMPARE(widget.boundingRect(), QRectF(0, 0, 0, 0));
+ QCOMPARE(widget.focusWidget(), (QGraphicsWidget*)0);
+ QCOMPARE(widget.focusPolicy(), Qt::NoFocus);
+ QCOMPARE(widget.font(), QFont());
+ QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size()));
+ QCOMPARE(widget.layout(), (QGraphicsLayout*)0);
+ QCOMPARE(widget.layoutDirection(), Qt::LeftToRight);
+ QCOMPARE(widget.palette(), QPalette());
+ QCOMPARE(widget.parentWidget(), (QGraphicsWidget*)0);
+ QCOMPARE(widget.rect(), QRectF(QPointF(), widget.size()));
+ QCOMPARE(widget.size(), QSizeF(0, 0));
+ QVERIFY(widget.style() != (QStyle*)0);
+ QCOMPARE(widget.testAttribute(Qt::WA_AcceptDrops), false);
+ QCOMPARE(widget.topLevelWidget(), (QGraphicsWidget*)&widget);
+ QCOMPARE(widget.type(), (int)QGraphicsWidget::Type);
+ QCOMPARE(widget.call_propertyChange(QString(), QVariant()), QVariant());
+ widget.call_sizeHint(Qt::PreferredSize, QSizeF());
+
+ QGraphicsScene scene;
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ SizeHinter *child = new SizeHinter(parent);
+
+ QCOMPARE(child->minimumSize(), QSizeF(5, 5));
+}
+
+void tst_QGraphicsWidget::activation()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *window1 = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsWidget *window2 = new QGraphicsWidget(0, Qt::Window);
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(!window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+ scene.addItem(window1);
+ scene.addItem(window2);
+
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(!window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ QEvent activateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activateEvent);
+
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ scene.setActiveWindow(window1);
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ QEvent deactivateEvent(QEvent::WindowDeactivate);
+ QApplication::sendEvent(&scene, &deactivateEvent);
+
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(!window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+}
+
+void tst_QGraphicsWidget::boundingRect_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("null") << QSizeF(0, 0);
+ QTest::newRow("avg") << QSizeF(10, 10);
+}
+
+// QRectF boundingRect() const public
+void tst_QGraphicsWidget::boundingRect()
+{
+ QFETCH(QSizeF, size);
+ SubQGraphicsWidget widget;
+ widget.resize(size);
+ QCOMPARE(widget.rect(), QRectF(QPointF(), size));
+ QCOMPARE(widget.boundingRect(), QRectF(QPointF(0, 0), size));
+}
+
+void tst_QGraphicsWidget::dumpFocusChain_data()
+{
+ QTest::addColumn<bool>("scene");
+ QTest::addColumn<int>("children");
+ QTest::addColumn<bool>("setFocus");
+ QTest::newRow("empty world") << false << 0 << false;
+ QTest::newRow("one world") << true << 2 << false;
+ QTest::newRow("one world w/focus") << true << 2 << true;
+}
+
+// void dumpFocusChain(QGraphicsScene* scene) public (static)
+void tst_QGraphicsWidget::dumpFocusChain()
+{
+ // ### this test is very strange...
+ QFETCH(bool, scene);
+ SubQGraphicsWidget *parent = new SubQGraphicsWidget;
+ QGraphicsScene *theScene = 0;
+ if (scene) {
+ theScene = new QGraphicsScene(this);
+ theScene->addItem(parent);
+ }
+ QFETCH(int, children);
+ QFETCH(bool, setFocus);
+ for (int i = 0; i < children; ++i) {
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget(parent);
+ if (setFocus) {
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ if (scene)
+ theScene->setFocusItem(widget);
+ }
+ }
+
+ if (!scene)
+ delete parent;
+}
+
+void tst_QGraphicsWidget::focusWidget_data()
+{
+ QTest::addColumn<int>("childCount");
+ QTest::addColumn<int>("childWithFocus");
+ QTest::newRow("none") << 0 << 0;
+ QTest::newRow("first") << 3 << 0;
+ QTest::newRow("last") << 3 << 2;
+}
+
+// QGraphicsWidget* focusWidget() const public
+void tst_QGraphicsWidget::focusWidget()
+{
+ SubQGraphicsWidget *parent = new SubQGraphicsWidget;
+ QCOMPARE(parent->focusWidget(), (QGraphicsWidget *)0);
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.addItem(parent);
+
+ QFETCH(int, childCount);
+ QList<SubQGraphicsWidget *> children;
+ for (int i = 0; i < childCount; ++i) {
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget(parent);
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ children.append(widget);
+ }
+ if (childCount > 0) {
+ QFETCH(int, childWithFocus);
+ SubQGraphicsWidget *widget = children[childWithFocus];
+ widget->setFocus();
+ QTRY_VERIFY(widget->hasFocus());
+ QCOMPARE(parent->focusWidget(), static_cast<QGraphicsWidget*>(widget));
+ }
+}
+
+void tst_QGraphicsWidget::focusWidget2()
+{
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ EventSpy focusInSpy(widget, QEvent::FocusIn);
+ EventSpy focusOutSpy(widget, QEvent::FocusOut);
+
+ scene.addItem(widget);
+
+ QTRY_VERIFY(!widget->hasFocus());
+ widget->setFocusPolicy(Qt::StrongFocus);
+ QTRY_VERIFY(!widget->hasFocus());
+
+ QGraphicsWidget *subWidget = new QGraphicsWidget(widget);
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ scene.setFocus();
+
+ QTRY_VERIFY(!widget->hasFocus());
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ widget->setFocus();
+
+ QTRY_VERIFY(widget->hasFocus());
+ QTRY_COMPARE(focusInSpy.count(), 1);
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ QGraphicsWidget *otherSubWidget = new QGraphicsWidget;
+ EventSpy otherFocusInSpy(otherSubWidget, QEvent::FocusIn);
+ EventSpy otherFocusOutSpy(otherSubWidget, QEvent::FocusOut);
+
+ otherSubWidget->setFocusPolicy(Qt::StrongFocus);
+ otherSubWidget->setParentItem(widget);
+
+ QTRY_VERIFY(widget->hasFocus());
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)widget);
+ QTRY_VERIFY(!subWidget->hasFocus());
+ QTRY_VERIFY(!otherSubWidget->hasFocus());
+
+ widget->hide();
+ QTRY_VERIFY(!widget->hasFocus()); // lose but still has subfocus
+ QCOMPARE(focusInSpy.count(), 1);
+ QCOMPARE(focusOutSpy.count(), 1);
+
+ widget->show();
+ QTRY_VERIFY(!widget->hasFocus()); // no regain
+ QCOMPARE(focusInSpy.count(), 1);
+ QCOMPARE(focusOutSpy.count(), 1);
+
+ widget->hide();
+
+ // try to setup subFocus on item that can't take focus
+ subWidget->setFocus();
+ QTRY_VERIFY(!subWidget->hasFocus());
+ QVERIFY(!scene.focusItem()); // but isn't the scene's focus item
+
+ // try to setup subFocus on item that can take focus
+ otherSubWidget->setFocus();
+ QTRY_VERIFY(!otherSubWidget->hasFocus());
+ QCOMPARE(widget->focusWidget(), otherSubWidget);
+ QVERIFY(!scene.focusItem()); // but isn't the scene's focus item
+
+ widget->show();
+
+ QTRY_COMPARE(scene.focusItem(), (QGraphicsItem *)otherSubWidget); // but isn't the scene's focus item
+ QCOMPARE(otherFocusInSpy.count(), 1);
+ QCOMPARE(otherFocusOutSpy.count(), 0);
+
+ delete otherSubWidget;
+
+ QTRY_COMPARE(otherFocusOutSpy.count(), 1);
+ QVERIFY(!scene.focusItem());
+ QVERIFY(!widget->focusWidget());
+}
+
+class FocusWatchWidget : public QGraphicsWidget
+{
+public:
+ FocusWatchWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent) { gotFocusInCount = 0; gotFocusOutCount = 0; }
+ int gotFocusInCount, gotFocusOutCount;
+protected:
+ void focusInEvent(QFocusEvent *fe) { gotFocusInCount++; QGraphicsWidget::focusInEvent(fe); }
+ void focusOutEvent(QFocusEvent *fe) { gotFocusOutCount++; QGraphicsWidget::focusOutEvent(fe); }
+};
+
+void tst_QGraphicsWidget::focusWidget3()
+{
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ FocusWatchWidget *subWidget = new FocusWatchWidget(widget);
+ subWidget->setFocusPolicy(Qt::StrongFocus);
+
+ scene.addItem(widget);
+ widget->show();
+
+ QTRY_VERIFY(!widget->hasFocus());
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ subWidget->setFocus();
+ QCOMPARE(subWidget->gotFocusInCount, 1);
+ QCOMPARE(subWidget->gotFocusOutCount, 0);
+ widget->hide();
+ QCOMPARE(subWidget->gotFocusOutCount, 1);
+}
+
+Q_DECLARE_METATYPE(Qt::FocusPolicy)
+void tst_QGraphicsWidget::focusPolicy_data()
+{
+ QTest::addColumn<Qt::FocusPolicy>("focusPolicy1");
+ QTest::addColumn<Qt::FocusPolicy>("focusPolicy2");
+
+ for (int i = 0; i < 25; ++i) {
+ QTestData &data = QTest::newRow(QString("%1").arg(i).toLatin1());
+ switch(i % 5) {
+ case 0: data << Qt::TabFocus; break;
+ case 1: data << Qt::ClickFocus; break;
+ case 2: data << Qt::StrongFocus; break;
+ case 3: data << Qt::WheelFocus; break;
+ case 4: data << Qt::NoFocus; break;
+ }
+ switch(i / 5) {
+ case 0: data << Qt::TabFocus; break;
+ case 1: data << Qt::ClickFocus; break;
+ case 2: data << Qt::StrongFocus; break;
+ case 3: data << Qt::WheelFocus; break;
+ case 4: data << Qt::NoFocus; break;
+ }
+ }
+}
+
+// Qt::FocusPolicy focusPolicy() const public
+void tst_QGraphicsWidget::focusPolicy()
+{
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget;
+ scene.addItem(widget);
+ QTRY_COMPARE(Qt::NoFocus, widget->focusPolicy());
+
+ QFETCH(Qt::FocusPolicy, focusPolicy1);
+ widget->setFocusPolicy(focusPolicy1);
+ QTRY_COMPARE(widget->focusPolicy(), focusPolicy1);
+ bool isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable;
+ bool wasFocusable = isFocusable;
+ QTRY_VERIFY(isFocusable == (focusPolicy1 != Qt::NoFocus));
+ widget->setFocus();
+ QTRY_COMPARE(widget->hasFocus(), isFocusable);
+
+ QFETCH(Qt::FocusPolicy, focusPolicy2);
+ widget->setFocusPolicy(focusPolicy2);
+ QCOMPARE(widget->focusPolicy(), focusPolicy2);
+ isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable;
+ QVERIFY(isFocusable == (focusPolicy2 != Qt::NoFocus));
+ QCOMPARE(widget->hasFocus(), wasFocusable && isFocusable);
+}
+
+void tst_QGraphicsWidget::font_data()
+{
+ QTest::addColumn<QString>("fontName");
+ QTest::newRow("Helvetica") << "Helvetica";
+}
+
+// QFont font() const public
+void tst_QGraphicsWidget::font()
+{
+ QFETCH(QString, fontName);
+ SubQGraphicsWidget widget;
+ QCOMPARE(widget.font(), QFont());
+
+ QFont font(fontName);
+ widget.setFont(font);
+ QCOMPARE(widget.font().family(), font.family());
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveToChildren()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ root->setFont(font);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *child3 = new QGraphicsWidget();
+ child3->setParentItem(root);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(root->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child3->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveToGrandChildren()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ root->setFont(font);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+ QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
+
+ QGraphicsWidget *child3 = new QGraphicsWidget();
+ QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
+ QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
+ child3->setParentItem(root);
+ grandChild5->setParentItem(child3);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild4->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild5->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveViaNonWidget()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsPixmapItem *child1 = new QGraphicsPixmapItem(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ root->setFont(font);
+
+ QGraphicsPixmapItem *child2 = new QGraphicsPixmapItem(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+ QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
+
+ QGraphicsPixmapItem *child3 = new QGraphicsPixmapItem();
+ QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
+ QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
+ child3->setParentItem(root);
+ grandChild5->setParentItem(child3);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild4->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild5->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveFromScene()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ scene.setFont(font);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+ QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
+
+ QGraphicsWidget *child3 = new QGraphicsWidget();
+ QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
+ QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
+ child3->setParentItem(root);
+ grandChild5->setParentItem(child3);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(root->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild4->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild5->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveInParentChange()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont italicFont;
+ italicFont.setItalic(true);
+ child1->setFont(italicFont);
+
+ QFont boldFont;
+ boldFont.setBold(true);
+ child2->setFont(boldFont);
+
+ QVERIFY(grandChild1->font().italic());
+ QVERIFY(!grandChild1->font().bold());
+ QVERIFY(!grandChild2->font().italic());
+ QVERIFY(grandChild2->font().bold());
+
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::WeightResolved));
+
+ grandChild2->setParentItem(child1);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QVERIFY(grandChild1->font().italic());
+ QVERIFY(!grandChild1->font().bold());
+ QVERIFY(grandChild2->font().italic());
+ QVERIFY(!grandChild2->font().bold());
+
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+
+}
+
+void tst_QGraphicsWidget::fontPropagation()
+{
+ QGraphicsWidget *root = new QGraphicsWidget;
+ QGraphicsWidget *child0 = new QGraphicsWidget(root);
+ QGraphicsWidget *child1 = new QGraphicsWidget(child0);
+ QGraphicsWidget *child2 = new QGraphicsWidget(child1);
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // Check that only the application fonts apply.
+ QFont appFont = QApplication::font();
+ QCOMPARE(scene.font(), appFont);
+ QCOMPARE(root->font(), appFont);
+ QCOMPARE(child0->font(), appFont);
+ QCOMPARE(child1->font(), appFont);
+
+ // Set child0's Text, and set ToolTipBase on child1.
+ QFont boldFont;
+ boldFont.setBold(true);
+ child0->setFont(boldFont);
+ QFont italicFont;
+ italicFont.setItalic(true);
+ child1->setFont(italicFont);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->font(), appFont);
+ QCOMPARE(scene.font(), appFont);
+ QVERIFY(child0->font().bold());
+ QVERIFY(!child0->font().italic());
+ QVERIFY(child1->font().bold());
+ QVERIFY(child1->font().italic());
+ QVERIFY(child2->font().bold());
+ QVERIFY(child2->font().italic());
+
+ QGraphicsWidget *child3 = new QGraphicsWidget(child2);
+ QVERIFY(child3->font().bold());
+ QVERIFY(child3->font().italic());
+
+ QGraphicsWidget *child4 = new QGraphicsWidget;
+ child4->setParentItem(child3);
+ QVERIFY(child4->font().bold());
+ QVERIFY(child4->font().italic());
+
+ // Replace the app font for child2. Button should propagate but Text
+ // should still be ignored. The previous ToolTipBase setting is gone.
+ QFont sizeFont;
+ sizeFont.setPointSize(43);
+ child1->setFont(sizeFont);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->font(), appFont);
+ QCOMPARE(scene.font(), appFont);
+ QVERIFY(child0->font().bold());
+ QVERIFY(!child0->font().italic());
+ QVERIFY(child1->font().bold());
+ QVERIFY(!child1->font().italic());
+ QCOMPARE(child1->font().pointSize(), 43);
+ QVERIFY(child2->font().bold());
+ QVERIFY(!child2->font().italic());
+ QCOMPARE(child2->font().pointSize(), 43);
+}
+
+void tst_QGraphicsWidget::fontChangedEvent()
+{
+ QGraphicsWidget *root = new QGraphicsWidget;
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // Check that only the application fonts apply.
+ QFont appFont = QApplication::font();
+ QCOMPARE(scene.font(), appFont);
+ QCOMPARE(root->font(), appFont);
+
+ EventSpy rootSpyFont(root, QEvent::FontChange);
+ EventSpy rootSpyPolish(root, QEvent::Polish);
+ QTRY_COMPARE(rootSpyFont.count(), 0);
+ QTRY_COMPARE(rootSpyPolish.count(), 1);
+ //The font is still the same so no fontChangeEvent
+ QTRY_COMPARE(rootSpyFont.count(), 0);
+
+ QFont font;
+ font.setPointSize(43);
+ root->setFont(font);
+ //The font changed
+ QTRY_COMPARE(rootSpyFont.count(), 1);
+
+ //then roll back to the default one.
+ root->setFont(appFont);
+ //The font changed
+ QTRY_COMPARE(rootSpyFont.count(), 2);
+}
+
+void tst_QGraphicsWidget::fontPropagationWidgetItemWidget()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsRectItem *rect = new QGraphicsRectItem(widget);
+ QGraphicsWidget *widget2 = new QGraphicsWidget(rect);
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ QFont font;
+ font.setPointSize(43);
+ widget->setFont(font);
+
+ QCOMPARE(widget2->font().pointSize(), 43);
+ QCOMPARE(widget2->font().resolve(), uint(QFont::SizeResolved));
+
+ widget->setFont(QFont());
+
+ QCOMPARE(widget2->font().pointSize(), qApp->font().pointSize());
+ QCOMPARE(widget2->font().resolve(), QFont().resolve());
+}
+
+void tst_QGraphicsWidget::fontPropagationSceneChange()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsRectItem *rect = new QGraphicsRectItem(widget);
+ QGraphicsWidget *widget2 = new QGraphicsWidget(rect);
+
+ QGraphicsScene scene;
+ QGraphicsScene scene2;
+
+ QFont font;
+ font.setPointSize(47);
+ scene.setFont(font);
+
+ QFont font2;
+ font2.setPointSize(74);
+ scene2.setFont(font2);
+
+ scene.addItem(widget);
+ QCOMPARE(widget2->font().pointSize(), 47);
+ scene2.addItem(widget);
+ QCOMPARE(widget2->font().pointSize(), 74);
+}
+
+void tst_QGraphicsWidget::geometry_data()
+{
+ QTest::addColumn<QPointF>("pos");
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("null, null") << QPointF() << QSizeF(0, 0);
+ QTest::newRow("null, normal") << QPointF() << QSizeF(10, 10);
+ QTest::newRow("neg, normal") << QPointF(-5, -5) << QSizeF(10, 10);
+}
+
+// QRectF geometry() const public
+void tst_QGraphicsWidget::geometry()
+{
+ SubQGraphicsWidget widget;
+ QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size()));
+ QSignalSpy spy(&widget, SIGNAL(geometryChanged()));
+ QFETCH(QPointF, pos);
+ QFETCH(QSizeF, size);
+ widget.setPos(pos);
+ widget.resize(size);
+ if (!size.isNull() && !pos.isNull())
+ QCOMPARE(spy.count(), 2);
+ if (!size.isNull() && pos.isNull())
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(widget.geometry(), QRectF(pos, size));
+}
+
+void tst_QGraphicsWidget::geometryChanged()
+{
+ QGraphicsWidget w;
+ w.setGeometry(0, 0, 200, 200);
+ QCOMPARE(w.geometry(), QRectF(0, 0, 200, 200));
+ QSignalSpy spy(&w, SIGNAL(geometryChanged()));
+ w.setGeometry(0, 0, 100, 100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(w.geometry(), QRectF(0, 0, 100, 100));
+ w.setPos(10, 10);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(w.geometry(), QRectF(10, 10, 100, 100));
+
+}
+
+void tst_QGraphicsWidget::width()
+{
+ QGraphicsWidget w;
+ QCOMPARE(w.property("width").toReal(), qreal(0));
+ QSignalSpy spy(&w, SIGNAL(widthChanged()));
+ w.setProperty("width", qreal(50));
+ QCOMPARE(w.property("width").toReal(), qreal(50));
+ QCOMPARE(spy.count(), 1);
+ //calling old school setGeometry should work too
+ w.setGeometry(0, 0, 200, 200);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QGraphicsWidget::height()
+{
+ QGraphicsWidget w;
+ QCOMPARE(w.property("height").toReal(), qreal(0));
+ QSignalSpy spy(&w, SIGNAL(heightChanged()));
+ w.setProperty("height", qreal(50));
+ QCOMPARE(w.property("height").toReal(), qreal(50));
+ QCOMPARE(spy.count(), 1);
+ //calling old school setGeometry should work too
+ w.setGeometry(0, 0, 200, 200);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QGraphicsWidget::getContentsMargins_data()
+{
+ QTest::addColumn<qreal>("left");
+ QTest::addColumn<qreal>("top");
+ QTest::addColumn<qreal>("right");
+ QTest::addColumn<qreal>("bottom");
+ QTest::newRow("null") << (qreal)0 << (qreal)0 << (qreal)0 << (qreal)0;
+ QTest::newRow("something") << (qreal)10 << (qreal)5 << (qreal)3 << (qreal)7;
+ QTest::newRow("real") << (qreal)1.7 << (qreal)5.9 << (qreal)3.2 << (qreal)9.7;
+}
+
+// void getContentsMargins(qreal* left, qreal* top, qreal* right, qreal* bottom) const public
+void tst_QGraphicsWidget::getContentsMargins()
+{
+ qreal gleft;
+ qreal gtop;
+ qreal gright;
+ qreal gbottom;
+
+ SubQGraphicsWidget widget;
+ widget.getContentsMargins(&gleft, &gtop, &gright, &gbottom);
+ QCOMPARE(gleft, (qreal)0);
+ QCOMPARE(gtop, (qreal)0);
+ QCOMPARE(gright, (qreal)0);
+ QCOMPARE(gbottom, (qreal)0);
+
+ QFETCH(qreal, left);
+ QFETCH(qreal, top);
+ QFETCH(qreal, right);
+ QFETCH(qreal, bottom);
+ int oldEventCounts = widget.eventCount;
+ widget.setContentsMargins(left, top, right, bottom);
+ QVERIFY(left == 0 || oldEventCounts != widget.eventCount);
+ widget.getContentsMargins(&gleft, &gtop, &gright, &gbottom);
+ QCOMPARE(gleft, left);
+ QCOMPARE(gtop, top);
+ QCOMPARE(gright, right);
+ QCOMPARE(gbottom, bottom);
+}
+
+Q_DECLARE_METATYPE(Qt::LayoutDirection)
+void tst_QGraphicsWidget::initStyleOption_data()
+{
+ QTest::addColumn<bool>("enabled");
+ QTest::addColumn<bool>("focus");
+ QTest::addColumn<bool>("underMouse");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QPalette>("palette");
+ QTest::addColumn<QString>("fontName");
+ QTest::newRow("none") << false << false << false << Qt::LeftToRight << QSizeF(0, 0) << QPalette() << QString();
+ QTest::newRow("all") << true << true << true << Qt::RightToLeft << QSizeF(300, 300) << QPalette(Qt::magenta) << "Helvetica";
+ QTest::newRow("rand") << true << false << false << Qt::RightToLeft << QSizeF(1, 0) << QPalette(Qt::darkCyan) << "Times";
+}
+
+// void initStyleOption(QStyleOption* option) const public
+void tst_QGraphicsWidget::initStyleOption()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget;
+ widget->setAcceptsHoverEvents(true);
+ QStyleOption option;
+ scene.addItem(widget);
+
+ QFETCH(QSizeF, size);
+ widget->resize(size);
+
+ QFETCH(bool, enabled);
+ widget->setEnabled(enabled);
+ QFETCH(bool, focus);
+ if (focus) {
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ widget->setFocus();
+ QVERIFY(widget->hasFocus());
+ }
+ QFETCH(bool, underMouse);
+ if (underMouse) {
+ view.resize(300, 300);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ sendMouseMove(view.viewport(), view.mapFromScene(widget->mapToScene(widget->boundingRect().center())));
+ }
+
+ QFETCH(QPalette, palette);
+ widget->setPalette(palette);
+
+ QFETCH(QString, fontName);
+ widget->setFont(QFont(fontName));
+
+ // The test
+ widget->initStyleOption(&option);
+
+ bool isEnabled = option.state & QStyle::State_Enabled;
+ QCOMPARE(isEnabled, enabled);
+ bool hasFocus = option.state & QStyle::State_HasFocus;
+ QCOMPARE(hasFocus, focus);
+ bool isUnderMouse = option.state & QStyle::State_MouseOver;
+#ifndef Q_OS_WINCE
+ QCOMPARE(isUnderMouse, underMouse);
+#endif
+ // if (layoutDirection != Qt::LeftToRight)
+ //QEXPECT_FAIL("", "QApplicaiton::layoutDirection doesn't propagate to QGraphicsWidget", Continue);
+ //QCOMPARE(option.direction, layoutDirection);
+ QCOMPARE(option.rect, QRectF(QPointF(), size).toRect());
+ QCOMPARE(option.palette, palette.resolve(QApplication::palette()));
+ QCOMPARE(option.fontMetrics, QFontMetrics(widget->font()));
+}
+
+void tst_QGraphicsWidget::layout_data()
+{
+ QTest::addColumn<int>("childCount");
+ QTest::newRow("empty") << 0;
+ QTest::newRow("10") << 10;
+}
+
+// QGraphicsLayout* layout() const public
+void tst_QGraphicsWidget::layout()
+{
+ SubQGraphicsWidget widget;
+ widget.setContentsMargins(10, 5, 50, 100);
+ QCOMPARE(widget.layout(), (QGraphicsLayout *)0);
+ QFETCH(int, childCount);
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < childCount; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget;
+ layout->addItem(item);
+ children.append(item);
+ }
+ QSignalSpy spy(&widget, SIGNAL(layoutChanged()));
+ widget.setLayout(layout);
+
+ QTRY_COMPARE(widget.layout(), static_cast<QGraphicsLayout*>(layout));
+ for (int i = 0; i < children.count(); ++i) {
+ SubQGraphicsWidget *item = children[i];
+ QCOMPARE(item->parentWidget(), (QGraphicsWidget *)&widget);
+ QVERIFY(item->geometry() != QRectF(0, 0, -1, -1));
+ }
+ QCOMPARE(spy.count(), 1);
+ // don't crash
+ widget.setLayout(0);
+}
+
+void tst_QGraphicsWidget::layoutDirection_data()
+{
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::newRow("rtl") << Qt::RightToLeft;
+ QTest::newRow("ltr") << Qt::LeftToRight;
+}
+
+// Qt::LayoutDirection layoutDirection() const public
+void tst_QGraphicsWidget::layoutDirection()
+{
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ SubQGraphicsWidget widget;
+ scene.addItem(&widget);
+ QCOMPARE(widget.layoutDirection(), Qt::LeftToRight);
+ QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false);
+
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < 10; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget(&widget);
+ children.append(item);
+ QCOMPARE(item->testAttribute(Qt::WA_SetLayoutDirection), false);
+ }
+ widget.setLayoutDirection(layoutDirection);
+ QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), true);
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ for (int i = 0; i < children.count(); ++i) {
+ QTRY_COMPARE(children[i]->layoutDirection(), layoutDirection);
+ QTRY_COMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false);
+ view->repaint();
+ QTRY_COMPARE(children[i]->m_painterLayoutDirection, layoutDirection);
+ }
+ delete view;
+}
+
+void tst_QGraphicsWidget::paint_data()
+{
+ // currently QGraphicsWidget doesn't paint or do anything ...
+}
+
+// void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget) public
+void tst_QGraphicsWidget::paint()
+{
+ SubQGraphicsWidget widget;
+ QPainter painter;
+ QStyleOptionGraphicsItem option;
+ widget.paint(&painter, &option, 0); // check that widget = 0 works.
+}
+
+void tst_QGraphicsWidget::palettePropagation()
+{
+ QGraphicsWidget *root = new QGraphicsWidget;
+ QGraphicsWidget *child0 = new QGraphicsWidget(root);
+ QGraphicsWidget *child1 = new QGraphicsWidget(child0);
+ QGraphicsWidget *child2 = new QGraphicsWidget(child1);
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // These colors are unlikely to be imposed on the default palette of
+ // QWidget ;-).
+ QColor sysPalText(21, 22, 23);
+ QColor sysPalToolTipBase(12, 13, 14);
+ QColor overridePalText(42, 43, 44);
+ QColor overridePalToolTipBase(45, 46, 47);
+ QColor sysPalButton(99, 98, 97);
+
+ // Check that only the application fonts apply.
+ QPalette appPal = QApplication::palette();
+ QCOMPARE(scene.palette(), appPal);
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette(), appPal);
+ QCOMPARE(child1->palette(), appPal);
+
+ // Set child0's Text, and set ToolTipBase on child1.
+ QPalette textPalette;
+ textPalette.setColor(QPalette::Text, overridePalText);
+ child0->setPalette(textPalette);
+ QPalette toolTipPalette;
+ toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
+ child1->setPalette(toolTipPalette);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(scene.palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+
+ QGraphicsWidget *child3 = new QGraphicsWidget(child2);
+ QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+
+ QGraphicsWidget *child4 = new QGraphicsWidget;
+ child4->setParentItem(child3);
+ QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+
+ // Replace the app palette for child2. Button should propagate but Text
+ // should still be ignored. The previous ToolTipBase setting is gone.
+ QPalette buttonPalette;
+ buttonPalette.setColor(QPalette::Button, sysPalButton);
+ child1->setPalette(buttonPalette);
+
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(scene.palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::Button), sysPalButton);
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child2->palette().color(QPalette::Button), sysPalButton);
+}
+
+void tst_QGraphicsWidget::parentWidget_data()
+{
+ QTest::addColumn<int>("childrenCount");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("10") << 10;
+}
+
+// QGraphicsWidget* parentWidget() const public
+void tst_QGraphicsWidget::parentWidget()
+{
+ QFETCH(int, childrenCount);
+ SubQGraphicsWidget standAlongWidget;
+ QGraphicsLineItem standAlongItem;
+
+ SubQGraphicsWidget widgetChild(&standAlongWidget);
+ SubQGraphicsWidget itemChild(&standAlongItem);
+
+ QCOMPARE(standAlongWidget.parentWidget(), (QGraphicsWidget*)0);
+ QCOMPARE(widgetChild.parentWidget(), static_cast<QGraphicsWidget*>(&standAlongWidget));
+ QCOMPARE(itemChild.parentWidget(), (QGraphicsWidget*)0);
+
+ for (int i = 0; i < childrenCount; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget(&standAlongWidget);
+ QCOMPARE(item->parentWidget(), static_cast<QGraphicsWidget*>(&standAlongWidget));
+ }
+}
+
+void tst_QGraphicsWidget::resize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("null") << QSizeF();
+ QTest::newRow("10x10") << QSizeF(10, 10);
+ QTest::newRow("10x-1") << QSizeF(10, -1);
+}
+
+// void resize(qreal w, qreal h) public
+void tst_QGraphicsWidget::resize()
+{
+ QFETCH(QSizeF, size);
+ SubQGraphicsWidget widget;
+
+ int oldEventCounts = widget.eventCount;
+ QSizeF oldSize = widget.size();
+ widget.resize(size);
+
+ QSizeF boundedSize = size.expandedTo(widget.minimumSize()).boundedTo(widget.maximumSize());
+ QCOMPARE(widget.eventCount, oldEventCounts + ((oldSize == boundedSize) ? 0 : 1));
+ QCOMPARE(widget.size(), boundedSize);
+}
+
+Q_DECLARE_METATYPE(Qt::WidgetAttribute)
+void tst_QGraphicsWidget::setAttribute_data()
+{
+ QTest::addColumn<Qt::WidgetAttribute>("attribute");
+ QTest::addColumn<bool>("supported");
+ QTest::newRow("WA_SetLayoutDirection") << Qt::WA_SetLayoutDirection << true;
+ QTest::newRow("WA_RightToLeft") << Qt::WA_RightToLeft << true;
+ QTest::newRow("WA_SetStyle") << Qt::WA_SetStyle << true;
+ QTest::newRow("WA_Resized") << Qt::WA_Resized << true;
+ QTest::newRow("unsupported") << Qt::WA_PaintOutsidePaintEvent << false;
+}
+
+// void setAttribute(Qt::WidgetAttribute attribute, bool on = true) public
+void tst_QGraphicsWidget::setAttribute()
+{
+ QFETCH(Qt::WidgetAttribute, attribute);
+ QFETCH(bool, supported);
+ SubQGraphicsWidget widget;
+ if (attribute == Qt::WA_PaintOutsidePaintEvent)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsWidget::setAttribute: unsupported attribute 13");
+ widget.setAttribute(attribute);
+ QCOMPARE(widget.testAttribute(attribute), supported);
+}
+
+void tst_QGraphicsWidget::setStyle_data()
+{
+ QTest::addColumn<QString>("style");
+ QTest::newRow("null") << "";
+ QTest::newRow("cleanlooks") << "QCleanlooksStyle";
+}
+
+// void setStyle(QStyle* style) public
+void tst_QGraphicsWidget::setStyle()
+{
+ SubQGraphicsWidget widget;
+ QCleanlooksStyle cleanlooksStyle;
+
+ int oldEventCounts = widget.eventCount;
+
+ QFETCH(QString, style);
+ if (style == "QCleanlooksStyle") {
+ widget.setStyle(&cleanlooksStyle);
+ QCOMPARE(widget.style(), static_cast<QStyle*>(&cleanlooksStyle));
+ } else {
+ widget.setStyle(0);
+ QVERIFY(widget.style() != (QStyle *)0);
+ }
+ QCOMPARE(widget.eventCount, oldEventCounts + 1);
+ QCOMPARE(widget.testAttribute(Qt::WA_SetStyle), !style.isEmpty());
+
+ // cleanup
+ widget.setStyle(0);
+}
+
+void tst_QGraphicsWidget::setTabOrder_data()
+{
+ QTest::addColumn<int>("childrenCount");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("10") << 10;
+}
+
+// void setTabOrder(QGraphicsWidget* first, QGraphicsWidget* second) public
+void tst_QGraphicsWidget::setTabOrder()
+{
+ QFETCH(int, childrenCount);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ QGraphicsWidget *lastItem = 0;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsWidget::setTabOrder(0, 0) is undefined");
+ QGraphicsWidget::setTabOrder(0, 0);
+
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < childrenCount; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget();
+ item->setFocusPolicy(Qt::TabFocus);
+ children.append(item);
+ scene.addItem(item);
+ if (lastItem)
+ QGraphicsWidget::setTabOrder(lastItem, item);
+ lastItem = item;
+ }
+
+ if (!children.isEmpty()) {
+ QGraphicsWidget *first = children.first();
+ view.viewport()->setFocus();
+ QTRY_VERIFY(view.viewport()->hasFocus());
+ first->setFocus();
+ QVERIFY(first->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(view.viewport()->hasFocus());
+
+ int currentItem = 0;
+ while (currentItem < children.count() - 1) {
+ QTest::keyPress(view.viewport(), Qt::Key_Tab);
+ ++currentItem;
+ QVERIFY(children[currentItem % children.size()]->hasFocus());
+ }
+ }
+}
+
+static bool compareFocusChain(QGraphicsView *view, const QList<QGraphicsItem*> &order)
+{
+ QGraphicsScene *scene = view->scene();
+ QStringList actual;
+ QGraphicsItem *oldFocusItem = scene->focusItem();
+ for (int i = 0; i < order.count(); ++i) {
+ QGraphicsItem *focusItem = scene->focusItem();
+ actual << focusItem->data(0).toString();
+ //qDebug() << "i:" << i << "expected:" << QString::number(uint(order.at(i)), 16) << QString::number(uint(focusItem), 16);
+ if (focusItem != order.at(i)) {
+ qDebug() << "actual:" << actual;
+ scene->setFocusItem(oldFocusItem);
+ return false;
+ }
+ if (i < order.count() - 1)
+ QTest::keyPress(view, Qt::Key_Tab);
+ }
+ scene->setFocusItem(oldFocusItem);
+ return true;
+}
+
+void tst_QGraphicsWidget::setTabOrderAndReparent()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ int i;
+ QGraphicsWidget *w1, *w2, *w3, *w4;
+ for (i = 1; i < 4; ++i) {
+ QGraphicsWidget *wid = new QGraphicsWidget;
+ wid->setFocusPolicy(Qt::StrongFocus);
+ wid->setData(0, QString::fromAscii("w%1").arg(i));
+ scene.addItem(wid);
+ if (i == 1)
+ w1 = wid;
+ else if (i == 2)
+ w2 = wid;
+ else if (i == 3)
+ w3 = wid;
+ }
+
+ w1->setFocus();
+ QTRY_VERIFY(w1->hasFocus());
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w1 << w2 << w3));
+
+ QGraphicsWidget *p = new QGraphicsWidget;
+ p->setData(0, QLatin1String("parent"));
+ p->setFocusPolicy(Qt::StrongFocus);
+
+ w1->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w1 << w2 << w3));
+
+ w1->setParentItem(p);
+ w2->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w2 << w3));
+
+ w2->setParentItem(p);
+ w3->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w3));
+ w3->setParentItem(p);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem*>(0));
+
+ scene.addItem(p);
+ p->setFocus();
+
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << p << w1 << w2 << w3));
+ delete p;
+
+ for (i = 1; i < 5; ++i) {
+ QGraphicsWidget *wid = new QGraphicsWidget;
+ wid->setFocusPolicy(Qt::StrongFocus);
+ wid->setData(0, QString::fromAscii("w%1").arg(i));
+ scene.addItem(wid);
+ if (i == 1)
+ w1 = wid;
+ else if (i == 2)
+ w2 = wid;
+ else if (i == 3)
+ w3 = wid;
+ else if (i == 4)
+ w4 = wid;
+ }
+ w4->setParentItem(w1);
+ QGraphicsWidget::setTabOrder(w1, w4);
+ w1->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w1 << w4 << w2 << w3));
+
+ p = new QGraphicsWidget;
+ p->setData(0, QLatin1String("parent"));
+ p->setFocusPolicy(Qt::StrongFocus);
+
+ w1->setParentItem(p);
+ w2->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w2 << w3));
+
+ scene.addItem(p);
+ w2->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w2 << w3 << p << w1 << w4));
+}
+
+void tst_QGraphicsWidget::topLevelWidget_data()
+{
+ QTest::addColumn<QString>("str");
+ QTest::newRow("test one") << "foo";
+}
+
+// QGraphicsWidget* topLevelWidget() const public
+void tst_QGraphicsWidget::topLevelWidget()
+{
+ QFETCH(QString, str);
+ SubQGraphicsWidget widget;
+ QCOMPARE(widget.topLevelWidget(), (QGraphicsWidget *)&widget);
+}
+
+void tst_QGraphicsWidget::unsetLayoutDirection_data()
+{
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::newRow("rtl") << Qt::RightToLeft;
+ QTest::newRow("ltr") << Qt::LeftToRight;
+}
+
+// void unsetLayoutDirection() public
+void tst_QGraphicsWidget::unsetLayoutDirection()
+{
+ QApplication::setLayoutDirection(Qt::LeftToRight);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ SubQGraphicsWidget widget;
+ QCOMPARE(Qt::LeftToRight, widget.layoutDirection());
+
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < 10; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget(&widget);
+ children.append(item);
+ }
+ widget.setLayoutDirection(layoutDirection);
+ widget.unsetLayoutDirection();
+ QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false);
+ for (int i = 0; i < children.count(); ++i) {
+ QCOMPARE(children[i]->layoutDirection(), Qt::LeftToRight);
+ }
+}
+
+void tst_QGraphicsWidget::focusNextPrevChild_data()
+{
+ QTest::addColumn<QString>("str");
+ QTest::newRow("test one") << "foo";
+}
+
+// bool focusNextPrevChild(bool next) protected
+void tst_QGraphicsWidget::focusNextPrevChild()
+{
+ QFETCH(QString, str);
+ SubQGraphicsWidget widget;
+ // ### write test after just calling it stops crashing :)
+ widget.call_focusNextPrevChild(true);
+}
+
+void tst_QGraphicsWidget::verifyFocusChain()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ {
+ // parent/child focus
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ w->setFocusPolicy(Qt::StrongFocus);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ w->setFocus();
+ QVERIFY(w->hasFocus());
+ w->call_focusNextPrevChild(true);
+ QVERIFY(w1_1->hasFocus());
+ delete w;
+ }
+
+ {
+ // delete item in focus chain and verify chain
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ SubQGraphicsWidget *w1_2 = new SubQGraphicsWidget(w);
+ SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ w1_2->setFocusPolicy(Qt::StrongFocus);
+ w1_3->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ w1_1->setFocus();
+ QVERIFY(w1_1->hasFocus());
+ QCOMPARE(w->call_focusNextPrevChild(true), true);
+ QVERIFY(w1_2->hasFocus());
+ QCOMPARE(w->call_focusNextPrevChild(true), true);
+ QVERIFY(w1_3->hasFocus());
+ w1_1->setFocus();
+ delete w1_2;
+ w->call_focusNextPrevChild(true);
+ QVERIFY(w1_3->hasFocus());
+ delete w;
+ }
+ {
+ // parent/child focus
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ w->setFocusPolicy(Qt::StrongFocus);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ w->setFocus();
+ QVERIFY(w->hasFocus());
+ w->call_focusNextPrevChild(true);
+ QVERIFY(w1_1->hasFocus());
+ delete w;
+ }
+ {
+ // remove the tabFocusFirst widget from the scene.
+ QWidget *window = new QWidget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ window->setLayout(layout);
+ QLineEdit *lineEdit = new QLineEdit;
+ layout->addWidget(lineEdit);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ scene.setSceneRect(-20, -20, 200, 50);
+ layout->addWidget(view);
+ view->setMinimumSize(150, 50);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget;
+ w1_1->setData(0, "w1_1");
+ w1_1->setGeometry(0,0,25, 25);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w1_1);
+ SubQGraphicsWidget *w1_2 = new SubQGraphicsWidget;
+ w1_2->setData(0, "w1_2");
+ w1_2->setGeometry(25,0,25, 25);
+ w1_2->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w1_2);
+ window->show();
+ QApplication::setActiveWindow(window);
+ QTest::qWaitForWindowShown(window);
+
+ lineEdit->setFocus();
+ QTRY_VERIFY(lineEdit->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_2->hasFocus());
+
+ // remove the tabFocusFirst and insert new item
+ delete w1_1; // calls _q_removeItemLater
+ SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget;
+ w1_3->setFocusPolicy(Qt::StrongFocus);
+ w1_3->setData(0, "w1_3");
+ w1_3->setGeometry(50,0,25, 25);
+ scene.addItem(w1_3);
+ QTRY_VERIFY(w1_2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(lineEdit->hasFocus());
+ // tabFocusFirst should now point to w1_2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_3->hasFocus());
+ scene.removeItem(w1_2); // does not call _q_removeItemLater
+ delete w1_2; // calls _q_removeItemLater
+
+ SubQGraphicsWidget *w1_4 = new SubQGraphicsWidget;
+ w1_4->setFocusPolicy(Qt::StrongFocus);
+ w1_4->setData(0, "w1_4");
+ w1_4->setGeometry(75,0,25, 25);
+ scene.addItem(w1_4);
+ QTRY_VERIFY(w1_3->hasFocus());
+ QTRY_VERIFY(compareFocusChain(view, QList<QGraphicsItem*>() << w1_3 << w1_4));
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(lineEdit->hasFocus());
+ // tabFocusFirst should now point to w1_3
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_3->hasFocus());
+ QTRY_VERIFY(compareFocusChain(view, QList<QGraphicsItem*>() << w1_3 << w1_4));
+ delete window;
+ }
+}
+
+void tst_QGraphicsWidget::updateFocusChainWhenChildDie()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ // delete item in focus chain with no focus and verify chain
+ SubQGraphicsWidget *parent = new SubQGraphicsWidget(0, Qt::Window);
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ w->resize(50,50);
+ w->resize(100,100);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ w->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ scene.addItem(parent);
+ w1_1->setFocus();
+
+ QVERIFY(w1_1->hasFocus());
+ QWidget myWidget(0);
+ QLineEdit edit(&myWidget);
+ myWidget.show();
+ edit.setFocus();
+ QTRY_VERIFY(edit.hasFocus());
+ delete w1_1;
+ myWidget.hide();
+ w->setParentItem(parent);
+ //We don't crash perfect
+ QVERIFY(w);
+ QTest::mouseMove(view.viewport());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0);
+ QTRY_COMPARE(qApp->activeWindow(), static_cast<QWidget *>(&view));
+ QTRY_COMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(w));
+}
+
+void tst_QGraphicsWidget::sizeHint_data()
+{
+ QTest::addColumn<bool>("layout");
+ QTest::newRow("no layout") << false;
+ QTest::newRow("layout") << true;
+}
+
+// QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const protected
+void tst_QGraphicsWidget::sizeHint()
+{
+ QFETCH(bool, layout);
+ SubQGraphicsWidget widget;
+
+ if (layout) {
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ widget.setLayout(layout);
+ }
+ widget.call_sizeHint(Qt::MinimumSize, QSizeF());
+}
+
+void tst_QGraphicsWidget::consistentPosSizeGeometry_data()
+{
+ QTest::addColumn<QSizeF>("minSize");
+ QTest::addColumn<QSizeF>("maxSize");
+ QTest::addColumn<QRectF>("geometry");
+ QTest::addColumn<QRectF>("expectedGeometry");
+
+ QTest::newRow("size is valid") << QSizeF(0, 0) << QSizeF(200, 200) << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100);
+ QTest::newRow("size is larger than max") << QSizeF(0, 0) << QSizeF(50, 50) << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50);
+ QTest::newRow("size is smaller than min") << QSizeF(50, 50) << QSizeF(150, 150) << QRectF(0, 0, 10, 10) << QRectF(0, 0, 50, 50);
+}
+
+void tst_QGraphicsWidget::consistentPosSizeGeometry()
+{
+ QFETCH(QSizeF, minSize);
+ QFETCH(QSizeF, maxSize);
+ QFETCH(QRectF, geometry);
+ QFETCH(QRectF, expectedGeometry);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *w = new QGraphicsWidget;
+ scene.addItem(w);
+ w->setMinimumSize(minSize);
+ w->setMaximumSize(maxSize);
+ w->setGeometry(geometry);
+ QCOMPARE(w->geometry(), expectedGeometry);
+ QCOMPARE(w->pos(), expectedGeometry.topLeft());
+ QCOMPARE(w->size(), expectedGeometry.size());
+
+ QRectF otherGeom = QRectF(QPointF(12.34,12.34), minSize);
+ w->setGeometry(otherGeom);
+ QCOMPARE(w->geometry(), otherGeom);
+ QCOMPARE(w->pos(), otherGeom.topLeft());
+ QCOMPARE(w->size(), otherGeom.size());
+
+ w->setPos(geometry.topLeft());
+ QCOMPARE(w->geometry().topLeft(), expectedGeometry.topLeft());
+ QCOMPARE(w->pos(), expectedGeometry.topLeft());
+
+ w->resize(geometry.size());
+ QCOMPARE(w->geometry().size(), expectedGeometry.size());
+ QCOMPARE(w->geometry(), expectedGeometry);
+
+ view.show();
+
+}
+
+
+enum WhichSize {
+ MinimumWidth,
+ PreferredWidth,
+ MaximumWidth,
+ MinimumHeight,
+ PreferredHeight,
+ MaximumHeight,
+ MinimumSize,
+ PreferredSize,
+ MaximumSize,
+ MinimumSizeHint,
+ PreferredSizeHint,
+ MaximumSizeHint,
+ Size,
+ None,
+};
+
+typedef QPair<int, QVariant> Inst;
+
+Q_DECLARE_METATYPE(Inst)
+Q_DECLARE_METATYPE(QVector<Inst>)
+
+void tst_QGraphicsWidget::setSizes_data()
+{
+
+ QTest::addColumn<QVector<Inst> >("inputInstructions");
+ QTest::addColumn<QVector<Inst> >("compareInstructions");
+
+ QTest::newRow("minSize1") << (QVector<Inst>() << Inst(Size, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10)))
+ << (QVector<Inst>() << Inst(Size, QSize(25,25)));
+ QTest::newRow("minSize2") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumSize, QSizeF(25, 25)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(25, 25)));
+ QTest::newRow("minWidth1") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)));
+ QTest::newRow("minWidth2") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(25, 20)));
+ QTest::newRow("minHeight1") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)));
+ QTest::newRow("minHeight2") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(20, 25)));
+ QTest::newRow("maxSize1") << (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, 30)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(30, 30)));
+ QTest::newRow("maxSize2") << (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, -1)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(30, 40)));
+ QTest::newRow("maxSize3") << (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, 30)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(40, 30)));
+ QTest::newRow("maxWidth1")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumWidth, 30))
+ << (QVector<Inst>() << Inst(Size, QSizeF(30, 40)));
+ QTest::newRow("maxHeight")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumHeight, 20))
+ << (QVector<Inst>() << Inst(Size, QSizeF(40, 20)));
+ QTest::newRow("unsetMinSize")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MinimumSize, QSizeF(-1, -1)))
+ << (QVector<Inst>() << Inst(MinimumSize, QSizeF(5, 5)));
+ QTest::newRow("unsetMaxSize")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, -1)))
+ << (QVector<Inst>() << Inst(MaximumSize, QSizeF(500, 500)));
+ QTest::newRow("unsetMinSize, expand size to minimumSizeHint") << (QVector<Inst>()
+ << Inst(MinimumSize, QSize(0, 0))
+ << Inst(Size, QSize(1,1))
+ << Inst(MinimumSize, QSize(-1.0, -1.0))
+ )
+ << (QVector<Inst>()
+ << Inst(Size, QSize(5,5))
+ << Inst(MinimumSize, QSize(5,5))
+ );
+
+}
+
+void tst_QGraphicsWidget::setSizes()
+{
+ QFETCH(QVector<Inst>, inputInstructions);
+ QFETCH(QVector<Inst>, compareInstructions);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ SizeHinter *widget = new SizeHinter(0, Qt::Window);
+ QSizeF min = QSizeF(10, 10);
+ QSizeF pref = QSizeF(25, 25);
+ QSizeF max = QSizeF(50, 50);
+
+ int i;
+ for (i = 0; i < inputInstructions.count(); ++i) {
+ Inst input = inputInstructions.at(i);
+
+ // defaults
+ switch (input.first) {
+ case MinimumSize:
+ min = input.second.toSizeF();
+ break;
+ case PreferredSize:
+ pref = input.second.toSizeF();
+ break;
+ case MaximumSize:
+ max = input.second.toSizeF();
+ break;
+ case Size:
+ widget->resize(input.second.toSizeF());
+ break;
+ case MinimumWidth:
+ widget->setMinimumWidth(qreal(input.second.toDouble()));
+ break;
+ case PreferredWidth:
+ widget->setPreferredWidth(qreal(input.second.toDouble()));
+ break;
+ case MaximumWidth:
+ widget->setMaximumWidth(qreal(input.second.toDouble()));
+ break;
+ case MinimumHeight:
+ widget->setMinimumHeight(qreal(input.second.toDouble()));
+ break;
+ case PreferredHeight:
+ widget->setPreferredHeight(qreal(input.second.toDouble()));
+ break;
+ case MaximumHeight:
+ widget->setMaximumHeight(qreal(input.second.toDouble()));
+ break;
+ case MinimumSizeHint:
+ widget->setSizeHint(Qt::MinimumSize, input.second.toSizeF());
+ break;
+ case PreferredSizeHint:
+ widget->setSizeHint(Qt::PreferredSize, input.second.toSizeF());
+ break;
+ case MaximumSizeHint:
+ widget->setSizeHint(Qt::MaximumSize, input.second.toSizeF());
+ break;
+ default:
+ qWarning("instruction not implemented");
+ break;
+ }
+ }
+
+ widget->setMinimumSize(min);
+ widget->setPreferredSize(pref);
+ widget->setMaximumSize(max);
+
+ for (i = 0; i < compareInstructions.count(); ++i) {
+ Inst input = compareInstructions.at(i);
+ switch (input.first) {
+ case MinimumSize:
+ QTRY_COMPARE(widget->minimumSize(), input.second.toSizeF());
+ break;
+ case PreferredSize:
+ QTRY_COMPARE(widget->preferredSize(), input.second.toSizeF());
+ break;
+ case MaximumSize:
+ QTRY_COMPARE(widget->maximumSize(), input.second.toSizeF());
+ break;
+ case Size:
+ QTRY_COMPARE(widget->size(), input.second.toSizeF());
+ break;
+ case MinimumWidth:
+ QTRY_COMPARE(widget->minimumWidth(), qreal(input.second.toDouble()));
+ break;
+ case PreferredWidth:
+ QTRY_COMPARE(widget->preferredWidth(), qreal(input.second.toDouble()));
+ break;
+ case MaximumWidth:
+ QTRY_COMPARE(widget->maximumWidth(), qreal(input.second.toDouble()));
+ break;
+ default:
+ qWarning("instruction not implemented");
+ break;
+ }
+ }
+ delete widget;
+}
+
+void tst_QGraphicsWidget::closePopupOnOutsideClick()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
+ widget->resize(100, 100);
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+
+ QVERIFY(widget->isVisible());
+ QVERIFY(event.isAccepted());
+
+ event.ignore();
+ event.setScenePos(QPointF(150, 150));
+ qApp->sendEvent(&scene, &event);
+
+ QVERIFY(!widget->isVisible());
+ QVERIFY(event.isAccepted());
+}
+
+void tst_QGraphicsWidget::task236127_bspTreeIndexFails()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget->resize(10, 10);
+ widget2->resize(10, 10);
+ widget2->setZValue(1);
+ QCOMPARE(widget2->zValue(), qreal(1));
+ QCOMPARE(widget->zValue(), qreal(0));
+ widget->setData(0, "widget");
+ widget2->setData(0, "widget2");
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+ scene.addItem(widget2);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ QTRY_VERIFY(!scene.itemAt(25, 25));
+ widget->setGeometry(0, 112, 360, 528);
+ QTRY_COMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget);
+ widget2->setGeometry(0, 573, 360, 67);
+ QTRY_COMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget);
+ QTRY_COMPARE(scene.itemAt(50, 585), (QGraphicsItem *)widget2);
+}
+
+void tst_QGraphicsWidget::defaultSize()
+{
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget;
+ widget->setMinimumSize(40, 40);
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QSizeF initialSize = widget->size();
+
+ widget->resize(initialSize);
+ QCOMPARE(widget->geometry().size(), initialSize);
+ widget->setVisible(false);
+ widget->setMinimumSize(10, 10);
+ widget->setPreferredSize(60, 60);
+ widget->setMaximumSize(110, 110);
+ widget->setVisible(true);
+ // should still have its size set to initialsize
+ QTRY_COMPARE(widget->geometry().size(), initialSize);
+
+}
+
+void tst_QGraphicsWidget::explicitMouseGrabber()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+
+ // Grab without scene
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: cannot grab mouse without scene");
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 0);
+
+ // Add to scene
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ // Ungrab while not grabber
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: not a mouse grabber");
+ widget->ungrabMouse();
+
+ // Simple grab with scene
+ QVERIFY(!scene.mouseGrabberItem());
+ widget->grabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+
+ // Grab while grabbing
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: already a mouse grabber");
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+
+ // Add two more widgets to the scene
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ scene.addItem(widget2);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ QGraphicsWidget *widget3 = new QGraphicsWidget;
+ scene.addItem(widget3);
+ EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
+ EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
+
+ widget->setData(0, "widget");
+ widget2->setData(0, "widget2");
+ widget3->setData(0, "widget3");
+
+ // Simple nested grabbing
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ widget2->grabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 3);
+ QCOMPARE(widget2GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->grabMouse();
+ QCOMPARE(widget2UngrabEventSpy.count(), 1);
+ QCOMPARE(widget3GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+ widget3->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 1);
+ QCOMPARE(widget2GrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget2->ungrabMouse();
+ QCOMPARE(widget2UngrabEventSpy.count(), 2);
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Out of order ungrab
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 5);
+ widget2->grabMouse();
+ QCOMPARE(widget2GrabEventSpy.count(), 3);
+ widget3->grabMouse();
+ QCOMPARE(widget3GrabEventSpy.count(), 2);
+ widget2->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 2);
+ QCOMPARE(widget2UngrabEventSpy.count(), 4);
+ QCOMPARE(widgetGrabEventSpy.count(), 6);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+}
+
+void tst_QGraphicsWidget::implicitMouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget->resize(200, 200);
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+ scene.addItem(widget);
+
+ QVERIFY(!scene.mouseGrabberItem());
+
+ // Click on an item, see if gain and lose implicit mouse grab.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+
+ // Click on an item that already grabs the mouse. Shouldn't have any effect.
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Implicit mouse grabber tries to explicitly grab the mouse
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ widget->grabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(widgetUngrabEventSpy.count(), 3);
+
+ // Arrival of a new widget
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget2->resize(200, 200);
+ widget2->setPos(205, 0);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ scene.addItem(widget2);
+
+ // Implicit grab while there's an explicit grab is not possible.
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(250, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ QCOMPARE(widget2GrabEventSpy.count(), 0);
+ QCOMPARE(widget2UngrabEventSpy.count(), 0);
+
+ scene.removeItem(widget);
+ QCOMPARE(widgetUngrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+class GrabOnPressItem : public QGraphicsRectItem
+{
+public:
+ GrabOnPressItem(const QRectF &rect)
+ : QGraphicsRectItem(rect),
+ npress(0), nrelease(0), ndoubleClick(0),
+ ngrab(0), nungrab(0)
+ {
+ }
+ int npress;
+ int nrelease;
+ int ndoubleClick;
+ int ngrab;
+ int nungrab;
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::GrabMouse:
+ ++ngrab;
+ break;
+ case QEvent::UngrabMouse:
+ ++nungrab;
+ break;
+ default:
+ break;
+ }
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ {
+ grabMouse();
+ ++npress;
+ }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ {
+ ungrabMouse();
+ ++nrelease;
+ }
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
+ {
+ ++ndoubleClick;
+ }
+};
+
+void tst_QGraphicsWidget::doubleClickAfterExplicitMouseGrab()
+{
+ QGraphicsScene scene;
+ GrabOnPressItem *item = new GrabOnPressItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->npress, 1);
+ QCOMPARE(item->ngrab, 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(item->nrelease, 1);
+ QCOMPARE(item->nungrab, 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseDoubleClick);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->ndoubleClick, 1);
+ QCOMPARE(item->ngrab, 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(item->nrelease, 2);
+ QCOMPARE(item->nungrab, 2);
+}
+
+void tst_QGraphicsWidget::popupMouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
+ widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget->resize(200, 200);
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+
+ // Simply adding a visible popup to the scene immediately grabs the mouse.
+ scene.addItem(widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+
+ // Hiding it loses the grab again.
+ widget->hide();
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Showing it grabs the mouse again
+ widget->show();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+
+ // Add two popups
+ QGraphicsWidget *widget2 = new QGraphicsWidget(0, Qt::Popup);
+ widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget2->resize(200, 200);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ QGraphicsWidget *widget3 = new QGraphicsWidget(0, Qt::Popup);
+ widget3->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget3->resize(200, 200);
+ EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
+ EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
+
+ // Adding to the scene grabs
+ scene.addItem(widget2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ QCOMPARE(widget2GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+
+ // Adding to the scene grabs again
+ scene.addItem(widget3);
+ QCOMPARE(widget2UngrabEventSpy.count(), 1);
+ QCOMPARE(widget3GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // Hiding the topmost widget causes widget 2 to regain grab.
+ widget3->hide();
+ QCOMPARE(widget2GrabEventSpy.count(), 2);
+ QCOMPARE(widget3UngrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->show();
+ QCOMPARE(widget2UngrabEventSpy.count(), 2);
+ QCOMPARE(widget3GrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // Clicking outside the popup still causes it to close (despite that it's
+ // an explicit mouse grabber).
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(500, 500)); // outside
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!widget3->isVisible());
+ QCOMPARE(widget3UngrabEventSpy.count(), 2);
+ QCOMPARE(widget2GrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ QVERIFY(widget2->isVisible());
+ QVERIFY(widget->isVisible());
+ widget3->show();
+ QCOMPARE(widget3GrabEventSpy.count(), 3);
+ QCOMPARE(widget2UngrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // This is something of a curiosity. What happens if you call
+ // ungrabMouse() on a popup? The answer is - it loses the grab. If you
+ // hide and show the popup again, it will regain the grab.
+ widget3->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 3);
+ QCOMPARE(widget2GrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->hide();
+ widget3->show();
+ QCOMPARE(widget3GrabEventSpy.count(), 4);
+ QCOMPARE(widget2UngrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+}
+
+void tst_QGraphicsWidget::windowFlags_data()
+{
+ QTest::addColumn<int>("inputFlags");
+ QTest::addColumn<int>("outputFlags");
+
+ QTest::newRow("nil") << 0 << 0;
+
+ // Window types
+ QTest::newRow("Qt::Window") << int(Qt::Window)
+ << int(Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ QTest::newRow("Qt::SubWindow") << int(Qt::SubWindow)
+ << int(Qt::SubWindow | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ QTest::newRow("Qt::Dialog") << int(Qt::Dialog)
+ << int(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("Qt::Sheet") << int(Qt::Sheet)
+ << int(Qt::Sheet | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("Qt::Tool") << int(Qt::Tool)
+ << int(Qt::Tool | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
+
+ // Custom window flags
+ QTest::newRow("Qt::FramelessWindowHint") << int(Qt::FramelessWindowHint)
+ << int(Qt::FramelessWindowHint);
+ QTest::newRow("Qt::CustomizeWindowHint") << int(Qt::CustomizeWindowHint)
+ << int(Qt::CustomizeWindowHint);
+}
+
+void tst_QGraphicsWidget::windowFlags()
+{
+ QFETCH(int, inputFlags);
+ QFETCH(int, outputFlags);
+
+ // Construct with flags set already
+ QGraphicsWidget widget(0, Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Set flags after construction
+ QGraphicsWidget widget2;
+ widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Reset flags
+ widget2.setWindowFlags(0);
+ QVERIFY(!widget2.windowFlags());
+
+ // Set flags back again
+ widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Construct with custom flags set already
+ QGraphicsWidget widget3(0, Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget3.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ // Set custom flags after construction
+ QGraphicsWidget widget4;
+ widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ // Reset flags
+ widget4.setWindowFlags(0);
+ QVERIFY(!widget4.windowFlags());
+
+ // Set custom flags back again
+ widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ QGraphicsWidget *widget5 = new QGraphicsWidget;
+ widget5->setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
+ QGraphicsWidget window(0, Qt::Window);
+ widget5->setParentItem(&window);
+ QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
+}
+
+void tst_QGraphicsWidget::shortcutsDeletion()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget->setMinimumSize(40, 40);
+ QWidgetAction *del = new QWidgetAction(widget);
+ del->setIcon(QIcon("edit-delete"));
+ del->setShortcut(Qt::Key_Delete);
+ del->setShortcutContext(Qt::WidgetShortcut);
+ widget2->addAction(del);
+ widget2->addAction(del);
+ delete widget;
+}
+
+class MessUpPainterWidget : public QGraphicsWidget
+{
+public:
+ MessUpPainterWidget(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0)
+ : QGraphicsWidget(parent, wFlags)
+ {}
+
+ void paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->setOpacity(0.0);
+ QGraphicsWidget::paintWindowFrame(painter, option, widget);
+ }
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->drawRect(0, 0, 100, 100);
+ QGraphicsWidget::paint(painter, option, widget);
+ }
+
+};
+
+void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame()
+{
+ MessUpPainterWidget *widget = new MessUpPainterWidget(0, Qt::Window);
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsView view(&scene);
+ scene.addItem(widget);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+}
+
+class ProxyStyle : public QCommonStyle
+{
+public:
+ ProxyStyle(QStyle *proxyStyle) : QCommonStyle()
+ {
+ m_proxyStyle = proxyStyle;
+ }
+
+ int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const
+ {
+ return m_proxyStyle->pixelMetric(metric, option, widget);
+ }
+
+private:
+ QStyle *m_proxyStyle;
+};
+
+class StyledGraphicsWidget : public QGraphicsWidget
+{
+public:
+ StyledGraphicsWidget(bool useOwnStyle) : QGraphicsWidget(), m_style(0) {
+ if (useOwnStyle) {
+ QStyle *oldStyle = style();
+ m_style = new ProxyStyle(oldStyle);
+ setStyle(m_style);
+ }
+
+ style()->pixelMetric(QStyle::PM_SmallIconSize); // crash when style() is still in widgetStyles
+ }
+
+ ~StyledGraphicsWidget() {
+ delete m_style;
+ }
+
+private:
+ QStyle *m_style;
+};
+
+void tst_QGraphicsWidget::task243004_setStyleCrash()
+{
+ QGraphicsItem *item1 = new StyledGraphicsWidget(true);
+ delete item1; // item1 not removed from widgetStyles
+
+ QGraphicsItem *item2 = new StyledGraphicsWidget(false);
+ delete item2;
+}
+
+class GraphicsWidget_task250119 : public QGraphicsWidget
+{
+public:
+ GraphicsWidget_task250119()
+ : shortcutEvents(0)
+ {
+ setFocusPolicy(Qt::StrongFocus);
+ resize(100, 100);
+ }
+
+ int shortcutEvents;
+
+private:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::Shortcut)
+ shortcutEvents++;
+ return QGraphicsWidget::event(event);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ if (hasFocus()) {
+ painter->setPen(QPen(Qt::black, 0, Qt::DashLine));
+ painter->drawRect(rect());
+ }
+ painter->setPen(QPen(Qt::black, 0, Qt::SolidLine));
+ painter->fillRect(rect().adjusted(2, 2, -2, -2), Qt::yellow);
+ painter->drawRect(rect().adjusted(2, 2, -2, -2));
+ }
+};
+
+void tst_QGraphicsWidget::task250119_shortcutContext()
+{
+ QGraphicsScene scene;
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+
+ // *** Event: ***
+
+ GraphicsWidget_task250119 w_event;
+ scene.addItem(&w_event);
+
+ const int id = w_event.grabShortcut(Qt::Key_A, Qt::WidgetWithChildrenShortcut);
+ w_event.setShortcutEnabled(id, true);
+
+ w_event.setFocus();
+ QTest::keyPress(&view, Qt::Key_A);
+ QCOMPARE(w_event.shortcutEvents, 1);
+
+ w_event.clearFocus();
+ QTest::keyPress(&view, Qt::Key_A);
+ QCOMPARE(w_event.shortcutEvents, 1);
+
+ scene.removeItem(&w_event);
+
+
+ // *** Signal: ***
+
+ GraphicsWidget_task250119 w_signal;
+ scene.addItem(&w_signal);
+
+ QAction action(0);
+ action.setShortcut(Qt::Key_B);
+ action.setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ QSignalSpy spy(&action, SIGNAL(triggered()));
+
+ w_signal.addAction(&action);
+
+ w_signal.setFocus();
+ QTest::keyPress(&view, Qt::Key_B);
+ QCOMPARE(spy.count(), 1);
+
+ w_signal.clearFocus();
+ QTest::keyPress(&view, Qt::Key_B);
+ QCOMPARE(spy.count(), 1);
+
+ scene.removeItem(&w_signal);
+}
+
+class ClippingAndTransformsScene : public QGraphicsScene
+{
+public:
+ QList<QGraphicsItem *> drawnItems;
+protected:
+ void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
+ const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
+ {
+ drawnItems.clear();
+ for (int i = 0; i < numItems; ++i)
+ drawnItems << items[i];
+ QGraphicsScene::drawItems(painter, numItems, items, options, widget);
+ }
+};
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+
+ RectWidget(Qt::GlobalColor color, QGraphicsItem *parent=0) : QGraphicsWidget(parent), mColor(color) {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(QBrush(mColor));
+ painter->drawRect(boundingRect());
+ }
+
+ Qt::GlobalColor mColor;
+};
+
+class RectItem : public QGraphicsItem
+{
+public:
+
+ RectItem(Qt::GlobalColor color, QGraphicsItem *parent=0) : QGraphicsItem(parent), mColor(color) {}
+
+ QRectF boundingRect() const
+ {return QRectF(10,10,50,50);}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(QBrush(mColor));
+ painter->drawRect(boundingRect());
+ }
+
+ Qt::GlobalColor mColor;
+};
+
+void tst_QGraphicsWidget::ensureClipping()
+{
+ ClippingAndTransformsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ //A root that clip children
+ RectWidget *clipWidget = new RectWidget(Qt::black);
+ scene.addItem(clipWidget);
+
+ clipWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ //a child
+ RectWidget *childWidget = new RectWidget(Qt::red, clipWidget);
+ clipWidget->setGeometry(QRectF(10, 10, 100, 100));
+ childWidget->setGeometry(QRectF(25, 25, 50, 50));
+
+ //We put a QGraphicsItem to be sure this one is also paint
+ RectItem *childitem = new RectItem(Qt::blue, clipWidget);
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QList<QGraphicsItem *> expected;
+ expected << clipWidget << childWidget << childitem;
+ QTRY_VERIFY(scene.drawnItems.contains(clipWidget));
+ QVERIFY(scene.drawnItems.contains(childWidget));
+ QVERIFY(scene.drawnItems.contains(childitem));
+}
+
+class ItemChangeTester : public QGraphicsWidget
+{
+public:
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsWidget(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+ QList<GraphicsItemChange> changes;
+ QList<QVariant> values;
+ QList<QVariant> oldValues;
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ changes << change;
+ values << value;
+ switch (change) {
+ case QGraphicsItem::ItemPositionChange:
+ oldValues << pos();
+ break;
+ case QGraphicsItem::ItemPositionHasChanged:
+ break;
+ default:
+ break;
+ }
+ return value;
+ }
+};
+
+void tst_QGraphicsWidget::widgetSendsGeometryChanges()
+{
+ ItemChangeTester widget;
+ widget.setFlags(0);
+ widget.clear();
+
+ QPointF pos(10, 10);
+ widget.setPos(pos);
+
+ QCOMPARE(widget.pos(), pos);
+ QCOMPARE(widget.changes.size(), 0);
+
+ widget.setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+ QCOMPARE(widget.changes.size(), 2);
+
+ widget.setPos(QPointF());
+ QCOMPARE(widget.changes.size(), 4);
+
+ QCOMPARE(widget.pos(), QPointF());
+
+ QRectF geometry(20, 20, 50, 50);
+ widget.setGeometry(geometry);
+ QCOMPARE(widget.changes.size(), 6);
+
+ QCOMPARE(widget.geometry(), geometry);
+
+ QCOMPARE(widget.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged);
+}
+
+class HFWWidget : public QGraphicsWidget
+{
+public:
+ HFWWidget() : QGraphicsWidget(0, Qt::Window)
+ {
+ QSizePolicy sp;
+ sp.setHeightForWidth(true);
+ setSizePolicy(sp);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ qreal w = rect().width();
+ QRectF box(0, 0, w, 2400/w);
+ painter->drawRoundRect(box);
+ painter->drawLine(box.topLeft(), box.bottomRight());
+ painter->drawLine(box.bottomLeft(), box.topRight());
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ qreal w = constraint.width();
+ switch (which) {
+ case Qt::MinimumSize:
+ if (w >= 0 && constraint.height() < 0) {
+ // keep the same area of 60x40 = 2400
+ return QSizeF(w, 2400.0/w);
+ } else {
+ return QSizeF(10, 10);
+ }
+ break;
+ case Qt::PreferredSize:
+ return QSizeF(48.989794, 48.989794);
+ default:
+ break;
+ }
+ return QGraphicsWidget::sizeHint(which, constraint);
+ }
+};
+
+void tst_QGraphicsWidget::respectHFW()
+{
+#if defined(Q_OS_WINCE) || defined(Q_OS_MAC) || defined(Q_WS_QWS)
+ qDebug("This test is platform dependent, it fails on wince, mac and qws. Please fix.");
+#else
+ QGraphicsScene scene;
+ HFWWidget *window = new HFWWidget;
+ scene.addItem(window);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->resize(400, 400);
+ view->setSceneRect(-100, -100, 300,300);
+
+ view->show();
+ window->setGeometry(0, 0, 70, 70);
+ QTest::qWaitForWindowShown(view);
+
+ { // here we go - simulate a interactive resize of the window
+ QTest::mouseMove(view, view->mapFromScene(71, 71)); // bottom right corner
+
+ QTest::mousePress(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(71, 71), 200);
+ view->grabMouse();
+ // move both mouse cursor and set correct event in order to emulate resize
+ QTest::mouseMove(view->viewport(), view->mapFromScene(60, 30), 200);
+ QMouseEvent e = QMouseEvent(QEvent::MouseMove,
+ view->mapFromScene(60, 20),
+ Qt::NoButton,
+ Qt::LeftButton,
+ Qt::NoModifier);
+ QApplication::sendEvent(view->viewport(), &e);
+ view->releaseMouse();
+ }
+ const QSizeF winSize = window->size();
+ qreal minHFW = window->effectiveSizeHint(Qt::MinimumSize, QSizeF(winSize.width(), -1)).height();
+ QTRY_VERIFY(qAbs(minHFW - winSize.height()) < 1);
+#endif
+}
+
+class PolishWidget : public QGraphicsWidget
+{
+public:
+
+ PolishWidget(Qt::GlobalColor color, QGraphicsItem *parent=0) :
+ QGraphicsWidget(parent), mColor(color)
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(QBrush(mColor));
+ painter->drawRect(boundingRect());
+ }
+
+ void polishEvent()
+ {
+ if (!parentWidget()) {
+ //We add a child in the polish event for the parent
+ PolishWidget *childWidget = new PolishWidget(Qt::black, this);
+ childWidget->setGeometry(QRectF(10,10,30,30));
+ }
+
+ QGraphicsWidget::polishEvent();
+ mColor = Qt::red;
+ update();
+ numberOfPolish++;
+ }
+
+ static int numberOfPolish;
+
+private:
+ Qt::GlobalColor mColor;
+};
+
+int PolishWidget::numberOfPolish = 0;
+
+void tst_QGraphicsWidget::addChildInpolishEvent()
+{
+ QGraphicsScene scene;
+
+ PolishWidget *parentWidget = new PolishWidget(Qt::white);
+ scene.addItem(parentWidget);
+
+ QGraphicsView view(&scene);
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(PolishWidget::numberOfPolish, 2);
+}
+
+void tst_QGraphicsWidget::polishEvent()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
+ { events << QEvent::Paint; }
+ void polishEvent()
+ { events << QEvent::Polish; }
+ QList<QEvent::Type> events;
+ };
+
+ QGraphicsScene scene;
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Make sure the item is painted.
+ QTRY_VERIFY(widget->events.contains(QEvent::Paint));
+
+ // Make sure the item got polish before paint.
+ QCOMPARE(widget->events.at(0), QEvent::Polish);
+}
+
+void tst_QGraphicsWidget::polishEvent2()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ void polishEvent()
+ { events << QEvent::Polish; }
+ QList<QEvent::Type> events;
+ };
+
+ QGraphicsScene scene;
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ widget->hide();
+ scene.addItem(widget);
+
+ widget->events.clear();
+
+ // Make sure the item got polish event.
+ QTRY_VERIFY(widget->events.contains(QEvent::Polish));
+}
+
+void tst_QGraphicsWidget::autoFillBackground()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QCOMPARE(widget->autoFillBackground(), false);
+ widget->setAutoFillBackground(true);
+ QCOMPARE(widget->autoFillBackground(), true);
+
+ const QColor color(Qt::red);
+ const QRect rect(0, 0, 1, 1);
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+ widget->setGeometry(rect);
+
+ QPalette palette = widget->palette();
+ palette.setColor(QPalette::Window, color);
+ widget->setPalette(palette);
+
+ QImage image(rect.size(), QImage::Format_RGB32);
+ QPainter painter;
+ painter.begin(&image);
+ scene.render(&painter, rect, rect);
+ painter.end();
+ QCOMPARE(image.pixel(0, 0), color.rgb());
+}
+
+void tst_QGraphicsWidget::initialShow()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ MyGraphicsWidget() : repaints(0) {}
+ int repaints;
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) { ++repaints; }
+ void polishEvent() { update(); }
+ };
+
+ QGraphicsScene scene;
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+
+ QGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ scene.addItem(widget);
+
+ QTRY_COMPARE(widget->repaints, 1);
+}
+
+void tst_QGraphicsWidget::initialShow2()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ MyGraphicsWidget() : repaints(0) {}
+ int repaints;
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) { ++repaints; }
+ void polishEvent() { update(); }
+ };
+
+ // Don't let paint events triggered by the windowing system
+ // influence our test case. We're only interested in knowing
+ // whether a QGraphicsWidget generates an additional repaint
+ // on the initial show. Hence create a dummy scenario to find out
+ // how many repaints we should expect.
+ QGraphicsScene dummyScene(0, 0, 200, 200);
+ dummyScene.addItem(new QGraphicsRectItem(0, 0, 100, 100));
+
+ QGraphicsView *dummyView = new QGraphicsView(&dummyScene);
+ dummyView->setWindowFlags(Qt::X11BypassWindowManagerHint);
+ EventSpy paintSpy(dummyView->viewport(), QEvent::Paint);
+ dummyView->show();
+ QTest::qWaitForWindowShown(dummyView);
+ const int expectedRepaintCount = paintSpy.count();
+ delete dummyView;
+ dummyView = 0;
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ widget->resize(100, 100);
+
+ QGraphicsScene scene(0, 0, 200, 200);
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_COMPARE(widget->repaints, expectedRepaintCount);
+}
+
+void tst_QGraphicsWidget::itemChangeEvents()
+{
+ class TestGraphicsWidget : public QGraphicsWidget
+ { public:
+ TestGraphicsWidget() : QGraphicsWidget() {}
+ QHash<QEvent::Type, QVariant> valueDuringEvents;
+ bool event(QEvent *event) {
+ Q_UNUSED(event);
+ switch (event->type()) {
+ case QEvent::EnabledChange: {
+ valueDuringEvents.insert(QEvent::EnabledChange, isEnabled());
+ break;
+ }
+ case QEvent::ParentAboutToChange: {
+ valueDuringEvents.insert(QEvent::ParentAboutToChange, qVariantFromValue(parentItem()));
+ break;
+ }
+ case QEvent::ParentChange: {
+ valueDuringEvents.insert(QEvent::ParentChange, qVariantFromValue(parentItem()));
+ break;
+ }
+ case QEvent::CursorChange: {
+ valueDuringEvents.insert(QEvent::CursorChange, int(cursor().shape()));
+ break;
+ }
+ case QEvent::ToolTipChange: {
+ valueDuringEvents.insert(QEvent::ToolTipChange, toolTip());
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return true;
+ }
+ void showEvent(QShowEvent *event) {
+ Q_UNUSED(event);
+ valueDuringEvents.insert(QEvent::Show, isVisible());
+ }
+ void hideEvent(QHideEvent *event) {
+ Q_UNUSED(event);
+ valueDuringEvents.insert(QEvent::Hide, isVisible());
+ }
+ };
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ scene.addItem(parent);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ TestGraphicsWidget *item = new TestGraphicsWidget;
+ item->setParentItem(parent);
+ // ParentAboutToChange should be triggered before the parent has changed
+ QTRY_COMPARE(qVariantValue<QGraphicsItem *>(item->valueDuringEvents.value(QEvent::ParentAboutToChange)),
+ static_cast<QGraphicsItem *>(0));
+ // ParentChange should be triggered after the parent has changed
+ QTRY_COMPARE(qVariantValue<QGraphicsItem *>(item->valueDuringEvents.value(QEvent::ParentChange)),
+ static_cast<QGraphicsItem *>(parent));
+
+ // ShowEvent should be triggered before the item is shown
+ QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::Show).toBool());
+
+ // HideEvent should be triggered after the item is hidden
+ QVERIFY(item->isVisible());
+ item->setVisible(false);
+ QVERIFY(!item->isVisible());
+ QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::Hide).toBool());
+
+ // CursorChange should be triggered after the cursor has changed
+ item->setCursor(Qt::PointingHandCursor);
+ QTRY_COMPARE(item->valueDuringEvents.value(QEvent::CursorChange).toInt(), int(item->cursor().shape()));
+
+ // ToolTipChange should be triggered after the tooltip has changed
+ item->setToolTip("tooltipText");
+ QTRY_COMPARE(item->valueDuringEvents.value(QEvent::ToolTipChange).toString(), item->toolTip());
+
+ // EnabledChange should be triggered after the enabled state has changed
+ QVERIFY(item->isEnabled());
+ item->setEnabled(false);
+ QVERIFY(!item->isEnabled());
+ QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::EnabledChange).toBool());
+}
+
+void tst_QGraphicsWidget::itemSendGeometryPosChangesDeactivated()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *item = new QGraphicsWidget;
+ scene.addItem(item);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ item->setGeometry(QRectF(0, 0, 50, 50));
+ QTRY_COMPARE(item->geometry(), QRectF(0, 0, 50, 50));
+
+ item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
+ item->setGeometry(QRectF(0, 0, 60, 60));
+ QCOMPARE(item->geometry(), QRectF(0, 0, 60, 60));
+ QCOMPARE(item->pos(), QPointF(0, 0));
+ item->setPos(QPointF(10, 10));
+ QCOMPARE(item->pos(), QPointF(10, 10));
+ QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60));
+
+ item->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
+ item->setGeometry(QRectF(0, 0, 60, 60));
+ QCOMPARE(item->geometry(), QRectF(0, 0, 60, 60));
+ QCOMPARE(item->pos(), QPointF(0, 0));
+ item->setPos(QPointF(10, 10));
+ QCOMPARE(item->pos(), QPointF(10, 10));
+ QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60));
+}
+
+void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget* parent1 = new QGraphicsWidget;
+ QGraphicsWidget* child1_0 = new QGraphicsWidget;
+ QGraphicsWidget* child1_1 = new QGraphicsWidget;
+
+ QGraphicsWidget* parent2 = new QGraphicsWidget;
+
+ // Add the parent and child to the scene.
+ scene.addItem(parent1);
+ child1_0->setParentItem(parent1);
+ child1_1->setParentItem(parent1);
+
+ // Hide and show the child.
+ child1_0->setParentItem(NULL);
+ scene.removeItem(child1_0);
+
+ // Remove parent from the scene.
+ scene.removeItem(parent1);
+
+ delete child1_0;
+ delete child1_1;
+ delete parent1;
+
+ // Add an item into the scene.
+ scene.addItem(parent2);
+
+ //This should not crash
+}
+void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget* item1 = new QGraphicsWidget;
+ QGraphicsWidget* item2 = new QGraphicsWidget;
+ QGraphicsWidget* item3 = new QGraphicsWidget;
+
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ scene.removeItem(item2);
+ scene.removeItem(item1);
+ delete item2;
+ delete item1;
+
+ scene.addItem(item3);
+
+ //This should not crash
+}
+
+QTEST_MAIN(tst_QGraphicsWidget)
+#include "tst_qgraphicswidget.moc"
diff --git a/tests/auto/widgets/itemviews/itemviews.pro b/tests/auto/widgets/itemviews/itemviews.pro
new file mode 100644
index 0000000000..fc338fdb7b
--- /dev/null
+++ b/tests/auto/widgets/itemviews/itemviews.pro
@@ -0,0 +1,33 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qabstractitemview \
+ qabstractproxymodel \
+ qcolumnview \
+ qdatawidgetmapper \
+ qdirmodel \
+ qfileiconprovider \
+ qheaderview \
+ qidentityproxymodel \
+ qitemdelegate \
+ qitemeditorfactory \
+ qitemselectionmodel \
+ qitemview \
+ qlistview \
+ qlistwidget \
+ qsortfilterproxymodel \
+ qstandarditem \
+ qstandarditemmodel \
+ qstringlistmodel \
+ qtableview \
+ qtablewidget \
+ qtreeview \
+ qtreewidget \
+ qtreewidgetitemiterator \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qcolumnview \
+ qlistwidget \
+
+# This test takes too long to run on IRIX, so skip it on that platform
+irix-*:SUBDIRS -= qitemview
+
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/.gitignore b/tests/auto/widgets/itemviews/qabstractitemview/.gitignore
new file mode 100644
index 0000000000..2f9f90e27e
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qabstractitemview/.gitignore
@@ -0,0 +1 @@
+tst_qabstractitemview
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro b/tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro
new file mode 100644
index 0000000000..7f6c2cb65c
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstractitemview.cpp
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
new file mode 100644
index 0000000000..b9c652f1d3
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -0,0 +1,1504 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qabstractitemview.h>
+#include <qstandarditemmodel.h>
+#include <qapplication.h>
+#include <qlistview.h>
+#include <qlistwidget.h>
+#include <qtableview.h>
+#include <qtablewidget.h>
+#include <qtreeview.h>
+#include <qtreewidget.h>
+#include <qheaderview.h>
+#include <qspinbox.h>
+#include <qitemdelegate.h>
+#include <qpushbutton.h>
+#include <qscrollbar.h>
+#include <qboxlayout.h>
+#include <qlineedit.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+// Will try to wait for the condition while allowing event processing
+// for a maximum of 5 seconds.
+#define TRY_COMPARE(expr, expected) \
+ do { \
+ const int step = 50; \
+ for (int q = 0; q < 5000 && ((expr) != (expected)); q+=step) { \
+ QTest::qWait(step); \
+ } \
+ QCOMPARE(expr, expected); \
+ } while(0)
+
+class TestView : public QAbstractItemView
+{
+ Q_OBJECT
+public:
+ inline void tst_dataChanged(const QModelIndex &tl, const QModelIndex &br)
+ { dataChanged(tl, br); }
+ inline void tst_setHorizontalStepsPerItem(int steps)
+ { setHorizontalStepsPerItem(steps); }
+ inline int tst_horizontalStepsPerItem() const
+ { return horizontalStepsPerItem(); }
+ inline void tst_setVerticalStepsPerItem(int steps)
+ { setVerticalStepsPerItem(steps); }
+ inline int tst_verticalStepsPerItem() const
+ { return verticalStepsPerItem(); }
+
+ inline void tst_rowsInserted(const QModelIndex &parent, int start, int end)
+ { rowsInserted(parent, start, end); }
+ inline void tst_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+ { rowsAboutToBeRemoved(parent, start, end); }
+ inline void tst_selectionChanged(const QItemSelection &selected,
+ const QItemSelection &deselected)
+ { selectionChanged(selected, deselected); }
+ inline void tst_currentChanged(const QModelIndex &current, const QModelIndex &previous)
+ { currentChanged(current, previous); }
+ inline void tst_updateEditorData()
+ { updateEditorData(); }
+ inline void tst_updateEditorGeometries()
+ { updateEditorGeometries(); }
+ inline void tst_updateGeometries()
+ { updateGeometries(); }
+ inline void tst_verticalScrollbarAction(int action)
+ { verticalScrollbarAction(action); }
+ inline void tst_horizontalScrollbarAction(int action)
+ { horizontalScrollbarAction(action); }
+ inline void tst_verticalScrollbarValueChanged(int value)
+ { verticalScrollbarValueChanged(value); }
+ inline void tst_horizontalScrollbarValueChanged(int value)
+ { horizontalScrollbarValueChanged(value); }
+ inline void tst_closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
+ { closeEditor(editor, hint); }
+ inline void tst_commitData(QWidget *editor)
+ { commitData(editor); }
+ inline void tst_editorDestroyed(QObject *editor)
+ { editorDestroyed(editor); }
+ enum tst_CursorAction {
+ MoveUp = QAbstractItemView::MoveUp,
+ MoveDown = QAbstractItemView::MoveDown,
+ MoveLeft = QAbstractItemView::MoveLeft,
+ MoveRight = QAbstractItemView::MoveRight,
+ MoveHome = QAbstractItemView::MoveHome,
+ MoveEnd = QAbstractItemView::MoveEnd,
+ MovePageUp = QAbstractItemView::MovePageUp,
+ MovePageDown = QAbstractItemView::MovePageDown,
+ MoveNext = QAbstractItemView::MoveNext,
+ MovePrevious = QAbstractItemView::MovePrevious
+ };
+ inline QModelIndex tst_moveCursor(tst_CursorAction cursorAction,
+ Qt::KeyboardModifiers modifiers)
+ { return moveCursor(QAbstractItemView::CursorAction(cursorAction), modifiers); }
+ inline int tst_horizontalOffset() const
+ { return horizontalOffset(); }
+ inline int tst_verticalOffset() const
+ { return verticalOffset(); }
+ inline bool tst_isIndexHidden(const QModelIndex &index) const
+ { return isIndexHidden(index); }
+ inline void tst_setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
+ { setSelection(rect, command); }
+ inline QRegion tst_visualRegionForSelection(const QItemSelection &selection) const
+ { return visualRegionForSelection(selection); }
+ inline QModelIndexList tst_selectedIndexes() const
+ { return selectedIndexes(); }
+ inline bool tst_edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
+ { return edit(index, trigger, event); }
+ inline QItemSelectionModel::SelectionFlags tst_selectionCommand(const QModelIndex &index,
+ const QEvent *event = 0) const
+ { return selectionCommand(index, event); }
+#ifndef QT_NO_DRAGANDDROP
+ inline void tst_startDrag(Qt::DropActions supportedActions)
+ { startDrag(supportedActions); }
+#endif
+ inline QStyleOptionViewItem tst_viewOptions() const
+ { return viewOptions(); }
+ enum tst_State {
+ NoState = QAbstractItemView::NoState,
+ DraggingState = QAbstractItemView::DraggingState,
+ DragSelectingState = QAbstractItemView::DragSelectingState,
+ EditingState = QAbstractItemView::EditingState,
+ ExpandingState = QAbstractItemView::ExpandingState,
+ CollapsingState = QAbstractItemView::CollapsingState
+ };
+ inline tst_State tst_state() const
+ { return (tst_State)state(); }
+ inline void tst_setState(tst_State state)
+ { setState(QAbstractItemView::State(state)); }
+ inline void tst_startAutoScroll()
+ { startAutoScroll(); }
+ inline void tst_stopAutoScroll()
+ { stopAutoScroll(); }
+ inline void tst_doAutoScroll()
+ { doAutoScroll(); }
+};
+
+class tst_QAbstractItemView : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ tst_QAbstractItemView();
+ virtual ~tst_QAbstractItemView();
+ void basic_tests(TestView *view);
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void getSetCheck();
+ void emptyModels_data();
+ void emptyModels();
+ void setModel_data();
+ void setModel();
+ void noModel();
+ void dragSelect();
+ void rowDelegate();
+ void columnDelegate();
+ void selectAll();
+ void ctrlA();
+ void persistentEditorFocus();
+ void setItemDelegate();
+ void setItemDelegate_data();
+ // The dragAndDrop() test doesn't work, and is thus disabled on Mac and Windows
+ // for the following reasons:
+ // Mac: use of GetCurrentEventButtonState() in QDragManager::drag()
+ // Win: unknown reason
+#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
+#if 0
+ void dragAndDrop();
+ void dragAndDropOnChild();
+#endif
+#endif
+ void noFallbackToRoot();
+ void setCurrentIndex_data();
+ void setCurrentIndex();
+
+ void task221955_selectedEditor();
+ void task250754_fontChange();
+ void task200665_itemEntered();
+ void task257481_emptyEditor();
+ void shiftArrowSelectionAfterScrolling();
+ void shiftSelectionAfterRubberbandSelection();
+ void ctrlRubberbandSelection();
+ void QTBUG6407_extendedSelection();
+ void QTBUG6753_selectOnSelection();
+};
+
+class MyAbstractItemDelegate : public QAbstractItemDelegate
+{
+public:
+ MyAbstractItemDelegate() : QAbstractItemDelegate() {};
+ void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
+ QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
+ const QModelIndex &) const { return new QWidget(parent); }
+};
+
+// Testing get/set functions
+void tst_QAbstractItemView::getSetCheck()
+{
+ QListView view;
+ TestView *obj1 = reinterpret_cast<TestView*>(&view);
+ // QAbstractItemDelegate * QAbstractItemView::itemDelegate()
+ // void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *)
+ MyAbstractItemDelegate *var1 = new MyAbstractItemDelegate;
+ obj1->setItemDelegate(var1);
+ QCOMPARE((QAbstractItemDelegate*)var1, obj1->itemDelegate());
+ obj1->setItemDelegate((QAbstractItemDelegate *)0);
+ QCOMPARE((QAbstractItemDelegate *)0, obj1->itemDelegate());
+ delete var1;
+
+ // EditTriggers QAbstractItemView::editTriggers()
+ // void QAbstractItemView::setEditTriggers(EditTriggers)
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers), obj1->editTriggers());
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged), obj1->editTriggers());
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked), obj1->editTriggers());
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked), obj1->editTriggers());
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed), obj1->editTriggers());
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed), obj1->editTriggers());
+ obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers));
+ QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers), obj1->editTriggers());
+
+ // bool QAbstractItemView::tabKeyNavigation()
+ // void QAbstractItemView::setTabKeyNavigation(bool)
+ obj1->setTabKeyNavigation(false);
+ QCOMPARE(false, obj1->tabKeyNavigation());
+ obj1->setTabKeyNavigation(true);
+ QCOMPARE(true, obj1->tabKeyNavigation());
+
+ // bool QAbstractItemView::dragEnabled()
+ // void QAbstractItemView::setDragEnabled(bool)
+#ifndef QT_NO_DRAGANDDROP
+ obj1->setDragEnabled(false);
+ QCOMPARE(false, obj1->dragEnabled());
+ obj1->setDragEnabled(true);
+ QCOMPARE(true, obj1->dragEnabled());
+#endif
+ // bool QAbstractItemView::alternatingRowColors()
+ // void QAbstractItemView::setAlternatingRowColors(bool)
+ obj1->setAlternatingRowColors(false);
+ QCOMPARE(false, obj1->alternatingRowColors());
+ obj1->setAlternatingRowColors(true);
+ QCOMPARE(true, obj1->alternatingRowColors());
+
+ // State QAbstractItemView::state()
+ // void QAbstractItemView::setState(State)
+ obj1->tst_setState(TestView::tst_State(TestView::NoState));
+ QCOMPARE(TestView::tst_State(TestView::NoState), obj1->tst_state());
+ obj1->tst_setState(TestView::tst_State(TestView::DraggingState));
+ QCOMPARE(TestView::tst_State(TestView::DraggingState), obj1->tst_state());
+ obj1->tst_setState(TestView::tst_State(TestView::DragSelectingState));
+ QCOMPARE(TestView::tst_State(TestView::DragSelectingState), obj1->tst_state());
+ obj1->tst_setState(TestView::tst_State(TestView::EditingState));
+ QCOMPARE(TestView::tst_State(TestView::EditingState), obj1->tst_state());
+ obj1->tst_setState(TestView::tst_State(TestView::ExpandingState));
+ QCOMPARE(TestView::tst_State(TestView::ExpandingState), obj1->tst_state());
+ obj1->tst_setState(TestView::tst_State(TestView::CollapsingState));
+ QCOMPARE(TestView::tst_State(TestView::CollapsingState), obj1->tst_state());
+
+ // QWidget QAbstractScrollArea::viewport()
+ // void setViewport(QWidget*)
+ QWidget *vp = new QWidget;
+ obj1->setViewport(vp);
+ QCOMPARE(vp, obj1->viewport());
+
+ QCOMPARE(16, obj1->autoScrollMargin());
+ obj1->setAutoScrollMargin(20);
+ QCOMPARE(20, obj1->autoScrollMargin());
+ obj1->setAutoScrollMargin(16);
+ QCOMPARE(16, obj1->autoScrollMargin());
+}
+
+tst_QAbstractItemView::tst_QAbstractItemView()
+{
+}
+
+tst_QAbstractItemView::~tst_QAbstractItemView()
+{
+}
+
+void tst_QAbstractItemView::initTestCase()
+{
+#ifdef Q_OS_WINCE_WM
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QAbstractItemView::cleanupTestCase()
+{
+}
+
+void tst_QAbstractItemView::emptyModels_data()
+{
+ QTest::addColumn<QString>("viewType");
+
+ QTest::newRow("QListView") << "QListView";
+ QTest::newRow("QTableView") << "QTableView";
+ QTest::newRow("QTreeView") << "QTreeView";
+ QTest::newRow("QHeaderView") << "QHeaderView";
+}
+
+void tst_QAbstractItemView::emptyModels()
+{
+ QFETCH(QString, viewType);
+
+ TestView *view = 0;
+ if (viewType == "QListView")
+ view = reinterpret_cast<TestView*>(new QListView());
+ else if (viewType == "QTableView")
+ view = reinterpret_cast<TestView*>(new QTableView());
+ else if (viewType == "QTreeView")
+ view = reinterpret_cast<TestView*>(new QTreeView());
+ else if (viewType == "QHeaderView")
+ view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
+ else
+ QVERIFY(0);
+ view->show();
+
+ QVERIFY(!view->model());
+ QVERIFY(!view->selectionModel());
+ //QVERIFY(view->itemDelegate() != 0);
+
+ basic_tests(view);
+ delete view;
+}
+
+void tst_QAbstractItemView::setModel_data()
+{
+ QTest::addColumn<QString>("viewType");
+
+ QTest::newRow("QListView") << "QListView";
+ QTest::newRow("QTableView") << "QTableView";
+ QTest::newRow("QTreeView") << "QTreeView";
+ QTest::newRow("QHeaderView") << "QHeaderView";
+}
+
+void tst_QAbstractItemView::setModel()
+{
+ QFETCH(QString, viewType);
+ TestView *view = 0;
+ if (viewType == "QListView")
+ view = reinterpret_cast<TestView*>(new QListView());
+ else if (viewType == "QTableView")
+ view = reinterpret_cast<TestView*>(new QTableView());
+ else if (viewType == "QTreeView")
+ view = reinterpret_cast<TestView*>(new QTreeView());
+ else if (viewType == "QHeaderView")
+ view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
+ else
+ QVERIFY(0);
+ view->show();
+
+ QStandardItemModel model(20,20);
+ view->setModel(0);
+ view->setModel(&model);
+ basic_tests(view);
+ delete view;
+}
+
+void tst_QAbstractItemView::basic_tests(TestView *view)
+{
+ // setSelectionModel
+ // Will assert as it should
+ //view->setSelectionModel(0);
+ // setItemDelegate
+ //view->setItemDelegate(0);
+ // Will asswert as it should
+
+ // setSelectionMode
+ view->setSelectionMode(QAbstractItemView::SingleSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::SingleSelection);
+ view->setSelectionMode(QAbstractItemView::ContiguousSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::ContiguousSelection);
+ view->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::ExtendedSelection);
+ view->setSelectionMode(QAbstractItemView::MultiSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::MultiSelection);
+ view->setSelectionMode(QAbstractItemView::NoSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::NoSelection);
+
+ // setSelectionBehavior
+ view->setSelectionBehavior(QAbstractItemView::SelectItems);
+ QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectItems);
+ view->setSelectionBehavior(QAbstractItemView::SelectRows);
+ QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectRows);
+ view->setSelectionBehavior(QAbstractItemView::SelectColumns);
+ QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectColumns);
+
+ // setEditTriggers
+ view->setEditTriggers(QAbstractItemView::EditKeyPressed);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::EditKeyPressed);
+ view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::NoEditTriggers);
+ view->setEditTriggers(QAbstractItemView::CurrentChanged);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::CurrentChanged);
+ view->setEditTriggers(QAbstractItemView::DoubleClicked);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::DoubleClicked);
+ view->setEditTriggers(QAbstractItemView::SelectedClicked);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::SelectedClicked);
+ view->setEditTriggers(QAbstractItemView::AnyKeyPressed);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::AnyKeyPressed);
+ view->setEditTriggers(QAbstractItemView::AllEditTriggers);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::AllEditTriggers);
+
+ // setAutoScroll
+ view->setAutoScroll(false);
+ QCOMPARE(view->hasAutoScroll(), false);
+ view->setAutoScroll(true);
+ QCOMPARE(view->hasAutoScroll(), true);
+
+ // setTabKeyNavigation
+ view->setTabKeyNavigation(false);
+ QCOMPARE(view->tabKeyNavigation(), false);
+ view->setTabKeyNavigation(true);
+ QCOMPARE(view->tabKeyNavigation(), true);
+
+#ifndef QT_NO_DRAGANDDROP
+ // setDropIndicatorShown
+ view->setDropIndicatorShown(false);
+ QCOMPARE(view->showDropIndicator(), false);
+ view->setDropIndicatorShown(true);
+ QCOMPARE(view->showDropIndicator(), true);
+
+ // setDragEnabled
+ view->setDragEnabled(false);
+ QCOMPARE(view->dragEnabled(), false);
+ view->setDragEnabled(true);
+ QCOMPARE(view->dragEnabled(), true);
+#endif
+
+ // setAlternatingRowColors
+ view->setAlternatingRowColors(false);
+ QCOMPARE(view->alternatingRowColors(), false);
+ view->setAlternatingRowColors(true);
+ QCOMPARE(view->alternatingRowColors(), true);
+
+ // setIconSize
+ view->setIconSize(QSize(16, 16));
+ QCOMPARE(view->iconSize(), QSize(16, 16));
+ view->setIconSize(QSize(32, 32));
+ QCOMPARE(view->iconSize(), QSize(32, 32));
+ // Should this happen?
+ view->setIconSize(QSize(-1, -1));
+ QCOMPARE(view->iconSize(), QSize(-1, -1));
+
+ QCOMPARE(view->currentIndex(), QModelIndex());
+ QCOMPARE(view->rootIndex(), QModelIndex());
+
+ view->keyboardSearch("");
+ view->keyboardSearch("foo");
+ view->keyboardSearch("1");
+
+ QCOMPARE(view->visualRect(QModelIndex()), QRect());
+
+ view->scrollTo(QModelIndex());
+
+ QCOMPARE(view->sizeHintForIndex(QModelIndex()), QSize());
+ QCOMPARE(view->indexAt(QPoint(-1, -1)), QModelIndex());
+
+ if (!view->model()){
+ QCOMPARE(view->indexAt(QPoint(10, 10)), QModelIndex());
+ QCOMPARE(view->sizeHintForRow(0), -1);
+ QCOMPARE(view->sizeHintForColumn(0), -1);
+ }else if (view->itemDelegate()){
+ view->sizeHintForRow(0);
+ view->sizeHintForColumn(0);
+ }
+ view->openPersistentEditor(QModelIndex());
+ view->closePersistentEditor(QModelIndex());
+
+ view->reset();
+ view->setRootIndex(QModelIndex());
+ view->doItemsLayout();
+ view->selectAll();
+ view->edit(QModelIndex());
+ view->clearSelection();
+ view->setCurrentIndex(QModelIndex());
+
+ // protected methods
+ view->tst_dataChanged(QModelIndex(), QModelIndex());
+ view->tst_rowsInserted(QModelIndex(), -1, -1);
+ view->tst_rowsAboutToBeRemoved(QModelIndex(), -1, -1);
+ view->tst_selectionChanged(QItemSelection(), QItemSelection());
+ if (view->model()){
+ view->tst_currentChanged(QModelIndex(), QModelIndex());
+ view->tst_currentChanged(QModelIndex(), view->model()->index(0,0));
+ }
+ view->tst_updateEditorData();
+ view->tst_updateEditorGeometries();
+ view->tst_updateGeometries();
+ view->tst_verticalScrollbarAction(QAbstractSlider::SliderSingleStepAdd);
+ view->tst_horizontalScrollbarAction(QAbstractSlider::SliderSingleStepAdd);
+ view->tst_verticalScrollbarValueChanged(10);
+ view->tst_horizontalScrollbarValueChanged(10);
+ view->tst_closeEditor(0, QAbstractItemDelegate::NoHint);
+ view->tst_commitData(0);
+ view->tst_editorDestroyed(0);
+
+ view->tst_setHorizontalStepsPerItem(2);
+ view->tst_horizontalStepsPerItem();
+ view->tst_setVerticalStepsPerItem(2);
+ view->tst_verticalStepsPerItem();
+
+ // Will assert as it should
+ // view->setIndexWidget(QModelIndex(), 0);
+
+ view->tst_moveCursor(TestView::MoveUp, Qt::NoModifier);
+ view->tst_horizontalOffset();
+ view->tst_verticalOffset();
+
+// view->tst_isIndexHidden(QModelIndex()); // will (correctly) assert
+ if(view->model())
+ view->tst_isIndexHidden(view->model()->index(0,0));
+
+ view->tst_setSelection(QRect(0, 0, 10, 10), QItemSelectionModel::ClearAndSelect);
+ view->tst_setSelection(QRect(-1, -1, -1, -1), QItemSelectionModel::ClearAndSelect);
+ view->tst_visualRegionForSelection(QItemSelection());
+ view->tst_selectedIndexes();
+
+ view->tst_edit(QModelIndex(), QAbstractItemView::NoEditTriggers, 0);
+
+ view->tst_selectionCommand(QModelIndex(), 0);
+
+#ifndef QT_NO_DRAGANDDROP
+ if (!view->model())
+ view->tst_startDrag(Qt::CopyAction);
+
+ view->tst_viewOptions();
+
+ view->tst_setState(TestView::NoState);
+ QVERIFY(view->tst_state()==TestView::NoState);
+ view->tst_setState(TestView::DraggingState);
+ QVERIFY(view->tst_state()==TestView::DraggingState);
+ view->tst_setState(TestView::DragSelectingState);
+ QVERIFY(view->tst_state()==TestView::DragSelectingState);
+ view->tst_setState(TestView::EditingState);
+ QVERIFY(view->tst_state()==TestView::EditingState);
+ view->tst_setState(TestView::ExpandingState);
+ QVERIFY(view->tst_state()==TestView::ExpandingState);
+ view->tst_setState(TestView::CollapsingState);
+ QVERIFY(view->tst_state()==TestView::CollapsingState);
+#endif
+
+ view->tst_startAutoScroll();
+ view->tst_stopAutoScroll();
+ view->tst_doAutoScroll();
+
+ // testing mouseFoo and key functions
+// QTest::mousePress(view, Qt::LeftButton, Qt::NoModifier, QPoint(0,0));
+// mouseMove(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+// QTest::mouseRelease(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+// QTest::mouseClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+// mouseDClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+// QTest::keyClick(view, Qt::Key_A);
+}
+
+void tst_QAbstractItemView::noModel()
+{
+ // From task #85415
+
+ QStandardItemModel model(20,20);
+ QTreeView view;
+
+ view.setModel(&model);
+ // Make the viewport smaller than the contents, so that we can scroll
+ view.resize(100,100);
+ view.show();
+
+ // make sure that the scrollbars are not at value 0
+ view.scrollTo(view.model()->index(10,10));
+ QApplication::processEvents();
+
+ view.setModel(0);
+ // Due to the model is removed, this will generate a valueChanged signal on both scrollbars. (value to 0)
+ QApplication::processEvents();
+ QCOMPARE(view.model(), (QAbstractItemModel*)0);
+}
+
+void tst_QAbstractItemView::dragSelect()
+{
+ // From task #86108
+
+ QStandardItemModel model(64,64);
+
+ QTableView view;
+ view.setModel(&model);
+ view.setVisible(true);
+
+ const int delay = 2;
+ for (int i = 0; i < 2; ++i) {
+ bool tracking = (i == 1);
+ view.setMouseTracking(false);
+ QTest::mouseMove(&view, QPoint(0, 0), delay);
+ view.setMouseTracking(tracking);
+ QTest::mouseMove(&view, QPoint(50, 50), delay);
+ QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
+ }
+}
+
+void tst_QAbstractItemView::rowDelegate()
+{
+ QStandardItemModel model(4,4);
+ MyAbstractItemDelegate delegate;
+
+ QTableView view;
+ view.setModel(&model);
+ view.setItemDelegateForRow(3, &delegate);
+ view.show();
+
+ QModelIndex index = model.index(3, 0);
+ view.openPersistentEditor(index);
+ QWidget *w = view.indexWidget(index);
+ QVERIFY(w);
+ QCOMPARE(w->metaObject()->className(), "QWidget");
+}
+
+void tst_QAbstractItemView::columnDelegate()
+{
+ QStandardItemModel model(4,4);
+ MyAbstractItemDelegate delegate;
+
+ QTableView view;
+ view.setModel(&model);
+ view.setItemDelegateForColumn(3, &delegate);
+ view.show();
+
+ QModelIndex index = model.index(0, 3);
+ view.openPersistentEditor(index);
+ QWidget *w = view.indexWidget(index);
+ QVERIFY(w);
+ QCOMPARE(w->metaObject()->className(), "QWidget");
+}
+
+void tst_QAbstractItemView::selectAll()
+{
+ QStandardItemModel model(4,4);
+ QTableView view;
+ view.setModel(&model);
+
+ TestView *tst_view = (TestView*)&view;
+
+ QCOMPARE(tst_view->tst_selectedIndexes().count(), 0);
+ view.selectAll();
+ QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4);
+}
+
+void tst_QAbstractItemView::ctrlA()
+{
+ QStandardItemModel model(4,4);
+ QTableView view;
+ view.setModel(&model);
+
+ TestView *tst_view = (TestView*)&view;
+
+ QCOMPARE(tst_view->tst_selectedIndexes().count(), 0);
+ QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4);
+}
+
+void tst_QAbstractItemView::persistentEditorFocus()
+{
+ // one row, three columns
+ QStandardItemModel model(1, 3);
+ for(int i = 0; i < model.columnCount(); ++i)
+ model.setData(model.index(0, i), i);
+ QTableView view;
+ view.setModel(&model);
+
+ view.openPersistentEditor(model.index(0, 1));
+ view.openPersistentEditor(model.index(0, 2));
+
+ //these are spinboxes because we put numbers inside
+ QList<QSpinBox*> list = qFindChildren<QSpinBox*>(view.viewport());
+ QCOMPARE(list.count(), 2); //these should be the 2 editors
+
+ view.setCurrentIndex(model.index(0, 0));
+ QCOMPARE(view.currentIndex(), model.index(0, 0));
+ view.show();
+ QTRY_VERIFY(view.isVisible());
+
+ for (int i = 0; i < list.count(); ++i) {
+ TRY_COMPARE(list.at(i)->isVisible(), true);
+ QPoint p = QPoint(5, 5);
+ QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton,
+ Qt::LeftButton, Qt::NoModifier);
+ qApp->sendEvent(list.at(i), &mouseEvent);
+ if (!qApp->focusWidget())
+ QSKIP("Some window managers don't handle focus that well", SkipAll);
+ QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget *>(list.at(i)));
+ }
+}
+
+
+#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
+
+#if 0
+
+static void sendMouseMove(QWidget *widget, QPoint pos = QPoint())
+{
+ if (pos.isNull())
+ pos = widget->rect().center();
+ QMouseEvent event(QEvent::MouseMove, pos, widget->mapToGlobal(pos), Qt::NoButton, 0, 0);
+ QCursor::setPos(widget->mapToGlobal(pos));
+ qApp->processEvents();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(widget);
+#endif
+ QApplication::sendEvent(widget, &event);
+}
+
+static void sendMousePress(
+ QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton)
+{
+ if (pos.isNull())
+ pos = widget->rect().center();
+ QMouseEvent event(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+static void sendMouseRelease(
+ QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton)
+{
+ if (pos.isNull())
+ pos = widget->rect().center();
+ QMouseEvent event(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+class DnDTestModel : public QStandardItemModel
+{
+ Q_OBJECT
+ bool dropMimeData(const QMimeData *md, Qt::DropAction action, int r, int c, const QModelIndex &p)
+ {
+ dropAction_result = action;
+ QStandardItemModel::dropMimeData(md, action, r, c, p);
+ return true;
+ }
+ Qt::DropActions supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; }
+
+ Qt::DropAction dropAction_result;
+public:
+ DnDTestModel() : QStandardItemModel(20, 20), dropAction_result(Qt::IgnoreAction) {
+ for (int i = 0; i < rowCount(); ++i)
+ setData(index(i, 0), QString("%1").arg(i));
+ }
+ Qt::DropAction dropAction() const { return dropAction_result; }
+};
+
+class DnDTestView : public QTreeView
+{
+ Q_OBJECT
+
+ QPoint dropPoint;
+ Qt::DropAction dropAction;
+
+ void dragEnterEvent(QDragEnterEvent *event)
+ {
+ QAbstractItemView::dragEnterEvent(event);
+ }
+
+ void dropEvent(QDropEvent *event)
+ {
+ event->setDropAction(dropAction);
+ QTreeView::dropEvent(event);
+ }
+
+ void timerEvent(QTimerEvent *event)
+ {
+ killTimer(event->timerId());
+ sendMouseMove(this, dropPoint);
+ sendMouseRelease(this);
+ }
+
+ void mousePressEvent(QMouseEvent *e)
+ {
+ QTreeView::mousePressEvent(e);
+
+ startTimer(0);
+ setState(DraggingState);
+ startDrag(dropAction);
+ }
+
+public:
+ DnDTestView(Qt::DropAction dropAction, QAbstractItemModel *model)
+ : dropAction(dropAction)
+ {
+ header()->hide();
+ setModel(model);
+ setDragDropMode(QAbstractItemView::DragDrop);
+ setAcceptDrops(true);
+ setDragEnabled(true);
+ }
+
+ void dragAndDrop(QPoint drag, QPoint drop)
+ {
+ dropPoint = drop;
+ setCurrentIndex(indexAt(drag));
+ sendMousePress(viewport(), drag);
+ }
+};
+
+class DnDTestWidget : public QWidget
+{
+ Q_OBJECT
+
+ Qt::DropAction dropAction_request;
+ Qt::DropAction dropAction_result;
+ QWidget *dropTarget;
+
+ void timerEvent(QTimerEvent *event)
+ {
+ killTimer(event->timerId());
+ sendMouseMove(dropTarget);
+ sendMouseRelease(dropTarget);
+ }
+
+ void mousePressEvent(QMouseEvent *)
+ {
+ QDrag *drag = new QDrag(this);
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData("application/x-qabstractitemmodeldatalist", QByteArray(""));
+ drag->setMimeData(mimeData);
+ startTimer(0);
+ dropAction_result = drag->start(dropAction_request);
+ }
+
+public:
+ Qt::DropAction dropAction() const { return dropAction_result; }
+
+ void dragAndDrop(QWidget *dropTarget, Qt::DropAction dropAction)
+ {
+ this->dropTarget = dropTarget;
+ dropAction_request = dropAction;
+ sendMousePress(this);
+ }
+};
+
+void tst_QAbstractItemView::dragAndDrop()
+{
+ // From Task 137729
+
+#ifdef Q_WS_QWS
+ QSKIP("Embedded drag-and-drop not good enough yet...", SkipAll);
+#endif
+
+ const int attempts = 10;
+ int successes = 0;
+ for (int i = 0; i < attempts; ++i) {
+ Qt::DropAction dropAction = Qt::MoveAction;
+
+ DnDTestModel model;
+ DnDTestView view(dropAction, &model);
+ DnDTestWidget widget;
+
+ const int size = 200;
+ widget.setFixedSize(size, size);
+ view.setFixedSize(size, size);
+
+ widget.move(0, 0);
+ view.move(int(size * 1.5), int(size * 1.5));
+
+ widget.show();
+ view.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&widget);
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ widget.dragAndDrop(&view, dropAction);
+ if (model.dropAction() == dropAction
+ && widget.dropAction() == dropAction)
+ ++successes;
+ }
+
+ if (successes < attempts) {
+ QString msg = QString("# successes (%1) < # attempts (%2)").arg(successes).arg(attempts);
+ QWARN(msg.toLatin1());
+ }
+ QVERIFY(successes > 0); // allow for some "event unstability" (i.e. unless
+ // successes == 0, QAbstractItemView is probably ok!)
+}
+
+void tst_QAbstractItemView::dragAndDropOnChild()
+{
+#ifdef Q_WS_QWS
+ QSKIP("Embedded drag-and-drop not good enough yet...", SkipAll);
+#endif
+
+ const int attempts = 10;
+ int successes = 0;
+ for (int i = 0; i < attempts; ++i) {
+ Qt::DropAction dropAction = Qt::MoveAction;
+
+ DnDTestModel model;
+ QModelIndex parent = model.index(0, 0);
+ model.insertRow(0, parent);
+ model.insertColumn(0, parent);
+ QModelIndex child = model.index(0, 0, parent);
+ model.setData(child, "child");
+ QCOMPARE(model.rowCount(parent), 1);
+ DnDTestView view(dropAction, &model);
+ view.setExpanded(parent, true);
+ view.setDragDropMode(QAbstractItemView::InternalMove);
+
+ const int size = 200;
+ view.setFixedSize(size, size);
+ view.move(int(size * 1.5), int(size * 1.5));
+ view.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ view.dragAndDrop(view.visualRect(parent).center(),
+ view.visualRect(child).center());
+ if (model.dropAction() == dropAction)
+ ++successes;
+ }
+
+ QVERIFY(successes == 0);
+}
+
+#endif // 0
+#endif // !Q_OS_MAC && !Q_OS_WIN
+
+class TestModel : public QStandardItemModel
+{
+public:
+ TestModel(int rows, int columns) : QStandardItemModel(rows, columns)
+ {
+ setData_count = 0;
+ }
+
+ virtual bool setData(const QModelIndex &/*index*/, const QVariant &/*value*/, int /*role = Qt::EditRole*/)
+ {
+ ++setData_count;
+ return true;
+ }
+
+ int setData_count;
+};
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+void tst_QAbstractItemView::setItemDelegate_data()
+{
+ // default is rows, a -1 will switch to columns
+ QTest::addColumn<IntList>("rowsOrColumnsWithDelegate");
+ QTest::addColumn<QPoint>("cellToEdit");
+ QTest::newRow("4 columndelegates")
+ << (IntList() << -1 << 0 << 1 << 2 << 3)
+ << QPoint(0, 0);
+ QTest::newRow("2 identical rowdelegates on the same row")
+ << (IntList() << 0 << 0)
+ << QPoint(0, 0);
+ QTest::newRow("2 identical columndelegates on the same column")
+ << (IntList() << -1 << 2 << 2)
+ << QPoint(2, 0);
+ QTest::newRow("2 duplicate delegates, 1 row and 1 column")
+ << (IntList() << 0 << -1 << 2)
+ << QPoint(2, 0);
+ QTest::newRow("4 duplicate delegates, 2 row and 2 column")
+ << (IntList() << 0 << 0 << -1 << 2 << 2)
+ << QPoint(2, 0);
+
+}
+
+void tst_QAbstractItemView::setItemDelegate()
+{
+ QFETCH(IntList, rowsOrColumnsWithDelegate);
+ QFETCH(QPoint, cellToEdit);
+ QTableView v;
+ QItemDelegate *delegate = new QItemDelegate(&v);
+ TestModel model(5, 5);
+ v.setModel(&model);
+
+ bool row = true;
+ foreach (int rc, rowsOrColumnsWithDelegate) {
+ if (rc == -1) {
+ row = !row;
+ } else {
+ if (row) {
+ v.setItemDelegateForRow(rc, delegate);
+ } else {
+ v.setItemDelegateForColumn(rc, delegate);
+ }
+ }
+ }
+ v.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&v);
+ QCursor::setPos(v.geometry().center());
+ QApplication::syncX();
+#endif
+ QTest::qWait(20);
+ QApplication::setActiveWindow(&v);
+
+ QModelIndex index = model.index(cellToEdit.y(), cellToEdit.x());
+ v.edit(index);
+
+ // This will close the editor
+ TRY_COMPARE(QApplication::focusWidget() == 0, false);
+ QWidget *editor = QApplication::focusWidget();
+ QVERIFY(editor);
+ editor->hide();
+ delete editor;
+ QCOMPARE(model.setData_count, 1);
+ delete delegate;
+}
+
+void tst_QAbstractItemView::noFallbackToRoot()
+{
+ QStandardItemModel model(0, 1);
+ for (int i = 0; i < 5; ++i)
+ model.appendRow(new QStandardItem("top" + QString::number(i)));
+ QStandardItem *par1 = model.item(1);
+ for (int j = 0; j < 15; ++j)
+ par1->appendRow(new QStandardItem("sub" + QString::number(j)));
+ QStandardItem *par2 = par1->child(2);
+ for (int k = 0; k < 10; ++k)
+ par2->appendRow(new QStandardItem("bot" + QString::number(k)));
+ QStandardItem *it1 = par2->child(5);
+
+ QModelIndex parent1 = model.indexFromItem(par1);
+ QModelIndex parent2 = model.indexFromItem(par2);
+ QModelIndex item1 = model.indexFromItem(it1);
+
+ QTreeView v;
+ v.setModel(&model);
+ v.setRootIndex(parent1);
+ v.setCurrentIndex(item1);
+ QCOMPARE(v.currentIndex(), item1);
+ QVERIFY(model.removeRows(0, 10, parent2));
+ QCOMPARE(v.currentIndex(), parent2);
+ QVERIFY(model.removeRows(0, 15, parent1));
+ QCOMPARE(v.currentIndex(), QModelIndex());
+}
+
+void tst_QAbstractItemView::setCurrentIndex_data()
+{
+ QTest::addColumn<QString>("viewType");
+ QTest::addColumn<int>("itemFlags");
+ QTest::addColumn<bool>("result");
+
+ QStringList widgets;
+ widgets << "QListView" << "QTreeView" << "QHeaderView" << "QTableView";
+
+ foreach(QString widget, widgets) {
+ QTest::newRow((widget+QLatin1String(": no flags")).toLocal8Bit().constData())
+ << widget << (int)0 << false;
+ QTest::newRow((widget+QLatin1String(": checkable")).toLocal8Bit().constData())
+ << widget << (int)Qt::ItemIsUserCheckable << false;
+ QTest::newRow((widget+QLatin1String(": selectable")).toLocal8Bit().constData())
+ << widget << (int)Qt::ItemIsSelectable << false;
+ QTest::newRow((widget+QLatin1String(": enabled")).toLocal8Bit().constData())
+ << widget << (int)Qt::ItemIsEnabled << true;
+ QTest::newRow((widget+QLatin1String(": enabled|selectable")).toLocal8Bit().constData())
+ << widget << (int)(Qt::ItemIsSelectable|Qt::ItemIsEnabled) << true;
+ }
+}
+
+void tst_QAbstractItemView::setCurrentIndex()
+{
+ QFETCH(QString, viewType);
+ QFETCH(int, itemFlags);
+ QFETCH(bool, result);
+
+ TestView *view = 0;
+ if (viewType == "QListView")
+ view = reinterpret_cast<TestView*>(new QListView());
+ else if (viewType == "QTableView")
+ view = reinterpret_cast<TestView*>(new QTableView());
+ else if (viewType == "QTreeView")
+ view = reinterpret_cast<TestView*>(new QTreeView());
+ else if (viewType == "QHeaderView")
+ view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
+ else
+ QVERIFY(0);
+ view->show();
+
+ QStandardItemModel *model = new QStandardItemModel(view);
+ QStandardItem *item = new QStandardItem("first item");
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ model->appendRow(item);
+
+ item = new QStandardItem("test item");
+ item->setFlags(Qt::ItemFlags(itemFlags));
+ model->appendRow(item);
+
+ view->setModel(model);
+
+ view->setCurrentIndex(model->index(0,0));
+ QVERIFY(view->currentIndex() == model->index(0,0));
+ view->setCurrentIndex(model->index(1,0));
+ QVERIFY(view->currentIndex() == model->index(result ? 1 : 0,0));
+
+ delete view;
+}
+
+void tst_QAbstractItemView::task221955_selectedEditor()
+{
+ QPushButton *button;
+
+ QTreeWidget tree;
+ tree.setColumnCount(2);
+
+ tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Foo" <<"1"));
+ tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Bar" <<"2"));
+ tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Baz" <<"3"));
+
+ QTreeWidgetItem *dummy = new QTreeWidgetItem();
+ tree.addTopLevelItem(dummy);
+ tree.setItemWidget(dummy, 0, button = new QPushButton("More..."));
+ button->setAutoFillBackground(true); // as recommended in doc
+
+ tree.show();
+ tree.setFocus();
+ tree.setCurrentIndex(tree.model()->index(1,0));
+ QTest::qWait(100);
+ QApplication::setActiveWindow(&tree);
+
+ QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
+
+ //We set the focus to the button, the index need to be selected
+ button->setFocus();
+ QTest::qWait(100);
+ QVERIFY(tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
+
+ tree.setCurrentIndex(tree.model()->index(1,0));
+ QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
+
+ //Same thing but with the flag NoSelection, nothing can be selected.
+ tree.setFocus();
+ tree.setSelectionMode(QAbstractItemView::NoSelection);
+ tree.clearSelection();
+ QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty());
+ QTest::qWait(10);
+ button->setFocus();
+ QTest::qWait(50);
+ QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty());
+}
+
+void tst_QAbstractItemView::task250754_fontChange()
+{
+ QString app_css = qApp->styleSheet();
+ qApp->setStyleSheet("/* */");
+
+ QWidget w;
+ QTreeView tree(&w);
+ QVBoxLayout *vLayout = new QVBoxLayout(&w);
+ vLayout->addWidget(&tree);
+
+ QStandardItemModel *m = new QStandardItemModel(this);
+ for (int i=0; i<5; ++i) {
+ QStandardItem *item = new QStandardItem(QString("Item number %1").arg(i));
+ for (int j=0; j<5; ++j) {
+ QStandardItem *child = new QStandardItem(QString("Child Item number %1").arg(j));
+ item->setChild(j, 0, child);
+ }
+ m->setItem(i, 0, item);
+ }
+ tree.setModel(m);
+
+ w.show();
+ w.resize(150,240);
+ QTest::qWait(30);
+ QFont font = tree.font();
+ font.setPixelSize(10);
+ tree.setFont(font);
+ QTRY_VERIFY(!tree.verticalScrollBar()->isVisible());
+
+ font.setPixelSize(60);
+ tree.setFont(font);
+ //now with the huge items, the scrollbar must be visible
+ QTRY_VERIFY(tree.verticalScrollBar()->isVisible());
+
+ qApp->setStyleSheet(app_css);
+}
+
+void tst_QAbstractItemView::task200665_itemEntered()
+{
+#ifdef Q_OS_WINCE_WM
+ QSKIP("On Windows Mobile the mouse tracking is unavailable at the moment", SkipAll);
+#endif
+ //we test that view will emit entered
+ //when the scrollbar move but not the mouse itself
+ QStandardItemModel model(1000,1);
+ QListView view;
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(200);
+ QRect rect = view.visualRect(model.index(0,0));
+ QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) );
+ QSignalSpy spy(&view, SIGNAL(entered(QModelIndex)));
+ view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
+
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QAbstractItemView::task257481_emptyEditor()
+{
+ QIcon icon = qApp->style()->standardIcon(QStyle::SP_ComputerIcon);
+
+ QStandardItemModel model;
+
+ model.appendRow( new QStandardItem(icon, QString()) );
+ model.appendRow( new QStandardItem(icon, "Editor works") );
+ model.appendRow( new QStandardItem( QString() ) );
+
+ QTreeView treeView;
+ treeView.setRootIsDecorated(false);
+ treeView.setModel(&model);
+ treeView.show();
+
+ treeView.edit(model.index(0,0));
+ QList<QLineEdit *> lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
+ QCOMPARE(lineEditors.count(), 1);
+ QVERIFY(!lineEditors.first()->size().isEmpty());
+
+ QTest::qWait(30);
+
+ treeView.edit(model.index(1,0));
+ lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
+ QCOMPARE(lineEditors.count(), 1);
+ QVERIFY(!lineEditors.first()->size().isEmpty());
+
+ QTest::qWait(30);
+
+ treeView.edit(model.index(2,0));
+ lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
+ QCOMPARE(lineEditors.count(), 1);
+ QVERIFY(!lineEditors.first()->size().isEmpty());
+}
+
+void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling()
+{
+ QStandardItemModel model;
+ for (int i=0; i<10; ++i) {
+ QStandardItem *item = new QStandardItem(QString("%1").arg(i));
+ model.setItem(i, 0, item);
+ }
+
+ QListView view;
+ view.setFixedSize(150, 250);
+ view.setFlow(QListView::LeftToRight);
+ view.setGridSize(QSize(100, 100));
+ view.setSelectionMode(QListView::ExtendedSelection);
+ view.setViewMode(QListView::IconMode);
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(30);
+
+ QModelIndex index0 = model.index(0, 0);
+ QModelIndex index1 = model.index(1, 0);
+ QModelIndex index9 = model.index(9, 0);
+
+ view.selectionModel()->setCurrentIndex(index0, QItemSelectionModel::NoUpdate);
+ QCOMPARE(view.currentIndex(), index0);
+
+ view.scrollTo(index9);
+ QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
+
+ QCOMPARE(view.currentIndex(), index1);
+ QModelIndexList selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 2);
+ QVERIFY(selected.contains(index0));
+ QVERIFY(selected.contains(index1));
+}
+
+void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection()
+{
+ QStandardItemModel model;
+ for (int i=0; i<3; ++i) {
+ QStandardItem *item = new QStandardItem(QString("%1").arg(i));
+ model.setItem(i, 0, item);
+ }
+
+ QListView view;
+ view.setFixedSize(150, 450);
+ view.setFlow(QListView::LeftToRight);
+ view.setGridSize(QSize(100, 100));
+ view.setSelectionMode(QListView::ExtendedSelection);
+ view.setViewMode(QListView::IconMode);
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(30);
+
+ QModelIndex index0 = model.index(0, 0);
+ QModelIndex index1 = model.index(1, 0);
+ QModelIndex index2 = model.index(2, 0);
+
+ view.setCurrentIndex(index0);
+ QCOMPARE(view.currentIndex(), index0);
+
+ // Determine the points where the rubberband selection starts and ends
+ QPoint pressPos = view.visualRect(index1).bottomRight() + QPoint(1, 1);
+ QPoint releasePos = view.visualRect(index1).center();
+ QVERIFY(!view.indexAt(pressPos).isValid());
+ QCOMPARE(view.indexAt(releasePos), index1);
+
+ // Select item 1 using a rubberband selection
+ // The mouse move event has to be created manually because the QTest framework does not
+ // contain a function for mouse moves with buttons pressed
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos);
+ QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
+ bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
+ QVERIFY(moveEventReceived);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos);
+ QCOMPARE(view.currentIndex(), index1);
+
+ // Shift-click item 2
+ QPoint item2Pos = view.visualRect(index2).center();
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, item2Pos);
+ QCOMPARE(view.currentIndex(), index2);
+
+ // Verify that the selection worked OK
+ QModelIndexList selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 2);
+ QVERIFY(selected.contains(index1));
+ QVERIFY(selected.contains(index2));
+
+ // Select item 0 to revert the selection
+ view.setCurrentIndex(index0);
+ QCOMPARE(view.currentIndex(), index0);
+
+ // Repeat the same steps as above, but with a Shift-Arrow selection
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos);
+ QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
+ moveEventReceived = qApp->notify(view.viewport(), &moveEvent2);
+ QVERIFY(moveEventReceived);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos);
+ QCOMPARE(view.currentIndex(), index1);
+
+ // Press Shift-Down
+ QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
+ QCOMPARE(view.currentIndex(), index2);
+
+ // Verify that the selection worked OK
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 2);
+ QVERIFY(selected.contains(index1));
+ QVERIFY(selected.contains(index2));
+}
+
+void tst_QAbstractItemView::ctrlRubberbandSelection()
+{
+ QStandardItemModel model;
+ for (int i=0; i<3; ++i) {
+ QStandardItem *item = new QStandardItem(QString("%1").arg(i));
+ model.setItem(i, 0, item);
+ }
+
+ QListView view;
+ view.setFixedSize(150, 450);
+ view.setFlow(QListView::LeftToRight);
+ view.setGridSize(QSize(100, 100));
+ view.setSelectionMode(QListView::ExtendedSelection);
+ view.setViewMode(QListView::IconMode);
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(30);
+
+ QModelIndex index1 = model.index(1, 0);
+ QModelIndex index2 = model.index(2, 0);
+
+ // Select item 1
+ view.setCurrentIndex(index1);
+ QModelIndexList selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(index1));
+
+ // Now press control and draw a rubberband around items 1 and 2.
+ // The mouse move event has to be created manually because the QTest framework does not
+ // contain a function for mouse moves with buttons pressed.
+ QPoint pressPos = view.visualRect(index1).topLeft() - QPoint(1, 1);
+ QPoint releasePos = view.visualRect(index2).bottomRight() + QPoint(1, 1);
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pressPos);
+ QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
+ bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
+ QVERIFY(moveEventReceived);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, releasePos);
+
+ // Verify that item 2 is selected now
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(index2));
+}
+
+void tst_QAbstractItemView::QTBUG6407_extendedSelection()
+{
+ QListWidget view;
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ for(int i = 0; i < 50; ++i)
+ view.addItem(QString::number(i));
+
+ QFont font = view.font();
+ font.setPixelSize(10);
+ view.setFont(font);
+ view.resize(200,240);
+
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
+
+ view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
+ QTest::qWait(20);
+
+ QModelIndex index49 = view.model()->index(49,0);
+ QPoint p = view.visualRect(index49).center();
+ QVERIFY(view.viewport()->rect().contains(p));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
+ QCOMPARE(view.currentIndex(), index49);
+ QCOMPARE(view.selectedItems().count(), 1);
+
+ QModelIndex index47 = view.model()->index(47,0);
+ p = view.visualRect(index47).center();
+ QVERIFY(view.viewport()->rect().contains(p));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
+ QCOMPARE(view.currentIndex(), index47);
+ QCOMPARE(view.selectedItems().count(), 3); //49, 48, 47;
+
+ QModelIndex index44 = view.model()->index(44,0);
+ p = view.visualRect(index44).center();
+ QVERIFY(view.viewport()->rect().contains(p));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
+ QCOMPARE(view.currentIndex(), index44);
+ QCOMPARE(view.selectedItems().count(), 6); //49 .. 44;
+
+}
+
+void tst_QAbstractItemView::QTBUG6753_selectOnSelection()
+{
+ QTableWidget table(5, 5);
+ for (int i = 0; i < table.rowCount(); ++i)
+ for (int j = 0; j < table.columnCount(); ++j)
+ table.setItem(i, j, new QTableWidgetItem("choo-be-doo-wah"));
+
+ table.show();
+ table.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ table.selectAll();
+ QTest::qWaitForWindowShown(&table);
+ QModelIndex item = table.model()->index(1,1);
+ QRect itemRect = table.visualRect(item);
+ QTest::mouseMove(table.viewport(), itemRect.center());
+ QTest::mouseClick(table.viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center());
+ QTest::qWait(20);
+
+ QCOMPARE(table.selectedItems().count(), 1);
+ QCOMPARE(table.selectedItems().first(), table.item(item.row(), item.column()));
+}
+
+QTEST_MAIN(tst_QAbstractItemView)
+#include "tst_qabstractitemview.moc"
diff --git a/tests/auto/widgets/itemviews/qabstractproxymodel/.gitignore b/tests/auto/widgets/itemviews/qabstractproxymodel/.gitignore
new file mode 100644
index 0000000000..bffc04d632
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qabstractproxymodel/.gitignore
@@ -0,0 +1 @@
+tst_qabstractproxymodel
diff --git a/tests/auto/widgets/itemviews/qabstractproxymodel/qabstractproxymodel.pro b/tests/auto/widgets/itemviews/qabstractproxymodel/qabstractproxymodel.pro
new file mode 100644
index 0000000000..7a6a841796
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qabstractproxymodel/qabstractproxymodel.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstractproxymodel.cpp
diff --git a/tests/auto/widgets/itemviews/qabstractproxymodel/tst_qabstractproxymodel.cpp b/tests/auto/widgets/itemviews/qabstractproxymodel/tst_qabstractproxymodel.cpp
new file mode 100644
index 0000000000..b6557c45ec
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qabstractproxymodel/tst_qabstractproxymodel.cpp
@@ -0,0 +1,449 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qabstractproxymodel.h>
+#include <QItemSelection>
+#include <qstandarditemmodel.h>
+
+class tst_QAbstractProxyModel : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qabstractproxymodel_data();
+ void qabstractproxymodel();
+ void data_data();
+ void data();
+ void flags_data();
+ void flags();
+ void headerData_data();
+ void headerData();
+ void itemData_data();
+ void itemData();
+ void mapFromSource_data();
+ void mapFromSource();
+ void mapSelectionFromSource_data();
+ void mapSelectionFromSource();
+ void mapSelectionToSource_data();
+ void mapSelectionToSource();
+ void mapToSource_data();
+ void mapToSource();
+ void revert_data();
+ void revert();
+ void setSourceModel_data();
+ void setSourceModel();
+ void submit_data();
+ void submit();
+ void testRoleNames();
+};
+
+// Subclass that exposes the protected functions.
+class SubQAbstractProxyModel : public QAbstractProxyModel
+{
+public:
+ // QAbstractProxyModel::mapFromSource is a pure virtual function.
+ QModelIndex mapFromSource(QModelIndex const& sourceIndex) const
+ { Q_UNUSED(sourceIndex); return QModelIndex(); }
+
+ // QAbstractProxyModel::mapToSource is a pure virtual function.
+ QModelIndex mapToSource(QModelIndex const& proxyIndex) const
+ { Q_UNUSED(proxyIndex); return QModelIndex(); }
+
+ QModelIndex index(int, int, const QModelIndex&) const
+ {
+ return QModelIndex();
+ }
+
+ QModelIndex parent(const QModelIndex&) const
+ {
+ return QModelIndex();
+ }
+
+ int rowCount(const QModelIndex&) const
+ {
+ return 0;
+ }
+
+ int columnCount(const QModelIndex&) const
+ {
+ return 0;
+ }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QAbstractProxyModel::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QAbstractProxyModel::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QAbstractProxyModel::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QAbstractProxyModel::cleanup()
+{
+}
+
+void tst_QAbstractProxyModel::qabstractproxymodel_data()
+{
+}
+
+void tst_QAbstractProxyModel::qabstractproxymodel()
+{
+ SubQAbstractProxyModel model;
+ model.data(QModelIndex());
+ model.flags(QModelIndex());
+ model.headerData(0, Qt::Vertical, 0);
+ model.itemData(QModelIndex());
+ model.mapFromSource(QModelIndex());
+ model.mapSelectionFromSource(QItemSelection());
+ model.mapSelectionToSource(QItemSelection());
+ model.mapToSource(QModelIndex());
+ model.revert();
+ model.setSourceModel(0);
+ QCOMPARE(model.sourceModel(), (QAbstractItemModel*)0);
+ model.submit();
+}
+
+Q_DECLARE_METATYPE(QVariant)
+Q_DECLARE_METATYPE(QModelIndex)
+void tst_QAbstractProxyModel::data_data()
+{
+ QTest::addColumn<QModelIndex>("proxyIndex");
+ QTest::addColumn<int>("role");
+ QTest::addColumn<QVariant>("data");
+ QTest::newRow("null") << QModelIndex() << 0 << QVariant();
+}
+
+// public QVariant data(QModelIndex const& proxyIndex, int role = Qt::DisplayRole) const
+void tst_QAbstractProxyModel::data()
+{
+ QFETCH(QModelIndex, proxyIndex);
+ QFETCH(int, role);
+ QFETCH(QVariant, data);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.data(proxyIndex, role), data);
+}
+
+Q_DECLARE_METATYPE(Qt::ItemFlags)
+void tst_QAbstractProxyModel::flags_data()
+{
+ QTest::addColumn<QModelIndex>("index");
+ QTest::addColumn<Qt::ItemFlags>("flags");
+ QTest::newRow("null") << QModelIndex() << (Qt::ItemFlags)0;
+}
+
+// public Qt::ItemFlags flags(QModelIndex const& index) const
+void tst_QAbstractProxyModel::flags()
+{
+ QFETCH(QModelIndex, index);
+ QFETCH(Qt::ItemFlags, flags);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.flags(index), flags);
+}
+
+Q_DECLARE_METATYPE(Qt::Orientation)
+Q_DECLARE_METATYPE(Qt::ItemDataRole)
+void tst_QAbstractProxyModel::headerData_data()
+{
+ QTest::addColumn<int>("section");
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<Qt::ItemDataRole>("role");
+ QTest::addColumn<QVariant>("headerData");
+ QTest::newRow("null") << 0 << Qt::Vertical << Qt::UserRole << QVariant();
+}
+
+// public QVariant headerData(int section, Qt::Orientation orientation, int role) const
+void tst_QAbstractProxyModel::headerData()
+{
+ QFETCH(int, section);
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(Qt::ItemDataRole, role);
+ QFETCH(QVariant, headerData);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.headerData(section, orientation, role), headerData);
+}
+
+void tst_QAbstractProxyModel::itemData_data()
+{
+ QTest::addColumn<QModelIndex>("index");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("null") << QModelIndex() << 0;
+}
+
+// public QMap<int,QVariant> itemData(QModelIndex const& index) const
+void tst_QAbstractProxyModel::itemData()
+{
+ QFETCH(QModelIndex, index);
+ QFETCH(int, count);
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.itemData(index).count(), count);
+}
+
+void tst_QAbstractProxyModel::mapFromSource_data()
+{
+ QTest::addColumn<QModelIndex>("sourceIndex");
+ QTest::addColumn<QModelIndex>("mapFromSource");
+ QTest::newRow("null") << QModelIndex() << QModelIndex();
+}
+
+// public QModelIndex mapFromSource(QModelIndex const& sourceIndex) const
+void tst_QAbstractProxyModel::mapFromSource()
+{
+ QFETCH(QModelIndex, sourceIndex);
+ QFETCH(QModelIndex, mapFromSource);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.mapFromSource(sourceIndex), mapFromSource);
+}
+
+Q_DECLARE_METATYPE(QItemSelection)
+void tst_QAbstractProxyModel::mapSelectionFromSource_data()
+{
+ QTest::addColumn<QItemSelection>("selection");
+ QTest::addColumn<QItemSelection>("mapSelectionFromSource");
+ QTest::newRow("null") << QItemSelection() << QItemSelection();
+ QTest::newRow("empty") << QItemSelection(QModelIndex(), QModelIndex()) << QItemSelection(QModelIndex(), QModelIndex());
+}
+
+// public QItemSelection mapSelectionFromSource(QItemSelection const& selection) const
+void tst_QAbstractProxyModel::mapSelectionFromSource()
+{
+ QFETCH(QItemSelection, selection);
+ QFETCH(QItemSelection, mapSelectionFromSource);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.mapSelectionFromSource(selection), mapSelectionFromSource);
+}
+
+void tst_QAbstractProxyModel::mapSelectionToSource_data()
+{
+ QTest::addColumn<QItemSelection>("selection");
+ QTest::addColumn<QItemSelection>("mapSelectionToSource");
+ QTest::newRow("null") << QItemSelection() << QItemSelection();
+ QTest::newRow("empty") << QItemSelection(QModelIndex(), QModelIndex()) << QItemSelection(QModelIndex(), QModelIndex());
+}
+
+// public QItemSelection mapSelectionToSource(QItemSelection const& selection) const
+void tst_QAbstractProxyModel::mapSelectionToSource()
+{
+ QFETCH(QItemSelection, selection);
+ QFETCH(QItemSelection, mapSelectionToSource);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.mapSelectionToSource(selection), mapSelectionToSource);
+}
+
+void tst_QAbstractProxyModel::mapToSource_data()
+{
+ QTest::addColumn<QModelIndex>("proxyIndex");
+ QTest::addColumn<QModelIndex>("mapToSource");
+ QTest::newRow("null") << QModelIndex() << QModelIndex();
+}
+
+// public QModelIndex mapToSource(QModelIndex const& proxyIndex) const
+void tst_QAbstractProxyModel::mapToSource()
+{
+ QFETCH(QModelIndex, proxyIndex);
+ QFETCH(QModelIndex, mapToSource);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.mapToSource(proxyIndex), mapToSource);
+}
+
+void tst_QAbstractProxyModel::revert_data()
+{
+ //QTest::addColumn<int>("foo");
+ //QTest::newRow("null") << 0;
+}
+
+// public void revert()
+void tst_QAbstractProxyModel::revert()
+{
+ //QFETCH(int, foo);
+
+ SubQAbstractProxyModel model;
+ model.revert();
+}
+
+void tst_QAbstractProxyModel::setSourceModel_data()
+{
+ //QTest::addColumn<int>("sourceModelCount");
+ //QTest::newRow("null") << 0;
+}
+
+// public void setSourceModel(QAbstractItemModel* sourceModel)
+void tst_QAbstractProxyModel::setSourceModel()
+{
+ //QFETCH(int, sourceModelCount);
+
+ SubQAbstractProxyModel model;
+ QStandardItemModel *sourceModel = new QStandardItemModel(&model);
+ model.setSourceModel(sourceModel);
+ QCOMPARE(model.sourceModel(), static_cast<QAbstractItemModel*>(sourceModel));
+
+ QStandardItemModel *sourceModel2 = new QStandardItemModel(&model);
+ model.setSourceModel(sourceModel2);
+ QCOMPARE(model.sourceModel(), static_cast<QAbstractItemModel*>(sourceModel2));
+
+ delete sourceModel2;
+ QCOMPARE(model.sourceModel(), static_cast<QAbstractItemModel*>(0));
+}
+
+void tst_QAbstractProxyModel::submit_data()
+{
+ QTest::addColumn<bool>("submit");
+ QTest::newRow("null") << true;
+}
+
+// public bool submit()
+void tst_QAbstractProxyModel::submit()
+{
+ QFETCH(bool, submit);
+
+ SubQAbstractProxyModel model;
+ QCOMPARE(model.submit(), submit);
+}
+
+class StandardItemModelWithCustomRoleNames : public QStandardItemModel
+{
+public:
+ enum CustomRole {
+ CustomRole1 = Qt::UserRole,
+ CustomRole2
+ };
+
+ StandardItemModelWithCustomRoleNames() {
+ QHash<int, QByteArray> _roleNames = roleNames();
+ _roleNames.insert(CustomRole1, "custom1");
+ _roleNames.insert(CustomRole2, "custom2");
+ setRoleNames(_roleNames);
+ }
+};
+
+class AnotherStandardItemModelWithCustomRoleNames : public QStandardItemModel
+{
+ public:
+ enum CustomRole {
+ AnotherCustomRole1 = Qt::UserRole + 10, // Different to StandardItemModelWithCustomRoleNames::CustomRole1
+ AnotherCustomRole2
+ };
+
+ AnotherStandardItemModelWithCustomRoleNames() {
+ QHash<int, QByteArray> _roleNames = roleNames();
+ _roleNames.insert(AnotherCustomRole1, "another_custom1");
+ _roleNames.insert(AnotherCustomRole2, "another_custom2");
+ setRoleNames(_roleNames);
+ }
+};
+
+/**
+ Verifies that @p subSet is a subset of @p superSet. That is, all keys in @p subSet exist in @p superSet and have the same values.
+*/
+static void verifySubSetOf(const QHash<int, QByteArray> &superSet, const QHash<int, QByteArray> &subSet)
+{
+ QHash<int, QByteArray>::const_iterator it = subSet.constBegin();
+ const QHash<int, QByteArray>::const_iterator end = subSet.constEnd();
+ for ( ; it != end; ++it ) {
+ QVERIFY(superSet.contains(it.key()));
+ QVERIFY(it.value() == superSet.value(it.key()));
+ }
+}
+
+void tst_QAbstractProxyModel::testRoleNames()
+{
+ QStandardItemModel defaultModel;
+ StandardItemModelWithCustomRoleNames model;
+ QHash<int, QByteArray> rootModelRoleNames = model.roleNames();
+ QHash<int, QByteArray> defaultModelRoleNames = defaultModel.roleNames();
+
+ verifySubSetOf( rootModelRoleNames, defaultModelRoleNames);
+ QVERIFY( rootModelRoleNames.size() == defaultModelRoleNames.size() + 2 );
+ QVERIFY( rootModelRoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole1));
+ QVERIFY( rootModelRoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole2));
+ QVERIFY( rootModelRoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole1) == "custom1" );
+ QVERIFY( rootModelRoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole2) == "custom2" );
+
+ SubQAbstractProxyModel proxy1;
+ proxy1.setSourceModel(&model);
+ QHash<int, QByteArray> proxy1RoleNames = proxy1.roleNames();
+ verifySubSetOf( proxy1RoleNames, defaultModelRoleNames );
+ QVERIFY( proxy1RoleNames.size() == defaultModelRoleNames.size() + 2 );
+ QVERIFY( proxy1RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole1));
+ QVERIFY( proxy1RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole2));
+ QVERIFY( proxy1RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole1) == "custom1" );
+ QVERIFY( proxy1RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole2) == "custom2" );
+
+ SubQAbstractProxyModel proxy2;
+ proxy2.setSourceModel(&proxy1);
+ QHash<int, QByteArray> proxy2RoleNames = proxy2.roleNames();
+ verifySubSetOf( proxy2RoleNames, defaultModelRoleNames );
+ QVERIFY( proxy2RoleNames.size() == defaultModelRoleNames.size() + 2 );
+ QVERIFY( proxy2RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole1));
+ QVERIFY( proxy2RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole2));
+ QVERIFY( proxy2RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole1) == "custom1" );
+ QVERIFY( proxy2RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole2) == "custom2" );
+
+}
+
+QTEST_MAIN(tst_QAbstractProxyModel)
+#include "tst_qabstractproxymodel.moc"
+
diff --git a/tests/auto/widgets/itemviews/qcolumnview/.gitignore b/tests/auto/widgets/itemviews/qcolumnview/.gitignore
new file mode 100644
index 0000000000..580ca0edad
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qcolumnview/.gitignore
@@ -0,0 +1 @@
+tst_qcolumnview
diff --git a/tests/auto/widgets/itemviews/qcolumnview/qcolumnview.pro b/tests/auto/widgets/itemviews/qcolumnview/qcolumnview.pro
new file mode 100644
index 0000000000..bca9e75ba5
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qcolumnview/qcolumnview.pro
@@ -0,0 +1,6 @@
+CONFIG += qttest_p4
+QT += widgets widgets-private
+QT += gui-private core-private
+
+SOURCES += tst_qcolumnview.cpp
+TARGET = tst_qcolumnview
diff --git a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp
new file mode 100644
index 0000000000..364f917511
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp
@@ -0,0 +1,1040 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qstandarditemmodel.h>
+#include <qitemdelegate.h>
+#include <qcolumnview.h>
+#include "../../../src/widgets/itemviews/qcolumnviewgrip_p.h"
+#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h"
+#include <qdirmodel.h>
+#include <qstringlistmodel.h>
+#include <qdebug.h>
+#include <qitemdelegate.h>
+#include <qscrollbar.h>
+#include <private/qcolumnview_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#define ANIMATION_DELAY 300
+
+class tst_QColumnView : public QObject {
+ Q_OBJECT
+
+public:
+ tst_QColumnView();
+ virtual ~tst_QColumnView();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void rootIndex();
+ void grips();
+ void isIndexHidden();
+ void indexAt();
+ void scrollContentsBy_data();
+ void scrollContentsBy();
+ void scrollTo_data();
+ void scrollTo();
+ void moveCursor_data();
+ void moveCursor();
+ void selectAll();
+ void clicked();
+ void selectedColumns();
+ void setSelection();
+ void setSelectionModel();
+ void visualRegionForSelection();
+
+ void dynamicModelChanges();
+
+ // grip
+ void moveGrip_basic();
+ void moveGrip_data();
+ void moveGrip();
+ void doubleClick();
+ void gripMoved();
+
+ void preview();
+ void swapPreview();
+ void sizes();
+ void rowDelegate();
+ void resize();
+ void changeSameColumn();
+ void parentCurrentIndex_data();
+ void parentCurrentIndex();
+ void pullRug_data();
+ void pullRug();
+
+protected slots:
+ void setPreviewWidget();
+};
+
+class TreeModel : public QStandardItemModel
+{
+public:
+ TreeModel()
+ {
+ for (int j = 0; j < 10; ++j) {
+ QStandardItem *parentItem = invisibleRootItem();
+ for (int i = 0; i < 10; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ QStandardItem *item2 = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item2);
+ item2->appendRow(new QStandardItem(QString("item %0").arg(i)));
+ parentItem->appendRow(new QStandardItem(QString("file %0").arg(i)));
+ parentItem = item;
+ }
+ }
+ }
+
+ inline QModelIndex firstLevel() { return index(0, 0, QModelIndex()); }
+ inline QModelIndex secondLevel() { return index(0, 0, firstLevel()); }
+ inline QModelIndex thirdLevel() { return index(0, 0, secondLevel()); }
+};
+
+class ColumnView : public QColumnView {
+
+public:
+ ColumnView(QWidget *parent = 0) : QColumnView(parent){}
+
+ QList<QPointer<QAbstractItemView> > createdColumns;
+ void ScrollContentsBy(int x, int y) {scrollContentsBy(x,y); }
+ int HorizontalOffset() const { return horizontalOffset(); }
+ void emitClicked() { emit clicked(QModelIndex()); }
+
+ enum PublicCursorAction {
+ MoveUp = QAbstractItemView::MoveUp,
+ MoveDown = QAbstractItemView::MoveDown,
+ MoveLeft = QAbstractItemView::MoveLeft,
+ MoveRight = QAbstractItemView::MoveRight,
+ MoveHome = QAbstractItemView::MoveHome,
+ MoveEnd = QAbstractItemView::MoveEnd,
+ MovePageUp = QAbstractItemView::MovePageUp,
+ MovePageDown = QAbstractItemView::MovePageDown,
+ MoveNext = QAbstractItemView::MoveNext,
+ MovePrevious = QAbstractItemView::MovePrevious
+ };
+
+ inline QModelIndex MoveCursor(PublicCursorAction ca, Qt::KeyboardModifiers kbm)
+ { return QColumnView::moveCursor((CursorAction)ca, kbm); }
+ bool IsIndexHidden(const QModelIndex&index) const
+ { return isIndexHidden(index); }
+
+ void setSelection(const QRect & rect, QItemSelectionModel::SelectionFlags command )
+ {
+ QColumnView::setSelection(rect, command);
+ }
+
+ QRegion visualRegionForSelection(QItemSelection selection){
+ return QColumnView::visualRegionForSelection(selection);
+ }
+protected:
+ QAbstractItemView *createColumn(const QModelIndex &index) {
+ QAbstractItemView *view = QColumnView::createColumn(index);
+ QPointer<QAbstractItemView> savedView = view;
+ createdColumns.append(savedView);
+ return view;
+ }
+
+};
+
+tst_QColumnView::tst_QColumnView()
+{
+}
+
+tst_QColumnView::~tst_QColumnView()
+{
+}
+
+void tst_QColumnView::init()
+{
+ qApp->setLayoutDirection(Qt::LeftToRight);
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QColumnView::cleanup()
+{
+}
+
+void tst_QColumnView::rootIndex()
+{
+ ColumnView view;
+ // no model
+ view.setRootIndex(QModelIndex());
+
+ TreeModel model;
+ view.setModel(&model);
+
+ // A top level index
+ QModelIndex drive = model.firstLevel();
+ QVERIFY(view.visualRect(drive).isValid());
+ view.setRootIndex(QModelIndex());
+ QCOMPARE(view.HorizontalOffset(), 0);
+ QCOMPARE(view.rootIndex(), QModelIndex());
+ QVERIFY(view.visualRect(drive).isValid());
+
+ // A item under the rootIndex exists
+ QModelIndex home = model.thirdLevel();
+ QModelIndex homeFile = model.index(0, 0, home);
+ int i = 0;
+ while (i < model.rowCount(home) - 1 && !model.hasChildren(homeFile))
+ homeFile = model.index(++i, 0, home);
+ view.setRootIndex(home);
+ QCOMPARE(view.HorizontalOffset(), 0);
+ QCOMPARE(view.rootIndex(), home);
+ QVERIFY(!view.visualRect(drive).isValid());
+ QVERIFY(!view.visualRect(home).isValid());
+ if (homeFile.isValid())
+ QVERIFY(view.visualRect(homeFile).isValid());
+
+ // set root when there already is one and everything should still be ok
+ view.setRootIndex(home);
+ view.setCurrentIndex(homeFile);
+ view.scrollTo(model.index(0,0, homeFile));
+ QCOMPARE(view.HorizontalOffset(), 0);
+ QCOMPARE(view.rootIndex(), home);
+ QVERIFY(!view.visualRect(drive).isValid());
+ QVERIFY(!view.visualRect(home).isValid());
+ if (homeFile.isValid())
+ QVERIFY(view.visualRect(homeFile).isValid());
+
+ //
+ homeFile = model.thirdLevel();
+ home = homeFile.parent();
+ view.setRootIndex(home);
+ view.setCurrentIndex(homeFile);
+ view.show();
+ i = 0;
+ QModelIndex two = model.index(0, 0, homeFile);
+ while (i < model.rowCount(homeFile) - 1 && !model.hasChildren(two))
+ two = model.index(++i, 0, homeFile);
+ qApp->processEvents();
+ QTest::qWait(ANIMATION_DELAY);
+ view.setCurrentIndex(two);
+ view.scrollTo(two);
+ QTest::qWait(ANIMATION_DELAY);
+ qApp->processEvents();
+ QVERIFY(two.isValid());
+ QVERIFY(view.HorizontalOffset() != 0);
+
+ view.setRootIndex(homeFile);
+ QCOMPARE(view.HorizontalOffset(), 0);
+}
+
+void tst_QColumnView::grips()
+{
+ QColumnView view;
+ QDirModel model;
+ view.setModel(&model);
+ QCOMPARE(view.resizeGripsVisible(), true);
+
+ view.setResizeGripsVisible(true);
+ QCOMPARE(view.resizeGripsVisible(), true);
+
+ {
+ const QObjectList list = view.viewport()->children();
+ for (int i = 0 ; i < list.count(); ++i) {
+ if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(list.at(i)))
+ QVERIFY(view->cornerWidget() != 0);
+ }
+ }
+ view.setResizeGripsVisible(false);
+ QCOMPARE(view.resizeGripsVisible(), false);
+
+ {
+ const QObjectList list = view.viewport()->children();
+ for (int i = 0 ; i < list.count(); ++i) {
+ if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(list.at(i))) {
+ if (view->isVisible())
+ QVERIFY(view->cornerWidget() == 0);
+ }
+ }
+ }
+
+ view.setResizeGripsVisible(true);
+ QCOMPARE(view.resizeGripsVisible(), true);
+}
+
+void tst_QColumnView::isIndexHidden()
+{
+ ColumnView view;
+ QModelIndex idx;
+ QCOMPARE(view.IsIndexHidden(idx), false);
+ QDirModel model;
+ view.setModel(&model);
+ QCOMPARE(view.IsIndexHidden(idx), false);
+}
+
+void tst_QColumnView::indexAt()
+{
+ QColumnView view;
+ QCOMPARE(view.indexAt(QPoint(0,0)), QModelIndex());
+ QDirModel model;
+ view.setModel(&model);
+
+ QModelIndex home = model.index(QDir::homePath());
+ QModelIndex homeFile = model.index(0, 0, home);
+ if (!homeFile.isValid())
+ return;
+ view.setRootIndex(home);
+ QRect rect = view.visualRect(QModelIndex());
+ QVERIFY(!rect.isValid());
+ rect = view.visualRect(homeFile);
+ QVERIFY(rect.isValid());
+
+ QModelIndex child;
+ for (int i = 0; i < model.rowCount(home); ++i) {
+ child = model.index(i, 0, home);
+ rect = view.visualRect(child);
+ QVERIFY(rect.isValid());
+ if (i > 0)
+ QVERIFY(rect.top() > 0);
+ QCOMPARE(view.indexAt(rect.center()), child);
+
+ view.selectionModel()->select(child, QItemSelectionModel::SelectCurrent);
+ view.setCurrentIndex(child);
+ qApp->processEvents();
+ QTest::qWait(200);
+
+ // test that the second row doesn't start at 0
+ if (model.rowCount(child) > 0) {
+ child = model.index(0, 0, child);
+ QVERIFY(child.isValid());
+ rect = view.visualRect(child);
+ QVERIFY(rect.isValid());
+ QVERIFY(rect.left() > 0);
+ QCOMPARE(view.indexAt(rect.center()), child);
+ break;
+ }
+ }
+}
+
+void tst_QColumnView::scrollContentsBy_data()
+{
+ QTest::addColumn<bool>("reverse");
+ QTest::newRow("normal") << false;
+ QTest::newRow("reverse") << true;
+}
+
+void tst_QColumnView::scrollContentsBy()
+{
+ QFETCH(bool, reverse);
+ if (reverse)
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ ColumnView view;
+ view.ScrollContentsBy(-1, -1);
+ view.ScrollContentsBy(0, 0);
+
+ TreeModel model;
+ view.setModel(&model);
+ view.ScrollContentsBy(0, 0);
+
+ QModelIndex home = model.thirdLevel();
+ view.setCurrentIndex(home);
+ QTest::qWait(ANIMATION_DELAY);
+ view.ScrollContentsBy(0, 0);
+}
+
+void tst_QColumnView::scrollTo_data()
+{
+ QTest::addColumn<bool>("reverse");
+ QTest::addColumn<bool>("giveFocus");
+ /// ### add test later for giveFocus == true
+ QTest::newRow("normal") << false << false;
+ QTest::newRow("reverse") << true << false;
+}
+
+void tst_QColumnView::scrollTo()
+{
+ QFETCH(bool, reverse);
+ QFETCH(bool, giveFocus);
+ if (reverse)
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ QWidget topLevel;
+ ColumnView view(&topLevel);
+ view.resize(200, 200);
+ topLevel.show();
+ view.scrollTo(QModelIndex(), QAbstractItemView::EnsureVisible);
+ QCOMPARE(view.HorizontalOffset(), 0);
+
+ TreeModel model;
+ view.setModel(&model);
+ view.scrollTo(QModelIndex(), QAbstractItemView::EnsureVisible);
+
+ QModelIndex home;
+ home = model.index(0, 0, home);
+ home = model.index(0, 0, home);
+ home = model.index(0, 0, home);
+ view.scrollTo(home, QAbstractItemView::EnsureVisible);
+ QModelIndex homeFile = model.index(0, 0, home);
+ view.setRootIndex(home);
+
+ QModelIndex index = model.index(0, 0, home);
+ view.scrollTo(index, QAbstractItemView::EnsureVisible);
+ QCOMPARE(view.HorizontalOffset(), 0);
+
+ // Embedded requires that at least one widget have focus
+ QWidget w;
+ w.show();
+
+ if (giveFocus)
+ view.setFocus(Qt::OtherFocusReason);
+ else
+ view.clearFocus();
+
+ qApp->processEvents();
+ QTRY_COMPARE(view.hasFocus(), giveFocus);
+ // scroll to the right
+ int level = 0;
+ int last = view.HorizontalOffset();
+ while(model.hasChildren(index) && level < 5) {
+ view.setCurrentIndex(index);
+ QTest::qWait(ANIMATION_DELAY);
+ view.scrollTo(index, QAbstractItemView::EnsureVisible);
+ QTest::qWait(ANIMATION_DELAY);
+ qApp->processEvents();
+ index = model.index(0, 0, index);
+ level++;
+ if (level >= 2) {
+ if (!reverse) {
+ QTRY_VERIFY(view.HorizontalOffset() < 0);
+ QTRY_VERIFY(last > view.HorizontalOffset());
+ } else {
+ QTRY_VERIFY(view.HorizontalOffset() > 0);
+ QTRY_VERIFY(last < view.HorizontalOffset());
+ }
+ }
+ last = view.HorizontalOffset();
+ }
+
+ // scroll to the left
+ int start = level;
+ while(index.parent().isValid() && index != view.rootIndex()) {
+ view.setCurrentIndex(index);
+ QTest::qWait(ANIMATION_DELAY);
+ view.scrollTo(index, QAbstractItemView::EnsureVisible);
+ index = index.parent();
+ if (start != level) {
+ if (!reverse)
+ QTRY_VERIFY(last < view.HorizontalOffset());
+ else
+ QTRY_VERIFY(last > view.HorizontalOffset());
+ }
+ level--;
+ last = view.HorizontalOffset();
+ }
+ // It shouldn't automatically steal focus if it doesn't have it
+ QTRY_COMPARE(view.hasFocus(), giveFocus);
+
+ // Try scrolling to something that is above the root index
+ home = model.index(0, 0, QModelIndex());
+ QModelIndex temp = model.index(1, 0, home);
+ home = model.index(0, 0, home);
+ home = model.index(0, 0, home);
+ view.setRootIndex(home);
+ view.scrollTo(model.index(0, 0, home));
+ QTest::qWait(ANIMATION_DELAY);
+ view.scrollTo(temp);
+}
+
+void tst_QColumnView::moveCursor_data()
+{
+ QTest::addColumn<bool>("reverse");
+ QTest::newRow("normal") << false;
+ QTest::newRow("reverse") << true;
+}
+
+void tst_QColumnView::moveCursor()
+{
+ QFETCH(bool, reverse);
+ if (reverse)
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ ColumnView view;
+
+ // don't crash
+ view.MoveCursor(ColumnView::MoveUp, Qt::NoModifier);
+
+ // don't do anything
+ QCOMPARE(view.MoveCursor(ColumnView::MoveEnd, Qt::NoModifier), QModelIndex());
+
+ QDirModel model;
+ view.setModel(&model);
+ QModelIndex home = model.index(QDir::homePath());
+ QModelIndex ci = view.currentIndex();
+ QCOMPARE(view.MoveCursor(ColumnView::MoveUp, Qt::NoModifier), QModelIndex());
+ QCOMPARE(view.MoveCursor(ColumnView::MoveDown, Qt::NoModifier), QModelIndex());
+
+ // left at root
+ view.setCurrentIndex(model.index(0,0));
+ ColumnView::PublicCursorAction action = reverse ? ColumnView::MoveRight : ColumnView::MoveLeft;
+ QCOMPARE(view.MoveCursor(action, Qt::NoModifier), model.index(0,0));
+
+ // left shouldn't move up
+ int i = 0;
+ ci = model.index(0, 0);
+ while (i < model.rowCount() - 1 && !model.hasChildren(ci))
+ ci = model.index(++i, 0);
+ QVERIFY(model.hasChildren(ci));
+ view.setCurrentIndex(ci);
+ action = reverse ? ColumnView::MoveRight : ColumnView::MoveLeft;
+ QCOMPARE(view.MoveCursor(action, Qt::NoModifier), ci);
+
+ // now move to the left (i.e. move over one column)
+ view.setCurrentIndex(home);
+ QCOMPARE(view.MoveCursor(action, Qt::NoModifier), home.parent());
+
+ // right
+ action = reverse ? ColumnView::MoveLeft : ColumnView::MoveRight;
+ view.setCurrentIndex(ci);
+ QModelIndex mc = view.MoveCursor(action, Qt::NoModifier);
+ QCOMPARE(mc, model.index(0,0, ci));
+
+ // next one should move down
+ QModelIndex idx = model.index(0, 0, ci);
+ while (model.hasChildren(idx) && model.rowCount(ci) > idx.row() + 1)
+ idx = idx.sibling(idx.row() + 1, idx.column());
+ view.setCurrentIndex(idx);
+ mc = view.MoveCursor(action, Qt::NoModifier);
+ QCOMPARE(mc, idx.sibling(idx.row() + 1, idx.column()));
+}
+
+void tst_QColumnView::selectAll()
+{
+ ColumnView view;
+ view.selectAll();
+
+ QDirModel model;
+ view.setModel(&model);
+ view.selectAll();
+ QVERIFY(view.selectionModel()->selectedIndexes().count() >= 0);
+
+ QModelIndex home = model.index(QDir::homePath());
+ view.setCurrentIndex(home);
+ view.selectAll();
+ QVERIFY(view.selectionModel()->selectedIndexes().count() > 0);
+
+ QModelIndex file;
+ for (int i = 0; i < model.rowCount(home); ++i)
+ if (!model.hasChildren(model.index(i, 0, home))) {
+ file = model.index(i, 0, home);
+ break;
+ }
+ view.setCurrentIndex(file);
+ view.selectAll();
+ QVERIFY(view.selectionModel()->selectedIndexes().count() > 0);
+
+ view.setCurrentIndex(QModelIndex());
+ QVERIFY(view.selectionModel()->selectedIndexes().count() == 0);
+}
+
+void tst_QColumnView::clicked()
+{
+ ColumnView view;
+
+ QDirModel model;
+ view.setModel(&model);
+ view.resize(800,300);
+ view.show();
+
+ QModelIndex home = model.index(QDir::homePath());
+ QVERIFY(home.isValid());
+ view.setCurrentIndex(home);
+ QTest::qWait(ANIMATION_DELAY);
+
+ QModelIndex parent = home.parent();
+ QVERIFY(parent.isValid());
+
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ QSignalSpy clickedSpy(&view, SIGNAL(clicked(const QModelIndex &)));
+
+ QPoint localPoint = view.visualRect(home).center();
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, localPoint);
+ QCOMPARE(clickedSpy.count(), 1);
+ qApp->processEvents();
+
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+
+ for (int i = 0; i < view.createdColumns.count(); ++i) {
+ QAbstractItemView *column = view.createdColumns.at(i);
+ if (column && column->selectionModel() && (column->rootIndex() == home))
+ QVERIFY(column->selectionModel()->selectedIndexes().isEmpty());
+ }
+}
+
+void tst_QColumnView::selectedColumns()
+{
+ ColumnView view;
+ QDirModel model;
+ view.setModel(&model);
+ view.resize(800,300);
+ view.show();
+
+ QModelIndex home = model.index(QDir::homePath());
+ view.setCurrentIndex(home);
+
+ QTest::qWait(ANIMATION_DELAY);
+
+ for (int i = 0; i < view.createdColumns.count(); ++i) {
+ QAbstractItemView *column = view.createdColumns.at(i);
+ if (!column)
+ continue;
+ if (!column->rootIndex().isValid() || column->rootIndex() == home)
+ continue;
+ QTRY_VERIFY(column->currentIndex().isValid());
+ }
+}
+
+void tst_QColumnView::setSelection()
+{
+ ColumnView view;
+ // shouldn't do anything, it falls to the columns to handle this
+ QRect r;
+ view.setSelection(r, QItemSelectionModel::NoUpdate);
+}
+
+void tst_QColumnView::setSelectionModel()
+{
+ ColumnView view;
+ QDirModel model;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex home = model.index(QDir::homePath());
+ view.setCurrentIndex(home);
+ QTest::qWait(ANIMATION_DELAY);
+
+ QItemSelectionModel *selectionModel = new QItemSelectionModel(&model);
+ view.setSelectionModel(selectionModel);
+
+ bool found = false;
+ for (int i = 0; i < view.createdColumns.count(); ++i) {
+ if (view.createdColumns.at(i)->selectionModel() == selectionModel) {
+ found = true;
+ break;
+ }
+ }
+ QVERIFY(found);
+}
+
+void tst_QColumnView::visualRegionForSelection()
+{
+ ColumnView view;
+ QItemSelection emptyItemSelection;
+ QCOMPARE(QRegion(), view.visualRegionForSelection(emptyItemSelection));
+
+ // a region that isn't empty
+ QDirModel model;
+ view.setModel(&model);
+
+ // On Windows CE the home directory might actually be empty.
+#ifndef Q_OS_WINCE
+ QString location = QDir::homePath();
+#else
+ QString location = QLatin1String("/Windows");
+#endif
+
+ QModelIndex home = model.index(location);
+ QVERIFY(model.rowCount(home) > 1);
+ QItemSelection itemSelection(model.index(0, 0, home), model.index(model.rowCount(home) - 1, 0, home));
+ QVERIFY(QRegion() != view.visualRegionForSelection(itemSelection));
+}
+
+void tst_QColumnView::moveGrip_basic()
+{
+ QColumnView view;
+ QColumnViewGrip *grip = new QColumnViewGrip(&view);
+ QSignalSpy spy(grip, SIGNAL(gripMoved(int)));
+ view.setCornerWidget(grip);
+ int oldX = view.width();
+ grip->moveGrip(10);
+ QCOMPARE(oldX + 10, view.width());
+ grip->moveGrip(-10);
+ QCOMPARE(oldX, view.width());
+ grip->moveGrip(-800);
+ QVERIFY(view.width() == 0 || view.width() == 1);
+ grip->moveGrip(800);
+ view.setMinimumWidth(200);
+ grip->moveGrip(-800);
+ QCOMPARE(view.width(), 200);
+ QCOMPARE(spy.count(), 5);
+}
+
+void tst_QColumnView::moveGrip_data()
+{
+ QTest::addColumn<bool>("reverse");
+ QTest::newRow("normal") << false;
+ QTest::newRow("reverse") << true;
+}
+
+void tst_QColumnView::moveGrip()
+{
+ QFETCH(bool, reverse);
+ if (reverse)
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ QWidget topLevel;
+ ColumnView view(&topLevel);
+ TreeModel model;
+ view.setModel(&model);
+ QModelIndex home = model.thirdLevel();
+ view.setCurrentIndex(home);
+ view.resize(640, 200);
+ topLevel.show();
+ QTest::qWait(ANIMATION_DELAY);
+
+ int columnNum = view.createdColumns.count() - 2;
+ QVERIFY(columnNum >= 0);
+ QObjectList list = view.createdColumns[columnNum]->children();
+ QColumnViewGrip *grip = 0;
+ for (int i = 0; i < list.count(); ++i) {
+ if ((grip = qobject_cast<QColumnViewGrip *>(list[i]))) {
+ break;
+ }
+ }
+ if (!grip)
+ return;
+
+ QAbstractItemView *column = qobject_cast<QAbstractItemView *>(grip->parent());
+ int oldX = column->width();
+ QCOMPARE(view.columnWidths().value(columnNum), oldX);
+ grip->moveGrip(10);
+ QCOMPARE(view.columnWidths().value(columnNum), (oldX + (reverse ? -10 : 10)));
+}
+
+void tst_QColumnView::doubleClick()
+{
+ QColumnView view;
+ QColumnViewGrip *grip = new QColumnViewGrip(&view);
+ QSignalSpy spy(grip, SIGNAL(gripMoved(int)));
+ view.setCornerWidget(grip);
+ view.resize(200, 200);
+ QCOMPARE(view.width(), 200);
+ QTest::mouseDClick(grip, Qt::LeftButton);
+ QCOMPARE(view.width(), view.sizeHint().width());
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QColumnView::gripMoved()
+{
+ QColumnView view;
+ QColumnViewGrip *grip = new QColumnViewGrip(&view);
+ QSignalSpy spy(grip, SIGNAL(gripMoved(int)));
+ view.setCornerWidget(grip);
+ view.move(300, 300);
+ view.resize(200, 200);
+ qApp->processEvents();
+
+ int oldWidth = view.width();
+
+ QTest::mousePress(grip, Qt::LeftButton, 0, QPoint(1,1));
+ //QTest::mouseMove(grip, QPoint(grip->globalX()+50, y));
+
+ QPoint posNew = QPoint(grip->mapToGlobal(QPoint(1,1)).x() + 65, 0);
+ QMouseEvent *event = new QMouseEvent(QEvent::MouseMove, posNew, posNew, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QCoreApplication::postEvent(grip, event);
+ QCoreApplication::processEvents();
+ QTest::mouseRelease(grip, Qt::LeftButton);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(view.width(), oldWidth + 65);
+}
+
+void tst_QColumnView::preview()
+{
+ QColumnView view;
+ QCOMPARE(view.previewWidget(), (QWidget*)0);
+ TreeModel model;
+ view.setModel(&model);
+ QCOMPARE(view.previewWidget(), (QWidget*)0);
+ QModelIndex home = model.index(0, 0);
+ QVERIFY(home.isValid());
+ QVERIFY(model.hasChildren(home));
+ view.setCurrentIndex(home);
+ QCOMPARE(view.previewWidget(), (QWidget*)0);
+
+ QModelIndex file;
+ QVERIFY(model.rowCount(home) > 0);
+ for (int i = 0; i < model.rowCount(home); ++i) {
+ if (!model.hasChildren(model.index(i, 0, home))) {
+ file = model.index(i, 0, home);
+ break;
+ }
+ }
+ QVERIFY(file.isValid());
+ view.setCurrentIndex(file);
+ QVERIFY(view.previewWidget() != (QWidget*)0);
+
+ QWidget *previewWidget = new QWidget(&view);
+ view.setPreviewWidget(previewWidget);
+ QCOMPARE(view.previewWidget(), previewWidget);
+ QVERIFY(previewWidget->parent() != ((QWidget*)&view));
+ view.setCurrentIndex(home);
+
+ // previewWidget should be marked for deletion
+ QWidget *previewWidget2 = new QWidget(&view);
+ view.setPreviewWidget(previewWidget2);
+ QCOMPARE(view.previewWidget(), previewWidget2);
+}
+
+void tst_QColumnView::swapPreview()
+{
+ // swap the preview widget in updatePreviewWidget
+ QColumnView view;
+ QStringList sl;
+ sl << QLatin1String("test");
+ QStringListModel model(sl);
+ view.setModel(&model);
+ view.setCurrentIndex(view.indexAt(QPoint(1, 1)));
+ connect(&view, SIGNAL(updatePreviewWidget(const QModelIndex &)),
+ this, SLOT(setPreviewWidget()));
+ view.setCurrentIndex(view.indexAt(QPoint(1, 1)));
+ QTest::qWait(ANIMATION_DELAY);
+ qApp->processEvents();
+}
+
+void tst_QColumnView::setPreviewWidget()
+{
+ ((QColumnView*)sender())->setPreviewWidget(new QWidget);
+}
+
+void tst_QColumnView::sizes()
+{
+ QColumnView view;
+ QCOMPARE(view.columnWidths().count(), 0);
+
+ QList<int> newSizes;
+ newSizes << 10 << 4 << 50 << 6;
+
+ QList<int> visibleSizes;
+ view.setColumnWidths(newSizes);
+ QCOMPARE(view.columnWidths(), visibleSizes);
+
+ QDirModel model;
+ view.setModel(&model);
+ QModelIndex home = model.index(QDir::homePath());
+ view.setCurrentIndex(home);
+
+ QList<int> postSizes = view.columnWidths().mid(0, newSizes.count());
+ QCOMPARE(postSizes, newSizes.mid(0, postSizes.count()));
+
+ QVERIFY(view.columnWidths().count() > 1);
+ QList<int> smallerSizes;
+ smallerSizes << 6;
+ view.setColumnWidths(smallerSizes);
+ QList<int> expectedSizes = newSizes;
+ expectedSizes[0] = 6;
+ postSizes = view.columnWidths().mid(0, newSizes.count());
+ QCOMPARE(postSizes, expectedSizes.mid(0, postSizes.count()));
+}
+
+void tst_QColumnView::rowDelegate()
+{
+ ColumnView view;
+ QItemDelegate *d = new QItemDelegate;
+ view.setItemDelegateForRow(3, d);
+
+ QDirModel model;
+ view.setModel(&model);
+ for (int i = 0; i < view.createdColumns.count(); ++i) {
+ QAbstractItemView *column = view.createdColumns.at(i);
+ QCOMPARE(column->itemDelegateForRow(3), (QAbstractItemDelegate*)d);
+ }
+ delete d;
+}
+
+void tst_QColumnView::resize()
+{
+ QWidget topLevel;
+ ColumnView view(&topLevel);
+ QDirModel model;
+ view.setModel(&model);
+ view.resize(200, 200);
+
+ topLevel.show();
+ QModelIndex home = model.index(QDir::homePath()).parent();
+ view.setCurrentIndex(home);
+ QTest::qWait(ANIMATION_DELAY);
+ view.resize(200, 300);
+ QTest::qWait(ANIMATION_DELAY);
+
+ QVERIFY(view.horizontalScrollBar()->maximum() != 0);
+ view.resize(view.horizontalScrollBar()->maximum() * 10, 300);
+ QTest::qWait(ANIMATION_DELAY);
+ QVERIFY(view.horizontalScrollBar()->maximum() <= 0);
+}
+
+void tst_QColumnView::changeSameColumn()
+{
+ ColumnView view;
+ TreeModel model;
+ view.setModel(&model);
+ QModelIndex second;
+
+ QModelIndex home = model.secondLevel();
+ //index(QDir::homePath());
+ view.setCurrentIndex(home);
+ for (int i = 0; i < model.rowCount(home.parent()); ++i) {
+ QModelIndex idx = model.index(i, 0, home.parent());
+ if (model.hasChildren(idx) && idx != home) {
+ second = idx;
+ break;
+ }
+ }
+ QVERIFY(second.isValid());
+
+ QList<QPointer<QAbstractItemView> > old = view.createdColumns;
+ view.setCurrentIndex(second);
+
+ QCOMPARE(old, view.createdColumns);
+}
+
+void tst_QColumnView::parentCurrentIndex_data()
+{
+ QTest::addColumn<int>("firstRow");
+ QTest::addColumn<int>("secondRow");
+ QTest::newRow("down") << 0 << 1;
+ QTest::newRow("up") << 1 << 0;
+}
+
+void tst_QColumnView::parentCurrentIndex()
+{
+ QFETCH(int, firstRow);
+ QFETCH(int, secondRow);
+
+ ColumnView view;
+ TreeModel model;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex first;
+ QModelIndex second;
+ QModelIndex third;
+ first = model.index(0, 0, QModelIndex());
+ second = model.index(firstRow, 0, first);
+ third = model.index(0, 0, second);
+ QVERIFY(first.isValid());
+ QVERIFY(second.isValid());
+ QVERIFY(third.isValid());
+ view.setCurrentIndex(third);
+ QTest::qWait(ANIMATION_DELAY);
+ QTRY_COMPARE(view.createdColumns[0]->currentIndex(), first);
+ QTRY_COMPARE(view.createdColumns[1]->currentIndex(), second);
+ QTRY_COMPARE(view.createdColumns[2]->currentIndex(), third);
+
+ first = model.index(0, 0, QModelIndex());
+ second = model.index(secondRow, 0, first);
+ third = model.index(0, 0, second);
+ QVERIFY(first.isValid());
+ QVERIFY(second.isValid());
+ QVERIFY(third.isValid());
+ view.setCurrentIndex(third);
+ QTest::qWait(ANIMATION_DELAY);
+ QTRY_COMPARE(view.createdColumns[0]->currentIndex(), first);
+ QTRY_COMPARE(view.createdColumns[1]->currentIndex(), second);
+ QTRY_COMPARE(view.createdColumns[2]->currentIndex(), third);
+}
+
+void tst_QColumnView::pullRug_data()
+{
+ QTest::addColumn<bool>("removeModel");
+ QTest::newRow("model") << true;
+ QTest::newRow("index") << false;
+}
+
+void tst_QColumnView::pullRug()
+{
+ QFETCH(bool, removeModel);
+ ColumnView view;
+ TreeModel model;
+ view.setModel(&model);
+ QModelIndex home = model.thirdLevel();
+ view.setCurrentIndex(home);
+ if (removeModel)
+ view.setModel(0);
+ else
+ view.setCurrentIndex(QModelIndex());
+ QTest::qWait(ANIMATION_DELAY);
+ // don't crash
+}
+
+void tst_QColumnView::dynamicModelChanges()
+{
+ struct MyItemDelegate : public QItemDelegate
+ {
+ void paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+ {
+ paintedIndexes += index;
+ QItemDelegate::paint(painter, option, index);
+ }
+
+ mutable QSet<QModelIndex> paintedIndexes;
+
+ } delegate;;
+ QStandardItemModel model;
+ ColumnView view;
+ view.setModel(&model);
+ view.setItemDelegate(&delegate);
+ view.show();
+
+ QStandardItem *item = new QStandardItem(QLatin1String("item"));
+ model.appendRow(item);
+
+ QTest::qWait(200); //let the time for painting to occur
+ QCOMPARE(delegate.paintedIndexes.count(), 1);
+ QCOMPARE(*delegate.paintedIndexes.begin(), model.index(0,0));
+
+
+}
+
+
+QTEST_MAIN(tst_QColumnView)
+#include "tst_qcolumnview.moc"
+
diff --git a/tests/auto/widgets/itemviews/qdatawidgetmapper/.gitignore b/tests/auto/widgets/itemviews/qdatawidgetmapper/.gitignore
new file mode 100644
index 0000000000..9b0a1e6399
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdatawidgetmapper/.gitignore
@@ -0,0 +1 @@
+tst_qdatawidgetmapper
diff --git a/tests/auto/widgets/itemviews/qdatawidgetmapper/qdatawidgetmapper.pro b/tests/auto/widgets/itemviews/qdatawidgetmapper/qdatawidgetmapper.pro
new file mode 100644
index 0000000000..64e3b57291
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdatawidgetmapper/qdatawidgetmapper.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdatawidgetmapper.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp b/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp
new file mode 100644
index 0000000000..7488195497
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+#include <QtTest/QtTest>
+
+class tst_QDataWidgetMapper: public QObject
+{
+ Q_OBJECT
+private slots:
+ void setModel();
+ void navigate();
+ void addMapping();
+ void currentIndexChanged();
+ void changingValues();
+ void setData();
+ void mappedWidgetAt();
+
+ void comboBox();
+};
+
+static QStandardItemModel *testModel(QObject *parent = 0)
+{
+ QStandardItemModel *model = new QStandardItemModel(10, 10, parent);
+
+ for (int row = 0; row < 10; ++row) {
+ for (int col = 0; col < 10; ++col)
+ model->setData(model->index(row, col), QString("item %1 %2").arg(row).arg(col));
+ }
+
+ return model;
+}
+
+void tst_QDataWidgetMapper::setModel()
+{
+ QDataWidgetMapper mapper;
+
+ QCOMPARE(mapper.model(), (QAbstractItemModel *)0);
+
+ { // let the model go out of scope firstma
+ QStandardItemModel model;
+ mapper.setModel(&model);
+ QCOMPARE(mapper.model(), static_cast<QAbstractItemModel *>(&model));
+ }
+
+ QCOMPARE(mapper.model(), (QAbstractItemModel *)0);
+
+ { // let the mapper go out of scope first
+ QStandardItemModel model2;
+ QDataWidgetMapper mapper2;
+ mapper2.setModel(&model2);
+ }
+}
+
+void tst_QDataWidgetMapper::navigate()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+
+ QLineEdit edit1;
+ QLineEdit edit2;
+ QLineEdit edit3;
+
+ mapper.addMapping(&edit1, 0);
+ mapper.toFirst();
+ mapper.addMapping(&edit2, 1);
+ mapper.addMapping(&edit3, 2);
+
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QVERIFY(edit2.text().isEmpty());
+ QVERIFY(edit3.text().isEmpty());
+ QVERIFY(mapper.submit());
+ edit2.setText(QString("item 0 1"));
+ edit3.setText(QString("item 0 2"));
+ QVERIFY(mapper.submit());
+
+ mapper.toFirst(); //this will repopulate
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QCOMPARE(edit2.text(), QString("item 0 1"));
+ QCOMPARE(edit3.text(), QString("item 0 2"));
+
+
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QCOMPARE(edit2.text(), QString("item 0 1"));
+ QCOMPARE(edit3.text(), QString("item 0 2"));
+
+ mapper.toPrevious(); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QCOMPARE(edit2.text(), QString("item 0 1"));
+ QCOMPARE(edit3.text(), QString("item 0 2"));
+
+ mapper.toNext();
+ QCOMPARE(edit1.text(), QString("item 1 0"));
+ QCOMPARE(edit2.text(), QString("item 1 1"));
+ QCOMPARE(edit3.text(), QString("item 1 2"));
+
+ mapper.toLast();
+ QCOMPARE(edit1.text(), QString("item 9 0"));
+ QCOMPARE(edit2.text(), QString("item 9 1"));
+ QCOMPARE(edit3.text(), QString("item 9 2"));
+
+ mapper.toNext(); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 9 0"));
+ QCOMPARE(edit2.text(), QString("item 9 1"));
+ QCOMPARE(edit3.text(), QString("item 9 2"));
+
+ mapper.setCurrentIndex(4);
+ QCOMPARE(edit1.text(), QString("item 4 0"));
+ QCOMPARE(edit2.text(), QString("item 4 1"));
+ QCOMPARE(edit3.text(), QString("item 4 2"));
+
+ mapper.setCurrentIndex(-1); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 4 0"));
+ QCOMPARE(edit2.text(), QString("item 4 1"));
+ QCOMPARE(edit3.text(), QString("item 4 2"));
+
+ mapper.setCurrentIndex(10); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 4 0"));
+ QCOMPARE(edit2.text(), QString("item 4 1"));
+ QCOMPARE(edit3.text(), QString("item 4 2"));
+
+ mapper.setCurrentModelIndex(QModelIndex()); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 4 0"));
+ QCOMPARE(edit2.text(), QString("item 4 1"));
+ QCOMPARE(edit3.text(), QString("item 4 2"));
+
+ mapper.setCurrentModelIndex(model->index(6, 0));
+ QCOMPARE(edit1.text(), QString("item 6 0"));
+ QCOMPARE(edit2.text(), QString("item 6 1"));
+ QCOMPARE(edit3.text(), QString("item 6 2"));
+
+ /* now try vertical navigation */
+
+ mapper.setOrientation(Qt::Vertical);
+
+ mapper.addMapping(&edit1, 0);
+ mapper.addMapping(&edit2, 1);
+ mapper.addMapping(&edit3, 2);
+
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QCOMPARE(edit2.text(), QString("item 1 0"));
+ QCOMPARE(edit3.text(), QString("item 2 0"));
+
+ mapper.toPrevious(); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QCOMPARE(edit2.text(), QString("item 1 0"));
+ QCOMPARE(edit3.text(), QString("item 2 0"));
+
+ mapper.toNext();
+ QCOMPARE(edit1.text(), QString("item 0 1"));
+ QCOMPARE(edit2.text(), QString("item 1 1"));
+ QCOMPARE(edit3.text(), QString("item 2 1"));
+
+ mapper.toLast();
+ QCOMPARE(edit1.text(), QString("item 0 9"));
+ QCOMPARE(edit2.text(), QString("item 1 9"));
+ QCOMPARE(edit3.text(), QString("item 2 9"));
+
+ mapper.toNext(); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 0 9"));
+ QCOMPARE(edit2.text(), QString("item 1 9"));
+ QCOMPARE(edit3.text(), QString("item 2 9"));
+
+ mapper.setCurrentIndex(4);
+ QCOMPARE(edit1.text(), QString("item 0 4"));
+ QCOMPARE(edit2.text(), QString("item 1 4"));
+ QCOMPARE(edit3.text(), QString("item 2 4"));
+
+ mapper.setCurrentIndex(-1); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 0 4"));
+ QCOMPARE(edit2.text(), QString("item 1 4"));
+ QCOMPARE(edit3.text(), QString("item 2 4"));
+
+ mapper.setCurrentIndex(10); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 0 4"));
+ QCOMPARE(edit2.text(), QString("item 1 4"));
+ QCOMPARE(edit3.text(), QString("item 2 4"));
+
+ mapper.setCurrentModelIndex(QModelIndex()); // should do nothing
+ QCOMPARE(edit1.text(), QString("item 0 4"));
+ QCOMPARE(edit2.text(), QString("item 1 4"));
+ QCOMPARE(edit3.text(), QString("item 2 4"));
+
+ mapper.setCurrentModelIndex(model->index(0, 6));
+ QCOMPARE(edit1.text(), QString("item 0 6"));
+ QCOMPARE(edit2.text(), QString("item 1 6"));
+ QCOMPARE(edit3.text(), QString("item 2 6"));
+}
+
+void tst_QDataWidgetMapper::addMapping()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+
+ QLineEdit edit1;
+ mapper.addMapping(&edit1, 0);
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+
+ mapper.addMapping(&edit1, 1);
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString("item 0 1"));
+
+ QCOMPARE(mapper.mappedSection(&edit1), 1);
+
+ edit1.clear();
+ mapper.removeMapping(&edit1);
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString());
+
+ {
+ QLineEdit edit2;
+ mapper.addMapping(&edit2, 2);
+ mapper.toFirst();
+ QCOMPARE(edit2.text(), QString("item 0 2"));
+ } // let the edit go out of scope
+
+ QCOMPARE(mapper.mappedWidgetAt(2), (QWidget *)0);
+ mapper.toLast();
+}
+
+void tst_QDataWidgetMapper::currentIndexChanged()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+
+ QSignalSpy spy(&mapper, SIGNAL(currentIndexChanged(int)));
+
+ mapper.toFirst();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).toInt(), 0);
+
+ mapper.toNext();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).toInt(), 1);
+
+ mapper.setCurrentIndex(7);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).toInt(), 7);
+
+ mapper.setCurrentIndex(-1);
+ QCOMPARE(spy.count(), 0);
+
+ mapper.setCurrentIndex(42);
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QDataWidgetMapper::changingValues()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+
+ QLineEdit edit1;
+ mapper.addMapping(&edit1, 0);
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+
+ QLineEdit edit2;
+ mapper.addMapping(&edit2, 0, "text");
+ mapper.toFirst();
+ QCOMPARE(edit2.text(), QString("item 0 0"));
+
+ model->setData(model->index(0, 0), QString("changed"));
+ QCOMPARE(edit1.text(), QString("changed"));
+ QCOMPARE(edit2.text(), QString("changed"));
+}
+
+void tst_QDataWidgetMapper::setData()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+
+ QLineEdit edit1;
+ QLineEdit edit2;
+ QLineEdit edit3;
+
+ mapper.addMapping(&edit1, 0);
+ mapper.addMapping(&edit2, 1);
+ mapper.addMapping(&edit3, 0, "text");
+ mapper.toFirst();
+ QCOMPARE(edit1.text(), QString("item 0 0"));
+ QCOMPARE(edit2.text(), QString("item 0 1"));
+ QCOMPARE(edit3.text(), QString("item 0 0"));
+
+ edit1.setText("new text");
+
+ mapper.submit();
+ QCOMPARE(model->data(model->index(0, 0)).toString(), QString("new text"));
+
+ edit3.setText("more text");
+
+ mapper.submit();
+ QCOMPARE(model->data(model->index(0, 0)).toString(), QString("more text"));
+}
+
+void tst_QDataWidgetMapper::comboBox()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+ mapper.setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
+
+ QComboBox readOnlyBox;
+ readOnlyBox.setEditable(false);
+ readOnlyBox.addItem("read only item 0");
+ readOnlyBox.addItem("read only item 1");
+ readOnlyBox.addItem("read only item 2");
+
+ QComboBox readWriteBox;
+ readWriteBox.setEditable(true);
+ readWriteBox.addItem("read write item 0");
+ readWriteBox.addItem("read write item 1");
+ readWriteBox.addItem("read write item 2");
+
+ // populat the combo boxes with data
+ mapper.addMapping(&readOnlyBox, 0, "currentIndex");
+ mapper.addMapping(&readWriteBox, 1, "currentText");
+ mapper.toFirst();
+
+ QCOMPARE(readOnlyBox.currentText(), QString("read only item 0"));
+ QCOMPARE(readWriteBox.currentText(), QString("read write item 0"));
+
+ // set some new values on the boxes
+ readOnlyBox.setCurrentIndex(1);
+ readWriteBox.setEditText("read write item y");
+
+ mapper.submit();
+
+ // make sure the new values are in the model
+ QCOMPARE(model->data(model->index(0, 0)).toInt(), 1);
+ QCOMPARE(model->data(model->index(0, 1)).toString(), QString("read write item y"));
+
+ // now test updating of the widgets
+ model->setData(model->index(0, 0), 2, Qt::EditRole);
+ model->setData(model->index(0, 1), QString("read write item z"), Qt::EditRole);
+
+ QCOMPARE(readOnlyBox.currentIndex(), 2);
+ QEXPECT_FAIL("", "See task 125493 and QTBUG-428", Abort);
+ QCOMPARE(readWriteBox.currentText(), QString("read write item z"));
+}
+
+void tst_QDataWidgetMapper::mappedWidgetAt()
+{
+ QDataWidgetMapper mapper;
+ QAbstractItemModel *model = testModel(&mapper);
+ mapper.setModel(model);
+
+ QLineEdit lineEdit1;
+ QLineEdit lineEdit2;
+
+ QCOMPARE(mapper.mappedWidgetAt(432312), (QWidget*)0);
+
+ mapper.addMapping(&lineEdit1, 1);
+ mapper.addMapping(&lineEdit2, 2);
+
+ QCOMPARE(mapper.mappedWidgetAt(1), static_cast<QWidget *>(&lineEdit1));
+ QCOMPARE(mapper.mappedWidgetAt(2), static_cast<QWidget *>(&lineEdit2));
+
+ mapper.addMapping(&lineEdit2, 4242);
+
+ QCOMPARE(mapper.mappedWidgetAt(2), (QWidget*)0);
+ QCOMPARE(mapper.mappedWidgetAt(4242), static_cast<QWidget *>(&lineEdit2));
+}
+
+QTEST_MAIN(tst_QDataWidgetMapper)
+#include "tst_qdatawidgetmapper.moc"
diff --git a/tests/auto/widgets/itemviews/qdirmodel/.gitignore b/tests/auto/widgets/itemviews/qdirmodel/.gitignore
new file mode 100644
index 0000000000..641c99880f
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/.gitignore
@@ -0,0 +1 @@
+tst_qdirmodel
diff --git a/tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/dummy b/tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/dummy
new file mode 100644
index 0000000000..4d6a3b44f4
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/dummy
@@ -0,0 +1 @@
+ECHO is on.
diff --git a/tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/test b/tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/test
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/test
diff --git a/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro b/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro
new file mode 100644
index 0000000000..bc4e98d6ff
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro
@@ -0,0 +1,20 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdirmodel.cpp
+
+wince* {
+ addit.files = dirtest\\test1\\*
+ addit.path = dirtest\\test1
+ tests.files = test\\*
+ tests.path = test
+ sourceFile.files = tst_qdirmodel.cpp
+ sourceFile.path = .
+ DEPLOYMENT += addit tests sourceFile
+}
+
+wince*: {
+ DEFINES += SRCDIR=\\\"./\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
diff --git a/tests/auto/widgets/itemviews/qdirmodel/test/file01.tst b/tests/auto/widgets/itemviews/qdirmodel/test/file01.tst
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/test/file01.tst
diff --git a/tests/auto/widgets/itemviews/qdirmodel/test/file02.tst b/tests/auto/widgets/itemviews/qdirmodel/test/file02.tst
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/test/file02.tst
diff --git a/tests/auto/widgets/itemviews/qdirmodel/test/file03.tst b/tests/auto/widgets/itemviews/qdirmodel/test/file03.tst
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/test/file03.tst
diff --git a/tests/auto/widgets/itemviews/qdirmodel/test/file04.tst b/tests/auto/widgets/itemviews/qdirmodel/test/file04.tst
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/test/file04.tst
diff --git a/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp b/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp
new file mode 100644
index 0000000000..70eb17b5e6
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp
@@ -0,0 +1,698 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qdirmodel.h>
+#include <qapplication.h>
+#include <qtreeview.h>
+#include <qdir.h>
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QDirModel : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ tst_QDirModel();
+ virtual ~tst_QDirModel();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ /*
+ void construct();
+ void rowCount();
+ void columnCount();
+ void t_data();
+ void setData();
+ void hasChildren();
+ void isEditable();
+ void isDragEnabled();
+ void isDropEnabled();
+ void sort();
+ */
+ bool rowsAboutToBeRemoved_init(const QString &test_path, const QStringList &initial_files);
+ bool rowsAboutToBeRemoved_cleanup(const QString &test_path);
+ void rowsAboutToBeRemoved_data();
+ void rowsAboutToBeRemoved();
+
+ void mkdir_data();
+ void mkdir();
+
+ void rmdir_data();
+ void rmdir();
+
+ void filePath();
+
+#ifdef Q_OS_UNIX
+ void hidden();
+#endif
+
+ void fileName();
+ void fileName_data();
+ void task196768_sorting();
+ void filter();
+
+ void task244669_remove();
+
+ void roleNames_data();
+ void roleNames();
+};
+
+// Testing get/set functions
+void tst_QDirModel::getSetCheck()
+{
+ QDirModel obj1;
+ // QFileIconProvider * QDirModel::iconProvider()
+ // void QDirModel::setIconProvider(QFileIconProvider *)
+ QFileIconProvider *var1 = new QFileIconProvider;
+ obj1.setIconProvider(var1);
+ QCOMPARE(var1, obj1.iconProvider());
+ obj1.setIconProvider((QFileIconProvider *)0);
+ QCOMPARE((QFileIconProvider *)0, obj1.iconProvider());
+ delete var1;
+
+ // bool QDirModel::resolveSymlinks()
+ // void QDirModel::setResolveSymlinks(bool)
+ obj1.setResolveSymlinks(false);
+ QCOMPARE(false, obj1.resolveSymlinks());
+ obj1.setResolveSymlinks(true);
+ QCOMPARE(true, obj1.resolveSymlinks());
+
+ // bool QDirModel::lazyChildCount()
+ // void QDirModel::setLazyChildCount(bool)
+ obj1.setLazyChildCount(false);
+ QCOMPARE(false, obj1.lazyChildCount());
+ obj1.setLazyChildCount(true);
+ QCOMPARE(true, obj1.lazyChildCount());
+}
+
+
+Q_DECLARE_METATYPE(QModelIndex)
+Q_DECLARE_METATYPE(QModelIndexList)
+
+tst_QDirModel::tst_QDirModel()
+
+{
+}
+
+tst_QDirModel::~tst_QDirModel()
+{
+}
+
+void tst_QDirModel::initTestCase()
+{
+}
+
+void tst_QDirModel::cleanupTestCase()
+{
+ QDir current;
+ current.rmdir(".qtest_hidden");
+}
+
+void tst_QDirModel::init()
+{
+}
+
+void tst_QDirModel::cleanup()
+{
+}
+
+/*
+ tests
+*/
+/*
+void tst_QDirModel::construct()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ index = model.index(2, 0, index);
+ QVERIFY(index.isValid());
+ QFileInfo info(QDir::currentPath() + "/test/file03.tst");
+ QCOMPARE(model.filePath(index), info.absoluteFilePath());
+}
+
+void tst_QDirModel::rowCount()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+ QCOMPARE(model.rowCount(index), 4);
+}
+
+void tst_QDirModel::columnCount()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+ QCOMPARE(model.columnCount(index), 4);
+}
+
+void tst_QDirModel::t_data()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+ QCOMPARE(model.rowCount(index), 4);
+
+ index = model.index(2, 0, index);
+ QVERIFY(index.isValid());
+ QCOMPARE(model.data(index).toString(), QString::fromLatin1("file03.tst"));
+ QCOMPARE(model.rowCount(index), 0);
+}
+
+void tst_QDirModel::setData()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+
+ index = model.index(2, 0, index);
+ QVERIFY(index.isValid());
+ QVERIFY(!model.setData(index, "file0X.tst", Qt::EditRole));
+}
+
+void tst_QDirModel::hasChildren()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+
+ index = model.index(2, 0, index);
+ QVERIFY(index.isValid());
+ QVERIFY(!model.hasChildren(index));
+}
+
+void tst_QDirModel::isEditable()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+
+ index = model.index(2, 0, index);
+ QVERIFY(index.isValid());
+ QVERIFY(!(model.flags(index) & Qt::ItemIsEditable));
+}
+
+void tst_QDirModel::isDragEnabled()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+
+ index = model.index(2, 0, index);
+ QVERIFY(index.isValid());
+ QVERIFY(model.flags(index) & Qt::ItemIsDragEnabled);
+}
+
+void tst_QDirModel::isDropEnabled()
+{
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/test");
+ QVERIFY(index.isValid());
+
+ index = model.index(2, 0, index);
+ QVERIFY(!(model.flags(index) & Qt::ItemIsDropEnabled));
+}
+
+void tst_QDirModel::sort()
+{
+ QDirModel model;
+ QModelIndex parent = model.index(QDir::currentPath() + "/test");
+ QVERIFY(parent.isValid());
+
+ QModelIndex index = model.index(0, 0, parent);
+ QCOMPARE(model.data(index).toString(), QString::fromLatin1("file01.tst"));
+
+ index = model.index(3, 0, parent);
+ QCOMPARE(model.data(index).toString(), QString::fromLatin1("file04.tst"));
+
+ model.sort(0, Qt::DescendingOrder);
+ parent = model.index(QDir::currentPath() + "/test");
+
+ index = model.index(0, 0, parent);
+ QCOMPARE(model.data(index).toString(), QString::fromLatin1("file04.tst"));
+
+ index = model.index(3, 0, parent);
+ QCOMPARE(model.data(index).toString(), QString::fromLatin1("file01.tst"));
+}
+*/
+
+void tst_QDirModel::mkdir_data()
+{
+ QTest::addColumn<QString>("dirName"); // the directory to be made under <currentpath>/dirtest
+ QTest::addColumn<bool>("mkdirSuccess");
+ QTest::addColumn<int>("rowCount");
+
+ QTest::newRow("okDirName") << QString("test2") << true << 2;
+ QTest::newRow("existingDirName") << QString("test1") << false << 1;
+ QTest::newRow("nameWithSpace") << QString("ab cd") << true << 2;
+ QTest::newRow("emptyDirName") << QString("") << false << 1;
+ QTest::newRow("nullDirName") << QString() << false << 1;
+
+/*
+ QTest::newRow("recursiveDirName") << QString("test2/test3") << false << false;
+ QTest::newRow("singleDotDirName") << QString("./test3") << true << true;
+ QTest::newRow("outOfTreeDirName") << QString("../test4") << false << false;
+ QTest::newRow("insideTreeDirName") << QString("../dirtest/test4") << true << true;
+ QTest::newRow("insideTreeDirName2") << QString("./././././../dirtest/./../dirtest/test4") << true << true;
+ QTest::newRow("absoluteDirName") << QString(QDir::currentPath() + "/dirtest/test5") << true << true;
+ QTest::newRow("outOfTreeDirName") << QString(QDir::currentPath() + "/test5") << false << false;
+
+ // Directory names only illegal on Windows
+#ifdef Q_WS_WIN
+ QTest::newRow("illegalDirName") << QString("*") << false << false;
+ QTest::newRow("illegalDirName2") << QString("|") << false << false;
+ QTest::newRow("onlySpace") << QString(" ") << false << false;
+#endif
+ */
+}
+
+void tst_QDirModel::mkdir()
+{
+ QFETCH(QString, dirName);
+ QFETCH(bool, mkdirSuccess);
+ QFETCH(int, rowCount);
+
+ QDirModel model;
+ model.setReadOnly(false);
+
+ QModelIndex parent = model.index(SRCDIR "dirtest");
+ QVERIFY(parent.isValid());
+ QCOMPARE(model.rowCount(parent), 1); // start out with only 'test1' - in's in the depot
+
+ QModelIndex index = model.mkdir(parent, dirName);
+ bool success = index.isValid();
+ int rows = model.rowCount(parent);
+
+ if (success && !model.rmdir(index))
+ QVERIFY(QDir(SRCDIR "dirtests").rmdir(dirName));
+
+ QCOMPARE(rows, rowCount);
+ QCOMPARE(success, mkdirSuccess);
+}
+
+void tst_QDirModel::rmdir_data()
+{
+ QTest::addColumn<QString>("dirName"); // <currentpath>/dirtest/dirname
+ QTest::addColumn<bool>("rmdirSuccess");
+ QTest::addColumn<int>("rowCount");
+
+ QTest::newRow("okDirName") << QString("test2") << true << 2;
+ QTest::newRow("existingDirName") << QString("test1") << false << 1;
+ QTest::newRow("nameWithSpace") << QString("ab cd") << true << 2;
+ QTest::newRow("emptyDirName") << QString("") << false << 1;
+ QTest::newRow("nullDirName") << QString() << false << 1;
+}
+
+void tst_QDirModel::rmdir()
+{
+ QFETCH(QString, dirName);
+ QFETCH(bool, rmdirSuccess);
+ QFETCH(int, rowCount);
+
+ QDirModel model;
+ model.setReadOnly(false);
+
+ QModelIndex parent = model.index(SRCDIR "/dirtest");
+ QVERIFY(parent.isValid());
+ QCOMPARE(model.rowCount(parent), 1); // start out with only 'test1' - in's in the depot
+
+ QModelIndex index;
+ if (rmdirSuccess) {
+ index = model.mkdir(parent, dirName);
+ QVERIFY(index.isValid());
+ }
+
+ int rows = model.rowCount(parent);
+ bool success = model.rmdir(index);
+
+ if (!success) { // cleanup
+ QDir dirtests(SRCDIR "/dirtests/");
+ dirtests.rmdir(dirName);
+ }
+
+ QCOMPARE(rows, rowCount);
+ QCOMPARE(success, rmdirSuccess);
+}
+
+void tst_QDirModel::rowsAboutToBeRemoved_data()
+{
+ QTest::addColumn<QString>("test_path");
+ QTest::addColumn<QStringList>("initial_files");
+ QTest::addColumn<int>("remove_row");
+ QTest::addColumn<QStringList>("remove_files");
+ QTest::addColumn<QStringList>("expected_files");
+
+ QString test_path = "test2";
+ QStringList initial_files = (QStringList()
+ << "file1.tst"
+ << "file2.tst"
+ << "file3.tst"
+ << "file4.tst");
+
+ QTest::newRow("removeFirstRow")
+ << test_path
+ << initial_files
+ << 0
+ << (QStringList() << "file1.tst")
+ << (QStringList() << "file2.tst" << "file3.tst" << "file4.tst");
+
+ QTest::newRow("removeMiddle")
+ << test_path
+ << initial_files
+ << 1
+ << (QStringList() << "file2.tst")
+ << (QStringList() << "file1.tst" << "file3.tst" << "file4.tst");
+
+ QTest::newRow("removeLastRow")
+ << test_path
+ << initial_files
+ << 3
+ << (QStringList() << "file4.tst")
+ << (QStringList() << "file1.tst" << "file2.tst" << "file3.tst");
+
+}
+
+bool tst_QDirModel::rowsAboutToBeRemoved_init(const QString &test_path, const QStringList &initial_files)
+{
+ QString path = QDir::currentPath() + "/" + test_path;
+ if (!QDir::current().mkdir(test_path) && false) { // FIXME
+ qDebug() << "failed to create dir" << path;
+ return false;
+ }
+
+ for (int i = 0; i < initial_files.count(); ++i) {
+ QFile file(path + "/" + initial_files.at(i));
+ if (!file.open(QIODevice::WriteOnly)) {
+ qDebug() << "failed to open file" << initial_files.at(i);
+ return false;
+ }
+ if (!file.resize(1024)) {
+ qDebug() << "failed to resize file" << initial_files.at(i);
+ return false;
+ }
+ if (!file.flush()) {
+ qDebug() << "failed to flush file" << initial_files.at(i);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool tst_QDirModel::rowsAboutToBeRemoved_cleanup(const QString &test_path)
+{
+ QString path = QDir::currentPath() + "/" + test_path;
+ QDir dir(path, "*", QDir::SortFlags(QDir::Name|QDir::IgnoreCase), QDir::Files);
+ QStringList files = dir.entryList();
+
+ for (int i = 0; i < files.count(); ++i) {
+ if (!dir.remove(files.at(i))) {
+ qDebug() << "failed to remove file" << files.at(i);
+ return false;
+ }
+ }
+
+ if (!QDir::current().rmdir(test_path) && false) { // FIXME
+ qDebug() << "failed to remove dir" << test_path;
+ return false;
+ }
+
+ return true;
+}
+
+void tst_QDirModel::rowsAboutToBeRemoved()
+{
+ QFETCH(QString, test_path);
+ QFETCH(QStringList, initial_files);
+ QFETCH(int, remove_row);
+ QFETCH(QStringList, remove_files);
+ QFETCH(QStringList, expected_files);
+
+ rowsAboutToBeRemoved_cleanup(test_path); // clean up first
+ QVERIFY(rowsAboutToBeRemoved_init(test_path, initial_files));
+
+ QDirModel model;
+ model.setReadOnly(false);
+
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+
+ // NOTE: QDirModel will call refresh() when a file is removed. refresh() will reread the entire directory,
+ // and emit layoutAboutToBeChanged and layoutChange. So, instead of checking for
+ // rowsAboutToBeRemoved/rowsRemoved we check for layoutAboutToBeChanged/layoutChanged
+ QSignalSpy spy(&model, SIGNAL(layoutAboutToBeChanged()));
+
+ QModelIndex parent = model.index(test_path);
+ QVERIFY(parent.isValid());
+
+ // remove the file
+ {
+ QModelIndex index = model.index(remove_row, 0, parent);
+ QVERIFY(index.isValid());
+ QVERIFY(model.remove(index));
+ }
+
+ QCOMPARE(spy.count(), 1);
+
+ // Compare the result
+ for (int row = 0; row < expected_files.count(); ++row) {
+ QModelIndex index = model.index(row, 0, parent);
+ QString str = index.data().toString();
+ QCOMPARE(str, expected_files.at(row));
+ }
+
+ QVERIFY(rowsAboutToBeRemoved_cleanup(test_path));
+}
+
+#ifdef Q_OS_UNIX
+void tst_QDirModel::hidden()
+{
+ QDir current;
+ current.mkdir(".qtest_hidden");
+
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/.qtest_hidden");
+ //QVERIFY(!index.isValid()); // hidden items are not listed, but if you specify a valid path, it will give a valid index
+
+ current.mkdir(".qtest_hidden/qtest_visible");
+ QModelIndex index2 = model.index(QDir::currentPath() + "/.qtest_hidden/qtest_visible");
+ QVERIFY(index2.isValid());
+
+ QDirModel model2;
+ model2.setFilter(model2.filter() | QDir::Hidden);
+ index = model2.index(QDir::currentPath() + "/.qtest_hidden");
+ QVERIFY(index.isValid());
+}
+#endif
+
+void tst_QDirModel::fileName_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("result");
+
+ QTest::newRow("invalid") << "" << "";
+ //QTest::newRow("root") << "/" << "/";
+ //QTest::newRow("home") << "/home" << "home";
+ // TODO add symlink test too
+}
+
+void tst_QDirModel::fileName()
+{
+ QDirModel model;
+
+ QFETCH(QString, path);
+ QFETCH(QString, result);
+ QCOMPARE(model.fileName(model.index(path)), result);
+}
+
+#if 0
+#ifdef Q_OS_UNIX
+void tst_QDirModel::unreadable()
+{
+ //QFile current("qtest_unreadable");
+ //QVERIFY(current.setPermissions(QFile::WriteOwner));
+
+ QDirModel model;
+ QModelIndex index = model.index(QDir::currentPath() + "/qtest_unreadable");
+ QVERIFY(!index.isValid());
+
+ QDirModel model2;
+ model2.setFilter(model2.filter() | QDir::Hidden);
+ index = model2.index(QDir::currentPath() + "/qtest_unreadable");
+ QVERIFY(index.isValid());
+}
+#endif
+#endif
+
+void tst_QDirModel::filePath()
+{
+ QFile::remove(SRCDIR "test.lnk");
+ QVERIFY(QFile(SRCDIR "tst_qdirmodel.cpp").link(SRCDIR "test.lnk"));
+ QDirModel model;
+ model.setResolveSymlinks(false);
+ QModelIndex index = model.index(SRCDIR "test.lnk");
+ QVERIFY(index.isValid());
+#ifndef Q_OS_WINCE
+ QString path = SRCDIR;
+#else
+ QString path = QFileInfo(SRCDIR).absoluteFilePath() + "/";
+#endif
+ QCOMPARE(model.filePath(index), path + QString( "test.lnk"));
+ model.setResolveSymlinks(true);
+ QCOMPARE(model.filePath(index), path + QString( "tst_qdirmodel.cpp"));
+ QFile::remove(SRCDIR "test.lnk");
+}
+
+void tst_QDirModel::task196768_sorting()
+{
+ //this task showed that the persistent model indexes got corrupted when sorting
+ QString path = SRCDIR;
+
+ QDirModel model;
+
+ /* QDirModel has a bug if we show the content of the subdirectory inside a hidden directory
+ and we don't add QDir::Hidden. But as QDirModel is deprecated, we decided not to fix it. */
+ model.setFilter(QDir::AllEntries | QDir::Hidden | QDir::AllDirs);
+
+ QTreeView view;
+ QPersistentModelIndex index = model.index(path);
+ view.setModel(&model);
+ QModelIndex index2 = model.index(path);
+ QCOMPARE(index.data(), index2.data());
+ view.setRootIndex(index);
+ index2 = model.index(path);
+ QCOMPARE(index.data(), index2.data());
+ view.setCurrentIndex(index);
+ index2 = model.index(path);
+ QCOMPARE(index.data(), index2.data());
+ view.setSortingEnabled(true);
+ index2 = model.index(path);
+
+ QCOMPARE(index.data(), index2.data());
+}
+
+void tst_QDirModel::filter()
+{
+ QDirModel model;
+ model.setNameFilters(QStringList() << "*.nada");
+ QModelIndex index = model.index(SRCDIR "test");
+ QCOMPARE(model.rowCount(index), 0);
+ QModelIndex index2 = model.index(SRCDIR "test/file01.tst");
+ QVERIFY(!index2.isValid());
+ QCOMPARE(model.rowCount(index), 0);
+}
+
+void tst_QDirModel::task244669_remove()
+{
+ QFile f1(SRCDIR "dirtest/f1.txt");
+ QVERIFY(f1.open(QIODevice::WriteOnly));
+ f1.close();
+ QFile f2(SRCDIR "dirtest/f2.txt");
+ QVERIFY(f2.open(QIODevice::WriteOnly));
+ f2.close();
+
+ QDirModel model;
+ model.setReadOnly(false);
+ QPersistentModelIndex parent = model.index(SRCDIR "dirtest");
+ QPersistentModelIndex index2 = model.index(SRCDIR "dirtest/f2.txt");
+ QPersistentModelIndex index1 = model.index(SRCDIR "dirtest/f1.txt");
+
+ QVERIFY(parent.isValid());
+ QVERIFY(index1.isValid());
+ QVERIFY(index2.isValid());
+ QCOMPARE(parent.data() , model.index(SRCDIR "dirtest").data());
+ QCOMPARE(index1.data() , model.index(SRCDIR "dirtest/f1.txt").data());
+ QCOMPARE(index2.data() , model.index(SRCDIR "dirtest/f2.txt").data());
+
+ QVERIFY(model.remove(index1));
+
+ QVERIFY(parent.isValid());
+ QVERIFY(!index1.isValid());
+ QVERIFY(index2.isValid());
+ QCOMPARE(parent.data() , model.index(SRCDIR "dirtest").data());
+ QCOMPARE(index2.data() , model.index(SRCDIR "dirtest/f2.txt").data());
+
+ QVERIFY(model.remove(index2));
+
+ QVERIFY(parent.isValid());
+ QVERIFY(!index2.isValid());
+ QVERIFY(!index1.isValid());
+ QCOMPARE(parent.data() , model.index(SRCDIR "dirtest").data());
+}
+
+void tst_QDirModel::roleNames_data()
+{
+ QTest::addColumn<int>("role");
+ QTest::addColumn<QByteArray>("roleName");
+ QTest::newRow("decoration") << int(Qt::DecorationRole) << QByteArray("decoration");
+ QTest::newRow("display") << int(Qt::DisplayRole) << QByteArray("display");
+ QTest::newRow("fileIcon") << int(QDirModel::FileIconRole) << QByteArray("fileIcon");
+ QTest::newRow("filePath") << int(QDirModel::FilePathRole) << QByteArray("filePath");
+ QTest::newRow("fileName") << int(QDirModel::FileNameRole) << QByteArray("fileName");
+}
+
+void tst_QDirModel::roleNames()
+{
+ QDirModel model;
+ QHash<int, QByteArray> roles = model.roleNames();
+
+ QFETCH(int, role);
+ QVERIFY(roles.contains(role));
+
+ QFETCH(QByteArray, roleName);
+ QList<QByteArray> values = roles.values(role);
+ QVERIFY(values.contains(roleName));
+}
+
+
+QTEST_MAIN(tst_QDirModel)
+#include "tst_qdirmodel.moc"
diff --git a/tests/auto/widgets/itemviews/qfileiconprovider/.gitignore b/tests/auto/widgets/itemviews/qfileiconprovider/.gitignore
new file mode 100644
index 0000000000..1b673b8fd4
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qfileiconprovider/.gitignore
@@ -0,0 +1 @@
+tst_qfileiconprovider
diff --git a/tests/auto/widgets/itemviews/qfileiconprovider/qfileiconprovider.pro b/tests/auto/widgets/itemviews/qfileiconprovider/qfileiconprovider.pro
new file mode 100644
index 0000000000..1e3d26de00
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qfileiconprovider/qfileiconprovider.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qfileiconprovider.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp b/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp
new file mode 100644
index 0000000000..cf53019ff1
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qfileiconprovider.h>
+#include <qfileinfo.h>
+
+class tst_QFileIconProvider : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qfileiconprovider_data();
+ void qfileiconprovider();
+
+ void iconType_data();
+ void iconType();
+
+ void iconInfo_data();
+ void iconInfo();
+
+ void type_data();
+ void type();
+};
+
+// Subclass that exposes the protected functions.
+class SubQFileIconProvider : public QFileIconProvider
+{
+public:
+
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QFileIconProvider::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QFileIconProvider::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QFileIconProvider::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QFileIconProvider::cleanup()
+{
+}
+
+
+void tst_QFileIconProvider::qfileiconprovider_data()
+{
+}
+
+void tst_QFileIconProvider::qfileiconprovider()
+{
+ // don't crash
+ SubQFileIconProvider provider;
+}
+
+Q_DECLARE_METATYPE(QFileIconProvider::IconType)
+void tst_QFileIconProvider::iconType_data()
+{
+ QTest::addColumn<QFileIconProvider::IconType>("type");
+
+ QTest::newRow("computer") << QFileIconProvider::Computer;
+ QTest::newRow("desktop") << QFileIconProvider::Desktop;
+ QTest::newRow("trashcan") << QFileIconProvider::Trashcan;
+ QTest::newRow("network") << QFileIconProvider::Network;
+ QTest::newRow("drive") << QFileIconProvider::Drive;
+ QTest::newRow("folder") << QFileIconProvider::Folder;
+ QTest::newRow("file") << QFileIconProvider::File;
+}
+
+// public QIcon icon(QFileIconProvider::IconType const& type) const
+void tst_QFileIconProvider::iconType()
+{
+ QFETCH(QFileIconProvider::IconType, type);
+ SubQFileIconProvider provider;
+ QVERIFY(!provider.icon(type).isNull());
+}
+
+Q_DECLARE_METATYPE(QFileInfo)
+void tst_QFileIconProvider::iconInfo_data()
+{
+ QTest::addColumn<QFileInfo>("info");
+ QTest::addColumn<bool>("setPath");
+
+ QTest::newRow("null") << QFileInfo() << false;
+ QTest::newRow("drive") << QFileInfo(QDir::rootPath()) << true;
+ QTest::newRow("home") << QFileInfo(QDir::homePath()) << true;
+ QTest::newRow("current") << QFileInfo(QDir::currentPath()) << true;
+}
+
+// public QIcon icon(QFileInfo const& info) const
+void tst_QFileIconProvider::iconInfo()
+{
+ QFETCH(QFileInfo, info);
+ QFETCH(bool, setPath);
+
+ if (setPath)
+ QVERIFY(info.exists());
+ SubQFileIconProvider provider;
+ // we should always get an icon
+ QVERIFY(!provider.icon(info).isNull());
+}
+
+void tst_QFileIconProvider::type_data()
+{
+ QTest::addColumn<QFileInfo>("info");
+ // Return value is _very_ system dependent, hard to test
+ // QTest::addColumn<QString>("type");
+
+ QTest::newRow("null") << QFileInfo();
+ QTest::newRow("drive") << QFileInfo(QDir::rootPath());
+ QTest::newRow("home") << QFileInfo(QDir::homePath());
+ QTest::newRow("current") << QFileInfo(QDir::currentPath());
+ QTest::newRow("exe") << QFileInfo(QCoreApplication::applicationFilePath());
+}
+
+// public QString type(QFileInfo const& info) const
+void tst_QFileIconProvider::type()
+{
+ QFETCH(QFileInfo, info);
+ SubQFileIconProvider provider;
+ QVERIFY(!provider.type(info).isEmpty());
+}
+
+QTEST_MAIN(tst_QFileIconProvider)
+#include "tst_qfileiconprovider.moc"
+
diff --git a/tests/auto/widgets/itemviews/qheaderview/.gitignore b/tests/auto/widgets/itemviews/qheaderview/.gitignore
new file mode 100644
index 0000000000..dafdb3d2fb
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qheaderview/.gitignore
@@ -0,0 +1 @@
+tst_qheaderview
diff --git a/tests/auto/widgets/itemviews/qheaderview/qheaderview.pro b/tests/auto/widgets/itemviews/qheaderview/qheaderview.pro
new file mode 100644
index 0000000000..3b3afa7e49
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qheaderview/qheaderview.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qheaderview.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
new file mode 100644
index 0000000000..dd087b0e95
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -0,0 +1,2135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QStandardItemModel>
+#include <QStringListModel>
+#include <QSortFilterProxyModel>
+#include <QTableView>
+
+#include <qabstractitemmodel.h>
+#include <qapplication.h>
+#include <qheaderview.h>
+#include <private/qheaderview_p.h>
+#include <qitemdelegate.h>
+#include <qtreewidget.h>
+#include <qdebug.h>
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+typedef QList<bool> BoolList;
+Q_DECLARE_METATYPE(BoolList)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+// Will try to wait for the condition while allowing event processing
+// for a maximum of 2 seconds.
+#define WAIT_FOR_CONDITION(expr, expected) \
+ do { \
+ const int step = 100; \
+ for (int i = 0; i < 2000 && expr != expected; i+=step) { \
+ QTest::qWait(step); \
+ } \
+ } while(0)
+
+class protected_QHeaderView : public QHeaderView
+{
+ Q_OBJECT
+public:
+ protected_QHeaderView(Qt::Orientation orientation) : QHeaderView(orientation) {
+ resizeSections();
+ };
+
+ void testEvent();
+ void testhorizontalOffset();
+ void testverticalOffset();
+ friend class tst_QHeaderView;
+};
+
+class tst_QHeaderView : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QHeaderView();
+ virtual ~tst_QHeaderView();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void visualIndex();
+
+ void visualIndexAt_data();
+ void visualIndexAt();
+
+ void noModel();
+ void emptyModel();
+ void removeRows();
+ void removeCols();
+
+ void clickable();
+ void movable();
+ void hidden();
+ void stretch();
+
+ void sectionSize_data();
+ void sectionSize();
+
+ void length();
+ void offset();
+ void sectionSizeHint();
+ void logicalIndex();
+ void logicalIndexAt();
+ void swapSections();
+
+ void moveSection_data();
+ void moveSection();
+
+ void resizeMode();
+
+ void resizeSection_data();
+ void resizeSection();
+
+ void resizeAndMoveSection_data();
+ void resizeAndMoveSection();
+ void resizeHiddenSection_data();
+ void resizeHiddenSection();
+ void resizeAndInsertSection_data();
+ void resizeAndInsertSection();
+ void resizeWithResizeModes_data();
+ void resizeWithResizeModes();
+ void moveAndInsertSection_data();
+ void moveAndInsertSection();
+ void highlightSections();
+ void showSortIndicator();
+ void sortIndicatorTracking();
+ void removeAndInsertRow();
+ void unhideSection();
+ void event();
+ void headerDataChanged();
+ void currentChanged();
+ void horizontalOffset();
+ void verticalOffset();
+ void stretchSectionCount();
+ void hiddenSectionCount();
+ void focusPolicy();
+ void moveSectionAndReset();
+ void moveSectionAndRemove();
+ void saveRestore();
+
+ void defaultAlignment_data();
+ void defaultAlignment();
+
+ void globalResizeMode_data();
+ void globalResizeMode();
+
+ void sectionPressedSignal_data();
+ void sectionPressedSignal();
+ void sectionClickedSignal_data() { sectionPressedSignal_data(); }
+ void sectionClickedSignal();
+
+ void defaultSectionSize_data();
+ void defaultSectionSize();
+
+ void oneSectionSize();
+
+ void hideAndInsert_data();
+ void hideAndInsert();
+
+ void removeSection();
+ void preserveHiddenSectionWidth();
+ void invisibleStretchLastSection();
+
+ void emptySectionSpan();
+ void task236450_hidden_data();
+ void task236450_hidden();
+ void task248050_hideRow();
+ void QTBUG6058_reset();
+ void QTBUG7833_sectionClicked();
+ void QTBUG8650_crashOnInsertSections();
+ void QTBUG12268_hiddenMovedSectionSorting();
+
+ void initialSortOrderRole();
+
+protected:
+ QWidget *topLevel;
+ QHeaderView *view;
+ QStandardItemModel *model;
+};
+
+class QtTestModel: public QAbstractTableModel
+{
+
+Q_OBJECT
+
+public:
+ QtTestModel(QObject *parent = 0): QAbstractTableModel(parent),
+ cols(0), rows(0), wrongIndex(false) {}
+ int rowCount(const QModelIndex&) const { return rows; }
+ int columnCount(const QModelIndex&) const { return cols; }
+ bool isEditable(const QModelIndex &) const { return true; }
+
+ QVariant data(const QModelIndex &idx, int) const
+ {
+ if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
+ wrongIndex = true;
+ qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(), idx.internalPointer());
+ }
+ return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(0);//idx.data());
+ }
+
+ void insertOneColumn(int col)
+ {
+ beginInsertColumns(QModelIndex(), col, col);
+ --cols;
+ endInsertColumns();
+ }
+
+ void removeLastRow()
+ {
+ beginRemoveRows(QModelIndex(), rows - 1, rows - 1);
+ --rows;
+ endRemoveRows();
+ }
+
+ void removeAllRows()
+ {
+ beginRemoveRows(QModelIndex(), 0, rows - 1);
+ rows = 0;
+ endRemoveRows();
+ }
+
+ void removeOneColumn(int col)
+ {
+ beginRemoveColumns(QModelIndex(), col, col);
+ --cols;
+ endRemoveColumns();
+ }
+
+ void removeLastColumn()
+ {
+ beginRemoveColumns(QModelIndex(), cols - 1, cols - 1);
+ --cols;
+ endRemoveColumns();
+ }
+
+ void removeAllColumns()
+ {
+ beginRemoveColumns(QModelIndex(), 0, cols - 1);
+ cols = 0;
+ endRemoveColumns();
+ }
+
+ void cleanup()
+ {
+ cols = 3;
+ rows = 3;
+ emit layoutChanged();
+ }
+
+ int cols, rows;
+ mutable bool wrongIndex;
+};
+
+// Testing get/set functions
+void tst_QHeaderView::getSetCheck()
+{
+ protected_QHeaderView obj1(Qt::Horizontal);
+ // bool QHeaderView::highlightSections()
+ // void QHeaderView::setHighlightSections(bool)
+ obj1.setHighlightSections(false);
+ QCOMPARE(false, obj1.highlightSections());
+ obj1.setHighlightSections(true);
+ QCOMPARE(true, obj1.highlightSections());
+
+ // bool QHeaderView::stretchLastSection()
+ // void QHeaderView::setStretchLastSection(bool)
+ obj1.setStretchLastSection(false);
+ QCOMPARE(false, obj1.stretchLastSection());
+ obj1.setStretchLastSection(true);
+ QCOMPARE(true, obj1.stretchLastSection());
+
+ // int QHeaderView::defaultSectionSize()
+ // void QHeaderView::setDefaultSectionSize(int)
+ obj1.setDefaultSectionSize(0);
+ QCOMPARE(0, obj1.defaultSectionSize());
+ obj1.setDefaultSectionSize(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.defaultSectionSize());
+ obj1.setDefaultSectionSize(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.defaultSectionSize());
+ // ### the test above does not make sense for values below 0
+
+ // int QHeaderView::minimumSectionSize()
+ // void QHeaderView::setMinimumSectionSize(int)
+ obj1.setMinimumSectionSize(0);
+ QCOMPARE(0, obj1.minimumSectionSize());
+ obj1.setMinimumSectionSize(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.minimumSectionSize());
+ obj1.setMinimumSectionSize(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.minimumSectionSize());
+ // ### the test above does not make sense for values below 0
+
+ // int QHeaderView::offset()
+ // void QHeaderView::setOffset(int)
+ obj1.setOffset(0);
+ QCOMPARE(0, obj1.offset());
+ obj1.setOffset(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.offset());
+ obj1.setOffset(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.offset());
+
+}
+
+tst_QHeaderView::tst_QHeaderView()
+{
+ qRegisterMetaType<int>("Qt::SortOrder");
+}
+
+tst_QHeaderView::~tst_QHeaderView()
+{
+}
+
+void tst_QHeaderView::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QHeaderView::cleanupTestCase()
+{
+}
+
+void tst_QHeaderView::init()
+{
+ topLevel = new QWidget();
+ view = new QHeaderView(Qt::Vertical,topLevel);
+ // Some initial value tests before a model is added
+ QCOMPARE(view->length(), 0);
+ QVERIFY(view->sizeHint() == QSize(0,0));
+ QCOMPARE(view->sectionSizeHint(0), -1);
+
+ /*
+ model = new QStandardItemModel(1, 1);
+ view->setModel(model);
+ //qDebug() << view->count();
+ view->sizeHint();
+ */
+
+ int rows = 4;
+ int columns = 4;
+ model = new QStandardItemModel(rows, columns);
+ /*
+ for (int row = 0; row < rows; ++row) {
+ for (int column = 0; column < columns; ++column) {
+ QModelIndex index = model->index(row, column, QModelIndex());
+ model->setData(index, QVariant((row+1) * (column+1)));
+ }
+ }
+ */
+
+ QSignalSpy spy(view, SIGNAL(sectionCountChanged(int, int)));
+ view->setModel(model);
+ QCOMPARE(spy.count(), 1);
+ view->resize(200,200);
+ topLevel->show();
+}
+
+void tst_QHeaderView::cleanup()
+{
+ delete view;
+ view = 0;
+ delete model;
+ model = 0;
+}
+
+void tst_QHeaderView::noModel()
+{
+ QHeaderView emptyView(Qt::Vertical);
+ QCOMPARE(emptyView.count(), 0);
+}
+
+void tst_QHeaderView::emptyModel()
+{
+ QtTestModel testmodel;
+ view->setModel(&testmodel);
+ QVERIFY(!testmodel.wrongIndex);
+ QCOMPARE(view->count(), testmodel.rows);
+ view->setModel(model);
+}
+
+void tst_QHeaderView::removeRows()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+
+ QHeaderView vertical(Qt::Vertical);
+ QHeaderView horizontal(Qt::Horizontal);
+
+ vertical.setModel(&model);
+ horizontal.setModel(&model);
+ vertical.show();
+ horizontal.show();
+ QCOMPARE(vertical.count(), model.rows);
+ QCOMPARE(horizontal.count(), model.cols);
+
+ model.removeLastRow();
+ QVERIFY(!model.wrongIndex);
+ QCOMPARE(vertical.count(), model.rows);
+ QCOMPARE(horizontal.count(), model.cols);
+
+ model.removeAllRows();
+ QVERIFY(!model.wrongIndex);
+ QCOMPARE(vertical.count(), model.rows);
+ QCOMPARE(horizontal.count(), model.cols);
+}
+
+
+void tst_QHeaderView::removeCols()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+
+ QHeaderView vertical(Qt::Vertical);
+ QHeaderView horizontal(Qt::Horizontal);
+ vertical.setModel(&model);
+ horizontal.setModel(&model);
+ vertical.show();
+ horizontal.show();
+ QCOMPARE(vertical.count(), model.rows);
+ QCOMPARE(horizontal.count(), model.cols);
+
+ model.removeLastColumn();
+ QVERIFY(!model.wrongIndex);
+ QCOMPARE(vertical.count(), model.rows);
+ QCOMPARE(horizontal.count(), model.cols);
+
+ model.removeAllColumns();
+ QVERIFY(!model.wrongIndex);
+ QCOMPARE(vertical.count(), model.rows);
+ QCOMPARE(horizontal.count(), model.cols);
+}
+
+void tst_QHeaderView::movable()
+{
+ QCOMPARE(view->isMovable(), false);
+ view->setMovable(false);
+ QCOMPARE(view->isMovable(), false);
+ view->setMovable(true);
+ QCOMPARE(view->isMovable(), true);
+}
+
+void tst_QHeaderView::clickable()
+{
+ QCOMPARE(view->isClickable(), false);
+ view->setClickable(false);
+ QCOMPARE(view->isClickable(), false);
+ view->setClickable(true);
+ QCOMPARE(view->isClickable(), true);
+}
+
+void tst_QHeaderView::hidden()
+{
+ //hideSection() & showSection call setSectionHidden
+ // Test bad arguments
+ QCOMPARE(view->isSectionHidden(-1), false);
+ QCOMPARE(view->isSectionHidden(view->count()), false);
+ QCOMPARE(view->isSectionHidden(999999), false);
+
+ view->setSectionHidden(-1, true);
+ view->setSectionHidden(view->count(), true);
+ view->setSectionHidden(999999, true);
+ view->setSectionHidden(-1, false);
+ view->setSectionHidden(view->count(), false);
+ view->setSectionHidden(999999, false);
+
+ // Hidden sections shouldn't have visual properties (except position)
+ int pos = view->defaultSectionSize();
+ view->setSectionHidden(1, true);
+ QCOMPARE(view->sectionSize(1), 0);
+ QCOMPARE(view->sectionPosition(1), pos);
+ view->resizeSection(1, 100);
+ QCOMPARE(view->sectionViewportPosition(1), pos);
+ QCOMPARE(view->sectionSize(1), 0);
+ view->setSectionHidden(1, false);
+ QCOMPARE(view->isSectionHidden(0), false);
+ QCOMPARE(view->sectionSize(0), view->defaultSectionSize());
+}
+
+void tst_QHeaderView::stretch()
+{
+ // Show before resize and setStrechLastSection
+#if defined(Q_OS_WINCE)
+ QSize viewSize(200,300);
+#else
+ QSize viewSize(500, 500);
+#endif
+ view->resize(viewSize);
+ view->setStretchLastSection(true);
+ QCOMPARE(view->stretchLastSection(), true);
+ topLevel->show();
+ QCOMPARE(view->width(), viewSize.width());
+ QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 3);
+
+ view->setSectionHidden(3, true);
+ QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 2);
+
+ view->setStretchLastSection(false);
+ QCOMPARE(view->stretchLastSection(), false);
+}
+
+void tst_QHeaderView::oneSectionSize()
+{
+ //this ensures that if there is only one section, it gets a correct width (more than 0)
+ QHeaderView view (Qt::Vertical);
+ QtTestModel model;
+ model.cols = 1;
+ model.rows = 1;
+
+ view.setResizeMode(QHeaderView::Interactive);
+ view.setModel(&model);
+
+ view.show();
+
+ QVERIFY(view.sectionSize(0) > 0);
+}
+
+
+void tst_QHeaderView::sectionSize_data()
+{
+ QTest::addColumn<QList<int> >("boundsCheck");
+ QTest::addColumn<QList<int> >("defaultSizes");
+ QTest::addColumn<int>("initialDefaultSize");
+ QTest::addColumn<int>("lastVisibleSectionSize");
+ QTest::addColumn<int>("persistentSectionSize");
+
+ QTest::newRow("data set one")
+ << (QList<int>() << -1 << 0 << 4 << 9999)
+ << (QList<int>() << 10 << 30 << 30)
+ << 30
+ << 300
+ << 20;
+}
+
+void tst_QHeaderView::sectionSize()
+{
+ QFETCH(QList<int>, boundsCheck);
+ QFETCH(QList<int>, defaultSizes);
+ QFETCH(int, initialDefaultSize);
+ QFETCH(int, lastVisibleSectionSize);
+ QFETCH(int, persistentSectionSize);
+
+#ifdef Q_OS_WINCE
+ // We test on a device with doubled pixels. Therefore we need to specify
+ // different boundaries.
+ initialDefaultSize = qMax(view->minimumSectionSize(), 30);
+#endif
+
+ // bounds check
+ foreach (int val, boundsCheck)
+ view->sectionSize(val);
+
+ // default size
+ QCOMPARE(view->defaultSectionSize(), initialDefaultSize);
+ foreach (int def, defaultSizes) {
+ view->setDefaultSectionSize(def);
+ QCOMPARE(view->defaultSectionSize(), def);
+ }
+
+ view->setDefaultSectionSize(initialDefaultSize);
+ for (int s = 0; s < view->count(); ++s)
+ QCOMPARE(view->sectionSize(s), initialDefaultSize);
+ view->doItemsLayout();
+
+ // stretch last section
+ view->setStretchLastSection(true);
+ int lastSection = view->count() - 1;
+
+ //test that when hiding the last column,
+ //resizing the new last visible columns still works
+ view->hideSection(lastSection);
+ view->resizeSection(lastSection - 1, lastVisibleSectionSize);
+ QCOMPARE(view->sectionSize(lastSection - 1), lastVisibleSectionSize);
+ view->showSection(lastSection);
+
+ // turn off stretching
+ view->setStretchLastSection(false);
+ QCOMPARE(view->sectionSize(lastSection), initialDefaultSize);
+
+ // test persistence
+ int sectionCount = view->count();
+ for (int i = 0; i < sectionCount; ++i)
+ view->resizeSection(i, persistentSectionSize);
+ QtTestModel model;
+ model.cols = sectionCount * 2;
+ model.rows = sectionCount * 2;
+ view->setModel(&model);
+ for (int j = 0; j < sectionCount; ++j)
+ QCOMPARE(view->sectionSize(j), persistentSectionSize);
+ for (int k = sectionCount; k < view->count(); ++k)
+ QCOMPARE(view->sectionSize(k), initialDefaultSize);
+}
+
+void tst_QHeaderView::visualIndex()
+{
+ // Test bad arguments
+ QCOMPARE(view->visualIndex(999999), -1);
+ QCOMPARE(view->visualIndex(-1), -1);
+ QCOMPARE(view->visualIndex(1), 1);
+ view->setSectionHidden(1, true);
+ QCOMPARE(view->visualIndex(1), 1);
+ QCOMPARE(view->visualIndex(2), 2);
+
+ view->setSectionHidden(1, false);
+ QCOMPARE(view->visualIndex(1), 1);
+ QCOMPARE(view->visualIndex(2), 2);
+}
+
+void tst_QHeaderView::visualIndexAt_data()
+{
+ QTest::addColumn<QList<int> >("hidden");
+ QTest::addColumn<QList<int> >("from");
+ QTest::addColumn<QList<int> >("to");
+ QTest::addColumn<QList<int> >("coordinate");
+ QTest::addColumn<QList<int> >("visual");
+
+ QList<int> coordinateList;
+#ifndef Q_OS_WINCE
+ coordinateList << -1 << 0 << 31 << 91 << 99999;
+#else
+ // We test on a device with doubled pixels. Therefore we need to specify
+ // different boundaries.
+ coordinateList << -1 << 0 << 33 << 97 << 99999;
+#endif
+
+ QTest::newRow("no hidden, no moved sections")
+ << QList<int>()
+ << QList<int>()
+ << QList<int>()
+ << coordinateList
+ << (QList<int>() << -1 << 0 << 1 << 3 << -1);
+
+ QTest::newRow("no hidden, moved sections")
+ << QList<int>()
+ << (QList<int>() << 0)
+ << (QList<int>() << 1)
+ << coordinateList
+ << (QList<int>() << -1 << 0 << 1 << 3 << -1);
+
+ QTest::newRow("hidden, no moved sections")
+ << (QList<int>() << 0)
+ << QList<int>()
+ << QList<int>()
+ << coordinateList
+ << (QList<int>() << -1 << 1 << 2 << 3 << -1);
+}
+
+void tst_QHeaderView::visualIndexAt()
+{
+ QFETCH(QList<int>, hidden);
+ QFETCH(QList<int>, from);
+ QFETCH(QList<int>, to);
+ QFETCH(QList<int>, coordinate);
+ QFETCH(QList<int>, visual);
+
+ view->setStretchLastSection(true);
+ topLevel->show();
+
+ for (int i = 0; i < hidden.count(); ++i)
+ view->setSectionHidden(hidden.at(i), true);
+
+ for (int j = 0; j < from.count(); ++j)
+ view->moveSection(from.at(j), to.at(j));
+
+ QTest::qWait(100);
+
+ for (int k = 0; k < coordinate.count(); ++k)
+ QCOMPARE(view->visualIndexAt(coordinate.at(k)), visual.at(k));
+}
+
+void tst_QHeaderView::length()
+{
+#if defined(Q_OS_WINCE)
+ QFont font(QLatin1String("Tahoma"), 7);
+ view->setFont(font);
+#endif
+ view->setStretchLastSection(true);
+ topLevel->show();
+
+ //minimumSectionSize should be the size of the last section of the widget is not tall enough
+ int length = view->minimumSectionSize();
+ for (int i=0; i < view->count()-1; i++) {
+ length += view->sectionSize(i);
+ }
+
+ length = qMax(length, view->viewport()->height());
+ QCOMPARE(length, view->length());
+
+ view->setStretchLastSection(false);
+ topLevel->show();
+
+ QVERIFY(length != view->length());
+
+ // layoutChanged might mean rows have been removed
+ QtTestModel model;
+ model.cols = 10;
+ model.rows = 10;
+ view->setModel(&model);
+ int oldLength = view->length();
+ model.cleanup();
+ QCOMPARE(model.rows, view->count());
+ QVERIFY(oldLength != view->length());
+}
+
+void tst_QHeaderView::offset()
+{
+ QCOMPARE(view->offset(), 0);
+ view->setOffset(10);
+ QCOMPARE(view->offset(), 10);
+ view->setOffset(0);
+ QCOMPARE(view->offset(), 0);
+
+ // Test odd arguments
+ view->setOffset(-1);
+}
+
+void tst_QHeaderView::sectionSizeHint()
+{
+ // Test bad arguments
+ view->sectionSizeHint(-1);
+ view->sectionSizeHint(99999);
+
+ // TODO how to test the return value?
+}
+
+void tst_QHeaderView::logicalIndex()
+{
+ // Test bad arguments
+ QCOMPARE(view->logicalIndex(-1), -1);
+ QCOMPARE(view->logicalIndex(99999), -1);
+}
+
+void tst_QHeaderView::logicalIndexAt()
+{
+ // Test bad arguments
+ view->logicalIndexAt(-1);
+ view->logicalIndexAt(99999);
+ QCOMPARE(view->logicalIndexAt(0), 0);
+ QCOMPARE(view->logicalIndexAt(1), 0);
+
+ topLevel->show();
+ view->setStretchLastSection(true);
+ // First item
+ QCOMPARE(view->logicalIndexAt(0), 0);
+ QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 0);
+ QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 1);
+ // Last item
+ int last = view->length() - 1;//view->viewport()->height() - 10;
+ QCOMPARE(view->logicalIndexAt(last), 3);
+ // Not in widget
+ int outofbounds = view->length() + 1;//view->viewport()->height() + 1;
+ QCOMPARE(view->logicalIndexAt(outofbounds), -1);
+
+ view->moveSection(0,1);
+ // First item
+ QCOMPARE(view->logicalIndexAt(0), 1);
+ QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 1);
+ QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 0);
+ // Last item
+ QCOMPARE(view->logicalIndexAt(last), 3);
+ view->moveSection(1,0);
+
+}
+
+void tst_QHeaderView::swapSections()
+{
+ view->swapSections(-1, 1);
+ view->swapSections(99999, 1);
+ view->swapSections(1, -1);
+ view->swapSections(1, 99999);
+
+ QVector<int> logical = (QVector<int>() << 0 << 1 << 2 << 3);
+
+ QSignalSpy spy1(view, SIGNAL(sectionMoved(int, int, int)));
+
+ QCOMPARE(view->sectionsMoved(), false);
+ view->swapSections(1, 1);
+ QCOMPARE(view->sectionsMoved(), false);
+ view->swapSections(1, 2);
+ QCOMPARE(view->sectionsMoved(), true);
+ view->swapSections(2, 1);
+ QCOMPARE(view->sectionsMoved(), true);
+ for (int i = 0; i < view->count(); ++i)
+ QCOMPARE(view->logicalIndex(i), logical.at(i));
+ QCOMPARE(spy1.count(), 4);
+
+ logical = (QVector<int>() << 3 << 1 << 2 << 0);
+ view->swapSections(3, 0);
+ QCOMPARE(view->sectionsMoved(), true);
+ for (int j = 0; j < view->count(); ++j)
+ QCOMPARE(view->logicalIndex(j), logical.at(j));
+ QCOMPARE(spy1.count(), 6);
+}
+
+void tst_QHeaderView::moveSection_data()
+{
+ QTest::addColumn<QList<int> >("hidden");
+ QTest::addColumn<QList<int> >("from");
+ QTest::addColumn<QList<int> >("to");
+ QTest::addColumn<QList<bool> >("moved");
+ QTest::addColumn<QList<int> >("logical");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("bad args, no hidden")
+ << QList<int>()
+ << (QList<int>() << -1 << 1 << 99999 << 1)
+ << (QList<int>() << 1 << -1 << 1 << 99999)
+ << (QList<bool>() << false << false << false << false)
+ << (QList<int>() << 0 << 1 << 2 << 3)
+ << 0;
+
+ QTest::newRow("good args, no hidden")
+ << QList<int>()
+ << (QList<int>() << 1 << 1 << 2 << 1)
+ << (QList<int>() << 1 << 2 << 1 << 2)
+ << (QList<bool>() << false << true << true << true)
+ << (QList<int>() << 0 << 2 << 1 << 3)
+ << 3;
+
+ QTest::newRow("hidden sections")
+ << (QList<int>() << 0 << 3)
+ << (QList<int>() << 1 << 1 << 2 << 1)
+ << (QList<int>() << 1 << 2 << 1 << 2)
+ << (QList<bool>() << false << true << true << true)
+ << (QList<int>() << 0 << 2 << 1 << 3)
+ << 3;
+}
+
+void tst_QHeaderView::moveSection()
+{
+ QFETCH(QList<int>, hidden);
+ QFETCH(QList<int>, from);
+ QFETCH(QList<int>, to);
+ QFETCH(QList<bool>, moved);
+ QFETCH(QList<int>, logical);
+ QFETCH(int, count);
+
+ QVERIFY(from.count() == to.count());
+ QVERIFY(from.count() == moved.count());
+ QVERIFY(view->count() == logical.count());
+
+ QSignalSpy spy1(view, SIGNAL(sectionMoved(int, int, int)));
+ QCOMPARE(view->sectionsMoved(), false);
+
+ for (int h = 0; h < hidden.count(); ++h)
+ view->setSectionHidden(hidden.at(h), true);
+
+ for (int i = 0; i < from.count(); ++i) {
+ view->moveSection(from.at(i), to.at(i));
+ QCOMPARE(view->sectionsMoved(), moved.at(i));
+ }
+
+ for (int j = 0; j < view->count(); ++j)
+ QCOMPARE(view->logicalIndex(j), logical.at(j));
+
+ QCOMPARE(spy1.count(), count);
+}
+
+void tst_QHeaderView::resizeAndMoveSection_data()
+{
+ QTest::addColumn<IntList>("logicalIndexes");
+ QTest::addColumn<IntList>("sizes");
+ QTest::addColumn<int>("logicalFrom");
+ QTest::addColumn<int>("logicalTo");
+
+ QTest::newRow("resizeAndMove-1")
+ << (IntList() << 0 << 1)
+ << (IntList() << 20 << 40)
+ << 0 << 1;
+
+ QTest::newRow("resizeAndMove-2")
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 20 << 60 << 10 << 80)
+ << 0 << 2;
+
+ QTest::newRow("resizeAndMove-3")
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 100 << 60 << 40 << 10)
+ << 0 << 3;
+
+ QTest::newRow("resizeAndMove-4")
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 10 << 40 << 80 << 30)
+ << 1 << 2;
+
+ QTest::newRow("resizeAndMove-5")
+ << (IntList() << 2 << 3)
+ << (IntList() << 100 << 200)
+ << 3 << 2;
+}
+
+void tst_QHeaderView::resizeAndMoveSection()
+{
+ QFETCH(IntList, logicalIndexes);
+ QFETCH(IntList, sizes);
+ QFETCH(int, logicalFrom);
+ QFETCH(int, logicalTo);
+
+ // Save old visual indexes and sizes
+ IntList oldVisualIndexes;
+ IntList oldSizes;
+ foreach (int logical, logicalIndexes) {
+ oldVisualIndexes.append(view->visualIndex(logical));
+ oldSizes.append(view->sectionSize(logical));
+ }
+
+ // Resize sections
+ for (int i = 0; i < logicalIndexes.size(); ++i) {
+ int logical = logicalIndexes.at(i);
+ view->resizeSection(logical, sizes.at(i));
+ }
+
+ // Move sections
+ int visualFrom = view->visualIndex(logicalFrom);
+ int visualTo = view->visualIndex(logicalTo);
+ view->moveSection(visualFrom, visualTo);
+ QCOMPARE(view->visualIndex(logicalFrom), visualTo);
+
+ // Check that sizes are still correct
+ for (int i = 0; i < logicalIndexes.size(); ++i) {
+ int logical = logicalIndexes.at(i);
+ QCOMPARE(view->sectionSize(logical), sizes.at(i));
+ }
+
+ // Move sections back
+ view->moveSection(visualTo, visualFrom);
+
+ // Check that sizes are still correct
+ for (int i = 0; i < logicalIndexes.size(); ++i) {
+ int logical = logicalIndexes.at(i);
+ QCOMPARE(view->sectionSize(logical), sizes.at(i));
+ }
+
+ // Put everything back as it was
+ for (int i = 0; i < logicalIndexes.size(); ++i) {
+ int logical = logicalIndexes.at(i);
+ view->resizeSection(logical, oldSizes.at(i));
+ QCOMPARE(view->visualIndex(logical), oldVisualIndexes.at(i));
+ }
+}
+
+void tst_QHeaderView::resizeHiddenSection_data()
+{
+ QTest::addColumn<int>("section");
+ QTest::addColumn<int>("initialSize");
+ QTest::addColumn<int>("finalSize");
+
+ QTest::newRow("section 0 resize 50 to 20")
+ << 0 << 50 << 20;
+
+ QTest::newRow("section 1 resize 50 to 20")
+ << 1 << 50 << 20;
+
+ QTest::newRow("section 2 resize 50 to 20")
+ << 2 << 50 << 20;
+
+ QTest::newRow("section 3 resize 50 to 20")
+ << 3 << 50 << 20;
+}
+
+void tst_QHeaderView::resizeHiddenSection()
+{
+ QFETCH(int, section);
+ QFETCH(int, initialSize);
+ QFETCH(int, finalSize);
+
+ view->resizeSection(section, initialSize);
+ view->setSectionHidden(section, true);
+ QCOMPARE(view->sectionSize(section), 0);
+
+ view->resizeSection(section, finalSize);
+ QCOMPARE(view->sectionSize(section), 0);
+
+ view->setSectionHidden(section, false);
+ QCOMPARE(view->sectionSize(section), finalSize);
+}
+
+void tst_QHeaderView::resizeAndInsertSection_data()
+{
+ QTest::addColumn<int>("section");
+ QTest::addColumn<int>("size");
+ QTest::addColumn<int>("insert");
+ QTest::addColumn<int>("compare");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("section 0 size 50 insert 0")
+ << 0 << 50 << 0 << 1 << 50;
+
+ QTest::newRow("section 1 size 50 insert 1")
+ << 0 << 50 << 1 << 0 << 50;
+
+ QTest::newRow("section 1 size 50 insert 0")
+ << 1 << 50 << 0 << 2 << 50;
+
+}
+
+void tst_QHeaderView::resizeAndInsertSection()
+{
+ QFETCH(int, section);
+ QFETCH(int, size);
+ QFETCH(int, insert);
+ QFETCH(int, compare);
+ QFETCH(int, expected);
+
+ view->setStretchLastSection(false);
+
+ view->resizeSection(section, size);
+ QCOMPARE(view->sectionSize(section), size);
+
+ model->insertRow(insert);
+
+ QCOMPARE(view->sectionSize(compare), expected);
+}
+
+void tst_QHeaderView::resizeWithResizeModes_data()
+{
+ QTest::addColumn<int>("size");
+ QTest::addColumn<QList<int> >("sections");
+ QTest::addColumn<QList<int> >("modes");
+ QTest::addColumn<QList<int> >("expected");
+
+ QTest::newRow("stretch first section")
+ << 600
+ << (QList<int>() << 100 << 100 << 100 << 100)
+ << (QList<int>() << ((int)QHeaderView::Stretch)
+ << ((int)QHeaderView::Interactive)
+ << ((int)QHeaderView::Interactive)
+ << ((int)QHeaderView::Interactive))
+ << (QList<int>() << 300 << 100 << 100 << 100);
+}
+
+void tst_QHeaderView::resizeWithResizeModes()
+{
+ QFETCH(int, size);
+ QFETCH(QList<int>, sections);
+ QFETCH(QList<int>, modes);
+ QFETCH(QList<int>, expected);
+
+ view->setStretchLastSection(false);
+ for (int i = 0; i < sections.count(); ++i) {
+ view->resizeSection(i, sections.at(i));
+ view->setResizeMode(i, (QHeaderView::ResizeMode)modes.at(i));
+ }
+ topLevel->show();
+ view->resize(size, size);
+ for (int j = 0; j < expected.count(); ++j)
+ QCOMPARE(view->sectionSize(j), expected.at(j));
+}
+
+void tst_QHeaderView::moveAndInsertSection_data()
+{
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<int>("insert");
+ QTest::addColumn<QList<int> >("mapping");
+
+ QTest::newRow("move from 1 to 3, insert 0")
+ << 1 << 3 << 0 <<(QList<int>() << 0 << 1 << 3 << 4 << 2);
+
+}
+
+void tst_QHeaderView::moveAndInsertSection()
+{
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(int, insert);
+ QFETCH(QList<int>, mapping);
+
+ view->setStretchLastSection(false);
+
+ view->moveSection(from, to);
+
+ model->insertRow(insert);
+
+ for (int i = 0; i < mapping.count(); ++i)
+ QCOMPARE(view->logicalIndex(i), mapping.at(i));
+}
+
+void tst_QHeaderView::resizeMode()
+{
+ // resizeMode must not be called with an invalid index
+ int last = view->count() - 1;
+ view->setResizeMode(QHeaderView::Interactive);
+ QCOMPARE(view->resizeMode(last), QHeaderView::Interactive);
+ QCOMPARE(view->resizeMode(1), QHeaderView::Interactive);
+ view->setResizeMode(QHeaderView::Stretch);
+ QCOMPARE(view->resizeMode(last), QHeaderView::Stretch);
+ QCOMPARE(view->resizeMode(1), QHeaderView::Stretch);
+ view->setResizeMode(QHeaderView::Custom);
+ QCOMPARE(view->resizeMode(last), QHeaderView::Custom);
+ QCOMPARE(view->resizeMode(1), QHeaderView::Custom);
+
+ // test when sections have been moved
+ view->setStretchLastSection(false);
+ for (int i=0; i < (view->count() - 1); ++i)
+ view->setResizeMode(i, QHeaderView::Interactive);
+ int logicalIndex = view->count() / 2;
+ view->setResizeMode(logicalIndex, QHeaderView::Stretch);
+ view->moveSection(view->visualIndex(logicalIndex), 0);
+ for (int i=0; i < (view->count() - 1); ++i) {
+ if (i == logicalIndex)
+ QCOMPARE(view->resizeMode(i), QHeaderView::Stretch);
+ else
+ QCOMPARE(view->resizeMode(i), QHeaderView::Interactive);
+ }
+}
+
+void tst_QHeaderView::resizeSection_data()
+{
+ QTest::addColumn<int>("initial");
+ QTest::addColumn<QList<int> >("logical");
+ QTest::addColumn<QList<int> >("size");
+ QTest::addColumn<QList<int> >("mode");
+ QTest::addColumn<int>("resized");
+ QTest::addColumn<QList<int> >("expected");
+
+ QTest::newRow("bad args")
+ << 100
+ << (QList<int>() << -1 << -1 << 99999 << 99999 << 4)
+ << (QList<int>() << -1 << 0 << 99999 << -1 << -1)
+ << (QList<int>()
+ << int(QHeaderView::Interactive)
+ << int(QHeaderView::Interactive)
+ << int(QHeaderView::Interactive)
+ << int(QHeaderView::Interactive))
+ << 0
+ << (QList<int>() << 0 << 0 << 0 << 0 << 0);
+}
+
+void tst_QHeaderView::resizeSection()
+{
+
+ QFETCH(int, initial);
+ QFETCH(QList<int>, logical);
+ QFETCH(QList<int>, size);
+ QFETCH(QList<int>, mode);
+ QFETCH(int, resized);
+ QFETCH(QList<int>, expected);
+
+ view->resize(400, 400);
+
+ topLevel->show();
+ view->setMovable(true);
+ view->setStretchLastSection(false);
+
+ for (int i = 0; i < logical.count(); ++i)
+ if (logical.at(i) > -1 && logical.at(i) < view->count()) // for now
+ view->setResizeMode(logical.at(i), (QHeaderView::ResizeMode)mode.at(i));
+
+ for (int j = 0; j < logical.count(); ++j)
+ view->resizeSection(logical.at(j), initial);
+
+ QSignalSpy spy(view, SIGNAL(sectionResized(int, int, int)));
+
+ for (int k = 0; k < logical.count(); ++k)
+ view->resizeSection(logical.at(k), size.at(k));
+
+ QCOMPARE(spy.count(), resized);
+
+ for (int l = 0; l < logical.count(); ++l)
+ QCOMPARE(view->sectionSize(logical.at(l)), expected.at(l));
+}
+
+void tst_QHeaderView::highlightSections()
+{
+ view->setHighlightSections(true);
+ QCOMPARE(view->highlightSections(), true);
+ view->setHighlightSections(false);
+ QCOMPARE(view->highlightSections(), false);
+}
+
+void tst_QHeaderView::showSortIndicator()
+{
+ view->setSortIndicatorShown(true);
+ QCOMPARE(view->isSortIndicatorShown(), true);
+ QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder);
+ view->setSortIndicator(1, Qt::AscendingOrder);
+ QCOMPARE(view->sortIndicatorOrder(), Qt::AscendingOrder);
+ view->setSortIndicator(1, Qt::DescendingOrder);
+ QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder);
+ view->setSortIndicatorShown(false);
+ QCOMPARE(view->isSortIndicatorShown(), false);
+
+ view->setSortIndicator(999999, Qt::DescendingOrder);
+ // Don't segfault baby :)
+ view->setSortIndicatorShown(true);
+
+ view->setSortIndicator(0, Qt::DescendingOrder);
+ // Don't assert baby :)
+}
+
+void tst_QHeaderView::sortIndicatorTracking()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+
+ QHeaderView hv(Qt::Horizontal);
+
+ hv.setModel(&model);
+ hv.show();
+ hv.setSortIndicatorShown(true);
+ hv.setSortIndicator(1, Qt::DescendingOrder);
+
+ model.removeOneColumn(8);
+ QCOMPARE(hv.sortIndicatorSection(), 1);
+
+ model.removeOneColumn(2);
+ QCOMPARE(hv.sortIndicatorSection(), 1);
+
+ model.insertOneColumn(2);
+ QCOMPARE(hv.sortIndicatorSection(), 1);
+
+ model.insertOneColumn(1);
+ QCOMPARE(hv.sortIndicatorSection(), 2);
+
+ model.removeOneColumn(0);
+ QCOMPARE(hv.sortIndicatorSection(), 1);
+
+ model.removeOneColumn(1);
+ QCOMPARE(hv.sortIndicatorSection(), -1);
+}
+
+void tst_QHeaderView::removeAndInsertRow()
+{
+ // Check if logicalIndex returns the correct value after we have removed a row
+ // we might as well te
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+
+ while (model->removeRow(0)) {
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+ }
+
+ int pass = 0;
+ for (pass = 0; pass < 5; pass++) {
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+ model->insertRow(0);
+ }
+
+ while (model->removeRows(0, 2)) {
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+ }
+
+ for (pass = 0; pass < 3; pass++) {
+ model->insertRows(0, 2);
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+ }
+
+ for (pass = 0; pass < 3; pass++) {
+ model->insertRows(3, 2);
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+ }
+
+ // Insert at end
+ for (pass = 0; pass < 3; pass++) {
+ int rowCount = model->rowCount();
+ model->insertRows(rowCount, 1);
+ for (int i = 0; i < rowCount; ++i) {
+ QCOMPARE(i, view->logicalIndex(i));
+ }
+ }
+
+}
+void tst_QHeaderView::unhideSection()
+{
+ // You should not necessarily expect the same size back again, so the best test we can do is to test if it is larger than 0 after a unhide.
+ QCOMPARE(view->sectionsHidden(), false);
+ view->setSectionHidden(0, true);
+ QCOMPARE(view->sectionsHidden(), true);
+ QVERIFY(view->sectionSize(0) == 0);
+ view->setResizeMode(QHeaderView::Interactive);
+ view->setSectionHidden(0, false);
+ QVERIFY(view->sectionSize(0) > 0);
+
+ view->setSectionHidden(0, true);
+ QVERIFY(view->sectionSize(0) == 0);
+ view->setSectionHidden(0, true);
+ QVERIFY(view->sectionSize(0) == 0);
+ view->setResizeMode(QHeaderView::Stretch);
+ view->setSectionHidden(0, false);
+ QVERIFY(view->sectionSize(0) > 0);
+
+}
+
+void tst_QHeaderView::event()
+{
+ protected_QHeaderView x(Qt::Vertical);
+ x.testEvent();
+ protected_QHeaderView y(Qt::Horizontal);
+ y.testEvent();
+}
+
+
+void protected_QHeaderView::testEvent()
+{
+ // No crashy please
+ QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(), QPoint());
+ event(&enterEvent);
+ QHoverEvent eventLeave(QEvent::HoverLeave, QPoint(), QPoint());
+ event(&eventLeave);
+ QHoverEvent eventMove(QEvent::HoverMove, QPoint(), QPoint());
+ event(&eventMove);
+}
+
+void tst_QHeaderView::headerDataChanged()
+{
+ // This shouldn't asserver because view is Vertical
+ view->headerDataChanged(Qt::Horizontal, -1, -1);
+#if 0
+ // This will assert
+ view->headerDataChanged(Qt::Vertical, -1, -1);
+#endif
+
+ // No crashing please
+ view->headerDataChanged(Qt::Horizontal, 0, 1);
+ view->headerDataChanged(Qt::Vertical, 0, 1);
+}
+
+void tst_QHeaderView::currentChanged()
+{
+ view->setCurrentIndex(QModelIndex());
+}
+
+void tst_QHeaderView::horizontalOffset()
+{
+ protected_QHeaderView x(Qt::Vertical);
+ x.testhorizontalOffset();
+ protected_QHeaderView y(Qt::Horizontal);
+ y.testhorizontalOffset();
+}
+
+void tst_QHeaderView::verticalOffset()
+{
+ protected_QHeaderView x(Qt::Vertical);
+ x.testverticalOffset();
+ protected_QHeaderView y(Qt::Horizontal);
+ y.testverticalOffset();
+}
+
+void protected_QHeaderView::testhorizontalOffset()
+{
+ if(orientation() == Qt::Horizontal){
+ QCOMPARE(horizontalOffset(), 0);
+ setOffset(10);
+ QCOMPARE(horizontalOffset(), 10);
+ }
+ else
+ QCOMPARE(horizontalOffset(), 0);
+
+}
+
+void protected_QHeaderView::testverticalOffset()
+{
+ if(orientation() == Qt::Vertical){
+ QCOMPARE(verticalOffset(), 0);
+ setOffset(10);
+ QCOMPARE(verticalOffset(), 10);
+ }
+ else
+ QCOMPARE(verticalOffset(), 0);
+}
+
+void tst_QHeaderView::stretchSectionCount()
+{
+ view->setStretchLastSection(false);
+ QCOMPARE(view->stretchSectionCount(), 0);
+ view->setStretchLastSection(true);
+ QCOMPARE(view->stretchSectionCount(), 0);
+
+ view->setResizeMode(0, QHeaderView::Stretch);
+ QCOMPARE(view->stretchSectionCount(), 1);
+}
+
+void tst_QHeaderView::hiddenSectionCount()
+{
+ model->clear();
+ model->insertRows(0, 10);
+ // Hide every other one
+ for (int i=0; i<10; i++)
+ view->setSectionHidden(i, (i & 1) == 0);
+
+ QCOMPARE(view->hiddenSectionCount(), 5);
+
+ view->setResizeMode(QHeaderView::Stretch);
+ QCOMPARE(view->hiddenSectionCount(), 5);
+
+ // Remove some rows and make sure they are now still counted
+ model->removeRow(9);
+ model->removeRow(8);
+ model->removeRow(7);
+ model->removeRow(6);
+ QCOMPARE(view->count(), 6);
+ QCOMPARE(view->hiddenSectionCount(), 3);
+ model->removeRows(0,5);
+ QCOMPARE(view->count(), 1);
+ QCOMPARE(view->hiddenSectionCount(), 0);
+ QVERIFY(view->count() >= view->hiddenSectionCount());
+}
+
+void tst_QHeaderView::focusPolicy()
+{
+ QHeaderView view(Qt::Horizontal);
+ QCOMPARE(view.focusPolicy(), Qt::NoFocus);
+
+ QTreeWidget widget;
+ QCOMPARE(widget.header()->focusPolicy(), Qt::NoFocus);
+ QVERIFY(!widget.focusProxy());
+ QVERIFY(!widget.hasFocus());
+ QVERIFY(!widget.header()->focusProxy());
+ QVERIFY(!widget.header()->hasFocus());
+
+ widget.show();
+ widget.setFocus(Qt::OtherFocusReason);
+ QApplication::setActiveWindow(&widget);
+ QTest::qWaitForWindowShown(&widget);
+ widget.activateWindow();
+ QTest::qWait(100);
+
+ qApp->processEvents();
+
+ WAIT_FOR_CONDITION(widget.hasFocus(), true);
+
+ QVERIFY(widget.hasFocus());
+ QVERIFY(!widget.header()->hasFocus());
+
+ widget.setFocusPolicy(Qt::NoFocus);
+ widget.clearFocus();
+
+ qApp->processEvents();
+ qApp->processEvents();
+
+ WAIT_FOR_CONDITION(widget.hasFocus(), false);
+ QVERIFY(!widget.hasFocus());
+ QVERIFY(!widget.header()->hasFocus());
+
+ QTest::keyPress(&widget, Qt::Key_Tab);
+
+ qApp->processEvents();
+ qApp->processEvents();
+
+ QVERIFY(!widget.hasFocus());
+ QVERIFY(!widget.header()->hasFocus());
+}
+
+class SimpleModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+
+ SimpleModel( QObject* parent=0)
+ : QAbstractItemModel(parent),
+ m_col_count(3) {}
+
+ QModelIndex parent(const QModelIndex &/*child*/) const
+ {
+ return QModelIndex();
+ }
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+ {
+ return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
+ }
+ int rowCount(const QModelIndex & /* parent */) const
+ {
+ return 8;
+ }
+ int columnCount(const QModelIndex &/*parent= QModelIndex()*/) const
+ {
+ return m_col_count;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (!index.isValid())
+ {
+ return QVariant();
+ }
+ if (role == Qt::DisplayRole) {
+ return QString::fromAscii("%1,%2").arg(index.row()).arg(index.column());
+ }
+ return QVariant();
+ }
+
+ void setColumnCount( int c )
+ {
+ m_col_count = c;
+ }
+
+private:
+ int m_col_count;
+};
+
+void tst_QHeaderView::moveSectionAndReset()
+{
+ SimpleModel m;
+ QHeaderView v(Qt::Horizontal);
+ v.setModel(&m);
+ int cc = 2;
+ for (cc = 2; cc < 4; ++cc) {
+ m.setColumnCount(cc);
+ int movefrom = 0;
+ int moveto;
+ for (moveto = 1; moveto < cc; ++moveto) {
+ v.moveSection(movefrom, moveto);
+ m.setColumnCount(cc - 1);
+ v.reset();
+ for (int i = 0; i < cc - 1; ++i) {
+ QCOMPARE(v.logicalIndex(v.visualIndex(i)), i);
+ }
+ }
+ }
+}
+
+void tst_QHeaderView::moveSectionAndRemove()
+{
+ QStandardItemModel m;
+ QHeaderView v(Qt::Horizontal);
+
+ v.setModel(&m);
+ v.model()->insertColumns(0, 3);
+ v.moveSection(0, 1);
+
+ QCOMPARE(v.count(), 3);
+ v.model()->removeColumns(0, v.model()->columnCount());
+ QCOMPARE(v.count(), 0);
+}
+
+void tst_QHeaderView::saveRestore()
+{
+ SimpleModel m;
+ QHeaderView h1(Qt::Horizontal);
+ h1.setModel(&m);
+ h1.swapSections(0, 2);
+ h1.resizeSection(1, 10);
+ h1.setSortIndicatorShown(true);
+ h1.setSortIndicator(1,Qt::DescendingOrder);
+ QByteArray s1 = h1.saveState();
+
+ QHeaderView h2(Qt::Vertical);
+ QSignalSpy spy(&h2, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)));
+
+ h2.setModel(&m);
+ h2.restoreState(s1);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), 1);
+
+ QCOMPARE(h2.logicalIndex(0), 2);
+ QCOMPARE(h2.logicalIndex(2), 0);
+ QCOMPARE(h2.sectionSize(1), 10);
+ QCOMPARE(h2.sortIndicatorSection(), 1);
+ QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder);
+ QCOMPARE(h2.isSortIndicatorShown(), true);
+
+ QByteArray s2 = h2.saveState();
+
+ QVERIFY(s1 == s2);
+}
+
+void tst_QHeaderView::defaultAlignment_data()
+{
+ QTest::addColumn<int>("direction");
+ QTest::addColumn<int>("initial");
+ QTest::addColumn<int>("alignment");
+
+ QTest::newRow("horizontal right aligned")
+ << int(Qt::Horizontal)
+ << int(Qt::AlignCenter)
+ << int(Qt::AlignRight);
+
+ QTest::newRow("horizontal left aligned")
+ << int(Qt::Horizontal)
+ << int(Qt::AlignCenter)
+ << int(Qt::AlignLeft);
+
+ QTest::newRow("vertical right aligned")
+ << int(Qt::Vertical)
+ << int(Qt::AlignLeft|Qt::AlignVCenter)
+ << int(Qt::AlignRight);
+
+ QTest::newRow("vertical left aligned")
+ << int(Qt::Vertical)
+ << int(Qt::AlignLeft|Qt::AlignVCenter)
+ << int(Qt::AlignLeft);
+}
+
+void tst_QHeaderView::defaultAlignment()
+{
+ QFETCH(int, direction);
+ QFETCH(int, initial);
+ QFETCH(int, alignment);
+
+ SimpleModel m;
+
+ QHeaderView header((Qt::Orientation)direction);
+ header.setModel(&m);
+
+ QCOMPARE(header.defaultAlignment(), (Qt::Alignment)initial);
+ header.setDefaultAlignment((Qt::Alignment)alignment);
+ QCOMPARE(header.defaultAlignment(), (Qt::Alignment)alignment);
+}
+
+void tst_QHeaderView::globalResizeMode_data()
+{
+ QTest::addColumn<int>("direction");
+ QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("insert");
+
+ QTest::newRow("horizontal ResizeToContents 0")
+ << int(Qt::Horizontal)
+ << int(QHeaderView::ResizeToContents)
+ << 0;
+}
+
+void tst_QHeaderView::globalResizeMode()
+{
+ QFETCH(int, direction);
+ QFETCH(int, mode);
+ QFETCH(int, insert);
+
+ QStandardItemModel m(4, 4);
+ QHeaderView h((Qt::Orientation)direction);
+ h.setModel(&m);
+
+ h.setResizeMode((QHeaderView::ResizeMode)mode);
+ m.insertRow(insert);
+ for (int i = 0; i < h.count(); ++i)
+ QCOMPARE(h.resizeMode(i), (QHeaderView::ResizeMode)mode);
+}
+
+
+void tst_QHeaderView::sectionPressedSignal_data()
+{
+ QTest::addColumn<int>("direction");
+ QTest::addColumn<bool>("clickable");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("horizontal unclickable 0")
+ << int(Qt::Horizontal)
+ << false
+ << 0;
+
+ QTest::newRow("horizontal clickable 1")
+ << int(Qt::Horizontal)
+ << true
+ << 1;
+}
+
+void tst_QHeaderView::sectionPressedSignal()
+{
+ QFETCH(int, direction);
+ QFETCH(bool, clickable);
+ QFETCH(int, count);
+
+ QStandardItemModel m(4, 4);
+ QHeaderView h((Qt::Orientation)direction);
+
+ h.setModel(&m);
+ h.show();
+ h.setClickable(clickable);
+
+ QSignalSpy spy(&h, SIGNAL(sectionPressed(int)));
+
+ QCOMPARE(spy.count(), 0);
+ QTest::mousePress(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QCOMPARE(spy.count(), count);
+}
+
+void tst_QHeaderView::sectionClickedSignal()
+{
+ QFETCH(int, direction);
+ QFETCH(bool, clickable);
+ QFETCH(int, count);
+
+ QStandardItemModel m(4, 4);
+ QHeaderView h((Qt::Orientation)direction);
+
+ h.setModel(&m);
+ h.show();
+ h.setClickable(clickable);
+ h.setSortIndicatorShown(true);
+
+ QSignalSpy spy(&h, SIGNAL(sectionClicked(int)));
+ QSignalSpy spy2(&h, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)));
+
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(spy2.count(), 0);
+ QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QCOMPARE(spy.count(), count);
+ QCOMPARE(spy2.count(), count);
+
+ //now let's try with the sort indicator hidden (the result should be the same
+ spy.clear();
+ spy2.clear();
+ h.setSortIndicatorShown(false);
+ QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QCOMPARE(spy.count(), count);
+ QCOMPARE(spy2.count(), count);
+}
+
+void tst_QHeaderView::defaultSectionSize_data()
+{
+ QTest::addColumn<int>("direction");
+ QTest::addColumn<int>("oldDefaultSize");
+ QTest::addColumn<int>("newDefaultSize");
+
+ //QTest::newRow("horizontal,-5") << int(Qt::Horizontal) << 100 << -5;
+ QTest::newRow("horizontal, 0") << int(Qt::Horizontal) << 100 << 0;
+ QTest::newRow("horizontal, 5") << int(Qt::Horizontal) << 100 << 5;
+ QTest::newRow("horizontal,25") << int(Qt::Horizontal) << 100 << 5;
+}
+
+void tst_QHeaderView::defaultSectionSize()
+{
+ QFETCH(int, direction);
+ QFETCH(int, oldDefaultSize);
+ QFETCH(int, newDefaultSize);
+
+ QStandardItemModel m(4, 4);
+ QHeaderView h((Qt::Orientation)direction);
+
+ h.setModel(&m);
+
+ QCOMPARE(h.defaultSectionSize(), oldDefaultSize);
+ h.setDefaultSectionSize(newDefaultSize);
+ QCOMPARE(h.defaultSectionSize(), newDefaultSize);
+ h.reset();
+ for (int i = 0; i < h.count(); ++i)
+ QCOMPARE(h.sectionSize(i), newDefaultSize);
+}
+
+void tst_QHeaderView::hideAndInsert_data()
+{
+ QTest::addColumn<int>("direction");
+ QTest::addColumn<int>("hide");
+ QTest::addColumn<int>("insert");
+ QTest::addColumn<int>("hidden");
+
+ QTest::newRow("horizontal, 0, 0") << int(Qt::Horizontal) << 0 << 0 << 1;
+}
+
+void tst_QHeaderView::hideAndInsert()
+{
+ QFETCH(int, direction);
+ QFETCH(int, hide);
+ QFETCH(int, insert);
+ QFETCH(int, hidden);
+
+ QStandardItemModel m(4, 4);
+ QHeaderView h((Qt::Orientation)direction);
+
+ h.setModel(&m);
+
+ h.setSectionHidden(hide, true);
+
+ if (direction == Qt::Vertical)
+ m.insertRow(insert);
+ else
+ m.insertColumn(insert);
+
+ for (int i = 0; i < h.count(); ++i)
+ if (i != hidden)
+ QCOMPARE(h.isSectionHidden(i), false);
+ else
+ QCOMPARE(h.isSectionHidden(i), true);
+}
+
+void tst_QHeaderView::removeSection()
+{
+//test that removing a hidden section gives the expected result: the next row should be hidden
+//(see task
+ const int hidden = 3; //section that will be hidden
+ const QStringList list = QStringList() << "0" << "1" << "2" << "3" << "4" << "5" << "6";
+
+ QStringListModel model( list );
+ QHeaderView view(Qt::Vertical);
+ view.setModel(&model);
+ view.hideSection(hidden);
+ view.hideSection(1);
+ model.removeRow(1);
+ view.show();
+
+ for(int i = 0; i < view.count(); i++) {
+ if (i == (hidden-1)) { //-1 because we removed a row in the meantime
+ QCOMPARE(view.sectionSize(i), 0);
+ QVERIFY(view.isSectionHidden(i));
+ } else {
+ QCOMPARE(view.sectionSize(i), view.defaultSectionSize() );
+ QVERIFY(!view.isSectionHidden(i));
+ }
+ }
+}
+
+void tst_QHeaderView::preserveHiddenSectionWidth()
+{
+ const QStringList list = QStringList() << "0" << "1" << "2" << "3";
+
+ QStringListModel model( list );
+ QHeaderView view(Qt::Vertical);
+ view.setModel(&model);
+ view.resizeSection(0, 100);
+ view.resizeSection(1, 10);
+ view.resizeSection(2, 50);
+ view.setResizeMode(3, QHeaderView::Stretch);
+ view.show();
+
+ view.hideSection(2);
+ model.removeRow(1);
+ view.showSection(1);
+ QCOMPARE(view.sectionSize(0), 100);
+ QCOMPARE(view.sectionSize(1), 50);
+
+ view.hideSection(1);
+ model.insertRow(1);
+ view.showSection(2);
+ QCOMPARE(view.sectionSize(0), 100);
+ QCOMPARE(view.sectionSize(1), view.defaultSectionSize());
+ QCOMPARE(view.sectionSize(2), 50);
+}
+
+void tst_QHeaderView::invisibleStretchLastSection()
+{
+ int count = 6;
+ QStandardItemModel model(1, count);
+ QHeaderView view(Qt::Horizontal);
+ view.setModel(&model);
+ int height = view.height();
+
+ view.resize(view.defaultSectionSize() * (count / 2), height); // don't show all sections
+ view.show();
+ view.setStretchLastSection(true);
+ // stretch section is not visible; it should not be stretched
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(view.sectionSize(i), view.defaultSectionSize());
+
+ view.resize(view.defaultSectionSize() * (count + 1), height); // give room to stretch
+
+ // stretch section is visible; it should be stretched
+ for (int i = 0; i < count - 1; ++i)
+ QCOMPARE(view.sectionSize(i), view.defaultSectionSize());
+ QCOMPARE(view.sectionSize(count - 1), view.defaultSectionSize() * 2);
+}
+
+void tst_QHeaderView::emptySectionSpan()
+{
+ QHeaderViewPrivate::SectionSpan span;
+ QCOMPARE(span.sectionSize(), 0);
+}
+
+void tst_QHeaderView::task236450_hidden_data()
+{
+ QTest::addColumn<QList<int> >("hide1");
+ QTest::addColumn<QList<int> >("hide2");
+
+ QTest::newRow("set 1") << (QList<int>() << 1 << 3)
+ << (QList<int>() << 1 << 5);
+
+ QTest::newRow("set 2") << (QList<int>() << 2 << 3)
+ << (QList<int>() << 1 << 5);
+
+ QTest::newRow("set 3") << (QList<int>() << 0 << 2 << 4)
+ << (QList<int>() << 2 << 3 << 5);
+
+}
+
+void tst_QHeaderView::task236450_hidden()
+{
+ QFETCH(QList<int>, hide1);
+ QFETCH(QList<int>, hide2);
+ const QStringList list = QStringList() << "0" << "1" << "2" << "3" << "4" << "5";
+
+ QStringListModel model( list );
+ protected_QHeaderView view(Qt::Vertical);
+ view.setModel(&model);
+ view.show();
+
+ foreach (int i, hide1)
+ view.hideSection(i);
+
+ QCOMPARE(view.hiddenSectionCount(), hide1.count());
+ for (int i = 0; i < 6; i++) {
+ QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i));
+ }
+
+ view.setDefaultSectionSize(2);
+ view.scheduleDelayedItemsLayout();
+ view.executeDelayedItemsLayout(); //force to do a relayout
+
+ QCOMPARE(view.hiddenSectionCount(), hide1.count());
+ for (int i = 0; i < 6; i++) {
+ QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i));
+ view.setSectionHidden(i, hide2.contains(i));
+ }
+
+ QCOMPARE(view.hiddenSectionCount(), hide2.count());
+ for (int i = 0; i < 6; i++) {
+ QCOMPARE(!view.isSectionHidden(i), !hide2.contains(i));
+ }
+
+}
+
+void tst_QHeaderView::task248050_hideRow()
+{
+ //this is the sequence of events that make the task fail
+ protected_QHeaderView header(Qt::Vertical);
+ QStandardItemModel model(0, 1);
+ header.setStretchLastSection(false);
+ header.setDefaultSectionSize(17);
+ header.setModel(&model);
+ header.doItemsLayout();
+
+ model.setRowCount(3);
+
+ QCOMPARE(header.sectionPosition(2), 17*2);
+
+ header.hideSection(1);
+ QCOMPARE(header.sectionPosition(2), 17);
+
+ QTest::qWait(100);
+ //the size of the section shouldn't have changed
+ QCOMPARE(header.sectionPosition(2), 17);
+}
+
+
+//returns 0 if everything is fine.
+static int checkHeaderViewOrder(QHeaderView *view, const QVector<int> &expected)
+{
+ if (view->count() != expected.count())
+ return 1;
+
+ for (int i = 0; i < expected.count(); i++) {
+ if (view->logicalIndex(i) != expected.at(i))
+ return i + 10;
+ if (view->visualIndex(expected.at(i)) != i)
+ return i + 100;
+ }
+ return 0;
+}
+
+
+void tst_QHeaderView::QTBUG6058_reset()
+{
+ QStringListModel model1( QStringList() << "0" << "1" << "2" << "3" << "4" << "5" );
+ QStringListModel model2( QStringList() << "a" << "b" << "c" );
+ QSortFilterProxyModel proxy;
+
+ QHeaderView view(Qt::Vertical);
+ view.setModel(&proxy);
+ view.show();
+ QTest::qWait(20);
+
+ proxy.setSourceModel(&model1);
+ QApplication::processEvents();
+ view.swapSections(0,2);
+ view.swapSections(1,4);
+ QApplication::processEvents();
+ QCOMPARE(checkHeaderViewOrder(&view, QVector<int>() << 2 << 4 << 0 << 3 << 1 << 5) , 0);
+
+ proxy.setSourceModel(&model2);
+ QApplication::processEvents();
+ QCOMPARE(checkHeaderViewOrder(&view, QVector<int>() << 2 << 0 << 1 ) , 0);
+
+ proxy.setSourceModel(&model1);
+ QApplication::processEvents();
+ QCOMPARE(checkHeaderViewOrder(&view, QVector<int>() << 2 << 0 << 1 << 3 << 4 << 5 ) , 0);
+}
+
+void tst_QHeaderView::QTBUG7833_sectionClicked()
+{
+
+
+
+
+ QTableView tv;
+ QStandardItemModel *sim = new QStandardItemModel(&tv);
+ QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(&tv);
+ proxyModel->setSourceModel(sim);
+ proxyModel->setDynamicSortFilter(true);
+ proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+
+ QList<QStandardItem *> row;
+ for (int i = 0; i < 12; i++)
+ row.append(new QStandardItem(QString(QLatin1Char('A' + i))));
+ sim->appendRow(row);
+ row.clear();
+ for (int i = 12; i > 0; i--)
+ row.append(new QStandardItem(QString(QLatin1Char('A' + i))));
+ sim->appendRow(row);
+
+ tv.setSortingEnabled(true);
+ tv.horizontalHeader()->setSortIndicatorShown(true);
+ tv.horizontalHeader()->setClickable(true);
+ tv.horizontalHeader()->setStretchLastSection(true);
+ tv.horizontalHeader()->setResizeMode(QHeaderView::Interactive);
+
+ tv.setModel(proxyModel);
+ tv.setColumnHidden(5, true);
+ tv.setColumnHidden(6, true);
+ tv.horizontalHeader()->swapSections(8, 10);
+ tv.sortByColumn(1, Qt::AscendingOrder);
+
+ QSignalSpy clickedSpy(tv.horizontalHeader(), SIGNAL(sectionClicked(int)));
+ QSignalSpy pressedSpy(tv.horizontalHeader(), SIGNAL(sectionPressed(int)));
+
+
+ QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier,
+ QPoint(tv.horizontalHeader()->sectionViewportPosition(11) + tv.horizontalHeader()->sectionSize(11)/2, 5));
+ QCOMPARE(clickedSpy.count(), 1);
+ QCOMPARE(pressedSpy.count(), 1);
+ QCOMPARE(clickedSpy.at(0).at(0).toInt(), 11);
+ QCOMPARE(pressedSpy.at(0).at(0).toInt(), 11);
+
+ QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier,
+ QPoint(tv.horizontalHeader()->sectionViewportPosition(8) + tv.horizontalHeader()->sectionSize(0)/2, 5));
+
+ QCOMPARE(clickedSpy.count(), 2);
+ QCOMPARE(pressedSpy.count(), 2);
+ QCOMPARE(clickedSpy.at(1).at(0).toInt(), 8);
+ QCOMPARE(pressedSpy.at(1).at(0).toInt(), 8);
+
+ QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier,
+ QPoint(tv.horizontalHeader()->sectionViewportPosition(0) + tv.horizontalHeader()->sectionSize(0)/2, 5));
+
+ QCOMPARE(clickedSpy.count(), 3);
+ QCOMPARE(pressedSpy.count(), 3);
+ QCOMPARE(clickedSpy.at(2).at(0).toInt(), 0);
+ QCOMPARE(pressedSpy.at(2).at(0).toInt(), 0);
+}
+
+void tst_QHeaderView::QTBUG8650_crashOnInsertSections()
+{
+ QStringList headerLabels;
+ QHeaderView view(Qt::Horizontal);
+ QStandardItemModel model(2,2);
+ view.setModel(&model);
+ view.moveSection(1, 0);
+ view.hideSection(0);
+
+ QList<QStandardItem *> items;
+ items << new QStandardItem("c");
+ model.insertColumn(0, items);
+}
+
+void tst_QHeaderView::QTBUG12268_hiddenMovedSectionSorting()
+{
+ QTableView view;
+ QStandardItemModel *model = new QStandardItemModel(4,3, &view);
+ for (int i = 0; i< model->rowCount(); ++i)
+ for (int j = 0; j< model->columnCount(); ++j)
+ model->setData(model->index(i,j), QString("item [%1,%2]").arg(i).arg(j));
+ view.setModel(model);
+ view.horizontalHeader()->setMovable(true);
+ view.setSortingEnabled(true);
+ view.sortByColumn(1, Qt::AscendingOrder);
+ view.horizontalHeader()->moveSection(0,2);
+ view.setColumnHidden(1, true);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1);
+ QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton);
+ QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1);
+}
+
+void tst_QHeaderView::initialSortOrderRole()
+{
+ QTableView view;
+ QStandardItemModel *model = new QStandardItemModel(4, 3, &view);
+ for (int i = 0; i< model->rowCount(); ++i)
+ for (int j = 0; j< model->columnCount(); ++j)
+ model->setData(model->index(i,j), QString("item [%1,%2]").arg(i).arg(j));
+ QStandardItem *ascendingItem = new QStandardItem();
+ QStandardItem *descendingItem = new QStandardItem();
+ ascendingItem->setData(Qt::AscendingOrder, Qt::InitialSortOrderRole);
+ descendingItem->setData(Qt::DescendingOrder, Qt::InitialSortOrderRole);
+ model->setHorizontalHeaderItem(1, ascendingItem);
+ model->setHorizontalHeaderItem(2, descendingItem);
+ view.setModel(model);
+ view.setSortingEnabled(true);
+ view.sortByColumn(0, Qt::AscendingOrder);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ const int column1Pos = view.horizontalHeader()->sectionViewportPosition(1) + 5; // +5 not to be on the handle
+ QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column1Pos, 0));
+ QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 1);
+ QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder);
+
+ const int column2Pos = view.horizontalHeader()->sectionViewportPosition(2) + 5; // +5 not to be on the handle
+ QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column2Pos, 0));
+ QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 2);
+ QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::DescendingOrder);
+
+ const int column0Pos = view.horizontalHeader()->sectionViewportPosition(0) + 5; // +5 not to be on the handle
+ QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column0Pos, 0));
+ QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 0);
+ QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder);
+}
+
+QTEST_MAIN(tst_QHeaderView)
+#include "tst_qheaderview.moc"
diff --git a/tests/auto/widgets/itemviews/qidentityproxymodel/qidentityproxymodel.pro b/tests/auto/widgets/itemviews/qidentityproxymodel/qidentityproxymodel.pro
new file mode 100644
index 0000000000..141e72a8c0
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qidentityproxymodel/qidentityproxymodel.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+mtdir = ../../../integrationtests/modeltest
+INCLUDEPATH += $$PWD/$${mtdir}
+QT += widgets
+SOURCES += tst_qidentityproxymodel.cpp $${mtdir}/dynamictreemodel.cpp $${mtdir}/modeltest.cpp
+HEADERS += $${mtdir}/dynamictreemodel.h $${mtdir}/modeltest.h
diff --git a/tests/auto/widgets/itemviews/qidentityproxymodel/tst_qidentityproxymodel.cpp b/tests/auto/widgets/itemviews/qidentityproxymodel/tst_qidentityproxymodel.cpp
new file mode 100644
index 0000000000..6d73cbe2e1
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qidentityproxymodel/tst_qidentityproxymodel.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore>
+#include <QtGui>
+#include <QtWidgets>
+
+#include "dynamictreemodel.h"
+#include "qidentityproxymodel.h"
+
+//TESTED CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+class tst_QIdentityProxyModel : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ tst_QIdentityProxyModel();
+ virtual ~tst_QIdentityProxyModel();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void insertRows();
+ void removeRows();
+ void moveRows();
+ void reset();
+
+protected:
+ void verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex());
+
+private:
+ QStandardItemModel *m_model;
+ QIdentityProxyModel *m_proxy;
+};
+
+tst_QIdentityProxyModel::tst_QIdentityProxyModel()
+ : m_model(0), m_proxy(0)
+{
+
+}
+
+tst_QIdentityProxyModel::~tst_QIdentityProxyModel()
+{
+
+}
+
+void tst_QIdentityProxyModel::initTestCase()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+
+ m_model = new QStandardItemModel(0, 1);
+ m_proxy = new QIdentityProxyModel();
+}
+
+void tst_QIdentityProxyModel::cleanupTestCase()
+{
+ delete m_proxy;
+ delete m_model;
+}
+
+void tst_QIdentityProxyModel::init()
+{
+}
+
+void tst_QIdentityProxyModel::cleanup()
+{
+ m_model->clear();
+ m_model->insertColumns(0, 1);
+}
+
+void tst_QIdentityProxyModel::verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent)
+{
+ const int rows = model->rowCount(parent);
+ const int columns = model->columnCount(parent);
+ const QModelIndex proxyParent = m_proxy->mapFromSource(parent);
+
+ QVERIFY(m_proxy->mapToSource(proxyParent) == parent);
+ QVERIFY(rows == m_proxy->rowCount(proxyParent));
+ QVERIFY(columns == m_proxy->columnCount(proxyParent));
+
+ for (int row = 0; row < rows; ++row) {
+ for (int column = 0; column < columns; ++column) {
+ const QModelIndex idx = model->index(row, column, parent);
+ const QModelIndex proxyIdx = m_proxy->mapFromSource(idx);
+ QVERIFY(proxyIdx.model() == m_proxy);
+ QVERIFY(m_proxy->mapToSource(proxyIdx) == idx);
+ QVERIFY(proxyIdx.isValid());
+ QVERIFY(proxyIdx.row() == row);
+ QVERIFY(proxyIdx.column() == column);
+ QVERIFY(proxyIdx.parent() == proxyParent);
+ QVERIFY(proxyIdx.data() == idx.data());
+ QVERIFY(proxyIdx.flags() == idx.flags());
+ const int childCount = m_proxy->rowCount(proxyIdx);
+ const bool hasChildren = m_proxy->hasChildren(proxyIdx);
+ QVERIFY(model->hasChildren(idx) == hasChildren);
+ QVERIFY((childCount > 0) == hasChildren);
+
+ if (hasChildren)
+ verifyIdentity(model, idx);
+ }
+ }
+}
+
+/*
+ tests
+*/
+
+void tst_QIdentityProxyModel::insertRows()
+{
+ QStandardItem *parentItem = m_model->invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+
+ m_proxy->setSourceModel(m_model);
+
+ verifyIdentity(m_model);
+
+ QSignalSpy modelBeforeSpy(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy modelAfterSpy(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(rowsInserted(QModelIndex,int,int)));
+
+ QStandardItem *item = new QStandardItem(QString("new item"));
+ parentItem->appendRow(item);
+
+ QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
+ QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
+
+ QVERIFY(modelBeforeSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value<QModelIndex>()));
+ QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1));
+ QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2));
+
+ QVERIFY(modelAfterSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().first().value<QModelIndex>()));
+ QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1));
+ QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2));
+
+ verifyIdentity(m_model);
+
+}
+
+void tst_QIdentityProxyModel::removeRows()
+{
+ QStandardItem *parentItem = m_model->invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+
+ m_proxy->setSourceModel(m_model);
+
+ verifyIdentity(m_model);
+
+ QSignalSpy modelBeforeSpy(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy modelAfterSpy(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+
+ const QModelIndex topLevel = m_model->index(0, 0, QModelIndex());
+ const QModelIndex secondLevel = m_model->index(0, 0, topLevel);
+ const QModelIndex thirdLevel = m_model->index(0, 0, secondLevel);
+
+ QVERIFY(thirdLevel.isValid());
+
+ m_model->removeRow(0, secondLevel);
+
+ QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
+ QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
+
+ QVERIFY(modelBeforeSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value<QModelIndex>()));
+ QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1));
+ QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2));
+
+ QVERIFY(modelAfterSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().first().value<QModelIndex>()));
+ QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1));
+ QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2));
+
+ verifyIdentity(m_model);
+}
+
+void tst_QIdentityProxyModel::moveRows()
+{
+ DynamicTreeModel model;
+
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(QList<int>() << 5);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+
+ m_proxy->setSourceModel(&model);
+
+ verifyIdentity(&model);
+
+ QSignalSpy modelBeforeSpy(&model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ QSignalSpy modelAfterSpy(&model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+
+ {
+ ModelMoveCommand moveCommand(&model, 0);
+ moveCommand.setAncestorRowNumbers(QList<int>() << 5);
+ moveCommand.setStartRow(3);
+ moveCommand.setEndRow(4);
+ moveCommand.setDestRow(1);
+ moveCommand.doCommand();
+ }
+
+ QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
+ QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
+
+ QVERIFY(modelBeforeSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value<QModelIndex>()));
+ QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1));
+ QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2));
+ QVERIFY(modelBeforeSpy.first().at(3).value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().at(3).value<QModelIndex>()));
+ QVERIFY(modelBeforeSpy.first().at(4) == proxyBeforeSpy.first().at(4));
+
+ QVERIFY(modelAfterSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().first().value<QModelIndex>()));
+ QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1));
+ QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2));
+ QVERIFY(modelAfterSpy.first().at(3).value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().at(3).value<QModelIndex>()));
+ QVERIFY(modelAfterSpy.first().at(4) == proxyAfterSpy.first().at(4));
+
+ verifyIdentity(&model);
+
+ m_proxy->setSourceModel(0);
+}
+
+void tst_QIdentityProxyModel::reset()
+{
+ DynamicTreeModel model;
+
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(QList<int>() << 5);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+
+ m_proxy->setSourceModel(&model);
+
+ verifyIdentity(&model);
+
+ QSignalSpy modelBeforeSpy(&model, SIGNAL(modelAboutToBeReset()));
+ QSignalSpy modelAfterSpy(&model, SIGNAL(modelReset()));
+ QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(modelAboutToBeReset()));
+ QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(modelReset()));
+
+ {
+ ModelResetCommandFixed resetCommand(&model, 0);
+ resetCommand.setAncestorRowNumbers(QList<int>() << 5);
+ resetCommand.setStartRow(3);
+ resetCommand.setEndRow(4);
+ resetCommand.setDestRow(1);
+ resetCommand.doCommand();
+ }
+
+ QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
+ QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
+
+ verifyIdentity(&model);
+ m_proxy->setSourceModel(0);
+}
+
+QTEST_MAIN(tst_QIdentityProxyModel)
+#include "tst_qidentityproxymodel.moc"
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/.gitignore b/tests/auto/widgets/itemviews/qitemdelegate/.gitignore
new file mode 100644
index 0000000000..5faa678712
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemdelegate/.gitignore
@@ -0,0 +1 @@
+tst_qitemdelegate
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
new file mode 100644
index 0000000000..9a1a3b5e94
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qitemdelegate.cpp
+
+win32:!wince*: LIBS += -lUser32
+
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
new file mode 100644
index 0000000000..e419a7f097
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
@@ -0,0 +1,1216 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qabstractitemview.h>
+#include <qstandarditemmodel.h>
+#include <qapplication.h>
+#include <qdatetimeedit.h>
+#include <qspinbox.h>
+#include <qlistview.h>
+#include <qtableview.h>
+#include <qtreeview.h>
+#include <qheaderview.h>
+#include <qitemeditorfactory.h>
+#include <qlineedit.h>
+#include <qvalidator.h>
+#include <qtablewidget.h>
+#include <qtreewidget.h>
+
+#include <QItemDelegate>
+#include <QAbstractItemDelegate>
+#include <QTextEdit>
+#include <QPlainTextEdit>
+#include <QDialog>
+
+Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
+#include <windows.h>
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("The widgets don't get the paint events", SkipSingle);
+#else
+#define Q_CHECK_PAINTEVENTS
+#endif
+
+//Begin of class definitions
+
+class TestItemDelegate : public QItemDelegate
+{
+public:
+ TestItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {}
+ ~TestItemDelegate() {}
+
+ void drawDisplay(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QRect &rect, const QString &text) const
+ {
+ displayText = text;
+ displayFont = option.font;
+ QItemDelegate::drawDisplay(painter, option, rect, text);
+ }
+
+ void drawDecoration(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QRect &rect, const QPixmap &pixmap) const
+ {
+ decorationPixmap = pixmap;
+ decorationRect = rect;
+ QItemDelegate::drawDecoration(painter, option, rect, pixmap);
+ }
+
+
+ inline QRect textRectangle(QPainter * painter, const QRect &rect,
+ const QFont &font, const QString &text) const
+ {
+ return QItemDelegate::textRectangle(painter, rect, font, text);
+ }
+
+ inline void doLayout(const QStyleOptionViewItem &option,
+ QRect *checkRect, QRect *pixmapRect,
+ QRect *textRect, bool hint) const
+ {
+ QItemDelegate::doLayout(option, checkRect, pixmapRect, textRect, hint);
+ }
+
+ inline QRect rect(const QStyleOptionViewItem &option,
+ const QModelIndex &index, int role) const
+ {
+ return QItemDelegate::rect(option, index, role);
+ }
+
+ inline bool eventFilter(QObject *object, QEvent *event)
+ {
+ return QItemDelegate::eventFilter(object, event);
+ }
+
+ inline bool editorEvent(QEvent *event,
+ QAbstractItemModel *model,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index)
+ {
+ return QItemDelegate::editorEvent(event, model, option, index);
+ }
+
+ // stored values for testing
+ mutable QString displayText;
+ mutable QFont displayFont;
+ mutable QPixmap decorationPixmap;
+ mutable QRect decorationRect;
+};
+
+class TestItemModel : public QAbstractTableModel
+{
+public:
+
+ enum Roles {
+ PixmapTestRole,
+ ImageTestRole,
+ IconTestRole,
+ ColorTestRole,
+ DoubleTestRole
+ };
+
+ TestItemModel(const QSize &size) : size(size) {}
+
+ ~TestItemModel() {}
+
+ int rowCount(const QModelIndex &parent) const
+ {
+ Q_UNUSED(parent);
+ return 1;
+ }
+
+ int columnCount(const QModelIndex &parent) const
+ {
+ Q_UNUSED(parent);
+ return 1;
+ }
+
+ QVariant data(const QModelIndex& index, int role) const
+ {
+ Q_UNUSED(index);
+ static QPixmap pixmap(size);
+ static QImage image(size, QImage::Format_Mono);
+ static QIcon icon(pixmap);
+ static QColor color(Qt::green);
+
+ switch (role) {
+ case PixmapTestRole: return pixmap;
+ case ImageTestRole: return image;
+ case IconTestRole: return icon;
+ case ColorTestRole: return color;
+ case DoubleTestRole: return 10.00000001;
+ default: break;
+ }
+
+ return QVariant();
+ }
+
+private:
+ QSize size;
+};
+
+class tst_QItemDelegate : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QItemDelegate();
+ virtual ~tst_QItemDelegate();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+ void getSetCheck();
+ void textRectangle_data();
+ void textRectangle();
+ void sizeHint_data();
+ void sizeHint();
+ void editorKeyPress_data();
+ void editorKeyPress();
+ void doubleEditorNegativeInput();
+ void font_data();
+ void font();
+ void doLayout_data();
+ void doLayout();
+ void rect_data();
+ void rect();
+ void eventFilter();
+ void dateTimeEditor_data();
+ void dateTimeEditor();
+ void decoration_data();
+ void decoration();
+ void editorEvent_data();
+ void editorEvent();
+ void enterKey_data();
+ void enterKey();
+
+ void task257859_finalizeEdit();
+ void QTBUG4435_keepSelectionOnCheck();
+};
+
+
+//End of class definitions
+
+// Testing get/set functions
+void tst_QItemDelegate::getSetCheck()
+{
+ QItemDelegate obj1;
+
+ // QItemEditorFactory * QItemDelegate::itemEditorFactory()
+ // void QItemDelegate::setItemEditorFactory(QItemEditorFactory *)
+ QItemEditorFactory *var1 = new QItemEditorFactory;
+ obj1.setItemEditorFactory(var1);
+ QCOMPARE(var1, obj1.itemEditorFactory());
+ obj1.setItemEditorFactory((QItemEditorFactory *)0);
+ QCOMPARE((QItemEditorFactory *)0, obj1.itemEditorFactory());
+ delete var1;
+
+ QCOMPARE(obj1.hasClipping(), true);
+ obj1.setClipping(false);
+ QCOMPARE(obj1.hasClipping(), false);
+ obj1.setClipping(true);
+ QCOMPARE(obj1.hasClipping(), true);
+}
+
+tst_QItemDelegate::tst_QItemDelegate()
+{
+}
+
+tst_QItemDelegate::~tst_QItemDelegate()
+{
+}
+
+void tst_QItemDelegate::initTestCase()
+{
+}
+
+void tst_QItemDelegate::cleanupTestCase()
+{
+}
+
+void tst_QItemDelegate::init()
+{
+}
+
+void tst_QItemDelegate::cleanup()
+{
+}
+
+void tst_QItemDelegate::textRectangle_data()
+{
+ QFont font;
+ QFontMetrics fontMetrics(font);
+ int pm = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ int margins = 2 * (pm + 1); // margin on each side of the text
+ int height = fontMetrics.height();
+
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QRect>("rect");
+ QTest::addColumn<QRect>("expected");
+
+ QTest::newRow("empty") << QString()
+ << QRect()
+ << QRect(0, 0, margins, height);
+}
+
+void tst_QItemDelegate::textRectangle()
+{
+ QFETCH(QString, text);
+ QFETCH(QRect, rect);
+ QFETCH(QRect, expected);
+
+ QFont font;
+ TestItemDelegate delegate;
+ QRect result = delegate.textRectangle(0, rect, font, text);
+
+ QCOMPARE(result, expected);
+}
+
+void tst_QItemDelegate::sizeHint_data()
+{
+ QTest::addColumn<QSize>("expected");
+
+ QFont font;
+ QFontMetrics fontMetrics(font);
+ //int m = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ QTest::newRow("empty")
+ << QSize(0, fontMetrics.height());
+
+}
+
+void tst_QItemDelegate::sizeHint()
+{
+ QFETCH(QSize, expected);
+
+ QModelIndex index;
+ QStyleOptionViewItem option;
+
+ TestItemDelegate delegate;
+ QSize result = delegate.sizeHint(option, index);
+ QCOMPARE(result, expected);
+}
+
+void tst_QItemDelegate::editorKeyPress_data()
+{
+ QTest::addColumn<QString>("initial");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("foo bar")
+ << QString("foo")
+ << QString("bar");
+}
+
+void tst_QItemDelegate::editorKeyPress()
+{
+ QFETCH(QString, initial);
+ QFETCH(QString, expected);
+
+ QStandardItemModel model;
+ model.appendRow(new QStandardItem(initial));
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex index = model.index(0, 0);
+ view.setCurrentIndex(index); // the editor will only selectAll on the current index
+ view.edit(index);
+
+ QList<QLineEdit*> lineEditors = qFindChildren<QLineEdit *>(view.viewport());
+ QCOMPARE(lineEditors.count(), 1);
+
+ QLineEdit *editor = lineEditors.at(0);
+ QCOMPARE(editor->selectedText(), initial);
+
+ QTest::keyClicks(editor, expected);
+ QTest::keyClick(editor, Qt::Key_Enter);
+ QApplication::processEvents();
+
+ QCOMPARE(index.data().toString(), expected);
+}
+
+void tst_QItemDelegate::doubleEditorNegativeInput()
+{
+ QStandardItemModel model;
+
+ QStandardItem *item = new QStandardItem;
+ item->setData(10.0, Qt::DisplayRole);
+ model.appendRow(item);
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex index = model.index(0, 0);
+ view.setCurrentIndex(index); // the editor will only selectAll on the current index
+ view.edit(index);
+
+ QList<QDoubleSpinBox*> editors = qFindChildren<QDoubleSpinBox *>(view.viewport());
+ QCOMPARE(editors.count(), 1);
+
+ QDoubleSpinBox *editor = editors.at(0);
+ QCOMPARE(editor->value(), double(10));
+
+ QTest::keyClick(editor, Qt::Key_Minus);
+ QTest::keyClick(editor, Qt::Key_1);
+ QTest::keyClick(editor, Qt::Key_0);
+ QTest::keyClick(editor, Qt::Key_Comma); //support both , and . locales
+ QTest::keyClick(editor, Qt::Key_Period);
+ QTest::keyClick(editor, Qt::Key_0);
+ QTest::keyClick(editor, Qt::Key_Enter);
+ QApplication::processEvents();
+
+ QCOMPARE(index.data().toString(), QString("-10"));
+}
+
+void tst_QItemDelegate::font_data()
+{
+ QTest::addColumn<QString>("itemText");
+ QTest::addColumn<QString>("properties");
+ QTest::addColumn<QFont>("itemFont");
+ QTest::addColumn<QFont>("viewFont");
+
+ QFont itemFont;
+ itemFont.setItalic(true);
+ QFont viewFont;
+
+ QTest::newRow("foo italic")
+ << QString("foo")
+ << QString("italic")
+ << itemFont
+ << viewFont;
+
+ itemFont.setItalic(true);
+
+ QTest::newRow("foo bold")
+ << QString("foo")
+ << QString("bold")
+ << itemFont
+ << viewFont;
+
+ itemFont.setFamily(itemFont.defaultFamily());
+
+ QTest::newRow("foo family")
+ << QString("foo")
+ << QString("family")
+ << itemFont
+ << viewFont;
+ }
+
+void tst_QItemDelegate::font()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QFETCH(QString, itemText);
+ QFETCH(QString, properties);
+ QFETCH(QFont, itemFont);
+ QFETCH(QFont, viewFont);
+
+ QTableWidget table(1, 1);
+ table.setFont(viewFont);
+
+ TestItemDelegate *delegate = new TestItemDelegate(&table);
+ table.setItemDelegate(delegate);
+ table.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&table);
+#endif
+
+ QTableWidgetItem *item = new QTableWidgetItem;
+ item->setText(itemText);
+ item->setFont(itemFont);
+ table.setItem(0, 0, item);
+
+ QApplication::processEvents();
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+
+ QTRY_COMPARE(delegate->displayText, item->text());
+ if (properties.contains("italic")) {
+ QCOMPARE(delegate->displayFont.italic(), item->font().italic());
+ }
+ if (properties.contains("bold")){
+ QCOMPARE(delegate->displayFont.bold(), item->font().bold());
+ }
+ if (properties.contains("family")){
+ QCOMPARE(delegate->displayFont.family(), item->font().family());
+ }
+}
+
+//Testing the different QRect created by the doLayout function.
+//Tests are made with different values for the QStyleOptionViewItem properties:
+//decorationPosition and position.
+
+void tst_QItemDelegate::doLayout_data()
+{
+ QTest::addColumn<int>("position");
+ QTest::addColumn<int>("direction");
+ QTest::addColumn<bool>("hint");
+ QTest::addColumn<QRect>("itemRect");
+ QTest::addColumn<QRect>("checkRect");
+ QTest::addColumn<QRect>("pixmapRect");
+ QTest::addColumn<QRect>("textRect");
+ QTest::addColumn<QRect>("expectedCheckRect");
+ QTest::addColumn<QRect>("expectedPixmapRect");
+ QTest::addColumn<QRect>("expectedTextRect");
+
+ int m = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ //int item = 400;
+ //int check = 50;
+ //int pixmap = 1000;
+ //int text = 400;
+
+ QTest::newRow("top, left to right, hint")
+ << (int)QStyleOptionViewItem::Top
+ << (int)Qt::LeftToRight
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(m, 0, 50 + 2*m, 1000)
+ << QRect(50 + 2*m, 0, 1000 + 2*m, 1000 + m)
+ << QRect(50 + 2*m, 1000 + m, 1000 + 2*m, 400);
+ /*
+ QTest::newRow("top, left to right, limited")
+ << (int)QStyleOptionViewItem::Top
+ << (int)Qt::LeftToRight
+ << false
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(m, (400/2) - (50/2), 50, 50)
+ << QRect(50 + 2*m, 0, 1000, 1000)
+ << QRect(50 + 2*m, 1000 + m, 400 - (50 + 2*m), 400 - 1000 - m);
+ */
+ QTest::newRow("top, right to left, hint")
+ << (int)QStyleOptionViewItem::Top
+ << (int)Qt::RightToLeft
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(1000 + 2 * m, 0, 50 + 2 * m, 1000)
+ << QRect(0, 0, 1000 + 2 * m, 1000 + m)
+ << QRect(0, 1000 + m, 1000 + 2 * m, 400);
+
+ QTest::newRow("bottom, left to right, hint")
+ << (int)QStyleOptionViewItem::Bottom
+ << (int)Qt::LeftToRight
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(m, 0, 50 + 2 * m, 1000)
+ << QRect(50 + 2 * m, 400 + m, 1000 + 2 * m, 1000)
+ << QRect(50 + 2 * m, 0, 1000 + 2 * m, 400 + m);
+
+ QTest::newRow("bottom, right to left, hint")
+ << (int)QStyleOptionViewItem::Bottom
+ << (int)Qt::RightToLeft
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(1000 + 2 * m, 0, 50 + 2 * m, 1000)
+ << QRect(0, 400 + m, 1000 + 2 * m, 1000)
+ << QRect(0, 0, 1000 + 2 * m, 400 + m);
+
+ QTest::newRow("left, left to right, hint")
+ << (int)QStyleOptionViewItem::Left
+ << (int)Qt::LeftToRight
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(m, 0, 50 + 2 * m, 1000)
+ << QRect(50 + 2 * m, 0, 1000 + 2 * m, 1000)
+ << QRect(1050 + 4 * m, 0, 400 + 2 * m, 1000);
+
+ QTest::newRow("left, right to left, hint")
+ << (int)QStyleOptionViewItem::Left
+ << (int)Qt::RightToLeft
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(1400 + 4 * m, 0, 50 + 2 * m, 1000)
+ << QRect(400 + 2 * m, 0, 1000 + 2 * m, 1000)
+ << QRect(0, 0, 400 + 2 * m, 1000);
+
+ QTest::newRow("right, left to right, hint")
+ << (int)QStyleOptionViewItem::Right
+ << (int)Qt::LeftToRight
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(m, 0, 50 + 2 * m, 1000)
+ << QRect(450 + 4 * m, 0, 1000 + 2 * m, 1000)
+ << QRect(50 + 2 * m, 0, 400 + 2 * m, 1000);
+
+ QTest::newRow("right, right to left, hint")
+ << (int)QStyleOptionViewItem::Right
+ << (int)Qt::RightToLeft
+ << true
+ << QRect(0, 0, 400, 400)
+ << QRect(0, 0, 50, 50)
+ << QRect(0, 0, 1000, 1000)
+ << QRect(0, 0, 400, 400)
+ << QRect(1400 + 4 * m, 0, 50 + 2 * m, 1000)
+ << QRect(0, 0, 1000 + 2 * m, 1000)
+ << QRect(1000 + 2 * m, 0, 400 + 2 * m, 1000);
+}
+
+void tst_QItemDelegate::doLayout()
+{
+ QFETCH(int, position);
+ QFETCH(int, direction);
+ QFETCH(bool, hint);
+ QFETCH(QRect, itemRect);
+ QFETCH(QRect, checkRect);
+ QFETCH(QRect, pixmapRect);
+ QFETCH(QRect, textRect);
+ QFETCH(QRect, expectedCheckRect);
+ QFETCH(QRect, expectedPixmapRect);
+ QFETCH(QRect, expectedTextRect);
+
+ TestItemDelegate delegate;
+ QStyleOptionViewItem option;
+
+ option.rect = itemRect;
+ option.decorationPosition = (QStyleOptionViewItem::Position)position;
+ option.direction = (Qt::LayoutDirection)direction;
+
+ delegate.doLayout(option, &checkRect, &pixmapRect, &textRect, hint);
+
+ QCOMPARE(checkRect, expectedCheckRect);
+ QCOMPARE(pixmapRect, expectedPixmapRect);
+ QCOMPARE(textRect, expectedTextRect);
+}
+
+void tst_QItemDelegate::rect_data()
+{
+ QTest::addColumn<int>("role");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QRect>("expected");
+
+ QTest::newRow("pixmap")
+ << (int)TestItemModel::PixmapTestRole
+ << QSize(200, 300)
+ << QRect(0, 0, 200, 300);
+
+ QTest::newRow("image")
+ << (int)TestItemModel::ImageTestRole
+ << QSize(200, 300)
+ << QRect(0, 0, 200, 300);
+
+ QTest::newRow("icon")
+ << (int)TestItemModel::IconTestRole
+ << QSize(200, 300)
+ << QRect(0, 0, 200, 300);
+
+ QTest::newRow("color")
+ << (int)TestItemModel::ColorTestRole
+ << QSize(200, 300)
+ << QRect(0, 0, 200, 300);
+
+ QTest::newRow("double")
+ << (int)TestItemModel::DoubleTestRole
+ << QSize()
+ << QRect();
+}
+
+void tst_QItemDelegate::rect()
+{
+ QFETCH(int, role);
+ QFETCH(QSize, size);
+ QFETCH(QRect, expected);
+
+ TestItemModel model(size);
+ QStyleOptionViewItem option;
+ TestItemDelegate delegate;
+ option.decorationSize = size;
+
+ if (role == TestItemModel::DoubleTestRole)
+ expected = delegate.textRectangle(0, QRect(), QFont(), QLatin1String("10.00000001"));
+
+ QModelIndex index = model.index(0, 0);
+ QVERIFY(index.isValid());
+ QRect result = delegate.rect(option, index, role);
+ QCOMPARE(result, expected);
+}
+
+//TODO : Add a test for the keyPress event
+//with Qt::Key_Enter and Qt::Key_Return
+void tst_QItemDelegate::eventFilter()
+{
+ TestItemDelegate delegate;
+ QWidget widget;
+ QEvent *event;
+
+ qRegisterMetaType<QAbstractItemDelegate::EndEditHint>("QAbstractItemDelegate::EndEditHint");
+
+ QSignalSpy commitDataSpy(&delegate, SIGNAL(commitData(QWidget *)));
+ QSignalSpy closeEditorSpy(&delegate,
+ SIGNAL(closeEditor(QWidget *,
+ QAbstractItemDelegate::EndEditHint)));
+
+ //Subtest KeyPress
+ //For each test we send a key event and check if signals were emitted.
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
+ QVERIFY(delegate.eventFilter(&widget, event));
+ QCOMPARE(closeEditorSpy.count(), 1);
+ QCOMPARE(commitDataSpy.count(), 1);
+ delete event;
+
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier);
+ QVERIFY(delegate.eventFilter(&widget, event));
+ QCOMPARE(closeEditorSpy.count(), 2);
+ QCOMPARE(commitDataSpy.count(), 2);
+ delete event;
+
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
+ QVERIFY(delegate.eventFilter(&widget, event));
+ QCOMPARE(closeEditorSpy.count(), 3);
+ QCOMPARE(commitDataSpy.count(), 2);
+ delete event;
+
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
+ QVERIFY(!delegate.eventFilter(&widget, event));
+ QCOMPARE(closeEditorSpy.count(), 3);
+ QCOMPARE(commitDataSpy.count(), 2);
+ delete event;
+
+ //Subtest focusEvent
+ event = new QFocusEvent(QEvent::FocusOut);
+ QVERIFY(!delegate.eventFilter(&widget, event));
+ QCOMPARE(closeEditorSpy.count(), 4);
+ QCOMPARE(commitDataSpy.count(), 3);
+ delete event;
+}
+
+void tst_QItemDelegate::dateTimeEditor_data()
+{
+ QTest::addColumn<QTime>("time");
+ QTest::addColumn<QDate>("date");
+
+ QTest::newRow("data")
+ << QTime(7, 16, 34)
+ << QDate(2006, 10, 31);
+}
+
+void tst_QItemDelegate::dateTimeEditor()
+{
+ QFETCH(QTime, time);
+ QFETCH(QDate, date);
+
+ QTableWidgetItem *item1 = new QTableWidgetItem;
+ item1->setData(Qt::DisplayRole, time);
+
+ QTableWidgetItem *item2 = new QTableWidgetItem;
+ item2->setData(Qt::DisplayRole, date);
+
+ QTableWidgetItem *item3 = new QTableWidgetItem;
+ item3->setData(Qt::DisplayRole, QDateTime(date, time));
+
+ QTableWidget widget(1, 3);
+ widget.setItem(0, 0, item1);
+ widget.setItem(0, 1, item2);
+ widget.setItem(0, 2, item3);
+ widget.show();
+
+ widget.editItem(item1);
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QTimeEdit *timeEditor = qFindChild<QTimeEdit *>(widget.viewport());
+ QVERIFY(timeEditor);
+ QCOMPARE(timeEditor->time(), time);
+
+ widget.clearFocus();
+ qApp->setActiveWindow(&widget);
+ widget.setFocus();
+ widget.editItem(item2);
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QDateEdit *dateEditor = qFindChild<QDateEdit *>(widget.viewport());
+ QVERIFY(dateEditor);
+ QCOMPARE(dateEditor->date(), date);
+
+ widget.clearFocus();
+ widget.setFocus();
+ widget.editItem(item3);
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QList<QDateTimeEdit *> dateTimeEditors = widget.findChildren<QDateTimeEdit *>();
+ QDateTimeEdit *dateTimeEditor = 0;
+ foreach(dateTimeEditor, dateTimeEditors)
+ if (dateTimeEditor->metaObject()->className() == QLatin1String("QDateTimeEdit"))
+ break;
+ QVERIFY(dateTimeEditor);
+ QCOMPARE(dateTimeEditor->date(), date);
+ QCOMPARE(dateTimeEditor->time(), time);
+}
+
+void tst_QItemDelegate::decoration_data()
+{
+ QTest::addColumn<int>("type");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QSize>("expected");
+
+ int pm = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
+
+ QTest::newRow("pixmap 30x30")
+ << (int)QVariant::Pixmap
+ << QSize(30, 30)
+ << QSize(30, 30);
+
+ QTest::newRow("image 30x30")
+ << (int)QVariant::Image
+ << QSize(30, 30)
+ << QSize(30, 30);
+
+//The default engine scales pixmaps down if required, but never up. For WinCE we need bigger IconSize than 30
+ QTest::newRow("icon 30x30")
+ << (int)QVariant::Icon
+ << QSize(60, 60)
+ << QSize(pm, pm);
+
+ QTest::newRow("color 30x30")
+ << (int)QVariant::Color
+ << QSize(30, 30)
+ << QSize(pm, pm);
+
+ // This demands too much memory and potentially hangs. Feel free to uncomment
+ // for your own testing.
+// QTest::newRow("pixmap 30x30 big")
+// << (int)QVariant::Pixmap
+// << QSize(1024, 1024) // Over 1M
+// << QSize(1024, 1024);
+}
+
+void tst_QItemDelegate::decoration()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QFETCH(int, type);
+ QFETCH(QSize, size);
+ QFETCH(QSize, expected);
+
+ QTableWidget table(1, 1);
+ TestItemDelegate delegate;
+ table.setItemDelegate(&delegate);
+ table.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&table);
+#endif
+ QApplication::setActiveWindow(&table);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&table));
+
+ QVariant value;
+ switch ((QVariant::Type)type) {
+ case QVariant::Pixmap: {
+ QPixmap pm(size);
+ pm.fill(Qt::black);
+ value = pm;
+ break;
+ }
+ case QVariant::Image: {
+ QImage img(size, QImage::Format_Mono);
+ qMemSet(img.bits(), 0, img.byteCount());
+ value = img;
+ break;
+ }
+ case QVariant::Icon: {
+ QPixmap pm(size);
+ pm.fill(Qt::black);
+ value = QIcon(pm);
+ break;
+ }
+ case QVariant::Color:
+ value = QColor(Qt::green);
+ break;
+ default:
+ break;
+ }
+
+ QTableWidgetItem *item = new QTableWidgetItem;
+ item->setData(Qt::DecorationRole, value);
+ table.setItem(0, 0, item);
+ item->setSelected(true);
+
+ QApplication::processEvents();
+
+ QTRY_COMPARE(delegate.decorationRect.size(), expected);
+}
+
+void tst_QItemDelegate::editorEvent_data()
+{
+ QTest::addColumn<QRect>("rect");
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("checkState");
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<bool>("inCheck");
+ QTest::addColumn<int>("type");
+ QTest::addColumn<int>("button");
+ QTest::addColumn<bool>("edited");
+ QTest::addColumn<int>("expectedCheckState");
+
+ QTest::newRow("unchecked, checkable, release")
+ << QRect(0, 0, 20, 20)
+ << QString("foo")
+ << (int)(Qt::Unchecked)
+ << (int)(Qt::ItemIsEditable
+ |Qt::ItemIsSelectable
+ |Qt::ItemIsUserCheckable
+ |Qt::ItemIsEnabled
+ |Qt::ItemIsDragEnabled
+ |Qt::ItemIsDropEnabled)
+ << true
+ << (int)(QEvent::MouseButtonRelease)
+ << (int)(Qt::LeftButton)
+ << true
+ << (int)(Qt::Checked);
+
+ QTest::newRow("checked, checkable, release")
+ << QRect(0, 0, 20, 20)
+ << QString("foo")
+ << (int)(Qt::Checked)
+ << (int)(Qt::ItemIsEditable
+ |Qt::ItemIsSelectable
+ |Qt::ItemIsUserCheckable
+ |Qt::ItemIsEnabled
+ |Qt::ItemIsDragEnabled
+ |Qt::ItemIsDropEnabled)
+ << true
+ << (int)(QEvent::MouseButtonRelease)
+ << (int)(Qt::LeftButton)
+ << true
+ << (int)(Qt::Unchecked);
+
+ QTest::newRow("unchecked, checkable, release")
+ << QRect(0, 0, 20, 20)
+ << QString("foo")
+ << (int)(Qt::Unchecked)
+ << (int)(Qt::ItemIsEditable
+ |Qt::ItemIsSelectable
+ |Qt::ItemIsUserCheckable
+ |Qt::ItemIsEnabled
+ |Qt::ItemIsDragEnabled
+ |Qt::ItemIsDropEnabled)
+ << true
+ << (int)(QEvent::MouseButtonRelease)
+ << (int)(Qt::LeftButton)
+ << true
+ << (int)(Qt::Checked);
+
+ QTest::newRow("unchecked, checkable, release, right button")
+ << QRect(0, 0, 20, 20)
+ << QString("foo")
+ << (int)(Qt::Unchecked)
+ << (int)(Qt::ItemIsEditable
+ |Qt::ItemIsSelectable
+ |Qt::ItemIsUserCheckable
+ |Qt::ItemIsEnabled
+ |Qt::ItemIsDragEnabled
+ |Qt::ItemIsDropEnabled)
+ << true
+ << (int)(QEvent::MouseButtonRelease)
+ << (int)(Qt::RightButton)
+ << false
+ << (int)(Qt::Unchecked);
+
+ QTest::newRow("unchecked, checkable, release outside")
+ << QRect(0, 0, 20, 20)
+ << QString("foo")
+ << (int)(Qt::Unchecked)
+ << (int)(Qt::ItemIsEditable
+ |Qt::ItemIsSelectable
+ |Qt::ItemIsUserCheckable
+ |Qt::ItemIsEnabled
+ |Qt::ItemIsDragEnabled
+ |Qt::ItemIsDropEnabled)
+ << false
+ << (int)(QEvent::MouseButtonRelease)
+ << (int)(Qt::LeftButton)
+ << false
+ << (int)(Qt::Unchecked);
+
+ QTest::newRow("unchecked, checkable, dblclick")
+ << QRect(0, 0, 20, 20)
+ << QString("foo")
+ << (int)(Qt::Unchecked)
+ << (int)(Qt::ItemIsEditable
+ |Qt::ItemIsSelectable
+ |Qt::ItemIsUserCheckable
+ |Qt::ItemIsEnabled
+ |Qt::ItemIsDragEnabled
+ |Qt::ItemIsDropEnabled)
+ << true
+ << (int)(QEvent::MouseButtonDblClick)
+ << (int)(Qt::LeftButton)
+ << true
+ << (int)(Qt::Unchecked);
+}
+
+void tst_QItemDelegate::editorEvent()
+{
+ QFETCH(QRect, rect);
+ QFETCH(QString, text);
+ QFETCH(int, checkState);
+ QFETCH(int, flags);
+ QFETCH(bool, inCheck);
+ QFETCH(int, type);
+ QFETCH(int, button);
+ QFETCH(bool, edited);
+ QFETCH(int, expectedCheckState);
+
+ QStandardItemModel model(1, 1);
+ QModelIndex index = model.index(0, 0);
+ QVERIFY(index.isValid());
+
+ QStandardItem *item = model.itemFromIndex(index);
+ item->setText(text);
+ item->setCheckState((Qt::CheckState)checkState);
+ item->setFlags((Qt::ItemFlags)flags);
+
+ QStyleOptionViewItem option;
+ option.rect = rect;
+ option.state |= QStyle::State_Enabled;
+
+ const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
+ QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200);
+
+ QEvent *event = new QMouseEvent((QEvent::Type)type,
+ pos,
+ (Qt::MouseButton)button,
+ (Qt::MouseButton)button,
+ Qt::NoModifier);
+ TestItemDelegate delegate;
+ bool wasEdited = delegate.editorEvent(event, &model, option, index);
+ delete event;
+
+ QApplication::processEvents();
+
+ QCOMPARE(wasEdited, edited);
+ QCOMPARE(index.data(Qt::CheckStateRole).toInt(), expectedCheckState);
+}
+
+enum WidgetType
+{
+ LineEdit,
+ TextEdit,
+ PlainTextEdit
+};
+Q_DECLARE_METATYPE(WidgetType);
+
+void tst_QItemDelegate::enterKey_data()
+{
+ QTest::addColumn<WidgetType>("widget");
+ QTest::addColumn<int>("key");
+ QTest::addColumn<bool>("expectedFocus");
+
+ QTest::newRow("lineedit enter") << LineEdit << int(Qt::Key_Enter) << false;
+ QTest::newRow("textedit enter") << TextEdit << int(Qt::Key_Enter) << true;
+ QTest::newRow("plaintextedit enter") << PlainTextEdit << int(Qt::Key_Enter) << true;
+ QTest::newRow("plaintextedit return") << PlainTextEdit << int(Qt::Key_Return) << true;
+ QTest::newRow("plaintextedit tab") << PlainTextEdit << int(Qt::Key_Tab) << false;
+ QTest::newRow("lineedit tab") << LineEdit << int(Qt::Key_Tab) << false;
+}
+
+void tst_QItemDelegate::enterKey()
+{
+ QFETCH(WidgetType, widget);
+ QFETCH(int, key);
+ QFETCH(bool, expectedFocus);
+
+ QStandardItemModel model;
+ model.appendRow(new QStandardItem());
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ view.setFocus();
+ QTest::qWait(30);
+
+ struct TestDelegate : public QItemDelegate
+ {
+ WidgetType widgetType;
+ virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
+ {
+ QWidget *editor = 0;
+ switch(widgetType) {
+ case LineEdit:
+ editor = new QLineEdit(parent);
+ break;
+ case TextEdit:
+ editor = new QTextEdit(parent);
+ break;
+ case PlainTextEdit:
+ editor = new QPlainTextEdit(parent);
+ break;
+ }
+ editor->setObjectName(QString::fromLatin1("TheEditor"));
+ return editor;
+ }
+ } delegate;
+
+ delegate.widgetType = widget;
+
+ view.setItemDelegate(&delegate);
+ QModelIndex index = model.index(0, 0);
+ view.setCurrentIndex(index); // the editor will only selectAll on the current index
+ view.edit(index);
+ QTest::qWait(30);
+
+ QList<QWidget*> lineEditors = qFindChildren<QWidget *>(view.viewport(), QString::fromLatin1("TheEditor"));
+ QCOMPARE(lineEditors.count(), 1);
+
+ QPointer<QWidget> editor = lineEditors.at(0);
+ QCOMPARE(editor->hasFocus(), true);
+
+ QTest::keyClick(editor, Qt::Key(key));
+ QApplication::processEvents();
+
+ // The line edit has already been destroyed, so avoid that case.
+ if (widget == TextEdit || widget == PlainTextEdit) {
+ QVERIFY(!editor.isNull());
+ QCOMPARE(editor && editor->hasFocus(), expectedFocus);
+ }
+}
+
+void tst_QItemDelegate::task257859_finalizeEdit()
+{
+ QStandardItemModel model;
+ model.appendRow(new QStandardItem());
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ view.setFocus();
+ QTest::qWait(30);
+
+ QModelIndex index = model.index(0, 0);
+ view.edit(index);
+ QTest::qWait(30);
+
+ QList<QLineEdit *> lineEditors = qFindChildren<QLineEdit *>(view.viewport());
+ QCOMPARE(lineEditors.count(), 1);
+
+ QPointer<QWidget> editor = lineEditors.at(0);
+ QCOMPARE(editor->hasFocus(), true);
+
+ QDialog dialog;
+ QTimer::singleShot(500, &dialog, SLOT(close()));
+ dialog.exec();
+ QTRY_VERIFY(!editor);
+}
+
+void tst_QItemDelegate::QTBUG4435_keepSelectionOnCheck()
+{
+ QStandardItemModel model(3, 1);
+ for (int i = 0; i < 3; ++i) {
+ QStandardItem *item = new QStandardItem(QLatin1String("Item ") + QString::number(i));
+ item->setCheckable(true);
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
+ model.setItem(i, item);
+ }
+ QTableView view;
+ view.setModel(&model);
+ view.setItemDelegate(new TestItemDelegate);
+ view.show();
+ view.selectAll();
+ QTest::qWaitForWindowShown(&view);
+ QStyleOptionViewItem option;
+ option.rect = view.visualRect(model.index(0, 0));
+ const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
+ QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center()
+ + QPoint(checkMargin, 0);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pos);
+ QTRY_VERIFY(view.selectionModel()->isColumnSelected(0, QModelIndex()));
+ QCOMPARE(model.item(0)->checkState(), Qt::Checked);
+}
+
+
+// ### _not_ covered:
+
+// editing with a custom editor factory
+
+// painting when editing
+// painting elided text
+// painting wrapped text
+// painting focus
+// painting icon
+// painting color
+// painting check
+// painting selected
+
+// rect for invalid
+// rect for pixmap
+// rect for image
+// rect for icon
+// rect for check
+
+QTEST_MAIN(tst_QItemDelegate)
+#include "tst_qitemdelegate.moc"
diff --git a/tests/auto/widgets/itemviews/qitemeditorfactory/.gitignore b/tests/auto/widgets/itemviews/qitemeditorfactory/.gitignore
new file mode 100644
index 0000000000..33a458e65d
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemeditorfactory/.gitignore
@@ -0,0 +1 @@
+tst_qitemeditorfactory
diff --git a/tests/auto/widgets/itemviews/qitemeditorfactory/qitemeditorfactory.pro b/tests/auto/widgets/itemviews/qitemeditorfactory/qitemeditorfactory.pro
new file mode 100644
index 0000000000..89bc944c51
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemeditorfactory/qitemeditorfactory.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qitemeditorfactory.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp b/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp
new file mode 100644
index 0000000000..53c00dab0e
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+#include <QtTest/QtTest>
+
+class tst_QItemEditorFactory: public QObject
+{
+ Q_OBJECT
+private slots:
+ void createEditor();
+ void createCustomEditor();
+};
+
+void tst_QItemEditorFactory::createEditor()
+{
+ const QItemEditorFactory *factory = QItemEditorFactory::defaultFactory();
+
+ QWidget parent;
+
+ QWidget *w = factory->createEditor(QVariant::String, &parent);
+ QCOMPARE(w->metaObject()->className(), "QExpandingLineEdit");
+}
+
+//we make it inherit from QObject so that we can use QPointer
+class MyEditor : public QObject, public QStandardItemEditorCreator<QDoubleSpinBox>
+{
+};
+
+void tst_QItemEditorFactory::createCustomEditor()
+{
+ QPointer<MyEditor> creator = new MyEditor;
+ QPointer<MyEditor> creator2 = new MyEditor;
+
+ {
+ QItemEditorFactory editorFactory;
+
+ editorFactory.registerEditor(QVariant::Rect, creator);
+ editorFactory.registerEditor(QVariant::RectF, creator);
+
+ //creator should not be deleted as a result of calling the next line
+ editorFactory.registerEditor(QVariant::Rect, creator2);
+ QVERIFY(creator);
+
+ //this should erase creator2
+ editorFactory.registerEditor(QVariant::Rect, creator);
+ QVERIFY(creator2.isNull());
+
+
+ QWidget parent;
+
+ QWidget *w = editorFactory.createEditor(QVariant::Rect, &parent);
+ QCOMPARE(w->metaObject()->className(), "QDoubleSpinBox");
+ QCOMPARE(w->metaObject()->userProperty().type(), QVariant::Double);
+ }
+
+ //editorFactory has been deleted, so should be creator
+ //because editorFActory has the ownership
+ QVERIFY(creator.isNull());
+ QVERIFY(creator2.isNull());
+
+ delete creator;
+}
+
+QTEST_MAIN(tst_QItemEditorFactory)
+#include "tst_qitemeditorfactory.moc"
+
diff --git a/tests/auto/widgets/itemviews/qitemselectionmodel/.gitignore b/tests/auto/widgets/itemviews/qitemselectionmodel/.gitignore
new file mode 100644
index 0000000000..aa543a200a
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemselectionmodel/.gitignore
@@ -0,0 +1 @@
+tst_qitemselectionmodel
diff --git a/tests/auto/widgets/itemviews/qitemselectionmodel/qitemselectionmodel.pro b/tests/auto/widgets/itemviews/qitemselectionmodel/qitemselectionmodel.pro
new file mode 100644
index 0000000000..c675a6eb9d
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemselectionmodel/qitemselectionmodel.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qitemselectionmodel.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/widgets/itemviews/qitemselectionmodel/tst_qitemselectionmodel.cpp
new file mode 100644
index 0000000000..f7ce339854
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemselectionmodel/tst_qitemselectionmodel.cpp
@@ -0,0 +1,2714 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QItemSelectionModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QItemSelectionModel();
+ virtual ~tst_QItemSelectionModel();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+private slots:
+ void clear_data();
+ void clear();
+ void clearAndSelect();
+ void toggleSelection();
+ void select_data();
+ void select();
+ void persistentselections_data();
+ void persistentselections();
+ void resetModel();
+ void removeRows_data();
+ void removeRows();
+ void removeColumns_data();
+ void removeColumns();
+ void modelLayoutChanged_data();
+ void modelLayoutChanged();
+ void selectedRows_data();
+ void selectedRows();
+ void selectedColumns_data();
+ void selectedColumns();
+ void setCurrentIndex();
+ void splitOnInsert();
+ void task196285_rowIntersectsSelection();
+ void unselectable();
+ void task220420_selectedIndexes();
+ void task240734_layoutChanged();
+ void merge_data();
+ void merge();
+ void task119433_isRowSelected();
+ void task252069_rowIntersectsSelection();
+ void task232634_childrenDeselectionSignal();
+ void task260134_layoutChangedWithAllSelected();
+ void QTBUG5671_layoutChangedWithAllSelected();
+ void QTBUG2804_layoutChangedTreeSelection();
+ void deselectRemovedMiddleRange();
+ void rangeOperatorLessThan_data();
+ void rangeOperatorLessThan();
+
+ void testDifferentModels();
+
+ void testValidRangesInSelectionsAfterReset();
+ void testChainedSelectionClear();
+
+private:
+ QAbstractItemModel *model;
+ QItemSelectionModel *selection;
+};
+
+QDataStream &operator<<(QDataStream &, const QModelIndex &);
+QDataStream &operator>>(QDataStream &, QModelIndex &);
+QDataStream &operator<<(QDataStream &, const QModelIndexList &);
+QDataStream &operator>>(QDataStream &, QModelIndexList &);
+
+typedef QList<int> IntList;
+typedef QPair<int, int> IntPair;
+typedef QList<IntPair> PairList;
+
+
+Q_DECLARE_METATYPE(PairList)
+Q_DECLARE_METATYPE(QModelIndex)
+Q_DECLARE_METATYPE(QModelIndexList)
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(QItemSelection)
+
+class QStreamHelper: public QAbstractItemModel
+{
+public:
+ QStreamHelper() {}
+ static QModelIndex create(int row = -1, int column = -1, void *data = 0)
+ {
+ QStreamHelper helper;
+ return helper.QAbstractItemModel::createIndex(row, column, data);
+ }
+
+ QModelIndex index(int, int, const QModelIndex&) const
+ { return QModelIndex(); }
+ QModelIndex parent(const QModelIndex&) const
+ { return QModelIndex(); }
+ int rowCount(const QModelIndex & = QModelIndex()) const
+ { return 0; }
+ int columnCount(const QModelIndex & = QModelIndex()) const
+ { return 0; }
+ QVariant data(const QModelIndex &, int = Qt::DisplayRole) const
+ { return QVariant(); }
+ bool hasChildren(const QModelIndex &) const
+ { return false; }
+};
+
+QDataStream &operator<<(QDataStream &s, const QModelIndex &input)
+{
+ s << input.row()
+ << input.column()
+ << reinterpret_cast<qlonglong>(input.internalPointer());
+ return s;
+}
+
+QDataStream &operator>>(QDataStream &s, QModelIndex &output)
+{
+ int r, c;
+ qlonglong ptr;
+ s >> r;
+ s >> c;
+ s >> ptr;
+ output = QStreamHelper::create(r, c, reinterpret_cast<void *>(ptr));
+ return s;
+}
+
+QDataStream &operator<<(QDataStream &s, const QModelIndexList &input)
+{
+ s << input.count();
+ for (int i=0; i<input.count(); ++i)
+ s << input.at(i);
+ return s;
+}
+
+QDataStream &operator>>(QDataStream &s, QModelIndexList &output)
+{
+ QModelIndex tmpIndex;
+ int count;
+ s >> count;
+ for (int i=0; i<count; ++i) {
+ s >> tmpIndex;
+ output << tmpIndex;
+ }
+ return s;
+}
+
+tst_QItemSelectionModel::tst_QItemSelectionModel() : model(0), selection(0)
+{
+}
+
+tst_QItemSelectionModel::~tst_QItemSelectionModel()
+{
+}
+
+/*
+ This test usually uses a model with a 5x5 table
+ -------------------------------------------
+ | 0,0 | 0,1 | 0,2 | 0,3 | 0,4 |
+ -------------------------------------------
+ | 1,0 | 1,1 | 1,2 | 1,3 | 1,4 |
+ -------------------------------------------
+ | 2,0 | 2,1 | 2,2 | 2,3 | 2,4 |
+ -------------------------------------------
+ | 3,0 | 3,1 | 3,2 | 3,3 | 3,4 |
+ -------------------------------------------
+ | 4,0 | 4,1 | 4,2 | 4,3 | 4,4 |
+ -------------------------------------------
+
+ ...that for each row has a children in a new 5x5 table ad infinitum.
+
+*/
+void tst_QItemSelectionModel::initTestCase()
+{
+ qRegisterMetaType<QItemSelection>("QItemSelection");
+
+ model = new QStandardItemModel(5, 5);
+ QModelIndex parent = model->index(0, 0, QModelIndex());
+ model->insertRows(0, 5, parent);
+ model->insertColumns(0, 5, parent);
+ selection = new QItemSelectionModel(model);
+}
+
+void tst_QItemSelectionModel::cleanupTestCase()
+{
+ delete selection;
+ delete model;
+}
+
+void tst_QItemSelectionModel::init()
+{
+ selection->clear();
+ while (model->rowCount(QModelIndex()) > 5)
+ model->removeRow(0, QModelIndex());
+ while (model->rowCount(QModelIndex()) < 5)
+ model->insertRow(0, QModelIndex());
+}
+
+void tst_QItemSelectionModel::clear_data()
+{
+ QTest::addColumn<QModelIndexList>("indexList");
+ QTest::addColumn<IntList>("commandList");
+ {
+ QModelIndexList index;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ index << model->index(1, 0, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ QTest::newRow("(0, 0) and (1, 0): Select|Rows")
+ << index
+ << command;
+ }
+ {
+ QModelIndexList index;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ index << model->index(0, 1, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ QTest::newRow("(0, 0) and (1, 0): Select|Columns")
+ << index
+ << command;
+ }
+ {
+ QModelIndexList index;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(1, 1, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::SelectCurrent;
+ QTest::newRow("(0, 0), (1, 1) and (2, 2): Select, Select, SelectCurrent")
+ << index
+ << command;
+ }
+ {
+ QModelIndexList index;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(1, 1, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(1, 1, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+ QTest::newRow("(0, 0), (1, 1) and (1, 1): Select, Select, Toggle")
+ << index
+ << command;
+ }
+ {
+ QModelIndexList index;
+ IntList command;
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ QTest::newRow("child (0, 0) of (0, 0): Select|Rows")
+ << index
+ << command;
+ }
+}
+
+void tst_QItemSelectionModel::clear()
+{
+ QFETCH(QModelIndexList, indexList);
+ QFETCH(IntList, commandList);
+
+ // do selections
+ for (int i=0; i<indexList.count(); ++i) {
+ selection->select(indexList.at(i), (QItemSelectionModel::SelectionFlags)commandList.at(i));
+ }
+ // test that we have selected items
+ QVERIFY(!selection->selectedIndexes().isEmpty());
+ selection->clear();
+ // test that they were all cleared
+ QVERIFY(selection->selectedIndexes().isEmpty());
+}
+
+void tst_QItemSelectionModel::clearAndSelect()
+{
+ // populate selectionmodel
+ selection->select(model->index(1, 1, QModelIndex()), QItemSelectionModel::Select);
+ QCOMPARE(selection->selectedIndexes().count(), 1);
+ QVERIFY(selection->hasSelection());
+
+ // ClearAndSelect with empty selection
+ QItemSelection emptySelection;
+ selection->select(emptySelection, QItemSelectionModel::ClearAndSelect);
+
+ // verify the selectionmodel is empty
+ QVERIFY(selection->selectedIndexes().isEmpty());
+ QVERIFY(selection->hasSelection()==false);
+}
+
+void tst_QItemSelectionModel::toggleSelection()
+{
+ //test the toggle selection and checks whether selectedIndex
+ //and hasSelection returns the correct value
+
+ selection->clearSelection();
+ QCOMPARE(selection->selectedIndexes().count(), 0);
+ QVERIFY(selection->hasSelection()==false);
+
+ QModelIndex index=model->index(1, 1, QModelIndex());
+ // populate selectionmodel
+ selection->select(index, QItemSelectionModel::Toggle);
+ QCOMPARE(selection->selectedIndexes().count(), 1);
+ QVERIFY(selection->hasSelection()==true);
+
+ selection->select(index, QItemSelectionModel::Toggle);
+ QCOMPARE(selection->selectedIndexes().count(), 0);
+ QVERIFY(selection->hasSelection()==false);
+
+ // populate selectionmodel with rows
+ selection->select(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
+ QCOMPARE(selection->selectedIndexes().count(), model->columnCount());
+ QVERIFY(selection->hasSelection()==true);
+
+ selection->select(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
+ QCOMPARE(selection->selectedIndexes().count(), 0);
+ QVERIFY(selection->hasSelection()==false);
+
+}
+
+
+void tst_QItemSelectionModel::select_data()
+{
+ QTest::addColumn<QModelIndexList>("indexList");
+ QTest::addColumn<bool>("useRanges");
+ QTest::addColumn<IntList>("commandList");
+ QTest::addColumn<QModelIndexList>("expectedList");
+
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ expected << model->index(0, 0, QModelIndex());
+ QTest::newRow("(0, 0): Select")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ command << QItemSelectionModel::Select;
+ expected << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ QTest::newRow("child (0, 0) of (0, 0): Select")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Deselect;
+ QTest::newRow("(0, 0): Deselect")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+ expected << model->index(0, 0, QModelIndex());
+ QTest::newRow("(0, 0): Toggle")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+ QTest::newRow("(0, 0) and (0, 0): Select and Toggle")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Deselect;
+ QTest::newRow("(0, 0) and (0, 0): Select and Deselect")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ command << QItemSelectionModel::ClearAndSelect;
+ expected << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ QTest::newRow("(0, 0) and child (0, 0) of (0, 0): Select and ClearAndSelect")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(0, 1, QModelIndex());
+ index << model->index(4, 1, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 1, QModelIndex());
+ command << QItemSelectionModel::Deselect;
+ QTest::newRow("(0, 0 to 4, 0) and (0, 1 to 4, 1) and (0, 0 to 4, 1): Select and Select and Deselect")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(4, 4, QModelIndex());
+ command << QItemSelectionModel::Select;
+ expected << model->index(0, 0, QModelIndex()) << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0) and (4, 4): Select")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(4, 4, QModelIndex());
+ command << QItemSelectionModel::ClearAndSelect;
+ expected << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0) and (4, 4): Select and ClearAndSelect")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ index << model->index(4, 4, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(4, 1, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(4, 3, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0) and (4, 4): Select|Rows")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ index << model->index(4, 4, model->index(0, 0, QModelIndex()));
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ QModelIndex parent = model->index(0, 0, QModelIndex());
+ expected << model->index(0, 0, parent)
+ << model->index(0, 1, parent)
+ << model->index(0, 2, parent)
+ << model->index(0, 3, parent)
+ << model->index(0, 4, parent)
+ << model->index(4, 0, parent)
+ << model->index(4, 1, parent)
+ << model->index(4, 2, parent)
+ << model->index(4, 3, parent)
+ << model->index(4, 4, parent);
+ QTest::newRow("child (0, 0) and (4, 4) of (0, 0): Select|Rows")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ index << model->index(4, 4, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ << model->index(3, 4, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0) and (4, 4): Select|Columns")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ index << model->index(4, 4, model->index(0, 0, QModelIndex()));
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ expected << model->index(0, 0, model->index(0, 0, QModelIndex()))
+ << model->index(1, 0, model->index(0, 0, QModelIndex()))
+ << model->index(2, 0, model->index(0, 0, QModelIndex()))
+ << model->index(3, 0, model->index(0, 0, QModelIndex()))
+ << model->index(4, 0, model->index(0, 0, QModelIndex()))
+ << model->index(0, 4, model->index(0, 0, QModelIndex()))
+ << model->index(1, 4, model->index(0, 0, QModelIndex()))
+ << model->index(2, 4, model->index(0, 0, QModelIndex()))
+ << model->index(3, 4, model->index(0, 0, QModelIndex()))
+ << model->index(4, 4, model->index(0, 0, QModelIndex()));
+ QTest::newRow("child (0, 0) and (4, 4) of (0, 0): Select|Columns")
+ << index
+ << false
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 0, QModelIndex());
+ command << QItemSelectionModel::Select;
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(4, 0, QModelIndex());
+ QTest::newRow("(0, 0 to 4, 0): Select")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ /* ### FAILS
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ command << QItemSelectionModel::Select;
+ QTest::newRow("(0, 0 to child 0, 0): Select")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ */
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, model->index(0, 0, QModelIndex()));
+ index << model->index(0, 0, model->index(1, 0, QModelIndex()));
+ command << QItemSelectionModel::Select;
+ QTest::newRow("child (0, 0) of (0, 0) to child (0, 0) of (1, 0): Select")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 4, QModelIndex());
+ command << QItemSelectionModel::Select;
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(1, 3, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(3, 1, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(3, 3, QModelIndex())
+ << model->index(3, 4, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(4, 1, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(4, 3, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0 to 4, 4): Select")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 0, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(1, 3, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(3, 1, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(3, 3, QModelIndex())
+ << model->index(3, 4, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(4, 1, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(4, 3, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0 to 4, 0): Select|Rows")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(0, 4, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(1, 3, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(3, 1, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(3, 3, QModelIndex())
+ << model->index(3, 4, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(4, 1, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(4, 3, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0 to 0, 4): Select|Columns")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 4, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(1, 3, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(3, 1, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(3, 3, QModelIndex())
+ << model->index(3, 4, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(4, 1, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(4, 3, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0 to 4, 4): Select|Rows")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(4, 4, QModelIndex());
+ command << (QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(1, 3, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ << model->index(3, 0, QModelIndex())
+ << model->index(3, 1, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(3, 3, QModelIndex())
+ << model->index(3, 4, QModelIndex())
+ << model->index(4, 0, QModelIndex())
+ << model->index(4, 1, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(4, 3, QModelIndex())
+ << model->index(4, 4, QModelIndex());
+ QTest::newRow("(0, 0 to 4, 4): Select|Columns")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 2, QModelIndex());
+ index << model->index(4, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(2, 0, QModelIndex());
+ index << model->index(2, 4, QModelIndex());
+ command << QItemSelectionModel::Select;
+ expected << model->index(0, 2, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex());
+ QTest::newRow("(0, 2 to 4, 2) and (2, 0 to 2, 4): Select")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 2, QModelIndex());
+ index << model->index(4, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(2, 0, QModelIndex());
+ index << model->index(2, 4, QModelIndex());
+ command << QItemSelectionModel::SelectCurrent;
+ expected << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex());
+ QTest::newRow("(0, 2 to 4, 2) and (2, 0 to 2, 4): Select and SelectCurrent")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 2, QModelIndex());
+ index << model->index(4, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(2, 0, QModelIndex());
+ index << model->index(2, 4, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+ expected << model->index(0, 2, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(4, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex());
+ QTest::newRow("(0, 2 to 4, 2) and (2, 0 to 2, 4): Select and Toggle")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 2, QModelIndex());
+ index << model->index(4, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+ index << model->index(2, 0, QModelIndex());
+ index << model->index(2, 4, QModelIndex());
+ command << QItemSelectionModel::Deselect;
+ expected << model->index(0, 2, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(4, 2, QModelIndex());
+ QTest::newRow("(0, 2 to 4, 2) and (2, 0 to 2, 4): Select and Deselect")
+ << index
+ << true
+ << command
+ << expected;
+ }
+
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(0, 0, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (0, 0 to 0, 0): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(0, 1, QModelIndex());
+ index << model->index(0, 1, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (0, 1 to 0, 1): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(0, 2, QModelIndex());
+ index << model->index(0, 2, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (0, 2 to 0, 2): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(1, 0, QModelIndex());
+ index << model->index(1, 0, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (1, 0 to 1, 0): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(1, 1, QModelIndex());
+ index << model->index(1, 1, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (1, 1 to 1, 1): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(1, 2, QModelIndex());
+ index << model->index(1, 2, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (1, 2 to 1, 2): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(2, 0, QModelIndex());
+ index << model->index(2, 0, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (2, 0 to 2, 0): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(2, 1, QModelIndex());
+ index << model->index(2, 1, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 2, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (2, 1 to 2, 1): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList index;
+ QModelIndexList expected;
+ IntList command;
+
+ index << model->index(0, 0, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Select;
+
+ index << model->index(2, 2, QModelIndex());
+ index << model->index(2, 2, QModelIndex());
+ command << QItemSelectionModel::Toggle;
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex());
+
+ QTest::newRow("(0, 0 to 2, 2) and (2, 2 to 2, 2): Select and Toggle at selection boundary")
+ << index
+ << true
+ << command
+ << expected;
+ }
+ {
+ QModelIndexList indexes;
+ IntList commands;
+ QModelIndexList expected;
+
+ indexes << model->index(0, 0, QModelIndex()) << model->index(0, 0, QModelIndex()) // press 0
+ << model->index(0, 0, QModelIndex()) << model->index(0, 0, QModelIndex()) // release 0
+ << model->index(1, 0, QModelIndex()) << model->index(1, 0, QModelIndex()) // press 1
+ << model->index(1, 0, QModelIndex()) << model->index(1, 0, QModelIndex()) // release 1
+ << model->index(2, 0, QModelIndex()) << model->index(2, 0, QModelIndex()) // press 2
+ << model->index(2, 0, QModelIndex()) << model->index(2, 0, QModelIndex()) // release 2
+ << model->index(3, 0, QModelIndex()) << model->index(3, 0, QModelIndex()) // press 3
+ << model->index(3, 0, QModelIndex()) << model->index(3, 0, QModelIndex()) // release 3
+ << model->index(2, 0, QModelIndex()) << model->index(2, 0, QModelIndex()) // press 2 again
+ << model->index(2, 0, QModelIndex()) << model->index(2, 0, QModelIndex());// move 2
+
+ commands << (QItemSelectionModel::NoUpdate) // press 0
+ << (QItemSelectionModel::Toggle|QItemSelectionModel::Rows) // release 0
+ << (QItemSelectionModel::NoUpdate) // press 1
+ << (QItemSelectionModel::Toggle|QItemSelectionModel::Rows) // release 1
+ << (QItemSelectionModel::NoUpdate) // press 2
+ << (QItemSelectionModel::Toggle|QItemSelectionModel::Rows) // release 2
+ << (QItemSelectionModel::NoUpdate) // press 3
+ << (QItemSelectionModel::Toggle|QItemSelectionModel::Rows) // release 3
+ << (QItemSelectionModel::NoUpdate) // press 2 again
+ << (QItemSelectionModel::Toggle/*Current*/|QItemSelectionModel::Rows);// move 2
+
+ expected << model->index(0, 0, QModelIndex())
+ << model->index(0, 1, QModelIndex())
+ << model->index(0, 2, QModelIndex())
+ << model->index(0, 3, QModelIndex())
+ << model->index(0, 4, QModelIndex())
+
+ << model->index(1, 0, QModelIndex())
+ << model->index(1, 1, QModelIndex())
+ << model->index(1, 2, QModelIndex())
+ << model->index(1, 3, QModelIndex())
+ << model->index(1, 4, QModelIndex())
+ /*
+ << model->index(2, 0, QModelIndex())
+ << model->index(2, 1, QModelIndex())
+ << model->index(2, 2, QModelIndex())
+ << model->index(2, 3, QModelIndex())
+ << model->index(2, 4, QModelIndex())
+ */
+ << model->index(3, 0, QModelIndex())
+ << model->index(3, 1, QModelIndex())
+ << model->index(3, 2, QModelIndex())
+ << model->index(3, 3, QModelIndex())
+ << model->index(3, 4, QModelIndex());
+
+ QTest::newRow("simulated treeview multiselection behavior")
+ << indexes
+ << true
+ << commands
+ << expected;
+ }
+}
+
+void tst_QItemSelectionModel::select()
+{
+ QFETCH(QModelIndexList, indexList);
+ QFETCH(bool, useRanges);
+ QFETCH(IntList, commandList);
+ QFETCH(QModelIndexList, expectedList);
+
+ int lastCommand = 0;
+ // do selections
+ for (int i = 0; i<commandList.count(); ++i) {
+ if (useRanges) {
+ selection->select(QItemSelection(indexList.at(2*i), indexList.at(2*i+1)),
+ (QItemSelectionModel::SelectionFlags)commandList.at(i));
+ } else {
+ selection->select(indexList.at(i),
+ (QItemSelectionModel::SelectionFlags)commandList.at(i));
+ }
+ lastCommand = commandList.at(i);
+ }
+
+
+ QModelIndexList selectedList = selection->selectedIndexes();
+
+ QVERIFY(selection->hasSelection()!=selectedList.isEmpty());
+
+ // debug output
+// for (int i=0; i<selectedList.count(); ++i)
+// qDebug(QString("selected (%1, %2)")
+// .arg(selectedList.at(i).row())
+// .arg(selectedList.at(i).column()));
+
+ // test that the number of indices are as expected
+ QVERIFY2(selectedList.count() == expectedList.count(),
+ QString("expected indices: %1 actual indices: %2")
+ .arg(expectedList.count())
+ .arg(selectedList.count()).toLatin1());
+
+ // test existence of each index
+ for (int i=0; i<expectedList.count(); ++i) {
+ QVERIFY2(selectedList.contains(expectedList.at(i)),
+ QString("expected index(%1, %2) not found in selectedIndexes()")
+ .arg(expectedList.at(i).row())
+ .arg(expectedList.at(i).column()).toLatin1());
+ }
+
+ // test that isSelected agrees
+ for (int i=0; i<indexList.count(); ++i) {
+ QModelIndex idx = indexList.at(i);
+ QVERIFY2(selection->isSelected(idx) == selectedList.contains(idx),
+ QString("isSelected(index: %1, %2) does not match selectedIndexes()")
+ .arg(idx.row())
+ .arg(idx.column()).toLatin1());
+ }
+
+ //for now we assume Rows/Columns flag is the same for all commands, therefore we just check lastCommand
+ // test that isRowSelected agrees
+ if (lastCommand & QItemSelectionModel::Rows) {
+ for (int i=0; i<selectedList.count(); ++i)
+ QVERIFY2(selection->isRowSelected(selectedList.at(i).row(),
+ model->parent(selectedList.at(i))),
+ QString("isRowSelected(row: %1) does not match selectedIndexes()")
+ .arg(selectedList.at(i).row()).toLatin1());
+ }
+
+ // test that isColumnSelected agrees
+ if (lastCommand & QItemSelectionModel::Columns) {
+ for (int i=0; i<selectedList.count(); ++i)
+ QVERIFY2(selection->isColumnSelected(selectedList.at(i).column(),
+ model->parent(selectedList.at(i))),
+ QString("isColumnSelected(column: %1) does not match selectedIndexes()")
+ .arg(selectedList.at(i).column()).toLatin1());
+ }
+}
+
+void tst_QItemSelectionModel::persistentselections_data()
+{
+ QTest::addColumn<PairList>("indexList");
+ QTest::addColumn<IntList>("commandList");
+ QTest::addColumn<IntList>("insertRows"); // start, count
+ QTest::addColumn<IntList>("insertColumns"); // start, count
+ QTest::addColumn<IntList>("deleteRows"); // start, count
+ QTest::addColumn<IntList>("deleteColumns"); // start, count
+ QTest::addColumn<PairList>("expectedList");
+
+ PairList index, expected;
+ IntList command, insertRows, insertColumns, deleteRows, deleteColumns;
+
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ deleteRows << 4 << 1;
+ expected << IntPair(0, 0);
+ QTest::newRow("ClearAndSelect (0, 0). Delete last row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ deleteRows << 0 << 1;
+ QTest::newRow("ClearAndSelect (0, 0). Delete first row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(1, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ deleteRows << 0 << 1;
+ expected << IntPair(0, 0);
+ QTest::newRow("ClearAndSelect (1, 0). Delete first row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ insertRows << 5 << 1;
+ expected << IntPair(0, 0);
+ QTest::newRow("ClearAndSelect (0, 0). Append row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ insertRows << 0 << 1;
+ expected << IntPair(1, 0);
+ QTest::newRow("ClearAndSelect (0, 0). Insert before first row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0)
+ << IntPair(4, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ insertRows << 5 << 1;
+ expected << IntPair(0, 0)
+ << IntPair(1, 0)
+ << IntPair(2, 0)
+ << IntPair(3, 0)
+ << IntPair(4, 0);
+ QTest::newRow("ClearAndSelect (0, 0) to (4, 0). Append row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0)
+ << IntPair(4, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ insertRows << 0 << 1;
+ expected << IntPair(1, 0)
+ << IntPair(2, 0)
+ << IntPair(3, 0)
+ << IntPair(4, 0)
+ << IntPair(5, 0);
+ QTest::newRow("ClearAndSelect (0, 0) to (4, 0). Insert before first row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0)
+ << IntPair(4, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ deleteRows << 0 << 1;
+ expected << IntPair(0, 0)
+ << IntPair(1, 0)
+ << IntPair(2, 0)
+ << IntPair(3, 0);
+ QTest::newRow("ClearAndSelect (0, 0) to (4, 0). Delete first row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0)
+ << IntPair(4, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ deleteRows << 4 << 1;
+ expected << IntPair(0, 0)
+ << IntPair(1, 0)
+ << IntPair(2, 0)
+ << IntPair(3, 0);
+ QTest::newRow("ClearAndSelect (0, 0) to (4, 0). Delete last row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0)
+ << IntPair(4, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ deleteRows << 1 << 3;
+ expected << IntPair(0, 0)
+ << IntPair(1, 0);
+ QTest::newRow("ClearAndSelect (0, 0) to (4, 0). Deleting all but first and last row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+
+ index.clear(); expected.clear(); command.clear();
+ insertRows.clear(); insertColumns.clear(); deleteRows.clear(); deleteColumns.clear();
+ index << IntPair(0, 0)
+ << IntPair(4, 0);
+ command << QItemSelectionModel::ClearAndSelect;
+ insertRows << 1 << 1;
+ expected << IntPair(0, 0)
+ // the inserted row should not be selected
+ << IntPair(2, 0)
+ << IntPair(3, 0)
+ << IntPair(4, 0)
+ << IntPair(5, 0);
+ QTest::newRow("ClearAndSelect (0, 0) to (4, 0). Insert after first row.")
+ << index << command
+ << insertRows << insertColumns << deleteRows << deleteColumns
+ << expected;
+}
+
+void tst_QItemSelectionModel::persistentselections()
+{
+ QFETCH(PairList, indexList);
+ QFETCH(IntList, commandList);
+ QFETCH(IntList, insertRows);
+ QFETCH(IntList, insertColumns);
+ QFETCH(IntList, deleteRows);
+ QFETCH(IntList, deleteColumns);
+ QFETCH(PairList, expectedList);
+
+ // make sure the model is sane (5x5)
+ QCOMPARE(model->rowCount(QModelIndex()), 5);
+ QCOMPARE(model->columnCount(QModelIndex()), 5);
+
+ // do selections
+ for (int i=0; i<commandList.count(); ++i) {
+ if (indexList.count() == commandList.count()) {
+ QModelIndex index = model->index(indexList.at(i).first,
+ indexList.at(i).second,
+ QModelIndex());
+ selection->select(index, (QItemSelectionModel::SelectionFlags)commandList.at(i));
+ } else {
+ QModelIndex tl = model->index(indexList.at(2*i).first,
+ indexList.at(2*i).second,
+ QModelIndex());
+ QModelIndex br = model->index(indexList.at(2*i+1).first,
+ indexList.at(2*i+1).second,
+ QModelIndex());
+ selection->select(QItemSelection(tl, br),
+ (QItemSelectionModel::SelectionFlags)commandList.at(i));
+ }
+ }
+ // test that we have selected items
+ QVERIFY(!selection->selectedIndexes().isEmpty());
+ QVERIFY(selection->hasSelection());
+
+ // insert/delete row and/or columns
+ if (insertRows.count() > 1)
+ model->insertRows(insertRows.at(0), insertRows.at(1), QModelIndex());
+ if (insertColumns.count() > 1)
+ model->insertColumns(insertColumns.at(0), insertColumns.at(1), QModelIndex());
+ if (deleteRows.count() > 1)
+ model->removeRows(deleteRows.at(0), deleteRows.at(1), QModelIndex());
+ if (deleteColumns.count() > 1)
+ model->removeColumns(deleteColumns.at(0), deleteColumns.at(1), QModelIndex());
+
+ // check that the selected items are the correct number and indexes
+ QModelIndexList selectedList = selection->selectedIndexes();
+ QCOMPARE(selectedList.count(), expectedList.count());
+ foreach(IntPair pair, expectedList) {
+ QModelIndex index = model->index(pair.first, pair.second, QModelIndex());
+ QVERIFY(selectedList.contains(index));
+ }
+}
+
+// "make reset public"-model
+class MyStandardItemModel: public QStandardItemModel
+{
+ Q_OBJECT
+public:
+ inline MyStandardItemModel(int i1, int i2): QStandardItemModel(i1, i2) {}
+ inline void reset() { QStandardItemModel::reset(); }
+};
+
+void tst_QItemSelectionModel::resetModel()
+{
+ MyStandardItemModel model(20, 20);
+ QTreeView view;
+ view.setModel(&model);
+
+ QSignalSpy spy(view.selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)));
+
+ view.selectionModel()->select(QItemSelection(model.index(0, 0), model.index(5, 5)), QItemSelectionModel::Select);
+
+ QCOMPARE(spy.count(), 1);
+
+ model.reset();
+
+ QVERIFY(view.selectionModel()->selection().isEmpty());
+ QVERIFY(view.selectionModel()->hasSelection() == false);
+
+ view.selectionModel()->select(QItemSelection(model.index(0, 0), model.index(5, 5)), QItemSelectionModel::Select);
+
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.at(1).count(), 2);
+ // make sure we don't get an "old selection"
+ QCOMPARE(spy.at(1).at(1).userType(), qMetaTypeId<QItemSelection>());
+ QVERIFY(qvariant_cast<QItemSelection>(spy.at(1).at(1)).isEmpty());
+}
+
+void tst_QItemSelectionModel::removeRows_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+
+ QTest::addColumn<int>("selectTop");
+ QTest::addColumn<int>("selectLeft");
+ QTest::addColumn<int>("selectBottom");
+ QTest::addColumn<int>("selectRight");
+
+ QTest::addColumn<int>("removeTop");
+ QTest::addColumn<int>("removeBottom");
+
+ QTest::addColumn<int>("expectedTop");
+ QTest::addColumn<int>("expectedLeft");
+ QTest::addColumn<int>("expectedBottom");
+ QTest::addColumn<int>("expectedRight");
+
+ QTest::newRow("4x4 <0,1><1,1>")
+ << 4 << 4
+ << 0 << 1 << 1 << 1
+ << 0 << 0
+ << 0 << 1 << 0 << 1;
+}
+
+void tst_QItemSelectionModel::removeRows()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, selectTop);
+ QFETCH(int, selectLeft);
+ QFETCH(int, selectBottom);
+ QFETCH(int, selectRight);
+ QFETCH(int, removeTop);
+ QFETCH(int, removeBottom);
+ QFETCH(int, expectedTop);
+ QFETCH(int, expectedLeft);
+ QFETCH(int, expectedBottom);
+ QFETCH(int, expectedRight);
+
+ MyStandardItemModel model(rowCount, columnCount);
+ QItemSelectionModel selections(&model);
+ QSignalSpy spy(&selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)));
+
+ QModelIndex tl = model.index(selectTop, selectLeft);
+ QModelIndex br = model.index(selectBottom, selectRight);
+ selections.select(QItemSelection(tl, br), QItemSelectionModel::ClearAndSelect);
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(selections.isSelected(tl));
+ QVERIFY(selections.isSelected(br));
+ QVERIFY(selections.hasSelection());
+
+ model.removeRows(removeTop, removeBottom - removeTop + 1);
+
+ QCOMPARE(spy.count(), 2);
+ tl = model.index(expectedTop, expectedLeft);
+ br = model.index(expectedBottom, expectedRight);
+ QVERIFY(selections.isSelected(tl));
+ QVERIFY(selections.isSelected(br));
+}
+
+void tst_QItemSelectionModel::removeColumns_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+
+ QTest::addColumn<int>("selectTop");
+ QTest::addColumn<int>("selectLeft");
+ QTest::addColumn<int>("selectBottom");
+ QTest::addColumn<int>("selectRight");
+
+ QTest::addColumn<int>("removeLeft");
+ QTest::addColumn<int>("removeRight");
+
+ QTest::addColumn<int>("expectedTop");
+ QTest::addColumn<int>("expectedLeft");
+ QTest::addColumn<int>("expectedBottom");
+ QTest::addColumn<int>("expectedRight");
+
+ QTest::newRow("4x4 <0,1><1,1>")
+ << 4 << 4
+ << 1 << 0 << 1 << 1
+ << 0 << 0
+ << 1 << 0 << 1 << 0;
+}
+
+void tst_QItemSelectionModel::removeColumns()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, selectTop);
+ QFETCH(int, selectLeft);
+ QFETCH(int, selectBottom);
+ QFETCH(int, selectRight);
+ QFETCH(int, removeLeft);
+ QFETCH(int, removeRight);
+ QFETCH(int, expectedTop);
+ QFETCH(int, expectedLeft);
+ QFETCH(int, expectedBottom);
+ QFETCH(int, expectedRight);
+
+ MyStandardItemModel model(rowCount, columnCount);
+ QItemSelectionModel selections(&model);
+ QSignalSpy spy(&selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)));
+
+ QModelIndex tl = model.index(selectTop, selectLeft);
+ QModelIndex br = model.index(selectBottom, selectRight);
+ selections.select(QItemSelection(tl, br), QItemSelectionModel::ClearAndSelect);
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(selections.isSelected(tl));
+ QVERIFY(selections.isSelected(br));
+ QVERIFY(selections.hasSelection());
+
+ model.removeColumns(removeLeft, removeRight - removeLeft + 1);
+
+ QCOMPARE(spy.count(), 2);
+ tl = model.index(expectedTop, expectedLeft);
+ br = model.index(expectedBottom, expectedRight);
+ QVERIFY(selections.isSelected(tl));
+ QVERIFY(selections.isSelected(br));
+}
+
+typedef QList<IntList> IntListList;
+typedef QPair<IntPair, IntPair> IntPairPair;
+typedef QList<IntPairPair> IntPairPairList;
+Q_DECLARE_METATYPE(IntListList)
+Q_DECLARE_METATYPE(IntPairPair)
+Q_DECLARE_METATYPE(IntPairPairList)
+
+void tst_QItemSelectionModel::modelLayoutChanged_data()
+{
+ QTest::addColumn<IntListList>("items");
+ QTest::addColumn<IntPairPairList>("initialSelectedRanges");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<int>("sortColumn");
+ QTest::addColumn<IntPairPairList>("expectedSelectedRanges");
+
+ QTest::newRow("everything selected, then row order reversed")
+ << (IntListList()
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 3 << 2 << 1 << 0))
+ << (IntPairPairList()
+ << IntPairPair(IntPair(0, 0), IntPair(3, 1)))
+ << int(Qt::DescendingOrder)
+ << 0
+ << (IntPairPairList()
+ << IntPairPair(IntPair(0, 0), IntPair(3, 1)));
+ QTest::newRow("first two rows selected, then row order reversed")
+ << (IntListList()
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 3 << 2 << 1 << 0))
+ << (IntPairPairList()
+ << IntPairPair(IntPair(0, 0), IntPair(1, 1)))
+ << int(Qt::DescendingOrder)
+ << 0
+ << (IntPairPairList()
+ << IntPairPair(IntPair(2, 0), IntPair(3, 1)));
+ QTest::newRow("middle two rows selected, then row order reversed")
+ << (IntListList()
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 3 << 2 << 1 << 0))
+ << (IntPairPairList()
+ << IntPairPair(IntPair(1, 0), IntPair(2, 1)))
+ << int(Qt::DescendingOrder)
+ << 0
+ << (IntPairPairList()
+ << IntPairPair(IntPair(1, 0), IntPair(2, 1)));
+ QTest::newRow("two ranges")
+ << (IntListList()
+ << (IntList() << 2 << 0 << 3 << 1)
+ << (IntList() << 2 << 0 << 3 << 1))
+ << (IntPairPairList()
+ << IntPairPair(IntPair(1, 0), IntPair(1, 1))
+ << IntPairPair(IntPair(3, 0), IntPair(3, 1)))
+ << int(Qt::AscendingOrder)
+ << 0
+ << (IntPairPairList()
+ << IntPairPair(IntPair(0, 0), IntPair(0, 1))
+ << IntPairPair(IntPair(1, 0), IntPair(1, 1)));
+}
+
+void tst_QItemSelectionModel::modelLayoutChanged()
+{
+ QFETCH(IntListList, items);
+ QFETCH(IntPairPairList, initialSelectedRanges);
+ QFETCH(int, sortOrder);
+ QFETCH(int, sortColumn);
+ QFETCH(IntPairPairList, expectedSelectedRanges);
+
+ MyStandardItemModel model(items.at(0).count(), items.count());
+ // initialize model data
+ for (int i = 0; i < model.rowCount(); ++i) {
+ for (int j = 0; j < model.columnCount(); ++j) {
+ QModelIndex index = model.index(i, j);
+ model.setData(index, items.at(j).at(i), Qt::DisplayRole);
+ }
+ }
+
+ // select initial ranges
+ QItemSelectionModel selectionModel(&model);
+ foreach (IntPairPair range, initialSelectedRanges) {
+ IntPair tl = range.first;
+ IntPair br = range.second;
+ QItemSelection selection(
+ model.index(tl.first, tl.second),
+ model.index(br.first, br.second));
+ selectionModel.select(selection, QItemSelectionModel::Select);
+ }
+
+ // sort the model
+ model.sort(sortColumn, Qt::SortOrder(sortOrder));
+
+ // verify that selection is as expected
+ QItemSelection selection = selectionModel.selection();
+ QCOMPARE(selection.count(), expectedSelectedRanges.count());
+ QVERIFY(selectionModel.hasSelection() == !expectedSelectedRanges.isEmpty());
+
+ for (int i = 0; i < expectedSelectedRanges.count(); ++i) {
+ IntPairPair expectedRange = expectedSelectedRanges.at(i);
+ IntPair expectedTl = expectedRange.first;
+ IntPair expectedBr = expectedRange.second;
+ QItemSelectionRange actualRange = selection.at(i);
+ QModelIndex actualTl = actualRange.topLeft();
+ QModelIndex actualBr = actualRange.bottomRight();
+ QCOMPARE(actualTl.row(), expectedTl.first);
+ QCOMPARE(actualTl.column(), expectedTl.second);
+ QCOMPARE(actualBr.row(), expectedBr.first);
+ QCOMPARE(actualBr.column(), expectedBr.second);
+ }
+}
+
+void tst_QItemSelectionModel::selectedRows_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<IntList>("selectRows");
+ QTest::addColumn<IntList>("expectedRows");
+ QTest::addColumn<IntList>("unexpectedRows");
+
+ QTest::newRow("10x10, first row")
+ << 10 << 10 << 0
+ << (IntList() << 0)
+ << (IntList() << 0)
+ << (IntList() << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9);
+
+ QTest::newRow("10x10, first 4 rows")
+ << 10 << 10 << 0
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 4 << 5 << 6 << 7 << 8 << 9);
+
+ QTest::newRow("10x10, last 4 rows")
+ << 10 << 10 << 0
+ << (IntList() << 6 << 7 << 8 << 9)
+ << (IntList() << 6 << 7 << 8 << 9)
+ << (IntList() << 0 << 1 << 2 << 3 << 4 << 6);
+}
+
+void tst_QItemSelectionModel::selectedRows()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, column);
+ QFETCH(IntList, selectRows);
+ QFETCH(IntList, expectedRows);
+ QFETCH(IntList, unexpectedRows);
+
+ MyStandardItemModel model(rowCount, columnCount);
+ QItemSelectionModel selectionModel(&model);
+
+ for (int i = 0; i < selectRows.count(); ++i)
+ selectionModel.select(model.index(selectRows.at(i), 0),
+ QItemSelectionModel::Select
+ |QItemSelectionModel::Rows);
+
+ for (int j = 0; j < selectRows.count(); ++j)
+ QVERIFY(selectionModel.isRowSelected(expectedRows.at(j), QModelIndex()));
+
+ for (int k = 0; k < selectRows.count(); ++k)
+ QVERIFY(!selectionModel.isRowSelected(unexpectedRows.at(k), QModelIndex()));
+
+ QModelIndexList selectedRowIndexes = selectionModel.selectedRows(column);
+ QCOMPARE(selectedRowIndexes.count(), expectedRows.count());
+ qSort(selectedRowIndexes);
+ for (int l = 0; l < selectedRowIndexes.count(); ++l) {
+ QCOMPARE(selectedRowIndexes.at(l).row(), expectedRows.at(l));
+ QCOMPARE(selectedRowIndexes.at(l).column(), column);
+ }
+}
+
+void tst_QItemSelectionModel::selectedColumns_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<IntList>("selectColumns");
+ QTest::addColumn<IntList>("expectedColumns");
+ QTest::addColumn<IntList>("unexpectedColumns");
+
+ QTest::newRow("10x10, first columns")
+ << 10 << 10 << 0
+ << (IntList() << 0)
+ << (IntList() << 0)
+ << (IntList() << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9);
+
+ QTest::newRow("10x10, first 4 columns")
+ << 10 << 10 << 0
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 0 << 1 << 2 << 3)
+ << (IntList() << 4 << 5 << 6 << 7 << 8 << 9);
+
+ QTest::newRow("10x10, last 4 columns")
+ << 10 << 10 << 0
+ << (IntList() << 6 << 7 << 8 << 9)
+ << (IntList() << 6 << 7 << 8 << 9)
+ << (IntList() << 0 << 1 << 2 << 3 << 4 << 6);
+}
+
+void tst_QItemSelectionModel::selectedColumns()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(IntList, selectColumns);
+ QFETCH(IntList, expectedColumns);
+ QFETCH(IntList, unexpectedColumns);
+
+ MyStandardItemModel model(rowCount, columnCount);
+ QItemSelectionModel selectionModel(&model);
+
+ for (int i = 0; i < selectColumns.count(); ++i)
+ selectionModel.select(model.index(0, selectColumns.at(i)),
+ QItemSelectionModel::Select
+ |QItemSelectionModel::Columns);
+
+ for (int j = 0; j < selectColumns.count(); ++j)
+ QVERIFY(selectionModel.isColumnSelected(expectedColumns.at(j), QModelIndex()));
+
+ for (int k = 0; k < selectColumns.count(); ++k)
+ QVERIFY(!selectionModel.isColumnSelected(unexpectedColumns.at(k), QModelIndex()));
+
+ QModelIndexList selectedColumnIndexes = selectionModel.selectedColumns(row);
+ QCOMPARE(selectedColumnIndexes.count(), expectedColumns.count());
+ qSort(selectedColumnIndexes);
+ for (int l = 0; l < selectedColumnIndexes.count(); ++l) {
+ QCOMPARE(selectedColumnIndexes.at(l).column(), expectedColumns.at(l));
+ QCOMPARE(selectedColumnIndexes.at(l).row(), row);
+ }
+}
+
+void tst_QItemSelectionModel::setCurrentIndex()
+{
+ // Build up a simple tree
+ QStandardItemModel *treemodel = new QStandardItemModel(0, 1);
+ treemodel->insertRow(0, new QStandardItem(1));
+ treemodel->insertRow(1, new QStandardItem(2));
+
+ QTreeView treeView;
+ treeView.setModel(treemodel);
+ QItemSelectionModel *selectionModel = treeView.selectionModel();
+ selectionModel->setCurrentIndex(
+ treemodel->index(0, 0, treemodel->index(0, 0)),
+ QItemSelectionModel::SelectCurrent);
+
+ QSignalSpy currentSpy(selectionModel,
+ SIGNAL(currentChanged(QModelIndex,QModelIndex)));
+ QSignalSpy rowSpy(selectionModel,
+ SIGNAL(currentRowChanged(QModelIndex,QModelIndex)));
+ QSignalSpy columnSpy(selectionModel,
+ SIGNAL(currentColumnChanged(QModelIndex,QModelIndex)));
+
+ // Select the same row and column indexes, but with a different parent
+ selectionModel->setCurrentIndex(
+ treemodel->index(0, 0, treemodel->index(1, 0)),
+ QItemSelectionModel::SelectCurrent);
+
+ QCOMPARE(currentSpy.count(), 1);
+ QCOMPARE(rowSpy.count(), 1);
+ QCOMPARE(columnSpy.count(), 1);
+
+ // Select another row in the same parent
+ selectionModel->setCurrentIndex(
+ treemodel->index(1, 0, treemodel->index(1, 0)),
+ QItemSelectionModel::SelectCurrent);
+
+ QCOMPARE(currentSpy.count(), 2);
+ QCOMPARE(rowSpy.count(), 2);
+ QCOMPARE(columnSpy.count(), 1);
+
+ delete treemodel;
+}
+
+void tst_QItemSelectionModel::splitOnInsert()
+{
+ QStandardItemModel model(4, 1);
+ QItemSelectionModel selectionModel(&model);
+ selectionModel.select(model.index(2, 0), QItemSelectionModel::Select);
+ model.insertRow(2);
+ model.removeRow(3);
+ QVERIFY(!selectionModel.isSelected(model.index(1, 0)));
+}
+
+void tst_QItemSelectionModel::task196285_rowIntersectsSelection()
+{
+ QTableWidget table;
+ table.setColumnCount(1);
+ table.setRowCount(1);
+ table.setItem(0, 0, new QTableWidgetItem("foo"));
+ QAbstractItemModel *model = table.model();
+ QItemSelectionModel *selectionModel = table.selectionModel();
+ QModelIndex index = model->index(0, 0, QModelIndex());
+
+ selectionModel->select(index, QItemSelectionModel::Select);
+ QVERIFY(selectionModel->rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY(selectionModel->columnIntersectsSelection(0, QModelIndex()));
+
+ selectionModel->select(index, QItemSelectionModel::Deselect);
+ QVERIFY(!selectionModel->rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY(!selectionModel->columnIntersectsSelection(0, QModelIndex()));
+
+ selectionModel->select(index, QItemSelectionModel::Toggle);
+ QVERIFY(selectionModel->rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY(selectionModel->columnIntersectsSelection(0, QModelIndex()));
+
+ selectionModel->select(index, QItemSelectionModel::Toggle);
+ QVERIFY(!selectionModel->rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY(!selectionModel->columnIntersectsSelection(0, QModelIndex()));
+}
+
+void tst_QItemSelectionModel::unselectable()
+{
+ QTreeWidget w;
+ for (int i = 0; i < 10; ++i)
+ w.setItemSelected(new QTreeWidgetItem(&w), true);
+ QCOMPARE(w.topLevelItemCount(), 10);
+ QCOMPARE(w.selectionModel()->selectedIndexes().count(), 10);
+ QCOMPARE(w.selectionModel()->selectedRows().count(), 10);
+ for (int j = 0; j < 10; ++j)
+ w.topLevelItem(j)->setFlags(0);
+ QCOMPARE(w.selectionModel()->selectedIndexes().count(), 0);
+ QCOMPARE(w.selectionModel()->selectedRows().count(), 0);
+}
+
+void tst_QItemSelectionModel::task220420_selectedIndexes()
+{
+ QStandardItemModel model(2, 2);
+ QItemSelectionModel selectionModel(&model);
+ QItemSelection selection;
+ selection.append(QItemSelectionRange(model.index(0,0)));
+ selection.append(QItemSelectionRange(model.index(0,1)));
+
+ //we select the 1st row
+ selectionModel.select(selection, QItemSelectionModel::Rows | QItemSelectionModel::Select);
+
+ QCOMPARE(selectionModel.selectedRows().count(), 1);
+ QCOMPARE(selectionModel.selectedIndexes().count(), model.columnCount());
+}
+
+
+class QtTestTableModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+ public:
+ QtTestTableModel(int rows = 0, int columns = 0, QObject *parent = 0)
+ : QAbstractTableModel(parent),
+ row_count(rows),
+ column_count(columns) {}
+
+ int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; }
+ int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; }
+ bool isEditable(const QModelIndex &) const { return true; }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return QString("[%1,%2]").arg(idx.row()).arg(idx.column());
+ return QVariant();
+ }
+
+ int row_count;
+ int column_count;
+ friend class tst_QItemSelectionModel;
+};
+
+
+void tst_QItemSelectionModel::task240734_layoutChanged()
+{
+ QtTestTableModel model(1,1);
+ QItemSelectionModel selectionModel(&model);
+ selectionModel.select(model.index(0,0), QItemSelectionModel::Select);
+ QCOMPARE(selectionModel.selectedIndexes().count() , 1);
+
+ emit model.layoutAboutToBeChanged();
+ model.row_count = 5;
+ emit model.layoutChanged();
+
+ //The selection should not change.
+ QCOMPARE(selectionModel.selectedIndexes().count() , 1);
+ QCOMPARE(selectionModel.selectedIndexes().first() , model.index(0,0));
+}
+
+void tst_QItemSelectionModel::merge_data()
+{
+ QTest::addColumn<QItemSelection>("init");
+ QTest::addColumn<QItemSelection>("other");
+ QTest::addColumn<int>("command");
+ QTest::addColumn<QItemSelection>("result");
+
+ QTest::newRow("Simple select")
+ << QItemSelection()
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << int(QItemSelectionModel::Select)
+ << QItemSelection(model->index(2, 1) , model->index(3, 4));
+
+ QTest::newRow("Simple deselect")
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << int(QItemSelectionModel::Deselect)
+ << QItemSelection();
+
+ QTest::newRow("Simple Toggle deselect")
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << int(QItemSelectionModel::Toggle)
+ << QItemSelection();
+
+ QTest::newRow("Simple Toggle select")
+ << QItemSelection()
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << int(QItemSelectionModel::Toggle)
+ << QItemSelection(model->index(2, 1) , model->index(3, 4));
+
+ QTest::newRow("Add select")
+ << QItemSelection(model->index(2, 1) , model->index(3, 3))
+ << QItemSelection(model->index(2, 2) , model->index(3, 4))
+ << int(QItemSelectionModel::Select)
+ << QItemSelection(model->index(2, 1) , model->index(3, 4));
+
+ QTest::newRow("Deselect")
+ << QItemSelection(model->index(2, 1) , model->index(3, 4))
+ << QItemSelection(model->index(2, 2) , model->index(3, 4))
+ << int(QItemSelectionModel::Deselect)
+ << QItemSelection(model->index(2, 1) , model->index(3, 1));
+
+ QItemSelection r1(model->index(2, 1) , model->index(3, 1));
+ r1.select(model->index(2, 4) , model->index(3, 4));
+ QTest::newRow("Toggle")
+ << QItemSelection(model->index(2, 1) , model->index(3, 3))
+ << QItemSelection(model->index(2, 2) , model->index(3, 4))
+ << int(QItemSelectionModel::Toggle)
+ << r1;
+}
+
+
+void tst_QItemSelectionModel::merge()
+{
+ QFETCH(QItemSelection, init);
+ QFETCH(QItemSelection, other);
+ QFETCH(int, command);
+ QFETCH(QItemSelection, result);
+
+ init.merge(other, QItemSelectionModel::SelectionFlags(command));
+
+ foreach(const QModelIndex &idx, init.indexes())
+ QVERIFY(result.contains(idx));
+ foreach(const QModelIndex &idx, result.indexes())
+ QVERIFY(init.contains(idx));
+}
+
+void tst_QItemSelectionModel::task119433_isRowSelected()
+{
+ QStandardItemModel model(2,2);
+ model.setData(model.index(0,0), 0, Qt::UserRole - 1);
+ QItemSelectionModel sel(&model);
+ sel.select( QItemSelection(model.index(0,0), model.index(0, 1)), QItemSelectionModel::Select);
+ QCOMPARE(sel.selectedIndexes().count(), 1);
+ QVERIFY(sel.isRowSelected(0, QModelIndex()));
+}
+
+void tst_QItemSelectionModel::task252069_rowIntersectsSelection()
+{
+ QStandardItemModel m;
+ for (int i=0; i<8; ++i) {
+ for (int j=0; j<8; ++j) {
+ QStandardItem *item = new QStandardItem(QString("Item number %1").arg(i));
+ if ((i % 2 == 0 && j == 0) ||
+ (j % 2 == 0 && i == 0) ||
+ j == 5 || i == 5 ) {
+ item->setEnabled(false);
+ //item->setSelectable(false);
+ }
+ m.setItem(i, j, item);
+ }
+ }
+
+ QItemSelectionModel selected(&m);
+ //nothing is selected
+ QVERIFY(!selected.rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(2, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(3, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(5, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(0, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(2, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(3, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(5, QModelIndex()));
+ selected.select(m.index(2, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ QVERIFY(!selected.rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY( selected.rowIntersectsSelection(2, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(3, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(5, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(0, QModelIndex()));
+ QVERIFY( selected.columnIntersectsSelection(2, QModelIndex()));
+ QVERIFY( selected.columnIntersectsSelection(3, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(5, QModelIndex()));
+ selected.select(m.index(0, 5), QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ QVERIFY(!selected.rowIntersectsSelection(0, QModelIndex()));
+ QVERIFY( selected.rowIntersectsSelection(2, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(3, QModelIndex()));
+ QVERIFY(!selected.rowIntersectsSelection(5, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(0, QModelIndex()));
+ QVERIFY( selected.columnIntersectsSelection(2, QModelIndex()));
+ QVERIFY( selected.columnIntersectsSelection(3, QModelIndex()));
+ QVERIFY(!selected.columnIntersectsSelection(5, QModelIndex()));
+}
+
+void tst_QItemSelectionModel::task232634_childrenDeselectionSignal()
+{
+ QStandardItemModel model;
+
+ QStandardItem *parentItem = model.invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+
+ QModelIndex root = model.index(0,0);
+ QModelIndex par = root.child(0,0);
+ QModelIndex sel = par.child(0,0);
+
+ QItemSelectionModel selectionModel(&model);
+ selectionModel.select(sel, QItemSelectionModel::SelectCurrent);
+
+ QSignalSpy deselectSpy(&selectionModel, SIGNAL(selectionChanged(const QItemSelection& , const QItemSelection&)));
+ model.removeRows(0, 1, root);
+ QVERIFY(deselectSpy.count() == 1);
+
+ // More testing stress for the patch.
+ model.clear();
+ selectionModel.clear();
+
+ parentItem = model.invisibleRootItem();
+ for (int i = 0; i < 2; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ }
+ for (int i = 0; i < 2; ++i) {
+ parentItem = model.invisibleRootItem()->child(i, 0);
+ for (int j = 0; j < 2; ++j) {
+ QStandardItem *item = new QStandardItem(QString("item %0.%1").arg(i).arg(j));
+ parentItem->appendRow(item);
+ }
+ }
+
+ sel = model.index(0, 0).child(0, 0);
+ selectionModel.select(sel, QItemSelectionModel::Select);
+ QModelIndex sel2 = model.index(1, 0).child(0, 0);
+ selectionModel.select(sel2, QItemSelectionModel::Select);
+
+ QVERIFY(selectionModel.selection().contains(sel));
+ QVERIFY(selectionModel.selection().contains(sel2));
+ deselectSpy.clear();
+ model.removeRow(0, model.index(0, 0));
+ QVERIFY(deselectSpy.count() == 1);
+ QVERIFY(!selectionModel.selection().contains(sel));
+ QVERIFY(selectionModel.selection().contains(sel2));
+}
+
+void tst_QItemSelectionModel::task260134_layoutChangedWithAllSelected()
+{
+ QStringListModel model( QStringList() << "foo" << "bar" << "foo2");
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QItemSelectionModel selection(&proxy);
+
+
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(proxy.rowCount(), 3);
+ proxy.setFilterRegExp( QRegExp("f"));
+ QCOMPARE(proxy.rowCount(), 2);
+
+ QList<QPersistentModelIndex> indexList;
+ indexList << proxy.index(0,0) << proxy.index(1,0);
+ selection.select( QItemSelection(indexList.first(), indexList.last()), QItemSelectionModel::Select);
+
+ //let's check the selection hasn't changed
+ QCOMPARE(selection.selectedIndexes().count(), indexList.count());
+ foreach(QPersistentModelIndex index, indexList)
+ QVERIFY(selection.isSelected(index));
+
+ proxy.setFilterRegExp(QRegExp());
+ QCOMPARE(proxy.rowCount(), 3);
+
+ //let's check the selection hasn't changed
+ QCOMPARE(selection.selectedIndexes().count(), indexList.count());
+ foreach(QPersistentModelIndex index, indexList)
+ QVERIFY(selection.isSelected(index));
+}
+
+
+void tst_QItemSelectionModel::QTBUG5671_layoutChangedWithAllSelected()
+{
+ struct MyFilterModel : public QSortFilterProxyModel
+ { // Override sort filter proxy to remove even numbered rows.
+ bool filtering;
+ virtual bool filterAcceptsRow( int source_row, const QModelIndex& /* source_parent */) const
+ {
+ return !filtering || !( source_row & 1 );
+ }
+ };
+
+ //same as task260134_layoutChangedWithAllSelected but with a sightly bigger model
+
+ enum { cNumRows=30, cNumCols=20 };
+
+ QStandardItemModel model(cNumRows, cNumCols);
+ MyFilterModel proxy;
+ proxy.filtering = true;
+ proxy.setSourceModel(&model);
+ QItemSelectionModel selection(&proxy);
+
+ // Populate the tree view.
+ for (unsigned int i = 0; i < cNumCols; i++)
+ model.setHeaderData( i, Qt::Horizontal, QString::fromLatin1("Column %1").arg(i));
+
+ for (unsigned int r = 0; r < cNumRows; r++) {
+ for (unsigned int c = 0; c < cNumCols; c++) {
+ model.setData(model.index(r, c, QModelIndex()),
+ QString::fromLatin1("r:%1/c:%2").arg(r, c));
+ }
+ }
+
+
+ QCOMPARE(model.rowCount(), int(cNumRows));
+ QCOMPARE(proxy.rowCount(), int(cNumRows/2));
+
+ selection.select( QItemSelection(proxy.index(0,0), proxy.index(proxy.rowCount() - 1, proxy.columnCount() - 1)), QItemSelectionModel::Select);
+
+ QList<QPersistentModelIndex> indexList;
+ foreach(const QModelIndex &id, selection.selectedIndexes())
+ indexList << id;
+
+ proxy.filtering = false;
+ proxy.invalidate();
+ QCOMPARE(proxy.rowCount(), int(cNumRows));
+
+ //let's check the selection hasn't changed
+ QCOMPARE(selection.selectedIndexes().count(), indexList.count());
+ foreach(QPersistentModelIndex index, indexList)
+ QVERIFY(selection.isSelected(index));
+}
+
+void tst_QItemSelectionModel::QTBUG2804_layoutChangedTreeSelection()
+{
+ QStandardItemModel model;
+ QStandardItem top1("Child1"), top2("Child2"), top3("Child3");
+ QStandardItem sub11("Alpha"), sub12("Beta"), sub13("Gamma"), sub14("Delta"),
+ sub21("Alpha"), sub22("Beta"), sub23("Gamma"), sub24("Delta");
+ top1.appendColumn(QList<QStandardItem*>() << &sub11 << &sub12 << &sub13 << &sub14);
+ top2.appendColumn(QList<QStandardItem*>() << &sub21 << &sub22 << &sub23 << &sub24);
+ model.appendColumn(QList<QStandardItem*>() << &top1 << &top2 << &top3);
+
+ QItemSelectionModel selModel(&model);
+
+ selModel.select(sub11.index(), QItemSelectionModel::Select);
+ selModel.select(sub12.index(), QItemSelectionModel::Select);
+ selModel.select(sub21.index(), QItemSelectionModel::Select);
+ selModel.select(sub23.index(), QItemSelectionModel::Select);
+
+ QModelIndexList list = selModel.selectedIndexes();
+ QCOMPARE(list.count(), 4);
+
+ model.sort(0); //this will provoke a relayout
+
+ QCOMPARE(selModel.selectedIndexes().count(), 4);
+}
+
+class RemovalObserver : public QObject
+{
+ Q_OBJECT
+ QItemSelectionModel *m_itemSelectionModel;
+public:
+ RemovalObserver(QItemSelectionModel *selectionModel)
+ : m_itemSelectionModel(selectionModel)
+ {
+ connect(m_itemSelectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection)));
+ }
+
+public slots:
+ void selectionChanged(const QItemSelection & /* selected */, const QItemSelection &deselected)
+ {
+ foreach(const QModelIndex &index, deselected.indexes()) {
+ QVERIFY(!m_itemSelectionModel->selection().contains(index));
+ }
+ QVERIFY(m_itemSelectionModel->selection().size() == 2);
+ }
+
+};
+
+void tst_QItemSelectionModel::deselectRemovedMiddleRange()
+{
+ QStandardItemModel model(8, 0);
+
+ for (int row = 0; row < 8; ++row) {
+ static const int column = 0;
+ QStandardItem *item = new QStandardItem(QString::number(row));
+ model.setItem(row, column, item);
+ }
+
+ QItemSelectionModel selModel(&model);
+
+ selModel.select(QItemSelection(model.index(3, 0), model.index(6, 0)), QItemSelectionModel::Select);
+
+ QVERIFY(selModel.selection().size() == 1);
+
+ RemovalObserver ro(&selModel);
+
+ QSignalSpy spy(&selModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)));
+ bool ok = model.removeRows(4, 2);
+
+ QVERIFY(ok);
+ QVERIFY(spy.size() == 1);
+}
+
+static QStandardItemModel* getModel(QObject *parent)
+{
+ QStandardItemModel *model = new QStandardItemModel(parent);
+
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *parentItem = model->invisibleRootItem();
+ QList<QStandardItem*> list;
+ for (int j = 0; j < 4; ++j) {
+ list.append(new QStandardItem(QString("item %1, %2").arg(i).arg(j)));
+ }
+ parentItem->appendRow(list);
+ parentItem = list.first();
+ for (int j = 0; j < 4; ++j) {
+ QList<QStandardItem*> list;
+ for (int k = 0; k < 4; ++k) {
+ list.append(new QStandardItem(QString("item %1, %2").arg(i).arg(j)));
+ }
+ parentItem->appendRow(list);
+ }
+ }
+ return model;
+}
+
+enum Result {
+ LessThan,
+ NotLessThan,
+ NotEqual
+};
+
+Q_DECLARE_METATYPE(Result);
+
+void tst_QItemSelectionModel::rangeOperatorLessThan_data()
+{
+ QTest::addColumn<int>("parent1");
+ QTest::addColumn<int>("top1");
+ QTest::addColumn<int>("left1");
+ QTest::addColumn<int>("bottom1");
+ QTest::addColumn<int>("right1");
+ QTest::addColumn<int>("parent2");
+ QTest::addColumn<int>("top2");
+ QTest::addColumn<int>("left2");
+ QTest::addColumn<int>("bottom2");
+ QTest::addColumn<int>("right2");
+ QTest::addColumn<Result>("result");
+
+ QTest::newRow("lt01") << -1 << 0 << 0 << 3 << 3
+ << -1 << 0 << 0 << 3 << 3 << NotLessThan;
+
+ QTest::newRow("lt02") << -1 << 0 << 0 << 2 << 3
+ << -1 << 0 << 0 << 3 << 3 << LessThan;
+ QTest::newRow("lt03") << -1 << 0 << 0 << 3 << 2
+ << -1 << 0 << 0 << 3 << 3 << LessThan;
+ QTest::newRow("lt04") << -1 << 0 << 0 << 2 << 2
+ << -1 << 0 << 0 << 3 << 3 << LessThan;
+
+ QTest::newRow("lt05") << -1 << 0 << 0 << 3 << 3
+ << -1 << 0 << 0 << 2 << 3 << NotLessThan;
+ QTest::newRow("lt06") << -1 << 0 << 0 << 3 << 3
+ << -1 << 0 << 0 << 3 << 2 << NotLessThan;
+ QTest::newRow("lt07") << -1 << 0 << 0 << 3 << 3
+ << -1 << 0 << 0 << 2 << 2 << NotLessThan;
+
+ QTest::newRow("lt08") << -1 << 0 << 0 << 3 << 3
+ << 0 << 0 << 0 << 3 << 3 << NotEqual;
+ QTest::newRow("lt09") << 1 << 0 << 0 << 3 << 3
+ << 0 << 0 << 0 << 3 << 3 << NotEqual;
+ QTest::newRow("lt10") << 1 << 0 << 0 << 1 << 1
+ << 0 << 2 << 2 << 3 << 3 << NotEqual;
+ QTest::newRow("lt11") << 1 << 2 << 2 << 3 << 3
+ << 0 << 0 << 0 << 1 << 1 << NotEqual;
+
+ QTest::newRow("lt12") << -1 << 0 << 0 << 1 << 1
+ << -1 << 2 << 2 << 3 << 3 << LessThan;
+ QTest::newRow("lt13") << -1 << 2 << 2 << 3 << 3
+ << -1 << 0 << 0 << 1 << 1 << NotLessThan;
+ QTest::newRow("lt14") << 1 << 0 << 0 << 1 << 1
+ << 1 << 2 << 2 << 3 << 3 << LessThan;
+ QTest::newRow("lt15") << 1 << 2 << 2 << 3 << 3
+ << 1 << 0 << 0 << 1 << 1 << NotLessThan;
+
+ QTest::newRow("lt16") << -1 << 0 << 0 << 2 << 2
+ << -1 << 1 << 1 << 3 << 3 << LessThan;
+ QTest::newRow("lt17") << -1 << 1 << 1 << 3 << 3
+ << -1 << 0 << 0 << 2 << 2 << NotLessThan;
+ QTest::newRow("lt18") << 1 << 0 << 0 << 2 << 2
+ << 1 << 1 << 1 << 3 << 3 << LessThan;
+ QTest::newRow("lt19") << 1 << 1 << 1 << 3 << 3
+ << 1 << 0 << 0 << 2 << 2 << NotLessThan;
+}
+
+void tst_QItemSelectionModel::rangeOperatorLessThan()
+{
+ QStandardItemModel *model1 = getModel(this);
+ QStandardItemModel *model2 = getModel(this);
+
+ QFETCH(int, parent1);
+ QFETCH(int, top1);
+ QFETCH(int, left1);
+ QFETCH(int, bottom1);
+ QFETCH(int, right1);
+ QFETCH(int, parent2);
+ QFETCH(int, top2);
+ QFETCH(int, left2);
+ QFETCH(int, bottom2);
+ QFETCH(int, right2);
+ QFETCH(Result, result);
+
+ QModelIndex p1 = model1->index(parent1, 0);
+
+ QModelIndex tl1 = model1->index(top1, left1, p1);
+ QModelIndex br1 = model1->index(bottom1, right1, p1);
+
+ QItemSelectionRange r1(tl1, br1);
+
+ QModelIndex p2 = model1->index(parent2, 0);
+
+ QModelIndex tl2 = model1->index(top2, left2, p2);
+ QModelIndex br2 = model1->index(bottom2, right2, p2);
+
+ QItemSelectionRange r2(tl2, br2);
+
+ if (result == LessThan)
+ QVERIFY(r1 < r2);
+ else if (result == NotLessThan)
+ QVERIFY(!(r1 < r2));
+ else if (result == NotEqual)
+ if (!(r1 < r2))
+ QVERIFY(r2 < r1);
+
+ // Ranges in different models are always non-equal
+
+ QModelIndex p3 = model2->index(parent1, 0);
+
+ QModelIndex tl3 = model2->index(top1, left1, p3);
+ QModelIndex br3 = model2->index(bottom1, right1, p3);
+
+ QItemSelectionRange r3(tl3, br3);
+
+ if (!(r1 < r3))
+ QVERIFY(r3 < r1);
+
+ if (!(r2 < r3))
+ QVERIFY(r3 < r2);
+
+ QModelIndex p4 = model2->index(parent2, 0);
+
+ QModelIndex tl4 = model2->index(top2, left2, p4);
+ QModelIndex br4 = model2->index(bottom2, right2, p4);
+
+ QItemSelectionRange r4(tl4, br4);
+
+ if (!(r1 < r4))
+ QVERIFY(r4 < r1);
+
+ if (!(r2 < r4))
+ QVERIFY(r4 < r2);
+}
+
+void tst_QItemSelectionModel::testDifferentModels()
+{
+ QStandardItemModel model1;
+ QStandardItemModel model2;
+ QStandardItem top11("Child1"), top12("Child2"), top13("Child3");
+ QStandardItem top21("Child1"), top22("Child2"), top23("Child3");
+
+ model1.appendColumn(QList<QStandardItem*>() << &top11 << &top12 << &top13);
+ model2.appendColumn(QList<QStandardItem*>() << &top21 << &top22 << &top23);
+
+
+ QModelIndex topIndex1 = model1.index(0, 0);
+ QModelIndex bottomIndex1 = model1.index(2, 0);
+ QModelIndex topIndex2 = model2.index(0, 0);
+
+ QItemSelectionRange range(topIndex1, bottomIndex1);
+
+ QVERIFY(range.intersects(QItemSelectionRange(topIndex1, topIndex1)));
+ QVERIFY(!range.intersects(QItemSelectionRange(topIndex2, topIndex2)));
+
+ QItemSelection newSelection;
+ QItemSelection::split(range, QItemSelectionRange(topIndex2, topIndex2), &newSelection);
+
+ QVERIFY(newSelection.isEmpty());
+}
+
+class SelectionObserver : public QObject
+{
+ Q_OBJECT
+public:
+ SelectionObserver(QAbstractItemModel *model, QObject *parent = 0)
+ : QObject(parent), m_model(model), m_selectionModel(0)
+ {
+ connect(model, SIGNAL(modelReset()), SLOT(modelReset()));
+ }
+
+ void setSelectionModel(QItemSelectionModel *selectionModel)
+ {
+ m_selectionModel = selectionModel;
+ connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged(QItemSelection,QItemSelection)));
+ }
+
+ private slots:
+ void modelReset()
+ {
+ const QModelIndex idx = m_model->index(2, 0);
+ QVERIFY(idx.isValid());
+ m_selectionModel->select(QItemSelection(idx, idx), QItemSelectionModel::Clear);
+ }
+
+ void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+ {
+ foreach(const QItemSelectionRange &range, selected)
+ QVERIFY(range.isValid());
+ foreach(const QItemSelectionRange &range, deselected)
+ QVERIFY(range.isValid());
+ }
+
+private:
+ QAbstractItemModel *m_model;
+ QItemSelectionModel *m_selectionModel;
+};
+
+void tst_QItemSelectionModel::testValidRangesInSelectionsAfterReset()
+{
+ QStringListModel model;
+
+ QStringList strings;
+ strings << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five";
+
+ model.setStringList(strings);
+
+ SelectionObserver observer(&model);
+
+ QItemSelectionModel selectionModel(&model);
+
+ selectionModel.select(QItemSelection(model.index(1, 0), model.index(3, 0)), QItemSelectionModel::Select);
+
+ // Cause d->ranges to contain something.
+ model.insertRows(2, 1);
+
+ observer.setSelectionModel(&selectionModel);
+
+ model.setStringList(strings);
+}
+
+class DuplicateItemSelectionModel : public QItemSelectionModel
+{
+ Q_OBJECT
+public:
+ DuplicateItemSelectionModel(QItemSelectionModel *target, QAbstractItemModel *model, QObject *parent = 0)
+ : QItemSelectionModel(model, parent), m_target(target)
+ {
+
+ }
+
+ void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
+ {
+ QItemSelectionModel::select(selection, command);
+ m_target->select(selection, command);
+ }
+
+ using QItemSelectionModel::select;
+
+private:
+ QItemSelectionModel *m_target;
+
+};
+
+void tst_QItemSelectionModel::testChainedSelectionClear()
+{
+ QStringListModel model(QStringList() << "Apples" << "Pears");
+
+ QItemSelectionModel selectionModel(&model, 0);
+ DuplicateItemSelectionModel duplicate(&selectionModel, &model, 0);
+
+ duplicate.select(model.index(0, 0), QItemSelectionModel::Select);
+
+ {
+ QModelIndexList selectedIndexes = selectionModel.selection().indexes();
+ QModelIndexList duplicatedIndexes = duplicate.selection().indexes();
+
+ QVERIFY(selectedIndexes.size() == duplicatedIndexes.size());
+ QVERIFY(selectedIndexes.size() == 1);
+ QVERIFY(selectedIndexes.first() == model.index(0, 0));
+ }
+
+ duplicate.clearSelection();
+
+ {
+ QModelIndexList selectedIndexes = selectionModel.selection().indexes();
+ QModelIndexList duplicatedIndexes = duplicate.selection().indexes();
+
+ QVERIFY(selectedIndexes.size() == duplicatedIndexes.size());
+ QVERIFY(selectedIndexes.size() == 0);
+ }
+
+}
+
+QTEST_MAIN(tst_QItemSelectionModel)
+#include "tst_qitemselectionmodel.moc"
diff --git a/tests/auto/widgets/itemviews/qitemview/.gitignore b/tests/auto/widgets/itemviews/qitemview/.gitignore
new file mode 100644
index 0000000000..c129cad63c
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemview/.gitignore
@@ -0,0 +1 @@
+tst_qitemview
diff --git a/tests/auto/widgets/itemviews/qitemview/qitemview.pro b/tests/auto/widgets/itemviews/qitemview/qitemview.pro
new file mode 100644
index 0000000000..dbdd4612d5
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemview/qitemview.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qitemview.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
new file mode 100644
index 0000000000..4c64d4c52a
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
@@ -0,0 +1,928 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/QtCore>
+#include "viewstotest.cpp"
+#include <stdlib.h>
+
+#if defined(Q_OS_UNIX)
+#include <time.h>
+#endif
+#if defined(Q_OS_WIN)
+#include <time.h>
+#if defined(Q_OS_WINCE)
+#include <aygshell.h>
+#endif
+#define random rand
+#define srandom srand
+
+#if defined(Q_OS_WINCE)
+bool qt_wince_is_platform(const QString &platformString) {
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
+ sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
+ return true;
+ return false;
+}
+
+bool qt_wince_is_pocket_pc() {
+ return qt_wince_is_platform(QString::fromLatin1("PocketPC"));
+}
+
+bool qt_wince_is_smartphone() {
+ return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
+}
+bool qt_wince_is_mobile() {
+ return (qt_wince_is_smartphone() || qt_wince_is_pocket_pc());
+}
+#endif
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/itemviews/qtreeview.h gui/itemviews/qtreeview.cpp
+
+/*!
+ See viewstotest.cpp for instructions on how to have your view tested with these tests.
+
+ Each test such as visualRect have a _data() function which populate the QTest data with
+ tests specified by viewstotest.cpp and any extra data needed for that particular test.
+
+ setupWithNoTestData() fills QTest data with only the tests it is used by most tests.
+
+ There are some basic qDebug statements sprikled about that might be helpfull for
+ fixing your issues.
+ */
+class tst_QItemView : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QItemView() {};
+ virtual ~tst_QItemView() {};
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void nonDestructiveBasicTest_data();
+ void nonDestructiveBasicTest();
+
+ void spider_data();
+ void spider();
+
+ void resize_data();
+ void resize();
+
+ void visualRect_data();
+ void visualRect();
+
+ void indexAt_data();
+ void indexAt();
+
+ void scrollTo_data();
+ void scrollTo();
+
+ void moveCursor_data();
+ void moveCursor();
+
+private:
+ void setupWithNoTestData();
+ void populate();
+ void walkScreen(QAbstractItemView *view);
+
+ QAbstractItemView *view;
+ QAbstractItemModel *treeModel;
+ ViewsToTest *testViews;
+};
+
+/*!
+ * Views should not make invalid requests, sense a model might not check all the bad cases.
+ */
+class CheckerModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ CheckerModel() : QStandardItemModel() {};
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole ) const {
+ if (!index.isValid()) {
+ qWarning("%s: index is not valid", Q_FUNC_INFO);
+ return QVariant();
+ }
+ return QStandardItemModel::data(index, role);
+ };
+
+ Qt::ItemFlags flags(const QModelIndex & index) const {
+ if (!index.isValid()) {
+ qWarning("%s: index is not valid", Q_FUNC_INFO);
+ return Qt::ItemFlags();
+ }
+ if (index.row() == 2 || index.row() == rowCount() - 3
+ || index.column() == 2 || index.column() == columnCount() - 3) {
+ Qt::ItemFlags f = QStandardItemModel::flags(index);
+ f &= ~Qt::ItemIsEnabled;
+ return f;
+ }
+ return QStandardItemModel::flags(index);
+ };
+
+ QModelIndex parent ( const QModelIndex & child ) const {
+ if (!child.isValid()) {
+ qWarning("%s: child index is not valid", Q_FUNC_INFO);
+ return QModelIndex();
+ }
+ return QStandardItemModel::parent(child);
+ };
+
+ QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const {
+ if (orientation == Qt::Horizontal
+ && (section < 0 || section > columnCount())) {
+ qWarning("%s: invalid section %d, must be in range 0..%d",
+ Q_FUNC_INFO, section, columnCount());
+ return QVariant();
+ }
+ if (orientation == Qt::Vertical
+ && (section < 0 || section > rowCount())) {
+ qWarning("%s: invalid section %d, must be in range 0..%d",
+ Q_FUNC_INFO, section, rowCount());
+ return QVariant();
+ }
+ return QStandardItemModel::headerData(section, orientation, role);
+ }
+
+ QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const {
+ return QStandardItemModel::index(row, column, parent);
+ };
+
+ bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ) {
+ if (!index.isValid()) {
+ qWarning("%s: index is not valid", Q_FUNC_INFO);
+ return false;
+ }
+ return QStandardItemModel::setData(index, value, role);
+ }
+
+ void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) {
+ if (column < 0 || column > columnCount())
+ qWarning("%s: invalid column %d, must be in range 0..%d",
+ Q_FUNC_INFO, column, columnCount());
+ else
+ QStandardItemModel::sort(column, order);
+ };
+
+ QModelIndexList match ( const QModelIndex & start, int role, const QVariant & value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags( Qt::MatchStartsWith | Qt::MatchWrap ) ) const {
+ if (hits <= 0) {
+ qWarning("%s: hits must be greater than zero", Q_FUNC_INFO);
+ return QModelIndexList();
+ }
+ if (!value.isValid()) {
+ qWarning("%s: value is not valid", Q_FUNC_INFO);
+ return QModelIndexList();
+ }
+ return QAbstractItemModel::match(start, role, value, hits, flags);
+ };
+
+ bool setHeaderData ( int section, Qt::Orientation orientation, const QVariant & value, int role = Qt::EditRole ) {
+ if (orientation == Qt::Horizontal
+ && (section < 0 || section > columnCount())) {
+ qWarning("%s: invalid section %d, must be in range 0..%d",
+ Q_FUNC_INFO, section, columnCount());
+ return false;
+ }
+ if (orientation == Qt::Vertical
+ && (section < 0 || section > rowCount())) {
+ qWarning("%s: invalid section %d, must be in range 0..%d",
+ Q_FUNC_INFO, section, rowCount());
+ return false;
+ }
+ return QAbstractItemModel::setHeaderData(section, orientation, value, role);
+ };
+};
+
+void tst_QItemView::init()
+{
+ testViews = new ViewsToTest();
+ populate();
+}
+
+void tst_QItemView::cleanup()
+{
+ delete testViews;
+ delete view;
+ delete treeModel;
+ view = 0;
+ testViews = 0;
+ treeModel = 0;
+}
+
+void tst_QItemView::setupWithNoTestData()
+{
+ ViewsToTest testViews;
+ QTest::addColumn<QString>("viewType");
+ QTest::addColumn<bool>("displays");
+ QTest::addColumn<int>("vscroll");
+ QTest::addColumn<int>("hscroll");
+ for (int i = 0; i < testViews.tests.size(); ++i) {
+ QString view = testViews.tests.at(i).viewType;
+ QString test = view + " ScrollPerPixel";
+ bool displayIndexes = (testViews.tests.at(i).display == ViewsToTest::DisplayRoot);
+ QTest::newRow(test.toLatin1().data()) << view << displayIndexes
+ << (int)QAbstractItemView::ScrollPerPixel
+ << (int)QAbstractItemView::ScrollPerPixel
+ ;
+ }
+ for (int i = 0; i < testViews.tests.size(); ++i) {
+ QString view = testViews.tests.at(i).viewType;
+ QString test = view + " ScrollPerItem";
+ bool displayIndexes = (testViews.tests.at(i).display == ViewsToTest::DisplayRoot);
+ QTest::newRow(test.toLatin1().data()) << view << displayIndexes
+ << (int)QAbstractItemView::ScrollPerItem
+ << (int)QAbstractItemView::ScrollPerItem
+ ;
+ }
+}
+
+void tst_QItemView::populate()
+{
+ treeModel = new CheckerModel;
+ QModelIndex parent;
+#if defined(QT_ARCH_ARM)
+ const int baseInsert = 4;
+#else
+ const int baseInsert = 26;
+#endif
+ for (int i = 0; i < 40; ++i) {
+ parent = treeModel->index(0, 0, parent);
+ treeModel->insertRows(0, baseInsert + i, parent);
+ treeModel->insertColumns(0, baseInsert + i, parent);
+ // Fill in some values to make it easier to debug
+ for (int x = 0; x < treeModel->rowCount(); ++x) {
+ for (int y = 0; y < treeModel->columnCount(); ++y) {
+ QModelIndex index = treeModel->index(x, y, parent);
+ treeModel->setData(index, QString("%1_%2_%3").arg(x).arg(y).arg(i));
+ treeModel->setData(index, QVariant(QColor(Qt::blue)), Qt::TextColorRole);
+ }
+ }
+ }
+}
+
+void tst_QItemView::nonDestructiveBasicTest_data()
+{
+ setupWithNoTestData();
+}
+
+/*!
+ nonDestructiveBasicTest tries to call a number of the basic functions (not all)
+ to make sure the view doesn't segfault, testing the functions that makes sense.
+ */
+void tst_QItemView::nonDestructiveBasicTest()
+{
+#ifdef Q_OS_WINCE
+ QTest::qWait(400);
+#endif
+
+ QFETCH(QString, viewType);
+ QFETCH(int, vscroll);
+ QFETCH(int, hscroll);
+
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ view->setVerticalScrollMode((QAbstractItemView::ScrollMode)vscroll);
+ view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
+
+ // setSelectionModel() will assert
+ //view->setSelectionModel(0);
+ // setItemDelegate() will assert
+ //view->setItemDelegate(0);
+
+ // setSelectionMode
+ view->setSelectionMode(QAbstractItemView::SingleSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::SingleSelection);
+ view->setSelectionMode(QAbstractItemView::ContiguousSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::ContiguousSelection);
+ view->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::ExtendedSelection);
+ view->setSelectionMode(QAbstractItemView::MultiSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::MultiSelection);
+ view->setSelectionMode(QAbstractItemView::NoSelection);
+ QCOMPARE(view->selectionMode(), QAbstractItemView::NoSelection);
+
+ // setSelectionBehavior
+ view->setSelectionBehavior(QAbstractItemView::SelectItems);
+ QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectItems);
+ view->setSelectionBehavior(QAbstractItemView::SelectRows);
+ QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectRows);
+ view->setSelectionBehavior(QAbstractItemView::SelectColumns);
+ QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectColumns);
+
+ // setEditTriggers
+ view->setEditTriggers(QAbstractItemView::EditKeyPressed);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::EditKeyPressed);
+ view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::NoEditTriggers);
+ view->setEditTriggers(QAbstractItemView::CurrentChanged);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::CurrentChanged);
+ view->setEditTriggers(QAbstractItemView::DoubleClicked);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::DoubleClicked);
+ view->setEditTriggers(QAbstractItemView::SelectedClicked);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::SelectedClicked);
+ view->setEditTriggers(QAbstractItemView::AnyKeyPressed);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::AnyKeyPressed);
+ view->setEditTriggers(QAbstractItemView::AllEditTriggers);
+ QCOMPARE(view->editTriggers(), QAbstractItemView::AllEditTriggers);
+
+ // setAutoScroll
+ view->setAutoScroll(false);
+ QCOMPARE(view->hasAutoScroll(), false);
+ view->setAutoScroll(true);
+ QCOMPARE(view->hasAutoScroll(), true);
+
+ // setTabKeyNavigation
+ view->setTabKeyNavigation(false);
+ QCOMPARE(view->tabKeyNavigation(), false);
+ view->setTabKeyNavigation(true);
+ QCOMPARE(view->tabKeyNavigation(), true);
+#ifndef QT_NO_DRAGANDDROP
+ // setDropIndicatorShown
+ view->setDropIndicatorShown(false);
+ QCOMPARE(view->showDropIndicator(), false);
+ view->setDropIndicatorShown(true);
+ QCOMPARE(view->showDropIndicator(), true);
+
+ // setDragEnabled
+ view->setDragEnabled(false);
+ QCOMPARE(view->dragEnabled(), false);
+ view->setDragEnabled(true);
+ QCOMPARE(view->dragEnabled(), true);
+#endif
+
+ // setAlternatingRowColors
+ view->setAlternatingRowColors(false);
+ QCOMPARE(view->alternatingRowColors(), false);
+ view->setAlternatingRowColors(true);
+ QCOMPARE(view->alternatingRowColors(), true);
+
+ // setIconSize
+ view->setIconSize(QSize(16, 16));
+ QCOMPARE(view->iconSize(), QSize(16, 16));
+ view->setIconSize(QSize(32, 32));
+ QCOMPARE(view->iconSize(), QSize(32, 32));
+ // Should this happen?
+ view->setIconSize(QSize(-1, -1));
+ QCOMPARE(view->iconSize(), QSize(-1, -1));
+
+ QCOMPARE(view->currentIndex(), QModelIndex());
+ QCOMPARE(view->rootIndex(), QModelIndex());
+
+ view->keyboardSearch("");
+ view->keyboardSearch("foo");
+ view->keyboardSearch("1");
+
+ QCOMPARE(view->visualRect(QModelIndex()), QRect());
+
+ view->scrollTo(QModelIndex());
+
+ QCOMPARE(view->sizeHintForIndex(QModelIndex()), QSize());
+ QCOMPARE(view->indexAt(QPoint(-1, -1)), QModelIndex());
+
+ if (!view->model()){
+ QCOMPARE(view->indexAt(QPoint(10, 10)), QModelIndex());
+ QCOMPARE(view->sizeHintForRow(0), -1);
+ QCOMPARE(view->sizeHintForColumn(0), -1);
+ } else if (view->itemDelegate()){
+ view->sizeHintForRow(0);
+ view->sizeHintForColumn(0);
+ }
+ view->openPersistentEditor(QModelIndex());
+ view->closePersistentEditor(QModelIndex());
+
+ view->reset();
+ view->setRootIndex(QModelIndex());
+ view->doItemsLayout();
+ view->selectAll();
+ // edit() causes warning by default
+ //view->edit(QModelIndex());
+ view->clearSelection();
+ view->setCurrentIndex(QModelIndex());
+}
+
+void tst_QItemView::spider_data()
+{
+ setupWithNoTestData();
+}
+
+void touch(QWidget *widget, Qt::KeyboardModifier modifier, Qt::Key keyPress){
+ int width = widget->width();
+ int height = widget->height();
+ for (int i = 0; i < 5; ++i) {
+ QTest::mouseClick(widget, Qt::LeftButton, modifier, QPoint(random() % width, random() % height));
+ QTest::mouseDClick(widget, Qt::LeftButton, modifier, QPoint(random() % width, random() % height));
+ QPoint press(random() % width, random() % height);
+ QPoint releasePoint(random() % width, random() % height);
+ QTest::mousePress(widget, Qt::LeftButton, modifier, press);
+ QTest::mouseMove(widget, releasePoint);
+ if (random() % 1 == 0)
+ QTest::mouseRelease(widget, Qt::LeftButton, 0, releasePoint);
+ else
+ QTest::mouseRelease(widget, Qt::LeftButton, modifier, releasePoint);
+ QTest::keyClick(widget, keyPress);
+ }
+}
+
+/*!
+ This is a basic stress testing application that tries a few basics such as clicking around
+ the screen, and key presses.
+
+ The main goal is to catch any easy segfaults, not to test every case.
+ */
+void tst_QItemView::spider()
+{
+ QFETCH(QString, viewType);
+ QFETCH(int, vscroll);
+ QFETCH(int, hscroll);
+
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ view->setVerticalScrollMode((QAbstractItemView::ScrollMode)vscroll);
+ view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
+ view->setModel(treeModel);
+ view->show();
+#if defined(Q_OS_WINCE)
+ srandom(0);
+#else
+ srandom(time(0));
+#endif
+ touch(view->viewport(), Qt::NoModifier, Qt::Key_Left);
+ touch(view->viewport(), Qt::ShiftModifier, Qt::Key_Enter);
+ touch(view->viewport(), Qt::ControlModifier, Qt::Key_Backspace);
+ touch(view->viewport(), Qt::AltModifier, Qt::Key_Up);
+}
+
+void tst_QItemView::resize_data()
+{
+ setupWithNoTestData();
+}
+
+/*!
+ The main goal is to catch any infinite loops from layouting
+ */
+void tst_QItemView::resize()
+{
+ QSKIP("This test needs to be re-thought out, it takes too long and doesn't really catch the problem.", SkipAll);
+
+ QFETCH(QString, viewType);
+ QFETCH(int, vscroll);
+ QFETCH(int, hscroll);
+
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ view->setVerticalScrollMode((QAbstractItemView::ScrollMode)vscroll);
+ view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
+ view->setModel(treeModel);
+ view->show();
+
+ for (int w = 100; w < 400; w+=10) {
+ for (int h = 100; h < 400; h+=10) {
+ view->resize(w, h);
+ QTest::qWait(1);
+ qApp->processEvents();
+ }
+ }
+}
+
+void tst_QItemView::visualRect_data()
+{
+ setupWithNoTestData();
+}
+
+void tst_QItemView::visualRect()
+{
+ QFETCH(QString, viewType);
+ QFETCH(int, vscroll);
+ QFETCH(int, hscroll);
+
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ view->setVerticalScrollMode((QAbstractItemView::ScrollMode)vscroll);
+ view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
+ QCOMPARE(view->visualRect(QModelIndex()), QRect());
+
+ // Add model
+ view->setModel(treeModel);
+ QCOMPARE(view->visualRect(QModelIndex()), QRect());
+
+ QModelIndex topIndex = treeModel->index(0,0);
+
+ QFETCH(bool, displays);
+ if (!displays){
+ QVERIFY(view->visualRect(topIndex) == QRect());
+ return;
+ }
+
+ QVERIFY(view->visualRect(topIndex) != QRect());
+ view->show();
+ QVERIFY(view->visualRect(topIndex) != QRect());
+
+ QVERIFY(topIndex == view->indexAt(view->visualRect(topIndex).center()));
+ QVERIFY(topIndex == view->indexAt(view->visualRect(topIndex).bottomLeft()));
+ QVERIFY(topIndex == view->indexAt(view->visualRect(topIndex).bottomRight()));
+ QVERIFY(topIndex == view->indexAt(view->visualRect(topIndex).topLeft()));
+ QVERIFY(topIndex == view->indexAt(view->visualRect(topIndex).topRight()));
+
+ testViews->hideIndexes(view);
+ QModelIndex hiddenIndex = treeModel->index(1, 0);
+ QVERIFY(view->visualRect(hiddenIndex) == QRect());
+}
+
+void tst_QItemView::walkScreen(QAbstractItemView *view)
+{
+ QModelIndex hiddenIndex = view->model() ? view->model()->index(1, 0) : QModelIndex();
+ int width = view->width();
+ int height = view->height();
+ for (int w = 0; w < width; ++w)
+ {
+ for (int h = 0; h < height; ++h)
+ {
+ QPoint point(w, h);
+ QModelIndex index = view->indexAt(point);
+
+ // If we have no model then we should *never* get a valid index
+ if (!view->model() || !view->isVisible())
+ QVERIFY(!index.isValid());
+ // index should not be the hidden one
+ if (hiddenIndex.isValid())
+ QVERIFY(hiddenIndex != index);
+ // If we are valid then check the visualRect for that index
+ if (index.isValid()){
+ QRect visualRect = view->visualRect(index);
+ if (!visualRect.contains(point))
+ qDebug() << point << visualRect;
+ QVERIFY(visualRect.contains(point));
+ }
+ }
+ }
+}
+
+void walkIndex(QModelIndex index, QAbstractItemView *view)
+{
+ QRect visualRect = view->visualRect(index);
+ //if (index.column() == 0)
+ //qDebug() << index << visualRect;
+ int width = visualRect.width();
+ int height = visualRect.height();
+
+ for (int w = 0; w < width; ++w)
+ {
+ for (int h = 0; h < height; ++h)
+ {
+ QPoint point(visualRect.x()+w, visualRect.y()+h);
+ if (view->indexAt(point) != index) {
+ qDebug() << "index" << index << "visualRect" << visualRect << point << view->indexAt(point);
+ }
+ QVERIFY(view->indexAt(point) == index);
+ }
+ }
+
+}
+
+/*!
+ A model that returns an index of parent X should also return X when asking
+ for the parent of the index.
+
+ This recursive function does pretty extensive testing on the whole model in an
+ effort to catch edge cases.
+
+ This function assumes that rowCount(), columnCount() and index() work. If they have
+ a bug it will point it out, but the above tests should have already found the basic bugs
+ because it is easier to figure out the problem in those tests then this one.
+ */
+void checkChildren(QAbstractItemView *currentView, const QModelIndex &parent = QModelIndex(), int currentDepth=0)
+{
+ QAbstractItemModel *currentModel = currentView->model();
+
+ int rows = currentModel->rowCount(parent);
+ int columns = currentModel->columnCount(parent);
+
+ for (int r = 0; r < rows; ++r) {
+ for (int c = 0; c < columns; ++c) {
+ QModelIndex index = currentModel->index(r, c, parent);
+ walkIndex(index, currentView);
+ if (QTest::currentTestFailed())
+ return;
+
+ // recursivly go down
+ if (currentModel->hasChildren(index) && currentDepth < 2) {
+ checkChildren(currentView, index, ++currentDepth);
+ // Because this is recursive we will return at the first failure rather then
+ // reporting it over and over
+ if (QTest::currentTestFailed())
+ return;
+ }
+ }
+ }
+}
+
+
+void tst_QItemView::indexAt_data()
+{
+ setupWithNoTestData();
+}
+
+void tst_QItemView::indexAt()
+{
+ QFETCH(QString, viewType);
+ QFETCH(int, vscroll);
+ QFETCH(int, hscroll);
+
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ view->setVerticalScrollMode((QAbstractItemView::ScrollMode)vscroll);
+ view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
+ view->show();
+ view->setModel(treeModel);
+#if 0
+ checkChildren(view);
+
+ QModelIndex index = view->model()->index(0, 0);
+ while (view->model()->hasChildren(index))
+ index = view->model()->index(0, 0, index);
+ QCOMPARE(view->model()->hasChildren(index), false);
+ QVERIFY(index.isValid());
+ view->setRootIndex(index);
+ //qDebug() << view->indexAt(QPoint(view->width()/2, view->height()/2)) << view->rootIndex();
+ QPoint p(1, view->height()/2);
+ QModelIndex idx = view->indexAt(p);
+ QCOMPARE(idx, QModelIndex());
+#endif
+}
+
+void tst_QItemView::scrollTo_data()
+{
+ setupWithNoTestData();
+}
+
+void tst_QItemView::scrollTo()
+{
+ QFETCH(QString, viewType);
+ QFETCH(int, vscroll);
+ QFETCH(int, hscroll);
+
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ view->setVerticalScrollMode((QAbstractItemView::ScrollMode)vscroll);
+ view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
+ view->setModel(treeModel);
+ view->show();
+
+ QModelIndex parent;
+ for (int row = 0; row < treeModel->rowCount(parent); ++row) {
+ for (int column = 0; column < treeModel->columnCount(parent); ++column) {
+ QModelIndex idx = treeModel->index(row, column, parent);
+ view->scrollTo(idx);
+ QRect rect = view->visualRect(idx);
+ view->scrollTo(idx);
+ QCOMPARE(rect, view->visualRect(idx));
+ }
+ }
+
+ QModelIndex idx = treeModel->index(0, 0, parent);
+ view->scrollTo(idx);
+ QRect rect = view->visualRect(idx);
+ view->scrollToBottom();
+ view->scrollTo(idx);
+ QCOMPARE(rect, view->visualRect(idx));
+}
+
+void tst_QItemView::moveCursor_data()
+{
+ setupWithNoTestData();
+}
+
+class Event {
+public:
+ Event(){}
+ Event(Qt::Key k, QModelIndex s, QModelIndex e, QString n) : key(k), start(s), end(e), name(n){}
+ Qt::Key key;
+ QModelIndex start;
+ QModelIndex end;
+ QString name;
+};
+
+
+void tst_QItemView::moveCursor()
+{
+ QFETCH(QString, viewType);
+ view = testViews->createView(viewType);
+ QVERIFY(view);
+ if (view->objectName() == "QHeaderView")
+ return;
+
+ view->setModel(treeModel);
+ testViews->hideIndexes(view);
+ view->resize(100, 100);
+
+ QModelIndex invalidIndex = QModelIndex();
+ QModelIndex firstRow = treeModel->index(0, 0);
+ QModelIndex hiddenRowT = treeModel->index(1, 0);
+ QModelIndex disabledRowT = treeModel->index(2, 0);
+ QModelIndex secondRow = treeModel->index(3, 0);
+
+ QModelIndex secondToLastRow = treeModel->index(treeModel->rowCount() - 4, 0);
+ QModelIndex disabledRowB = treeModel->index(treeModel->rowCount() - 3, 0);
+ QModelIndex hiddenRowB = treeModel->index(treeModel->rowCount() - 2, 0);
+ QModelIndex lastRow = treeModel->index(treeModel->rowCount() - 1, 0);
+
+ QStack<Event> events;
+
+ events.push(Event(Qt::Key_Up, invalidIndex, firstRow, "inv, first"));
+ events.push(Event(Qt::Key_Up, hiddenRowT, firstRow, "hid, first"));
+ events.push(Event(Qt::Key_Up, disabledRowT, firstRow, "dis, first"));
+ events.push(Event(Qt::Key_Up, firstRow, firstRow, "first, first"));
+ events.push(Event(Qt::Key_Up, secondRow, firstRow, "sec, first"));
+ events.push(Event(Qt::Key_Up, hiddenRowB, firstRow, "hidB, first"));
+ events.push(Event(Qt::Key_Up, disabledRowB, secondToLastRow, "disB, secLast"));
+ events.push(Event(Qt::Key_Up, lastRow, secondToLastRow, "last, secLast"));
+
+ events.push(Event(Qt::Key_Down, invalidIndex, firstRow, "inv, first"));
+ events.push(Event(Qt::Key_Down, hiddenRowT, firstRow, "hid, first"));
+ events.push(Event(Qt::Key_Down, disabledRowT, secondRow, "dis, sec"));
+ events.push(Event(Qt::Key_Down, firstRow, secondRow, "first, sec"));
+ events.push(Event(Qt::Key_Down, secondToLastRow, lastRow, "secLast, last" ));
+ events.push(Event(Qt::Key_Down, disabledRowB, lastRow, "disB, last"));
+ events.push(Event(Qt::Key_Down, hiddenRowB, firstRow, "hidB, first"));
+ events.push(Event(Qt::Key_Down, lastRow, lastRow, "last, last"));
+
+ events.push(Event(Qt::Key_Home, invalidIndex, firstRow, "inv, first"));
+ events.push(Event(Qt::Key_End, invalidIndex, firstRow, "inv, first"));
+
+ if (view->objectName() == "QTableView") {
+ // In a table we move to the first/last column
+ events.push(Event(Qt::Key_Home, hiddenRowT, firstRow, "hid, first"));
+ events.push(Event(Qt::Key_Home, disabledRowT, disabledRowT, "dis, dis"));
+ events.push(Event(Qt::Key_Home, firstRow, firstRow, "first, first"));
+ events.push(Event(Qt::Key_Home, secondRow, secondRow, "sec, sec"));
+ events.push(Event(Qt::Key_Home, disabledRowB, disabledRowB, "disB, disB"));
+ events.push(Event(Qt::Key_Home, hiddenRowB, firstRow, "hidB, first"));
+ events.push(Event(Qt::Key_Home, secondToLastRow, secondToLastRow, "secLast, secLast"));
+ events.push(Event(Qt::Key_Home, lastRow, lastRow, "last, last"));
+
+ int col = treeModel->columnCount() - 1;
+ events.push(Event(Qt::Key_End, hiddenRowT, firstRow, "hidT, hidT"));
+ events.push(Event(Qt::Key_End, disabledRowT, disabledRowT, "disT, disT"));
+ events.push(Event(Qt::Key_End, firstRow, firstRow.sibling(firstRow.row(), col), "first, first_C"));
+ events.push(Event(Qt::Key_End, secondRow, secondRow.sibling(secondRow.row(), col), "sec, sec_C"));
+ events.push(Event(Qt::Key_End, disabledRowB, disabledRowB, "disB, disB"));
+ events.push(Event(Qt::Key_End, hiddenRowB, firstRow, "hidB, hidB"));
+ events.push(Event(Qt::Key_End, secondToLastRow, secondToLastRow.sibling(secondToLastRow.row(), col), "secLast, secLast_C"));
+ events.push(Event(Qt::Key_End, lastRow, lastRow.sibling(lastRow.row(), col), "last, last_C"));
+ } else {
+ events.push(Event(Qt::Key_Home, hiddenRowT, firstRow, "hid, first"));
+ events.push(Event(Qt::Key_Home, disabledRowT, firstRow, "dis, first"));
+ events.push(Event(Qt::Key_Home, firstRow, firstRow, "first, first"));
+ events.push(Event(Qt::Key_Home, secondRow, firstRow, "sec, first"));
+ events.push(Event(Qt::Key_Home, disabledRowB, firstRow, "disB, first"));
+ events.push(Event(Qt::Key_Home, hiddenRowB, firstRow, "hidB, first"));
+ events.push(Event(Qt::Key_Home, secondToLastRow, firstRow, "sec, first"));
+ events.push(Event(Qt::Key_Home, lastRow, firstRow, "last, first"));
+
+ events.push(Event(Qt::Key_End, hiddenRowT, firstRow, "hid, last"));
+ events.push(Event(Qt::Key_End, disabledRowT, lastRow, "dis, last"));
+ events.push(Event(Qt::Key_End, firstRow, lastRow, "first, last"));
+ events.push(Event(Qt::Key_End, secondRow, lastRow, "sec, last"));
+ events.push(Event(Qt::Key_End, disabledRowB, lastRow, "disB, last"));
+ events.push(Event(Qt::Key_End, hiddenRowB, firstRow, "hidB, last"));
+ events.push(Event(Qt::Key_End, secondToLastRow, lastRow, "sec, last"));
+ events.push(Event(Qt::Key_End, lastRow, lastRow, "last, last"));
+ }
+
+ events.push(Event(Qt::Key_PageDown, invalidIndex, firstRow, "inv, first"));
+ events.push(Event(Qt::Key_PageDown, firstRow, QModelIndex(), "first, x"));
+ events.push(Event(Qt::Key_PageDown, secondRow, QModelIndex(), "sec, x"));
+ events.push(Event(Qt::Key_PageDown, hiddenRowT, QModelIndex(), "hid, x"));
+ events.push(Event(Qt::Key_PageDown, disabledRowT, QModelIndex(), "dis, x"));
+ events.push(Event(Qt::Key_PageDown, disabledRowB, lastRow, "disB, last"));
+ events.push(Event(Qt::Key_PageDown, hiddenRowB, lastRow, "hidB, last"));
+ events.push(Event(Qt::Key_PageDown, secondToLastRow, lastRow, "secLast, last"));
+ events.push(Event(Qt::Key_PageDown, lastRow, lastRow, "last, last"));
+
+ events.push(Event(Qt::Key_PageUp, invalidIndex, firstRow, "inv, first"));
+ events.push(Event(Qt::Key_PageUp, firstRow, firstRow, "first, first"));
+ events.push(Event(Qt::Key_PageUp, secondRow, firstRow, "sec, first"));
+ events.push(Event(Qt::Key_PageUp, secondToLastRow, QModelIndex(), "secLast, x"));
+ events.push(Event(Qt::Key_PageUp, lastRow, QModelIndex(), "last, x"));
+
+ if (view->objectName() == "QTableView") {
+ events.push(Event(Qt::Key_Left, firstRow, firstRow, "first_0, first"));
+ events.push(Event(Qt::Key_Left, firstRow.sibling(0, 1), firstRow, "first_1, first"));
+ events.push(Event(Qt::Key_Left, firstRow.sibling(0, 2), firstRow, "first_2, first"));
+ events.push(Event(Qt::Key_Left, firstRow.sibling(0, 3), firstRow, "first_3, first"));
+ events.push(Event(Qt::Key_Left, secondRow, secondRow, "sec, sec"));
+
+ events.push(Event(Qt::Key_Right, firstRow, firstRow.sibling(0, 3), "first, first_3"));
+ events.push(Event(Qt::Key_Right, firstRow.sibling(0, 1), firstRow, "first_1, first"));
+ events.push(Event(Qt::Key_Right, firstRow.sibling(0, 2), firstRow.sibling(0, 3), "first_2, first_3"));
+ events.push(Event(Qt::Key_Right, firstRow.sibling(0, treeModel->columnCount()-1), firstRow.sibling(0, treeModel->columnCount()-1), "first_3, sec"));
+ }
+
+#if 0 // ### disable this part for now
+
+ // ### hide the first/last row,column and re-run all of these tests
+ // ### Not 100% sure, but I think the next to are tableview specific only and everyone else just does up/down
+ // QAbstractItemView::MoveNext, AbstractItemView::MovePrevious
+
+ while (!events.isEmpty()) {
+ Event event = events.pop();
+ view->setCurrentIndex(event.start);
+ QCOMPARE(view->currentIndex(), event.start);
+
+ if (event.key == Qt::Key_PageUp && event.end == QModelIndex()) {
+ QModelIndex x = view->indexAt(QPoint(1,1));
+ if (x.row() == 0)
+ event.end = x;
+ else
+ event.end = x.sibling(x.row() - 1, x.column());
+ }
+ if (event.key == Qt::Key_PageDown && event.end == QModelIndex()) {
+ QModelIndex x = view->indexAt(QPoint(1, view->viewport()->height() - 10));
+ if (x.row() == view->model()->rowCount() - 1)
+ event.end = x;
+ else
+ event.end = x.sibling(x.row() + 1, x.column());
+ }
+
+ QTest::keyPress(view, event.key);
+ QTest::keyRelease(view, event.key);
+ QModelIndex current = view->currentIndex();
+ if (event.key == Qt::Key_PageUp) {
+ int diff = event.end.row() - current.row();
+ QVERIFY(diff <= 2);
+ continue;
+ }
+ if (event.key == Qt::Key_PageDown) {
+ int diff = current.row() - event.end.row();
+ QVERIFY(diff <= 2);
+ continue;
+ }
+
+ if (current != event.end) {
+ QString k;
+ if (event.key == Qt::Key_Up) k = "up";
+ if (event.key == Qt::Key_Right) k = "right";
+ if (event.key == Qt::Key_Left) k = "left";
+ if (event.key == Qt::Key_PageUp) k = "page up";
+ if (event.key == Qt::Key_PageDown) k = "page down";
+ if (event.key == Qt::Key_Down) k = "down";
+ if (event.key == Qt::Key_Home) k = "home";
+ if (event.key == Qt::Key_End) k = "end";
+ qDebug() << k << event.name << event.start << event.end << current;
+ }
+ QCOMPARE(current, event.end);
+ }
+#endif
+}
+
+QTEST_MAIN(tst_QItemView)
+#include "tst_qitemview.moc"
diff --git a/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp b/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp
new file mode 100644
index 0000000000..b61ecd5c2a
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/QtCore>
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+
+/*
+ To add a view to be tested add the header file to the includes
+ and impliment what is needed in the functions below.
+
+ You can add more then one view, several Qt views are included as examples.
+
+ In tst_qitemview.cpp a new ViewsToTest object is created for each test.
+
+ When you have errors fix the first ones first. Later tests depend upon them working
+*/
+
+class ViewsToTest
+{
+public:
+ ViewsToTest();
+
+ QAbstractItemView *createView(const QString &viewType);
+ void hideIndexes(QAbstractItemView *view);
+
+ enum Display { DisplayNone, DisplayRoot };
+
+ struct test {
+ test(QString m, Display d) : viewType(m), display(d){};
+ QString viewType;
+ Display display;
+ };
+
+ QList<test> tests;
+};
+
+
+/*!
+ Add new tests, they can be the same view, but in a different state.
+ */
+ViewsToTest::ViewsToTest()
+{
+ tests.append(test("QTreeView_ScrollPerItem", DisplayRoot));
+ tests.append(test("QTreeView_ScrollPerPixel", DisplayRoot));
+ tests.append(test("QListView_ScrollPerItem", DisplayRoot));
+ tests.append(test("QListView_ScrollPerPixel", DisplayRoot));
+ tests.append(test("QHeaderViewHorizontal", DisplayNone));
+ tests.append(test("QHeaderViewVertical", DisplayNone));
+ tests.append(test("QTableView_ScrollPerItem", DisplayRoot));
+ tests.append(test("QTableView_ScrollPerPixel", DisplayRoot));
+ tests.append(test("QTableViewNoGrid", DisplayRoot));
+}
+
+/*!
+ Return a new viewType.
+ */
+QAbstractItemView *ViewsToTest::createView(const QString &viewType)
+{
+ QAbstractItemView *view = 0;
+ if (viewType == "QListView_ScrollPerItem") {
+ view = new QListView();
+ view->setObjectName("QListView");
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+ } else if (viewType == "QListView_ScrollPerPixel") {
+ view = new QListView();
+ view->setObjectName("QListView");
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ } else if (viewType == "QHeaderViewHorizontal") {
+ view = new QHeaderView(Qt::Horizontal);
+ view->setObjectName("QHeaderView");
+ } else if (viewType == "QHeaderViewVertical") {
+ view = new QHeaderView(Qt::Vertical);
+ view->setObjectName("QHeaderView");
+ } else if (viewType == "QTableView_ScrollPerItem") {
+ view = new QTableView();
+ view->setObjectName("QTableView");
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+ } else if (viewType == "QTableView_ScrollPerPixel") {
+ view = new QTableView();
+ view->setObjectName("QTableView");
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ } else if (viewType == "QTableViewNoGrid") {
+ QTableView *table = new QTableView();
+ table->setObjectName("QTableView");
+ table->setShowGrid(false);
+ view = table;
+ } else if (viewType == "QTreeView_ScrollPerItem") {
+ view = new QTreeView();
+ view->setObjectName("QTreeView");
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+ view->setSelectionBehavior(QAbstractItemView::SelectItems);
+ } else if (viewType == "QTreeView_ScrollPerPixel") {
+ view = new QTreeView();
+ view->setObjectName("QTreeView");
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ view->setSelectionBehavior(QAbstractItemView::SelectItems);
+ }
+ return view;
+}
+
+void ViewsToTest::hideIndexes(QAbstractItemView *view)
+{
+ if (QTableView *tableView = qobject_cast<QTableView *>(view)) {
+ tableView->setColumnHidden(1, true);
+ tableView->setRowHidden(1, true);
+ tableView->setRowHidden(tableView->model()->rowCount()-2, true);
+ }
+ if (QTreeView *treeView = qobject_cast<QTreeView *>(view)) {
+ treeView->setColumnHidden(1, true);
+ treeView->setRowHidden(1, QModelIndex(), true);
+ treeView->setRowHidden(treeView->model()->rowCount()-2, QModelIndex(), true);
+ }
+ if (QListView *listView = qobject_cast<QListView *>(view)) {
+ listView->setRowHidden(1, true);
+ listView->setRowHidden(listView->model()->rowCount()-2, true);
+ }
+}
+
diff --git a/tests/auto/widgets/itemviews/qlistview/.gitignore b/tests/auto/widgets/itemviews/qlistview/.gitignore
new file mode 100644
index 0000000000..a0e31d03d4
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistview/.gitignore
@@ -0,0 +1 @@
+tst_qlistview
diff --git a/tests/auto/widgets/itemviews/qlistview/qlistview.pro b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
new file mode 100644
index 0000000000..07fabbce35
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets gui-private
+SOURCES += tst_qlistview.cpp
+win32:!wince*: LIBS += -luser32
+
+qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
new file mode 100644
index 0000000000..b58a306f94
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -0,0 +1,2073 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qabstractitemmodel.h>
+#include <qapplication.h>
+#include <qlistview.h>
+#include <qlistwidget.h>
+#include <qitemdelegate.h>
+#include <qstandarditemmodel.h>
+#include <qstringlistmodel.h>
+#include <cmath>
+#include <math.h>
+#include <QtWidgets/QScrollBar>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QStyledItemDelegate>
+#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+# include <windows.h>
+# include <QtGui/QGuiApplication>
+# include <QtGui/QPlatformNativeInterface>
+#endif // Q_OS_WIN
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+static inline HWND getHWNDForWidget(const QWidget *widget)
+{
+ QWindow *window = widget->windowHandle();
+ return static_cast<HWND> (QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", window));
+}
+#endif // Q_OS_WIN
+
+class tst_QListView : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QListView();
+ virtual ~tst_QListView();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void noDelegate();
+ void noModel();
+ void emptyModel();
+ void removeRows();
+ void cursorMove();
+ void hideRows();
+ void moveCursor();
+ void moveCursor2();
+ void moveCursor3();
+ void indexAt();
+ void clicked();
+ void singleSelectionRemoveRow();
+ void singleSelectionRemoveColumn();
+ void modelColumn();
+ void hideFirstRow();
+ void batchedMode();
+ void setCurrentIndex();
+ void selection_data();
+ void selection();
+ void scrollTo();
+ void scrollBarRanges();
+ void scrollBarAsNeeded_data();
+ void scrollBarAsNeeded();
+ void moveItems();
+ void wordWrap();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && WINVER >= 0x0500
+ void setCurrentIndexAfterAppendRowCrash();
+#endif
+ void emptyItemSize();
+ void task203585_selectAll();
+ void task228566_infiniteRelayout();
+ void task248430_crashWith0SizedItem();
+ void task250446_scrollChanged();
+ void task196118_visualRegionForSelection();
+ void task254449_draggingItemToNegativeCoordinates();
+ void keyboardSearch();
+ void shiftSelectionWithNonUniformItemSizes();
+ void clickOnViewportClearsSelection();
+ void task262152_setModelColumnNavigate();
+ void taskQTBUG_2233_scrollHiddenItems_data();
+ void taskQTBUG_2233_scrollHiddenItems();
+ void taskQTBUG_633_changeModelData();
+ void taskQTBUG_435_deselectOnViewportClick();
+ void taskQTBUG_2678_spacingAndWrappedText();
+ void taskQTBUG_5877_skippingItemInPageDownUp();
+ void taskQTBUG_9455_wrongScrollbarRanges();
+ void styleOptionViewItem();
+ void taskQTBUG_12308_artihmeticException();
+ void taskQTBUG_12308_wrongFlowLayout();
+};
+
+// Testing get/set functions
+void tst_QListView::getSetCheck()
+{
+ QListView obj1;
+ // Movement QListView::movement()
+ // void QListView::setMovement(Movement)
+ obj1.setMovement(QListView::Movement(QListView::Static));
+ QCOMPARE(QListView::Movement(QListView::Static), obj1.movement());
+ obj1.setMovement(QListView::Movement(QListView::Free));
+ QCOMPARE(QListView::Movement(QListView::Free), obj1.movement());
+ obj1.setMovement(QListView::Movement(QListView::Snap));
+ QCOMPARE(QListView::Movement(QListView::Snap), obj1.movement());
+
+ // Flow QListView::flow()
+ // void QListView::setFlow(Flow)
+ obj1.setFlow(QListView::Flow(QListView::LeftToRight));
+ QCOMPARE(QListView::Flow(QListView::LeftToRight), obj1.flow());
+ obj1.setFlow(QListView::Flow(QListView::TopToBottom));
+ QCOMPARE(QListView::Flow(QListView::TopToBottom), obj1.flow());
+
+ // ResizeMode QListView::resizeMode()
+ // void QListView::setResizeMode(ResizeMode)
+ obj1.setResizeMode(QListView::ResizeMode(QListView::Fixed));
+ QCOMPARE(QListView::ResizeMode(QListView::Fixed), obj1.resizeMode());
+ obj1.setResizeMode(QListView::ResizeMode(QListView::Adjust));
+ QCOMPARE(QListView::ResizeMode(QListView::Adjust), obj1.resizeMode());
+
+ // LayoutMode QListView::layoutMode()
+ // void QListView::setLayoutMode(LayoutMode)
+ obj1.setLayoutMode(QListView::LayoutMode(QListView::SinglePass));
+ QCOMPARE(QListView::LayoutMode(QListView::SinglePass), obj1.layoutMode());
+ obj1.setLayoutMode(QListView::LayoutMode(QListView::Batched));
+ QCOMPARE(QListView::LayoutMode(QListView::Batched), obj1.layoutMode());
+
+ // int QListView::spacing()
+ // void QListView::setSpacing(int)
+ obj1.setSpacing(0);
+ QCOMPARE(0, obj1.spacing());
+ obj1.setSpacing(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.spacing());
+ obj1.setSpacing(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.spacing());
+
+ // ViewMode QListView::viewMode()
+ // void QListView::setViewMode(ViewMode)
+ obj1.setViewMode(QListView::ViewMode(QListView::ListMode));
+ QCOMPARE(QListView::ViewMode(QListView::ListMode), obj1.viewMode());
+ obj1.setViewMode(QListView::ViewMode(QListView::IconMode));
+ QCOMPARE(QListView::ViewMode(QListView::IconMode), obj1.viewMode());
+
+ // int QListView::modelColumn()
+ // void QListView::setModelColumn(int)
+ obj1.setModelColumn(0);
+ QCOMPARE(0, obj1.modelColumn());
+ obj1.setModelColumn(INT_MIN);
+ QCOMPARE(0, obj1.modelColumn()); // Less than 0 => 0
+ obj1.setModelColumn(INT_MAX);
+ QCOMPARE(0, obj1.modelColumn()); // No model => 0
+
+ // bool QListView::uniformItemSizes()
+ // void QListView::setUniformItemSizes(bool)
+ obj1.setUniformItemSizes(false);
+ QCOMPARE(false, obj1.uniformItemSizes());
+ obj1.setUniformItemSizes(true);
+ QCOMPARE(true, obj1.uniformItemSizes());
+
+ // make sure setViewMode() doesn't reset resizeMode
+ obj1.clearPropertyFlags();
+ obj1.setResizeMode(QListView::Adjust);
+ obj1.setViewMode(QListView::IconMode);
+ QCOMPARE(obj1.resizeMode(), QListView::Adjust);
+
+ obj1.setWordWrap(false);
+ QCOMPARE(false, obj1.wordWrap());
+ obj1.setWordWrap(true);
+ QCOMPARE(true, obj1. wordWrap());
+}
+
+class QtTestModel: public QAbstractListModel
+{
+public:
+ QtTestModel(QObject *parent = 0): QAbstractListModel(parent),
+ colCount(0), rCount(0), wrongIndex(false) {}
+ int rowCount(const QModelIndex&) const { return rCount; }
+ int columnCount(const QModelIndex&) const { return colCount; }
+ bool isEditable(const QModelIndex &) const { return true; }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+
+ if (!m_icon.isNull() && role == Qt::DecorationRole) {
+ return m_icon;
+ }
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (idx.row() < 0 || idx.column() < 0 || idx.column() >= colCount
+ || idx.row() >= rCount) {
+ wrongIndex = true;
+ qWarning("got invalid modelIndex %d/%d", idx.row(), idx.column());
+ }
+ return QString("%1/%2").arg(idx.row()).arg(idx.column());
+ }
+
+ void removeLastRow()
+ {
+ beginRemoveRows(QModelIndex(), rCount - 2, rCount - 1);
+ --rCount;
+ endRemoveRows();
+ }
+
+ void removeAllRows()
+ {
+ beginRemoveRows(QModelIndex(), 0, rCount - 1);
+ rCount = 0;
+ endRemoveRows();
+ }
+
+ void setDataIcon(const QIcon &icon)
+ {
+ m_icon = icon;
+ }
+
+ int colCount, rCount;
+ QIcon m_icon;
+ mutable bool wrongIndex;
+};
+
+tst_QListView::tst_QListView()
+{
+}
+
+tst_QListView::~tst_QListView()
+{
+}
+
+void tst_QListView::initTestCase()
+{
+}
+
+void tst_QListView::cleanupTestCase()
+{
+}
+
+void tst_QListView::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QListView::cleanup()
+{
+}
+
+
+void tst_QListView::noDelegate()
+{
+ QtTestModel model(0);
+ model.rCount = model.colCount = 10;
+ QListView view;
+ view.setModel(&model);
+ view.setItemDelegate(0);
+ view.show();
+}
+
+void tst_QListView::noModel()
+{
+ QListView view;
+ view.show();
+ view.setRowHidden(0, true);
+}
+
+void tst_QListView::emptyModel()
+{
+ QtTestModel model(0);
+ QListView view;
+ view.setModel(&model);
+ view.show();
+ QVERIFY(!model.wrongIndex);
+}
+
+void tst_QListView::removeRows()
+{
+ QtTestModel model(0);
+ model.rCount = model.colCount = 10;
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+
+ model.removeLastRow();
+ QVERIFY(!model.wrongIndex);
+
+ model.removeAllRows();
+ QVERIFY(!model.wrongIndex);
+}
+
+void tst_QListView::cursorMove()
+{
+ int rows = 6*6;
+ int columns = 6;
+
+ QStandardItemModel model(rows, columns);
+ QWidget topLevel;
+ QListView view(&topLevel);
+ view.setModel(&model);
+
+ for (int j = 0; j < columns; ++j) {
+ view.setModelColumn(j);
+ for (int i = 0; i < rows; ++i) {
+ QModelIndex index = model.index(i, j);
+ model.setData(index, QString("[%1,%2]").arg(i).arg(j));
+ view.setCurrentIndex(index);
+ QApplication::processEvents();
+ QCOMPARE(view.currentIndex(), index);
+ }
+ }
+
+ QSize cellsize(60, 25);
+ int gap = 1; // compensate for the scrollbars
+ int displayColumns = 6;
+
+ view.resize((displayColumns + gap) * cellsize.width(),
+ int((ceil(double(rows) / displayColumns) + gap) * cellsize.height()));
+ view.setResizeMode(QListView::Adjust);
+ view.setGridSize(cellsize);
+ view.setViewMode(QListView::IconMode);
+ view.doItemsLayout();
+ topLevel.show();
+
+ QVector<Qt::Key> keymoves;
+ keymoves << Qt::Key_Up << Qt::Key_Up << Qt::Key_Right << Qt::Key_Right << Qt::Key_Up
+ << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down << Qt::Key_Up
+ << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up
+ << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down;
+
+ int displayRow = rows / displayColumns - 1;
+ int displayColumn = displayColumns - (rows % displayColumns) - 1;
+
+ QApplication::instance()->processEvents();
+ for (int i = 0; i < keymoves.size(); ++i) {
+ Qt::Key key = keymoves.at(i);
+ QTest::keyClick(&view, key);
+ switch (key) {
+ case Qt::Key_Up:
+ displayRow = qMax(0, displayRow - 1);
+ break;
+ case Qt::Key_Down:
+ displayRow = qMin(rows / displayColumns - 1, displayRow + 1);
+ break;
+ case Qt::Key_Left:
+ displayColumn = qMax(0, displayColumn - 1);
+ break;
+ case Qt::Key_Right:
+ displayColumn = qMin(displayColumns-1, displayColumn + 1);
+ break;
+ default:
+ QVERIFY(false);
+ }
+
+ QApplication::instance()->processEvents();
+
+ int row = displayRow * displayColumns + displayColumn;
+ int column = columns - 1;
+ QModelIndex index = model.index(row, column);
+ QCOMPARE(view.currentIndex().row(), row);
+ QCOMPARE(view.currentIndex().column(), column);
+ QCOMPARE(view.currentIndex(), index);
+ }
+}
+
+void tst_QListView::hideRows()
+{
+ QtTestModel model(0);
+ model.rCount = model.colCount = 10;
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+
+ // hide then show
+ QVERIFY(!view.isRowHidden(2));
+ view.setRowHidden(2, true);
+ QVERIFY(view.isRowHidden(2));
+ view.setRowHidden(2, false);
+ QVERIFY(!view.isRowHidden(2));
+
+ // re show same row
+ QVERIFY(!view.isRowHidden(2));
+ view.setRowHidden(2, false);
+ QVERIFY(!view.isRowHidden(2));
+
+ // double hidding
+ QVERIFY(!view.isRowHidden(2));
+ view.setRowHidden(2, true);
+ QVERIFY(view.isRowHidden(2));
+ view.setRowHidden(2, true);
+ QVERIFY(view.isRowHidden(2));
+ view.setRowHidden(2, false);
+ QVERIFY(!view.isRowHidden(2));
+
+ // show in per-item mode, then hide the first row
+ view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+ QVERIFY(!view.isRowHidden(0));
+ view.setRowHidden(0, true);
+ QVERIFY(view.isRowHidden(0));
+ view.setRowHidden(0, false);
+ QVERIFY(!view.isRowHidden(0));
+
+ QStandardItemModel sim(0);
+ QStandardItem *root = new QStandardItem("Root row");
+ for (int i=0;i<5;i++)
+ root->appendRow(new QStandardItem(QString("Row %1").arg(i)));
+ sim.appendRow(root);
+ view.setModel(&sim);
+ view.setRootIndex(root->index());
+ QVERIFY(!view.isRowHidden(0));
+ view.setRowHidden(0, true);
+ QVERIFY(view.isRowHidden(0));
+ view.setRowHidden(0, false);
+ QVERIFY(!view.isRowHidden(0));
+}
+
+
+void tst_QListView::moveCursor()
+{
+ QtTestModel model(0);
+ model.rCount = model.colCount = 10;
+
+ QListView view;
+ view.setModel(&model);
+
+ QTest::keyClick(&view, Qt::Key_Down);
+
+ view.setModel(0);
+ view.setModel(&model);
+ view.setRowHidden(0, true);
+
+ QTest::keyClick(&view, Qt::Key_Down);
+ QCOMPARE(view.selectionModel()->currentIndex(), model.index(1, 0));
+}
+
+class QMoveCursorListView : public QListView
+{
+public:
+ QMoveCursorListView() : QListView() {}
+
+ enum CursorAction { MoveUp, MoveDown, MoveLeft, MoveRight,
+ MoveHome, MoveEnd, MovePageUp, MovePageDown,
+ MoveNext, MovePrevious };
+
+ QModelIndex moveCursor(QMoveCursorListView::CursorAction action, Qt::KeyboardModifiers modifiers)
+ {
+ return QListView::moveCursor((QListView::CursorAction)action, modifiers);
+ }
+};
+
+void tst_QListView::moveCursor2()
+{
+ QtTestModel model(0);
+ model.colCount = 1;
+ model.rCount = 100;
+ QPixmap pm(32, 32);
+ pm.fill(Qt::green);
+ model.setDataIcon(QIcon(pm));
+
+ QMoveCursorListView vu;
+ vu.setModel(&model);
+ vu.setIconSize(QSize(36,48));
+ vu.setGridSize(QSize(34,56));
+ //Standard framesize is 1. If Framesize > 2 increase size
+ int frameSize = qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ vu.resize(300 + frameSize * 2,300);
+ vu.setFlow(QListView::LeftToRight);
+ vu.setMovement(QListView::Static);
+ vu.setWrapping(true);
+ vu.setViewMode(QListView::IconMode);
+ vu.setLayoutMode(QListView::Batched);
+ vu.show();
+ vu.selectionModel()->setCurrentIndex(model.index(0,0), QItemSelectionModel::SelectCurrent);
+ QCoreApplication::processEvents();
+
+ QModelIndex idx = vu.moveCursor(QMoveCursorListView::MoveHome, Qt::NoModifier);
+ QCOMPARE(idx, model.index(0,0));
+ idx = vu.moveCursor(QMoveCursorListView::MoveDown, Qt::NoModifier);
+ QCOMPARE(idx, model.index(8,0));
+}
+
+void tst_QListView::moveCursor3()
+{
+ //this tests is for task 159792
+ //it tests that navigation works even with non uniform item sizes
+ QListView view;
+ QStandardItemModel model(0, 1);
+ QStandardItem *i1 = new QStandardItem("First item, long name");
+ QStandardItem *i2 = new QStandardItem("2nd item");
+ QStandardItem *i3 = new QStandardItem("Third item, long name");
+ i1->setSizeHint(QSize(200,32));
+ model.appendRow(i1);
+ model.appendRow(i2);
+ model.appendRow(i3);
+ view.setModel(&model);
+
+ view.setCurrentIndex(model.index(0, 0));
+
+ QCOMPARE(view.selectionModel()->currentIndex(), model.index(0, 0));
+ QTest::keyClick(&view, Qt::Key_Down);
+ QCOMPARE(view.selectionModel()->currentIndex(), model.index(1, 0));
+ QTest::keyClick(&view, Qt::Key_Down);
+ QCOMPARE(view.selectionModel()->currentIndex(), model.index(2, 0));
+ QTest::keyClick(&view, Qt::Key_Up);
+ QCOMPARE(view.selectionModel()->currentIndex(), model.index(1, 0));
+ QTest::keyClick(&view, Qt::Key_Up);
+ QCOMPARE(view.selectionModel()->currentIndex(), model.index(0, 0));
+}
+
+
+class QListViewShowEventListener : public QListView
+{
+public:
+ QListViewShowEventListener() : QListView() { m_shown = false;}
+
+ virtual void showEvent(QShowEvent * /*e*/)
+ {
+ int columnwidth = sizeHintForColumn(0);
+ QSize sz = sizeHintForIndex(model()->index(0,0));
+
+ // This should retrieve a model index in the 2nd section
+ m_index = indexAt(QPoint(columnwidth +2, sz.height()/2));
+ m_shown = true;
+ }
+
+ QModelIndex m_index;
+ bool m_shown;
+
+};
+
+void tst_QListView::indexAt()
+{
+ QtTestModel model(0);
+ model.rCount = 2;
+ model.colCount = 1;
+
+ QListView view;
+ view.setModel(&model);
+ view.setViewMode(QListView::ListMode);
+ view.setFlow(QListView::TopToBottom);
+
+ QSize sz = view.sizeHintForIndex(model.index(0,0));
+ QModelIndex index;
+ index = view.indexAt(QPoint(20,0));
+ QVERIFY(index.isValid());
+ QCOMPARE(index.row(), 0);
+
+ index = view.indexAt(QPoint(20,sz.height()));
+ QVERIFY(index.isValid());
+ QCOMPARE(index.row(), 1);
+
+ index = view.indexAt(QPoint(20,2 * sz.height()));
+ QVERIFY(!index.isValid());
+
+ // Check when peeking out of the viewport bounds
+ index = view.indexAt(QPoint(view.viewport()->rect().width(), 0));
+ QVERIFY(!index.isValid());
+ index = view.indexAt(QPoint(-1, 0));
+ QVERIFY(!index.isValid());
+ index = view.indexAt(QPoint(20, view.viewport()->rect().height()));
+ QVERIFY(!index.isValid());
+ index = view.indexAt(QPoint(20, -1));
+ QVERIFY(!index.isValid());
+
+ model.rCount = 30;
+ QListViewShowEventListener view2;
+ // Set the height to a small enough value so that it wraps to a new section.
+ view2.resize(300,100);
+ view2.setModel(&model);
+ view2.setFlow(QListView::TopToBottom);
+ view2.setViewMode(QListView::ListMode);
+ view2.setWrapping(true);
+ // We really want to make sure it is shown, because the layout won't be known until it is shown
+ view2.show();
+ QTest::qWaitForWindowShown(&view2);
+ QTRY_VERIFY(view2.m_shown);
+
+ QVERIFY(view2.m_index.isValid());
+ QVERIFY(view2.m_index.row() != 0);
+}
+
+void tst_QListView::clicked()
+{
+ QtTestModel model;
+ model.rCount = 10;
+ model.colCount = 2;
+
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+
+ QListView view;
+ view.setModel(&model);
+
+ view.show();
+ QApplication::processEvents();
+
+ QModelIndex firstIndex = model.index(0, 0, QModelIndex());
+ QVERIFY(firstIndex.isValid());
+ int itemHeight = view.visualRect(firstIndex).height();
+ view.resize(200, itemHeight * (model.rCount + 1));
+
+ for (int i = 0; i < model.rCount; ++i) {
+ QPoint p(5, 1 + itemHeight * i);
+ QModelIndex index = view.indexAt(p);
+ if (!index.isValid())
+ continue;
+ QSignalSpy spy(&view, SIGNAL(clicked(const QModelIndex&)));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(spy.count(), 1);
+ }
+}
+
+void tst_QListView::singleSelectionRemoveRow()
+{
+ QStringList items;
+ items << "item1" << "item2" << "item3" << "item4";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex index;
+ view.setCurrentIndex(model.index(1));
+ index = view.currentIndex();
+ QCOMPARE(view.model()->data(index).toString(), QString("item2"));
+
+ model.removeRow(1);
+ index = view.currentIndex();
+ QCOMPARE(view.model()->data(index).toString(), QString("item3"));
+
+ model.removeRow(0);
+ index = view.currentIndex();
+ QCOMPARE(view.model()->data(index).toString(), QString("item3"));
+}
+
+void tst_QListView::singleSelectionRemoveColumn()
+{
+ int numCols = 3;
+ int numRows = 3;
+ QStandardItemModel model(numCols, numRows);
+ for (int r = 0; r < numRows; ++r)
+ for (int c = 0; c < numCols; ++c)
+ model.setData(model.index(r, c), QString("%1,%2").arg(r).arg(c));
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex index;
+ view.setCurrentIndex(model.index(1, 1));
+ index = view.currentIndex();
+ QCOMPARE(view.model()->data(index).toString(), QString("1,1"));
+
+ model.removeColumn(1);
+ index = view.currentIndex();
+ QCOMPARE(view.model()->data(index).toString(), QString("1,0"));
+
+ model.removeColumn(0);
+ index = view.currentIndex();
+ QCOMPARE(view.model()->data(index).toString(), QString("1,2"));
+}
+
+void tst_QListView::modelColumn()
+{
+ int numCols = 3;
+ int numRows = 3;
+ QStandardItemModel model(numCols, numRows);
+ for (int r = 0; r < numRows; ++r)
+ for (int c = 0; c < numCols; ++c)
+ model.setData(model.index(r, c), QString("%1,%2").arg(r).arg(c));
+
+
+ QListView view;
+ view.setModel(&model);
+
+
+ //
+ // Set and get with a valid model
+ //
+
+ // Default is column 0
+ QCOMPARE(view.modelColumn(), 0);
+
+ view.setModelColumn(0);
+ QCOMPARE(view.modelColumn(), 0);
+ view.setModelColumn(1);
+ QCOMPARE(view.modelColumn(), 1);
+ view.setModelColumn(2);
+ QCOMPARE(view.modelColumn(), 2);
+
+ // Out of bound cases should not modify the modelColumn
+ view.setModelColumn(-1);
+ QCOMPARE(view.modelColumn(), 2);
+ view.setModelColumn(INT_MAX);
+ QCOMPARE(view.modelColumn(), 2);
+
+
+ // See if it displays the right column using indexAt()...
+ view.resize(400,400);
+ view.show();
+
+ for (int c = 0; c < 3; ++c) {
+ view.setModelColumn(c);
+ int startrow = 0;
+ for (int y = 0; y < view.height(); ++y) {
+ QModelIndex idx = view.indexAt( QPoint(1, y) );
+ if (idx.row() == startrow + 1) ++startrow;
+ else if (idx.row() == -1) break;
+ QCOMPARE(idx.row(), startrow);
+ QCOMPARE(idx.column(), c);
+ }
+ QCOMPARE(startrow, 2);
+ }
+}
+
+void tst_QListView::hideFirstRow()
+{
+ QStringList items;
+ for (int i=0; i <100; ++i)
+ items << "item";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setModel(&model);
+ view.setUniformItemSizes(true);
+ view.setRowHidden(0,true);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(10);
+}
+
+void tst_QListView::batchedMode()
+{
+ QStringList items;
+ for (int i=0; i <3; ++i)
+ items << "item";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setModel(&model);
+ view.setUniformItemSizes(true);
+ view.setViewMode(QListView::ListMode);
+ view.setLayoutMode(QListView::Batched);
+ view.setBatchSize(2);
+ view.resize(200,400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(100);
+
+#if defined(Q_OS_WINCE)
+ QTest::qWait(2000);
+#endif
+ QBitArray ba;
+ for (int y = 0; y < view.height(); ++y) {
+ QModelIndex idx = view.indexAt( QPoint(1, y) );
+ if (!idx.isValid())
+ break;
+ if (idx.row() >= ba.size())
+ ba.resize(idx.row() + 1);
+ ba.setBit(idx.row(), true);
+ }
+ QCOMPARE(ba.size(), 3);
+
+
+ // Test the dynamic listview too.
+ view.setViewMode(QListView::IconMode);
+ view.setLayoutMode(QListView::Batched);
+ view.setFlow(QListView::TopToBottom);
+ view.setBatchSize(2);
+
+#if !defined(Q_OS_WINCE)
+ QTest::qWait(100);
+#else
+ QTest::qWait(2000);
+#endif
+
+ ba.clear();
+ for (int y = 0; y < view.height(); ++y) {
+ QModelIndex idx = view.indexAt( QPoint(1, y) );
+ if (!idx.isValid())
+ break;
+ if (idx.row() >= ba.size())
+ ba.resize(idx.row() + 1);
+ ba.setBit(idx.row(), true);
+ }
+ QCOMPARE(ba.size(), 3);
+}
+
+void tst_QListView::setCurrentIndex()
+{
+ QStringList items;
+ int i;
+ for (i=0; i <20; ++i)
+ items << QString("item %1").arg(i);
+ QStringListModel model(items);
+
+ QListView view;
+ view.setModel(&model);
+
+ view.resize(220,182);
+ view.show();
+
+ for (int pass = 0; pass < 2; ++pass) {
+ view.setFlow(pass == 0 ? QListView::TopToBottom : QListView::LeftToRight);
+ QScrollBar *sb = pass == 0 ? view.verticalScrollBar() : view.horizontalScrollBar();
+ QList<QSize> gridsizes;
+ gridsizes << QSize() << QSize(200,38);
+ for (int ig = 0; ig < gridsizes.count(); ++ig) {
+ if (pass == 1 && !gridsizes.at(ig).isValid()) // the width of an item varies, so it might jump two times
+ continue;
+ view.setGridSize(gridsizes.at(ig));
+
+ qApp->processEvents();
+ int offset = sb->value();
+
+ // first "scroll" down, verify that we scroll one step at a time
+ i = 0;
+ for (i = 0; i < 20; ++i) {
+ QModelIndex idx = model.index(i,0);
+ view.setCurrentIndex(idx);
+ if (offset != sb->value()) {
+ // If it has scrolled, it should have scrolled only by one.
+ QCOMPARE(sb->value(), offset + 1);
+ ++offset;
+ }
+ //QTest::qWait(50);
+ }
+
+ --i; // item 20 does not exist
+ // and then "scroll" up, verify that we scroll one step at a time
+ for (; i >= 0; --i) {
+ QModelIndex idx = model.index(i,0);
+ view.setCurrentIndex(idx);
+ if (offset != sb->value()) {
+ // If it has scrolled, it should have scrolled only by one.
+ QCOMPARE(sb->value(), offset - 1);
+ --offset;
+ }
+ //QTest::qWait(50);
+ }
+ }
+ }
+}
+
+class PublicListView : public QListView
+{
+ public:
+ PublicListView(QWidget *parent = 0) : QListView(parent)
+ {
+
+ }
+ void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) {
+ QListView::setSelection(rect, flags);
+ }
+ QSize contentsSize() const { return QListView::contentsSize(); }
+
+ void setPositionForIndex(const QPoint &pos, const QModelIndex &index) {
+ QListView::setPositionForIndex(pos, index);
+ }
+};
+
+class TestDelegate : public QItemDelegate
+{
+public:
+ TestDelegate(QObject *parent) : QItemDelegate(parent), m_sizeHint(50,50) {}
+ QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return m_sizeHint; }
+
+ QSize m_sizeHint;
+};
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+void tst_QListView::selection_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("viewMode");
+ QTest::addColumn<int>("flow");
+ QTest::addColumn<bool>("wrapping");
+ QTest::addColumn<int>("spacing");
+ QTest::addColumn<QSize>("gridSize");
+ QTest::addColumn<IntList>("hiddenRows");
+ QTest::addColumn<QRect>("selectionRect");
+ QTest::addColumn<IntList>("expectedItems");
+
+ QTest::newRow("select all")
+ << 4 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << false // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(0, 0, 10, 200) // selection rectangle
+ << (IntList() << 0 << 1 << 2 << 3); // expected items
+
+ QTest::newRow("select below, (on viewport)")
+ << 4 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << false // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(10, 250, 1, 1) // selection rectangle
+ << IntList(); // expected items
+
+ QTest::newRow("select below 2, (on viewport)")
+ << 4 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(10, 250, 1, 1) // selection rectangle
+ << IntList(); // expected items
+
+ QTest::newRow("select to the right, (on viewport)")
+ << 40 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(300, 10, 1, 1) // selection rectangle
+ << IntList(); // expected items
+
+ QTest::newRow("select to the right, (on viewport)")
+ << 40 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(300, 0, 1, 300) // selection rectangle
+ << IntList(); // expected items
+
+#if defined(Q_OS_WINCE)
+ // depending on whether the display is double-pixeld, we need
+ // to click at a different position
+ bool doubledSize = false;
+ int dpi = GetDeviceCaps(GetDC(0), LOGPIXELSX);
+ if ((dpi < 1000) && (dpi > 0)) {
+ doubledSize = true;
+ }
+ QTest::newRow("select inside contents, (on viewport)")
+ << 35 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(doubledSize?350:175,doubledSize?550:275, 1, 1)// selection rectangle
+ << IntList(); // expected items
+#else
+ QTest::newRow("select inside contents, (on viewport)")
+ << 35 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(175, 275, 1, 1) // selection rectangle
+ << IntList(); // expected items
+#endif
+
+ QTest::newRow("select a tall rect in LeftToRight flow, wrap items")
+ << 70 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::LeftToRight)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(90, 90, 1, 100) // selection rectangle
+ << (IntList() // expected items
+ << 11 << 12 << 13 << 14 << 15 << 16 << 17 << 18 << 19
+ << 20 << 21 << 22 << 23 << 24 << 25 << 26 << 27 << 28 << 29
+ << 30 << 31);
+
+ QTest::newRow("select a wide rect in LeftToRight, wrap items")
+ << 70 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::LeftToRight)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(90, 90, 200, 1) // selection rectangle
+ << (IntList() // expected items
+ << 11 << 12 << 13 << 14 << 15);
+
+ QTest::newRow("select a wide negative rect in LeftToRight flow, wrap items")
+ << 70 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::LeftToRight)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(290, 90, -200, 1) // selection rectangle
+ << (IntList() // expected items
+ << 11 << 12 << 13 << 14 << 15);
+
+ QTest::newRow("select a tall rect in TopToBottom flow, wrap items")
+ << 70 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(90, 90, 1, 100) // selection rectangle
+ << (IntList() // expected items
+ << 11
+ << 12
+ << 13);
+
+ QTest::newRow("select a tall negative rect in TopToBottom flow, wrap items")
+ << 70 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(90, 190, 1, -100) // selection rectangle
+ << (IntList() // expected items
+ << 11
+ << 12
+ << 13);
+
+ QTest::newRow("select a wide rect in TopToBottom, wrap items")
+ << 70 // itemCount
+ << int(QListView::ListMode)
+ << int(QListView::TopToBottom)
+ << true // wrapping
+ << 0 // spacing
+ << QSize() // gridSize
+ << IntList() // hiddenRows
+ << QRect(90, 90, 100, 1) // selection rectangle
+ << (IntList() // expected items
+ << 20 << 30
+ << 11 << 21 << 31
+ << 12 << 22
+ << 13 << 23
+ << 14 << 24
+ << 15 << 25
+ << 16 << 26
+ << 17 << 27
+ << 18 << 28
+ << 19 << 29);
+}
+
+void tst_QListView::selection()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, viewMode);
+ QFETCH(int, flow);
+ QFETCH(bool, wrapping);
+ QFETCH(int, spacing);
+ QFETCH(QSize, gridSize);
+ QFETCH(IntList, hiddenRows);
+ QFETCH(QRect, selectionRect);
+ QFETCH(IntList, expectedItems);
+
+ QWidget topLevel;
+ PublicListView v(&topLevel);
+ QtTestModel model;
+ model.colCount = 1;
+ model.rCount = itemCount;
+
+ // avoid scrollbar size mismatches among different styles
+ v.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ v.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ v.setItemDelegate(new TestDelegate(&v));
+ v.setModel(&model);
+ v.setViewMode(QListView::ViewMode(viewMode));
+ v.setFlow(QListView::Flow(flow));
+ v.setWrapping(wrapping);
+ v.setResizeMode(QListView::Adjust);
+ v.setSpacing(spacing);
+ if (gridSize.isValid())
+ v.setGridSize(gridSize);
+ for (int j = 0; j < hiddenRows.count(); ++j) {
+ v.setRowHidden(hiddenRows.at(j), true);
+ }
+
+#if defined(Q_OS_WINCE)
+ // If the device is double-pixeled then the scrollbars become
+ // 10 pixels wider than normal (Windows Style: 16, Windows Mobile Style: 26).
+ // So we have to make the window slightly bigger to have the same count of
+ // items in each row of the list view like in the other styles.
+ static const int dpi = ::GetDeviceCaps(GetDC(0), LOGPIXELSX);
+ if ((dpi < 1000) && (dpi > 0))
+ v.resize(535,535);
+#else
+ v.resize(525,525);
+#endif
+
+ topLevel.show();
+ QTest::qWaitForWindowShown(&v);
+ QApplication::processEvents();
+
+ v.setSelection(selectionRect, QItemSelectionModel::ClearAndSelect);
+
+ QModelIndexList selected = v.selectionModel()->selectedIndexes();
+
+ QCOMPARE(selected.count(), expectedItems.count());
+ for (int i = 0; i < selected.count(); ++i) {
+ QVERIFY(expectedItems.contains(selected.at(i).row()));
+ }
+}
+
+void tst_QListView::scrollTo()
+{
+ QWidget topLevel;
+ QListView lv(&topLevel);
+ QStringListModel model(&lv);
+ QStringList list;
+ list << "Short item 1";
+ list << "Short item 2";
+ list << "Short item 3";
+ list << "Short item 4";
+ list << "Short item 5";
+ list << "Short item 6";
+ list << "Begin This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\n"
+ "This is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item\nThis is a very long item End\n";
+ list << "Short item";
+ list << "Short item";
+ list << "Short item";
+ list << "Short item";
+ list << "Short item";
+ list << "Short item";
+ list << "Short item";
+ list << "Short item";
+ model.setStringList(list);
+ lv.setModel(&model);
+ lv.setFixedSize(100, 200);
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+
+ //by default, the list view scrolls per item and has no wrapping
+ QModelIndex index = model.index(6,0);
+
+ //we save the size of the item for later comparisons
+ const QSize itemsize = lv.visualRect(index).size();
+ QVERIFY(itemsize.height() > lv.height());
+ QVERIFY(itemsize.width() > lv.width());
+
+ //we click the item
+ QPoint p = lv.visualRect(index).center();
+ QTest::mouseClick(lv.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ //let's wait because the scrolling is delayed
+ QTest::qWait(QApplication::doubleClickInterval() + 150);
+ QTRY_COMPARE(lv.visualRect(index).y(),0);
+
+ //we scroll down. As the item is to tall for the view, it will disappear
+ QTest::keyClick(lv.viewport(), Qt::Key_Down, Qt::NoModifier);
+ QCOMPARE(lv.visualRect(index).y(), -itemsize.height());
+
+ QTest::keyClick(lv.viewport(), Qt::Key_Up, Qt::NoModifier);
+ QCOMPARE(lv.visualRect(index).y(), 0);
+
+ //Let's enable wrapping
+
+ lv.setWrapping(true);
+ lv.horizontalScrollBar()->setValue(0); //let's scroll to the beginning
+
+ //we click the item
+ p = lv.visualRect(index).center();
+ QTest::mouseClick(lv.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ //let's wait because the scrolling is delayed
+ QTest::qWait(QApplication::doubleClickInterval() + 150);
+ QTRY_COMPARE(lv.visualRect(index).x(),0);
+
+ //we scroll right. As the item is too wide for the view, it will disappear
+ QTest::keyClick(lv.viewport(), Qt::Key_Right, Qt::NoModifier);
+ QCOMPARE(lv.visualRect(index).x(), -itemsize.width());
+
+ QTest::keyClick(lv.viewport(), Qt::Key_Left, Qt::NoModifier);
+ QCOMPARE(lv.visualRect(index).x(), 0);
+
+ lv.setWrapping(false);
+ qApp->processEvents(); //let the layout happen
+
+ //Let's try with scrolling per pixel
+ lv.setHorizontalScrollMode( QListView::ScrollPerPixel);
+ lv.verticalScrollBar()->setValue(0); //scrolls back to the first item
+
+ //we click the item
+ p = lv.visualRect(index).center();
+ QTest::mouseClick(lv.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ //let's wait because the scrolling is delayed
+ QTest::qWait(QApplication::doubleClickInterval() + 150);
+ QTRY_COMPARE(lv.visualRect(index).y(),0);
+
+ //we scroll down. As the item is too tall for the view, it will partially disappear
+ QTest::keyClick(lv.viewport(), Qt::Key_Down, Qt::NoModifier);
+ QVERIFY(lv.visualRect(index).y()<0);
+
+ QTest::keyClick(lv.viewport(), Qt::Key_Up, Qt::NoModifier);
+ QCOMPARE(lv.visualRect(index).y(), 0);
+}
+
+
+void tst_QListView::scrollBarRanges()
+{
+ const int rowCount = 10;
+ const int rowHeight = 20;
+
+ QWidget topLevel;
+ QListView lv(&topLevel);
+ QStringListModel model(&lv);
+ QStringList list;
+ for (int i = 0; i < rowCount; ++i)
+ list << QString::fromAscii("Item %1").arg(i);
+
+ model.setStringList(list);
+ lv.setModel(&model);
+ lv.resize(250, 130);
+ TestDelegate *delegate = new TestDelegate(&lv);
+ delegate->m_sizeHint = QSize(100, rowHeight);
+ lv.setItemDelegate(delegate);
+ topLevel.show();
+
+ for (int h = 30; h <= 210; ++h) {
+ lv.resize(250, h);
+ QApplication::processEvents(); // wait for the layout to be done
+ int visibleRowCount = lv.viewport()->size().height() / rowHeight;
+ int invisibleRowCount = rowCount - visibleRowCount;
+ QCOMPARE(lv.verticalScrollBar()->maximum(), invisibleRowCount);
+ }
+}
+
+void tst_QListView::scrollBarAsNeeded_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("flow");
+ QTest::addColumn<bool>("horizontalScrollBarVisible");
+ QTest::addColumn<bool>("verticalScrollBarVisible");
+
+
+ QTest::newRow("TopToBottom, count:0")
+ << QSize(200, 100)
+ << 0
+ << int(QListView::TopToBottom)
+ << false
+ << false;
+
+ QTest::newRow("TopToBottom, count:1")
+ << QSize(200, 100)
+ << 1
+ << int(QListView::TopToBottom)
+ << false
+ << false;
+
+ QTest::newRow("TopToBottom, count:20")
+ << QSize(200, 100)
+ << 20
+ << int(QListView::TopToBottom)
+ << false
+ << true;
+
+ QTest::newRow("LeftToRight, count:0")
+ << QSize(200, 100)
+ << 0
+ << int(QListView::LeftToRight)
+ << false
+ << false;
+
+ QTest::newRow("LeftToRight, count:1")
+ << QSize(200, 100)
+ << 1
+ << int(QListView::LeftToRight)
+ << false
+ << false;
+
+ QTest::newRow("LeftToRight, count:20")
+ << QSize(200, 100)
+ << 20
+ << int(QListView::LeftToRight)
+ << true
+ << false;
+
+
+}
+void tst_QListView::scrollBarAsNeeded()
+{
+
+ QFETCH(QSize, size);
+ QFETCH(int, itemCount);
+ QFETCH(int, flow);
+ QFETCH(bool, horizontalScrollBarVisible);
+ QFETCH(bool, verticalScrollBarVisible);
+
+
+ const int rowCounts[3] = {0, 1, 20};
+
+ QWidget topLevel;
+ QListView lv(&topLevel);
+ lv.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ lv.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ lv.setFlow((QListView::Flow)flow);
+ QStringListModel model(&lv);
+ lv.setModel(&model);
+ lv.resize(size);
+ topLevel.show();
+
+ for (uint r = 0; r < sizeof(rowCounts)/sizeof(int); ++r) {
+ QStringList list;
+ int i;
+ for (i = 0; i < rowCounts[r]; ++i)
+ list << QString::fromAscii("Item %1").arg(i);
+
+ model.setStringList(list);
+ QApplication::processEvents();
+ QTest::qWait(50);
+
+ QStringList replacement;
+ for (i = 0; i < itemCount; ++i) {
+ replacement << QString::fromAscii("Item %1").arg(i);
+ }
+ model.setStringList(replacement);
+
+ QApplication::processEvents();
+
+ QTRY_COMPARE(lv.horizontalScrollBar()->isVisible(), horizontalScrollBarVisible);
+ QTRY_COMPARE(lv.verticalScrollBar()->isVisible(), verticalScrollBarVisible);
+ }
+}
+
+void tst_QListView::moveItems()
+{
+ QStandardItemModel model;
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ QStandardItem* item = new QStandardItem(QString("standard item (%1,%2)").arg(r).arg(c));
+ model.setItem(r, c, item);
+ }
+ }
+
+ PublicListView view;
+ view.setViewMode(QListView::IconMode);
+ view.setResizeMode(QListView::Fixed);
+ view.setWordWrap(true);
+ view.setModel(&model);
+ view.setItemDelegate(new TestDelegate(&view));
+
+ for (int r = 0; r < model.rowCount(); ++r) {
+ for (int c = 0; c < model.columnCount(); ++c) {
+ const QModelIndex& idx = model.index(r, c);
+ view.setPositionForIndex(QPoint(r * 75, r * 75), idx);
+ }
+ }
+
+ QCOMPARE(view.contentsSize(), QSize(275, 275));
+}
+
+void tst_QListView::wordWrap()
+{
+ QListView lv;
+ lv.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ lv.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ QStringListModel model(&lv);
+ QStringList list;
+ list << "Short item 1";
+ list << "Short item 2";
+ list << "Short item 3";
+ list << "Begin\nThis item take severals Lines\nEnd";
+ list << "And this is a very long item very long item this is a very vary vary long item"
+ "very long very very long long long this is a long item a very long item a very very long item";
+ list << "And this is a second even a little more long very long item very long item this is a very vary vary long item"
+ "very long very very long long long this is a long item a very long item a very very long item";
+ list << "Short item";
+ list << "rzeofig zerig fslfgj smdlfkgj qmsdlfj amrzriougf qsla zrg fgsdf gsdfg sdfgs dfg sdfgcvb sdfg qsdjfh qsdfjklh qs";
+ list << "Short item";
+ model.setStringList(list);
+ lv.setModel(&model);
+ lv.setWordWrap(true);
+ lv.setFixedSize(150, 150);
+ lv.show();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(lv.horizontalScrollBar()->isVisible(), false);
+ QTRY_COMPARE(lv.verticalScrollBar()->isVisible(), true);
+}
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+class SetCurrentIndexAfterAppendRowCrashDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ SetCurrentIndexAfterAppendRowCrashDialog()
+ {
+#if WINVER >= 0x0500
+ listView = new QListView();
+ listView->setViewMode(QListView::IconMode);
+
+ model = new QStandardItemModel(this);
+ listView->setModel(model);
+
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(buttonClicked()));
+ timer->start(1000);
+
+ DWORD lParam = 0xFFFFFFFC/*OBJID_CLIENT*/;
+ DWORD wParam = 0;
+ if (const HWND hwnd =getHWNDForWidget(this))
+ SendMessage(hwnd, WM_GETOBJECT, wParam, lParam);
+#endif
+ }
+
+private slots:
+ void buttonClicked()
+ {
+ timer->stop();
+ QStandardItem *item = new QStandardItem("test");
+ model->appendRow(item);
+ listView->setCurrentIndex(model->indexFromItem(item));
+ close();
+ }
+private:
+ QListView *listView;
+ QStandardItemModel *model;
+ QTimer *timer;
+};
+#endif
+
+// This test only makes sense on Windows 2000 and higher.
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && WINVER >= 0x0500
+void tst_QListView::setCurrentIndexAfterAppendRowCrash()
+{
+ SetCurrentIndexAfterAppendRowCrashDialog w;
+ w.exec();
+}
+#endif
+
+void tst_QListView::emptyItemSize()
+{
+ QStandardItemModel model;
+ for (int r = 0; r < 4; ++r) {
+ QStandardItem* item = new QStandardItem(QString("standard item (%1)").arg(r));
+ model.setItem(r, 0, item);
+ }
+ model.setItem(4, 0, new QStandardItem());
+
+ PublicListView view;
+ view.setModel(&model);
+
+ for (int i = 0; i < 5; ++i)
+ QVERIFY(!view.visualRect(model.index(i, 0)).isEmpty());
+}
+
+void tst_QListView::task203585_selectAll()
+{
+ //we make sure that "select all" doesn't select the hidden items
+ QListView view;
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.setModel(new QStringListModel( QStringList() << "foo"));
+ view.setRowHidden(0, true);
+ view.selectAll();
+ QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
+ view.setRowHidden(0, false);
+ view.selectAll();
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1);
+}
+
+void tst_QListView::task228566_infiniteRelayout()
+{
+ QListView view;
+
+ QStringList list;
+ for (int i = 0; i < 10; ++i) {
+ list << "small";
+ }
+
+ list << "BIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIG";
+ list << "BIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIG";
+
+ QStringListModel model(list);
+ view.setModel(&model);
+ view.setWrapping(true);
+ view.setResizeMode(QListView::Adjust);
+
+ const int itemHeight = view.visualRect( model.index(0, 0)).height();
+
+ view.setFixedHeight(itemHeight * 12);
+ view.show();
+ QTest::qWait(100); //make sure the layout is done once
+
+ QSignalSpy spy(view.horizontalScrollBar(), SIGNAL(rangeChanged(int, int)));
+
+ QTest::qWait(200);
+ //the layout should already have been done
+ //so there should be no change made to the scrollbar
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QListView::task248430_crashWith0SizedItem()
+{
+ QListView view;
+ view.setViewMode(QListView::IconMode);
+ QStringListModel model(QStringList() << QLatin1String("item1") << QString());
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+}
+
+void tst_QListView::task250446_scrollChanged()
+{
+ QStandardItemModel model(200, 1);
+ QListView view;
+ view.setModel(&model);
+ QModelIndex index = model.index(0, 0);
+ QVERIFY(index.isValid());
+ view.setCurrentIndex(index);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ const int scrollValue = view.verticalScrollBar()->maximum();
+ view.verticalScrollBar()->setValue(scrollValue);
+ QCOMPARE(view.verticalScrollBar()->value(), scrollValue);
+ QCOMPARE(view.currentIndex(), index);
+
+ view.showMinimized();
+ QTest::qWait(50);
+ QTRY_COMPARE(view.verticalScrollBar()->value(), scrollValue);
+ QTRY_COMPARE(view.currentIndex(), index);
+
+ view.showNormal();
+ QTest::qWait(50);
+ QTRY_COMPARE(view.verticalScrollBar()->value(), scrollValue);
+ QTRY_COMPARE(view.currentIndex(), index);
+}
+
+void tst_QListView::task196118_visualRegionForSelection()
+{
+ class MyListView : public QListView
+ {
+ public:
+ QRegion visualRegionForSelection() const
+ { return QListView::visualRegionForSelection( selectionModel()->selection()); }
+ } view;
+
+ QStandardItemModel model;
+ QStandardItem top1("top1");
+ QStandardItem sub1("sub1");
+ top1.appendRow(QList<QStandardItem*>() << &sub1);
+ model.appendColumn(QList<QStandardItem*>() << &top1);
+ view.setModel(&model);
+ view.setRootIndex(top1.index());
+
+ view.selectionModel()->select(top1.index(), QItemSelectionModel::Select);
+
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1);
+ QVERIFY(view.visualRegionForSelection().isEmpty());
+}
+
+void tst_QListView::task254449_draggingItemToNegativeCoordinates()
+{
+ //we'll check that the items are painted correctly
+ class MyListView : public QListView
+ {
+ public:
+ void setPositionForIndex(const QPoint &position, const QModelIndex &index)
+ { QListView::setPositionForIndex(position, index); }
+
+ } list;
+
+ QStandardItemModel model(1,1);
+ QModelIndex index = model.index(0,0);
+ model.setData(index, QLatin1String("foo"));
+ list.setModel(&model);
+ list.setViewMode(QListView::IconMode);
+ list.show();
+ QTest::qWaitForWindowShown(&list);
+ list.activateWindow();
+
+ class MyItemDelegate : public QStyledItemDelegate
+ {
+ public:
+ MyItemDelegate() : numPaints(0) { }
+ void paint(QPainter *painter,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ numPaints++;
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+
+ mutable int numPaints;
+ } delegate;
+ delegate.numPaints = 0;
+ list.setItemDelegate(&delegate);
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.numPaints > 0); //makes sure the layout is done
+
+ const QPoint topLeft(-6, 0);
+ list.setPositionForIndex(topLeft, index);
+
+ //we'll make sure the item is repainted
+ delegate.numPaints = 0;
+ QApplication::processEvents();
+ QTRY_COMPARE(delegate.numPaints, 1);
+ QCOMPARE(list.visualRect(index).topLeft(), topLeft);
+}
+
+
+void tst_QListView::keyboardSearch()
+{
+ QStringList items;
+ items << "AB" << "AC" << "BA" << "BB" << "BD" << "KAFEINE" << "KONQUEROR" << "KOPETE" << "KOOKA" << "OKULAR";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(30);
+// QCOMPARE(view.currentIndex() , model.index(0,0));
+
+ QTest::keyClick(&view, Qt::Key_K);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex() , model.index(5,0)); //KAFEINE
+
+ QTest::keyClick(&view, Qt::Key_O);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex() , model.index(6,0)); //KONQUEROR
+
+ QTest::keyClick(&view, Qt::Key_N);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex() , model.index(6,0)); //KONQUEROR
+}
+
+void tst_QListView::shiftSelectionWithNonUniformItemSizes()
+{
+ // This checks that no items are selected unexpectedly by Shift-Arrow
+ // when items with non-uniform sizes are laid out in a grid
+ { // First test: QListView::LeftToRight flow
+ QStringList items;
+ items << "Long\nText" << "Text" << "Text" << "Text";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setFixedSize(250, 250);
+ view.setFlow(QListView::LeftToRight);
+ view.setGridSize(QSize(100, 100));
+ view.setSelectionMode(QListView::ExtendedSelection);
+ view.setViewMode(QListView::IconMode);
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Verfify that item sizes are non-uniform
+ QVERIFY(view.sizeHintForIndex(model.index(0, 0)).height() > view.sizeHintForIndex(model.index(1, 0)).height());
+
+ QModelIndex index = model.index(3, 0);
+ view.setCurrentIndex(index);
+ QCOMPARE(view.currentIndex(), index);
+
+ QTest::keyClick(&view, Qt::Key_Up, Qt::ShiftModifier);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex(), model.index(1, 0));
+
+ QModelIndexList selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 3);
+ QVERIFY(!selected.contains(model.index(0, 0)));
+ }
+ { // Second test: QListView::TopToBottom flow
+ QStringList items;
+ items << "ab" << "a" << "a" << "a";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setFixedSize(250, 250);
+ view.setFlow(QListView::TopToBottom);
+ view.setGridSize(QSize(100, 100));
+ view.setSelectionMode(QListView::ExtendedSelection);
+ view.setViewMode(QListView::IconMode);
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Verfify that item sizes are non-uniform
+ QVERIFY(view.sizeHintForIndex(model.index(0, 0)).width() > view.sizeHintForIndex(model.index(1, 0)).width());
+
+ QModelIndex index = model.index(3, 0);
+ view.setCurrentIndex(index);
+ QCOMPARE(view.currentIndex(), index);
+
+ QTest::keyClick(&view, Qt::Key_Left, Qt::ShiftModifier);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex(), model.index(1, 0));
+
+ QModelIndexList selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 3);
+ QVERIFY(!selected.contains(model.index(0, 0)));
+ }
+}
+
+void tst_QListView::clickOnViewportClearsSelection()
+{
+ QStringList items;
+ items << "Text1";
+ QStringListModel model(items);
+ QListView view;
+ view.setModel(&model);
+ view.setSelectionMode(QListView::ExtendedSelection);
+
+ view.selectAll();
+ QModelIndex index = model.index(0);
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1);
+ QVERIFY(view.selectionModel()->isSelected(index));
+
+ //we try to click outside of the index
+ const QPoint point = view.visualRect(index).bottomRight() + QPoint(10,10);
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, point);
+ //at this point, the selection shouldn't have changed
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1);
+ QVERIFY(view.selectionModel()->isSelected(index));
+
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, point);
+ //now the selection should be cleared
+ QVERIFY(!view.selectionModel()->hasSelection());
+}
+
+void tst_QListView::task262152_setModelColumnNavigate()
+{
+ QListView view;
+ QStandardItemModel model(3,2);
+ model.setItem(0,1,new QStandardItem("[0,1]"));
+ model.setItem(1,1,new QStandardItem("[1,1]"));
+ model.setItem(2,1,new QStandardItem("[2,1]"));
+
+ view.setModel(&model);
+ view.setModelColumn(1);
+
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
+ QTest::keyClick(&view, Qt::Key_Down);
+ QTest::qWait(30);
+ QTRY_COMPARE(view.currentIndex(), model.index(1,1));
+ QTest::keyClick(&view, Qt::Key_Down);
+ QTest::qWait(30);
+ QTRY_COMPARE(view.currentIndex(), model.index(2,1));
+}
+
+void tst_QListView::taskQTBUG_2233_scrollHiddenItems_data()
+{
+ QTest::addColumn<int>("flow");
+
+ QTest::newRow("TopToBottom") << static_cast<int>(QListView::TopToBottom);
+ QTest::newRow("LeftToRight") << static_cast<int>(QListView::LeftToRight);
+}
+
+void tst_QListView::taskQTBUG_2233_scrollHiddenItems()
+{
+ QFETCH(int, flow);
+ const int rowCount = 200;
+
+ QWidget topLevel;
+ QListView view(&topLevel);
+ QStringListModel model(&view);
+ QStringList list;
+ for (int i = 0; i < rowCount; ++i)
+ list << QString::fromAscii("Item %1").arg(i);
+
+ model.setStringList(list);
+ view.setModel(&model);
+ view.setViewMode(QListView::ListMode);
+ for (int i = 0; i < rowCount / 2; ++i)
+ view.setRowHidden(2 * i, true);
+ view.setFlow(static_cast<QListView::Flow>(flow));
+ view.resize(130, 130);
+
+ for (int i = 0; i < 10; ++i) {
+ (view.flow() == QListView::TopToBottom
+ ? view.verticalScrollBar()
+ : view.horizontalScrollBar())->setValue(i);
+ QModelIndex index = view.indexAt(QPoint(0,0));
+ QVERIFY(index.isValid());
+ QCOMPARE(index.row(), 2 * i + 1);
+ }
+
+ //QTBUG-7929 should not crash
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QScrollBar *bar = view.flow() == QListView::TopToBottom
+ ? view.verticalScrollBar() : view.horizontalScrollBar();
+
+ int nbVisibleItem = rowCount / 2 - bar->maximum();
+
+ bar->setValue(bar->maximum());
+ QApplication::processEvents();
+ for (int i = rowCount; i > rowCount / 2; i--) {
+ view.setRowHidden(i, true);
+ }
+ QApplication::processEvents();
+ QTest::qWait(50);
+ QCOMPARE(bar->value(), bar->maximum());
+ QCOMPARE(bar->maximum(), rowCount/4 - nbVisibleItem);
+}
+
+void tst_QListView::taskQTBUG_633_changeModelData()
+{
+ QListView view;
+ view.setFlow(QListView::LeftToRight);
+ QStandardItemModel model(5,1);
+ for (int i = 0; i < model.rowCount(); ++i) {
+ model.setData( model.index(i, 0), QString::number(i));
+ }
+
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ model.setData( model.index(1, 0), QLatin1String("long long text"));
+ QTest::qWait(100); //leave time for relayouting the items
+ QRect rectLongText = view.visualRect(model.index(1,0));
+ QRect rect2 = view.visualRect(model.index(2,0));
+ QVERIFY( ! rectLongText.intersects(rect2) );
+}
+
+void tst_QListView::taskQTBUG_435_deselectOnViewportClick()
+{
+ QListView view;
+ QStringListModel model( QStringList() << "1" << "2" << "3" << "4");
+ view.setModel(&model);
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.selectAll();
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount());
+
+
+ const QRect itemRect = view.visualRect(model.index(model.rowCount() - 1));
+ QPoint p = view.visualRect(model.index(model.rowCount() - 1)).center() + QPoint(0, itemRect.height());
+ //first the left button
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
+ QVERIFY(!view.selectionModel()->hasSelection());
+
+ view.selectAll();
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount());
+
+ //and now the right button
+ QTest::mouseClick(view.viewport(), Qt::RightButton, 0, p);
+ QVERIFY(!view.selectionModel()->hasSelection());
+}
+
+void tst_QListView::taskQTBUG_2678_spacingAndWrappedText()
+{
+ static const QString lorem("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
+ QStringListModel model(QStringList() << lorem << lorem << "foo" << lorem << "bar" << lorem << lorem);
+ QListView w;
+ w.setModel(&model);
+ w.setViewMode(QListView::ListMode);
+ w.setWordWrap(true);
+ w.setSpacing(10);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QCOMPARE(w.horizontalScrollBar()->minimum(), w.horizontalScrollBar()->maximum());
+}
+
+void tst_QListView::taskQTBUG_5877_skippingItemInPageDownUp()
+{
+ QList<int> currentItemIndexes;
+ QtTestModel model(0);
+ model.colCount = 1;
+ model.rCount = 100;
+
+ currentItemIndexes << 0 << 6 << 16 << 25 << 34 << 42 << 57 << 68 << 77
+ << 83 << 91 << 94;
+ QMoveCursorListView vu;
+ vu.setModel(&model);
+ vu.show();
+
+ QTest::qWaitForWindowShown(&vu);
+
+ int itemHeight = vu.visualRect(model.index(0, 0)).height();
+ int visibleRowCount = vu.viewport()->height() / itemHeight;
+ int scrolledRowCount = visibleRowCount - 1;
+
+ for (int i = 0; i < currentItemIndexes.size(); ++i) {
+ vu.selectionModel()->setCurrentIndex(model.index(currentItemIndexes[i], 0),
+ QItemSelectionModel::SelectCurrent);
+
+ QModelIndex idx = vu.moveCursor(QMoveCursorListView::MovePageDown, Qt::NoModifier);
+ int newCurrent = qMin(currentItemIndexes[i] + scrolledRowCount, 99);
+ QCOMPARE(idx, model.index(newCurrent, 0));
+
+ idx = vu.moveCursor(QMoveCursorListView::MovePageUp, Qt::NoModifier);
+ newCurrent = qMax(currentItemIndexes[i] - scrolledRowCount, 0);
+ QCOMPARE(idx, model.index(newCurrent, 0));
+ }
+}
+
+class ListView_9455 : public QListView
+{
+public:
+ QSize contentsSize() const
+ {
+ return QListView::contentsSize();
+ }
+};
+
+void tst_QListView::taskQTBUG_9455_wrongScrollbarRanges()
+{
+ QStringList list;
+ const int nrItems = 8;
+ for (int i = 0; i < nrItems; i++)
+ list << QString().sprintf("item %d", i);
+
+ QStringListModel model(list);
+ ListView_9455 w;
+ w.setModel(&model);
+ w.setViewMode(QListView::IconMode);
+ w.resize(116, 132);
+ w.setMovement(QListView::Static);
+ const int spacing = 40;
+ w.setSpacing(spacing);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QCOMPARE(w.verticalScrollBar()->maximum(), w.contentsSize().height() - w.viewport()->geometry().height());
+}
+
+void tst_QListView::styleOptionViewItem()
+{
+ class MyDelegate : public QStyledItemDelegate
+ {
+ public:
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ QVERIFY(qstyleoption_cast<const QStyleOptionViewItemV4 *>(&option));
+ QStyleOptionViewItemV4 opt(option);
+ initStyleOption(&opt, index);
+
+ QCOMPARE(opt.index, index);
+
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+ };
+
+ QListView view;
+ QStandardItemModel model;
+ view.setModel(&model);
+ MyDelegate delegate;
+ view.setItemDelegate(&delegate);
+ model.appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") );
+
+ // Run test
+ view.showMaximized();
+ QApplication::processEvents();
+}
+
+void tst_QListView::taskQTBUG_12308_artihmeticException()
+{
+ QListWidget lw;
+ lw.setLayoutMode(QListView::Batched);
+ lw.setViewMode(QListView::IconMode);
+ for (int i = 0; i < lw.batchSize() + 1; i++) {
+ QListWidgetItem *item = new QListWidgetItem();
+ item->setText(QString("Item %L1").arg(i));
+ lw.addItem(item);
+ item->setHidden(true);
+ }
+ lw.show();
+ QTest::qWaitForWindowShown(&lw);
+ // No crash, it's all right.
+}
+
+class Delegate12308 : public QStyledItemDelegate
+{
+ Q_OBJECT
+public:
+ Delegate12308(QObject *parent = 0) : QStyledItemDelegate(parent)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ QVERIFY(option.rect.topLeft() != QPoint(-1, -1));
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+};
+
+void tst_QListView::taskQTBUG_12308_wrongFlowLayout()
+{
+ QListWidget lw;
+ Delegate12308 delegate;
+ lw.setLayoutMode(QListView::Batched);
+ lw.setViewMode(QListView::IconMode);
+ lw.setItemDelegate(&delegate);
+ for (int i = 0; i < lw.batchSize() + 1; i++) {
+ QListWidgetItem *item = new QListWidgetItem();
+ item->setText(QString("Item %L1").arg(i));
+ lw.addItem(item);
+ if (!item->text().contains(QString::fromAscii("1")))
+ item->setHidden(true);
+ }
+ lw.show();
+ QTest::qWaitForWindowShown(&lw);
+}
+
+QTEST_MAIN(tst_QListView)
+#include "tst_qlistview.moc"
diff --git a/tests/auto/widgets/itemviews/qlistwidget/.gitignore b/tests/auto/widgets/itemviews/qlistwidget/.gitignore
new file mode 100644
index 0000000000..085486b2de
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistwidget/.gitignore
@@ -0,0 +1 @@
+tst_qlistwidget
diff --git a/tests/auto/widgets/itemviews/qlistwidget/qlistwidget.pro b/tests/auto/widgets/itemviews/qlistwidget/qlistwidget.pro
new file mode 100644
index 0000000000..7343415e4c
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistwidget/qlistwidget.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qlistwidget.cpp
+
+qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test # QTBUG-21098, fails unstably
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
new file mode 100644
index 0000000000..9ede38f553
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -0,0 +1,1685 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+#include <qeventloop.h>
+#include <qlist.h>
+
+#include <qlistwidget.h>
+#include <private/qlistwidget_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QListWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QListWidget();
+ ~tst_QListWidget();
+
+ enum ModelChanged {
+ RowsAboutToBeInserted,
+ RowsInserted,
+ RowsAboutToBeRemoved,
+ RowsRemoved,
+ ColumnsAboutToBeInserted,
+ ColumnsInserted,
+ ColumnsAboutToBeRemoved,
+ ColumnsRemoved
+ };
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void addItem();
+ void addItem2();
+ void addItems();
+ void openPersistentEditor();
+ void closePersistentEditor();
+ void count();
+ void currentItem();
+ void setCurrentItem_data();
+ void setCurrentItem();
+ void currentRow();
+ void setCurrentRow_data();
+ void setCurrentRow();
+ void editItem_data();
+ void editItem();
+ void findItems();
+ void insertItem_data();
+ void insertItem();
+ void insertItems_data();
+ void insertItems();
+ void moveItemsPriv_data();
+ void moveItemsPriv();
+
+ void itemAssignment();
+ void item_data();
+ void item();
+ void takeItem_data();
+ void takeItem();
+ void setItemHidden();
+ void selectedItems_data();
+ void selectedItems();
+ void removeItems_data();
+ void removeItems();
+ void itemStreaming_data();
+ void itemStreaming();
+ void sortItems_data();
+ void sortItems();
+ void sortHiddenItems();
+ void sortHiddenItems_data();
+ void closeEditor();
+ void setData_data();
+ void setData();
+ void insertItemsWithSorting_data();
+ void insertItemsWithSorting();
+ void changeDataWithSorting_data();
+ void changeDataWithSorting();
+ void itemData();
+ void itemWidget();
+#ifndef Q_WS_MAC
+ void fastScroll();
+#endif
+ void insertUnchanged();
+ void setSortingEnabled();
+ void task199503_crashWhenCleared();
+ void task217070_scrollbarsAdjusted();
+ void task258949_keypressHangup();
+ void QTBUG8086_currentItemChangedOnClick();
+ void QTBUG14363_completerWithAnyKeyPressedEditTriggers();
+
+
+protected slots:
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsAboutToBeInserted, parent, first, last); }
+ void rowsInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsInserted, parent, first, last); }
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsAboutToBeRemoved, parent, first, last); }
+ void rowsRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsRemoved, parent, first, last); }
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsAboutToBeInserted, parent, first, last); }
+ void columnsInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsInserted, parent, first, last); }
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsAboutToBeRemoved, parent, first, last); }
+ void columnsRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsRemoved, parent, first, last); }
+
+ void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last);
+
+private:
+ QListWidget *testWidget;
+ QVector<QModelIndex> rcParent;
+ QVector<int> rcFirst;
+ QVector<int> rcLast;
+
+ void populate();
+ void checkDefaultValues();
+};
+
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(QVariantList)
+
+tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rcLast(8,0)
+{
+}
+
+tst_QListWidget::~tst_QListWidget()
+{
+}
+
+void tst_QListWidget::initTestCase()
+{
+ testWidget = new QListWidget();
+ testWidget->show();
+
+ connect(testWidget->model(), SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeInserted(QModelIndex, int, int)));
+ connect(testWidget->model(), SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(rowsInserted(QModelIndex, int, int)));
+ connect(testWidget->model(), SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ connect(testWidget->model(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsRemoved(QModelIndex, int, int)));
+
+ connect(testWidget->model(), SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)),
+ this, SLOT(columnsAboutToBeInserted(QModelIndex, int, int)));
+ connect(testWidget->model(), SIGNAL(columnsInserted(QModelIndex, int, int)),
+ this, SLOT(columnsInserted(QModelIndex, int, int)));
+ connect(testWidget->model(), SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(columnsAboutToBeRemoved(QModelIndex, int, int)));
+ connect(testWidget->model(), SIGNAL(columnsRemoved(QModelIndex, int, int)),
+ this, SLOT(columnsRemoved(QModelIndex, int, int)));
+
+ checkDefaultValues();
+}
+
+void tst_QListWidget::cleanupTestCase()
+{
+ delete testWidget;
+}
+
+void tst_QListWidget::init()
+{
+ testWidget->clear();
+
+ if (testWidget->viewport()->children().count() > 0) {
+ QEventLoop eventLoop;
+ for (int i=0; i < testWidget->viewport()->children().count(); ++i)
+ connect(testWidget->viewport()->children().at(i), SIGNAL(destroyed()), &eventLoop, SLOT(quit()));
+ QTimer::singleShot(100, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+ }
+}
+
+void tst_QListWidget::checkDefaultValues()
+{
+ QCOMPARE(testWidget->currentItem(), (QListWidgetItem *)0);
+ QCOMPARE(testWidget->currentRow(), -1);
+ QCOMPARE(testWidget->count(), 0);
+}
+
+void tst_QListWidget::cleanup()
+{
+}
+
+void tst_QListWidget::populate()
+{
+ addItem();
+ addItem2();
+ addItems();
+ setItemHidden();
+
+ testWidget->setCurrentIndex(testWidget->model()->index(0,0));
+
+ // setCurrentItem();
+ // setCurrentRow();
+}
+
+void tst_QListWidget::addItem()
+{
+ int count = testWidget->count();
+ QString label = QString("%1").arg(count);
+ testWidget->addItem(label);
+ QCOMPARE(testWidget->count(), ++count);
+ QCOMPARE(testWidget->item(testWidget->count()-1)->text(), label);
+}
+
+void tst_QListWidget::addItem2()
+{
+ int count = testWidget->count();
+
+ // Boundary Checking
+ testWidget->addItem(0);
+ QCOMPARE(testWidget->count(), count);
+
+ QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(count));
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ testWidget->addItem(item);
+ QCOMPARE(testWidget->count(), ++count);
+ QCOMPARE(testWidget->item(testWidget->count()-1), item);
+ QCOMPARE(testWidget->isItemHidden(item), false);
+}
+
+void tst_QListWidget::addItems()
+{
+ int count = testWidget->count();
+
+ // Boundary Checking
+ testWidget->addItems(QStringList());
+ QCOMPARE(testWidget->count(), count);
+
+ QStringList stringList;
+ QString label = QString("%1").arg(count);
+ stringList << QString("%1").arg(testWidget->count() + 1)
+ << QString("%1").arg(testWidget->count() + 2)
+ << QString("%1").arg(testWidget->count() + 3)
+ << label;
+ testWidget->addItems(stringList);
+ QCOMPARE(testWidget->count(), count + stringList.count());
+ QCOMPARE(testWidget->item(testWidget->count()-1)->text(), label);
+}
+
+
+void tst_QListWidget::openPersistentEditor()
+{
+ // Boundary checking
+ testWidget->openPersistentEditor(0);
+ QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
+ testWidget->openPersistentEditor(item);
+
+ int childCount = testWidget->viewport()->children().count();
+ testWidget->addItem(item);
+ testWidget->openPersistentEditor(item);
+ QCOMPARE(childCount + 1, testWidget->viewport()->children().count());
+}
+
+void tst_QListWidget::closePersistentEditor()
+{
+ // Boundary checking
+ int childCount = testWidget->viewport()->children().count();
+ testWidget->closePersistentEditor(0);
+ QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
+ testWidget->closePersistentEditor(item);
+ QCOMPARE(childCount, testWidget->viewport()->children().count());
+
+ // Create something
+ testWidget->addItem(item);
+ testWidget->openPersistentEditor(item);
+
+ // actual test
+ childCount = testWidget->viewport()->children().count();
+ testWidget->closePersistentEditor(item);
+ // Spin the event loop and hopefully it will die.
+ QEventLoop eventLoop;
+ for (int i=0; i < childCount; ++i)
+ connect(testWidget->viewport()->children().at(i), SIGNAL(destroyed()), &eventLoop, SLOT(quit()));
+ QTimer::singleShot(100, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+ QCOMPARE(testWidget->viewport()->children().count(), childCount - 1);
+}
+
+void tst_QListWidget::setItemHidden()
+{
+ // Boundary checking
+ testWidget->setItemHidden(0, true);
+ testWidget->setItemHidden(0, false);
+
+ int totalHidden = 0;
+ for (int i = 0; i < testWidget->model()->rowCount(); ++i)
+ if (testWidget->isItemHidden(testWidget->item(i)))
+ totalHidden++;
+
+ QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
+ testWidget->addItem(item);
+
+ // Check that nothing else changed
+ int newTotal = 0;
+ for (int i = 0; i < testWidget->model()->rowCount(); ++i)
+ if (testWidget->isItemHidden(testWidget->item(i)))
+ newTotal++;
+ QCOMPARE(newTotal, totalHidden);
+
+ testWidget->setItemHidden(item, true);
+ QCOMPARE(testWidget->isItemHidden(item), true);
+
+ // Check that nothing else changed
+ newTotal = 0;
+ for (int i = 0; i < testWidget->model()->rowCount(); ++i)
+ if (testWidget->isItemHidden(testWidget->item(i)))
+ newTotal++;
+ QCOMPARE(newTotal, totalHidden + 1);
+
+ testWidget->setItemHidden(item, false);
+ QCOMPARE(testWidget->isItemHidden(item), false);
+
+ // Check that nothing else changed
+ newTotal = 0;
+ for (int i = 0; i < testWidget->model()->rowCount(); ++i)
+ if (testWidget->isItemHidden(testWidget->item(i)))
+ newTotal++;
+ QCOMPARE(newTotal, totalHidden);
+
+ testWidget->setItemHidden(item, true);
+}
+
+void tst_QListWidget::setCurrentItem_data()
+{
+ QTest::addColumn<int>("fill");
+ QTest::newRow("HasItems: 0") << 0;
+ QTest::newRow("HasItems: 1") << 1;
+ QTest::newRow("HasItems: 2") << 2;
+ QTest::newRow("HasItems: 3") << 3;
+}
+
+void tst_QListWidget::setCurrentItem()
+{
+ QFETCH(int, fill);
+ for (int i = 0; i < fill; ++i)
+ testWidget->addItem(QString("%1").arg(i));
+
+ // Boundary checking
+ testWidget->setCurrentItem((QListWidgetItem *)0);
+ QCOMPARE((QListWidgetItem *)0, testWidget->currentItem());
+ QListWidgetItem item;
+ testWidget->setCurrentItem(&item);
+ QCOMPARE((QListWidgetItem *)0, testWidget->currentItem());
+
+ // Make sure that currentItem changes to what is passed into setCurrentItem
+ for (int i = 0; i < testWidget->count(); ++i) {
+ testWidget->setCurrentItem(testWidget->item(i));
+ for (int j = 0; j < testWidget->count(); ++j) {
+ testWidget->setCurrentItem(testWidget->item(j));
+ QCOMPARE(testWidget->item(j), testWidget->currentItem());
+ }
+ }
+}
+
+void tst_QListWidget::setCurrentRow_data()
+{
+ QTest::addColumn<int>("fill");
+ QTest::newRow("HasItems: 0") << 0;
+ QTest::newRow("HasItems: 1") << 1;
+ QTest::newRow("HasItems: 2") << 2;
+ QTest::newRow("HasItems: 3") << 3;
+}
+
+void tst_QListWidget::setCurrentRow()
+{
+ QFETCH(int, fill);
+ for (int i = 0; i < fill; ++i)
+ testWidget->addItem(QString("%1").arg(i));
+
+ // Boundary checking
+ testWidget->setCurrentRow(-1);
+ QCOMPARE(-1, testWidget->currentRow());
+ testWidget->setCurrentRow(testWidget->count());
+ QCOMPARE(-1, testWidget->currentRow());
+
+ // Make sure that currentRow changes to what is passed into setCurrentRow
+ for (int i = 0; i < testWidget->count(); ++i) {
+ testWidget->setCurrentRow(i);
+ for (int j = 0; j < testWidget->count(); ++j) {
+ testWidget->setCurrentRow(j);
+ QCOMPARE(j, testWidget->currentRow());
+ }
+ }
+}
+
+void tst_QListWidget::count()
+{
+ populate();
+
+ // actual test
+ QCOMPARE(testWidget->model()->rowCount(), testWidget->count());
+}
+
+void tst_QListWidget::currentItem()
+{
+ populate();
+
+ // actual test
+ QModelIndex currentIndex = testWidget->selectionModel()->currentIndex();
+ if (currentIndex.isValid())
+ QVERIFY(testWidget->currentItem() == testWidget->item(currentIndex.row()));
+ else
+ QVERIFY(testWidget->currentItem() == (QListWidgetItem*)0);
+}
+
+void tst_QListWidget::currentRow()
+{
+ populate();
+
+ // actual test
+ QModelIndex currentIndex = testWidget->selectionModel()->currentIndex();
+ if (currentIndex.isValid())
+ QCOMPARE(testWidget->currentRow(), currentIndex.row());
+ else
+ QCOMPARE(testWidget->currentRow(), -1);
+}
+
+void tst_QListWidget::editItem_data()
+{
+ QTest::addColumn<bool>("editable");
+ QTest::newRow("editable") << true;
+ QTest::newRow("not editable") << false;
+}
+
+void tst_QListWidget::editItem()
+{
+ // Boundary checking
+ testWidget->editItem(0);
+ QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(testWidget->count()));
+ testWidget->editItem(item);
+
+ QFETCH(bool, editable);
+ if (editable)
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ testWidget->addItem(item);
+
+ int childCount = testWidget->viewport()->children().count();
+ QWidget *existsAlready = testWidget->indexWidget(testWidget->model()->index(testWidget->row(item), 0));
+ testWidget->editItem(item);
+ Qt::ItemFlags flags = item->flags();
+
+ // There doesn't seem to be a way to detect if the item has already been edited...
+ if (!existsAlready && flags & Qt::ItemIsEditable && flags & Qt::ItemIsEnabled) {
+ QList<QObject *> children = testWidget->viewport()->children();
+ QVERIFY(children.count() > childCount);
+ bool found = false;
+ for (int i = 0; i < children.size(); ++i) {
+ if (children.at(i)->inherits("QExpandingLineEdit"))
+ found = true;
+ }
+ QVERIFY(found);
+ } else {
+ QCOMPARE(testWidget->viewport()->children().count(), childCount);
+ }
+}
+
+void tst_QListWidget::findItems()
+{
+ // This really just tests that the items that are returned are converted from index's to items correctly.
+
+ // Boundary checking
+ QCOMPARE(testWidget->findItems("GirlsCanWearJeansAndCutTheirHairShort", Qt::MatchExactly).count(), 0);
+
+ populate();
+
+ for (int i=0; i < testWidget->count(); ++i)
+ QCOMPARE(testWidget->findItems( (testWidget->item(i)->text()), Qt::MatchExactly).count(), 1);
+}
+
+
+void tst_QListWidget::insertItem_data()
+{
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<QString>("itemLabel");
+ QTest::addColumn<int>("expectedIndex");
+
+ QStringList initialItems;
+ initialItems << "foo" << "bar";
+
+ QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0;
+ QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0;
+ QTest::newRow("Insert beyond count") << initialItems << initialItems.count()+1 << "inserted" << initialItems.count();
+ QTest::newRow("Insert at count") << initialItems << initialItems.count() << "inserted" << initialItems.count();
+ QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1;
+}
+
+void tst_QListWidget::insertItem()
+{
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, insertIndex);
+ QFETCH(QString, itemLabel);
+ QFETCH(int, expectedIndex);
+
+ testWidget->insertItems(0, initialItems);
+ QCOMPARE(testWidget->count(), initialItems.count());
+
+ testWidget->insertItem(insertIndex, itemLabel);
+
+ QCOMPARE(rcFirst[RowsAboutToBeInserted], expectedIndex);
+ QCOMPARE(rcLast[RowsAboutToBeInserted], expectedIndex);
+ QCOMPARE(rcFirst[RowsInserted], expectedIndex);
+ QCOMPARE(rcLast[RowsInserted], expectedIndex);
+
+ QCOMPARE(testWidget->count(), initialItems.count() + 1);
+ QCOMPARE(testWidget->item(expectedIndex)->text(), itemLabel);
+}
+
+void tst_QListWidget::insertItems_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("insertType");
+
+ QTest::newRow("Insert 1 item using constructor") << 1 << 0;
+ QTest::newRow("Insert 10 items using constructor") << 10 << 0;
+ QTest::newRow("Insert 100 items using constructor") << 100 << 0;
+
+ QTest::newRow("Insert 1 item with insertItem") << 1 << 1;
+ QTest::newRow("Insert 10 items with insertItem") << 10 << 1;
+ QTest::newRow("Insert 100 items with insertItem") << 100 << 1;
+
+ QTest::newRow("Insert/Create 1 item using insertItem") << 1 << 2;
+ QTest::newRow("Insert/Create 10 items using insertItem") << 10 << 2;
+ QTest::newRow("Insert/Create 100 items using insertItem") << 100 << 2;
+
+ QTest::newRow("Insert 0 items with insertItems") << 0 << 3;
+ QTest::newRow("Insert 1 item with insertItems") << 1 << 3;
+ QTest::newRow("Insert 10 items with insertItems") << 10 << 3;
+ QTest::newRow("Insert 100 items with insertItems") << 100 << 3;
+}
+
+void tst_QListWidget::insertItems()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, insertType);
+
+ if (insertType == 3) {
+ QStringList strings;
+ for (int i=0; i<rowCount; ++i)
+ strings << QString::number(i);
+ testWidget->insertItems(0, strings);
+ } else {
+ for (int r = 0; r < rowCount; ++r) {
+ if (insertType == 0) {
+ // insert with QListWidgetItem constructor
+ new QListWidgetItem(QString::number(r), testWidget);
+ } else if (insertType == 1) {
+ // insert actual item
+ testWidget->insertItem(r, new QListWidgetItem(QString::number(r)));
+ } else if (insertType == 2) {
+ // insert/creating with string
+ testWidget->insertItem(r, QString::number(r));
+ } else if (insertType == 3) {
+ QStringList strings;
+ for (int i=0; i<rowCount; ++i)
+ strings << QString::number(i);
+ testWidget->insertItems(0, strings);
+ break;
+ } else {
+ QVERIFY(0);
+ }
+ }
+ }
+ // compare the results
+ QCOMPARE(testWidget->count(), rowCount);
+
+ // check if the text
+ for (int r = 0; r < rowCount; ++r)
+ QCOMPARE(testWidget->item(r)->text(), QString::number(r));
+
+ // make sure all items have view set correctly
+ for (int i=0; i<testWidget->count(); ++i)
+ QCOMPARE(testWidget->item(i)->listWidget(), testWidget);
+}
+
+void tst_QListWidget::itemAssignment()
+{
+ QListWidgetItem itemInWidget("inWidget", testWidget);
+ itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsTristate);
+ QListWidgetItem itemOutsideWidget("outsideWidget");
+
+ QVERIFY(itemInWidget.listWidget());
+ QCOMPARE(itemInWidget.text(), QString("inWidget"));
+ QVERIFY(itemInWidget.flags() & Qt::ItemIsTristate);
+
+ QVERIFY(!itemOutsideWidget.listWidget());
+ QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
+ QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsTristate));
+
+ itemOutsideWidget = itemInWidget;
+ QVERIFY(!itemOutsideWidget.listWidget());
+ QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
+ QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsTristate);
+}
+
+void tst_QListWidget::item_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<bool>("outOfBounds");
+
+ QTest::newRow("First item, row: 0") << 0 << false;
+ QTest::newRow("Middle item, row: 1") << 1 << false;
+ QTest::newRow("Last item, row: 2") << 2 << false;
+ QTest::newRow("Out of bounds, row: -1") << -1 << true;
+ QTest::newRow("Out of bounds, row: 3") << 3 << true;
+}
+
+void tst_QListWidget::item()
+{
+ QFETCH(int, row);
+ QFETCH(bool, outOfBounds);
+
+ (new QListWidgetItem(testWidget))->setText("item0");
+ (new QListWidgetItem(testWidget))->setText("item1");
+ (new QListWidgetItem(testWidget))->setText("item2");
+
+ QCOMPARE(testWidget->count(), 3);
+
+ QListWidgetItem *item = testWidget->item(row);
+ if (outOfBounds) {
+ QCOMPARE(item, static_cast<QListWidgetItem*>(0));
+ QCOMPARE(testWidget->count(), 3);
+ } else {
+ QCOMPARE(item->text(), QString("item%1").arg(row));
+ QCOMPARE(testWidget->count(), 3);
+ }
+}
+
+void tst_QListWidget::takeItem_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<bool>("outOfBounds");
+
+ QTest::newRow("First item, row: 0") << 0 << false;
+ QTest::newRow("Middle item, row: 1") << 1 << false;
+ QTest::newRow("Last item, row: 2") << 2 << false;
+ QTest::newRow("Out of bounds, row: -1") << -1 << true;
+ QTest::newRow("Out of bounds, row: 3") << 3 << true;
+}
+
+void tst_QListWidget::takeItem()
+{
+ QFETCH(int, row);
+ QFETCH(bool, outOfBounds);
+
+ (new QListWidgetItem(testWidget))->setText("item0");
+ (new QListWidgetItem(testWidget))->setText("item1");
+ (new QListWidgetItem(testWidget))->setText("item2");
+
+ QCOMPARE(testWidget->count(), 3);
+
+ QListWidgetItem *item = testWidget->takeItem(row);
+ if (outOfBounds) {
+ QCOMPARE(item, static_cast<QListWidgetItem*>(0));
+ QCOMPARE(testWidget->count(), 3);
+ } else {
+ QCOMPARE(item->text(), QString("item%1").arg(row));
+ QCOMPARE(testWidget->count(), 2);
+ }
+
+ delete item;
+}
+
+void tst_QListWidget::selectedItems_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<IntList>("hiddenRows");
+ QTest::addColumn<IntList>("selectedRows");
+ QTest::addColumn<IntList>("expectedRows");
+
+
+ QTest::newRow("none hidden, none selected")
+ << 3
+ << IntList()
+ << IntList()
+ << IntList();
+
+ QTest::newRow("none hidden, all selected")
+ << 3
+ << IntList()
+ << (IntList() << 0 << 1 << 2)
+ << (IntList() << 0 << 1 << 2);
+
+ QTest::newRow("first hidden, all selected")
+ << 3
+ << (IntList() << 0)
+ << (IntList() << 0 << 1 << 2)
+ << (IntList() << 0 << 1 << 2);
+
+ QTest::newRow("last hidden, all selected")
+ << 3
+ << (IntList() << 2)
+ << (IntList() << 0 << 1 << 2)
+ << (IntList() << 0 << 1 << 2);
+
+ QTest::newRow("middle hidden, all selected")
+ << 3
+ << (IntList() << 1)
+ << (IntList() << 0 << 1 << 2)
+ << (IntList() << 0 << 1 << 2);
+
+ QTest::newRow("all hidden, all selected")
+ << 3
+ << (IntList() << 0 << 1 << 2)
+ << (IntList() << 0 << 1 << 2)
+ << (IntList() << 0 << 1 << 2);
+}
+
+void tst_QListWidget::selectedItems()
+{
+ QFETCH(int, itemCount);
+ QFETCH(IntList, hiddenRows);
+ QFETCH(IntList, selectedRows);
+ QFETCH(IntList, expectedRows);
+
+ QVERIFY(testWidget->count() == 0);
+
+ //insert items
+ for (int i=0; i<itemCount; ++i)
+ new QListWidgetItem(QString("Item%1").arg(i), testWidget);
+
+ //test the selection
+ testWidget->setSelectionMode(QListWidget::SingleSelection);
+ for (int i=0; i<itemCount; ++i) {
+ QListWidgetItem *item = testWidget->item(i);
+ testWidget->setItemSelected(item, true);
+ QVERIFY(item->isSelected());
+ QCOMPARE(testWidget->selectedItems().count(), 1);
+ }
+ //let's clear the selection
+ testWidget->clearSelection();
+ //... and set the selection mode to allow more than 1 item to be selected
+ testWidget->setSelectionMode(QAbstractItemView::MultiSelection);
+
+ //verify items are inserted
+ QCOMPARE(testWidget->count(), itemCount);
+ // hide items
+ foreach (int row, hiddenRows)
+ testWidget->setItemHidden(testWidget->item(row), true);
+ // select items
+ foreach (int row, selectedRows)
+ testWidget->setItemSelected(testWidget->item(row), true);
+
+ // check that the correct number of items and the expected items are there
+ QList<QListWidgetItem *> selectedItems = testWidget->selectedItems();
+ QCOMPARE(selectedItems.count(), expectedRows.count());
+ foreach (int row, expectedRows)
+ QVERIFY(selectedItems.contains(testWidget->item(row)));
+
+ //check that isSelected agrees with selectedItems
+ for (int i=0; i<itemCount; ++i) {
+ QListWidgetItem *item = testWidget->item(i);
+ if (testWidget->isItemSelected(item))
+ QVERIFY(selectedItems.contains(item));
+ }
+}
+
+void tst_QListWidget::removeItems_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("removeRows");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("expectedRowCount");
+
+ QTest::newRow("Empty") << 0 << 1 << 0 << 0;
+ QTest::newRow("1:1") << 1 << 1 << 0 << 0;
+ QTest::newRow("3:1") << 3 << 1 << 0 << 2;
+ QTest::newRow("3:2") << 3 << 2 << 0 << 1;
+ QTest::newRow("100:10") << 100 << 10 << 0 << 90;
+}
+
+void tst_QListWidget::removeItems()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, removeRows);
+ QFETCH(int, row);
+ QFETCH(int, expectedRowCount);
+
+ //insert items
+ for (int r = 0; r < rowCount; ++r)
+ new QListWidgetItem(QString::number(r), testWidget);
+
+ // remove and compare the results
+ for (int r = 0; r < removeRows; ++r)
+ delete testWidget->item(row);
+ QCOMPARE(testWidget->count(), expectedRowCount);
+
+ // check if the correct items were removed
+ for (int r = 0; r < expectedRowCount; ++r)
+ if (r < row)
+ QCOMPARE(testWidget->item(r)->text(), QString::number(r));
+ else
+ QCOMPARE(testWidget->item(r)->text(), QString::number(r + removeRows));
+
+
+}
+
+void tst_QListWidget::moveItemsPriv_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("srcRow");
+ QTest::addColumn<int>("dstRow");
+ QTest::addColumn<bool>("shouldHaveSignaled");
+
+ QTest::newRow("Empty") << 0 << 0 << 0 << false;
+ QTest::newRow("Overflow src") << 5 << 5 << 2 << false;
+ QTest::newRow("Underflow src") << 5 << -1 << 2 << false;
+ QTest::newRow("Overflow dst") << 5 << 2 << 6 << false;
+ QTest::newRow("Underflow dst") << 5 << 2 << -1 << false;
+ QTest::newRow("Same place") << 5 << 2 << 2 << false;
+ QTest::newRow("Up") << 5 << 4 << 2 << true;
+ QTest::newRow("Down") << 5 << 2 << 4 << true;
+ QTest::newRow("QTBUG-6532 assert") << 5 << 0 << 1 << false;
+ QTest::newRow("QTBUG-6565 to the end") << 5 << 3 << 5 << true;
+ QTest::newRow("Same place 2") << 2 << 0 << 1 << false;
+ QTest::newRow("swap") << 2 << 0 << 2 << true;
+ QTest::newRow("swap2") << 4 << 1 << 3 << true;
+ QTest::newRow("swap3") << 4 << 3 << 2 << true;
+ QTest::newRow("swap4") << 2 << 1 << 0 << true;
+}
+
+void tst_QListWidget::moveItemsPriv()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, srcRow);
+ QFETCH(int, dstRow);
+ QFETCH(bool, shouldHaveSignaled);
+
+ for (int r = 0; r < rowCount; ++r)
+ new QListWidgetItem(QString::number(r), testWidget);
+
+ QListModel *model = qobject_cast<QListModel *>(testWidget->model());
+ QVERIFY(model);
+ QSignalSpy beginMoveSpy(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ QSignalSpy movedSpy(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ model->move(srcRow, dstRow);
+
+ if (shouldHaveSignaled) {
+ if (srcRow < dstRow)
+ QCOMPARE(testWidget->item(dstRow - 1)->text(), QString::number(srcRow));
+ else
+ QCOMPARE(testWidget->item(dstRow)->text(), QString::number(srcRow));
+
+ QCOMPARE(beginMoveSpy.count(), 1);
+ const QList<QVariant> &beginMoveArgs = beginMoveSpy.takeFirst();
+ QCOMPARE(beginMoveArgs.at(1).toInt(), srcRow);
+ QCOMPARE(beginMoveArgs.at(2).toInt(), srcRow);
+ QCOMPARE(beginMoveArgs.at(4).toInt(), dstRow);
+
+ QCOMPARE(movedSpy.count(), 1);
+ const QList<QVariant> &movedArgs = movedSpy.takeFirst();
+ QCOMPARE(movedArgs.at(1).toInt(), srcRow);
+ QCOMPARE(movedArgs.at(2).toInt(), srcRow);
+ QCOMPARE(movedArgs.at(4).toInt(), dstRow);
+ } else {
+ QCOMPARE(beginMoveSpy.count(), 0);
+ QCOMPARE(movedSpy.count(), 0);
+ }
+}
+
+void tst_QListWidget::itemStreaming_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("toolTip");
+
+ QTest::newRow("Data") << "item text" << "tool tip text";
+}
+
+void tst_QListWidget::itemStreaming()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, toolTip);
+
+ QListWidgetItem item;
+ QCOMPARE(item.text(), QString());
+ QCOMPARE(item.toolTip(), QString());
+
+ item.setText(text);
+ item.setToolTip(toolTip);
+ QCOMPARE(item.text(), text);
+ QCOMPARE(item.toolTip(), toolTip);
+
+ QByteArray buffer;
+ QDataStream out(&buffer, QIODevice::WriteOnly);
+ out << item;
+
+ QListWidgetItem item2;
+ QCOMPARE(item2.text(), QString());
+ QCOMPARE(item2.toolTip(), QString());
+
+ QVERIFY(!buffer.isEmpty());
+
+ QDataStream in(&buffer, QIODevice::ReadOnly);
+ in >> item2;
+ QCOMPARE(item2.text(), text);
+ QCOMPARE(item2.toolTip(), toolTip);
+}
+
+void tst_QListWidget::sortItems_data()
+{
+ QTest::addColumn<int>("order");
+ QTest::addColumn<QVariantList>("initialList");
+ QTest::addColumn<QVariantList>("expectedList");
+ QTest::addColumn<IntList>("expectedRows");
+
+ QTest::newRow("ascending strings")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b"))
+ << (QVariantList() << QString("a") << QString("b") << QString("c") << QString("d"))
+ << (IntList() << 2 << 3 << 0 << 1);
+
+ QTest::newRow("descending strings")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b"))
+ << (QVariantList() << QString("d") << QString("c") << QString("b") << QString("a"))
+ << (IntList() << 1 << 0 << 3 << 2);
+
+ QTest::newRow("ascending numbers")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QVariantList() << 1 << 11 << 2 << 22)
+ << (QVariantList() << 1 << 2 << 11 << 22)
+ << (IntList() << 0 << 2 << 1 << 3);
+
+ QTest::newRow("descending numbers")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QVariantList() << 1 << 11 << 2 << 22)
+ << (QVariantList() << 22 << 11 << 2 << 1)
+ << (IntList() << 3 << 1 << 2 << 0);
+}
+
+void tst_QListWidget::sortItems()
+{
+ QFETCH(int, order);
+ QFETCH(QVariantList, initialList);
+ QFETCH(QVariantList, expectedList);
+ QFETCH(IntList, expectedRows);
+
+ foreach (const QVariant &data, initialList) {
+ QListWidgetItem *item = new QListWidgetItem(testWidget);
+ item->setData(Qt::DisplayRole, data);
+ }
+
+ QAbstractItemModel *model = testWidget->model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
+ persistent << model->index(j, 0, QModelIndex());
+
+ testWidget->sortItems(static_cast<Qt::SortOrder>(order));
+
+ QCOMPARE(testWidget->count(), expectedList.count());
+ for (int i = 0; i < testWidget->count(); ++i)
+ QCOMPARE(testWidget->item(i)->text(), expectedList.at(i).toString());
+
+ for (int k = 0; k < testWidget->count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+}
+
+void tst_QListWidget::sortHiddenItems_data()
+{
+ QTest::addColumn<int>("order");
+ QTest::addColumn<QStringList>("initialList");
+ QTest::addColumn<QStringList>("expectedList");
+ QTest::addColumn<IntList>("expectedRows");
+ QTest::addColumn<IntList>("expectedVisibility");
+
+ QStringList initial, expected;
+ IntList rowOrder;
+ IntList visible;
+ for (int i = 0; i < 20; ++i) {
+ initial << QString(QChar(0x41 + i));
+ expected << QString(QChar(0x54 - i));
+ rowOrder << 19 - i;
+ visible << (i % 2);
+
+ }
+ QTest::newRow("descending order, 20 items")
+ << static_cast<int>(Qt::DescendingOrder)
+ << initial
+ << expected
+ << rowOrder
+ << visible;
+
+ QTest::newRow("ascending order")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "d" << "a" << "b")
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (IntList() << 2 << 3 << 0 << 1)
+ << (IntList() << 1 << 0 << 1 << 0);
+
+ QTest::newRow("descending order")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "c" << "d" << "a" << "b")
+ << (QStringList() << "d" << "c" << "b" << "a")
+ << (IntList() << 1 << 0 << 3 << 2)
+ << (IntList() << 0 << 1 << 0 << 1);
+}
+
+void tst_QListWidget::sortHiddenItems()
+{
+ QFETCH(int, order);
+ QFETCH(QStringList, initialList);
+ QFETCH(QStringList, expectedList);
+ QFETCH(IntList, expectedRows);
+ QFETCH(IntList, expectedVisibility);
+
+ // init() won't clear hidden items...
+ QListWidget *tw = new QListWidget();
+ tw->addItems(initialList);
+
+ QAbstractItemModel *model = tw->model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j) {
+ persistent << model->index(j, 0, QModelIndex());
+ tw->setRowHidden(j, j & 1); // every odd is hidden
+ }
+
+ tw->setSortingEnabled(true);
+ tw->sortItems(static_cast<Qt::SortOrder>(order));
+
+ QCOMPARE(tw->count(), expectedList.count());
+ for (int i = 0; i < tw->count(); ++i) {
+ QCOMPARE(tw->item(i)->text(), expectedList.at(i));
+ QCOMPARE(tw->item(i)->isHidden(), !expectedVisibility.at(i));
+ }
+
+ for (int k = 0; k < tw->count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+
+ delete tw;
+}
+
+void tst_QListWidget::modelChanged(ModelChanged change, const QModelIndex &parent,
+ int first, int last)
+{
+ rcParent[change] = parent;
+ rcFirst[change] = first;
+ rcLast[change] = last;
+}
+
+class TestListWidget : public QListWidget {
+public:
+ TestListWidget() : QListWidget()
+ {
+
+ }
+ State getState() {return QListWidget::state();}
+
+ void closeEditor(QWidget *w, QAbstractItemDelegate::EndEditHint hint) {
+ QListWidget::closeEditor(w, hint);
+ }
+
+ bool isEditingState(QListWidgetItem *item) {
+ Q_UNUSED(item);
+ return (QListWidget::state() == QListWidget::EditingState ? true : false);
+ }
+};
+
+void tst_QListWidget::closeEditor()
+{
+ TestListWidget w;
+ QStringList labels = (QStringList() << "a" << "b" << "c" << "d");
+ w.addItems(labels);
+ QListWidgetItem *item = w.item(0);
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ QVERIFY(item);
+ w.editItem(item);
+
+ QVERIFY(w.isEditingState(item));
+
+ w.reset();
+
+ QVERIFY(!w.isEditingState(item));
+}
+
+void tst_QListWidget::setData_data()
+{
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("itemIndex");
+ QTest::addColumn<IntList>("roles");
+ QTest::addColumn<QVariantList>("values");
+ QTest::addColumn<int>("expectedSignalCount");
+
+ QStringList initialItems;
+ IntList roles;
+ QVariantList values;
+
+ {
+ initialItems.clear(); roles.clear(); values.clear();
+ initialItems << "foo";
+ roles << Qt::DisplayRole;
+ values << "xxx";
+ QTest::newRow("changing a role should emit")
+ << initialItems << 0 << roles << values << 1;
+ }
+ {
+ initialItems.clear(); roles.clear(); values.clear();
+ initialItems << "foo";
+ roles << Qt::DisplayRole;
+ values << "foo";
+ QTest::newRow("setting the same value should not emit")
+ << initialItems << 0 << roles << values << 0;
+ }
+ {
+ initialItems.clear(); roles.clear(); values.clear();
+ initialItems << "foo";
+ roles << Qt::DisplayRole << Qt::DisplayRole;
+ values << "bar" << "bar";
+ QTest::newRow("setting the same value twice should only emit once")
+ << initialItems << 0 << roles << values << 1;
+ }
+ {
+ initialItems.clear(); roles.clear(); values.clear();
+ initialItems << "foo";
+ roles << Qt::DisplayRole << Qt::ToolTipRole << Qt::WhatsThisRole;
+ values << "bar" << "bartooltip" << "barwhatsthis";
+ QTest::newRow("changing three roles should emit three times")
+ << initialItems << 0 << roles << values << 3;
+ }
+}
+
+void tst_QListWidget::setData()
+{
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, itemIndex);
+ QFETCH(IntList, roles);
+ QFETCH(QVariantList, values);
+ QFETCH(int, expectedSignalCount);
+ qRegisterMetaType<QListWidgetItem *>("QListWidgetItem*");
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+
+ QVERIFY(roles.count() == values.count());
+
+ for (int manipulateModel=0; manipulateModel<2; ++manipulateModel) {
+ testWidget->clear();
+ testWidget->insertItems(0, initialItems);
+ QCOMPARE(testWidget->count(), initialItems.count());
+
+ QSignalSpy itemChanged(testWidget, SIGNAL(itemChanged(QListWidgetItem *)));
+ QSignalSpy dataChanged(testWidget->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+
+ for (int i=0; i < roles.count(); ++i) {
+ if (manipulateModel)
+ testWidget->model()->setData(
+ testWidget->model()->index(itemIndex, 0, testWidget->rootIndex()),
+ values.at(i),
+ roles.at(i));
+ else
+ testWidget->item(itemIndex)->setData(roles.at(i), values.at(i));
+ }
+
+ // make sure the data is actually set
+ for (int i=0; i < roles.count(); ++i)
+ QCOMPARE(testWidget->item(itemIndex)->data(roles.at(i)), values.at(i));
+
+ // make sure we get the right number of emits
+ QCOMPARE(itemChanged.count(), expectedSignalCount);
+ QCOMPARE(dataChanged.count(), expectedSignalCount);
+ }
+}
+
+void tst_QListWidget::insertItemsWithSorting_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<QStringList>("insertItems");
+ QTest::addColumn<QStringList>("expectedItems");
+ QTest::addColumn<IntList>("expectedRows");
+
+ QTest::newRow("() + (a) = (a)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList()
+ << (QStringList() << "a")
+ << (QStringList() << "a")
+ << IntList();
+ QTest::newRow("() + (c, b, a) = (a, b, c)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList()
+ << (QStringList() << "c" << "b" << "a")
+ << (QStringList() << "a" << "b" << "c")
+ << IntList();
+ QTest::newRow("() + (a, b, c) = (c, b, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QStringList()
+ << (QStringList() << "a" << "b" << "c")
+ << (QStringList() << "c" << "b" << "a")
+ << IntList();
+ QTest::newRow("(a) + (b) = (a, b)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList("a")
+ << (QStringList() << "b")
+ << (QStringList() << "a" << "b")
+ << (IntList() << 0);
+ QTest::newRow("(a) + (b) = (b, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QStringList("a")
+ << (QStringList() << "b")
+ << (QStringList() << "b" << "a")
+ << (IntList() << 1);
+ QTest::newRow("(a, c, b) + (d) = (a, b, c, d)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "b")
+ << (QStringList() << "d")
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (IntList() << 0 << 1 << 2);
+ QTest::newRow("(b, c, a) + (d) = (d, c, b, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "b" << "c" << "a")
+ << (QStringList() << "d")
+ << (QStringList() << "d" << "c" << "b" << "a")
+ << (IntList() << 1 << 2 << 3);
+ {
+ IntList ascendingRows;
+ IntList reverseRows;
+ QStringList ascendingItems;
+ QStringList reverseItems;
+ for (int i = 'a'; i <= 'z'; ++i) {
+ ascendingItems << QString("%0").arg(QLatin1Char(i));
+ reverseItems << QString("%0").arg(QLatin1Char('z' - i + 'a'));
+ ascendingRows << i - 'a';
+ reverseRows << 'z' - i + 'a';
+ }
+ QTest::newRow("() + (sorted items) = (sorted items)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList()
+ << ascendingItems
+ << ascendingItems
+ << IntList();
+ QTest::newRow("(sorted items) + () = (sorted items)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << ascendingItems
+ << QStringList()
+ << ascendingItems
+ << ascendingRows;
+ QTest::newRow("() + (ascending items) = (reverse items)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QStringList()
+ << ascendingItems
+ << reverseItems
+ << IntList();
+ QTest::newRow("(reverse items) + () = (ascending items)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << reverseItems
+ << QStringList()
+ << ascendingItems
+ << ascendingRows;
+ QTest::newRow("(reverse items) + () = (reverse items)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << reverseItems
+ << QStringList()
+ << reverseItems
+ << ascendingRows;
+ }
+}
+
+void tst_QListWidget::insertItemsWithSorting()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initialItems);
+ QFETCH(QStringList, insertItems);
+ QFETCH(QStringList, expectedItems);
+ QFETCH(IntList, expectedRows);
+
+ for (int method = 0; method < 5; ++method) {
+ QListWidget w;
+ w.setSortingEnabled(true);
+ w.sortItems(static_cast<Qt::SortOrder>(sortOrder));
+ w.addItems(initialItems);
+
+ QAbstractItemModel *model = w.model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
+ persistent << model->index(j, 0, QModelIndex());
+
+ switch (method) {
+ case 0:
+ // insert using item constructor
+ for (int i = 0; i < insertItems.size(); ++i)
+ new QListWidgetItem(insertItems.at(i), &w);
+ break;
+ case 1:
+ // insert using insertItems()
+ w.insertItems(0, insertItems);
+ break;
+ case 2:
+ // insert using insertItem()
+ for (int i = 0; i < insertItems.size(); ++i)
+ w.insertItem(0, insertItems.at(i));
+ break;
+ case 3:
+ // insert using addItems()
+ w.addItems(insertItems);
+ break;
+ case 4:
+ // insert using addItem()
+ for (int i = 0; i < insertItems.size(); ++i)
+ w.addItem(insertItems.at(i));
+ break;
+ }
+ QCOMPARE(w.count(), expectedItems.count());
+ for (int i = 0; i < w.count(); ++i)
+ QCOMPARE(w.item(i)->text(), expectedItems.at(i));
+
+ for (int k = 0; k < persistent.count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+ }
+}
+
+void tst_QListWidget::changeDataWithSorting_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("itemIndex");
+ QTest::addColumn<QString>("newValue");
+ QTest::addColumn<QStringList>("expectedItems");
+ QTest::addColumn<IntList>("expectedRows");
+ QTest::addColumn<bool>("reorderingExpected");
+
+ QTest::newRow("change a to b in (a)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a")
+ << 0 << "b"
+ << (QStringList() << "b")
+ << (IntList() << 0)
+ << false;
+ QTest::newRow("change a to b in (a, c)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c")
+ << 0 << "b"
+ << (QStringList() << "b" << "c")
+ << (IntList() << 0 << 1)
+ << false;
+ QTest::newRow("change a to c in (a, b)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "b")
+ << 0 << "c"
+ << (QStringList() << "b" << "c")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("change c to a in (c, b)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "c" << "b")
+ << 0 << "a"
+ << (QStringList() << "b" << "a")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("change e to i in (a, c, e, g)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "e" << "g")
+ << 2 << "i"
+ << (QStringList() << "a" << "c" << "g" << "i")
+ << (IntList() << 0 << 1 << 3 << 2)
+ << true;
+ QTest::newRow("change e to a in (c, e, g, i)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "e" << "g" << "i")
+ << 1 << "a"
+ << (QStringList() << "a" << "c" << "g" << "i")
+ << (IntList() << 1 << 0 << 2 << 3)
+ << true;
+ QTest::newRow("change e to f in (c, e, g, i)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "e" << "g" << "i")
+ << 1 << "f"
+ << (QStringList() << "c" << "f" << "g" << "i")
+ << (IntList() << 0 << 1 << 2 << 3)
+ << false;
+}
+
+void tst_QListWidget::itemData()
+{
+ QListWidget widget;
+ QListWidgetItem item(&widget);
+ item.setFlags(item.flags() | Qt::ItemIsEditable);
+ item.setData(Qt::DisplayRole, QString("0"));
+ item.setData(Qt::CheckStateRole, Qt::PartiallyChecked);
+ item.setData(Qt::UserRole + 0, QString("1"));
+ item.setData(Qt::UserRole + 1, QString("2"));
+ item.setData(Qt::UserRole + 2, QString("3"));
+ item.setData(Qt::UserRole + 3, QString("4"));
+ QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
+ QCOMPARE(flags.count(), 6);
+ QCOMPARE(flags[Qt::UserRole + 0].toString(), QString("1"));
+}
+
+void tst_QListWidget::changeDataWithSorting()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, itemIndex);
+ QFETCH(QString, newValue);
+ QFETCH(QStringList, expectedItems);
+ QFETCH(IntList, expectedRows);
+ QFETCH(bool, reorderingExpected);
+
+ QListWidget w;
+ w.setSortingEnabled(true);
+ w.sortItems(static_cast<Qt::SortOrder>(sortOrder));
+ w.addItems(initialItems);
+
+ QAbstractItemModel *model = w.model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
+ persistent << model->index(j, 0, QModelIndex());
+
+ QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+ QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
+
+ QListWidgetItem *item = w.item(itemIndex);
+ item->setText(newValue);
+ for (int i = 0; i < expectedItems.count(); ++i) {
+ QCOMPARE(w.item(i)->text(), expectedItems.at(i));
+ for (int j = 0; j < persistent.count(); ++j) {
+ if (persistent.at(j).row() == i) // the same toplevel row
+ QCOMPARE(persistent.at(j).internalPointer(), (void *)w.item(i));
+ }
+ }
+
+ for (int k = 0; k < persistent.count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
+}
+
+void tst_QListWidget::itemWidget()
+{
+ QListWidget list;
+ QWidget widget;
+
+ QListWidgetItem *item = new QListWidgetItem(&list);
+
+
+ QCOMPARE(list.itemWidget(item), static_cast<QWidget*>(0));
+ list.setItemWidget(item, &widget);
+ QCOMPARE(list.itemWidget(item), &widget);
+ list.removeItemWidget(item);
+ QCOMPARE(list.itemWidget(item), static_cast<QWidget*>(0));
+}
+
+#ifndef Q_WS_MAC
+class MyListWidget : public QListWidget
+{
+public:
+ MyListWidget(QWidget *parent=0)
+ : QListWidget(parent)
+ {
+ }
+
+ void paintEvent(QPaintEvent *e) {
+ painted += e->region();
+ QListWidget::paintEvent(e);
+ }
+
+ QRegion painted;
+};
+
+void tst_QListWidget::fastScroll()
+{
+ QWidget topLevel;
+ MyListWidget widget(&topLevel);
+ for (int i = 0; i < 50; ++i)
+ widget.addItem(QString("Item %1").arg(i));
+
+ topLevel.resize(300, 300); // toplevel needs to be wide enough for the item
+ topLevel.show();
+ // Make sure the widget gets the first full repaint. On
+ // some WMs, we'll get two (first inactive exposure, then
+ // active exposure.
+ QTest::qWaitForWindowShown(&widget);
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QApplication::processEvents();
+ QTest::qWait(500);
+
+ QSize itemSize = widget.visualItemRect(widget.item(0)).size();
+ QVERIFY(!itemSize.isEmpty());
+
+ QScrollBar *sbar = widget.verticalScrollBar();
+ widget.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+ widget.painted = QRegion();
+ sbar->setValue(sbar->value() + sbar->singleStep());
+ QApplication::processEvents();
+
+ // only one item should be repainted, the rest should be scrolled in memory
+ QCOMPARE(widget.painted.boundingRect().size(), itemSize);
+}
+#endif // Q_WS_MAC
+
+void tst_QListWidget::insertUnchanged()
+{
+ QListWidget w;
+ QSignalSpy itemChangedSpy(&w, SIGNAL(itemChanged(QListWidgetItem*)));
+ QListWidgetItem item("foo", &w);
+ QCOMPARE(itemChangedSpy.count(), 0);
+}
+
+void tst_QListWidget::setSortingEnabled()
+{
+ QListWidget w;
+ QListWidgetItem *item1 = new QListWidgetItem(&w);
+ QListWidgetItem *item2 = new QListWidgetItem(&w);
+
+ w.setSortingEnabled(true);
+ QCOMPARE(w.isSortingEnabled(), true);
+ QCOMPARE(w.item(0), item1);
+ QCOMPARE(w.item(1), item2);
+}
+
+void tst_QListWidget::task199503_crashWhenCleared()
+{
+ //we test here for a crash that would occur if you clear the items in the currentItemChanged signal
+ QListWidget w;
+ w.addItems( QStringList() << "item1" << "item2" << "item3");
+ w.setCurrentRow(0);
+ w.connect(&w, SIGNAL(currentItemChanged(QListWidgetItem *,QListWidgetItem*)), SLOT(clear()));
+ w.setCurrentRow(1);
+}
+
+void tst_QListWidget::task217070_scrollbarsAdjusted()
+{
+ //This task was mailing for style using SH_ScrollView_FrameOnlyAroundContents such as QMotifStyle
+ QListWidget v;
+ for (int i = 0; i<200;i++)
+ v.addItem(QString::number(i));
+ v.show();
+ v.setViewMode(QListView::IconMode);
+ v.setResizeMode(QListView::Adjust);
+ v.setUniformItemSizes(true);
+ v.resize(160,100);
+ QTest::qWait(50);
+ for(int f=150; f>90 ; f--) {
+ v.resize(f,100);
+ QTest::qWait(30);
+ QVERIFY(v.verticalScrollBar()->isVisible());
+ //the vertical scrollbar must not be visible.
+ QVERIFY(!v.horizontalScrollBar()->isVisible());
+ }
+}
+
+void tst_QListWidget::task258949_keypressHangup()
+{
+ QListWidget lw;
+ for (int y = 0; y < 5; y++) {
+ QListWidgetItem *lwi = new QListWidgetItem(&lw);
+ lwi->setText(y ? "1" : "0");
+ if (y)
+ lwi->setFlags(Qt::ItemIsSelectable);
+ }
+
+ lw.show();
+ lw.setCurrentIndex(lw.model()->index(0,0));
+ QCOMPARE(lw.currentIndex(), lw.model()->index(0,0));
+ QTest::qWait(30);
+ QTest::keyPress(&lw, '1'); //this used to freeze
+ QTest::qWait(30);
+ QCOMPARE(lw.currentIndex(), lw.model()->index(0,0));
+}
+
+void tst_QListWidget::QTBUG8086_currentItemChangedOnClick()
+{
+ qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
+ QWidget win;
+ QHBoxLayout layout(&win);
+ QListWidget list;
+ for (int i = 0 ; i < 4; ++i)
+ new QListWidgetItem(QString::number(i), &list);
+
+ layout.addWidget(&list);
+
+ QLineEdit edit;
+ layout.addWidget(&edit);
+
+ edit.setFocus();
+ win.show();
+
+ QSignalSpy spy(&list, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)));
+
+ QTest::qWaitForWindowShown(&win);
+
+ QCOMPARE(spy.count(), 0);
+
+ QTest::mouseClick(list.viewport(), Qt::LeftButton, 0, list.visualItemRect(list.item(2)).center());
+
+ QCOMPARE(spy.count(), 1);
+
+}
+
+
+class ItemDelegate : public QItemDelegate
+{
+public:
+ ItemDelegate(QObject *parent = 0) : QItemDelegate(parent)
+ {}
+ virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
+ {
+ QLineEdit *lineEdit = new QLineEdit(parent);
+ lineEdit->setFrame(false);
+ QCompleter *completer = new QCompleter(QStringList() << "completer", lineEdit);
+ completer->setCompletionMode(QCompleter::InlineCompletion);
+ lineEdit->setCompleter(completer);
+ return lineEdit;
+ }
+};
+
+void tst_QListWidget::QTBUG14363_completerWithAnyKeyPressedEditTriggers()
+{
+ QListWidget listWidget;
+ listWidget.setEditTriggers(QAbstractItemView::AnyKeyPressed);
+ listWidget.setItemDelegate(new ItemDelegate);
+ QListWidgetItem *item = new QListWidgetItem(QLatin1String("select an item (don't start editing)"), &listWidget);
+ item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsEditable);
+ new QListWidgetItem(QLatin1String("try to type the letter 'c'"), &listWidget);
+ new QListWidgetItem(QLatin1String("completer"), &listWidget);
+ listWidget.show();
+ listWidget.setCurrentItem(item);
+ QTest::qWaitForWindowShown(&listWidget);
+
+ QTest::keyClick(listWidget.viewport(), Qt::Key_C);
+
+ QLineEdit *le = qobject_cast<QLineEdit*>(listWidget.itemWidget(item));
+ QVERIFY(le);
+ QCOMPARE(le->text(), QString("completer"));
+ QCOMPARE(le->completer()->currentCompletion(), QString("completer"));
+}
+
+
+
+QTEST_MAIN(tst_QListWidget)
+#include "tst_qlistwidget.moc"
diff --git a/tests/auto/widgets/itemviews/qsortfilterproxymodel/.gitignore b/tests/auto/widgets/itemviews/qsortfilterproxymodel/.gitignore
new file mode 100644
index 0000000000..d3672fe4ae
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qsortfilterproxymodel/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel
diff --git a/tests/auto/widgets/itemviews/qsortfilterproxymodel/qsortfilterproxymodel.pro b/tests/auto/widgets/itemviews/qsortfilterproxymodel/qsortfilterproxymodel.pro
new file mode 100644
index 0000000000..65207b6563
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qsortfilterproxymodel/qsortfilterproxymodel.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += gui widgets
+mtdir = ../../../integrationtests/modeltest
+
+INCLUDEPATH += $$PWD/$${mtdir}
+SOURCES += tst_qsortfilterproxymodel.cpp $${mtdir}/dynamictreemodel.cpp $${mtdir}/modeltest.cpp
+HEADERS += $${mtdir}/dynamictreemodel.h $${mtdir}/modeltest.h
diff --git a/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
new file mode 100644
index 0000000000..96f7249e3c
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -0,0 +1,3274 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "dynamictreemodel.h"
+#include "modeltest.h"
+
+#include <QtCore>
+#include <QtGui>
+#include <QtWidgets>
+
+#include <qdebug.h>
+
+//TESTED CLASS=
+//TESTED_FILES=
+
+typedef QList<int> IntList;
+typedef QPair<int, int> IntPair;
+typedef QList<IntPair> IntPairList;
+
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(IntPair)
+Q_DECLARE_METATYPE(IntPairList)
+Q_DECLARE_METATYPE(QModelIndex)
+
+class tst_QSortFilterProxyModel : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ tst_QSortFilterProxyModel();
+ virtual ~tst_QSortFilterProxyModel();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void sort_data();
+ void sort();
+ void sortHierarchy_data();
+ void sortHierarchy();
+
+ void insertRows_data();
+ void insertRows();
+ void prependRow();
+// void insertColumns_data();
+// void insertColumns();
+ void removeRows_data();
+ void removeRows();
+ void removeColumns_data();
+ void removeColumns();
+ void insertAfterSelect();
+ void removeAfterSelect();
+ void filter_data();
+ void filter();
+ void filterHierarchy_data();
+ void filterHierarchy();
+ void filterColumns_data();
+ void filterColumns();
+
+ void filterTable();
+// void filterCurrent();
+
+ void changeSourceLayout();
+ void removeSourceRows_data();
+ void removeSourceRows();
+ void insertSourceRows_data();
+ void insertSourceRows();
+ void changeFilter_data();
+ void changeFilter();
+ void changeSourceData_data();
+ void changeSourceData();
+ void sortFilterRole();
+ void selectionFilteredOut();
+ void match_data();
+ void match();
+ void insertIntoChildrenlessItem();
+ void invalidateMappedChildren();
+ void insertRowIntoFilteredParent();
+ void filterOutParentAndFilterInChild();
+
+ void sourceInsertRows();
+ void sourceModelDeletion();
+
+ void sortColumnTracking1();
+ void sortColumnTracking2();
+
+ void sortStable();
+
+ void task236755_hiddenColumns();
+ void task247867_insertRowsSort();
+ void task248868_staticSorting();
+ void task248868_dynamicSorting();
+ void task250023_fetchMore();
+ void task251296_hiddenChildren();
+ void task252507_mapFromToSource();
+ void task255652_removeRowsRecursive();
+ void taskQTBUG_6205_doubleProxySelectionSetSourceModel();
+ void taskQTBUG_7537_appearsAndSort();
+ void taskQTBUG_7716_unnecessaryDynamicSorting();
+ void taskQTBUG_10287_unnecessaryMapCreation();
+ void taskQTBUG_17812_resetInvalidate_data();
+ void taskQTBUG_17812_resetInvalidate();
+
+ void testMultipleProxiesWithSelection();
+ void mapSelectionFromSource();
+ void filteredColumns();
+
+protected:
+ void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
+ void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
+
+private:
+ QStandardItemModel *m_model;
+ QSortFilterProxyModel *m_proxy;
+};
+
+// Testing get/set functions
+void tst_QSortFilterProxyModel::getSetCheck()
+{
+ QSortFilterProxyModel obj1;
+ QCOMPARE(obj1.sourceModel(), (QAbstractItemModel *)0);
+ // int QSortFilterProxyModel::filterKeyColumn()
+ // void QSortFilterProxyModel::setFilterKeyColumn(int)
+ obj1.setFilterKeyColumn(0);
+ QCOMPARE(0, obj1.filterKeyColumn());
+ obj1.setFilterKeyColumn(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.filterKeyColumn());
+ obj1.setFilterKeyColumn(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.filterKeyColumn());
+}
+
+tst_QSortFilterProxyModel::tst_QSortFilterProxyModel()
+ : m_model(0), m_proxy(0)
+{
+
+}
+
+tst_QSortFilterProxyModel::~tst_QSortFilterProxyModel()
+{
+
+}
+
+void tst_QSortFilterProxyModel::initTestCase()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ qRegisterMetaType<IntList>("IntList");
+ qRegisterMetaType<IntPair>("IntPair");
+ qRegisterMetaType<IntPairList>("IntPairList");
+ m_model = new QStandardItemModel(0, 1);
+ m_proxy = new QSortFilterProxyModel();
+ m_proxy->setSourceModel(m_model);
+}
+
+void tst_QSortFilterProxyModel::cleanupTestCase()
+{
+ delete m_proxy;
+ delete m_model;
+}
+
+void tst_QSortFilterProxyModel::init()
+{
+}
+
+void tst_QSortFilterProxyModel::cleanup()
+{
+ m_proxy->setFilterRegExp(QRegExp());
+ m_proxy->sort(-1, Qt::AscendingOrder);
+ m_model->clear();
+ m_model->insertColumns(0, 1);
+}
+
+/*
+ tests
+*/
+
+void tst_QSortFilterProxyModel::sort_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<int>("sortCaseSensitivity");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat descending") << static_cast<int>(Qt::DescendingOrder)
+ << int(Qt::CaseSensitive)
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "zulu"
+ << "yankee"
+ << "xray"
+ << "whiskey"
+ << "viktor"
+ << "uniform"
+ << "tango"
+ << "sierra"
+ << "romeo"
+ << "quebec"
+ << "papa"
+ << "oskar"
+ << "november"
+ << "mike"
+ << "lima"
+ << "kilo"
+ << "juliet"
+ << "india"
+ << "hotel"
+ << "golf"
+ << "foxtrot"
+ << "echo"
+ << "delta"
+ << "charlie"
+ << "bravo"
+ << "alpha");
+ QTest::newRow("flat ascending") << static_cast<int>(Qt::AscendingOrder)
+ << int(Qt::CaseSensitive)
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "alpha"
+ << "bravo"
+ << "charlie"
+ << "delta"
+ << "echo"
+ << "foxtrot"
+ << "golf"
+ << "hotel"
+ << "india"
+ << "juliet"
+ << "kilo"
+ << "lima"
+ << "mike"
+ << "november"
+ << "oskar"
+ << "papa"
+ << "quebec"
+ << "romeo"
+ << "sierra"
+ << "tango"
+ << "uniform"
+ << "viktor"
+ << "whiskey"
+ << "xray"
+ << "yankee"
+ << "zulu");
+ QTest::newRow("case insensitive") << static_cast<int>(Qt::AscendingOrder)
+ << int(Qt::CaseInsensitive)
+ << (QStringList()
+ << "alpha" << "BETA" << "Gamma" << "delta")
+ << (QStringList()
+ << "alpha" << "BETA" << "delta" << "Gamma");
+ QTest::newRow("case sensitive") << static_cast<int>(Qt::AscendingOrder)
+ << int(Qt::CaseSensitive)
+ << (QStringList()
+ << "alpha" << "BETA" << "Gamma" << "delta")
+ << (QStringList()
+ << "BETA" << "Gamma" << "alpha" << "delta");
+
+
+ QStringList list;
+ for (int i = 10000; i < 20000; ++i)
+ list.append(QString("Number: %1").arg(i));
+ QTest::newRow("large set ascending") << static_cast<int>(Qt::AscendingOrder) << int(Qt::CaseSensitive) << list << list;
+}
+
+void tst_QSortFilterProxyModel::sort()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(int, sortCaseSensitivity);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+
+ // prepare model
+ QStandardItem *root = m_model->invisibleRootItem ();
+ QList<QStandardItem *> items;
+ for (int i = 0; i < initial.count(); ++i) {
+ items.append(new QStandardItem(initial.at(i)));
+ }
+ root->insertRows(0, items);
+ QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
+ QCOMPARE(m_model->columnCount(QModelIndex()), 1);
+
+ // make sure the proxy is unsorted
+ QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
+ QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // sort
+ m_proxy->sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ m_proxy->setSortCaseSensitivity(static_cast<Qt::CaseSensitivity>(sortCaseSensitivity));
+
+ // make sure the model is unchanged
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+ // make sure the proxy is sorted
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // restore the unsorted order
+ m_proxy->sort(-1);
+
+ // make sure the proxy is unsorted again
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+}
+
+void tst_QSortFilterProxyModel::sortHierarchy_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+#if 1
+ QTest::newRow("flat ascending")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList()
+ << "c" << "f" << "d" << "e" << "a" << "b")
+ << (QStringList()
+ << "a" << "b" << "c" << "d" << "e" << "f");
+#endif
+ QTest::newRow("simple hierarchy")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">")
+ << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">");
+
+#if 1
+ QTest::newRow("hierarchical ascending")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList()
+ << "c"
+ << "<"
+ << "h"
+ << "<"
+ << "2"
+ << "0"
+ << "1"
+ << ">"
+ << "g"
+ << "i"
+ << ">"
+ << "b"
+ << "<"
+ << "l"
+ << "k"
+ << "<"
+ << "8"
+ << "7"
+ << "9"
+ << ">"
+ << "m"
+ << ">"
+ << "a"
+ << "<"
+ << "z"
+ << "y"
+ << "x"
+ << ">")
+ << (QStringList()
+ << "a"
+ << "<"
+ << "x"
+ << "y"
+ << "z"
+ << ">"
+ << "b"
+ << "<"
+ << "k"
+ << "<"
+ << "7"
+ << "8"
+ << "9"
+ << ">"
+ << "l"
+ << "m"
+ << ">"
+ << "c"
+ << "<"
+ << "g"
+ << "h"
+ << "<"
+ << "0"
+ << "1"
+ << "2"
+ << ">"
+ << "i"
+ << ">");
+#endif
+}
+
+void tst_QSortFilterProxyModel::sortHierarchy()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+
+ buildHierarchy(initial, m_model);
+ checkHierarchy(initial, m_model);
+ checkHierarchy(initial, m_proxy);
+ m_proxy->sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ checkHierarchy(initial, m_model);
+ checkHierarchy(expected, m_proxy);
+}
+
+void tst_QSortFilterProxyModel::insertRows_data()
+{
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+ QTest::addColumn<QStringList>("insert");
+ QTest::addColumn<int>("position");
+
+ QTest::newRow("insert one row in the middle")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "Three")
+ << 2;
+
+ QTest::newRow("insert one row in the begining")
+ << (QStringList()
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "One")
+ << 0;
+
+ QTest::newRow("insert one row in the end")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ <<"Five")
+ << 4;
+}
+
+void tst_QSortFilterProxyModel::insertRows()
+{
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ QFETCH(QStringList, insert);
+ QFETCH(int, position);
+ // prepare model
+ m_model->insertRows(0, initial.count(), QModelIndex());
+ //m_model->insertColumns(0, 1, QModelIndex());
+ QCOMPARE(m_model->columnCount(QModelIndex()), 1);
+ QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ m_model->setData(index, initial.at(row), Qt::DisplayRole);
+ }
+ // make sure the model correct before insert
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+ // make sure the proxy is correct before insert
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // insert the row
+ m_proxy->insertRows(position, insert.count(), QModelIndex());
+ QCOMPARE(m_model->rowCount(QModelIndex()), expected.count());
+ QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
+
+ // set the data for the inserted row
+ for (int i = 0; i < insert.count(); ++i) {
+ QModelIndex index = m_proxy->index(position + i, 0, QModelIndex());
+ m_proxy->setData(index, insert.at(i), Qt::DisplayRole);
+ }
+
+ // make sure the model correct after insert
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // make sure the proxy is correct after insert
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+void tst_QSortFilterProxyModel::prependRow()
+{
+ //this tests that data is correctly handled by the sort filter when prepending a row
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QStandardItem item("root");
+ model.appendRow(&item);
+
+ QStandardItem sub("sub");
+ item.appendRow(&sub);
+
+ sub.appendRow(new QStandardItem("test1"));
+ sub.appendRow(new QStandardItem("test2"));
+
+ QStandardItem sub2("sub2");
+ sub2.appendRow(new QStandardItem("sub3"));
+ item.insertRow(0, &sub2);
+
+ QModelIndex index_sub2 = proxy.mapFromSource(model.indexFromItem(&sub2));
+
+ QCOMPARE(sub2.rowCount(), proxy.rowCount(index_sub2));
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there
+}
+
+
+/*
+void tst_QSortFilterProxyModel::insertColumns_data()
+{
+
+}
+
+void tst_QSortFilterProxyModel::insertColumns()
+{
+
+}
+*/
+
+void tst_QSortFilterProxyModel::removeRows_data()
+{
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<int>("position");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<bool>("success");
+ QTest::addColumn<QStringList>("expectedProxy");
+ QTest::addColumn<QStringList>("expectedSource");
+
+ QTest::newRow("remove one row in the middle [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove one row in the beginning [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 0 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove one row in the end [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 4 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four");
+
+ QTest::newRow("remove all [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 0 // position
+ << 5 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << QStringList(); // expectedSource
+
+ QTest::newRow("remove one row past the end [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 5 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove row -1 [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << -1 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove three rows in the middle [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 1 // position
+ << 3 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Five");
+
+ QTest::newRow("remove one row in the middle [ascending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QString() // no filter
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "2"
+ << "4");
+
+ QTest::newRow("remove two rows in the middle [ascending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QString() // no filter
+ << 2 // position
+ << 2 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "2");
+
+ QTest::newRow("remove two rows in the middle [descending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QString() // no filter
+ << 2 // position
+ << 2 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "5"
+ << "4"
+ << "1")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "4");
+
+ QTest::newRow("remove one row in the middle [no sorting, filter=5|2|3]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << -1 // no sorting
+ << QString("5|2|3")
+ << 1 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "5"
+ << "3")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "4"
+ << "3");
+
+ QTest::newRow("remove all [ascending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QString() // no filter
+ << 0 // position
+ << 5 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << QStringList(); // expectedSource
+}
+
+void tst_QSortFilterProxyModel::removeRows()
+{
+ QFETCH(QStringList, initial);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(int, position);
+ QFETCH(int, count);
+ QFETCH(bool, success);
+ QFETCH(QStringList, expectedProxy);
+ QFETCH(QStringList, expectedSource);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ // prepare model
+ foreach (QString s, initial)
+ model.appendRow(new QStandardItem(s));
+
+ if (sortOrder != -1)
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ if (!filter.isEmpty())
+ proxy.setFilterRegExp(QRegExp(filter));
+
+ // remove the rows
+ QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success);
+ QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count());
+ QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.count());
+
+ // make sure the model is correct after remove
+ for (int row = 0; row < model.rowCount(QModelIndex()); ++row)
+ QCOMPARE(model.item(row)->text(), expectedSource.at(row));
+
+ // make sure the proxy is correct after remove
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedProxy.at(row));
+ }
+}
+
+class MyFilteredColumnProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ MyFilteredColumnProxyModel(QObject *parent = 0)
+ : QSortFilterProxyModel(parent) { }
+protected:
+ bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const
+ {
+ QString key = sourceModel()->headerData(sourceColumn, Qt::Horizontal).toString();
+ return key.contains(filterRegExp());
+ }
+};
+
+void tst_QSortFilterProxyModel::removeColumns_data()
+{
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<int>("position");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<bool>("success");
+ QTest::addColumn<QStringList>("expectedProxy");
+ QTest::addColumn<QStringList>("expectedSource");
+
+ QTest::newRow("remove one column in the middle [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove one column in the end [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 4 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "3"
+ << "4")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4");
+
+ QTest::newRow("remove one column past the end [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 5 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove column -1 [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << -1 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove all columns [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 0 // position
+ << 5 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << QStringList(); // expectedSource
+
+ QTest::newRow("remove one column in the middle [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 1 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove one column in the end [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "3")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4");
+
+ QTest::newRow("remove one column past the end [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 3 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "3"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove all columns [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 0 // position
+ << 3 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << (QStringList() // expectedSource
+ << "2"
+ << "4");
+}
+
+void tst_QSortFilterProxyModel::removeColumns()
+{
+ QFETCH(QStringList, initial);
+ QFETCH(QString, filter);
+ QFETCH(int, position);
+ QFETCH(int, count);
+ QFETCH(bool, success);
+ QFETCH(QStringList, expectedProxy);
+ QFETCH(QStringList, expectedSource);
+
+ QStandardItemModel model;
+ MyFilteredColumnProxyModel proxy;
+ proxy.setSourceModel(&model);
+ if (!filter.isEmpty())
+ proxy.setFilterRegExp(QRegExp(filter));
+
+ // prepare model
+ model.setHorizontalHeaderLabels(initial);
+
+ // remove the columns
+ QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success);
+ QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count());
+ QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.count());
+
+ // make sure the model is correct after remove
+ for (int col = 0; col < model.columnCount(QModelIndex()); ++col)
+ QCOMPARE(model.horizontalHeaderItem(col)->text(), expectedSource.at(col));
+
+ // make sure the proxy is correct after remove
+ for (int col = 0; col < proxy.columnCount(QModelIndex()); ++col) {
+ QCOMPARE(proxy.headerData(col, Qt::Horizontal, Qt::DisplayRole).toString(),
+ expectedProxy.at(col));
+ }
+}
+
+
+void tst_QSortFilterProxyModel::filterColumns_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<bool>("data");
+
+ QTest::newRow("all") << "a"
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima")
+ << true;
+
+ QTest::newRow("some") << "lie"
+ << (QStringList()
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel")
+ << true;
+
+ QTest::newRow("nothing") << "zoo"
+ << (QStringList()
+ << "foxtrot"
+ << "uniform"
+ << "alpha"
+ << "golf")
+ << false;
+}
+
+void tst_QSortFilterProxyModel::filterColumns()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(bool, data);
+ // prepare model
+ m_model->setColumnCount(initial.count());
+ m_model->setRowCount(1);
+ QCOMPARE(m_model->columnCount(QModelIndex()), initial.count());
+ QCOMPARE(m_model->rowCount(QModelIndex()), 1);
+ // set data
+ QCOMPARE(m_model->rowCount(QModelIndex()), 1);
+ for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
+ QModelIndex index = m_model->index(0, col, QModelIndex());
+ m_model->setData(index, initial.at(col), Qt::DisplayRole);
+ }
+ m_proxy->setFilterRegExp(pattern);
+ m_proxy->setFilterKeyColumn(-1);
+ // make sure the model is unchanged
+ for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
+ QModelIndex index = m_model->index(0, col, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(col));
+ }
+ // make sure the proxy is filtered
+ QModelIndex index = m_proxy->index(0, 0, QModelIndex());
+ QCOMPARE(index.isValid(), data);
+}
+
+void tst_QSortFilterProxyModel::filter_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat") << "e"
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "charlie"
+ << "juliet"
+ << "hotel"
+ << "echo"
+ << "quebec"
+ << "romeo"
+ << "november"
+ << "whiskey"
+ << "mike"
+ << "sierra");
+}
+
+void tst_QSortFilterProxyModel::filter()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ // prepare model
+ QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex()));
+ QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
+ // set data
+ QCOMPARE(m_model->columnCount(QModelIndex()), 1);
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ m_model->setData(index, initial.at(row), Qt::DisplayRole);
+ }
+ m_proxy->setFilterRegExp(pattern);
+ // make sure the proxy is unfiltered
+ QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
+ QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
+ // make sure the model is unchanged
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+ // make sure the proxy is filtered
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+void tst_QSortFilterProxyModel::filterHierarchy_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat") << ".*oo"
+ << (QStringList()
+ << "foo" << "boo" << "baz" << "moo" << "laa" << "haa")
+ << (QStringList()
+ << "foo" << "boo" << "moo");
+
+ QTest::newRow("simple hierarchy") << "b.*z"
+ << (QStringList() << "baz" << "<" << "boz" << "<" << "moo" << ">" << ">")
+ << (QStringList() << "baz" << "<" << "boz" << ">");
+#if 0
+ QTest::newRow("hierarchical")
+ << (QStringList()
+ << "a"
+ << "<"
+ << "x"
+ << "y"
+ << "z"
+ << ">"
+ << "b"
+ << "<"
+ << "k"
+ << "<"
+ << "7"
+ << "8"
+ << "9"
+ << ">"
+ << "l"
+ << "m"
+ << ">"
+ << "c"
+ << "<"
+ << "g"
+ << "h"
+ << "<"
+ << "0"
+ << "1"
+ << "2"
+ << ">"
+ << "i"
+ << ">")
+ << (QStringList()
+ << "a"
+ << "<"
+ << "x"
+ << "z"
+ << ">"
+ << "c"
+ << "<"
+ << "g"
+ << "i"
+ << ">");
+#endif
+}
+
+void tst_QSortFilterProxyModel::filterHierarchy()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ buildHierarchy(initial, m_model);
+ m_proxy->setFilterRegExp(pattern);
+ checkHierarchy(initial, m_model);
+ checkHierarchy(expected, m_proxy);
+}
+
+void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractItemModel *m)
+{
+ int ind = 0;
+ int row = 0;
+ QStack<int> row_stack;
+ QModelIndex parent;
+ QStack<QModelIndex> parent_stack;
+ for (int i = 0; i < l.count(); ++i) {
+ QString token = l.at(i);
+ if (token == "<") { // start table
+ ++ind;
+ parent_stack.push(parent);
+ row_stack.push(row);
+ parent = m->index(row - 1, 0, parent);
+ row = 0;
+ QVERIFY(m->insertColumns(0, 1, parent)); // add column
+ } else if (token == ">") { // end table
+ --ind;
+ parent = parent_stack.pop();
+ row = row_stack.pop();
+ } else { // append row
+ QVERIFY(m->insertRows(row, 1, parent));
+ QModelIndex index = m->index(row, 0, parent);
+ QVERIFY(index.isValid());
+ m->setData(index, token, Qt::DisplayRole);
+ ++row;
+#if 0
+ {
+ QString txt = token;
+ for (int t = 0; t < ind; ++t)
+ txt.prepend(' ');
+ qDebug() << "#" << txt;
+ }
+#endif
+ }
+ }
+}
+
+void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbstractItemModel *m)
+{
+ int row = 0;
+ int indent = 0;
+ QStack<int> row_stack;
+ QModelIndex parent;
+ QStack<QModelIndex> parent_stack;
+ for (int i = 0; i < l.count(); ++i) {
+ QString token = l.at(i);
+ if (token == "<") { // start table
+ ++indent;
+ parent_stack.push(parent);
+ row_stack.push(row);
+ parent = m->index(row - 1, 0, parent);
+ QVERIFY(parent.isValid());
+ row = 0;
+ } else if (token == ">") { // end table
+ --indent;
+ parent = parent_stack.pop();
+ row = row_stack.pop();
+ } else { // compare row
+ QModelIndex index = m->index(row, 0, parent);
+ QVERIFY(index.isValid());
+ QString str = m->data(index, Qt::DisplayRole).toString();
+#if 0
+ qDebug() << "proxy data is" << str << "level" << indent;
+#endif
+ QCOMPARE(str, token);
+ ++row;
+ }
+ }
+
+}
+
+
+
+class TestModel: public QAbstractTableModel
+{
+public:
+ int rowCount(const QModelIndex &) const { return 10000; }
+ int columnCount(const QModelIndex &) const { return 1; }
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ return QString::number(index.row());
+ }
+};
+
+void tst_QSortFilterProxyModel::filterTable()
+{
+ TestModel model;
+ QSortFilterProxyModel filter;
+ filter.setSourceModel(&model);
+ filter.setFilterRegExp("9");
+
+ for (int i = 0; i < filter.rowCount(); ++i)
+ QVERIFY(filter.data(filter.index(i, 0)).toString().contains("9"));
+}
+
+void tst_QSortFilterProxyModel::insertAfterSelect()
+{
+ QStandardItemModel model(10, 2);
+ for (int i = 0; i<10;i++)
+ model.setData(model.index(i, 0), QVariant(i));
+ QSortFilterProxyModel filter;
+ filter.setSourceModel(&model);
+ QTreeView view;
+ view.setModel(&filter);
+ view.show();
+ QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex()));
+ QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model());
+ QVERIFY(firstIndex.isValid());
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ QPoint p(itemOffset, 1);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0);
+ model.insertRows(5, 1, QModelIndex());
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection
+}
+
+void tst_QSortFilterProxyModel::removeAfterSelect()
+{
+ QStandardItemModel model(10, 2);
+ for (int i = 0; i<10;i++)
+ model.setData(model.index(i, 0), QVariant(i));
+ QSortFilterProxyModel filter;
+ filter.setSourceModel(&model);
+ QTreeView view;
+ view.setModel(&filter);
+ view.show();
+ QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex()));
+ QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model());
+ QVERIFY(firstIndex.isValid());
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ QPoint p(itemOffset, 1);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0);
+ model.removeRows(5, 1, QModelIndex());
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection
+}
+
+#if 0 // this test is disabled for now
+void tst_QSortFilterProxyModel::filterCurrent()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("AAA"));
+ model.setData(model.index(1, 0), QString("BBB"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QTreeView view;
+
+ view.show();
+ view.setModel(&proxy);
+ QSignalSpy spy(view.selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)));
+
+ view.setCurrentIndex(proxy.index(0, 0));
+ QCOMPARE(spy.count(), 1);
+ proxy.setFilterRegExp(QRegExp("^B"));
+ QCOMPARE(spy.count(), 2);
+}
+#endif
+
+void tst_QSortFilterProxyModel::changeSourceLayout()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("b"));
+ model.setData(model.index(1, 0), QString("a"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QList<QPersistentModelIndex> persistentSourceIndexes;
+ QList<QPersistentModelIndex> persistentProxyIndexes;
+ for (int row = 0; row < model.rowCount(); ++row) {
+ persistentSourceIndexes.append(model.index(row, 0));
+ persistentProxyIndexes.append(proxy.index(row, 0));
+ }
+
+ // change layout of source model
+ model.sort(0, Qt::AscendingOrder);
+
+ for (int row = 0; row < model.rowCount(); ++row) {
+ QCOMPARE(persistentProxyIndexes.at(row).row(),
+ persistentSourceIndexes.at(row).row());
+ }
+}
+
+void tst_QSortFilterProxyModel::removeSourceRows_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<IntPairList>("expectedRemovedProxyIntervals");
+ QTest::addColumn<QStringList>("expectedProxyItems");
+
+ QTest::newRow("remove one, no sorting")
+ << (QStringList() << "a" << "b") // sourceItems
+ << 0 // start
+ << 1 // count
+ << -1 // sortOrder (no sorting)
+ << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+ QTest::newRow("remove one, ascending sort (same order)")
+ << (QStringList() << "a" << "b") // sourceItems
+ << 0 // start
+ << 1 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+ QTest::newRow("remove one, ascending sort (reverse order)")
+ << (QStringList() << "b" << "a") // sourceItems
+ << 0 // start
+ << 1 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(1, 1)) // expectedRemovedIntervals
+ << (QStringList() << "a") // expectedProxyItems
+ ;
+ QTest::newRow("remove two, multiple proxy intervals")
+ << (QStringList() << "c" << "d" << "a" << "b") // sourceItems
+ << 1 // start
+ << 2 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(3, 3) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b" << "c") // expectedProxyItems
+ ;
+ QTest::newRow("remove three, multiple proxy intervals")
+ << (QStringList() << "b" << "d" << "f" << "a" << "c" << "e") // sourceItems
+ << 3 // start
+ << 3 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(4, 4) << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b" << "d" << "f") // expectedProxyItems
+ ;
+ QTest::newRow("remove all, single proxy intervals")
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
+ << 0 // start
+ << 6 // count
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << (IntPairList() << IntPair(0, 5)) // expectedRemovedIntervals
+ << QStringList() // expectedProxyItems
+ ;
+}
+
+// Check that correct proxy model rows are removed when rows are removed
+// from the source model
+void tst_QSortFilterProxyModel::removeSourceRows()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, start);
+ QFETCH(int, count);
+ QFETCH(int, sortOrder);
+ QFETCH(IntPairList, expectedRemovedProxyIntervals);
+ QFETCH(QStringList, expectedProxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex sindex = model.index(i, 0, QModelIndex());
+ model.setData(sindex, sourceItems.at(i), Qt::DisplayRole);
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole));
+ }
+
+ if (sortOrder != -1)
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ QSignalSpy removeSpy(&proxy, SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ QSignalSpy insertSpy(&proxy, SIGNAL(rowsInserted(QModelIndex, int, int)));
+ QSignalSpy aboutToRemoveSpy(&proxy, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ QSignalSpy aboutToInsertSpy(&proxy, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)));
+
+ model.removeRows(start, count, QModelIndex());
+
+ QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < aboutToRemoveSpy.count(); ++i) {
+ QList<QVariant> args = aboutToRemoveSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+ QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < removeSpy.count(); ++i) {
+ QList<QVariant> args = removeSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+
+ QCOMPARE(insertSpy.count(), 0);
+ QCOMPARE(aboutToInsertSpy.count(), 0);
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count());
+ for (int i = 0; i < expectedProxyItems.count(); ++i) {
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::insertSourceRows_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<QStringList>("newItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("proxyItems");
+
+ QTest::newRow("insert (1)")
+ << (QStringList() << "c" << "b") // sourceItems
+ << 1 // start
+ << (QStringList() << "a") // newItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (QStringList() << "a" << "b" << "c") // proxyItems
+ ;
+
+ QTest::newRow("insert (2)")
+ << (QStringList() << "d" << "b" << "c") // sourceItems
+ << 3 // start
+ << (QStringList() << "a") // newItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << (QStringList() << "d" << "c" << "b" << "a") // proxyItems
+ ;
+}
+
+// Check that rows are inserted at correct position in proxy model when
+// rows are inserted into the source model
+void tst_QSortFilterProxyModel::insertSourceRows()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, start);
+ QFETCH(QStringList, newItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, proxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ model.insertRows(start, newItems.size(), QModelIndex());
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count());
+ for (int i = 0; i < newItems.count(); ++i) {
+ QModelIndex index = model.index(start + i, 0, QModelIndex());
+ model.setData(index, newItems.at(i), Qt::DisplayRole);
+ }
+
+ for (int i = 0; i < proxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::changeFilter_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("initialFilter");
+ QTest::addColumn<IntPairList>("initialRemoveIntervals");
+ QTest::addColumn<QStringList>("initialProxyItems");
+ QTest::addColumn<QString>("finalFilter");
+ QTest::addColumn<IntPairList>("finalRemoveIntervals");
+ QTest::addColumn<IntPairList>("insertIntervals");
+ QTest::addColumn<QStringList>("finalProxyItems");
+
+ QTest::newRow("filter (1)")
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|b|c" // initialFilter
+ << (IntPairList() << IntPair(3, 5)) // initialRemoveIntervals
+ << (QStringList() << "a" << "b" << "c") // initialProxyItems
+ << "b|d|f" // finalFilter
+ << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // finalRemoveIntervals
+ << (IntPairList() << IntPair(1, 2)) // insertIntervals
+ << (QStringList() << "b" << "d" << "f") // finalProxyItems
+ ;
+
+ QTest::newRow("filter (2)")
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c|e" // initialFilter
+ << (IntPairList() << IntPair(5, 5) << IntPair(3, 3) << IntPair(1, 1)) // initialRemoveIntervals
+ << (QStringList() << "a" << "c" << "e") // initialProxyItems
+ << "" // finalFilter
+ << IntPairList() // finalRemoveIntervals
+ << (IntPairList() << IntPair(3, 3) << IntPair(2, 2) << IntPair(1, 1)) // insertIntervals
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // finalProxyItems
+ ;
+
+ QTest::newRow("filter (3)")
+ << (QStringList() << "a" << "b" << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a" // initialFilter
+ << (IntPairList() << IntPair(1, 2)) // initialRemoveIntervals
+ << (QStringList() << "a") // initialProxyItems
+ << "a" // finalFilter
+ << IntPairList() // finalRemoveIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "a") // finalProxyItems
+ ;
+}
+
+// Check that rows are added/removed when filter changes
+void tst_QSortFilterProxyModel::changeFilter()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, initialFilter);
+ QFETCH(IntPairList, initialRemoveIntervals);
+ QFETCH(QStringList, initialProxyItems);
+ QFETCH(QString, finalFilter);
+ QFETCH(IntPairList, finalRemoveIntervals);
+ QFETCH(IntPairList, insertIntervals);
+ QFETCH(QStringList, finalProxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ QSignalSpy initialRemoveSpy(&proxy, SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ QSignalSpy initialInsertSpy(&proxy, SIGNAL(rowsInserted(QModelIndex, int, int)));
+
+ proxy.setFilterRegExp(initialFilter);
+
+ QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count());
+ QCOMPARE(initialInsertSpy.count(), 0);
+ for (int i = 0; i < initialRemoveSpy.count(); ++i) {
+ QList<QVariant> args = initialRemoveSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), initialRemoveIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), initialRemoveIntervals.at(i).second);
+ }
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.count());
+ for (int i = 0; i < initialProxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initialProxyItems.at(i));
+ }
+
+ QSignalSpy finalRemoveSpy(&proxy, SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ QSignalSpy finalInsertSpy(&proxy, SIGNAL(rowsInserted(QModelIndex, int, int)));
+
+ proxy.setFilterRegExp(finalFilter);
+
+ QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count());
+ for (int i = 0; i < finalRemoveSpy.count(); ++i) {
+ QList<QVariant> args = finalRemoveSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), finalRemoveIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), finalRemoveIntervals.at(i).second);
+ }
+
+#ifdef Q_OS_IRIX
+ QEXPECT_FAIL("filter (2)", "Not reliable on IRIX", Abort);
+#endif
+ QCOMPARE(finalInsertSpy.count(), insertIntervals.count());
+ for (int i = 0; i < finalInsertSpy.count(); ++i) {
+ QList<QVariant> args = finalInsertSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second);
+ }
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.count());
+ for (int i = 0; i < finalProxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), finalProxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::changeSourceData_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<bool>("dynamic");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<QString>("newValue");
+ QTest::addColumn<IntPairList>("removeIntervals");
+ QTest::addColumn<IntPairList>("insertIntervals");
+ QTest::addColumn<QStringList>("proxyItems");
+
+ QTest::newRow("changeSourceData (1)")
+ << (QStringList() << "c" << "b" << "a") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << true // dynamic
+ << 2 // row
+ << "z" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "b" << "c" << "z") // proxyItems
+ ;
+
+ QTest::newRow("changeSourceData (2)")
+ << (QStringList() << "b" << "c" << "z") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "" // filter
+ << true // dynamic
+ << 1 // row
+ << "a" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "z" << "b" << "a") // proxyItems
+ ;
+
+ QTest::newRow("changeSourceData (3)")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "" // filter
+ << true // dynamic
+ << 0 // row
+ << "a" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "b" << "a") // proxyItems
+ ;
+
+ QTest::newRow("changeSourceData (4)")
+ << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c" // filter
+ << true // dynamic
+ << 1 // row
+ << "x" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "a" << "c") // proxyItems
+ ;
+
+ QTest::newRow("changeSourceData (5)")
+ << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c|x" // filter
+ << true // dynamic
+ << 1 // row
+ << "x" // newValue
+ << IntPairList() // removeIntervals
+ << (IntPairList() << IntPair(2, 2)) // insertIntervals
+ << (QStringList() << "a" << "c" << "x") // proxyItems
+ ;
+
+ QTest::newRow("changeSourceData (6)")
+ << (QStringList() << "c" << "b" << "a") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << false // dynamic
+ << 2 // row
+ << "x" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "x" << "b" << "c") // proxyItems
+ ;
+}
+
+void tst_QSortFilterProxyModel::changeSourceData()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(bool, dynamic);
+ QFETCH(int, row);
+ QFETCH(QString, newValue);
+ QFETCH(IntPairList, removeIntervals);
+ QFETCH(IntPairList, insertIntervals);
+ QFETCH(QStringList, proxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setDynamicSortFilter(dynamic);
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ proxy.setFilterRegExp(filter);
+
+ QSignalSpy removeSpy(&proxy, SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ QSignalSpy insertSpy(&proxy, SIGNAL(rowsInserted(QModelIndex, int, int)));
+
+ {
+ QModelIndex index = model.index(row, 0, QModelIndex());
+ model.setData(index, newValue, Qt::DisplayRole);
+ }
+
+ QCOMPARE(removeSpy.count(), removeIntervals.count());
+ for (int i = 0; i < removeSpy.count(); ++i) {
+ QList<QVariant> args = removeSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), removeIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), removeIntervals.at(i).second);
+ }
+
+ QCOMPARE(insertSpy.count(), insertIntervals.count());
+ for (int i = 0; i < insertSpy.count(); ++i) {
+ QList<QVariant> args = insertSpy.at(i);
+ QVERIFY(args.at(1).type() == QVariant::Int);
+ QVERIFY(args.at(2).type() == QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second);
+ }
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count());
+ for (int i = 0; i < proxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::sortFilterRole()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+
+ QList<QPair<QVariant, QVariant> > sourceItems;
+ sourceItems = QList<QPair<QVariant, QVariant> >()
+ << QPair<QVariant, QVariant>("b", 3)
+ << QPair<QVariant, QVariant>("c", 2)
+ << QPair<QVariant, QVariant>("a", 1);
+
+ QList<int> orderedItems;
+ orderedItems = QList<int>()
+ << 2 << 1;
+
+ model.insertRows(0, sourceItems.count());
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i).first, Qt::DisplayRole);
+ model.setData(index, sourceItems.at(i).second, Qt::UserRole);
+ }
+
+ proxy.setFilterRegExp("2");
+ QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role
+
+ proxy.setFilterRole(Qt::UserRole);
+ QCOMPARE(proxy.rowCount(), 1);
+
+ proxy.setFilterRole(Qt::DisplayRole);
+ QCOMPARE(proxy.rowCount(), 0);
+
+ proxy.setFilterRegExp("1|2|3");
+ QCOMPARE(proxy.rowCount(), 0);
+
+ proxy.setFilterRole(Qt::UserRole);
+ QCOMPARE(proxy.rowCount(), 3);
+
+ proxy.sort(0, Qt::AscendingOrder);
+ QCOMPARE(proxy.rowCount(), 3);
+
+ proxy.setSortRole(Qt::UserRole);
+ proxy.setFilterRole(Qt::DisplayRole);
+ proxy.setFilterRegExp("a|c");
+ QCOMPARE(proxy.rowCount(), orderedItems.count());
+ for (int i = 0; i < proxy.rowCount(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole), sourceItems.at(orderedItems.at(i)).first);
+ }
+}
+
+void tst_QSortFilterProxyModel::selectionFilteredOut()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("AAA"));
+ model.setData(model.index(1, 0), QString("BBB"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QTreeView view;
+
+ view.show();
+ view.setModel(&proxy);
+ QSignalSpy spy(view.selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)));
+
+ view.setCurrentIndex(proxy.index(0, 0));
+ QCOMPARE(spy.count(), 1);
+ proxy.setFilterRegExp(QRegExp("^B"));
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QSortFilterProxyModel::match_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<int>("proxyStartRow");
+ QTest::addColumn<QString>("what");
+ QTest::addColumn<int>("matchFlags");
+ QTest::addColumn<IntList>("expectedProxyItems");
+ QTest::newRow("1")
+ << (QStringList() << "a") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << 0 // proxyStartRow
+ << "a" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 0); // expectedProxyItems
+ QTest::newRow("2")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << 0 // proxyStartRow
+ << "b" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 1); // expectedProxyItems
+ QTest::newRow("3")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "" // filter
+ << 0 // proxyStartRow
+ << "a" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 1); // expectedProxyItems
+ QTest::newRow("4")
+ << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << 1 // proxyStartRow
+ << "a" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << IntList(); // expectedProxyItems
+ QTest::newRow("5")
+ << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|b" // filter
+ << 0 // proxyStartRow
+ << "c" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << IntList(); // expectedProxyItems
+ QTest::newRow("6")
+ << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "a|b" // filter
+ << 0 // proxyStartRow
+ << "b" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 0); // expectedProxyItems
+}
+
+void tst_QSortFilterProxyModel::match()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(int, proxyStartRow);
+ QFETCH(QString, what);
+ QFETCH(int, matchFlags);
+ QFETCH(IntList, expectedProxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ proxy.setFilterRegExp(filter);
+
+ QModelIndex startIndex = proxy.index(proxyStartRow, 0);
+ QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what,
+ expectedProxyItems.count(),
+ Qt::MatchFlags(matchFlags));
+ QCOMPARE(indexes.count(), expectedProxyItems.count());
+ for (int i = 0; i < indexes.count(); ++i)
+ QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i));
+}
+
+void tst_QSortFilterProxyModel::insertIntoChildrenlessItem()
+{
+ QStandardItemModel model;
+ QStandardItem *itemA = new QStandardItem("a");
+ model.appendRow(itemA);
+ QStandardItem *itemB = new QStandardItem("b");
+ model.appendRow(itemB);
+ QStandardItem *itemC = new QStandardItem("c");
+ model.appendRow(itemC);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QSignalSpy colsInsertedSpy(&proxy, SIGNAL(columnsInserted(const QModelIndex&, int, int)));
+ QSignalSpy rowsInsertedSpy(&proxy, SIGNAL(rowsInserted(const QModelIndex&, int, int)));
+
+ (void)proxy.rowCount(QModelIndex()); // force mapping of "a", "b", "c"
+ QCOMPARE(colsInsertedSpy.count(), 0);
+ QCOMPARE(rowsInsertedSpy.count(), 0);
+
+ // now add a child to itemB ==> should get insert notification from the proxy
+ itemB->appendRow(new QStandardItem("a.0"));
+ QCOMPARE(colsInsertedSpy.count(), 1);
+ QCOMPARE(rowsInsertedSpy.count(), 1);
+
+ QVariantList args = colsInsertedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index()));
+ QCOMPARE(qvariant_cast<int>(args.at(1)), 0);
+ QCOMPARE(qvariant_cast<int>(args.at(2)), 0);
+
+ args = rowsInsertedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index()));
+ QCOMPARE(qvariant_cast<int>(args.at(1)), 0);
+ QCOMPARE(qvariant_cast<int>(args.at(2)), 0);
+}
+
+void tst_QSortFilterProxyModel::invalidateMappedChildren()
+{
+ QStandardItemModel model;
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QStandardItem *itemA = new QStandardItem("a");
+ model.appendRow(itemA);
+ QStandardItem *itemB = new QStandardItem("b");
+ itemA->appendRow(itemB);
+
+ QStandardItem *itemC = new QStandardItem("c");
+ itemB->appendRow(itemC);
+ itemC->appendRow(new QStandardItem("d"));
+
+ // force mappings
+ (void)proxy.hasChildren(QModelIndex());
+ (void)proxy.hasChildren(proxy.mapFromSource(itemA->index()));
+ (void)proxy.hasChildren(proxy.mapFromSource(itemB->index()));
+ (void)proxy.hasChildren(proxy.mapFromSource(itemC->index()));
+
+ itemB->removeRow(0); // should invalidate mapping of itemC
+ itemC = new QStandardItem("c");
+ itemA->appendRow(itemC);
+ itemC->appendRow(new QStandardItem("d"));
+
+ itemA->removeRow(1); // should invalidate mapping of itemC
+ itemC = new QStandardItem("c");
+ itemB->appendRow(itemC);
+ itemC->appendRow(new QStandardItem("d"));
+
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemA->index())), 1);
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemB->index())), 1);
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemC->index())), 1);
+}
+
+class EvenOddFilterModel : public QSortFilterProxyModel
+{
+public:
+ virtual bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const
+ {
+ if (srcParent.isValid())
+ return (srcParent.row() % 2) ^ !(srcRow % 2);
+ return (srcRow % 2);
+ }
+};
+
+void tst_QSortFilterProxyModel::insertRowIntoFilteredParent()
+{
+ QStandardItemModel model;
+ EvenOddFilterModel proxy;
+ proxy.setSourceModel(&model);
+
+ QSignalSpy spy(&proxy, SIGNAL(rowsInserted(const QModelIndex&, int, int)));
+
+ QStandardItem *itemA = new QStandardItem();
+ model.appendRow(itemA); // A will be filtered
+ QStandardItem *itemB = new QStandardItem();
+ itemA->appendRow(itemB);
+
+ QCOMPARE(spy.count(), 0);
+
+ itemA->removeRow(0);
+
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ proxy.setFilterRegExp("A|B");
+ QStandardItem *itemA = new QStandardItem("A");
+ model.appendRow(itemA); // not filtered
+ QStandardItem *itemB = new QStandardItem("B");
+ itemA->appendRow(itemB); // not filtered
+ QStandardItem *itemC = new QStandardItem("C");
+ itemA->appendRow(itemC); // filtered
+
+ QSignalSpy removedSpy(&proxy, SIGNAL(rowsRemoved(const QModelIndex&, int, int)));
+ QSignalSpy insertedSpy(&proxy, SIGNAL(rowsInserted(const QModelIndex&, int, int)));
+
+ proxy.setFilterRegExp("C"); // A and B will be filtered out, C filtered in
+
+ // we should now have been notified that the subtree represented by itemA has been removed
+ QCOMPARE(removedSpy.count(), 1);
+ // we should NOT get any inserts; itemC should be filtered because its parent (itemA) is
+ QCOMPARE(insertedSpy.count(), 0);
+}
+
+void tst_QSortFilterProxyModel::sourceInsertRows()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ model.insertColumns(0, 1, QModelIndex());
+ model.insertRows(0, 2, QModelIndex());
+
+ {
+ QModelIndex parent = model.index(0, 0, QModelIndex());
+ model.insertColumns(0, 1, parent);
+ model.insertRows(0, 1, parent);
+ }
+
+ {
+ QModelIndex parent = model.index(1, 0, QModelIndex());
+ model.insertColumns(0, 1, parent);
+ model.insertRows(0, 1, parent);
+ }
+
+ model.insertRows(0, 1, QModelIndex());
+ model.insertRows(0, 1, QModelIndex());
+
+ QVERIFY(true); // if you got here without asserting, it's all good
+}
+
+void tst_QSortFilterProxyModel::sourceModelDeletion()
+{
+
+ QSortFilterProxyModel proxyModel;
+ {
+ QStandardItemModel model;
+ proxyModel.setSourceModel(&model);
+ QCOMPARE(proxyModel.sourceModel(), static_cast<QAbstractItemModel*>(&model));
+ }
+ QCOMPARE(proxyModel.sourceModel(), static_cast<QAbstractItemModel*>(0));
+
+}
+
+void tst_QSortFilterProxyModel::sortColumnTracking1()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ model.insertColumns(0, 10);
+ model.insertRows(0, 10);
+
+ proxyModel.sort(1);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.insertColumn(8);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.removeColumn(8);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.insertColumn(2);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.removeColumn(2);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.insertColumn(1);
+ QCOMPARE(proxyModel.sortColumn(), 2);
+
+ model.removeColumn(1);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.removeColumn(1);
+ QCOMPARE(proxyModel.sortColumn(), -1);
+}
+
+void tst_QSortFilterProxyModel::sortColumnTracking2()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setDynamicSortFilter(true);
+ proxyModel.setSourceModel(&model);
+
+ proxyModel.sort(0);
+ QCOMPARE(proxyModel.sortColumn(), 0);
+
+ QList<QStandardItem *> items;
+ QStringList strings;
+ strings << "foo" << "bar" << "some" << "others" << "item" << "aa" << "zz";
+ foreach (QString s, strings)
+ items << new QStandardItem(s);
+
+ model.insertColumn(0,items);
+ QCOMPARE(proxyModel.sortColumn(), 0);
+ QCOMPARE(proxyModel.data(proxyModel.index(0,0)).toString(),QString::fromLatin1("aa"));
+ QCOMPARE(proxyModel.data(proxyModel.index(strings.count()-1,0)).toString(),QString::fromLatin1("zz"));
+}
+
+void tst_QSortFilterProxyModel::sortStable()
+{
+ QStandardItemModel* model = new QStandardItemModel(5, 2);
+ for (int r=0; r<5; r++) {
+ for (int c=0; c<2; c++) {
+ QStandardItem* item = new QStandardItem(
+ QString("Row:%0, Column:%1").arg(r).arg(c) );
+ for( int i=0; i<3; i++ ) {
+ QStandardItem* child = new QStandardItem(
+ QString("Item %0").arg(i) );
+ item->appendRow( child );
+ }
+ model->setItem(r, c, item);
+ }
+ }
+ model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" ));
+ model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" ) );
+
+
+ QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model);
+ filterModel->setSourceModel(model);
+
+ QTreeView *view = new QTreeView;
+ view->setModel(filterModel);
+ QModelIndex firstRoot = filterModel->index(0,0);
+ view->expand(firstRoot);
+ view->setSortingEnabled(true);
+
+ view->model()->sort(1, Qt::DescendingOrder);
+ QVariant lastItemData =filterModel->index(2,0, firstRoot).data();
+ view->model()->sort(1, Qt::DescendingOrder);
+ QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data());
+}
+
+void tst_QSortFilterProxyModel::task236755_hiddenColumns()
+{
+ class MyStandardItemModel : public QStandardItemModel
+ {
+ public:
+ MyStandardItemModel() : QStandardItemModel(0,5) {}
+ void reset()
+ { QStandardItemModel::reset(); }
+ friend class tst_QSortFilterProxyModel;
+ } model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QTableView view;
+ view.setModel(&proxy);
+
+ view.hideColumn(0);
+
+ QVERIFY(view.isColumnHidden(0));
+ model.blockSignals(true);
+ model.setRowCount(1);
+ model.blockSignals(false);
+ model.reset();
+
+ //in the initial task this would be false because resetting
+ //model would also reset the hidden columns
+ QVERIFY(view.isColumnHidden(0));
+}
+
+void tst_QSortFilterProxyModel::task247867_insertRowsSort()
+{
+ QStandardItemModel model(2,2);
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ proxyModel.sort(0);
+ QCOMPARE(proxyModel.sortColumn(), 0);
+
+ model.insertColumns(0, 3, model.index(0,0));
+ QCOMPARE(proxyModel.sortColumn(), 0);
+
+ model.removeColumns(0, 3, model.index(0,0));
+ QCOMPARE(proxyModel.sortColumn(), 0);
+}
+
+void tst_QSortFilterProxyModel::task248868_staticSorting()
+{
+ QStandardItemModel model(0, 1);
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(false);
+ QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(" ");
+
+ // prepare model
+ QStandardItem *root = model.invisibleRootItem ();
+ QList<QStandardItem *> items;
+ for (int i = 0; i < initial.count(); ++i) {
+ items.append(new QStandardItem(initial.at(i)));
+ }
+ root->insertRows(0, items);
+ QCOMPARE(model.rowCount(QModelIndex()), initial.count());
+ QCOMPARE(model.columnCount(QModelIndex()), 1);
+
+ // make sure the proxy is unsorted
+ QCOMPARE(proxy.columnCount(QModelIndex()), 1);
+ QCOMPARE(proxy.rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // sort
+ proxy.sort(0);
+
+ QStringList expected = initial;
+ expected.sort();
+ // make sure the proxy is sorted
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ //update one item.
+ model.setItem(0, 0, new QStandardItem("girafe"));
+
+ // make sure the proxy is updated but not sorted
+ expected.replaceInStrings("bateau", "girafe");
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // sort again
+ proxy.sort(0);
+ expected.sort();
+
+ // make sure the proxy is sorted
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+}
+
+void tst_QSortFilterProxyModel::task248868_dynamicSorting()
+{
+ QStringListModel model1;
+ const QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(" ");
+ model1.setStringList(initial);
+ QSortFilterProxyModel proxy1;
+ proxy1.sort(0);
+ proxy1.setSourceModel(&model1);
+
+ QCOMPARE(proxy1.columnCount(QModelIndex()), 1);
+ //the model should not be sorted because sorting has not been set to dynamic yet.
+ QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ proxy1.setDynamicSortFilter(true);
+
+ //now the model should be sorted.
+ QStringList expected = initial;
+ expected.sort();
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ QStringList initial2 = initial;
+ initial2.replaceInStrings("bateau", "girafe");
+ model1.setStringList(initial2); //this will cause a reset
+
+ QStringList expected2 = initial2;
+ expected2.sort();
+
+ //now the model should still be sorted.
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected2.at(row));
+ }
+
+ QStringListModel model2(initial);
+ proxy1.setSourceModel(&model2);
+
+ //the model should again be sorted
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ //set up the sorting before seting the model up
+ QSortFilterProxyModel proxy2;
+ proxy2.setDynamicSortFilter(true);
+ proxy2.sort(0);
+ proxy2.setSourceModel(&model2);
+ for (int row = 0; row < proxy2.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy2.index(row, 0, QModelIndex());
+ QCOMPARE(proxy2.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+class QtTestModel: public QAbstractItemModel
+{
+ public:
+ QtTestModel(int _rows, int _cols, QObject *parent = 0): QAbstractItemModel(parent),
+ rows(_rows), cols(_cols), wrongIndex(false) { }
+
+ bool canFetchMore(const QModelIndex &idx) const {
+ return !fetched.contains(idx);
+ }
+
+ void fetchMore(const QModelIndex &idx) {
+ if (fetched.contains(idx))
+ return;
+ beginInsertRows(idx, 0, rows-1);
+ fetched.insert(idx);
+ endInsertRows();
+ }
+
+ bool hasChildren(const QModelIndex & = QModelIndex()) const {
+ return true;
+ }
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const {
+ return fetched.contains(parent) ? rows : 0;
+ }
+ int columnCount(const QModelIndex& parent = QModelIndex()) const {
+ Q_UNUSED(parent);
+ return cols;
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+ {
+ if (row < 0 || column < 0 || column >= cols || row >= rows) {
+ return QModelIndex();
+ }
+ QModelIndex i = createIndex(row, column, int(parent.internalId() + 1));
+ parentHash[i] = parent;
+ return i;
+ }
+
+ QModelIndex parent(const QModelIndex &index) const
+ {
+ if (!parentHash.contains(index))
+ return QModelIndex();
+ return parentHash[index];
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (!idx.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole) {
+ if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
+ wrongIndex = true;
+ qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(),
+ idx.internalPointer());
+ }
+ return QString("[%1,%2]").arg(idx.row()).arg(idx.column());
+ }
+ return QVariant();
+ }
+
+ QSet<QModelIndex> fetched;
+ int rows, cols;
+ mutable bool wrongIndex;
+ mutable QMap<QModelIndex,QModelIndex> parentHash;
+};
+
+void tst_QSortFilterProxyModel::task250023_fetchMore()
+{
+ QtTestModel model(10,10);
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QVERIFY(proxy.canFetchMore(QModelIndex()));
+ QVERIFY(proxy.hasChildren());
+ while (proxy.canFetchMore(QModelIndex()))
+ proxy.fetchMore(QModelIndex());
+ QCOMPARE(proxy.rowCount(), 10);
+ QCOMPARE(proxy.columnCount(), 10);
+
+ QModelIndex idx = proxy.index(1,1);
+ QVERIFY(idx.isValid());
+ QVERIFY(proxy.canFetchMore(idx));
+ QVERIFY(proxy.hasChildren(idx));
+ while (proxy.canFetchMore(idx))
+ proxy.fetchMore(idx);
+ QCOMPARE(proxy.rowCount(idx), 10);
+ QCOMPARE(proxy.columnCount(idx), 10);
+}
+
+void tst_QSortFilterProxyModel::task251296_hiddenChildren()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(true);
+
+ QStandardItem *itemA = new QStandardItem("A VISIBLE");
+ model.appendRow(itemA);
+ QStandardItem *itemB = new QStandardItem("B VISIBLE");
+ itemA->appendRow(itemB);
+ QStandardItem *itemC = new QStandardItem("C");
+ itemA->appendRow(itemC);
+ proxy.setFilterRegExp("VISIBLE");
+
+ QCOMPARE(proxy.rowCount(QModelIndex()) , 1);
+ QPersistentModelIndex indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE"));
+
+ QCOMPARE(proxy.rowCount(indexA) , 1);
+ QPersistentModelIndex indexB = proxy.index(0, 0, indexA);
+ QCOMPARE(proxy.data(indexB).toString(), QString::fromLatin1("B VISIBLE"));
+
+ itemA->setText("A");
+ QCOMPARE(proxy.rowCount(QModelIndex()), 0);
+ QVERIFY(!indexA.isValid());
+ QVERIFY(!indexB.isValid());
+
+ itemB->setText("B");
+ itemA->setText("A VISIBLE");
+ itemC->setText("C VISIBLE");
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1);
+ indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE"));
+
+ QCOMPARE(proxy.rowCount(indexA) , 1);
+ QModelIndex indexC = proxy.index(0, 0, indexA);
+ QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE"));
+
+ proxy.setFilterRegExp("C");
+ QCOMPARE(proxy.rowCount(QModelIndex()), 0);
+ itemC->setText("invisible");
+ itemA->setText("AC");
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1);
+ indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC"));
+ QCOMPARE(proxy.rowCount(indexA) , 0);
+}
+
+void tst_QSortFilterProxyModel::task252507_mapFromToSource()
+{
+ QtTestModel source(10,10);
+ source.fetchMore(QModelIndex());
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&source);
+ QCOMPARE(proxy.mapFromSource(source.index(5, 4)), proxy.index(5, 4));
+ QCOMPARE(proxy.mapToSource(proxy.index(3, 2)), source.index(3, 2));
+ QCOMPARE(proxy.mapFromSource(QModelIndex()), QModelIndex());
+ QCOMPARE(proxy.mapToSource(QModelIndex()), QModelIndex());
+
+#ifdef QT_NO_DEBUG //if Qt is compiled in debug mode, this will assert
+ QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapToSource ");
+ QCOMPARE(proxy.mapToSource(source.index(2, 3)), QModelIndex());
+ QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapFromSource ");
+ QCOMPARE(proxy.mapFromSource(proxy.index(6, 2)), QModelIndex());
+#endif
+}
+
+static QStandardItem *addEntry(QStandardItem* pParent, const QString &description)
+{
+ QStandardItem* pItem = new QStandardItem(description);
+ pParent->appendRow(pItem);
+ return pItem;
+}
+
+
+void tst_QSortFilterProxyModel::task255652_removeRowsRecursive()
+{
+ QStandardItemModel pModel;
+ QStandardItem *pItem1 = new QStandardItem("root");
+ pModel.appendRow(pItem1);
+ QList<QStandardItem *> items;
+
+ QStandardItem *pItem11 = addEntry(pItem1,"Sub-heading");
+ items << pItem11;
+ QStandardItem *pItem111 = addEntry(pItem11,"A");
+ items << pItem111;
+ items << addEntry(pItem111,"A1");
+ items << addEntry(pItem111,"A2");
+ QStandardItem *pItem112 = addEntry(pItem11,"B");
+ items << pItem112;
+ items << addEntry(pItem112,"B1");
+ items << addEntry(pItem112,"B2");
+ QStandardItem *pItem1123 = addEntry(pItem112,"B3");
+ items << pItem1123;
+ items << addEntry(pItem1123,"B3-");
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&pModel);
+
+ QList<QPersistentModelIndex> sourceIndexes;
+ QList<QPersistentModelIndex> proxyIndexes;
+ foreach (QStandardItem *item, items) {
+ QModelIndex idx = item->index();
+ sourceIndexes << idx;
+ proxyIndexes << proxy.mapFromSource(idx);
+ }
+
+ foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ QVERIFY(pidx.isValid());
+ foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ QVERIFY(pidx.isValid());
+
+ QList<QStandardItem*> itemRow = pItem1->takeRow(0);
+
+ QCOMPARE(itemRow.count(), 1);
+ QCOMPARE(itemRow.first(), pItem11);
+
+ foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ QVERIFY(!pidx.isValid());
+ foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ QVERIFY(!pidx.isValid());
+
+ delete pItem11;
+}
+
+void tst_QSortFilterProxyModel::taskQTBUG_6205_doubleProxySelectionSetSourceModel()
+{
+ QStandardItemModel *model1 = new QStandardItemModel;
+ QStandardItem *parentItem = model1->invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QString("model1 item %0").arg(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+
+ QStandardItemModel *model2 = new QStandardItemModel;
+ QStandardItem *parentItem2 = model2->invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QString("model2 item %0").arg(i));
+ parentItem2->appendRow(item);
+ parentItem2 = item;
+ }
+
+ QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel;
+ toggleProxy->setSourceModel(model1);
+
+ QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
+ proxyModel->setSourceModel(toggleProxy);
+
+ QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0)));
+ QItemSelectionModel ism(proxyModel);
+ ism.select(mi, QItemSelectionModel::Select);
+ QModelIndexList mil = ism.selectedIndexes();
+ QCOMPARE(mil.count(), 1);
+ QCOMPARE(mil.first(), mi);
+
+ toggleProxy->setSourceModel(model2);
+ // No crash, it's good news!
+ QVERIFY(ism.selection().isEmpty());
+}
+
+void tst_QSortFilterProxyModel::taskQTBUG_7537_appearsAndSort()
+{
+ class PModel : public QSortFilterProxyModel
+ {
+ public:
+ PModel() : mVisible(false) {};
+ protected:
+ bool filterAcceptsRow(int, const QModelIndex &) const
+ {
+ return mVisible;
+ }
+
+ public:
+ void updateXX()
+ {
+ mVisible = true;
+ invalidate();
+ }
+ private:
+ bool mVisible;
+ } proxyModel;
+
+
+ QStringListModel sourceModel;
+ QStringList list;
+ list << "b" << "a" << "c";
+ sourceModel.setStringList(list);
+
+ proxyModel.setSourceModel(&sourceModel);
+ proxyModel.setDynamicSortFilter(true);
+ proxyModel.sort(0, Qt::AscendingOrder);
+
+ QApplication::processEvents();
+ QCOMPARE(sourceModel.rowCount(), 3);
+ QCOMPARE(proxyModel.rowCount(), 0); //all rows are hidden at first;
+
+ QSignalSpy spyAbout1(&proxyModel, SIGNAL(layoutAboutToBeChanged()));
+ QSignalSpy spyChanged1(&proxyModel, SIGNAL(layoutChanged()));
+
+ //introducing secondProxyModel to test the layoutChange when many items appears at once
+ QSortFilterProxyModel secondProxyModel;
+ secondProxyModel.setSourceModel(&proxyModel);
+ secondProxyModel.setDynamicSortFilter(true);
+ secondProxyModel.sort(0, Qt::DescendingOrder);
+ QCOMPARE(secondProxyModel.rowCount(), 0); //all rows are hidden at first;
+ QSignalSpy spyAbout2(&secondProxyModel, SIGNAL(layoutAboutToBeChanged()));
+ QSignalSpy spyChanged2(&secondProxyModel, SIGNAL(layoutChanged()));
+
+ proxyModel.updateXX();
+ QApplication::processEvents();
+ //now rows should be visible, and sorted
+ QCOMPARE(proxyModel.rowCount(), 3);
+ QCOMPARE(proxyModel.data(proxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
+ QCOMPARE(proxyModel.data(proxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
+ QCOMPARE(proxyModel.data(proxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
+
+ //now rows should be visible, and sorted
+ QCOMPARE(secondProxyModel.rowCount(), 3);
+ QCOMPARE(secondProxyModel.data(secondProxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
+ QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
+ QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
+
+ QCOMPARE(spyAbout1.count(), 1);
+ QCOMPARE(spyChanged1.count(), 1);
+ QCOMPARE(spyAbout2.count(), 1);
+ QCOMPARE(spyChanged2.count(), 1);
+}
+
+void tst_QSortFilterProxyModel::taskQTBUG_7716_unnecessaryDynamicSorting()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(" ");
+ model.setStringList(initial);
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(false);
+ proxy.setSourceModel(&model);
+ proxy.sort(Qt::AscendingOrder);
+
+ //append two rows
+ int maxrows = proxy.rowCount(QModelIndex());
+ model.insertRows(maxrows, 2);
+ model.setData(model.index(maxrows, 0), QString("alpha"));
+ model.setData(model.index(maxrows + 1, 0), QString("fondue"));
+
+ //append new items to the initial string list and compare with model
+ QStringList expected = initial;
+ expected << QString("alpha") << QString("fondue");
+
+ //if bug 7716 is present, new rows were prepended, when they should have been appended
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+class SelectionProxyModel : QAbstractProxyModel
+{
+ Q_OBJECT
+public:
+ SelectionProxyModel()
+ : QAbstractProxyModel(), selectionModel(0)
+ {
+ }
+
+ QModelIndex mapFromSource(QModelIndex const&) const
+ { return QModelIndex(); }
+
+ QModelIndex mapToSource(QModelIndex const&) const
+ { return QModelIndex(); }
+
+ QModelIndex index(int, int, const QModelIndex&) const
+ { return QModelIndex(); }
+
+ QModelIndex parent(const QModelIndex&) const
+ { return QModelIndex(); }
+
+ int rowCount(const QModelIndex&) const
+ { return 0; }
+
+ int columnCount(const QModelIndex&) const
+ { return 0; }
+
+ void setSourceModel( QAbstractItemModel *sourceModel )
+ {
+ beginResetModel();
+ disconnect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
+ QAbstractProxyModel::setSourceModel( sourceModel );
+ connect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
+ endResetModel();
+ }
+
+ void setSelectionModel( QItemSelectionModel *_selectionModel )
+ {
+ selectionModel = _selectionModel;
+ }
+
+private slots:
+ void sourceModelAboutToBeReset()
+ {
+ QVERIFY( selectionModel->selectedIndexes().size() == 1 );
+ beginResetModel();
+ }
+
+ void sourceModelReset()
+ {
+ endResetModel();
+ }
+
+private:
+ QItemSelectionModel *selectionModel;
+
+};
+
+void tst_QSortFilterProxyModel::testMultipleProxiesWithSelection()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(" ");
+ model.setStringList(initial);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel( &model );
+
+ SelectionProxyModel proxy1;
+ QSortFilterProxyModel proxy2;
+
+ // Note that the order here matters. The order of the sourceAboutToBeReset
+ // exposes the bug in QSortFilterProxyModel.
+ proxy2.setSourceModel( &proxy );
+ proxy1.setSourceModel( &proxy );
+
+ QItemSelectionModel selectionModel(&proxy2);
+ proxy1.setSelectionModel( &selectionModel );
+
+ selectionModel.select( proxy2.index( 0, 0 ), QItemSelectionModel::Select );
+
+ // trick the proxy into emitting begin/end reset signals.
+ proxy.setSourceModel(0);
+
+}
+
+static bool isValid(const QItemSelection &selection) {
+ foreach(const QItemSelectionRange &range, selection)
+ if (!range.isValid())
+ return false;
+ return true;
+}
+
+void tst_QSortFilterProxyModel::mapSelectionFromSource()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(" ");
+ model.setStringList(initial);
+
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ proxy.setFilterRegExp("d.*");
+ proxy.setSourceModel(&model);
+
+ // Only "delta" remains.
+ QVERIFY(proxy.rowCount() == 1);
+
+ QItemSelection selection;
+ QModelIndex charlie = model.index(1, 0);
+ selection.append(QItemSelectionRange(charlie, charlie));
+ QModelIndex delta = model.index(2, 0);
+ selection.append(QItemSelectionRange(delta, delta));
+ QModelIndex echo = model.index(3, 0);
+ selection.append(QItemSelectionRange(echo, echo));
+
+ QVERIFY(isValid(selection));
+
+ QItemSelection proxiedSelection = proxy.mapSelectionFromSource(selection);
+
+ // Only "delta" is in the mapped result.
+ QVERIFY(proxiedSelection.size() == 1);
+ QVERIFY(isValid(proxiedSelection));
+}
+
+class Model10287 : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ Model10287(QObject *parent = 0)
+ : QStandardItemModel(0, 1, parent)
+ {
+ parentItem = new QStandardItem("parent");
+ parentItem->setData(false, Qt::UserRole);
+ appendRow(parentItem);
+
+ childItem = new QStandardItem("child");
+ childItem->setData(true, Qt::UserRole);
+ parentItem->appendRow(childItem);
+
+ childItem2 = new QStandardItem("child2");
+ childItem2->setData(true, Qt::UserRole);
+ parentItem->appendRow(childItem2);
+ }
+
+ void removeChild()
+ {
+ childItem2->setData(false, Qt::UserRole);
+ parentItem->removeRow(0);
+ }
+
+private:
+ QStandardItem *parentItem, *childItem, *childItem2;
+};
+
+class Proxy10287 : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ Proxy10287(QAbstractItemModel *model, QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+ setSourceModel(model);
+ setDynamicSortFilter(true);
+ }
+
+protected:
+ virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+ {
+ // Filter based on UserRole in model
+ QModelIndex i = sourceModel()->index(source_row, 0, source_parent);
+ return i.data(Qt::UserRole).toBool();
+ }
+};
+
+void tst_QSortFilterProxyModel::taskQTBUG_10287_unnecessaryMapCreation()
+{
+ Model10287 m;
+ Proxy10287 p(&m);
+ m.removeChild();
+ // No assert failure, it passes.
+}
+
+class FilteredColumnProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ FilteredColumnProxyModel(QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+
+ }
+
+protected:
+ bool filterAcceptsColumn(int column, const QModelIndex & /* source_parent */) const
+ {
+ return column % 2 != 0;
+ }
+};
+
+void tst_QSortFilterProxyModel::filteredColumns()
+{
+ DynamicTreeModel *model = new DynamicTreeModel(this);
+
+ FilteredColumnProxyModel *proxy = new FilteredColumnProxyModel(this);
+ proxy->setSourceModel(model);
+
+ new ModelTest(proxy, this);
+
+ ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
+ insertCommand->setNumCols(2);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(0);
+ // Parent is QModelIndex()
+ insertCommand->doCommand();
+}
+
+void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate_data()
+{
+ QTest::addColumn<int>("test");
+ QTest::addColumn<bool>("works");
+
+ QTest::newRow("nothing") << 0 << false;
+ QTest::newRow("reset") << 1 << true;
+ QTest::newRow("invalidate") << 2 << true;
+ QTest::newRow("invalidate_filter") << 3 << true;
+}
+
+void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate()
+{
+ QFETCH(int, test);
+ QFETCH(bool, works);
+
+ struct Proxy : QSortFilterProxyModel {
+ QString pattern;
+ virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const {
+ return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern);
+ }
+ void notifyChange(int test) {
+ switch (test) {
+ case 0: break;
+ case 1: reset(); break;
+ case 2: invalidate(); break;
+ case 3: invalidateFilter(); break;
+ }
+ }
+ };
+
+ QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis"
+ << "Elephant" << "Cochon" << "Serpent"
+ << "Mouton" << "Ecureuil" << "Mouche");
+ Proxy proxy;
+ proxy.pattern = QString::fromLatin1("n");
+ proxy.setSourceModel(&sourceModel);
+
+ QCOMPARE(proxy.rowCount(), 5);
+ for (int i = 0; i < proxy.rowCount(); i++) {
+ QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n'));
+ }
+
+ proxy.pattern = QString::fromLatin1("o");
+ proxy.notifyChange(test);
+
+ QCOMPARE(proxy.rowCount(), works ? 4 : 5);
+ bool ok = true;
+ for (int i = 0; i < proxy.rowCount(); i++) {
+ if (!proxy.data(proxy.index(i,0)).toString().contains('o'))
+ ok = false;
+ }
+ QCOMPARE(ok, works);
+}
+
+QTEST_MAIN(tst_QSortFilterProxyModel)
+#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/widgets/itemviews/qstandarditem/.gitignore b/tests/auto/widgets/itemviews/qstandarditem/.gitignore
new file mode 100644
index 0000000000..6da85cc6c8
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstandarditem/.gitignore
@@ -0,0 +1 @@
+tst_qstandarditem
diff --git a/tests/auto/widgets/itemviews/qstandarditem/qstandarditem.pro b/tests/auto/widgets/itemviews/qstandarditem/qstandarditem.pro
new file mode 100644
index 0000000000..1d280fc2f5
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstandarditem/qstandarditem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qstandarditem.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qstandarditem/tst_qstandarditem.cpp b/tests/auto/widgets/itemviews/qstandarditem/tst_qstandarditem.cpp
new file mode 100644
index 0000000000..206d469884
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstandarditem/tst_qstandarditem.cpp
@@ -0,0 +1,1110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qstandarditemmodel.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/itemviews/qstandarditemmodel.h gui/itemviews/qstandarditemmodel.cpp
+
+class tst_QStandardItem : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QStandardItem();
+ virtual ~tst_QStandardItem();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void ctor();
+ void textCtor();
+ void iconTextCtor();
+ void rowsColumnsCtor();
+ void getSetData();
+ void getSetFlags();
+ void getSetRowAndColumnCount();
+ void getSetChild_data();
+ void getSetChild();
+ void parent();
+ void insertColumn_data();
+ void insertColumn();
+ void insertColumns_data();
+ void insertColumns();
+ void insertRow_data();
+ void insertRow();
+ void insertRows_data();
+ void insertRows();
+ void appendColumn_data();
+ void appendColumn();
+ void appendRow_data();
+ void appendRow();
+ void takeChild();
+ void takeColumn_data();
+ void takeColumn();
+ void takeRow_data();
+ void takeRow();
+ void streamItem();
+ void deleteItem();
+ void clone();
+ void sortChildren();
+ void subclassing();
+};
+
+tst_QStandardItem::tst_QStandardItem()
+{
+}
+
+tst_QStandardItem::~tst_QStandardItem()
+{
+}
+
+void tst_QStandardItem::init()
+{
+}
+
+void tst_QStandardItem::cleanup()
+{
+}
+
+void tst_QStandardItem::ctor()
+{
+ QStandardItem item;
+ QVERIFY(!item.hasChildren());
+}
+
+void tst_QStandardItem::textCtor()
+{
+ QLatin1String text("text");
+ QStandardItem item(text);
+ QCOMPARE(item.text(), text);
+ QVERIFY(!item.hasChildren());
+}
+
+void tst_QStandardItem::iconTextCtor()
+{
+ QPixmap pixmap(32, 32);
+ pixmap.fill(Qt::red);
+ QIcon icon(pixmap);
+ QLatin1String text("text");
+ QStandardItem item(icon, text);
+ QCOMPARE(item.icon(), icon);
+ QCOMPARE(item.text(), text);
+ QVERIFY(!item.hasChildren());
+}
+
+void tst_QStandardItem::rowsColumnsCtor()
+{
+ const int rows = 5;
+ const int columns = 12;
+ QStandardItem item(rows, columns);
+ QCOMPARE(item.rowCount(), rows);
+ QCOMPARE(item.columnCount(), columns);
+}
+
+void tst_QStandardItem::getSetData()
+{
+ QStandardItem item;
+ for (int x = 0; x < 2; ++x) {
+ for (int i = 1; i <= 2; ++i) {
+ QString text = QString("text %0").arg(i);
+ item.setText(text);
+ QCOMPARE(item.text(), text);
+
+ QPixmap pixmap(32, 32);
+ pixmap.fill((i == 1) ? Qt::red : Qt::green);
+ QIcon icon(pixmap);
+ item.setIcon(icon);
+ QCOMPARE(item.icon(), icon);
+
+ QString toolTip = QString("toolTip %0").arg(i);
+ item.setToolTip(toolTip);
+ QCOMPARE(item.toolTip(), toolTip);
+
+ QString statusTip = QString("statusTip %0").arg(i);
+ item.setStatusTip(statusTip);
+ QCOMPARE(item.statusTip(), statusTip);
+
+ QString whatsThis = QString("whatsThis %0").arg(i);
+ item.setWhatsThis(whatsThis);
+ QCOMPARE(item.whatsThis(), whatsThis);
+
+ QSize sizeHint(64*i, 48*i);
+ item.setSizeHint(sizeHint);
+ QCOMPARE(item.sizeHint(), sizeHint);
+
+ QFont font;
+ item.setFont(font);
+ QCOMPARE(item.font(), font);
+
+ Qt::Alignment textAlignment((i == 1)
+ ? Qt::AlignLeft|Qt::AlignVCenter
+ : Qt::AlignRight);
+ item.setTextAlignment(textAlignment);
+ QCOMPARE(item.textAlignment(), textAlignment);
+
+ QColor backgroundColor((i == 1) ? Qt::blue : Qt::yellow);
+ item.setBackground(backgroundColor);
+ QCOMPARE(item.background().color(), backgroundColor);
+
+ QColor textColor((i == i) ? Qt::green : Qt::cyan);
+ item.setForeground(textColor);
+ QCOMPARE(item.foreground().color(), textColor);
+
+ Qt::CheckState checkState((i == 1) ? Qt::PartiallyChecked : Qt::Checked);
+ item.setCheckState(checkState);
+ QCOMPARE(item.checkState(), checkState);
+
+ QString accessibleText = QString("accessibleText %0").arg(i);
+ item.setAccessibleText(accessibleText);
+ QCOMPARE(item.accessibleText(), accessibleText);
+
+ QString accessibleDescription = QString("accessibleDescription %0").arg(i);
+ item.setAccessibleDescription(accessibleDescription);
+ QCOMPARE(item.accessibleDescription(), accessibleDescription);
+
+ QCOMPARE(item.text(), text);
+ QCOMPARE(item.icon(), icon);
+ QCOMPARE(item.toolTip(), toolTip);
+ QCOMPARE(item.statusTip(), statusTip);
+ QCOMPARE(item.whatsThis(), whatsThis);
+ QCOMPARE(item.sizeHint(), sizeHint);
+ QCOMPARE(item.font(), font);
+ QCOMPARE(item.textAlignment(), textAlignment);
+ QCOMPARE(item.background().color(), backgroundColor);
+ QCOMPARE(item.foreground().color(), textColor);
+ QCOMPARE(item.checkState(), checkState);
+ QCOMPARE(item.accessibleText(), accessibleText);
+ QCOMPARE(item.accessibleDescription(), accessibleDescription);
+
+ QCOMPARE(qvariant_cast<QString>(item.data(Qt::DisplayRole)), text);
+ QCOMPARE(qvariant_cast<QIcon>(item.data(Qt::DecorationRole)), icon);
+ QCOMPARE(qvariant_cast<QString>(item.data(Qt::ToolTipRole)), toolTip);
+ QCOMPARE(qvariant_cast<QString>(item.data(Qt::StatusTipRole)), statusTip);
+ QCOMPARE(qvariant_cast<QString>(item.data(Qt::WhatsThisRole)), whatsThis);
+ QCOMPARE(qvariant_cast<QSize>(item.data(Qt::SizeHintRole)), sizeHint);
+ QCOMPARE(qvariant_cast<QFont>(item.data(Qt::FontRole)), font);
+ QCOMPARE(qvariant_cast<int>(item.data(Qt::TextAlignmentRole)), int(textAlignment));
+ QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundColorRole)), QBrush(backgroundColor));
+ QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundRole)), QBrush(backgroundColor));
+ QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::TextColorRole)), QBrush(textColor));
+ QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::ForegroundRole)), QBrush(textColor));
+ QCOMPARE(qvariant_cast<int>(item.data(Qt::CheckStateRole)), int(checkState));
+ QCOMPARE(qvariant_cast<QString>(item.data(Qt::AccessibleTextRole)), accessibleText);
+ QCOMPARE(qvariant_cast<QString>(item.data(Qt::AccessibleDescriptionRole)), accessibleDescription);
+
+ item.setBackground(pixmap);
+ QCOMPARE(item.background().texture(), pixmap);
+ QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundRole)).texture(), pixmap);
+ }
+ item.setData(QVariant(), Qt::DisplayRole);
+ item.setData(QVariant(), Qt::DecorationRole);
+ item.setData(QVariant(), Qt::ToolTipRole);
+ item.setData(QVariant(), Qt::StatusTipRole);
+ item.setData(QVariant(), Qt::WhatsThisRole);
+ item.setData(QVariant(), Qt::SizeHintRole);
+ item.setData(QVariant(), Qt::FontRole);
+ item.setData(QVariant(), Qt::TextAlignmentRole);
+ item.setData(QVariant(), Qt::BackgroundRole);
+ item.setData(QVariant(), Qt::ForegroundRole);
+ item.setData(QVariant(), Qt::CheckStateRole);
+ item.setData(QVariant(), Qt::AccessibleTextRole);
+ item.setData(QVariant(), Qt::AccessibleDescriptionRole);
+
+ QCOMPARE(item.data(Qt::DisplayRole), QVariant());
+ QCOMPARE(item.data(Qt::DecorationRole), QVariant());
+ QCOMPARE(item.data(Qt::ToolTipRole), QVariant());
+ QCOMPARE(item.data(Qt::StatusTipRole), QVariant());
+ QCOMPARE(item.data(Qt::WhatsThisRole), QVariant());
+ QCOMPARE(item.data(Qt::SizeHintRole), QVariant());
+ QCOMPARE(item.data(Qt::FontRole), QVariant());
+ QCOMPARE(item.data(Qt::TextAlignmentRole), QVariant());
+ QCOMPARE(item.data(Qt::BackgroundColorRole), QVariant());
+ QCOMPARE(item.data(Qt::BackgroundRole), QVariant());
+ QCOMPARE(item.data(Qt::TextColorRole), QVariant());
+ QCOMPARE(item.data(Qt::ForegroundRole), QVariant());
+ QCOMPARE(item.data(Qt::CheckStateRole), QVariant());
+ QCOMPARE(item.data(Qt::AccessibleTextRole), QVariant());
+ QCOMPARE(item.data(Qt::AccessibleDescriptionRole), QVariant());
+ }
+}
+
+void tst_QStandardItem::getSetFlags()
+{
+ QStandardItem item;
+ item.setEnabled(true);
+ QVERIFY(item.isEnabled());
+ QVERIFY(item.flags() & Qt::ItemIsEnabled);
+ item.setEditable(true);
+ QVERIFY(item.isEditable());
+ QVERIFY(item.flags() & Qt::ItemIsEditable);
+ item.setSelectable(true);
+ QVERIFY(item.isSelectable());
+ QVERIFY(item.flags() & Qt::ItemIsSelectable);
+ item.setCheckable(true);
+ QVERIFY(item.isCheckable());
+ QCOMPARE(item.checkState(), Qt::Unchecked);
+ QVERIFY(item.flags() & Qt::ItemIsUserCheckable);
+ item.setTristate(true);
+ QVERIFY(item.isTristate());
+ QVERIFY(item.flags() & Qt::ItemIsTristate);
+#ifndef QT_NO_DRAGANDDROP
+ item.setDragEnabled(true);
+ QVERIFY(item.isDragEnabled());
+ QVERIFY(item.flags() & Qt::ItemIsDragEnabled);
+ item.setDropEnabled(true);
+ QVERIFY(item.isDropEnabled());
+ QVERIFY(item.flags() & Qt::ItemIsDropEnabled);
+#endif
+
+ QVERIFY(item.isEnabled());
+ item.setEnabled(false);
+ QVERIFY(!item.isEnabled());
+ QVERIFY(!(item.flags() & Qt::ItemIsEnabled));
+ QVERIFY(item.isEditable());
+ item.setEditable(false);
+ QVERIFY(!item.isEditable());
+ QVERIFY(!(item.flags() & Qt::ItemIsEditable));
+ QVERIFY(item.isSelectable());
+ item.setSelectable(false);
+ QVERIFY(!item.isSelectable());
+ QVERIFY(!(item.flags() & Qt::ItemIsSelectable));
+ QVERIFY(item.isCheckable());
+ item.setCheckable(false);
+ QVERIFY(!item.isCheckable());
+ QVERIFY(!(item.flags() & Qt::ItemIsUserCheckable));
+ QVERIFY(item.isTristate());
+ item.setTristate(false);
+ QVERIFY(!item.isTristate());
+ QVERIFY(!(item.flags() & Qt::ItemIsTristate));
+#ifndef QT_NO_DRAGANDDROP
+ QVERIFY(item.isDragEnabled());
+ item.setDragEnabled(false);
+ QVERIFY(!item.isDragEnabled());
+ QVERIFY(!(item.flags() & Qt::ItemIsDragEnabled));
+ QVERIFY(item.isDropEnabled());
+ item.setDropEnabled(false);
+ QVERIFY(!item.isDropEnabled());
+ QVERIFY(!(item.flags() & Qt::ItemIsDropEnabled));
+#endif
+
+ item.setCheckable(false);
+ item.setCheckState(Qt::Checked);
+ item.setCheckable(true);
+ QCOMPARE(item.checkState(), Qt::Checked);
+}
+
+void tst_QStandardItem::getSetRowAndColumnCount()
+{
+ QStandardItem item;
+
+ item.setRowCount(-1);
+ QCOMPARE(item.rowCount(), 0);
+
+ item.setColumnCount(-1);
+ QCOMPARE(item.columnCount(), 0);
+
+ item.setRowCount(1);
+ QCOMPARE(item.rowCount(), 1);
+ QCOMPARE(item.columnCount(), 0);
+
+ item.setColumnCount(1);
+ QCOMPARE(item.columnCount(), 1);
+ QCOMPARE(item.rowCount(), 1);
+
+ item.setColumnCount(10);
+ QCOMPARE(item.columnCount(), 10);
+ QCOMPARE(item.rowCount(), 1);
+
+ item.setRowCount(20);
+ QCOMPARE(item.rowCount(), 20);
+ QCOMPARE(item.columnCount(), 10);
+
+ item.setRowCount(-1);
+ QCOMPARE(item.rowCount(), 20);
+
+ item.setColumnCount(-1);
+ QCOMPARE(item.columnCount(), 10);
+
+ item.setColumnCount(0);
+ QCOMPARE(item.columnCount(), 0);
+ QCOMPARE(item.rowCount(), 20);
+
+ item.setRowCount(0);
+ QCOMPARE(item.rowCount(), 0);
+}
+
+void tst_QStandardItem::getSetChild_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+
+ QTest::newRow("0x0 children, child at (-1,-1)") << 0 << 0 << -1 << -1;
+ QTest::newRow("0x0 children, child at (0,0)") << 0 << 0 << 0 << 0;
+}
+
+void tst_QStandardItem::getSetChild()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, row);
+ QFETCH(int, column);
+
+ QStandardItem item(rows, columns);
+ bool shouldHaveChildren = (rows > 0) && (columns > 0);
+ QCOMPARE(item.hasChildren(), shouldHaveChildren);
+ QCOMPARE(item.child(row, column), static_cast<QStandardItem*>(0));
+
+ QStandardItem *child = new QStandardItem;
+ item.setChild(row, column, child);
+ if ((row >= 0) && (column >= 0)) {
+ QCOMPARE(item.rowCount(), qMax(rows, row + 1));
+ QCOMPARE(item.columnCount(), qMax(columns, column + 1));
+
+ QCOMPARE(item.child(row, column), child);
+ QCOMPARE(child->row(), row);
+ QCOMPARE(child->column(), column);
+
+ QStandardItem *anotherChild = new QStandardItem;
+ item.setChild(row, column, anotherChild);
+ QCOMPARE(item.child(row, column), anotherChild);
+ QCOMPARE(anotherChild->row(), row);
+ QCOMPARE(anotherChild->column(), column);
+ item.setChild(row, column, 0);
+ } else {
+ delete child;
+ }
+ QCOMPARE(item.child(row, column), static_cast<QStandardItem*>(0));
+}
+
+void tst_QStandardItem::parent()
+{
+ {
+ QStandardItem item;
+ QStandardItem *child = new QStandardItem;
+ QCOMPARE(child->parent(), static_cast<QStandardItem*>(0));
+ item.setChild(0, 0, child);
+ QCOMPARE(child->parent(), &item);
+
+ QStandardItem *childOfChild = new QStandardItem;
+ child->setChild(0, 0, childOfChild);
+ QCOMPARE(childOfChild->parent(), child);
+ }
+
+ {
+ QStandardItemModel model;
+ QStandardItem *item = new QStandardItem;
+ model.appendRow(item);
+ // parent of a top-level item should be 0
+ QCOMPARE(item->parent(), static_cast<QStandardItem*>(0));
+ }
+}
+
+void tst_QStandardItem::insertColumn_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("insert 0 at -1 in 0x0") << 0 << 0 << -1 << 0;
+ QTest::newRow("insert 0 at 0 in 0x0") << 0 << 0 << 0 << 0;
+ QTest::newRow("insert 0 at 0 in 1x0") << 1 << 0 << 0 << 0;
+ QTest::newRow("insert 0 at 0 in 0x1") << 0 << 1 << 0 << 0;
+ QTest::newRow("insert 0 at 0 in 1x1") << 1 << 1 << 0 << 0;
+ QTest::newRow("insert 1 at -1 in 0x0") << 0 << 0 << -1 << 1;
+ QTest::newRow("insert 1 at 0 in 0x0") << 0 << 0 << 0 << 1;
+ QTest::newRow("insert 1 at 0 in 1x0") << 1 << 0 << 0 << 1;
+ QTest::newRow("insert 1 at 0 in 0x1") << 0 << 1 << 0 << 1;
+ QTest::newRow("insert 1 at 0 in 1x1") << 1 << 1 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 1x1") << 1 << 1 << 1 << 1;
+ QTest::newRow("insert 1 at 0 in 2x1") << 2 << 1 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 2x1") << 2 << 1 << 1 << 1;
+ QTest::newRow("insert 1 at 0 in 1x2") << 1 << 2 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 1x2") << 1 << 2 << 1 << 1;
+ QTest::newRow("insert 1 at 0 in 8x4") << 8 << 4 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 8x4") << 8 << 4 << 1 << 1;
+ QTest::newRow("insert 1 at 2 in 8x4") << 8 << 4 << 2 << 1;
+ QTest::newRow("insert 1 at 3 in 8x4") << 8 << 4 << 3 << 1;
+ QTest::newRow("insert 1 at 4 in 8x4") << 8 << 4 << 4 << 1;
+ QTest::newRow("insert 4 at 0 in 8x4") << 8 << 4 << 0 << 4;
+ QTest::newRow("insert 4 at 4 in 8x4") << 8 << 4 << 4 << 4;
+ QTest::newRow("insert 6 at 0 in 8x4") << 8 << 4 << 0 << 6;
+ QTest::newRow("insert 6 at 4 in 8x4") << 8 << 4 << 4 << 6;
+}
+
+void tst_QStandardItem::insertColumn()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, column);
+ QFETCH(int, count);
+
+ QStandardItem item(rows, columns);
+
+ // make items for a new column
+ QList<QStandardItem*> columnItems;
+ for (int i = 0; i < count; ++i)
+ columnItems.append(new QStandardItem);
+
+ item.insertColumn(column, columnItems);
+
+ if (column >= 0) {
+ QCOMPARE(item.columnCount(), columns + 1);
+ QCOMPARE(item.rowCount(), qMax(rows, count));
+ // check to make sure items were inserted in correct place
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(item.child(i, column), columnItems.at(i));
+ for (int i = count; i < item.rowCount(); ++i)
+ QCOMPARE(item.child(i, column), static_cast<QStandardItem*>(0));
+ } else {
+ QCOMPARE(item.columnCount(), columns);
+ QCOMPARE(item.rowCount(), rows);
+ qDeleteAll(columnItems);
+ }
+}
+
+void tst_QStandardItem::insertColumns_data()
+{
+}
+
+void tst_QStandardItem::insertColumns()
+{
+}
+
+void tst_QStandardItem::insertRow_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("insert 0 at -1 in 0x0") << 0 << 0 << -1 << 0;
+ QTest::newRow("insert 0 at 0 in 0x0") << 0 << 0 << 0 << 0;
+ QTest::newRow("insert 0 at 0 in 1x0") << 1 << 0 << 0 << 0;
+ QTest::newRow("insert 0 at 0 in 0x1") << 0 << 1 << 0 << 0;
+ QTest::newRow("insert 0 at 0 in 1x1") << 1 << 1 << 0 << 0;
+ QTest::newRow("insert 1 at -1 in 0x0") << 0 << 0 << -1 << 1;
+ QTest::newRow("insert 1 at 0 in 0x0") << 0 << 0 << 0 << 1;
+ QTest::newRow("insert 1 at 0 in 1x0") << 1 << 0 << 0 << 1;
+ QTest::newRow("insert 1 at 0 in 0x1") << 0 << 1 << 0 << 1;
+ QTest::newRow("insert 1 at 0 in 1x1") << 1 << 1 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 1x1") << 1 << 1 << 1 << 1;
+ QTest::newRow("insert 1 at 0 in 2x1") << 2 << 1 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 2x1") << 2 << 1 << 1 << 1;
+ QTest::newRow("insert 1 at 0 in 1x2") << 1 << 2 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 1x2") << 1 << 2 << 1 << 1;
+ QTest::newRow("insert 1 at 0 in 4x8") << 4 << 8 << 0 << 1;
+ QTest::newRow("insert 1 at 1 in 4x8") << 4 << 8 << 1 << 1;
+ QTest::newRow("insert 1 at 2 in 4x8") << 4 << 8 << 2 << 1;
+ QTest::newRow("insert 1 at 3 in 4x8") << 4 << 8 << 3 << 1;
+ QTest::newRow("insert 1 at 4 in 4x8") << 4 << 8 << 4 << 1;
+ QTest::newRow("insert 4 at 0 in 4x8") << 4 << 8 << 0 << 4;
+ QTest::newRow("insert 4 at 4 in 4x8") << 4 << 8 << 4 << 4;
+ QTest::newRow("insert 6 at 0 in 4x8") << 4 << 8 << 0 << 6;
+ QTest::newRow("insert 6 at 4 in 4x8") << 4 << 8 << 4 << 6;
+}
+
+void tst_QStandardItem::insertRow()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, row);
+ QFETCH(int, count);
+
+ QStandardItem item(rows, columns);
+
+ // make items for a new column
+ QList<QStandardItem*> rowItems;
+ for (int i = 0; i < count; ++i)
+ rowItems.append(new QStandardItem);
+
+ item.insertRow(row, rowItems);
+
+ if (row >= 0) {
+ QCOMPARE(item.columnCount(), qMax(columns, count));
+ QCOMPARE(item.rowCount(), rows + 1);
+ // check to make sure items were inserted in correct place
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(item.child(row, i), rowItems.at(i));
+ for (int i = count; i < item.columnCount(); ++i)
+ QCOMPARE(item.child(row, i), static_cast<QStandardItem*>(0));
+ } else {
+ QCOMPARE(item.columnCount(), columns);
+ QCOMPARE(item.rowCount(), rows);
+ qDeleteAll(rowItems);
+ }
+}
+
+void tst_QStandardItem::insertRows_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("insertAt");
+ QTest::addColumn<int>("insertCount");
+
+ QTest::newRow("insert {0,1} at 0 in 0x0") << 0 << 0 << 0 << 2;
+}
+
+void tst_QStandardItem::insertRows()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, insertAt);
+ QFETCH(int, insertCount);
+
+ QStandardItem item(rows, columns);
+
+ QList<QStandardItem*> items;
+ for (int i = 0; i < insertCount; ++i) {
+ items.append(new QStandardItem());
+ }
+ item.insertRows(insertAt, items);
+
+ QCOMPARE(item.rowCount(), rows + insertCount);
+}
+
+void tst_QStandardItem::appendColumn_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("append 0 to 0x0") << 0 << 0 << 0;
+ QTest::newRow("append 1 to 0x0") << 0 << 0 << 1;
+ QTest::newRow("append 1 to 1x0") << 1 << 0 << 1;
+ QTest::newRow("append 1 to 0x1") << 0 << 1 << 1;
+ QTest::newRow("append 1 to 1x1") << 1 << 1 << 1;
+ QTest::newRow("append 1 to 2x0") << 2 << 0 << 1;
+ QTest::newRow("append 1 to 0x2") << 0 << 2 << 1;
+ QTest::newRow("append 1 to 2x1") << 2 << 1 << 1;
+ QTest::newRow("append 1 to 1x2") << 1 << 2 << 1;
+ QTest::newRow("append 1 to 2x2") << 2 << 2 << 1;
+ QTest::newRow("append 2 to 0x0") << 0 << 0 << 2;
+ QTest::newRow("append 2 to 1x0") << 1 << 0 << 2;
+ QTest::newRow("append 2 to 0x1") << 0 << 1 << 2;
+ QTest::newRow("append 2 to 1x1") << 1 << 1 << 2;
+ QTest::newRow("append 2 to 2x0") << 2 << 0 << 2;
+ QTest::newRow("append 2 to 0x2") << 0 << 2 << 2;
+ QTest::newRow("append 2 to 2x1") << 2 << 1 << 2;
+ QTest::newRow("append 2 to 1x2") << 1 << 2 << 2;
+ QTest::newRow("append 2 to 2x2") << 2 << 2 << 2;
+ QTest::newRow("append 3 to 2x1") << 2 << 1 << 3;
+ QTest::newRow("append 3 to 1x2") << 1 << 2 << 3;
+ QTest::newRow("append 3 to 2x2") << 2 << 2 << 3;
+ QTest::newRow("append 3 to 4x2") << 4 << 2 << 3;
+ QTest::newRow("append 3 to 2x4") << 2 << 4 << 3;
+ QTest::newRow("append 3 to 4x4") << 4 << 4 << 3;
+ QTest::newRow("append 7 to 4x2") << 4 << 2 << 7;
+ QTest::newRow("append 7 to 2x4") << 2 << 4 << 7;
+ QTest::newRow("append 7 to 4x4") << 4 << 4 << 7;
+}
+
+void tst_QStandardItem::appendColumn()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, count);
+
+ QStandardItem item(rows, columns);
+ QList<QStandardItem*> originalChildren;
+ // initialize children
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ QStandardItem *child = new QStandardItem;
+ originalChildren.append(child);
+ item.setChild(i, j, child);
+ }
+ }
+
+ // make items for a new column
+ QList<QStandardItem*> columnItems;
+ for (int i = 0; i < count; ++i)
+ columnItems.append(new QStandardItem);
+
+ item.appendColumn(columnItems);
+
+ QCOMPARE(item.columnCount(), columns + 1);
+ QCOMPARE(item.rowCount(), qMax(rows, count));
+ // check to make sure items were inserted in correct place
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(item.child(i, columns), columnItems.at(i));
+ for (int i = count; i < item.rowCount(); ++i)
+ QCOMPARE(item.child(i, columns), static_cast<QStandardItem*>(0));
+
+ // make sure original children remained unchanged
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j)
+ QCOMPARE(item.child(i, j), originalChildren.at(i*columns+j));
+ }
+}
+
+void tst_QStandardItem::appendRow_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("append 0 to 0x0") << 0 << 0 << 0;
+ QTest::newRow("append 1 to 0x0") << 0 << 0 << 1;
+ QTest::newRow("append 1 to 1x0") << 1 << 0 << 1;
+ QTest::newRow("append 1 to 0x1") << 0 << 1 << 1;
+ QTest::newRow("append 1 to 1x1") << 1 << 1 << 1;
+ QTest::newRow("append 1 to 2x0") << 2 << 0 << 1;
+ QTest::newRow("append 1 to 0x2") << 0 << 2 << 1;
+ QTest::newRow("append 1 to 2x1") << 2 << 1 << 1;
+ QTest::newRow("append 1 to 1x2") << 1 << 2 << 1;
+ QTest::newRow("append 1 to 2x2") << 2 << 2 << 1;
+ QTest::newRow("append 2 to 0x0") << 0 << 0 << 2;
+ QTest::newRow("append 2 to 1x0") << 1 << 0 << 2;
+ QTest::newRow("append 2 to 0x1") << 0 << 1 << 2;
+ QTest::newRow("append 2 to 1x1") << 1 << 1 << 2;
+ QTest::newRow("append 2 to 2x0") << 2 << 0 << 2;
+ QTest::newRow("append 2 to 0x2") << 0 << 2 << 2;
+ QTest::newRow("append 2 to 2x1") << 2 << 1 << 2;
+ QTest::newRow("append 2 to 1x2") << 1 << 2 << 2;
+ QTest::newRow("append 2 to 2x2") << 2 << 2 << 2;
+ QTest::newRow("append 3 to 2x1") << 2 << 1 << 3;
+ QTest::newRow("append 3 to 1x2") << 1 << 2 << 3;
+ QTest::newRow("append 3 to 2x2") << 2 << 2 << 3;
+ QTest::newRow("append 3 to 4x2") << 4 << 2 << 3;
+ QTest::newRow("append 3 to 2x4") << 2 << 4 << 3;
+ QTest::newRow("append 3 to 4x4") << 4 << 4 << 3;
+ QTest::newRow("append 7 to 4x2") << 4 << 2 << 7;
+ QTest::newRow("append 7 to 2x4") << 2 << 4 << 7;
+ QTest::newRow("append 7 to 4x4") << 4 << 4 << 7;
+}
+
+void tst_QStandardItem::appendRow()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, count);
+
+ QStandardItem item(rows, columns);
+ QList<QStandardItem*> originalChildren;
+ // initialize children
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ QStandardItem *child = new QStandardItem;
+ originalChildren.append(child);
+ item.setChild(i, j, child);
+ }
+ }
+
+ // make items for a new row
+ QList<QStandardItem*> rowItems;
+ for (int i = 0; i < count; ++i)
+ rowItems.append(new QStandardItem);
+
+ item.appendRow(rowItems);
+
+ QCOMPARE(item.rowCount(), rows + 1);
+ QCOMPARE(item.columnCount(), qMax(columns, count));
+ // check to make sure items were inserted in correct place
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(item.child(rows, i), rowItems.at(i));
+ for (int i = count; i < item.columnCount(); ++i)
+ QCOMPARE(item.child(rows, i), static_cast<QStandardItem*>(0));
+
+ // make sure original children remained unchanged
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j)
+ QCOMPARE(item.child(i, j), originalChildren.at(i*columns+j));
+ }
+}
+
+void tst_QStandardItem::takeChild()
+{
+ QList<QStandardItem*> itemList;
+ for (int i = 0; i < 10; ++i)
+ itemList.append(new QStandardItem);
+ QStandardItem item;
+ item.appendColumn(itemList);
+
+ for (int i = 0; i < item.rowCount(); ++i) {
+ QCOMPARE(item.takeChild(i), itemList.at(i));
+ QCOMPARE(item.takeChild(0, 0), static_cast<QStandardItem*>(0));
+ for (int j = i + 1; j < item.rowCount(); ++j)
+ QCOMPARE(item.child(j), itemList.at(j));
+ }
+ qDeleteAll(itemList);
+}
+
+void tst_QStandardItem::takeColumn_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<bool>("expectSuccess");
+
+ QTest::newRow("take -1 from 0x0") << 0 << 0 << -1 << false;
+ QTest::newRow("take 0 from 0x0") << 0 << 0 << 0 << false;
+ QTest::newRow("take 0 from 1x0") << 1 << 0 << 0 << false;
+ QTest::newRow("take 0 from 0x1") << 0 << 1 << 0 << true;
+ QTest::newRow("take 1 from 0x1") << 0 << 1 << 1 << false;
+ QTest::newRow("take 0 from 1x1") << 1 << 1 << 0 << true;
+ QTest::newRow("take 1 from 1x1") << 0 << 1 << 1 << false;
+ QTest::newRow("take 0 from 4x1") << 4 << 1 << 0 << true;
+ QTest::newRow("take 1 from 4x1") << 4 << 1 << 1 << false;
+ QTest::newRow("take 0 from 4x8") << 4 << 8 << 0 << true;
+ QTest::newRow("take 7 from 4x8") << 4 << 8 << 7 << true;
+ QTest::newRow("take 8 from 4x8") << 4 << 8 << 8 << false;
+}
+
+void tst_QStandardItem::takeColumn()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, column);
+ QFETCH(bool, expectSuccess);
+
+ QStandardItem item(rows, columns);
+ QList<QStandardItem*> originalChildren;
+ // initialize children
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ QStandardItem *child = new QStandardItem;
+ originalChildren.append(child);
+ item.setChild(i, j, child);
+ }
+ }
+
+ QList<QStandardItem *> taken = item.takeColumn(column);
+ if (expectSuccess) {
+ QCOMPARE(taken.count(), item.rowCount());
+ QCOMPARE(item.columnCount(), columns - 1);
+ int index = column;
+ for (int i = 0; i < taken.count(); ++i) {
+ QCOMPARE(taken.at(i), originalChildren.takeAt(index));
+ index += item.columnCount();
+ }
+ index = 0;
+ for (int i = 0; i < item.rowCount(); ++i) {
+ for (int j = 0; j < item.columnCount(); ++j) {
+ QCOMPARE(item.child(i, j), originalChildren.at(index));
+ ++index;
+ }
+ }
+ } else {
+ QVERIFY(taken.isEmpty());
+ }
+ qDeleteAll(taken);
+}
+
+void tst_QStandardItem::takeRow_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<bool>("expectSuccess");
+
+ QTest::newRow("take -1 from 0x0") << 0 << 0 << -1 << false;
+ QTest::newRow("take 0 from 0x0") << 0 << 0 << 0 << false;
+ QTest::newRow("take 0 from 1x0") << 1 << 0 << 0 << true;
+ QTest::newRow("take 0 from 0x1") << 0 << 1 << 0 << false;
+ QTest::newRow("take 1 from 0x1") << 0 << 1 << 1 << false;
+ QTest::newRow("take 0 from 1x1") << 1 << 1 << 0 << true;
+ QTest::newRow("take 1 from 1x1") << 0 << 1 << 1 << false;
+ QTest::newRow("take 0 from 1x4") << 1 << 4 << 0 << true;
+ QTest::newRow("take 1 from 1x4") << 1 << 4 << 1 << false;
+ QTest::newRow("take 0 from 8x4") << 8 << 4 << 0 << true;
+ QTest::newRow("take 7 from 8x4") << 8 << 4 << 7 << true;
+ QTest::newRow("take 8 from 8x4") << 8 << 4 << 8 << false;
+}
+
+void tst_QStandardItem::takeRow()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, row);
+ QFETCH(bool, expectSuccess);
+
+ QStandardItem item(rows, columns);
+ QList<QStandardItem*> originalChildren;
+ // initialize children
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ QStandardItem *child = new QStandardItem;
+ originalChildren.append(child);
+ item.setChild(i, j, child);
+ }
+ }
+
+ QList<QStandardItem *> taken = item.takeRow(row);
+ if (expectSuccess) {
+ QCOMPARE(taken.count(), item.columnCount());
+ QCOMPARE(item.rowCount(), rows - 1);
+ int index = row * columns;
+ for (int i = 0; i < taken.count(); ++i) {
+ QCOMPARE(taken.at(i), originalChildren.takeAt(index));
+ }
+ index = 0;
+ for (int i = 0; i < item.rowCount(); ++i) {
+ for (int j = 0; j < item.columnCount(); ++j) {
+ QCOMPARE(item.child(i, j), originalChildren.at(index));
+ ++index;
+ }
+ }
+ } else {
+ QVERIFY(taken.isEmpty());
+ }
+ qDeleteAll(taken);
+}
+
+void tst_QStandardItem::streamItem()
+{
+ QStandardItem item;
+
+ item.setText(QLatin1String("text"));
+ item.setToolTip(QLatin1String("toolTip"));
+ item.setStatusTip(QLatin1String("statusTip"));
+ item.setWhatsThis(QLatin1String("whatsThis"));
+ item.setSizeHint(QSize(64, 48));
+ item.setFont(QFont());
+ item.setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
+ item.setBackground(QColor(Qt::blue));
+ item.setForeground(QColor(Qt::green));
+ item.setCheckState(Qt::PartiallyChecked);
+ item.setAccessibleText(QLatin1String("accessibleText"));
+ item.setAccessibleDescription(QLatin1String("accessibleDescription"));
+
+ QByteArray ba;
+ {
+ QDataStream ds(&ba, QIODevice::WriteOnly);
+ ds << item;
+ }
+ {
+ QStandardItem streamedItem;
+ QDataStream ds(&ba, QIODevice::ReadOnly);
+ ds >> streamedItem;
+ QCOMPARE(streamedItem.text(), item.text());
+ QCOMPARE(streamedItem.toolTip(), item.toolTip());
+ QCOMPARE(streamedItem.statusTip(), item.statusTip());
+ QCOMPARE(streamedItem.whatsThis(), item.whatsThis());
+ QCOMPARE(streamedItem.sizeHint(), item.sizeHint());
+ QCOMPARE(streamedItem.font(), item.font());
+ QCOMPARE(streamedItem.textAlignment(), item.textAlignment());
+ QCOMPARE(streamedItem.background(), item.background());
+ QCOMPARE(streamedItem.foreground(), item.foreground());
+ QCOMPARE(streamedItem.checkState(), item.checkState());
+ QCOMPARE(streamedItem.accessibleText(), item.accessibleText());
+ QCOMPARE(streamedItem.accessibleDescription(), item.accessibleDescription());
+ QCOMPARE(streamedItem.flags(), item.flags());
+ }
+}
+
+void tst_QStandardItem::deleteItem()
+{
+ QStandardItemModel model(4, 6);
+ // initialize items
+ for (int i = 0; i < model.rowCount(); ++i) {
+ for (int j = 0; j < model.columnCount(); ++j) {
+ QStandardItem *item = new QStandardItem();
+ model.setItem(i, j, item);
+ }
+ }
+ // delete items
+ for (int i = 0; i < model.rowCount(); ++i) {
+ for (int j = 0; j < model.columnCount(); ++j) {
+ QStandardItem *item = model.item(i, j);
+ delete item;
+ QCOMPARE(model.item(i, j), static_cast<QStandardItem*>(0));
+ }
+ }
+}
+
+void tst_QStandardItem::clone()
+{
+ QStandardItem item;
+ item.setText(QLatin1String("text"));
+ item.setToolTip(QLatin1String("toolTip"));
+ item.setStatusTip(QLatin1String("statusTip"));
+ item.setWhatsThis(QLatin1String("whatsThis"));
+ item.setSizeHint(QSize(64, 48));
+ item.setFont(QFont());
+ item.setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
+ item.setBackground(QColor(Qt::blue));
+ item.setForeground(QColor(Qt::green));
+ item.setCheckState(Qt::PartiallyChecked);
+ item.setAccessibleText(QLatin1String("accessibleText"));
+ item.setAccessibleDescription(QLatin1String("accessibleDescription"));
+ item.setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
+
+ QStandardItem *clone = item.clone();
+ QCOMPARE(clone->text(), item.text());
+ QCOMPARE(clone->toolTip(), item.toolTip());
+ QCOMPARE(clone->statusTip(), item.statusTip());
+ QCOMPARE(clone->whatsThis(), item.whatsThis());
+ QCOMPARE(clone->sizeHint(), item.sizeHint());
+ QCOMPARE(clone->font(), item.font());
+ QCOMPARE(clone->textAlignment(), item.textAlignment());
+ QCOMPARE(clone->background(), item.background());
+ QCOMPARE(clone->foreground(), item.foreground());
+ QCOMPARE(clone->checkState(), item.checkState());
+ QCOMPARE(clone->accessibleText(), item.accessibleText());
+ QCOMPARE(clone->accessibleDescription(), item.accessibleDescription());
+ QCOMPARE(clone->flags(), item.flags());
+ QVERIFY(!(*clone < item));
+ delete clone;
+}
+
+void tst_QStandardItem::sortChildren()
+{
+ for (int x = 0; x < 2; ++x) {
+ QStandardItemModel *model = new QStandardItemModel;
+ QStandardItem *item = (x == 0) ? new QStandardItem : model->invisibleRootItem();
+ QStandardItem *one = new QStandardItem;
+ one->appendRow(new QStandardItem(QLatin1String("a")));
+ one->appendRow(new QStandardItem(QLatin1String("b")));
+ one->appendRow(new QStandardItem(QLatin1String("c")));
+ QStandardItem *two = new QStandardItem;
+ two->appendRow(new QStandardItem(QLatin1String("f")));
+ two->appendRow(new QStandardItem(QLatin1String("d")));
+ two->appendRow(new QStandardItem(QLatin1String("e")));
+ item->appendRow(one);
+ item->appendRow(two);
+
+ QSignalSpy layoutAboutToBeChangedSpy(
+ model, SIGNAL(layoutAboutToBeChanged()));
+ QSignalSpy layoutChangedSpy(
+ model, SIGNAL(layoutChanged()));
+
+ one->sortChildren(0, Qt::DescendingOrder);
+ // verify sorted
+ QCOMPARE(one->child(0)->text(), QLatin1String("c"));
+ QCOMPARE(one->child(1)->text(), QLatin1String("b"));
+ QCOMPARE(one->child(2)->text(), QLatin1String("a"));
+ // verify siblings unaffected
+ QCOMPARE(two->child(0)->text(), QLatin1String("f"));
+ QCOMPARE(two->child(1)->text(), QLatin1String("d"));
+ QCOMPARE(two->child(2)->text(), QLatin1String("e"));
+
+ two->sortChildren(0, Qt::AscendingOrder);
+ // verify sorted
+ QCOMPARE(two->child(0)->text(), QLatin1String("d"));
+ QCOMPARE(two->child(1)->text(), QLatin1String("e"));
+ QCOMPARE(two->child(2)->text(), QLatin1String("f"));
+ // verify siblings unaffected
+ QCOMPARE(one->child(0)->text(), QLatin1String("c"));
+ QCOMPARE(one->child(1)->text(), QLatin1String("b"));
+ QCOMPARE(one->child(2)->text(), QLatin1String("a"));
+
+ item->sortChildren(0, Qt::AscendingOrder);
+ // verify everything sorted
+ QCOMPARE(one->child(0)->text(), QLatin1String("a"));
+ QCOMPARE(one->child(1)->text(), QLatin1String("b"));
+ QCOMPARE(one->child(2)->text(), QLatin1String("c"));
+ QCOMPARE(two->child(0)->text(), QLatin1String("d"));
+ QCOMPARE(two->child(1)->text(), QLatin1String("e"));
+ QCOMPARE(two->child(2)->text(), QLatin1String("f"));
+
+ QCOMPARE(layoutAboutToBeChangedSpy.count(), (x == 0) ? 0 : 3);
+ QCOMPARE(layoutChangedSpy.count(), (x == 0) ? 0 : 3);
+
+ if (x == 0)
+ delete item;
+ delete model;
+ }
+}
+
+class CustomItem : public QStandardItem
+{
+public:
+ CustomItem(const QString &text) : QStandardItem(text) { }
+ CustomItem() { }
+ virtual ~CustomItem() { }
+
+ virtual int type() const { return QStandardItem::UserType + 1; }
+
+ virtual QStandardItem *clone() const { return QStandardItem::clone(); }
+
+ void emitDataChanged() { QStandardItem::emitDataChanged(); }
+
+ virtual bool operator<(const QStandardItem &other) const {
+ return text().length() < other.text().length();
+ }
+};
+
+Q_DECLARE_METATYPE(QStandardItem*)
+
+void tst_QStandardItem::subclassing()
+{
+ qMetaTypeId<QStandardItem*>();
+
+ CustomItem *item = new CustomItem;
+ QCOMPARE(item->type(), int(QStandardItem::UserType + 1));
+
+ item->setText(QString::fromLatin1("foo"));
+ QCOMPARE(item->text(), QString::fromLatin1("foo"));
+
+ item->emitDataChanged(); // does nothing
+
+ QStandardItemModel model;
+ model.appendRow(item);
+
+ QSignalSpy itemChangedSpy(&model, SIGNAL(itemChanged(QStandardItem*)));
+ item->emitDataChanged();
+ QCOMPARE(itemChangedSpy.count(), 1);
+ QCOMPARE(itemChangedSpy.at(0).count(), 1);
+ QCOMPARE(qvariant_cast<QStandardItem*>(itemChangedSpy.at(0).at(0)), (QStandardItem*)item);
+
+ CustomItem *child0 = new CustomItem("cc");
+ CustomItem *child1 = new CustomItem("bbb");
+ CustomItem *child2 = new CustomItem("a");
+ item->appendRow(child0);
+ item->appendRow(child1);
+ item->appendRow(child2);
+ item->sortChildren(0);
+ QCOMPARE(item->child(0), (QStandardItem*)child2);
+ QCOMPARE(item->child(1), (QStandardItem*)child0);
+ QCOMPARE(item->child(2), (QStandardItem*)child1);
+}
+
+QTEST_MAIN(tst_QStandardItem)
+#include "tst_qstandarditem.moc"
diff --git a/tests/auto/widgets/itemviews/qstandarditemmodel/.gitignore b/tests/auto/widgets/itemviews/qstandarditemmodel/.gitignore
new file mode 100644
index 0000000000..c218efce58
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstandarditemmodel/.gitignore
@@ -0,0 +1 @@
+tst_qstandarditemmodel
diff --git a/tests/auto/widgets/itemviews/qstandarditemmodel/qstandarditemmodel.pro b/tests/auto/widgets/itemviews/qstandarditemmodel/qstandarditemmodel.pro
new file mode 100644
index 0000000000..8c634b9630
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstandarditemmodel/qstandarditemmodel.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qstandarditemmodel.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/widgets/itemviews/qstandarditemmodel/tst_qstandarditemmodel.cpp
new file mode 100644
index 0000000000..84a33107aa
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstandarditemmodel/tst_qstandarditemmodel.cpp
@@ -0,0 +1,1666 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qstandarditemmodel.h>
+#include <QTreeView>
+#include <private/qtreeview_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QStandardItemModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QStandardItemModel();
+ virtual ~tst_QStandardItemModel();
+
+ enum ModelChanged {
+ RowsAboutToBeInserted,
+ RowsInserted,
+ RowsAboutToBeRemoved,
+ RowsRemoved,
+ ColumnsAboutToBeInserted,
+ ColumnsInserted,
+ ColumnsAboutToBeRemoved,
+ ColumnsRemoved
+ };
+
+public slots:
+ void init();
+ void cleanup();
+
+protected slots:
+ void checkAboutToBeRemoved();
+ void checkRemoved();
+ void updateRowAboutToBeRemoved();
+
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsAboutToBeInserted, parent, first, last); }
+ void rowsInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsInserted, parent, first, last); }
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsAboutToBeRemoved, parent, first, last); }
+ void rowsRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(RowsRemoved, parent, first, last); }
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsAboutToBeInserted, parent, first, last); }
+ void columnsInserted(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsInserted, parent, first, last); }
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsAboutToBeRemoved, parent, first, last); }
+ void columnsRemoved(const QModelIndex &parent, int first, int last)
+ { modelChanged(ColumnsRemoved, parent, first, last); }
+
+ void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last);
+
+private slots:
+ void insertRow_data();
+ void insertRow();
+ void insertRows();
+ void insertRowsItems();
+ void insertRowInHierarcy();
+ void insertColumn_data();
+ void insertColumn();
+ void insertColumns();
+ void removeRows();
+ void removeColumns();
+ void setHeaderData();
+ void persistentIndexes();
+ void removingPersistentIndexes();
+ void updatingPersistentIndexes();
+
+ void checkChildren();
+ void data();
+ void clear();
+ void sort_data();
+ void sort();
+ void sortRole_data();
+ void sortRole();
+ void findItems();
+ void getSetHeaderItem();
+ void indexFromItem();
+ void itemFromIndex();
+ void getSetItemPrototype();
+ void getSetItemData();
+ void setHeaderLabels_data();
+ void setHeaderLabels();
+ void itemDataChanged();
+ void takeHeaderItem();
+ void useCase1();
+ void useCase2();
+ void useCase3();
+
+ void rootItemFlags();
+ void treeDragAndDrop();
+ void removeRowsAndColumns();
+
+private:
+ QAbstractItemModel *m_model;
+ QPersistentModelIndex persistent;
+ QVector<QModelIndex> rcParent;
+ QVector<int> rcFirst;
+ QVector<int> rcLast;
+
+ //return true if models have the same structure, and all child have the same text
+ bool compareModels(QStandardItemModel *model1, QStandardItemModel *model2);
+ //return true if models have the same structure, and all child have the same text
+ bool compareItems(QStandardItem *item1, QStandardItem *item2);
+};
+
+static const int defaultSize = 3;
+
+Q_DECLARE_METATYPE(QModelIndex)
+Q_DECLARE_METATYPE(QStandardItem*)
+Q_DECLARE_METATYPE(Qt::Orientation)
+Q_DECLARE_METATYPE(QVariantList)
+
+tst_QStandardItemModel::tst_QStandardItemModel() : m_model(0), rcParent(8), rcFirst(8,0), rcLast(8,0)
+{
+}
+
+tst_QStandardItemModel::~tst_QStandardItemModel()
+{
+}
+
+/*
+ This test usually uses a model with a 3x3 table
+ ---------------------------
+ | 0,0 | 0,1 | 0,2 |
+ ---------------------------
+ | 1,0 | 1,1 | 1,2 |
+ ---------------------------
+ | 2,0 | 2,1 | 2,2 |
+ ---------------------------
+*/
+void tst_QStandardItemModel::init()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ qRegisterMetaType<QStandardItem*>("QStandardItem*");
+ qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
+
+ m_model = new QStandardItemModel(defaultSize, defaultSize);
+ connect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeInserted(QModelIndex, int, int)));
+ connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(rowsInserted(QModelIndex, int, int)));
+ connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsRemoved(QModelIndex, int, int)));
+
+ connect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)),
+ this, SLOT(columnsAboutToBeInserted(QModelIndex, int, int)));
+ connect(m_model, SIGNAL(columnsInserted(QModelIndex, int, int)),
+ this, SLOT(columnsInserted(QModelIndex, int, int)));
+ connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(columnsAboutToBeRemoved(QModelIndex, int, int)));
+ connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)),
+ this, SLOT(columnsRemoved(QModelIndex, int, int)));
+
+ rcFirst.fill(-1);
+ rcLast.fill(-1);
+}
+
+void tst_QStandardItemModel::cleanup()
+{
+ disconnect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeInserted(QModelIndex, int, int)));
+ disconnect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(rowsInserted(QModelIndex, int, int)));
+ disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsRemoved(QModelIndex, int, int)));
+
+ disconnect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)),
+ this, SLOT(columnsAboutToBeInserted(QModelIndex, int, int)));
+ disconnect(m_model, SIGNAL(columnsInserted(QModelIndex, int, int)),
+ this, SLOT(columnsInserted(QModelIndex, int, int)));
+ disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(columnsAboutToBeRemoved(QModelIndex, int, int)));
+ disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)),
+ this, SLOT(columnsRemoved(QModelIndex, int, int)));
+ delete m_model;
+ m_model = 0;
+}
+
+void tst_QStandardItemModel::insertRow_data()
+{
+ QTest::addColumn<int>("insertRow");
+ QTest::addColumn<int>("expectedRow");
+
+ QTest::newRow("Insert less then 0") << -1 << 0;
+ QTest::newRow("Insert at 0") << 0 << 0;
+ QTest::newRow("Insert beyond count") << defaultSize+1 << defaultSize;
+ QTest::newRow("Insert at count") << defaultSize << defaultSize;
+ QTest::newRow("Insert in the middle") << 1 << 1;
+}
+
+void tst_QStandardItemModel::insertRow()
+{
+ QFETCH(int, insertRow);
+ QFETCH(int, expectedRow);
+
+ QIcon icon;
+ // default all initial items to DisplayRole: "initalitem"
+ for (int r=0; r < m_model->rowCount(); ++r) {
+ for (int c=0; c < m_model->columnCount(); ++c) {
+ m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
+ }
+ }
+
+ // check that inserts changes rowCount
+ QCOMPARE(m_model->rowCount(), defaultSize);
+ m_model->insertRow(insertRow);
+ if (insertRow >= 0 && insertRow <= defaultSize) {
+ QCOMPARE(m_model->rowCount(), defaultSize + 1);
+
+ // check that signals were emitted with correct info
+ QCOMPARE(rcFirst[RowsAboutToBeInserted], expectedRow);
+ QCOMPARE(rcLast[RowsAboutToBeInserted], expectedRow);
+ QCOMPARE(rcFirst[RowsInserted], expectedRow);
+ QCOMPARE(rcLast[RowsInserted], expectedRow);
+
+ //check that the inserted item has different DisplayRole than initial items
+ QVERIFY(m_model->data(m_model->index(expectedRow, 0), Qt::DisplayRole).toString() != "initialitem");
+ } else {
+ // We inserted something outside the bounds, do nothing
+ QCOMPARE(m_model->rowCount(), defaultSize);
+ QCOMPARE(rcFirst[RowsAboutToBeInserted], -1);
+ QCOMPARE(rcLast[RowsAboutToBeInserted], -1);
+ QCOMPARE(rcFirst[RowsInserted], -1);
+ QCOMPARE(rcLast[RowsInserted], -1);
+ }
+}
+
+void tst_QStandardItemModel::insertRows()
+{
+ int rowCount = m_model->rowCount();
+ QCOMPARE(rowCount, defaultSize);
+
+ // insert custom header label
+ QString headerLabel = "custom";
+ m_model->setHeaderData(0, Qt::Vertical, headerLabel);
+
+ // insert one row
+ m_model->insertRows(0, 1);
+ QCOMPARE(m_model->rowCount(), rowCount + 1);
+ rowCount = m_model->rowCount();
+
+ // check header data has moved
+ QCOMPARE(m_model->headerData(1, Qt::Vertical).toString(), headerLabel);
+
+ // insert two rows
+ m_model->insertRows(0, 2);
+ QCOMPARE(m_model->rowCount(), rowCount + 2);
+
+ // check header data has moved
+ QCOMPARE(m_model->headerData(3, Qt::Vertical).toString(), headerLabel);
+}
+
+void tst_QStandardItemModel::insertRowsItems()
+{
+ int rowCount = m_model->rowCount();
+
+ QList<QStandardItem *> items;
+ QStandardItemModel *m = qobject_cast<QStandardItemModel*>(m_model);
+ QStandardItem *hiddenRoot = m->invisibleRootItem();
+ for (int i = 0; i < 3; ++i)
+ items.append(new QStandardItem(QString("%1").arg(i + 10)));
+ hiddenRoot->appendRows(items);
+ QCOMPARE(m_model->rowCount(), rowCount + 3);
+ QCOMPARE(m_model->index(rowCount + 0, 0).data().toInt(), 10);
+ QCOMPARE(m_model->index(rowCount + 1, 0).data().toInt(), 11);
+ QCOMPARE(m_model->index(rowCount + 2, 0).data().toInt(), 12);
+ for (int i = rowCount; i < rowCount + 3; ++i) {
+ QVERIFY(m->item(i));
+ QCOMPARE(static_cast<QAbstractItemModel *>(m->item(i)->model()), m_model);
+ }
+}
+
+void tst_QStandardItemModel::insertRowInHierarcy()
+{
+ QVERIFY(m_model->insertRows(0, 1, QModelIndex()));
+ QVERIFY(m_model->insertColumns(0, 1, QModelIndex()));
+ QVERIFY(m_model->hasIndex(0, 0, QModelIndex()));
+
+ QModelIndex parent = m_model->index(0, 0, QModelIndex());
+ QVERIFY(parent.isValid());
+
+ QVERIFY(m_model->insertRows(0, 1, parent));
+ QVERIFY(m_model->insertColumns(0, 1, parent));
+ QVERIFY(m_model->hasIndex(0, 0, parent));
+
+ QModelIndex child = m_model->index(0, 0, parent);
+ QVERIFY(child.isValid());
+}
+
+void tst_QStandardItemModel::insertColumn_data()
+{
+ QTest::addColumn<int>("insertColumn");
+ QTest::addColumn<int>("expectedColumn");
+
+ QTest::newRow("Insert less then 0") << -1 << 0;
+ QTest::newRow("Insert at 0") << 0 << 0;
+ QTest::newRow("Insert beyond count") << defaultSize+1 << defaultSize;
+ QTest::newRow("Insert at count") << defaultSize << defaultSize;
+ QTest::newRow("Insert in the middle") << 1 << 1;
+}
+
+void tst_QStandardItemModel::insertColumn()
+{
+ QFETCH(int, insertColumn);
+ QFETCH(int, expectedColumn);
+
+ // default all initial items to DisplayRole: "initalitem"
+ for (int r=0; r < m_model->rowCount(); ++r) {
+ for (int c=0; c < m_model->columnCount(); ++c) {
+ m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
+ }
+ }
+
+ // check that inserts changes columnCount
+ QCOMPARE(m_model->columnCount(), defaultSize);
+ m_model->insertColumn(insertColumn);
+ if (insertColumn >= 0 && insertColumn <= defaultSize) {
+ QCOMPARE(m_model->columnCount(), defaultSize + 1);
+ // check that signals were emitted with correct info
+ QCOMPARE(rcFirst[ColumnsAboutToBeInserted], expectedColumn);
+ QCOMPARE(rcLast[ColumnsAboutToBeInserted], expectedColumn);
+ QCOMPARE(rcFirst[ColumnsInserted], expectedColumn);
+ QCOMPARE(rcLast[ColumnsInserted], expectedColumn);
+
+ //check that the inserted item has different DisplayRole than initial items
+ QVERIFY(m_model->data(m_model->index(0, expectedColumn), Qt::DisplayRole).toString() != "initialitem");
+ } else {
+ // We inserted something outside the bounds, do nothing
+ QCOMPARE(m_model->columnCount(), defaultSize);
+ QCOMPARE(rcFirst[ColumnsAboutToBeInserted], -1);
+ QCOMPARE(rcLast[ColumnsAboutToBeInserted], -1);
+ QCOMPARE(rcFirst[ColumnsInserted], -1);
+ QCOMPARE(rcLast[ColumnsInserted], -1);
+ }
+
+}
+
+void tst_QStandardItemModel::insertColumns()
+{
+ int columnCount = m_model->columnCount();
+ QCOMPARE(columnCount, defaultSize);
+
+ // insert custom header label
+ QString headerLabel = "custom";
+ m_model->setHeaderData(0, Qt::Horizontal, headerLabel);
+
+ // insert one column
+ m_model->insertColumns(0, 1);
+ QCOMPARE(m_model->columnCount(), columnCount + 1);
+ columnCount = m_model->columnCount();
+
+ // check header data has moved
+ QCOMPARE(m_model->headerData(1, Qt::Horizontal).toString(), headerLabel);
+
+ // insert two columns
+ m_model->insertColumns(0, 2);
+ QCOMPARE(m_model->columnCount(), columnCount + 2);
+
+ // check header data has moved
+ QCOMPARE(m_model->headerData(3, Qt::Horizontal).toString(), headerLabel);
+}
+
+void tst_QStandardItemModel::removeRows()
+{
+ int rowCount = m_model->rowCount();
+ QCOMPARE(rowCount, defaultSize);
+
+ // insert custom header label
+ QString headerLabel = "custom";
+ m_model->setHeaderData(rowCount - 1, Qt::Vertical, headerLabel);
+
+ // remove one row
+ m_model->removeRows(0, 1);
+ QCOMPARE(m_model->rowCount(), rowCount - 1);
+ rowCount = m_model->rowCount();
+
+ // check header data has moved
+ QCOMPARE(m_model->headerData(rowCount - 1, Qt::Vertical).toString(), headerLabel);
+
+ // remove two rows
+ m_model->removeRows(0, 2);
+ QCOMPARE(m_model->rowCount(), rowCount - 2);
+}
+
+void tst_QStandardItemModel::removeColumns()
+{
+ int columnCount = m_model->columnCount();
+ QCOMPARE(columnCount, defaultSize);
+
+ // insert custom header label
+ QString headerLabel = "custom";
+ m_model->setHeaderData(columnCount - 1, Qt::Horizontal, headerLabel);
+
+ // remove one column
+ m_model->removeColumns(0, 1);
+ QCOMPARE(m_model->columnCount(), columnCount - 1);
+ columnCount = m_model->columnCount();
+
+ // check header data has moved
+ QCOMPARE(m_model->headerData(columnCount - 1, Qt::Horizontal).toString(), headerLabel);
+
+ // remove two columns
+ m_model->removeColumns(0, 2);
+ QCOMPARE(m_model->columnCount(), columnCount - 2);
+}
+
+
+void tst_QStandardItemModel::setHeaderData()
+{
+ for (int x = 0; x < 2; ++x) {
+ bool vertical = (x == 0);
+ int count = vertical ? m_model->rowCount() : m_model->columnCount();
+ QCOMPARE(count, defaultSize);
+ Qt::Orientation orient = vertical ? Qt::Vertical : Qt::Horizontal;
+
+ // check default values are ok
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(m_model->headerData(i, orient).toString(), QString::number(i + 1));
+
+ QSignalSpy headerDataChangedSpy(
+ m_model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
+ QSignalSpy dataChangedSpy(
+ m_model, SIGNAL(dataChanged(QModelIndex, QModelIndex)));
+ // insert custom values and check
+ for (int i = 0; i < count; ++i) {
+ QString customString = QString("custom") + QString::number(i);
+ QCOMPARE(m_model->setHeaderData(i, orient, customString), true);
+ QCOMPARE(headerDataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.count(), 0);
+ QVariantList args = headerDataChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<Qt::Orientation>(args.at(0)), orient);
+ QCOMPARE(args.at(1).toInt(), i);
+ QCOMPARE(args.at(2).toInt(), i);
+ QCOMPARE(m_model->headerData(i, orient).toString(), customString);
+ QCOMPARE(m_model->setHeaderData(i, orient, customString), true);
+ QCOMPARE(headerDataChangedSpy.count(), 0);
+ QCOMPARE(dataChangedSpy.count(), 0);
+ }
+
+ //check read from invalid sections
+ QVERIFY(!m_model->headerData(count, orient).isValid());
+ QVERIFY(!m_model->headerData(-1, orient).isValid());
+ //check write to invalid section
+ QCOMPARE(m_model->setHeaderData(count, orient, "foo"), false);
+ QCOMPARE(m_model->setHeaderData(-1, orient, "foo"), false);
+ QVERIFY(!m_model->headerData(count, orient).isValid());
+ QVERIFY(!m_model->headerData(-1, orient).isValid());
+ }
+}
+
+void tst_QStandardItemModel::persistentIndexes()
+{
+ QCOMPARE(m_model->rowCount(), defaultSize);
+ QCOMPARE(m_model->columnCount(), defaultSize);
+
+ // create a persisten index at 0,0
+ QPersistentModelIndex persistentIndex(m_model->index(0, 0));
+
+ // verify it is ok and at the correct spot
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 0);
+ QCOMPARE(persistentIndex.column(), 0);
+
+ // insert row and check that the persisten index has moved
+ QVERIFY(m_model->insertRow(0));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 1);
+ QCOMPARE(persistentIndex.column(), 0);
+
+ // insert row after the persisten index and see that it stays the same
+ QVERIFY(m_model->insertRow(m_model->rowCount()));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 1);
+ QCOMPARE(persistentIndex.column(), 0);
+
+ // insert column and check that the persisten index has moved
+ QVERIFY(m_model->insertColumn(0));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 1);
+ QCOMPARE(persistentIndex.column(), 1);
+
+ // insert column after the persisten index and see that it stays the same
+ QVERIFY(m_model->insertColumn(m_model->columnCount()));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 1);
+ QCOMPARE(persistentIndex.column(), 1);
+
+ // removes a row beyond the persistent index and see it stays the same
+ QVERIFY(m_model->removeRow(m_model->rowCount() - 1));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 1);
+ QCOMPARE(persistentIndex.column(), 1);
+
+ // removes a column beyond the persistent index and see it stays the same
+ QVERIFY(m_model->removeColumn(m_model->columnCount() - 1));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 1);
+ QCOMPARE(persistentIndex.column(), 1);
+
+ // removes a row before the persistent index and see it moves the same
+ QVERIFY(m_model->removeRow(0));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 0);
+ QCOMPARE(persistentIndex.column(), 1);
+
+ // removes a column before the persistent index and see it moves the same
+ QVERIFY(m_model->removeColumn(0));
+ QVERIFY(persistentIndex.isValid());
+ QCOMPARE(persistentIndex.row(), 0);
+ QCOMPARE(persistentIndex.column(), 0);
+
+ // remove the row where the persistent index is, and see that it becomes invalid
+ QVERIFY(m_model->removeRow(0));
+ QVERIFY(!persistentIndex.isValid());
+
+ // remove the row where the persistent index is, and see that it becomes invalid
+ persistentIndex = m_model->index(0, 0);
+ QVERIFY(persistentIndex.isValid());
+ QVERIFY(m_model->removeColumn(0));
+ QVERIFY(!persistentIndex.isValid());
+}
+
+void tst_QStandardItemModel::checkAboutToBeRemoved()
+{
+ QVERIFY(persistent.isValid());
+}
+
+void tst_QStandardItemModel::checkRemoved()
+{
+ QVERIFY(!persistent.isValid());
+}
+
+void tst_QStandardItemModel::removingPersistentIndexes()
+{
+ // add 10 rows and columns to model to make it big enough
+ QVERIFY(m_model->insertRows(0, 10));
+ QVERIFY(m_model->insertColumns(0, 10));
+
+ QObject::connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ this, SLOT(checkAboutToBeRemoved()));
+ QObject::connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(checkRemoved()));
+ QObject::connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
+ this, SLOT(checkAboutToBeRemoved()));
+ QObject::connect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
+ this, SLOT(checkRemoved()));
+
+
+ // test removeRow
+ // add child table 3x3 to parent index(0, 0)
+ QVERIFY(m_model->insertRows(0, 3, m_model->index(0, 0)));
+ QVERIFY(m_model->insertColumns(0, 3, m_model->index(0, 0)));
+
+ // set child to persistent and delete parent row
+ persistent = m_model->index(0, 0, m_model->index(0, 0));
+ QVERIFY(persistent.isValid());
+ QVERIFY(m_model->removeRow(0));
+
+ // set persistent to index(0, 0) and remove that row
+ persistent = m_model->index(0, 0);
+ QVERIFY(persistent.isValid());
+ QVERIFY(m_model->removeRow(0));
+
+
+ // test removeColumn
+ // add child table 3x3 to parent index (0, 0)
+ QVERIFY(m_model->insertRows(0, 3, m_model->index(0, 0)));
+ QVERIFY(m_model->insertColumns(0, 3, m_model->index(0, 0)));
+
+ // set child to persistent and delete parent column
+ persistent = m_model->index(0, 0, m_model->index(0, 0));
+ QVERIFY(persistent.isValid());
+ QVERIFY(m_model->removeColumn(0));
+
+ // set persistent to index(0, 0) and remove that column
+ persistent = m_model->index(0, 0);
+ QVERIFY(persistent.isValid());
+ QVERIFY(m_model->removeColumn(0));
+
+
+ QObject::disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ this, SLOT(checkAboutToBeRemoved()));
+ QObject::disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(checkRemoved()));
+ QObject::disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
+ this, SLOT(checkAboutToBeRemoved()));
+ QObject::disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
+ this, SLOT(checkRemoved()));
+}
+
+void tst_QStandardItemModel::updateRowAboutToBeRemoved()
+{
+ QModelIndex idx = m_model->index(0, 0);
+ QVERIFY(idx.isValid());
+ persistent = idx;
+}
+
+void tst_QStandardItemModel::updatingPersistentIndexes()
+{
+ QObject::connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ this, SLOT(updateRowAboutToBeRemoved()));
+
+ persistent = m_model->index(1, 0);
+ QVERIFY(persistent.isValid());
+ QVERIFY(m_model->removeRow(1));
+ QVERIFY(persistent.isValid());
+ QPersistentModelIndex tmp = m_model->index(0, 0);
+ QCOMPARE(persistent, tmp);
+
+ QObject::disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ this, SLOT(updateRowAboutToBeRemoved()));
+}
+
+void tst_QStandardItemModel::modelChanged(ModelChanged change, const QModelIndex &parent,
+ int first, int last)
+{
+ rcParent[change] = parent;
+ rcFirst[change] = first;
+ rcLast[change] = last;
+}
+
+
+void tst_QStandardItemModel::checkChildren()
+{
+ QStandardItemModel model(0, 0);
+ QCOMPARE(model.rowCount(), 0);
+ QCOMPARE(model.columnCount(), 0);
+ QVERIFY(!model.hasChildren());
+
+ QVERIFY(model.insertRows(0, 1));
+ QVERIFY(!model.hasChildren());
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.columnCount(), 0);
+
+ QVERIFY(model.insertColumns(0, 1));
+ QVERIFY(model.hasChildren());
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.columnCount(), 1);
+
+ QModelIndex idx = model.index(0, 0);
+ QVERIFY(!model.hasChildren(idx));
+ QCOMPARE(model.rowCount(idx), 0);
+ QCOMPARE(model.columnCount(idx), 0);
+
+ QVERIFY(model.insertRows(0, 1, idx));
+ QVERIFY(!model.hasChildren(idx));
+ QCOMPARE(model.rowCount(idx), 1);
+ QCOMPARE(model.columnCount(idx), 0);
+
+ QVERIFY(model.insertColumns(0, 1, idx));
+ QVERIFY(model.hasChildren(idx));
+ QCOMPARE(model.rowCount(idx), 1);
+ QCOMPARE(model.columnCount(idx), 1);
+
+ QModelIndex idx2 = model.index(0, 0, idx);
+ QVERIFY(!model.hasChildren(idx2));
+ QCOMPARE(model.rowCount(idx2), 0);
+ QCOMPARE(model.columnCount(idx2), 0);
+
+ QVERIFY(model.removeRows(0, 1, idx));
+ QVERIFY(model.hasChildren());
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.columnCount(), 1);
+ QVERIFY(!model.hasChildren(idx));
+ QCOMPARE(model.rowCount(idx), 0);
+ QCOMPARE(model.columnCount(idx), 1);
+
+ QVERIFY(model.removeRows(0, 1));
+ QVERIFY(!model.hasChildren());
+ QCOMPARE(model.rowCount(), 0);
+ QCOMPARE(model.columnCount(), 1);
+}
+
+void tst_QStandardItemModel::data()
+{
+ // bad args
+ m_model->setData(QModelIndex(), "bla", Qt::DisplayRole);
+
+ QIcon icon;
+ for (int r=0; r < m_model->rowCount(); ++r) {
+ for (int c=0; c < m_model->columnCount(); ++c) {
+ m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
+ m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole);
+ m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole);
+ }
+ }
+
+ QVERIFY(m_model->data(m_model->index(0, 0), Qt::DisplayRole).toString() == "initialitem");
+ QVERIFY(m_model->data(m_model->index(0, 0), Qt::ToolTipRole).toString() == "tooltip");
+
+}
+
+void tst_QStandardItemModel::clear()
+{
+ QStandardItemModel model;
+ model.insertColumns(0, 10);
+ model.insertRows(0, 10);
+ QCOMPARE(model.columnCount(), 10);
+ QCOMPARE(model.rowCount(), 10);
+
+ QSignalSpy modelResetSpy(&model, SIGNAL(modelReset()));
+ QSignalSpy layoutChangedSpy(&model, SIGNAL(layoutChanged()));
+ QSignalSpy rowsRemovedSpy(&model, SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ model.clear();
+
+ QCOMPARE(modelResetSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.count(), 0);
+ QCOMPARE(rowsRemovedSpy.count(), 0);
+ QCOMPARE(model.index(0, 0), QModelIndex());
+ QCOMPARE(model.columnCount(), 0);
+ QCOMPARE(model.rowCount(), 0);
+ QCOMPARE(model.hasChildren(), false);
+}
+
+void tst_QStandardItemModel::sort_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat descending") << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "zulu"
+ << "yankee"
+ << "xray"
+ << "whiskey"
+ << "viktor"
+ << "uniform"
+ << "tango"
+ << "sierra"
+ << "romeo"
+ << "quebec"
+ << "papa"
+ << "oskar"
+ << "november"
+ << "mike"
+ << "lima"
+ << "kilo"
+ << "juliet"
+ << "india"
+ << "hotel"
+ << "golf"
+ << "foxtrot"
+ << "echo"
+ << "delta"
+ << "charlie"
+ << "bravo"
+ << "alpha");
+ QTest::newRow("flat ascending") << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "alpha"
+ << "bravo"
+ << "charlie"
+ << "delta"
+ << "echo"
+ << "foxtrot"
+ << "golf"
+ << "hotel"
+ << "india"
+ << "juliet"
+ << "kilo"
+ << "lima"
+ << "mike"
+ << "november"
+ << "oskar"
+ << "papa"
+ << "quebec"
+ << "romeo"
+ << "sierra"
+ << "tango"
+ << "uniform"
+ << "viktor"
+ << "whiskey"
+ << "xray"
+ << "yankee"
+ << "zulu");
+ QStringList list;
+ for (int i=1000; i < 2000; ++i)
+ list.append(QString("Number: %1").arg(i));
+ QTest::newRow("large set ascending") << static_cast<int>(Qt::AscendingOrder) << list << list;
+}
+
+void tst_QStandardItemModel::sort()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ // prepare model
+ QStandardItemModel model;
+ QVERIFY(model.insertRows(0, initial.count(), QModelIndex()));
+ QCOMPARE(model.rowCount(QModelIndex()), initial.count());
+ model.insertColumns(0, 1, QModelIndex());
+ QCOMPARE(model.columnCount(QModelIndex()), 1);
+ for (int row = 0; row < model.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = model.index(row, 0, QModelIndex());
+ model.setData(index, initial.at(row), Qt::DisplayRole);
+ }
+
+ QSignalSpy layoutAboutToBeChangedSpy(
+ &model, SIGNAL(layoutAboutToBeChanged()));
+ QSignalSpy layoutChangedSpy(
+ &model, SIGNAL(layoutChanged()));
+
+ // sort
+ model.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+
+ QCOMPARE(layoutAboutToBeChangedSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.count(), 1);
+
+ // make sure the model is sorted
+ for (int row = 0; row < model.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = model.index(row, 0, QModelIndex());
+ QCOMPARE(model.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+void tst_QStandardItemModel::sortRole_data()
+{
+ QTest::addColumn<QStringList>("initialText");
+ QTest::addColumn<QVariantList>("initialData");
+ QTest::addColumn<int>("sortRole");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("expectedText");
+ QTest::addColumn<QVariantList>("expectedData");
+
+ QTest::newRow("sort ascending with Qt::DisplayRole")
+ << (QStringList() << "b" << "a" << "c")
+ << (QVariantList() << 2 << 3 << 1)
+ << static_cast<int>(Qt::DisplayRole)
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "b" << "c")
+ << (QVariantList() << 3 << 2 << 1);
+ QTest::newRow("sort ascending with Qt::UserRole")
+ << (QStringList() << "a" << "b" << "c")
+ << (QVariantList() << 3 << 2 << 1)
+ << static_cast<int>(Qt::UserRole)
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "b" << "a")
+ << (QVariantList() << 1 << 2 << 3);
+}
+
+void tst_QStandardItemModel::sortRole()
+{
+ QFETCH(QStringList, initialText);
+ QFETCH(QVariantList, initialData);
+ QFETCH(int, sortRole);
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, expectedText);
+ QFETCH(QVariantList, expectedData);
+
+ QStandardItemModel model;
+ for (int i = 0; i < initialText.count(); ++i) {
+ QStandardItem *item = new QStandardItem;
+ item->setText(initialText.at(i));
+ item->setData(initialData.at(i), Qt::UserRole);
+ model.appendRow(item);
+ }
+ model.setSortRole(sortRole);
+ model.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ for (int i = 0; i < expectedText.count(); ++i) {
+ QStandardItem *item = model.item(i);
+ QCOMPARE(item->text(), expectedText.at(i));
+ QCOMPARE(item->data(Qt::UserRole), expectedData.at(i));
+ }
+}
+
+void tst_QStandardItemModel::findItems()
+{
+ QStandardItemModel model;
+ model.appendRow(new QStandardItem(QLatin1String("foo")));
+ model.appendRow(new QStandardItem(QLatin1String("bar")));
+ model.item(1)->appendRow(new QStandardItem(QLatin1String("foo")));
+ QList<QStandardItem*> matches;
+ matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, 0);
+ QCOMPARE(matches.count(), 2);
+ matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly, 0);
+ QCOMPARE(matches.count(), 1);
+ matches = model.findItems(QLatin1String("food"), Qt::MatchExactly|Qt::MatchRecursive, 0);
+ QCOMPARE(matches.count(), 0);
+ matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, -1);
+ QCOMPARE(matches.count(), 0);
+ matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, 1);
+ QCOMPARE(matches.count(), 0);
+}
+
+void tst_QStandardItemModel::getSetHeaderItem()
+{
+ QStandardItemModel model;
+
+ QCOMPARE(model.horizontalHeaderItem(0), static_cast<QStandardItem*>(0));
+ QStandardItem *hheader = new QStandardItem();
+ model.setHorizontalHeaderItem(0, hheader);
+ QCOMPARE(model.columnCount(), 1);
+ QCOMPARE(model.horizontalHeaderItem(0), hheader);
+ QCOMPARE(hheader->model(), &model);
+ model.setHorizontalHeaderItem(0, 0);
+ QCOMPARE(model.horizontalHeaderItem(0), static_cast<QStandardItem*>(0));
+
+ QCOMPARE(model.verticalHeaderItem(0), static_cast<QStandardItem*>(0));
+ QStandardItem *vheader = new QStandardItem();
+ model.setVerticalHeaderItem(0, vheader);
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.verticalHeaderItem(0), vheader);
+ QCOMPARE(vheader->model(), &model);
+ model.setVerticalHeaderItem(0, 0);
+ QCOMPARE(model.verticalHeaderItem(0), static_cast<QStandardItem*>(0));
+}
+
+void tst_QStandardItemModel::indexFromItem()
+{
+ QStandardItemModel model;
+
+ QCOMPARE(model.indexFromItem(model.invisibleRootItem()), QModelIndex());
+
+ QStandardItem *item = new QStandardItem;
+ model.setItem(10, 20, item);
+ QCOMPARE(item->model(), &model);
+ QModelIndex itemIndex = model.indexFromItem(item);
+ QVERIFY(itemIndex.isValid());
+ QCOMPARE(itemIndex.row(), 10);
+ QCOMPARE(itemIndex.column(), 20);
+ QCOMPARE(itemIndex.parent(), QModelIndex());
+ QCOMPARE(itemIndex.model(), (const QAbstractItemModel*)(&model));
+
+ QStandardItem *child = new QStandardItem;
+ item->setChild(4, 2, child);
+ QModelIndex childIndex = model.indexFromItem(child);
+ QVERIFY(childIndex.isValid());
+ QCOMPARE(childIndex.row(), 4);
+ QCOMPARE(childIndex.column(), 2);
+ QCOMPARE(childIndex.parent(), itemIndex);
+
+ QStandardItem *dummy = new QStandardItem;
+ QModelIndex noSuchIndex = model.indexFromItem(dummy);
+ QVERIFY(!noSuchIndex.isValid());
+ delete dummy;
+
+ noSuchIndex = model.indexFromItem(0);
+ QVERIFY(!noSuchIndex.isValid());
+}
+
+void tst_QStandardItemModel::itemFromIndex()
+{
+ QStandardItemModel model;
+
+ QCOMPARE(model.itemFromIndex(QModelIndex()), (QStandardItem*)0);
+
+ QStandardItem *item = new QStandardItem;
+ model.setItem(10, 20, item);
+ QModelIndex itemIndex = model.index(10, 20, QModelIndex());
+ QVERIFY(itemIndex.isValid());
+ QCOMPARE(model.itemFromIndex(itemIndex), item);
+
+ QStandardItem *child = new QStandardItem;
+ item->setChild(4, 2, child);
+ QModelIndex childIndex = model.index(4, 2, itemIndex);
+ QVERIFY(childIndex.isValid());
+ QCOMPARE(model.itemFromIndex(childIndex), child);
+
+ QModelIndex noSuchIndex = model.index(99, 99, itemIndex);
+ QVERIFY(!noSuchIndex.isValid());
+}
+
+class CustomItem : public QStandardItem
+{
+public:
+ CustomItem() : QStandardItem() { }
+ ~CustomItem() { }
+ int type() const {
+ return UserType;
+ }
+ QStandardItem *clone() const {
+ return new CustomItem;
+ }
+};
+
+void tst_QStandardItemModel::getSetItemPrototype()
+{
+ QStandardItemModel model;
+ QCOMPARE(model.itemPrototype(), static_cast<const QStandardItem*>(0));
+
+ const CustomItem *proto = new CustomItem;
+ model.setItemPrototype(proto);
+ QCOMPARE(model.itemPrototype(), (const QStandardItem*)proto);
+
+ model.setRowCount(1);
+ model.setColumnCount(1);
+ QModelIndex index = model.index(0, 0, QModelIndex());
+ model.setData(index, "foo");
+ QStandardItem *item = model.itemFromIndex(index);
+ QVERIFY(item != 0);
+ QCOMPARE(item->type(), static_cast<int>(QStandardItem::UserType));
+
+ model.setItemPrototype(0);
+ QCOMPARE(model.itemPrototype(), static_cast<const QStandardItem*>(0));
+}
+
+void tst_QStandardItemModel::getSetItemData()
+{
+ QMap<int, QVariant> roles;
+ QLatin1String text("text");
+ roles.insert(Qt::DisplayRole, text);
+ QLatin1String statusTip("statusTip");
+ roles.insert(Qt::StatusTipRole, statusTip);
+ QLatin1String toolTip("toolTip");
+ roles.insert(Qt::ToolTipRole, toolTip);
+ QLatin1String whatsThis("whatsThis");
+ roles.insert(Qt::WhatsThisRole, whatsThis);
+ QSize sizeHint(64, 48);
+ roles.insert(Qt::SizeHintRole, sizeHint);
+ QFont font;
+ roles.insert(Qt::FontRole, font);
+ Qt::Alignment textAlignment(Qt::AlignLeft|Qt::AlignVCenter);
+ roles.insert(Qt::TextAlignmentRole, int(textAlignment));
+ QColor backgroundColor(Qt::blue);
+ roles.insert(Qt::BackgroundRole, backgroundColor);
+ QColor textColor(Qt::green);
+ roles.insert(Qt::TextColorRole, textColor);
+ Qt::CheckState checkState(Qt::PartiallyChecked);
+ roles.insert(Qt::CheckStateRole, int(checkState));
+ QLatin1String accessibleText("accessibleText");
+ roles.insert(Qt::AccessibleTextRole, accessibleText);
+ QLatin1String accessibleDescription("accessibleDescription");
+ roles.insert(Qt::AccessibleDescriptionRole, accessibleDescription);
+
+ QStandardItemModel model;
+ model.insertRows(0, 1);
+ model.insertColumns(0, 1);
+ QModelIndex idx = model.index(0, 0, QModelIndex());
+
+ QSignalSpy modelDataChangedSpy(
+ &model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)));
+ QVERIFY(model.setItemData(idx, roles));
+ QCOMPARE(modelDataChangedSpy.count(), 1);
+ QVERIFY(model.setItemData(idx, roles));
+ QCOMPARE(modelDataChangedSpy.count(), 1); //it was already changed once
+ QCOMPARE(model.itemData(idx), roles);
+}
+
+void tst_QStandardItemModel::setHeaderLabels_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("orientation");
+ QTest::addColumn<QStringList>("labels");
+ QTest::addColumn<QStringList>("expectedLabels");
+
+ QTest::newRow("horizontal labels")
+ << 1
+ << 4
+ << int(Qt::Horizontal)
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (QStringList() << "a" << "b" << "c" << "d");
+ QTest::newRow("vertical labels")
+ << 4
+ << 1
+ << int(Qt::Vertical)
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (QStringList() << "a" << "b" << "c" << "d");
+ QTest::newRow("too few (horizontal)")
+ << 1
+ << 4
+ << int(Qt::Horizontal)
+ << (QStringList() << "a" << "b")
+ << (QStringList() << "a" << "b" << "3" << "4");
+ QTest::newRow("too few (vertical)")
+ << 4
+ << 1
+ << int(Qt::Vertical)
+ << (QStringList() << "a" << "b")
+ << (QStringList() << "a" << "b" << "3" << "4");
+ QTest::newRow("too many (horizontal)")
+ << 1
+ << 2
+ << int(Qt::Horizontal)
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (QStringList() << "a" << "b" << "c" << "d");
+ QTest::newRow("too many (vertical)")
+ << 2
+ << 1
+ << int(Qt::Vertical)
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (QStringList() << "a" << "b" << "c" << "d");
+}
+
+void tst_QStandardItemModel::setHeaderLabels()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(int, orientation);
+ QFETCH(QStringList, labels);
+ QFETCH(QStringList, expectedLabels);
+ QStandardItemModel model(rows, columns);
+ QSignalSpy columnsInsertedSpy(
+ &model, SIGNAL(columnsInserted(QModelIndex,int,int)));
+ QSignalSpy rowsInsertedSpy(
+ &model, SIGNAL(rowsInserted(QModelIndex,int,int)));
+ if (orientation == Qt::Horizontal)
+ model.setHorizontalHeaderLabels(labels);
+ else
+ model.setVerticalHeaderLabels(labels);
+ for (int i = 0; i < expectedLabels.count(); ++i)
+ QCOMPARE(model.headerData(i, Qt::Orientation(orientation)).toString(), expectedLabels.at(i));
+ QCOMPARE(columnsInsertedSpy.count(),
+ (orientation == Qt::Vertical) ? 0 : labels.count() > columns);
+ QCOMPARE(rowsInsertedSpy.count(),
+ (orientation == Qt::Horizontal) ? 0 : labels.count() > rows);
+}
+
+void tst_QStandardItemModel::itemDataChanged()
+{
+ QStandardItemModel model(6, 4);
+ QStandardItem item;
+ QSignalSpy dataChangedSpy(
+ &model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+ QSignalSpy itemChangedSpy(
+ &model, SIGNAL(itemChanged(QStandardItem *)));
+
+ model.setItem(0, &item);
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ QModelIndex index = model.indexFromItem(&item);
+ QList<QVariant> args;
+ args = dataChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
+
+ item.setData(QLatin1String("foo"), Qt::DisplayRole);
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = dataChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
+
+ item.setData(item.data(Qt::DisplayRole), Qt::DisplayRole);
+ QCOMPARE(dataChangedSpy.count(), 0);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ item.setFlags(Qt::ItemIsEnabled);
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = dataChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
+
+ item.setFlags(item.flags());
+ QCOMPARE(dataChangedSpy.count(), 0);
+ QCOMPARE(itemChangedSpy.count(), 0);
+}
+
+void tst_QStandardItemModel::takeHeaderItem()
+{
+ QStandardItemModel model;
+ // set header items
+ QStandardItem *hheader = new QStandardItem();
+ model.setHorizontalHeaderItem(0, hheader);
+ QStandardItem *vheader = new QStandardItem();
+ model.setVerticalHeaderItem(0, vheader);
+ // take header items
+ QCOMPARE(model.takeHorizontalHeaderItem(0), hheader);
+ QCOMPARE(model.takeVerticalHeaderItem(0), vheader);
+ QCOMPARE(hheader->model(), static_cast<QStandardItemModel*>(0));
+ QCOMPARE(vheader->model(), static_cast<QStandardItemModel*>(0));
+ QCOMPARE(model.takeHorizontalHeaderItem(0), static_cast<QStandardItem*>(0));
+ QCOMPARE(model.takeVerticalHeaderItem(0), static_cast<QStandardItem*>(0));
+ delete hheader;
+ delete vheader;
+}
+
+void tst_QStandardItemModel::useCase1()
+{
+ const int rows = 5;
+ const int columns = 8;
+ QStandardItemModel model(rows, columns);
+ for (int i = 0; i < model.rowCount(); ++i) {
+ for (int j = 0; j < model.columnCount(); ++j) {
+ QCOMPARE(model.item(i, j), static_cast<QStandardItem*>(0));
+
+ QStandardItem *item = new QStandardItem();
+ model.setItem(i, j, item);
+ QCOMPARE(item->row(), i);
+ QCOMPARE(item->column(), j);
+ QCOMPARE(item->model(), &model);
+
+ QModelIndex index = model.indexFromItem(item);
+ QCOMPARE(index, model.index(i, j, QModelIndex()));
+ QStandardItem *sameItem = model.itemFromIndex(index);
+ QCOMPARE(sameItem, item);
+ }
+ }
+}
+
+static void createChildren(QStandardItemModel *model, QStandardItem *parent, int level)
+{
+ if (level > 4)
+ return;
+ for (int i = 0; i < 4; ++i) {
+ QCOMPARE(parent->rowCount(), i);
+ parent->appendRow(QList<QStandardItem*>());
+ for (int j = 0; j < parent->columnCount(); ++j) {
+ QStandardItem *item = new QStandardItem();
+ parent->setChild(i, j, item);
+ QCOMPARE(item->row(), i);
+ QCOMPARE(item->column(), j);
+
+ QModelIndex parentIndex = model->indexFromItem(parent);
+ QModelIndex index = model->indexFromItem(item);
+ QCOMPARE(index, model->index(i, j, parentIndex));
+ QStandardItem *theItem = model->itemFromIndex(index);
+ QCOMPARE(theItem, item);
+ QStandardItem *theParent = model->itemFromIndex(parentIndex);
+ QCOMPARE(theParent, (level == 0) ? (QStandardItem*)0 : parent);
+ }
+
+ {
+ QStandardItem *item = parent->child(i);
+ item->setColumnCount(parent->columnCount());
+ createChildren(model, item, level + 1);
+ }
+ }
+}
+
+void tst_QStandardItemModel::useCase2()
+{
+ QStandardItemModel model;
+ model.setColumnCount(2);
+ createChildren(&model, model.invisibleRootItem(), 0);
+}
+
+void tst_QStandardItemModel::useCase3()
+{
+ // create the tree structure first
+ QStandardItem *childItem = 0;
+ for (int i = 0; i < 100; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ if (childItem)
+ item->appendRow(childItem);
+ childItem = item;
+ }
+
+ // add to model as last step
+ QStandardItemModel model;
+ model.appendRow(childItem);
+
+ // make sure each item has the correct model and parent
+ QStandardItem *parentItem = 0;
+ while (childItem) {
+ QCOMPARE(childItem->model(), &model);
+ QCOMPARE(childItem->parent(), parentItem);
+ parentItem = childItem;
+ childItem = childItem->child(0);
+ }
+
+ // take the item, make sure model is set to 0, but that parents are the same
+ childItem = model.takeItem(0);
+ {
+ parentItem = 0;
+ QStandardItem *item = childItem;
+ while (item) {
+ QCOMPARE(item->model(), static_cast<QStandardItemModel*>(0));
+ QCOMPARE(item->parent(), parentItem);
+ parentItem = item;
+ item = item->child(0);
+ }
+ }
+ delete childItem;
+}
+
+void tst_QStandardItemModel::rootItemFlags()
+{
+ QStandardItemModel model(6, 4);
+ QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
+ QCOMPARE(model.invisibleRootItem()->flags() , Qt::ItemIsDropEnabled);
+
+ Qt::ItemFlags f = Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
+ model.invisibleRootItem()->setFlags(f);
+ QCOMPARE(model.invisibleRootItem()->flags() , f);
+ QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
+
+#ifndef QT_NO_DRAGANDDROP
+ model.invisibleRootItem()->setDropEnabled(false);
+#endif
+ QCOMPARE(model.invisibleRootItem()->flags() , Qt::ItemIsEnabled);
+ QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
+}
+
+bool tst_QStandardItemModel::compareModels(QStandardItemModel *model1, QStandardItemModel *model2)
+{
+ return compareItems(model1->invisibleRootItem(), model2->invisibleRootItem());
+}
+
+bool tst_QStandardItemModel::compareItems(QStandardItem *item1, QStandardItem *item2)
+{
+ if (!item1 && !item2)
+ return true;
+ if (!item1 || !item2)
+ return false;
+ if (item1->text() != item2->text()){
+ qDebug() << item1->text() << item2->text();
+ return false;
+ }
+ if (item1->rowCount() != item2->rowCount()) {
+ // qDebug() << "RowCount" << item1->text() << item1->rowCount() << item2->rowCount();
+ return false;
+ }
+ if (item1->columnCount() != item2->columnCount()) {
+ // qDebug() << "ColumnCount" << item1->text() << item1->columnCount() << item2->columnCount();
+ return false;
+ }
+ for (int row = 0; row < item1->columnCount(); row++)
+ for (int col = 0; col < item1->columnCount(); col++) {
+
+ if (!compareItems(item1->child(row, col), item2->child(row, col)))
+ return false;
+ }
+ return true;
+}
+
+static QStandardItem *itemFromText(QStandardItem *parent, const QString &text)
+{
+ QStandardItem *item = 0;
+ for(int i = 0; i < parent->columnCount(); i++)
+ for(int j = 0; j < parent->rowCount(); j++) {
+
+ QStandardItem *child = parent->child(j, i);
+
+ if(!child)
+ continue;
+
+ if (child->text() == text) {
+ if (item) {
+ return 0;
+ }
+ item = child;
+ }
+
+ QStandardItem *candidate = itemFromText(child, text);
+ if(candidate) {
+ if (item) {
+ return 0;
+ }
+ item = candidate;
+ }
+ }
+ return item;
+}
+
+#ifdef QT_BUILD_INTERNAL
+static QModelIndex indexFromText(QStandardItemModel *model, const QString &text)
+{
+ QStandardItem *item = itemFromText(model->invisibleRootItem(), text);
+ /*QVERIFY(item);*/
+ return model->indexFromItem(item);
+}
+
+
+struct FriendlyTreeView : public QTreeView
+{
+ friend class tst_QStandardItemModel;
+ Q_DECLARE_PRIVATE(QTreeView)
+};
+#endif
+
+void tst_QStandardItemModel::treeDragAndDrop()
+{
+#ifdef QT_BUILD_INTERNAL
+ const int nRow = 5;
+ const int nCol = 3;
+
+ QStandardItemModel model;
+ QStandardItemModel checkModel;
+
+ for (int i = 0; i < nRow; ++i) {
+ QList<QStandardItem *> colItems1;
+ for (int c = 0 ; c < nCol; c ++)
+ colItems1 << new QStandardItem(QString("item %1 - %0").arg(c).arg(i));
+ model.appendRow(colItems1);
+
+ for (int j = 0; j < nRow; ++j) {
+ QList<QStandardItem *> colItems2;
+ for (int c = 0 ; c < nCol; c ++)
+ colItems2 << new QStandardItem(QString("item %1/%2 - %0").arg(c).arg(i).arg(j));
+ colItems1.at(0)->appendRow(colItems2);
+
+ for (int k = 0; k < nRow; ++k) {
+ QList<QStandardItem *> colItems3;
+ for (int c = 0 ; c < nCol; c ++)
+ colItems3 << new QStandardItem(QString("item %1/%2/%3 - %0").arg(c).arg(i).arg(j).arg(k));
+ colItems2.at(0)->appendRow(colItems3);
+ }
+ }
+ }
+
+ for (int i = 0; i < nRow; ++i) {
+ QList<QStandardItem *> colItems1;
+ for (int c = 0 ; c < nCol; c ++)
+ colItems1 << new QStandardItem(QString("item %1 - %0").arg(c).arg(i));
+ checkModel.appendRow(colItems1);
+
+ for (int j = 0; j < nRow; ++j) {
+ QList<QStandardItem *> colItems2;
+ for (int c = 0 ; c < nCol; c ++)
+ colItems2 << new QStandardItem(QString("item %1/%2 - %0").arg(c).arg(i).arg(j));
+ colItems1.at(0)->appendRow(colItems2);
+
+ for (int k = 0; k < nRow; ++k) {
+ QList<QStandardItem *> colItems3;
+ for (int c = 0 ; c < nCol; c ++)
+ colItems3 << new QStandardItem(QString("item %1/%2/%3 - %0").arg(c).arg(i).arg(j).arg(k));
+ colItems2.at(0)->appendRow(colItems3);
+ }
+ }
+ }
+
+ QVERIFY(compareModels(&model, &checkModel));
+
+ FriendlyTreeView view;
+ view.setModel(&model);
+ view.expandAll();
+ view.show();
+#ifndef QT_NO_DRAGANDDROP
+ view.setDragDropMode(QAbstractItemView::InternalMove);
+#endif
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ QItemSelectionModel *selection = view.selectionModel();
+
+ //
+ // step1 drag "item 1" and "item 2" into "item 4"
+ //
+ {
+ selection->clear();
+ selection->select(QItemSelection(indexFromText(&model, QString("item 1 - 0")),
+ indexFromText(&model, QString("item 1 - %0").arg(nCol-1))), QItemSelectionModel::Select);
+
+ selection->select(QItemSelection(indexFromText(&model, QString("item 2 - 0")),
+ indexFromText(&model, QString("item 2 - %0").arg(nCol-1))), QItemSelectionModel::Select);
+
+ //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
+ QModelIndexList indexes = view.selectedIndexes();
+ QMimeData *data = model.mimeData(indexes);
+ if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 4 - 0")))
+ view.d_func()->clearOrRemove();
+ delete data;
+
+ QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
+ QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
+ item4->insertRow(0, checkModel.takeRow(1));
+ item4->insertRow(1, checkModel.takeRow(1));
+ QVERIFY(compareModels(&model, &checkModel));
+ }
+
+ //
+ // step2 drag "item 3" and "item 3/0" into "item 4"
+ //
+ {
+ selection->clear();
+ selection->select(QItemSelection(indexFromText(&model, QString("item 3 - 0")),
+ indexFromText(&model, QString("item 3 - %0").arg(nCol-1))), QItemSelectionModel::Select);
+
+ selection->select(QItemSelection(indexFromText(&model, QString("item 3/0 - 0")),
+ indexFromText(&model, QString("item 3/0 - %0").arg(nCol-1))), QItemSelectionModel::Select);
+
+ //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
+ QModelIndexList indexes = view.selectedIndexes();
+ QMimeData *data = model.mimeData(indexes);
+ if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 4 - 0")))
+ view.d_func()->clearOrRemove();
+ delete data;
+
+ QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
+ QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
+ item4->insertRow(0, checkModel.takeRow(1));
+
+ QVERIFY(compareModels(&model, &checkModel));
+ }
+
+ //
+ // step2 drag "item 3" and "item 3/0/2" into "item 0/2"
+ // ( remember "item 3" is now the first child of "item 4")
+ //
+ {
+ selection->clear();
+ selection->select(QItemSelection(indexFromText(&model, QString("item 3 - 0")),
+ indexFromText(&model, QString("item 3 - %0").arg(nCol-1))), QItemSelectionModel::Select);
+
+ selection->select(QItemSelection(indexFromText(&model, QString("item 3/0/2 - 0")),
+ indexFromText(&model, QString("item 3/0/2 - %0").arg(nCol-1))), QItemSelectionModel::Select);
+
+ //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
+ QModelIndexList indexes = view.selectedIndexes();
+ QMimeData *data = model.mimeData(indexes);
+ if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 0/2 - 0")))
+ view.d_func()->clearOrRemove();
+ delete data;
+
+ QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
+ QStandardItem *item02 = itemFromText(checkModel.invisibleRootItem(), "item 0/2 - 0");
+ QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
+ item02->insertRow(0, item4->takeRow(0));
+
+ QVERIFY(compareModels(&model, &checkModel));
+ }
+#endif
+}
+
+void tst_QStandardItemModel::removeRowsAndColumns()
+{
+#define VERIFY_MODEL \
+ for (int c = 0; c < col_list.count(); c++) \
+ for (int r = 0; r < row_list.count(); r++) \
+ QCOMPARE(model.item(r,c)->text() , row_list[r] + "x" + col_list[c]);
+
+ QVector<QString> row_list = QString("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20").split(',').toVector();
+ QVector<QString> col_list = row_list;
+ QStandardItemModel model;
+ for (int c = 0; c < col_list.count(); c++)
+ for (int r = 0; r < row_list.count(); r++)
+ model.setItem(r, c, new QStandardItem(row_list[r] + "x" + col_list[c]));
+ VERIFY_MODEL
+
+ row_list.remove(3);
+ model.removeRow(3);
+ VERIFY_MODEL
+
+ col_list.remove(5);
+ model.removeColumn(5);
+ VERIFY_MODEL
+
+ row_list.remove(2, 5);
+ model.removeRows(2, 5);
+ VERIFY_MODEL
+
+ col_list.remove(1, 6);
+ model.removeColumns(1, 6);
+ VERIFY_MODEL
+
+ QList<QStandardItem *> row_taken = model.takeRow(6);
+ QCOMPARE(row_taken.count(), col_list.count());
+ for (int c = 0; c < col_list.count(); c++)
+ QCOMPARE(row_taken[c]->text() , row_list[6] + "x" + col_list[c]);
+ row_list.remove(6);
+ VERIFY_MODEL
+
+ QList<QStandardItem *> col_taken = model.takeColumn(10);
+ QCOMPARE(col_taken.count(), row_list.count());
+ for (int r = 0; r < row_list.count(); r++)
+ QCOMPARE(col_taken[r]->text() , row_list[r] + "x" + col_list[10]);
+ col_list.remove(10);
+ VERIFY_MODEL
+}
+
+
+QTEST_MAIN(tst_QStandardItemModel)
+#include "tst_qstandarditemmodel.moc"
diff --git a/tests/auto/widgets/itemviews/qstringlistmodel/.gitignore b/tests/auto/widgets/itemviews/qstringlistmodel/.gitignore
new file mode 100644
index 0000000000..9c14561e3c
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstringlistmodel/.gitignore
@@ -0,0 +1 @@
+tst_qstringlistmodel
diff --git a/tests/auto/widgets/itemviews/qstringlistmodel/qmodellistener.h b/tests/auto/widgets/itemviews/qstringlistmodel/qmodellistener.h
new file mode 100644
index 0000000000..f3ed3c1793
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstringlistmodel/qmodellistener.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QObject>
+#include <QModelIndex>
+#include <qdebug.h>
+
+
+QT_FORWARD_DECLARE_CLASS(QStringListModel)
+
+class QModelListener : public QObject
+{
+ Q_OBJECT
+public:
+ QModelListener(QStringList *pAboutToStringlist, QStringList *pExpectedStringlist, QStringListModel *pModel)
+ {
+ setTestData(pAboutToStringlist, pExpectedStringlist, pModel);
+ }
+ virtual ~QModelListener() { }
+
+ void setTestData(QStringList *pAboutToStringlist, QStringList *pExpectedStringlist, QStringListModel *pModel)
+ {
+ m_pAboutToStringlist = pAboutToStringlist;
+ m_pExpectedStringlist = pExpectedStringlist;
+ m_pModel = pModel;
+ }
+
+private:
+ QStringList *m_pAboutToStringlist;
+ QStringList *m_pExpectedStringlist;
+ QStringListModel *m_pModel;
+
+public slots:
+ void rowsAboutToBeRemovedOrInserted(const QModelIndex & parent, int start, int end );
+ void rowsRemovedOrInserted(const QModelIndex & parent, int start, int end );
+
+};
+
diff --git a/tests/auto/widgets/itemviews/qstringlistmodel/qstringlistmodel.pro b/tests/auto/widgets/itemviews/qstringlistmodel/qstringlistmodel.pro
new file mode 100644
index 0000000000..fe70ed7345
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstringlistmodel/qstringlistmodel.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+QT += widgets
+HEADERS += qmodellistener.h
+
+SOURCES += tst_qstringlistmodel.cpp
+
+
+
diff --git a/tests/auto/widgets/itemviews/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/widgets/itemviews/qstringlistmodel/tst_qstringlistmodel.cpp
new file mode 100644
index 0000000000..2542496f14
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qstringlistmodel/tst_qstringlistmodel.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qabstractitemmodel.h>
+#include <qapplication.h>
+#include <qmap.h>
+#include <qstringlistmodel.h>
+#include <qstringlist.h>
+#include <qlistview.h>
+#include "qmodellistener.h"
+#include <qstringlistmodel.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+void QModelListener::rowsAboutToBeRemovedOrInserted(const QModelIndex & parent, int start, int end )
+{
+ int i;
+ for (i = 0; start + i <= end; i++)
+ {
+ QModelIndex mIndex = m_pModel->index(start + i, 0, parent);
+ QVariant var = m_pModel->data(mIndex, Qt::DisplayRole);
+ QString str = var.toString();
+
+ QCOMPARE(str, m_pAboutToStringlist->at(i));
+ }
+}
+
+void QModelListener::rowsRemovedOrInserted(const QModelIndex & parent, int , int)
+{
+ int i;
+ // Can the rows that *are* removed be iterated now ?
+
+ // What about rowsAboutToBeInserted - what will the indices be?
+ // will insertRow() overwrite existing, or insert (and conseq. grow the model?)
+ // What will the item then contain? empty data?
+
+ // RemoveColumn. Does that also fire the rowsRemoved-family signals?
+
+ for (i = 0; i < m_pExpectedStringlist->size(); i++)
+ {
+ QModelIndex mIndex = m_pModel->index(i, 0, parent);
+ QVariant var = m_pModel->data(mIndex, Qt::DisplayRole);
+ QString str = var.toString();
+
+ //qDebug() << "index: " << i << " start: " << start << "end: " << end;
+ QCOMPARE(str, m_pExpectedStringlist->at(i));
+ }
+}
+
+
+class tst_QStringListModel : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ tst_QStringListModel();
+ virtual ~tst_QStringListModel();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+
+ void rowsAboutToBeRemoved_rowsRemoved();
+ void rowsAboutToBeRemoved_rowsRemoved_data();
+
+ void rowsAboutToBeInserted_rowsInserted();
+ void rowsAboutToBeInserted_rowsInserted_data();
+};
+
+
+tst_QStringListModel::tst_QStringListModel()
+
+{
+}
+
+tst_QStringListModel::~tst_QStringListModel()
+{
+}
+
+void tst_QStringListModel::initTestCase()
+{
+}
+
+void tst_QStringListModel::cleanupTestCase()
+{
+}
+
+void tst_QStringListModel::init()
+{
+}
+
+void tst_QStringListModel::cleanup()
+{
+}
+
+/*
+ tests
+*/
+
+
+void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved_data()
+{
+ QTest::addColumn<QStringList>("input");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QStringList>("aboutto");
+ QTest::addColumn<QStringList>("res");
+
+ QStringList strings0; strings0 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto0; aboutto0 << "Two" << "Three";
+ QStringList res0; res0 << "One" << "Four" << "Five";
+ QTest::newRow( "data0" ) << strings0 << 1 << 2 << aboutto0 << res0;
+
+ QStringList strings1; strings1 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto1; aboutto1 << "One" << "Two";
+ QStringList res1; res1 << "Three" << "Four" << "Five";
+ QTest::newRow( "data1" ) << strings1 << 0 << 2 << aboutto1 << res1;
+
+ QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto2; aboutto2 << "Four" << "Five";
+ QStringList res2; res2 << "One" << "Two" << "Three";
+ QTest::newRow( "data2" ) << strings2 << 3 << 2 << aboutto2 << res2;
+
+ QStringList strings3; strings3 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto3; aboutto3 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList res3; res3 ;
+ QTest::newRow( "data3" ) << strings3 << 0 << 5 << aboutto3 << res3;
+
+ /* Not sure if this is a valid test */
+ QStringList strings4; strings4 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto4; aboutto4 << "Five" << "";
+ QStringList res4; res4 << "One" << "Two" << "Three" << "Four";
+ QTest::newRow( "data4" ) << strings4 << 4 << 2 << aboutto4 << res4;
+
+ /*
+ * Keep this, template to add more data
+ QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto2; aboutto2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList res2; res2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QTest::newRow( "data2" ) << strings2 << 0 << 5 << aboutto2 << res2;
+*/
+
+}
+
+void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved()
+{
+ QFETCH(QStringList, input);
+ QFETCH(int, row);
+ QFETCH(int, count);
+ QFETCH(QStringList, aboutto);
+ QFETCH(QStringList, res);
+
+ QStringListModel *model = new QStringListModel(input);
+ QModelListener *pListener = new QModelListener(&aboutto, &res, model);
+ pListener->connect(model, SIGNAL( rowsAboutToBeRemoved(const QModelIndex & , int , int )),
+ pListener, SLOT( rowsAboutToBeRemovedOrInserted(const QModelIndex & , int , int )) );
+
+ pListener->connect(model, SIGNAL( rowsRemoved(const QModelIndex & , int , int )),
+ pListener, SLOT( rowsRemovedOrInserted(const QModelIndex & , int , int )) );
+
+ model->removeRows(row,count);
+ // At this point, control goes to our connected slots inn this order:
+ // 1. rowsAboutToBeRemovedOrInserted
+ // 2. rowsRemovedOrInserted
+ // Control returns here
+
+ delete pListener;
+ delete model;
+
+}
+
+void tst_QStringListModel::rowsAboutToBeInserted_rowsInserted_data()
+{
+ QTest::addColumn<QStringList>("input");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QStringList>("aboutto");
+ QTest::addColumn<QStringList>("res");
+
+ QStringList strings0; strings0 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto0; aboutto0 << "Two" << "Three";
+ QStringList res0; res0 << "One" << "" << "" << "Two" << "Three" << "Four" << "Five";
+ QTest::newRow( "data0" ) << strings0 << 1 << 2 << aboutto0 << res0;
+
+ QStringList strings1; strings1 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto1; aboutto1 << "One" << "Two";
+ QStringList res1; res1 << "" << "" << "One" << "Two" << "Three" << "Four" << "Five";
+ QTest::newRow( "data1" ) << strings1 << 0 << 2 << aboutto1 << res1;
+
+ QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto2; aboutto2 << "Four" << "Five";
+ QStringList res2; res2 << "One" << "Two" << "Three" << "" << "" << "Four" << "Five";
+ QTest::newRow( "data2" ) << strings2 << 3 << 2 << aboutto2 << res2;
+
+ QStringList strings3; strings3 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto3; aboutto3 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList res3; res3 << "" << "" << "" << "" << "" << "One" << "Two" << "Three" << "Four" << "Five";
+ QTest::newRow( "data3" ) << strings3 << 0 << 5 << aboutto3 << res3;
+
+ /*
+ * Keep this, template to add more data
+ QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList aboutto2; aboutto2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList res2; res2 << "One" << "Two" << "Three" << "Four" << "Five";
+ QTest::newRow( "data2" ) << strings2 << 0 << 5 << aboutto2 << res2;
+*/
+
+}
+
+void tst_QStringListModel::rowsAboutToBeInserted_rowsInserted()
+{
+ QFETCH(QStringList, input);
+ QFETCH(int, row);
+ QFETCH(int, count);
+ QFETCH(QStringList, aboutto);
+ QFETCH(QStringList, res);
+
+ QStringListModel *model = new QStringListModel(input);
+ QModelListener *pListener = new QModelListener(&aboutto, &res, model);
+ connect(model, SIGNAL( rowsAboutToBeInserted(const QModelIndex & , int , int )),
+ pListener, SLOT( rowsAboutToBeRemovedOrInserted(const QModelIndex & , int , int )) );
+
+ connect(model, SIGNAL( rowsInserted(const QModelIndex & , int , int )),
+ pListener, SLOT( rowsRemovedOrInserted(const QModelIndex & , int , int )) );
+
+ model->insertRows(row,count);
+ // At this point, control goes to our connected slots inn this order:
+ // 1. rowsAboutToBeRemovedOrInserted
+ // 2. rowsRemovedOrInserted
+ // Control returns here
+
+ delete pListener;
+ delete model;
+
+}
+
+
+QTEST_MAIN(tst_QStringListModel)
+#include "tst_qstringlistmodel.moc"
+
diff --git a/tests/auto/widgets/itemviews/qtableview/.gitignore b/tests/auto/widgets/itemviews/qtableview/.gitignore
new file mode 100644
index 0000000000..e2c6365d65
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtableview/.gitignore
@@ -0,0 +1 @@
+tst_qtableview
diff --git a/tests/auto/widgets/itemviews/qtableview/qtableview.pro b/tests/auto/widgets/itemviews/qtableview/qtableview.pro
new file mode 100644
index 0000000000..408119a782
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtableview/qtableview.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+TARGET.EPOCHEAPSIZE = 0x200000 0x800000
+SOURCES += tst_qtableview.cpp
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
new file mode 100644
index 0000000000..2242490a44
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -0,0 +1,4075 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+#include <private/qtablewidget_p.h>
+#include <QtTest/QtTest>
+#include "private/qapplication_p.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+// Will try to wait for the condition while allowing event processing
+// for a maximum of 2 seconds.
+#define WAIT_FOR_CONDITION(expr, expected) \
+ do { \
+ const int step = 100; \
+ for (int i = 0; i < 2000 && expr != expected; i+=step) { \
+ QTest::qWait(step); \
+ } \
+ } while(0)
+
+#ifdef QT_BUILD_INTERNAL
+#define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) \
+ QVERIFY(static_cast<QTableViewPrivate*>(QObjectPrivate::get(TEST_VIEW_))->spans.checkConsistency())
+#else
+#define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) (void)false
+#endif
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+typedef QList<bool> BoolList;
+Q_DECLARE_METATYPE(BoolList)
+
+class tst_QTableView : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTableView();
+ virtual ~tst_QTableView();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+
+ void noDelegate();
+ void noModel();
+ void emptyModel();
+
+ void removeRows_data();
+ void removeRows();
+
+ void removeColumns_data();
+ void removeColumns();
+
+ void keyboardNavigation_data();
+ void keyboardNavigation();
+
+ void headerSections_data();
+ void headerSections();
+
+ void moveCursor_data();
+ void moveCursor();
+
+ void moveCursorStrikesBack_data();
+ void moveCursorStrikesBack();
+
+ void hideRows_data();
+ void hideRows();
+
+ void hideColumns_data();
+ void hideColumns();
+
+ void selection_data();
+ void selection();
+
+ void selectRow_data();
+ void selectRow();
+
+ void selectColumn_data();
+ void selectColumn();
+
+ void visualRect_data();
+ void visualRect();
+
+ void fetchMore();
+ void setHeaders();
+
+ void resizeRowsToContents_data();
+ void resizeRowsToContents();
+
+ void resizeColumnsToContents_data();
+ void resizeColumnsToContents();
+
+ void rowViewportPosition_data();
+ void rowViewportPosition();
+
+ void rowAt_data();
+ void rowAt();
+
+ void rowHeight_data();
+ void rowHeight();
+
+ void columnViewportPosition_data();
+ void columnViewportPosition();
+
+ void columnAt_data();
+ void columnAt();
+
+ void columnWidth_data();
+ void columnWidth();
+
+ void hiddenRow_data();
+ void hiddenRow();
+
+ void hiddenColumn_data();
+ void hiddenColumn();
+
+ void sortingEnabled_data();
+ void sortingEnabled();
+
+ void scrollTo_data();
+ void scrollTo();
+
+ void indexAt_data();
+ void indexAt();
+
+ void span_data();
+ void span();
+ void spans();
+ void spans_data();
+ void spansAfterRowInsertion();
+ void spansAfterColumnInsertion();
+ void spansAfterRowRemoval();
+ void spansAfterColumnRemoval();
+
+ void checkHeaderReset();
+ void checkHeaderMinSize();
+
+ void resizeToContents();
+
+ void tabFocus();
+ void bigModel();
+ void selectionSignal();
+
+ // task-specific tests:
+ void task173773_updateVerticalHeader();
+ void task227953_setRootIndex();
+ void task240266_veryBigColumn();
+ void task248688_autoScrollNavigation();
+ void task259308_scrollVerticalHeaderSwappedSections();
+ void task191545_dragSelectRows();
+ void taskQTBUG_5062_spansInconsistency();
+ void taskQTBUG_4516_clickOnRichTextLabel();
+ void taskQTBUG_5237_wheelEventOnHeader();
+ void taskQTBUG_8585_crashForNoGoodReason();
+ void taskQTBUG_7774_RtoLVisualRegionForSelection();
+ void taskQTBUG_8777_scrollToSpans();
+ void taskQTBUG_10169_sizeHintForRow();
+
+#ifndef Q_OS_WINCE
+ void mouseWheel_data();
+ void mouseWheel();
+#endif
+
+ void addColumnWhileEditing();
+ void task234926_setHeaderSorting();
+
+ void changeHeaderData();
+};
+
+// Testing get/set functions
+void tst_QTableView::getSetCheck()
+{
+ QTableView obj1;
+
+ obj1.setSortingEnabled(false);
+ QCOMPARE(false, obj1.isSortingEnabled());
+ obj1.setSortingEnabled(true);
+ QCOMPARE(true, obj1.isSortingEnabled());
+
+ obj1.setShowGrid(false);
+ QCOMPARE(false, obj1.showGrid());
+ obj1.setShowGrid(true);
+ QCOMPARE(true, obj1.showGrid());
+
+ obj1.setGridStyle(Qt::NoPen);
+ QCOMPARE(Qt::NoPen, obj1.gridStyle());
+ obj1.setGridStyle(Qt::SolidLine);
+ QCOMPARE(Qt::SolidLine, obj1.gridStyle());
+
+ obj1.setRootIndex(QModelIndex());
+ QCOMPARE(QModelIndex(), obj1.rootIndex());
+ QStandardItemModel model(10, 10);
+ obj1.setModel(&model);
+ QModelIndex index = model.index(0, 0);
+ obj1.setRootIndex(index);
+ QCOMPARE(index, obj1.rootIndex());
+
+ QHeaderView *var1 = new QHeaderView(Qt::Horizontal);
+ obj1.setHorizontalHeader(var1);
+ QCOMPARE(var1, obj1.horizontalHeader());
+ obj1.setHorizontalHeader((QHeaderView *)0);
+ QCOMPARE(var1, obj1.horizontalHeader());
+ delete var1;
+
+ QHeaderView *var2 = new QHeaderView(Qt::Vertical);
+ obj1.setVerticalHeader(var2);
+ QCOMPARE(var2, obj1.verticalHeader());
+ obj1.setVerticalHeader((QHeaderView *)0);
+ QCOMPARE(var2, obj1.verticalHeader());
+ delete var2;
+
+ QCOMPARE(obj1.isCornerButtonEnabled(), true);
+ obj1.setCornerButtonEnabled(false);
+ QCOMPARE(obj1.isCornerButtonEnabled(), false);
+}
+
+class QtTestTableModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+signals:
+ void invalidIndexEncountered() const;
+
+public:
+ QtTestTableModel(int rows = 0, int columns = 0, QObject *parent = 0)
+ : QAbstractTableModel(parent),
+ row_count(rows),
+ column_count(columns),
+ can_fetch_more(false),
+ fetch_more_count(0),
+ disabled_rows(),
+ disabled_columns() {}
+
+ int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; }
+ int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; }
+ bool isEditable(const QModelIndex &) const { return true; }
+
+ Qt::ItemFlags flags(const QModelIndex &index) const
+ {
+ Qt::ItemFlags index_flags = QAbstractTableModel::flags(index);
+ if (disabled_rows.contains(index.row())
+ || disabled_columns.contains(index.column()))
+ index_flags &= ~Qt::ItemIsEnabled;
+ return index_flags;
+ }
+
+ void disableRow(int row)
+ {
+ disabled_rows.insert(row);
+ }
+
+ void enableRow(int row)
+ {
+ disabled_rows.remove(row);
+ }
+
+ void disableColumn(int column)
+ {
+ disabled_columns.insert(column);
+ }
+
+ void enableColumn(int column)
+ {
+ disabled_columns.remove(column);
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (!idx.isValid() || idx.row() >= row_count || idx.column() >= column_count) {
+ qWarning() << "Invalid modelIndex [%d,%d,%p]" << idx;
+ emit invalidIndexEncountered();
+ return QVariant();
+ }
+
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(0);
+
+ return QVariant();
+ }
+
+ bool insertRows(int start, int count, const QModelIndex &parent = QModelIndex())
+ {
+ if (start < 0 || start > row_count)
+ return false;
+
+ beginInsertRows(parent, start, start + count - 1);
+ row_count += count;
+ endInsertRows();
+ return true;
+ }
+
+ bool removeRows(int start, int count, const QModelIndex &parent = QModelIndex())
+ {
+ if (start < 0 || start >= row_count || row_count < count)
+ return false;
+
+ beginRemoveRows(parent, start, start + count - 1);
+ row_count -= count;
+ endRemoveRows();
+ return true;
+ }
+
+ void removeLastRow()
+ {
+ beginRemoveRows(QModelIndex(), row_count - 1, row_count - 1);
+ --row_count;
+ endRemoveRows();
+ }
+
+ void removeAllRows()
+ {
+ beginRemoveRows(QModelIndex(), 0, row_count - 1);
+ row_count = 0;
+ endRemoveRows();
+ }
+
+ bool insertColumns(int start, int count, const QModelIndex &parent = QModelIndex())
+ {
+ if (start < 0 || start > column_count)
+ return false;
+
+ beginInsertColumns(parent, start, start + count - 1);
+ column_count += count;
+ endInsertColumns();
+ return true;
+ }
+
+ bool removeColumns(int start, int count, const QModelIndex &parent = QModelIndex())
+ {
+ if (start < 0 || start >= column_count || column_count < count)
+ return false;
+
+ beginRemoveColumns(parent, start, start + count - 1);
+ column_count -= count;
+ endRemoveColumns();
+ return true;
+ }
+
+ void removeLastColumn()
+ {
+ beginRemoveColumns(QModelIndex(), column_count - 1, column_count - 1);
+ --column_count;
+ endRemoveColumns();
+ }
+
+ void removeAllColumns()
+ {
+ beginRemoveColumns(QModelIndex(), 0, column_count - 1);
+ column_count = 0;
+ endRemoveColumns();
+ }
+
+ bool canFetchMore(const QModelIndex &) const
+ {
+ return can_fetch_more;
+ }
+
+ void fetchMore(const QModelIndex &)
+ {
+ ++fetch_more_count;
+ }
+
+ void reset()
+ {
+ QAbstractTableModel::reset();
+ }
+
+ int row_count;
+ int column_count;
+ bool can_fetch_more;
+ int fetch_more_count;
+ QSet<int> disabled_rows;
+ QSet<int> disabled_columns;
+};
+
+class QtTestTableView : public QTableView
+{
+Q_OBJECT
+
+public:
+ QtTestTableView(QWidget *parent = 0) : QTableView(parent), checkSignalOrder(false), hasCurrentChanged(0), hasSelectionChanged(0) {}
+
+ void setModel(QAbstractItemModel *model)
+ {
+ QTableView::setModel(model);
+ connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(currentChanged(QModelIndex,QModelIndex)));
+ connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ this, SLOT(itemSelectionChanged(QItemSelection,QItemSelection)));
+ }
+
+ enum CursorAction {
+ MoveUp = QAbstractItemView::MoveUp,
+ MoveDown = QAbstractItemView::MoveDown,
+ MoveLeft = QAbstractItemView::MoveLeft,
+ MoveRight = QAbstractItemView::MoveRight,
+ MoveHome = QAbstractItemView::MoveHome,
+ MoveEnd = QAbstractItemView::MoveEnd,
+ MovePageUp = QAbstractItemView::MovePageUp,
+ MovePageDown = QAbstractItemView::MovePageDown,
+ MoveNext = QAbstractItemView::MoveNext,
+ MovePrevious = QAbstractItemView::MovePrevious
+ };
+
+ QModelIndex moveCursor(QtTestTableView::CursorAction cursorAction,
+ Qt::KeyboardModifiers modifiers)
+ {
+ return QTableView::moveCursor((QAbstractItemView::CursorAction)cursorAction, modifiers);
+ }
+
+ int columnWidthHint(int column) const
+ {
+ return sizeHintForColumn(column);
+ }
+
+ int rowHeightHint(int row) const
+ {
+ return sizeHintForRow(row);
+ }
+
+ bool isIndexHidden(const QModelIndex &index) const
+ {
+ return QTableView::isIndexHidden(index);
+ }
+
+ void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
+ {
+ QTableView::setSelection(rect, command);
+ }
+
+ QModelIndexList selectedIndexes() const
+ {
+ return QTableView::selectedIndexes();
+ }
+
+ int sizeHintForRow(int row) const
+ {
+ return QTableView::sizeHintForRow(row);
+ }
+
+ bool checkSignalOrder;
+public slots:
+ void currentChanged(QModelIndex , QModelIndex ) {
+ hasCurrentChanged++;
+ if (checkSignalOrder)
+ QVERIFY(hasCurrentChanged > hasSelectionChanged);
+ }
+
+ void itemSelectionChanged(QItemSelection , QItemSelection ) {
+ hasSelectionChanged++;
+ if (checkSignalOrder)
+ QVERIFY(hasCurrentChanged >= hasSelectionChanged);
+ }
+private:
+ int hasCurrentChanged;
+ int hasSelectionChanged;
+
+};
+
+class QtTestItemDelegate : public QItemDelegate
+{
+public:
+ QSize sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const
+ {
+ return hint;
+ }
+
+ QSize hint;
+};
+
+tst_QTableView::tst_QTableView()
+{
+}
+
+tst_QTableView::~tst_QTableView()
+{
+}
+
+void tst_QTableView::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QTableView::cleanupTestCase()
+{
+}
+
+void tst_QTableView::init()
+{
+}
+
+void tst_QTableView::cleanup()
+{
+}
+
+void tst_QTableView::noDelegate()
+{
+ QtTestTableModel model(3, 3);
+ QTableView view;
+ view.setModel(&model);
+ view.setItemDelegate(0);
+ view.show();
+}
+
+void tst_QTableView::noModel()
+{
+ QTableView view;
+ view.show();
+}
+
+void tst_QTableView::emptyModel()
+{
+ QtTestTableModel model;
+ QTableView view;
+ QSignalSpy spy(&model, SIGNAL(invalidIndexEncountered()));
+ view.setModel(&model);
+ view.show();
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QTableView::removeRows_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+
+ QTest::newRow("2x2") << 2 << 2;
+ QTest::newRow("10x10") << 10 << 10;
+}
+
+void tst_QTableView::removeRows()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QSignalSpy spy(&model, SIGNAL(invalidIndexEncountered()));
+
+ QTableView view;
+ view.setModel(&model);
+ view.show();
+
+ model.removeLastRow();
+ QCOMPARE(spy.count(), 0);
+
+ model.removeAllRows();
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QTableView::removeColumns_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+
+ QTest::newRow("2x2") << 2 << 2;
+ QTest::newRow("10x10") << 10 << 10;
+}
+
+void tst_QTableView::removeColumns()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QSignalSpy spy(&model, SIGNAL(invalidIndexEncountered()));
+
+ QTableView view;
+ view.setModel(&model);
+ view.show();
+
+ model.removeLastColumn();
+ QCOMPARE(spy.count(), 0);
+
+ model.removeAllColumns();
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QTableView::keyboardNavigation_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<bool>("tabKeyNavigation");
+ QTest::addColumn<IntList>("keyPresses");
+
+ QTest::newRow("16x16 model") << 16 << 16 << true
+ << (IntList()
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Right
+ << Qt::Key_Right
+ << Qt::Key_Up
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Up
+ << Qt::Key_Down
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Up
+ << Qt::Key_Down
+ << Qt::Key_Down
+ << Qt::Key_Tab
+ << Qt::Key_Backtab);
+
+
+ QTest::newRow("no tab") << 8 << 8 << false
+ << (IntList()
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Right
+ << Qt::Key_Right
+ << Qt::Key_Up
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Up
+ << Qt::Key_Down
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Up
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Up
+ << Qt::Key_Down
+ << Qt::Key_Down
+ << Qt::Key_Tab
+ << Qt::Key_Backtab);
+}
+
+void tst_QTableView::keyboardNavigation()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(bool, tabKeyNavigation);
+ QFETCH(IntList, keyPresses);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QTableView view;
+ view.setModel(&model);
+
+ view.setTabKeyNavigation(tabKeyNavigation);
+ QModelIndex index = model.index(rowCount - 1, columnCount - 1);
+ view.setCurrentIndex(index);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ qApp->setActiveWindow(&view);
+
+ int row = rowCount - 1;
+ int column = columnCount - 1;
+ for (int i = 0; i < keyPresses.count(); ++i) {
+
+ Qt::Key key = (Qt::Key)keyPresses.at(i);
+
+ switch (key) {
+ case Qt::Key_Up:
+ row = qMax(0, row - 1);
+ break;
+ case Qt::Key_Down:
+ row = qMin(rowCount - 1, row + 1);
+ break;
+ case Qt::Key_Backtab:
+ if (!tabKeyNavigation)
+ break;
+ case Qt::Key_Left:
+ column = qMax(0, column - 1);
+ break;
+ case Qt::Key_Tab:
+ if (!tabKeyNavigation)
+ break;
+ case Qt::Key_Right:
+ column = qMin(columnCount - 1, column + 1);
+ break;
+ default:
+ break;
+ }
+
+ QTest::keyClick(&view, key);
+ QApplication::processEvents();
+
+ QModelIndex index = model.index(row, column);
+ QCOMPARE(view.currentIndex(), index);
+ }
+}
+
+void tst_QTableView::headerSections_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+
+ QTest::newRow("") << 10 << 10 << 5 << 5 << 30 << 30;
+}
+
+void tst_QTableView::headerSections()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+
+ QtTestTableModel model(rowCount, columnCount);
+
+ QTableView view;
+ QHeaderView *hheader = view.horizontalHeader();
+ QHeaderView *vheader = view.verticalHeader();
+
+ view.setModel(&model);
+ view.show();
+
+ hheader->doItemsLayout();
+ vheader->doItemsLayout();
+
+ QCOMPARE(hheader->count(), model.columnCount());
+ QCOMPARE(vheader->count(), model.rowCount());
+
+ view.setRowHeight(row, rowHeight);
+ QCOMPARE(view.rowHeight(row), rowHeight);
+ view.hideRow(row);
+ QCOMPARE(view.rowHeight(row), 0);
+ view.showRow(row);
+ QCOMPARE(view.rowHeight(row), rowHeight);
+
+ view.setColumnWidth(column, columnWidth);
+ QCOMPARE(view.columnWidth(column), columnWidth);
+ view.hideColumn(column);
+ QCOMPARE(view.columnWidth(column), 0);
+ view.showColumn(column);
+ QCOMPARE(view.columnWidth(column), columnWidth);
+}
+
+typedef QPair<int,int> IntPair;
+Q_DECLARE_METATYPE(IntPair)
+
+void tst_QTableView::moveCursor_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("hideRow");
+ QTest::addColumn<int>("hideColumn");
+
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("startColumn");
+
+ QTest::addColumn<int>("cursorMoveAction");
+ QTest::addColumn<int>("modifier");
+
+ QTest::addColumn<int>("expectedRow");
+ QTest::addColumn<int>("expectedColumn");
+ QTest::addColumn<IntPair>("moveRow");
+ QTest::addColumn<IntPair>("moveColumn");
+
+ // MoveRight
+ QTest::newRow("MoveRight (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
+ << 0 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveRight (3,0)")
+ << 4 << 4 << -1 << -1
+ << 3 << 0
+ << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
+ << 3 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveRight (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0); // ###
+
+ QTest::newRow("MoveRight, hidden column 1 (0,0)")
+ << 4 << 4 << -1 << 1
+ << 0 << 0
+ << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
+ << 0 << 2 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveRight, hidden column 3 (0,2)")
+ << 4 << 4 << -1 << 3
+ << 0 << 2
+ << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
+ << 0 << 2 << IntPair(0,0) << IntPair(0,0); // ###
+
+ // MoveNext should in addition wrap
+ QTest::newRow("MoveNext (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 0 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext (0,2)")
+ << 4 << 4 << -1 << -1
+ << 0 << 2
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 0 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, wrap (0,3)")
+ << 4 << 4 << -1 << -1
+ << 0 << 3
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 1 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, wrap (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, hidden column 1 (0,0)")
+ << 4 << 4 << -1 << 1
+ << 0 << 0
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 0 << 2 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, wrap, hidden column 3 (0,2)")
+ << 4 << 4 << -1 << 3
+ << 0 << 2
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 1 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, wrap, hidden column 3 (3,2)")
+ << 4 << 4 << -1 << 3
+ << 3 << 2
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, wrapy, wrapx, hidden column 3, hidden row 3 (2,2)")
+ << 4 << 4 << 3 << 3
+ << 2 << 2
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveNext, wrap, hidden column 2, moved column from 3 to 0. (0,2)")
+ << 4 << 4 << -1 << 2
+ << 0 << 2
+ << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
+ << 1 << 3 << IntPair(0,0) << IntPair(3,0);
+
+ // MoveLeft
+ QTest::newRow("MoveLeft (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveLeft (0,3)")
+ << 4 << 4 << -1 << -1
+ << 0 << 3
+ << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
+ << 0 << 2 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveLeft (1,0)")
+ << 4 << 4 << -1 << -1
+ << 1 << 0
+ << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
+ << 1 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveLeft, hidden column 0 (0,2)")
+ << 4 << 4 << -1 << 1
+ << 0 << 2
+ << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveLeft, hidden column 0 (0,1)")
+ << 4 << 4 << -1 << 0
+ << 0 << 1
+ << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
+ << 0 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ // MovePrevious should in addition wrap
+ QTest::newRow("MovePrevious (0,3)")
+ << 4 << 4 << -1 << -1
+ << 0 << 3
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 0 << 2 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious (0,1)")
+ << 4 << 4 << -1 << -1
+ << 0 << 1
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, wrap (1,0)")
+ << 4 << 4 << -1 << -1
+ << 1 << 0
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 0 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, wrap, (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, hidden column 1 (0,2)")
+ << 4 << 4 << -1 << 1
+ << 0 << 2
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, wrap, hidden column 3 (0,2)")
+ << 4 << 4 << -1 << 3
+ << 0 << 2
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 0 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, wrapy, hidden column 0 (0,1)")
+ << 4 << 4 << -1 << 0
+ << 0 << 1
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, wrap, hidden column 0, hidden row 0 (1,1)")
+ << 4 << 4 << 0 << 0
+ << 1 << 1
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePrevious, wrap, hidden column 1, moved column from 0 to 3. (1,2)")
+ << 4 << 4 << -1 << 1
+ << 1 << 2
+ << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,3);
+
+ // MoveDown
+ QTest::newRow("MoveDown (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
+ << 1 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveDown (3,0)")
+ << 4 << 4 << -1 << -1
+ << 3 << 0
+ << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
+ << 3 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveDown (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveDown, hidden row 1 (0,0)")
+ << 4 << 4 << 1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
+ << 2 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveDown, hidden row 3 (2,0)")
+ << 4 << 4 << 3 << -1
+ << 2 << 0
+ << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
+ << 2 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveDown, hidden row 0 hidden column 0 (0,0)")
+ << 4 << 4 << 0 << 0
+ << 0 << 0
+ << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
+ << 1 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ // MoveUp
+ QTest::newRow("MoveUp (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveUp (3, 0)")
+ << 4 << 4 << -1 << -1
+ << 3 << 0
+ << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
+ << 2 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveUp (0,1)")
+ << 4 << 4 << -1 << -1
+ << 0 << 1
+ << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
+ << 0 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveUp, hidden row 1 (2,0)")
+ << 4 << 4 << 1 << -1
+ << 2 << 0
+ << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveUp, hidden row (1,0)")
+ << 4 << 4 << 0 << -1
+ << 1 << 0
+ << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
+ << 1 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ // MoveHome
+ QTest::newRow("MoveHome (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveHome) << int(Qt::NoModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveHome (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveHome) << int(Qt::NoModifier)
+ << 3 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveHome, hidden column 0 (3,3)")
+ << 4 << 4 << -1 << 0
+ << 3 << 3
+ << int(QtTestTableView::MoveHome) << int(Qt::NoModifier)
+ << 3 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ // Use Ctrl modifier
+ QTest::newRow("MoveHome + Ctrl (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveHome) << int(Qt::ControlModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveHome + Ctrl (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveHome) << int(Qt::ControlModifier)
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveHome + Ctrl, hidden column 0, hidden row 0 (3,3)")
+ << 4 << 4 << 0 << 0
+ << 3 << 3
+ << int(QtTestTableView::MoveHome) << int(Qt::ControlModifier)
+ << 1 << 1 << IntPair(0,0) << IntPair(0,0);
+
+ // MoveEnd
+ QTest::newRow("MoveEnd (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveEnd) << int(Qt::NoModifier)
+ << 0 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveEnd (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveEnd) << int(Qt::NoModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveEnd, hidden column (0,0)")
+ << 4 << 4 << -1 << 3
+ << 0 << 0
+ << int(QtTestTableView::MoveEnd) << int(Qt::NoModifier)
+ << 0<< 2 << IntPair(0,0) << IntPair(0,0);
+
+ // Use Ctrl modifier
+ QTest::newRow("MoveEnd + Ctrl (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveEnd + Ctrl (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveEnd + Ctrl, hidden column 3 (0,0)")
+ << 4 << 4 << -1 << 3
+ << 0 << 0
+ << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
+ << 3 << 2 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MoveEnd + Ctrl, hidden column 3, hidden row 3 (0,0)")
+ << 4 << 4 << 3 << 3
+ << 0 << 0
+ << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
+ << 2 << 2 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePageUp (0,0)")
+ << 4 << 4 << -1 << -1
+ << 0 << 0
+ << int(QtTestTableView::MovePageUp) << 0
+ << 0 << 0 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePageUp (3,3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MovePageUp) << 0
+ << 0 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePageDown (3, 3)")
+ << 4 << 4 << -1 << -1
+ << 3 << 3
+ << int(QtTestTableView::MovePageDown) << 0
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+
+ QTest::newRow("MovePageDown (0, 3)")
+ << 4 << 4 << -1 << -1
+ << 0 << 3
+ << int(QtTestTableView::MovePageDown) << 0
+ << 3 << 3 << IntPair(0,0) << IntPair(0,0);
+}
+
+void tst_QTableView::moveCursor()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, hideRow);
+ QFETCH(int, hideColumn);
+ QFETCH(int, startRow);
+ QFETCH(int, startColumn);
+ QFETCH(int, cursorMoveAction);
+ QFETCH(int, modifier);
+ QFETCH(int, expectedRow);
+ QFETCH(int, expectedColumn);
+ QFETCH(IntPair, moveRow);
+ QFETCH(IntPair, moveColumn);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QtTestTableView view;
+
+ view.setModel(&model);
+ view.hideRow(hideRow);
+ view.hideColumn(hideColumn);
+ if (moveColumn.first != moveColumn.second)
+ view.horizontalHeader()->moveSection(moveColumn.first, moveColumn.second);
+ if (moveRow.first != moveRow.second)
+ view.verticalHeader()->moveSection(moveRow.first, moveRow.second);
+
+ view.show();
+
+ QModelIndex index = model.index(startRow, startColumn);
+ view.setCurrentIndex(index);
+
+ QModelIndex newIndex = view.moveCursor((QtTestTableView::CursorAction)cursorMoveAction,
+ (Qt::KeyboardModifiers)modifier);
+ // expected fails, task 119433
+ if(newIndex.row() == -1)
+ return;
+ QCOMPARE(newIndex.row(), expectedRow);
+ QCOMPARE(newIndex.column(), expectedColumn);
+}
+
+void tst_QTableView::moveCursorStrikesBack_data()
+{
+ QTest::addColumn<int>("hideRow");
+ QTest::addColumn<int>("hideColumn");
+ QTest::addColumn<IntList>("disableRows");
+ QTest::addColumn<IntList>("disableColumns");
+ QTest::addColumn<QRect>("span");
+
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("startColumn");
+ QTest::addColumn<IntList>("cursorMoveActions");
+ QTest::addColumn<int>("expectedRow");
+ QTest::addColumn<int>("expectedColumn");
+
+ QTest::newRow("Last column disabled. Task QTBUG-3878") << -1 << -1
+ << IntList()
+ << (IntList() << 6)
+ << QRect()
+ << 0 << 5 << (IntList() << int(QtTestTableView::MoveNext))
+ << 1 << 0;
+
+ QTest::newRow("Last column disabled. Task QTBUG-3878") << -1 << -1
+ << IntList()
+ << (IntList() << 6)
+ << QRect()
+ << 1 << 0 << (IntList() << int(QtTestTableView::MovePrevious))
+ << 0 << 5;
+
+ QTest::newRow("Span, anchor column hidden") << -1 << 1
+ << IntList()
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 2 << 0 << (IntList() << int(QtTestTableView::MoveNext))
+ << 2 << 2;
+
+ QTest::newRow("Span, anchor column disabled") << -1 << -1
+ << IntList()
+ << (IntList() << 1)
+ << QRect(1, 2, 2, 3)
+ << 2 << 0 << (IntList() << int(QtTestTableView::MoveNext))
+ << 2 << 2;
+
+ QTest::newRow("Span, anchor row hidden") << 2 << -1
+ << IntList()
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 1 << 2 << (IntList() << int(QtTestTableView::MoveDown))
+ << 3 << 2;
+
+ QTest::newRow("Span, anchor row disabled") << -1 << -1
+ << (IntList() << 2)
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 1 << 2 << (IntList() << int(QtTestTableView::MoveDown))
+ << 3 << 2;
+
+ QTest::newRow("Move through span right") << -1 << -1
+ << IntList()
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 3 << 0 << (IntList() << int(QtTestTableView::MoveRight) << int(QtTestTableView::MoveRight))
+ << 3 << 3;
+
+ QTest::newRow("Move through span left") << -1 << -1
+ << IntList()
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 3 << 3 << (IntList() << int(QtTestTableView::MoveLeft) << int(QtTestTableView::MoveLeft))
+ << 3 << 0;
+
+ QTest::newRow("Move through span down") << -1 << -1
+ << IntList()
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 1 << 2 << (IntList() << int(QtTestTableView::MoveDown) << int(QtTestTableView::MoveDown))
+ << 5 << 2;
+
+ QTest::newRow("Move through span up") << -1 << -1
+ << IntList()
+ << IntList()
+ << QRect(1, 2, 2, 3)
+ << 5 << 2 << (IntList() << int(QtTestTableView::MoveUp) << int(QtTestTableView::MoveUp))
+ << 1 << 2;
+
+ IntList fullList;
+ for (int i = 0; i < 7; ++i)
+ fullList << i;
+
+ QTest::newRow("All disabled, wrap forward. Timeout => FAIL") << -1 << -1
+ << fullList
+ << fullList
+ << QRect()
+ << 1 << 0 << (IntList() << int(QtTestTableView::MoveNext))
+ << 1 << 0;
+
+ QTest::newRow("All disabled, wrap backwards. Timeout => FAIL") << -1 << -1
+ << fullList
+ << fullList
+ << QRect()
+ << 1 << 0 << (IntList() << int(QtTestTableView::MovePrevious))
+ << 1 << 0;
+}
+
+void tst_QTableView::moveCursorStrikesBack()
+{
+ QFETCH(int, hideRow);
+ QFETCH(int, hideColumn);
+ QFETCH(IntList, disableRows);
+ QFETCH(IntList, disableColumns);
+ QFETCH(QRect, span);
+
+ QFETCH(int, startRow);
+ QFETCH(int, startColumn);
+ QFETCH(IntList, cursorMoveActions);
+ QFETCH(int, expectedRow);
+ QFETCH(int, expectedColumn);
+
+ QtTestTableModel model(7, 7);
+ QtTestTableView view;
+ view.setModel(&model);
+ view.hideRow(hideRow);
+ view.hideColumn(hideColumn);
+
+ if (span.height() && span.width())
+ view.setSpan(span.top(), span.left(), span.height(), span.width());
+ view.show();
+
+ QModelIndex index = model.index(startRow, startColumn);
+ view.setCurrentIndex(index);
+
+ foreach (int row, disableRows)
+ model.disableRow(row);
+ foreach (int column, disableColumns)
+ model.disableColumn(column);
+
+ int newRow = -1;
+ int newColumn = -1;
+ foreach (int cursorMoveAction, cursorMoveActions) {
+ QModelIndex newIndex = view.moveCursor((QtTestTableView::CursorAction)cursorMoveAction, 0);
+ view.setCurrentIndex(newIndex);
+ newRow = newIndex.row();
+ newColumn = newIndex.column();
+ }
+
+ // expected fails, task 119433
+ if(newRow == -1)
+ return;
+ QCOMPARE(newRow, expectedRow);
+ QCOMPARE(newColumn, expectedColumn);
+}
+
+void tst_QTableView::hideRows_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("showRow"); // hide, then show
+ QTest::addColumn<int>("hideRow"); // hide only
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+
+ QTest::newRow("show row 0, hide row 3, no span")
+ << 10 << 10
+ << 0
+ << 3
+ << -1 << -1
+ << 1 << 1;
+
+ QTest::newRow("show row 0, hide row 3, span")
+ << 10 << 10
+ << 0
+ << 3
+ << 0 << 0
+ << 3 << 2;
+}
+
+void tst_QTableView::hideRows()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, showRow);
+ QFETCH(int, hideRow);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QTableView view;
+
+ view.setModel(&model);
+ view.setSpan(row, column, rowSpan, columnSpan);
+
+ view.hideRow(showRow);
+ QVERIFY(view.isRowHidden(showRow));
+
+ view.hideRow(hideRow);
+ QVERIFY(view.isRowHidden(hideRow));
+
+ view.showRow(showRow);
+ QVERIFY(!view.isRowHidden(showRow));
+ QVERIFY(view.isRowHidden(hideRow));
+}
+
+void tst_QTableView::hideColumns_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("showColumn"); // hide, then show
+ QTest::addColumn<int>("hideColumn"); // hide only
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+
+ QTest::newRow("show col 0, hide col 3, no span")
+ << 10 << 10
+ << 0
+ << 3
+ << -1 << -1
+ << 1 << 1;
+
+ QTest::newRow("show col 0, hide col 3, span")
+ << 10 << 10
+ << 0
+ << 3
+ << 0 << 0
+ << 3 << 2;
+}
+
+void tst_QTableView::hideColumns()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, showColumn);
+ QFETCH(int, hideColumn);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+
+ QtTestTableModel model(rowCount, columnCount);
+
+ QTableView view;
+ view.setModel(&model);
+ view.setSpan(row, column, rowSpan, columnSpan);
+
+ view.hideColumn(showColumn);
+ QVERIFY(view.isColumnHidden(showColumn));
+
+ view.hideColumn(hideColumn);
+ QVERIFY(view.isColumnHidden(hideColumn));
+
+ view.showColumn(showColumn);
+ QVERIFY(!view.isColumnHidden(showColumn));
+ QVERIFY(view.isColumnHidden(hideColumn));
+}
+
+void tst_QTableView::selection_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+ QTest::addColumn<int>("hideRow");
+ QTest::addColumn<int>("hideColumn");
+ QTest::addColumn<int>("moveRowFrom");
+ QTest::addColumn<int>("moveRowTo");
+ QTest::addColumn<int>("moveColumnFrom");
+ QTest::addColumn<int>("moveColumnTo");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+ QTest::addColumn<int>("command");
+ QTest::addColumn<int>("selectedCount"); // ### make this more detailed
+
+ QTest::newRow("no span, no hidden, no moved, 3x3 select")
+ << 10 << 10 // dim
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << -1 << -1 // hide
+ << -1 << -1 // move row
+ << -1 << -1 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 9; // selected count
+
+ QTest::newRow("row span, no hidden, no moved, 3x3 select")
+ << 10 << 10 // dim
+ << 1 << 1 // pos
+ << 2 << 1 // span
+ << -1 << -1 // hide
+ << -1 << -1 // move row
+ << -1 << -1 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 8; // selected count
+
+ QTest::newRow("col span, no hidden, no moved, 3x3 select")
+ << 10 << 10 // dim
+ << 1 << 1 // pos
+ << 1 << 2 // span
+ << -1 << -1 // hide
+ << -1 << -1 // move row
+ << -1 << -1 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 8; // selected count
+
+ QTest::newRow("no span, row hidden, no moved, 3x3 select")
+ << 10 << 10 // dim
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 1 << -1 // hide
+ << -1 << -1 // move row
+ << -1 << -1 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 9; // selected count
+
+ QTest::newRow("no span, col hidden, no moved, 3x3 select")
+ << 10 << 10 // dim
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << -1 << 1 // hide
+ << -1 << -1 // move row
+ << -1 << -1 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 9; // selected count
+
+ QTest::newRow("no span, no hidden, row moved, 3x3 select")
+ << 10 << 10 // dim
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << -1 << -1 // hide
+ << 1 << 3 // move row
+ << -1 << -1 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 9; // selected count
+
+ QTest::newRow("no span, no hidden, col moved, 3x3 select")
+ << 10 << 10 // dim
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << -1 << -1 // hide
+ << -1 << -1 // move row
+ << 1 << 3 // move col
+ << 40 << 40 // cell size
+ << 20 << 20 << 80 << 80 // rect
+ << int(QItemSelectionModel::Select) // command
+ << 9; // selected count
+}
+
+void tst_QTableView::selection()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+ QFETCH(int, hideRow);
+ QFETCH(int, hideColumn);
+ QFETCH(int, moveRowFrom);
+ QFETCH(int, moveRowTo);
+ QFETCH(int, moveColumnFrom);
+ QFETCH(int, moveColumnTo);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+ QFETCH(int, x);
+ QFETCH(int, y);
+ QFETCH(int, width);
+ QFETCH(int, height);
+ QFETCH(int, command);
+ QFETCH(int, selectedCount);
+
+ QtTestTableModel model(rowCount, columnCount);
+
+ QtTestTableView view;
+ view.show();
+ view.setModel(&model);
+
+ view.setSpan(row, column, rowSpan, columnSpan);
+
+ view.hideRow(hideRow);
+ view.hideColumn(hideColumn);
+
+ view.verticalHeader()->moveSection(moveRowFrom, moveRowTo);
+ view.horizontalHeader()->moveSection(moveColumnFrom, moveColumnTo);
+
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHeight(r, rowHeight);
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnWidth(c, columnWidth);
+
+ view.setSelection(QRect(x, y, width, height),
+ QItemSelectionModel::SelectionFlags(command));
+
+ QCOMPARE(view.selectedIndexes().count(), selectedCount);
+}
+
+void tst_QTableView::selectRow_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("behavior");
+ QTest::addColumn<int>("selectedItems");
+
+ QTest::newRow("SingleSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::SingleSelection
+ << (int)QAbstractItemView::SelectItems
+ << 0;
+
+ QTest::newRow("SingleSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::SingleSelection
+ << (int)QAbstractItemView::SelectRows
+ << 10;
+
+ QTest::newRow("SingleSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::SingleSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 0;
+
+ QTest::newRow("MultiSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::MultiSelection
+ << (int)QAbstractItemView::SelectItems
+ << 10;
+
+ QTest::newRow("MultiSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::MultiSelection
+ << (int)QAbstractItemView::SelectRows
+ << 10;
+
+ QTest::newRow("MultiSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::MultiSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 0;
+
+ QTest::newRow("ExtendedSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ExtendedSelection
+ << (int)QAbstractItemView::SelectItems
+ << 10;
+
+ QTest::newRow("ExtendedSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ExtendedSelection
+ << (int)QAbstractItemView::SelectRows
+ << 10;
+
+ QTest::newRow("ExtendedSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ExtendedSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 0;
+
+ QTest::newRow("ContiguousSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ContiguousSelection
+ << (int)QAbstractItemView::SelectItems
+ << 10;
+
+ QTest::newRow("ContiguousSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ContiguousSelection
+ << (int)QAbstractItemView::SelectRows
+ << 10;
+
+ QTest::newRow("ContiguousSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ContiguousSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 0;
+}
+
+void tst_QTableView::selectRow()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, mode);
+ QFETCH(int, behavior);
+ QFETCH(int, selectedItems);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QTableView view;
+
+ view.setModel(&model);
+ view.setSelectionMode((QAbstractItemView::SelectionMode)mode);
+ view.setSelectionBehavior((QAbstractItemView::SelectionBehavior)behavior);
+
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0);
+
+ view.selectRow(row);
+
+ //test we have 10 items selected
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedItems);
+ //test that all 10 items are in the same row
+ for (int i = 0; selectedItems > 0 && i < rowCount; ++i)
+ QCOMPARE(view.selectionModel()->selectedIndexes().at(i).row(), row);
+}
+
+void tst_QTableView::selectColumn_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("behavior");
+ QTest::addColumn<int>("selectedItems");
+
+ QTest::newRow("SingleSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::SingleSelection
+ << (int)QAbstractItemView::SelectItems
+ << 0;
+
+ QTest::newRow("SingleSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::SingleSelection
+ << (int)QAbstractItemView::SelectRows
+ << 0;
+
+ QTest::newRow("SingleSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::SingleSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 10;
+
+ QTest::newRow("MultiSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::MultiSelection
+ << (int)QAbstractItemView::SelectItems
+ << 10;
+
+ QTest::newRow("MultiSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::MultiSelection
+ << (int)QAbstractItemView::SelectRows
+ << 0;
+
+ QTest::newRow("MultiSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::MultiSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 10;
+
+ QTest::newRow("ExtendedSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ExtendedSelection
+ << (int)QAbstractItemView::SelectItems
+ << 10;
+
+ QTest::newRow("ExtendedSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ExtendedSelection
+ << (int)QAbstractItemView::SelectRows
+ << 0;
+
+ QTest::newRow("ExtendedSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ExtendedSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 10;
+
+ QTest::newRow("ContiguousSelection and SelectItems")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ContiguousSelection
+ << (int)QAbstractItemView::SelectItems
+ << 10;
+
+ QTest::newRow("ContiguousSelection and SelectRows")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ContiguousSelection
+ << (int)QAbstractItemView::SelectRows
+ << 0;
+
+ QTest::newRow("ContiguousSelection and SelectColumns")
+ << 10 << 10
+ << 0
+ << (int)QAbstractItemView::ContiguousSelection
+ << (int)QAbstractItemView::SelectColumns
+ << 10;
+}
+
+void tst_QTableView::selectColumn()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, column);
+ QFETCH(int, mode);
+ QFETCH(int, behavior);
+ QFETCH(int, selectedItems);
+
+ QtTestTableModel model(rowCount, columnCount);
+
+ QTableView view;
+ view.setModel(&model);
+ view.setSelectionMode((QAbstractItemView::SelectionMode)mode);
+ view.setSelectionBehavior((QAbstractItemView::SelectionBehavior)behavior);
+
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0);
+
+ view.selectColumn(column);
+
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedItems);
+ for (int i = 0; selectedItems > 0 && i < columnCount; ++i)
+ QCOMPARE(view.selectionModel()->selectedIndexes().at(i).column(), column);
+}
+
+Q_DECLARE_METATYPE(QRect)
+void tst_QTableView::visualRect_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("hideRow");
+ QTest::addColumn<int>("hideColumn");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+ QTest::addColumn<QRect>("expectedRect");
+
+ QTest::newRow("(0,0)")
+ << 10 << 10
+ << -1 << -1
+ << 0 << 0
+ << 20 << 30
+ << QRect(0, 0, 29, 19);
+
+ QTest::newRow("(0,0) hidden row")
+ << 10 << 10
+ << 0 << -1
+ << 0 << 0
+ << 20 << 30
+ << QRect();
+
+ QTest::newRow("(0,0) hidden column")
+ << 10 << 10
+ << -1 << 0
+ << 0 << 0
+ << 20 << 30
+ << QRect();
+
+ QTest::newRow("(0,0) hidden row and column")
+ << 10 << 10
+ << 0 << 0
+ << 0 << 0
+ << 20 << 30
+ << QRect();
+
+ QTest::newRow("(0,0) out of bounds")
+ << 10 << 10
+ << -1 << -1
+ << 20 << 20
+ << 20 << 30
+ << QRect();
+
+ QTest::newRow("(5,5), hidden row")
+ << 10 << 10
+ << 5 << -1
+ << 5 << 5
+ << 20 << 30
+ << QRect();
+
+ QTest::newRow("(9,9)")
+ << 10 << 10
+ << -1 << -1
+ << 9 << 9
+ << 20 << 30
+ << QRect(30*9, 20*9, 29, 19);
+}
+
+void tst_QTableView::visualRect()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, hideRow);
+ QFETCH(int, hideColumn);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+ QFETCH(QRect, expectedRect);
+
+ QtTestTableModel model(rowCount, columnCount);
+
+ QTableView view;
+ view.setModel(&model);
+ // Make sure that it has 1 pixel between each cell.
+ view.setGridStyle(Qt::SolidLine);
+ for (int i = 0; i < view.verticalHeader()->count(); ++i)
+ view.verticalHeader()->resizeSection(i, rowHeight);
+ for (int i = 0; i < view.horizontalHeader()->count(); ++i)
+ view.horizontalHeader()->resizeSection(i, columnWidth);
+
+ view.hideRow(hideRow);
+ view.hideColumn(hideColumn);
+
+ QRect rect = view.visualRect(model.index(row, column));
+ QCOMPARE(rect, expectedRect);
+}
+
+void tst_QTableView::fetchMore()
+{
+ QtTestTableModel model(64, 64);
+
+ model.can_fetch_more = true;
+
+ QTableView view;
+ view.setModel(&model);
+ view.show();
+
+ QCOMPARE(model.fetch_more_count, 0);
+ view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
+ QVERIFY(model.fetch_more_count > 0);
+
+ model.fetch_more_count = 0; //reset
+ view.scrollToTop();
+ QCOMPARE(model.fetch_more_count, 0);
+
+ view.scrollToBottom();
+ QVERIFY(model.fetch_more_count > 0);
+
+ model.fetch_more_count = 0; //reset
+ view.scrollToTop();
+ view.setCurrentIndex(model.index(0, 0));
+ QCOMPARE(model.fetch_more_count, 0);
+
+ for (int i = 0; i < 64; ++i)
+ QTest::keyClick(&view, Qt::Key_Down);
+ QCOMPARE(view.currentIndex(), model.index(63, 0));
+ QVERIFY(model.fetch_more_count > 0);
+}
+
+void tst_QTableView::setHeaders()
+{
+ QTableView view;
+
+ // Make sure we don't delete ourselves
+ view.setVerticalHeader(view.verticalHeader());
+ view.verticalHeader()->count();
+ view.setHorizontalHeader(view.horizontalHeader());
+ view.horizontalHeader()->count();
+
+ // Try passing around a header without it being deleted
+ QTableView view2;
+ view2.setVerticalHeader(view.verticalHeader());
+ view2.setHorizontalHeader(view.horizontalHeader());
+ view.setHorizontalHeader(new QHeaderView(Qt::Horizontal));
+ view.setVerticalHeader(new QHeaderView(Qt::Vertical));
+ view2.verticalHeader()->count();
+ view2.horizontalHeader()->count();
+
+}
+
+void tst_QTableView::resizeRowsToContents_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<bool>("showGrid");
+ QTest::addColumn<int>("cellWidth");
+ QTest::addColumn<int>("cellHeight");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+
+ QTest::newRow("10x10 grid shown 40x40")
+ << 10 << 10 << false << 40 << 40 << 40 << 40;
+
+ QTest::newRow("10x10 grid not shown 40x40")
+ << 10 << 10 << true << 40 << 40 << 41 << 41;
+}
+
+void tst_QTableView::resizeRowsToContents()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(bool, showGrid);
+ QFETCH(int, cellWidth);
+ QFETCH(int, cellHeight);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+ Q_UNUSED(columnWidth);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QtTestTableView view;
+ QtTestItemDelegate delegate;
+
+ view.setModel(&model);
+ view.setItemDelegate(&delegate);
+ view.setShowGrid(showGrid); // the grid will add to the row height
+
+ delegate.hint = QSize(cellWidth, cellHeight);
+
+ QSignalSpy resizedSpy(view.verticalHeader(), SIGNAL(sectionResized(int, int, int)));
+ view.resizeRowsToContents();
+
+ QCOMPARE(resizedSpy.count(), model.rowCount());
+ for (int r = 0; r < model.rowCount(); ++r) {
+ QCOMPARE(view.rowHeight(r), rowHeight);
+ }
+}
+
+void tst_QTableView::resizeColumnsToContents_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<bool>("showGrid");
+ QTest::addColumn<int>("cellWidth");
+ QTest::addColumn<int>("cellHeight");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+
+ QTest::newRow("10x10 grid shown 40x40")
+ << 10 << 10 << false << 40 << 40 << 40 << 40;
+
+ QTest::newRow("10x10 grid not shown 40x40")
+ << 10 << 10 << true << 40 << 40 << 41 << 41;
+}
+
+void tst_QTableView::resizeColumnsToContents()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(bool, showGrid);
+ QFETCH(int, cellWidth);
+ QFETCH(int, cellHeight);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+ Q_UNUSED(rowHeight);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QtTestTableView view;
+ QtTestItemDelegate delegate;
+
+ view.setModel(&model);
+ view.setItemDelegate(&delegate);
+ view.setShowGrid(showGrid); // the grid will add to the row height
+
+ delegate.hint = QSize(cellWidth, cellHeight);
+
+ QSignalSpy resizedSpy(view.horizontalHeader(), SIGNAL(sectionResized(int, int, int)));
+ view.resizeColumnsToContents();
+
+ QCOMPARE(resizedSpy.count(), model.columnCount());
+ for (int c = 0; c < model.columnCount(); ++c)
+ QCOMPARE(view.columnWidth(c), columnWidth);
+}
+
+void tst_QTableView::rowViewportPosition_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("verticalScrollMode");
+ QTest::addColumn<int>("verticalScrollValue");
+ QTest::addColumn<int>("rowViewportPosition");
+
+ QTest::newRow("row 0, scroll per item 0")
+ << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerItem) << 0 << 0;
+
+ QTest::newRow("row 1, scroll per item, 0")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 0 << 1 * 40;
+
+ QTest::newRow("row 1, scroll per item, 1")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 1 << 0;
+
+ QTest::newRow("row 5, scroll per item, 0")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 0 << 5 * 40;
+
+ QTest::newRow("row 5, scroll per item, 5")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 5 << 0;
+
+ QTest::newRow("row 9, scroll per item, 0")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 0 << 9 * 40;
+
+ QTest::newRow("row 9, scroll per item, 5")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 5 << 4 * 40;
+
+ QTest::newRow("row 0, scroll per pixel 0")
+ << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerPixel) << 0 << 0;
+
+ QTest::newRow("row 1, scroll per pixel, 0")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 0 << 1 * 40;
+
+ QTest::newRow("row 1, scroll per pixel, 1")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 1 * 40 << 0;
+
+ QTest::newRow("row 5, scroll per pixel, 0")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 0 << 5 * 40;
+
+ QTest::newRow("row 5, scroll per pixel, 5")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 0;
+
+ QTest::newRow("row 9, scroll per pixel, 0")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 0 << 9 * 40;
+
+ QTest::newRow("row 9, scroll per pixel, 5")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 4 * 40;
+}
+
+void tst_QTableView::rowViewportPosition()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, rowHeight);
+ QFETCH(int, row);
+ QFETCH(int, verticalScrollMode);
+ QFETCH(int, verticalScrollValue);
+ QFETCH(int, rowViewportPosition);
+
+ QtTestTableModel model(rowCount, 1);
+ QtTestTableView view;
+ view.resize(100, 2 * rowHeight);
+ view.show();
+
+ view.setModel(&model);
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHeight(r, rowHeight);
+
+ view.setVerticalScrollMode((QAbstractItemView::ScrollMode)verticalScrollMode);
+ view.verticalScrollBar()->setValue(verticalScrollValue);
+
+ QCOMPARE(view.rowViewportPosition(row), rowViewportPosition);
+}
+
+void tst_QTableView::rowAt_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<IntList>("hiddenRows");
+ QTest::addColumn<int>("coordinate");
+ QTest::addColumn<int>("row");
+
+ QTest::newRow("row at 100") << 5 << 40 << IntList() << 100 << 2;
+ QTest::newRow("row at 180") << 5 << 40 << IntList() << 180 << 4;
+ QTest::newRow("row at 20") << 5 << 40 << IntList() << 20 << 0;
+
+ // ### expand the dataset to include hidden rows
+}
+
+void tst_QTableView::rowAt()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, rowHeight);
+ QFETCH(IntList, hiddenRows);
+ QFETCH(int, coordinate);
+ QFETCH(int, row);
+
+ QtTestTableModel model(rowCount, 1);
+ QtTestTableView view;
+ view.resize(100, 2 * rowHeight);
+
+ view.setModel(&model);
+
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHeight(r, rowHeight);
+
+ for (int i = 0; i < hiddenRows.count(); ++i)
+ view.hideRow(hiddenRows.at(i));
+
+ QCOMPARE(view.rowAt(coordinate), row);
+}
+
+void tst_QTableView::rowHeight_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<IntList>("rowHeights");
+ QTest::addColumn<BoolList>("hiddenRows");
+
+ QTest::newRow("increasing")
+ << 5
+ << (IntList() << 20 << 30 << 40 << 50 << 60)
+ << (BoolList() << false << false << false << false << false);
+
+ QTest::newRow("decreasing")
+ << 5
+ << (IntList() << 60 << 50 << 40 << 30 << 20)
+ << (BoolList() << false << false << false << false << false);
+
+ QTest::newRow("random")
+ << 5
+ << (IntList() << 87 << 34 << 68 << 91 << 27)
+ << (BoolList() << false << false << false << false << false);
+
+ // ### expand the dataset to include hidden rows
+}
+
+void tst_QTableView::rowHeight()
+{
+ QFETCH(int, rowCount);
+ QFETCH(IntList, rowHeights);
+ QFETCH(BoolList, hiddenRows);
+
+ QtTestTableModel model(rowCount, 1);
+ QtTestTableView view;
+
+ view.setModel(&model);
+
+ for (int r = 0; r < rowCount; ++r) {
+ view.setRowHeight(r, rowHeights.at(r));
+ view.setRowHidden(r, hiddenRows.at(r));
+ }
+
+ for (int r = 0; r < rowCount; ++r) {
+ if (hiddenRows.at(r))
+ QCOMPARE(view.rowHeight(r), 0);
+ else
+ QCOMPARE(view.rowHeight(r), rowHeights.at(r));
+ }
+}
+
+void tst_QTableView::columnViewportPosition_data()
+{
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("columnWidth");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("horizontalScrollMode");
+ QTest::addColumn<int>("horizontalScrollValue");
+ QTest::addColumn<int>("columnViewportPosition");
+
+ QTest::newRow("column 0, scroll per item 0")
+ << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerItem) << 0 << 0;
+
+ QTest::newRow("column 1, scroll per item, 0")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 0 << 1 * 40;
+
+ QTest::newRow("column 1, scroll per item, 1")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 1 << 0;
+
+ QTest::newRow("column 5, scroll per item, 0")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 0 << 5 * 40;
+
+ QTest::newRow("column 5, scroll per item, 5")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 5 << 0;
+
+ QTest::newRow("column 9, scroll per item, 0")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 0 << 9 * 40;
+
+ QTest::newRow("column 9, scroll per item, 5")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 5 << 4 * 40;
+
+ QTest::newRow("column 0, scroll per pixel 0")
+ << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerPixel) << 0 << 0;
+
+ QTest::newRow("column 1, scroll per pixel 0")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 0 << 1 * 40;
+
+ QTest::newRow("column 1, scroll per pixel 1")
+ << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 1 * 40 << 0;
+
+ QTest::newRow("column 5, scroll per pixel 0")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 0 << 5 * 40;
+
+ QTest::newRow("column 5, scroll per pixel 5")
+ << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 0;
+
+ QTest::newRow("column 9, scroll per pixel 0")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 0 << 9 * 40;
+
+ QTest::newRow("column 9, scroll per pixel 5")
+ << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 4 * 40;
+}
+
+void tst_QTableView::columnViewportPosition()
+{
+ QFETCH(int, columnCount);
+ QFETCH(int, columnWidth);
+ QFETCH(int, column);
+ QFETCH(int, horizontalScrollMode);
+ QFETCH(int, horizontalScrollValue);
+ QFETCH(int, columnViewportPosition);
+
+ QtTestTableModel model(1, columnCount);
+ QtTestTableView view;
+ view.resize(2 * columnWidth, 100);
+ view.show();
+
+ view.setModel(&model);
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnWidth(c, columnWidth);
+
+ view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)horizontalScrollMode);
+ view.horizontalScrollBar()->setValue(horizontalScrollValue);
+
+ QCOMPARE(view.columnViewportPosition(column), columnViewportPosition);
+}
+
+void tst_QTableView::columnAt_data()
+{
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("columnWidth");
+ QTest::addColumn<IntList>("hiddenColumns");
+ QTest::addColumn<int>("coordinate");
+ QTest::addColumn<int>("column");
+
+ QTest::newRow("column at 100") << 5 << 40 << IntList() << 100 << 2;
+ QTest::newRow("column at 180") << 5 << 40 << IntList() << 180 << 4;
+ QTest::newRow("column at 20") << 5 << 40 << IntList() << 20 << 0;
+
+ // ### expand the dataset to include hidden coumns
+}
+
+void tst_QTableView::columnAt()
+{
+ QFETCH(int, columnCount);
+ QFETCH(int, columnWidth);
+ QFETCH(IntList, hiddenColumns);
+ QFETCH(int, coordinate);
+ QFETCH(int, column);
+
+ QtTestTableModel model(1, columnCount);
+ QtTestTableView view;
+ view.resize(2 * columnWidth, 100);
+
+ view.setModel(&model);
+
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnWidth(c, columnWidth);
+
+ for (int i = 0; i < hiddenColumns.count(); ++i)
+ view.hideColumn(hiddenColumns.at(i));
+
+ QCOMPARE(view.columnAt(coordinate), column);
+}
+
+void tst_QTableView::columnWidth_data()
+{
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<IntList>("columnWidths");
+ QTest::addColumn<BoolList>("hiddenColumns");
+
+ QTest::newRow("increasing")
+ << 5
+ << (IntList() << 20 << 30 << 40 << 50 << 60)
+ << (BoolList() << false << false << false << false << false);
+
+ QTest::newRow("decreasing")
+ << 5
+ << (IntList() << 60 << 50 << 40 << 30 << 20)
+ << (BoolList() << false << false << false << false << false);
+
+ QTest::newRow("random")
+ << 5
+ << (IntList() << 87 << 34 << 68 << 91 << 27)
+ << (BoolList() << false << false << false << false << false);
+
+ // ### expand the dataset to include hidden columns
+}
+
+void tst_QTableView::columnWidth()
+{
+ QFETCH(int, columnCount);
+ QFETCH(IntList, columnWidths);
+ QFETCH(BoolList, hiddenColumns);
+
+ QtTestTableModel model(1, columnCount);
+ QtTestTableView view;
+
+ view.setModel(&model);
+
+ for (int c = 0; c < columnCount; ++c) {
+ view.setColumnWidth(c, columnWidths.at(c));
+ view.setColumnHidden(c, hiddenColumns.at(c));
+ }
+
+ for (int c = 0; c < columnCount; ++c) {
+ if (hiddenColumns.at(c))
+ QCOMPARE(view.columnWidth(c), 0);
+ else
+ QCOMPARE(view.columnWidth(c), columnWidths.at(c));
+ }
+}
+
+void tst_QTableView::hiddenRow_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<BoolList>("hiddenRows");
+
+ QTest::newRow("first hidden")
+ << 5 << (BoolList() << true << false << false << false << false);
+
+ QTest::newRow("last hidden")
+ << 5 << (BoolList() << false << false << false << false << true);
+
+ QTest::newRow("none hidden")
+ << 5 << (BoolList() << false << false << false << false << false);
+
+ QTest::newRow("all hidden")
+ << 5 << (BoolList() << true << true << true << true << true);
+ }
+
+void tst_QTableView::hiddenRow()
+{
+ QFETCH(int, rowCount);
+ QFETCH(BoolList, hiddenRows);
+
+
+ QtTestTableModel model(rowCount, 1);
+ QtTestTableView view;
+
+ view.setModel(&model);
+
+ for (int r = 0; r < rowCount; ++r)
+ QVERIFY(!view.isRowHidden(r));
+
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHidden(r, hiddenRows.at(r));
+
+ for (int r = 0; r < rowCount; ++r)
+ QCOMPARE(view.isRowHidden(r), hiddenRows.at(r));
+
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHidden(r, false);
+
+ for (int r = 0; r < rowCount; ++r)
+ QVERIFY(!view.isRowHidden(r));
+}
+
+void tst_QTableView::hiddenColumn_data()
+{
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<BoolList>("hiddenColumns");
+
+ QTest::newRow("first hidden")
+ << 5 << (BoolList() << true << false << false << false << false);
+
+ QTest::newRow("last hidden")
+ << 5 << (BoolList() << false << false << false << false << true);
+
+ QTest::newRow("none hidden")
+ << 5 << (BoolList() << false << false << false << false << false);
+
+ QTest::newRow("all hidden")
+ << 5 << (BoolList() << true << true << true << true << true);
+}
+
+void tst_QTableView::hiddenColumn()
+{
+ QFETCH(int, columnCount);
+ QFETCH(BoolList, hiddenColumns);
+
+ QtTestTableModel model(1, columnCount);
+ QtTestTableView view;
+
+ view.setModel(&model);
+
+ for (int c = 0; c < columnCount; ++c)
+ QVERIFY(!view.isColumnHidden(c));
+
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnHidden(c, hiddenColumns.at(c));
+
+ for (int c = 0; c < columnCount; ++c)
+ QCOMPARE(view.isColumnHidden(c), hiddenColumns.at(c));
+
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnHidden(c, false);
+
+ for (int c = 0; c < columnCount; ++c)
+ QVERIFY(!view.isColumnHidden(c));
+}
+
+void tst_QTableView::sortingEnabled_data()
+{
+// QTest::addColumn<int>("columnCount");
+}
+
+void tst_QTableView::sortingEnabled()
+{
+// QFETCH(int, columnCount);
+}
+
+void tst_QTableView::scrollTo_data()
+{
+ QTest::addColumn<int>("verticalScrollMode");
+ QTest::addColumn<int>("horizontalScrollMode");
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+ QTest::addColumn<int>("hiddenRow");
+ QTest::addColumn<int>("hiddenColumn");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+ QTest::addColumn<int>("horizontalScroll");
+ QTest::addColumn<int>("verticalScroll");
+ QTest::addColumn<int>("scrollHint");
+ QTest::addColumn<int>("expectedHorizontalScroll");
+ QTest::addColumn<int>("expectedVerticalScroll");
+
+ QTest::newRow("no hidden, no span, no scroll, per item")
+ << (int)QAbstractItemView::ScrollPerItem
+ << (int)QAbstractItemView::ScrollPerItem
+ << 10 << 10 // table
+ << 80 << 80 // size
+ << -1 << -1 // hide
+ << 0 << 0 // cell
+ << 1 << 1 // span
+ << 0 << 0 // scroll
+ << (int)QAbstractItemView::PositionAtTop
+ << 0 << 0; // expected
+
+ QTest::newRow("no hidden, no span, no scroll, per pixel")
+ << (int)QAbstractItemView::ScrollPerPixel
+ << (int)QAbstractItemView::ScrollPerPixel
+ << 10 << 10 // table
+ << 80 << 80 // size
+ << -1 << -1 // hide
+ << 0 << 0 // cell
+ << 1 << 1 // span
+ << 0 << 0 // scroll
+ << (int)QAbstractItemView::PositionAtTop
+ << 0 << 0; // expected
+
+ QTest::newRow("hidden, no span, no scroll, per item")
+ << (int)QAbstractItemView::ScrollPerItem
+ << (int)QAbstractItemView::ScrollPerItem
+ << 10 << 10 // table
+ << 80 << 80 // size
+ << 3 << 3 // hide
+ << 5 << 5 // cell
+ << 1 << 1 // span
+ << 0 << 0 // scroll
+ << (int)QAbstractItemView::PositionAtTop
+ << 4 << 4; // expected
+}
+
+void tst_QTableView::scrollTo()
+{
+ QFETCH(int, horizontalScrollMode);
+ QFETCH(int, verticalScrollMode);
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+ QFETCH(int, hiddenRow);
+ QFETCH(int, hiddenColumn);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+ QFETCH(int, horizontalScroll);
+ QFETCH(int, verticalScroll);
+ QFETCH(int, scrollHint);
+ QFETCH(int, expectedHorizontalScroll);
+ QFETCH(int, expectedVerticalScroll);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QWidget toplevel;
+ QtTestTableView view(&toplevel);
+
+ toplevel.show();
+ // resizing to this size will ensure that there can ONLY_BE_ONE_CELL inside the view.
+ QSize forcedSize(columnWidth * 2, rowHeight * 2);
+ view.resize(forcedSize);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(50);
+ QTRY_COMPARE(view.size(), forcedSize);
+
+ view.setModel(&model);
+ view.setSpan(row, column, rowSpan, columnSpan);
+ view.hideRow(hiddenRow);
+ view.hideColumn(hiddenColumn);
+ view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)horizontalScrollMode);
+ view.setVerticalScrollMode((QAbstractItemView::ScrollMode)verticalScrollMode);
+
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHeight(r, rowHeight);
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnWidth(c, columnWidth);
+
+ QTest::qWait(150); // ### needed to pass the test
+ view.horizontalScrollBar()->setValue(horizontalScroll);
+ view.verticalScrollBar()->setValue(verticalScroll);
+
+ QModelIndex index = model.index(row, column);
+ QVERIFY(index.isValid());
+ view.scrollTo(index, (QAbstractItemView::ScrollHint)scrollHint);
+ QCOMPARE(view.verticalScrollBar()->value(), expectedVerticalScroll);
+ QCOMPARE(view.horizontalScrollBar()->value(), expectedHorizontalScroll);
+}
+
+void tst_QTableView::indexAt_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+
+ QTest::addColumn<int>("rowHeight");
+ QTest::addColumn<int>("columnWidth");
+
+ QTest::addColumn<int>("hiddenRow");
+ QTest::addColumn<int>("hiddenColumn");
+
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+ QTest::addColumn<int>("horizontalScroll");
+ QTest::addColumn<int>("verticalScroll");
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::addColumn<int>("expectedRow");
+ QTest::addColumn<int>("expectedColumn");
+
+ QTest::newRow("no hidden, no span, no scroll, (20,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << -1 // hide
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 0 << 0 // scroll
+ << 20 << 20 // point
+ << 0 << 0; // expected
+
+ QTest::newRow("row hidden, no span, no scroll, at (20,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << 0 << -1 // hide
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 0 << 0 // scroll
+ << 20 << 20 // point
+ << 1 << 0; // expected
+
+ QTest::newRow("col hidden, no span, no scroll, at (20,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << 0 // hide
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 0 << 0 // scroll
+ << 20 << 20 // point
+ << 0 << 1; // expected
+
+ QTest::newRow("no hidden, row span, no scroll, at (60,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << -1 // hide
+ << 0 << 0 // pos
+ << 2 << 1 // span
+ << 0 << 0 // scroll
+ << 20 << 60 // point
+ << 0 << 0; // expected
+
+
+ QTest::newRow("no hidden, col span, no scroll, at (60,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << -1 // hide
+ << 0 << 0 // pos
+ << 1 << 2 // span
+ << 0 << 0 // scroll
+ << 60 << 20 // point
+ << 0 << 0; // expected
+
+ QTest::newRow("no hidden, no span, scroll (5,0), at (20,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << -1 // hide
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 5 << 0 // scroll
+ << 20 << 20 // point
+ << 0 << 5; // expected
+
+ QTest::newRow("no hidden, no span, scroll (0,5), at (20,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << -1 // hide
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 0 << 5 // scroll
+ << 20 << 20 // point
+ << 5 << 0; // expected
+
+ QTest::newRow("no hidden, no span, scroll (5,5), at (20,20)")
+ << 10 << 10 // dim
+ << 40 << 40 // size
+ << -1 << -1 // hide
+ << -1 << -1 // pos
+ << 1 << 1 // span
+ << 5 << 5 // scroll
+ << 20 << 20 // point
+ << 5 << 5; // expected
+}
+
+void tst_QTableView::indexAt()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, rowHeight);
+ QFETCH(int, columnWidth);
+ QFETCH(int, hiddenRow);
+ QFETCH(int, hiddenColumn);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+ QFETCH(int, horizontalScroll);
+ QFETCH(int, verticalScroll);
+ QFETCH(int, x);
+ QFETCH(int, y);
+ QFETCH(int, expectedRow);
+ QFETCH(int, expectedColumn);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QWidget toplevel;
+ QtTestTableView view(&toplevel);
+
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+
+ //some styles change the scroll mode in their polish
+ view.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
+ view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+
+ view.setModel(&model);
+ view.setSpan(row, column, rowSpan, columnSpan);
+ view.hideRow(hiddenRow);
+ view.hideColumn(hiddenColumn);
+
+ for (int r = 0; r < rowCount; ++r)
+ view.setRowHeight(r, rowHeight);
+ for (int c = 0; c < columnCount; ++c)
+ view.setColumnWidth(c, columnWidth);
+
+ QTest::qWait(20);
+ view.horizontalScrollBar()->setValue(horizontalScroll);
+ view.verticalScrollBar()->setValue(verticalScroll);
+ QTest::qWait(20);
+
+ QModelIndex index = view.indexAt(QPoint(x, y));
+ QCOMPARE(index.row(), expectedRow);
+ QCOMPARE(index.column(), expectedColumn);
+}
+
+void tst_QTableView::span_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("hiddenRow");
+ QTest::addColumn<int>("hiddenColumn");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+ QTest::addColumn<int>("expectedRowSpan");
+ QTest::addColumn<int>("expectedColumnSpan");
+ QTest::addColumn<bool>("clear");
+
+ QTest::newRow("top left 2x2")
+ << 10 << 10
+ << -1 << -1
+ << 0 << 0
+ << 2 << 2
+ << 2 << 2
+ << false;
+
+ QTest::newRow("top left 1x2")
+ << 10 << 10
+ << 3 << 3
+ << 0 << 0
+ << 1 << 2
+ << 1 << 2
+ << false;
+
+ QTest::newRow("top left 2x1")
+ << 10 << 10
+ << -1 << -1
+ << 0 << 0
+ << 2 << 1
+ << 2 << 1
+ << false;
+
+ /* This makes no sens.
+ QTest::newRow("top left 2x0")
+ << 10 << 10
+ << -1 << -1
+ << 0 << 0
+ << 2 << 0
+ << 2 << 0
+ << false;
+
+ QTest::newRow("top left 0x2")
+ << 10 << 10
+ << -1 << -1
+ << 0 << 0
+ << 0 << 2
+ << 0 << 2
+ << false;*/
+
+ QTest::newRow("invalid 2x2")
+ << 10 << 10
+ << -1 << -1
+ << -1 << -1
+ << 2 << 2
+ << 1 << 1
+ << false;
+
+ QTest::newRow("top left 2x2")
+ << 10 << 10
+ << -1 << -1
+ << 0 << 0
+ << 2 << 2
+ << 2 << 2
+ << false;
+
+ QTest::newRow("bottom right 2x2")
+ << 10 << 10
+ << -1 << -1
+ << 8 << 8
+ << 2 << 2
+ << 2 << 2
+ << false;
+
+ QTest::newRow("invalid span 2x2")
+ << 10 << 10
+ << -1 << -1
+ << 8 << 8
+ << 2 << 2
+ << 2 << 2
+ << false;
+
+ QTest::newRow("invalid span 3x3")
+ << 10 << 10
+ << -1 << -1
+ << 6 << 6
+ << 3 << 3
+ << 2 << 3
+ << true;
+
+}
+
+void tst_QTableView::span()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, hiddenRow);
+ QFETCH(int, hiddenColumn);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+ QFETCH(int, expectedRowSpan);
+ QFETCH(int, expectedColumnSpan);
+ QFETCH(bool, clear);
+
+ QtTestTableModel model(rowCount, columnCount);
+ QtTestTableView view;
+
+ view.setModel(&model);
+ view.show();
+
+ view.setSpan(row, column, rowSpan, columnSpan);
+ if (clear) {
+ model.removeLastRow();
+ model.removeLastRow();
+ view.update();
+ }
+
+ view.hideRow(hiddenRow);
+ view.hideColumn(hiddenColumn);
+ view.show();
+
+ QCOMPARE(view.rowSpan(row, column), expectedRowSpan);
+ QCOMPARE(view.columnSpan(row, column), expectedColumnSpan);
+
+ if (hiddenRow > -1) {
+ QModelIndex hidden = model.index(hiddenRow, columnCount - 1);
+ QVERIFY(view.isIndexHidden(hidden));
+ }
+
+ if (hiddenColumn > -1) {
+ QModelIndex hidden = model.index(rowCount - 1, hiddenColumn);
+ QVERIFY(view.isIndexHidden(hidden));
+ }
+
+ view.clearSpans();
+ QCOMPARE(view.rowSpan(row, column), 1);
+ QCOMPARE(view.columnSpan(row, column), 1);
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+typedef QVector<QRect> SpanList;
+Q_DECLARE_METATYPE(SpanList)
+
+void tst_QTableView::spans_data()
+{
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<SpanList>("spans");
+ QTest::addColumn<bool>("hideRowLastRowOfFirstSpan");
+ QTest::addColumn<QPoint>("pos");
+ QTest::addColumn<int>("expectedRowSpan");
+ QTest::addColumn<int>("expectedColumnSpan");
+
+ QTest::newRow("1x3 span, query 3,0")
+ << 5 << 5
+ << (SpanList() << QRect(3, 0, 1, 3))
+ << false //no hidden row
+ << QPoint(3, 0)
+ << 1
+ << 3;
+
+ QTest::newRow("1x3 span, query 3,1")
+ << 5 << 5
+ << (SpanList() << QRect(3, 0, 1, 3))
+ << false //no hidden row
+ << QPoint(3, 1)
+ << 1
+ << 3;
+
+ QTest::newRow("1x3 span, query 3,2")
+ << 5 << 5
+ << (SpanList() << QRect(3, 0, 1, 3))
+ << false //no hidden row
+ << QPoint(3, 2)
+ << 1
+ << 3;
+
+ QTest::newRow("two 1x2 spans at the same column, query at 3,0")
+ << 5 << 5
+ << (SpanList() << QRect(3, 0, 1, 2) << QRect(4, 0, 1, 2))
+ << false //no hidden row
+ << QPoint(3, 0)
+ << 1
+ << 2;
+
+ QTest::newRow("two 1x2 spans at the same column, query at 4,0")
+ << 5 << 5
+ << (SpanList() << QRect(3, 0, 1, 2) << QRect(4, 0, 1, 2))
+ << false //no hidden row
+ << QPoint(4, 0)
+ << 1
+ << 2;
+
+ QTest::newRow("how to order spans (1,1)")
+ << 5 << 5
+ << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
+ << false //no hidden row
+ << QPoint(1, 1)
+ << 3
+ << 1;
+
+ QTest::newRow("how to order spans (2,1)")
+ << 5 << 5
+ << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
+ << false //no hidden row
+ << QPoint(2, 1)
+ << 3
+ << 1;
+
+ QTest::newRow("how to order spans (3,1)")
+ << 5 << 5
+ << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
+ << false //no hidden row
+ << QPoint(3, 1)
+ << 3
+ << 1;
+
+ QTest::newRow("how to order spans (1,2)")
+ << 5 << 5
+ << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
+ << false //no hidden row
+ << QPoint(1, 2)
+ << 2
+ << 1;
+
+ QTest::newRow("how to order spans (2,2)")
+ << 5 << 5
+ << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
+ << false //no hidden row
+ << QPoint(2, 2)
+ << 2
+ << 1;
+
+ QTest::newRow("spans with hidden rows")
+ << 3 << 2
+ << (SpanList() << QRect(0, 0, 2, 2) << QRect(2, 0, 1, 2))
+ << true //we hide the last row of the first span
+ << QPoint(2, 0)
+ << 1
+ << 2;
+
+ QTest::newRow("QTBUG-6004: No failing assertion, then it passes.")
+ << 5 << 5
+ << (SpanList() << QRect(0, 0, 2, 2) << QRect(0, 0, 1, 1))
+ << false
+ << QPoint(0, 0)
+ << 1
+ << 1;
+
+ QTest::newRow("QTBUG-6004 (follow-up): No failing assertion, then it passes.")
+ << 10 << 10
+ << (SpanList() << QRect(2, 2, 1, 3) << QRect(2, 2, 1, 1))
+ << false
+ << QPoint(0, 0)
+ << 1
+ << 1;
+
+ QTest::newRow("QTBUG-9631: remove one span")
+ << 10 << 10
+ << (SpanList() << QRect(1, 1, 2, 1) << QRect(2, 2, 2, 2) << QRect(1, 1, 1, 1))
+ << false
+ << QPoint(1, 1)
+ << 1
+ << 1;
+}
+
+void tst_QTableView::spans()
+{
+ QFETCH(int, rows);
+ QFETCH(int, columns);
+ QFETCH(SpanList, spans);
+ QFETCH(bool, hideRowLastRowOfFirstSpan);
+ QFETCH(QPoint, pos);
+ QFETCH(int, expectedRowSpan);
+ QFETCH(int, expectedColumnSpan);
+
+ QtTestTableModel model(rows, columns);
+ QtTestTableView view;
+
+ view.setModel(&model);
+ view.show();
+
+ for (int i = 0; i < spans.count(); ++i) {
+ QRect sp = spans.at(i);
+ view.setSpan(sp.x(), sp.y(), sp.width(), sp.height());
+ }
+
+ if (hideRowLastRowOfFirstSpan) {
+ view.setRowHidden(spans.at(0).bottom(), true);
+ //we check that the span didn't break the visual rects of the model indexes
+ QRect first = view.visualRect( model.index(spans.at(0).top(), 0));
+ QRect next = view.visualRect( model.index(spans.at(0).bottom() + 1, 0));
+ QVERIFY(first.intersected(next).isEmpty());
+ }
+
+ QCOMPARE(view.columnSpan(pos.x(), pos.y()), expectedColumnSpan);
+ QCOMPARE(view.rowSpan(pos.x(), pos.y()), expectedRowSpan);
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+void tst_QTableView::spansAfterRowInsertion()
+{
+ QtTestTableModel model(10, 10);
+ QtTestTableView view;
+ view.setModel(&model);
+ view.setSpan(3, 3, 3, 3);
+ view.show();
+ QTest::qWait(50);
+
+ // Insertion before the span only shifts the span.
+ view.model()->insertRows(0, 2);
+ QCOMPARE(view.rowSpan(3, 3), 1);
+ QCOMPARE(view.columnSpan(3, 3), 1);
+ QCOMPARE(view.rowSpan(5, 3), 3);
+ QCOMPARE(view.columnSpan(5, 3), 3);
+
+ // Insertion happens before the given row, so it only shifts the span also.
+ view.model()->insertRows(5, 2);
+ QCOMPARE(view.rowSpan(5, 3), 1);
+ QCOMPARE(view.columnSpan(5, 3), 1);
+ QCOMPARE(view.rowSpan(7, 3), 3);
+ QCOMPARE(view.columnSpan(7, 3), 3);
+
+ // Insertion inside the span expands it.
+ view.model()->insertRows(8, 2);
+ QCOMPARE(view.rowSpan(7, 3), 5);
+ QCOMPARE(view.columnSpan(7, 3), 3);
+
+ // Insertion after the span does nothing to it.
+ view.model()->insertRows(12, 2);
+ QCOMPARE(view.rowSpan(7, 3), 5);
+ QCOMPARE(view.columnSpan(7, 3), 3);
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+void tst_QTableView::spansAfterColumnInsertion()
+{
+ QtTestTableModel model(10, 10);
+ QtTestTableView view;
+ view.setModel(&model);
+ view.setSpan(3, 3, 3, 3);
+ view.show();
+ QTest::qWait(50);
+
+ // Insertion before the span only shifts the span.
+ view.model()->insertColumns(0, 2);
+ QCOMPARE(view.rowSpan(3, 3), 1);
+ QCOMPARE(view.columnSpan(3, 3), 1);
+ QCOMPARE(view.rowSpan(3, 5), 3);
+ QCOMPARE(view.columnSpan(3, 5), 3);
+
+ // Insertion happens before the given column, so it only shifts the span also.
+ view.model()->insertColumns(5, 2);
+ QCOMPARE(view.rowSpan(3, 5), 1);
+ QCOMPARE(view.columnSpan(3, 5), 1);
+ QCOMPARE(view.rowSpan(3, 7), 3);
+ QCOMPARE(view.columnSpan(3, 7), 3);
+
+ // Insertion inside the span expands it.
+ view.model()->insertColumns(8, 2);
+ QCOMPARE(view.rowSpan(3, 7), 3);
+ QCOMPARE(view.columnSpan(3, 7), 5);
+
+ // Insertion after the span does nothing to it.
+ view.model()->insertColumns(12, 2);
+ QCOMPARE(view.rowSpan(3, 7), 3);
+ QCOMPARE(view.columnSpan(3, 7), 5);
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+void tst_QTableView::spansAfterRowRemoval()
+{
+ QtTestTableModel model(10, 10);
+ QtTestTableView view;
+ view.setModel(&model);
+
+ QList<QRect> spans;
+ spans << QRect(0, 1, 1, 2)
+ << QRect(1, 2, 1, 2)
+ << QRect(2, 2, 1, 5)
+ << QRect(2, 8, 1, 2)
+ << QRect(3, 4, 1, 2)
+ << QRect(4, 4, 1, 4)
+ << QRect(5, 6, 1, 3)
+ << QRect(6, 7, 1, 3);
+ foreach (QRect span, spans)
+ view.setSpan(span.top(), span.left(), span.height(), span.width());
+
+ view.show();
+ QTest::qWait(100);
+ view.model()->removeRows(3, 3);
+
+ QList<QRect> expectedSpans;
+ expectedSpans << QRect(0, 1, 1, 2)
+ << QRect(1, 2, 1, 1)
+ << QRect(2, 2, 1, 2)
+ << QRect(2, 5, 1, 2)
+ << QRect(3, 4, 1, 1)
+ << QRect(4, 3, 1, 2)
+ << QRect(5, 3, 1, 3)
+ << QRect(6, 4, 1, 3);
+ foreach (QRect span, expectedSpans) {
+ QCOMPARE(view.columnSpan(span.top(), span.left()), span.width());
+ QCOMPARE(view.rowSpan(span.top(), span.left()), span.height());
+ }
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+void tst_QTableView::spansAfterColumnRemoval()
+{
+ QtTestTableModel model(10, 10);
+ QtTestTableView view;
+ view.setModel(&model);
+
+ // Same set as above just swapping columns and rows.
+ QList<QRect> spans;
+ spans << QRect(0, 1, 1, 2)
+ << QRect(1, 2, 1, 2)
+ << QRect(2, 2, 1, 5)
+ << QRect(2, 8, 1, 2)
+ << QRect(3, 4, 1, 2)
+ << QRect(4, 4, 1, 4)
+ << QRect(5, 6, 1, 3)
+ << QRect(6, 7, 1, 3);
+ foreach (QRect span, spans)
+ view.setSpan(span.left(), span.top(), span.width(), span.height());
+
+ view.show();
+ QTest::qWait(100);
+ view.model()->removeColumns(3, 3);
+
+ QList<QRect> expectedSpans;
+ expectedSpans << QRect(0, 1, 1, 2)
+ << QRect(1, 2, 1, 1)
+ << QRect(2, 2, 1, 2)
+ << QRect(2, 5, 1, 2)
+ << QRect(3, 4, 1, 1)
+ << QRect(4, 3, 1, 2)
+ << QRect(5, 3, 1, 3)
+ << QRect(6, 4, 1, 3);
+ foreach (QRect span, expectedSpans) {
+ QCOMPARE(view.columnSpan(span.left(), span.top()), span.height());
+ QCOMPARE(view.rowSpan(span.left(), span.top()), span.width());
+ }
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+class Model : public QAbstractTableModel {
+
+Q_OBJECT
+
+public:
+ Model(QObject * parent = 0) : QAbstractTableModel(parent) {
+ }
+
+ int rowCount(const QModelIndex &) const {
+ return rows;
+ }
+ int columnCount(const QModelIndex &) const {
+ return columns;
+ }
+ QVariant data(const QModelIndex &, int) const
+ {
+ return QVariant();
+ }
+ void res() { reset(); }
+
+ int rows;
+ int columns;
+};
+
+void tst_QTableView::checkHeaderReset()
+{
+ QTableView view;
+ Model m;
+ m.rows = 3;
+ m.columns = 3;
+ view.setModel(&m);
+
+ m.rows = 4;
+ m.columns = 4;
+ m.res();
+ QCOMPARE(view.horizontalHeader()->count(), 4);
+}
+
+void tst_QTableView::checkHeaderMinSize()
+{
+ //tests if the minimumsize is of a header is taken into account
+ //while computing QTableView geometry. For that we test the position of the
+ //viewport.
+ QTableView view;
+ QStringListModel m;
+ m.setStringList( QStringList() << QLatin1String("one cell is enough"));
+ view.setModel(&m);
+
+ //setting the minimum height on the horizontal header
+ //and the minimum width on the vertical header
+ view.horizontalHeader()->setMinimumHeight(50);
+ view.verticalHeader()->setMinimumWidth(100);
+
+ view.show();
+
+ QVERIFY( view.verticalHeader()->y() >= view.horizontalHeader()->minimumHeight());
+ QVERIFY( view.horizontalHeader()->x() >= view.verticalHeader()->minimumWidth());
+}
+
+void tst_QTableView::resizeToContents()
+{
+ //checks that the resize to contents is consistent
+ QTableWidget table(2,3);
+ QTableWidget table2(2,3);
+ QTableWidget table3(2,3);
+
+
+ table.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
+ table2.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
+ table3.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
+ table.horizontalHeader()->setVisible(false);
+ table2.horizontalHeader()->setVisible(false);
+ table.verticalHeader()->setVisible(false);
+ table2.verticalHeader()->setVisible(false);
+
+
+ for(int i = 0;i<table.columnCount();i++) {
+ table.resizeColumnToContents(i);
+ }
+ for(int i = 0;i<table.rowCount();i++) {
+ table.resizeRowToContents(i);
+ }
+ table2.resizeColumnsToContents();
+ table2.resizeRowsToContents();
+ table3.resizeColumnsToContents();
+ table3.resizeRowsToContents();
+
+ //now let's check the row/col sizes
+ for(int i = 0;i<table.columnCount();i++) {
+ QCOMPARE( table.columnWidth(i), table2.columnWidth(i));
+ QCOMPARE( table2.columnWidth(i), table3.columnWidth(i));
+ }
+ for(int i = 0;i<table.rowCount();i++) {
+ QCOMPARE( table.rowHeight(i), table2.rowHeight(i));
+ QCOMPARE( table2.rowHeight(i), table3.rowHeight(i));
+ }
+
+}
+
+QT_BEGIN_NAMESPACE
+extern bool Q_GUI_EXPORT qt_tab_all_widgets; // qapplication.cpp
+QT_END_NAMESPACE
+
+void tst_QTableView::tabFocus()
+{
+ if (!qt_tab_all_widgets)
+ QSKIP("This test requires full keyboard control to be enabled.", SkipAll);
+
+ // QTableView enables tabKeyNavigation by default, but you should be able
+ // to change focus on an empty table view, or on a table view that doesn't
+ // have this property set.
+ QWidget window;
+
+ QTableView *view = new QTableView(&window);
+ QLineEdit *edit = new QLineEdit(&window);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ window.setFocus();
+ QTest::qWait(100);
+ window.activateWindow();
+ QTest::qWait(100);
+
+ qApp->processEvents();
+
+ WAIT_FOR_CONDITION(window.hasFocus(), true);
+
+ qApp->processEvents();
+
+ // window
+ QVERIFY(window.hasFocus());
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ for (int i = 0; i < 2; ++i) {
+ // tab to view
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(!window.hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ // tab to edit
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(edit->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!view->hasFocus());
+ }
+
+ // backtab to view
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ // backtab to edit
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(edit->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!view->hasFocus());
+
+ QStandardItemModel *model = new QStandardItemModel;
+ view->setModel(model);
+
+ // backtab to view
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ // backtab to edit
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(edit->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!view->hasFocus());
+
+ model->insertRow(0, new QStandardItem("Hei"));
+ model->insertRow(0, new QStandardItem("Hei"));
+ model->insertRow(0, new QStandardItem("Hei"));
+
+ // backtab to view
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ // backtab to edit doesn't work
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QVERIFY(!window.hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ view->setTabKeyNavigation(false);
+
+ // backtab to edit
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(edit->hasFocus());
+ QVERIFY(!window.hasFocus());
+ QVERIFY(!view->hasFocus());
+
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(view->hasFocus());
+ QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(edit->hasFocus());
+
+ delete model;
+}
+
+class BigModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ virtual QVariant data(const QModelIndex &index,
+ int role = Qt::DisplayRole) const
+ {
+ if (role == Qt::DisplayRole)
+ return QString("%1 - %2").arg(index.column()).arg(index.row());
+ return QVariant();
+ }
+
+
+ int rowCount(const QModelIndex & parent = QModelIndex()) const
+ {
+ Q_UNUSED(parent);
+ return 10000000;
+ }
+
+ int columnCount(const QModelIndex & parent = QModelIndex()) const
+ {
+ Q_UNUSED(parent);
+ return 20000000;
+ }
+};
+
+void tst_QTableView::bigModel()
+{
+ //should not crash
+ QTableView view;
+ BigModel model;
+ view.setModel(&model);
+ view.show();
+ view.setSpan(10002,10002,6,6);
+ QTest::qWait(100);
+ view.resize(1000,1000);
+ QTest::qWait(100);
+ view.scrollTo(model.index(10010,10010));
+ QTest::qWait(100);
+}
+
+void tst_QTableView::selectionSignal()
+{
+ QtTestTableModel model(10, 10);
+ QtTestTableView view;
+ view.checkSignalOrder = true;
+ view.setModel(&model);
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(model.index(2, 0)).center());
+}
+
+class task173773_EventFilter : public QObject
+{
+ int paintEventCount_;
+public:
+ task173773_EventFilter() : paintEventCount_(0) {}
+ int paintEventCount() const { return paintEventCount_; }
+private:
+ bool eventFilter(QObject *obj, QEvent *e)
+ {
+ Q_UNUSED(obj);
+ if (e->type() == QEvent::Paint)
+ ++paintEventCount_;
+ return false;
+ }
+};
+
+void tst_QTableView::task173773_updateVerticalHeader()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), 0);
+ model.setData(model.index(1, 0), 1);
+
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ QTableView view;
+ view.setModel(&proxyModel);
+ view.setSortingEnabled(true);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ view.sortByColumn(0, Qt::AscendingOrder);
+ QTest::qWait(100);
+
+ task173773_EventFilter eventFilter;
+ view.verticalHeader()->viewport()->installEventFilter(&eventFilter);
+
+ view.sortByColumn(0, Qt::DescendingOrder);
+ QTest::qWait(100);
+
+ // ### note: this test may occasionally pass even if the bug is present!
+ QVERIFY(eventFilter.paintEventCount() > 0);
+}
+
+void tst_QTableView::task227953_setRootIndex()
+{
+ QTableView tableView;
+
+ //model = tree with two items with tables as children
+ QStandardItemModel model;
+ QStandardItem item1, item2;
+ model.appendColumn(QList<QStandardItem*>() << &item1 << &item2);
+
+
+ //setup the first table as a child of the first item
+ for ( int row = 0; row < 40; ++row ) {
+ item1.appendRow(QList<QStandardItem*>() << new QStandardItem(QString("row %0").arg(row)));
+ }
+
+ //setup the second table as a child of the second item
+ for ( int row = 0; row < 10; ++row ) {
+ item2.appendRow(QList<QStandardItem*>() << new QStandardItem(QString("row %0").arg(row)));
+ }
+
+ tableView.setModel(&model);
+
+ //show the first 10 rows of the first table
+ QModelIndex root = model.indexFromItem(&item1);
+ tableView.setRootIndex(root);
+ for (int i = 10; i != 40; ++i) {
+ tableView.setRowHidden(i, true);
+ }
+
+ QCOMPARE(tableView.verticalHeader()->count(), 40);
+ QCOMPARE(tableView.verticalHeader()->hiddenSectionCount(), 30);
+
+ //show the first 10 rows of the second table
+ tableView.setRootIndex(model.indexFromItem(&item2));
+
+ QCOMPARE(tableView.verticalHeader()->count(), 10);
+ QCOMPARE(tableView.verticalHeader()->hiddenSectionCount(), 0);
+ QVERIFY(!tableView.verticalHeader()->isHidden());
+}
+
+void tst_QTableView::task240266_veryBigColumn()
+{
+ QTableView table;
+ table.setFixedSize(500, 300); //just to make sure we have the 2 first columns visible
+ QStandardItemModel model(1, 3);
+ table.setModel(&model);
+ table.setColumnWidth(0, 100); //normal column
+ table.setColumnWidth(1, 100); //normal column
+ table.setColumnWidth(2, 9000); //very big column
+ table.show();
+ QTest::qWaitForWindowShown(&table);
+
+ //some styles change the scroll mode in their polish
+ table.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
+ table.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+
+ QScrollBar *scroll = table.horizontalScrollBar();
+ QCOMPARE(scroll->minimum(), 0);
+ QCOMPARE(scroll->maximum(), model.columnCount() - 1);
+ QCOMPARE(scroll->singleStep(), 1);
+
+ //1 is not always a very correct value for pageStep. Ideally this should be dynamic.
+ //Maybe something for Qt 5 ;-)
+ QCOMPARE(scroll->pageStep(), 1);
+
+}
+
+void tst_QTableView::task248688_autoScrollNavigation()
+{
+ //we make sure that when navigating with the keyboard the view is correctly scrolled
+ //to the current item
+ QStandardItemModel model(16, 16);
+ QTableView view;
+ view.setModel(&model);
+
+ view.hideColumn(8);
+ view.hideRow(8);
+ view.show();
+ for (int r = 0; r < model.rowCount(); ++r) {
+ if (view.isRowHidden(r))
+ continue;
+ for (int c = 0; c < model.columnCount(); ++c) {
+ if (view.isColumnHidden(c))
+ continue;
+ QModelIndex index = model.index(r, c);
+ view.setCurrentIndex(index);
+ QVERIFY(view.viewport()->rect().contains(view.visualRect(index)));
+ }
+ }
+}
+
+
+// Since different Windows CE versions sport different taskbars, we skip this test.
+#ifndef Q_OS_WINCE
+void tst_QTableView::mouseWheel_data()
+{
+ QTest::addColumn<int>("scrollMode");
+ QTest::addColumn<int>("delta");
+ QTest::addColumn<int>("horizontalPositon");
+ QTest::addColumn<int>("verticalPosition");
+
+ QTest::newRow("scroll up per item")
+ << int(QAbstractItemView::ScrollPerItem) << 120
+ << 10 - qApp->wheelScrollLines() << 10 - qApp->wheelScrollLines();
+ QTest::newRow("scroll down per item")
+ << int(QAbstractItemView::ScrollPerItem) << -120
+ << 10 + qApp->wheelScrollLines() << 10 + qApp->wheelScrollLines();
+ QTest::newRow("scroll down per pixel")
+ << int(QAbstractItemView::ScrollPerPixel) << -120
+ << 10 + qApp->wheelScrollLines() * 89 << 10 + qApp->wheelScrollLines() * 28;
+}
+
+void tst_QTableView::mouseWheel()
+{
+
+ QFETCH(int, scrollMode);
+ QFETCH(int, delta);
+ QFETCH(int, horizontalPositon);
+ QFETCH(int, verticalPosition);
+
+ QtTestTableModel model(100, 100);
+ QWidget topLevel;
+ QtTestTableView view(&topLevel);
+ view.resize(500, 500);
+ for (int r = 0; r < 100; ++r)
+ view.setRowHeight(r, 50);
+ for (int c = 0; c < 100; ++c)
+ view.setColumnWidth(c, 100);
+ topLevel.show();
+
+ QTest::qWaitForWindowShown(&topLevel);
+
+ view.setModel(&model);
+
+ view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)scrollMode);
+ view.setVerticalScrollMode((QAbstractItemView::ScrollMode)scrollMode);
+ view.horizontalScrollBar()->setValue(10);
+ view.verticalScrollBar()->setValue(10);
+
+ QPoint pos = view.viewport()->geometry().center();
+ QWheelEvent verticalEvent(pos, delta, 0, 0, Qt::Vertical);
+ QWheelEvent horizontalEvent(pos, delta, 0, 0, Qt::Horizontal);
+ QApplication::sendEvent(view.viewport(), &horizontalEvent);
+ QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 10);
+ QApplication::sendEvent(view.viewport(), &verticalEvent);
+ QVERIFY(qAbs(view.verticalScrollBar()->value() - verticalPosition) < 10);
+}
+#endif
+
+void tst_QTableView::addColumnWhileEditing()
+{
+ QTableView view;
+ QStandardItemModel model(1, 10);
+ view.setModel(&model);
+ QModelIndex last = model.index(0,9);
+ view.show();
+
+ view.openPersistentEditor(last);
+ view.scrollTo(last);
+
+ //let's see if the editor is moved to the right location
+ //after adding a column
+ model.setColumnCount(model.columnCount() + 1);
+ QPointer<QLineEdit> editor = qFindChild<QLineEdit*>(&view);
+ QVERIFY(editor);
+ QCOMPARE(editor->geometry(), view.visualRect(last));
+
+ //let's see if the editor is moved to the right location
+ //after removing a column
+ view.scrollTo(model.index(0, model.columnCount()-1));
+ model.setColumnCount(model.columnCount() - 1);
+ QVERIFY(editor);
+ QCOMPARE(editor->geometry(), view.visualRect(last));
+}
+
+void tst_QTableView::task259308_scrollVerticalHeaderSwappedSections()
+{
+ QStandardItemModel model;
+ model.setRowCount(50);
+ model.setColumnCount(2);
+ for (int row = 0; row < model.rowCount(); ++row)
+ for (int col = 0; col < model.columnCount(); ++col) {
+ const QModelIndex &idx = model.index(row, col);
+ model.setData(idx, QVariant(row), Qt::EditRole);
+ }
+
+ QTableView tv;
+ tv.setModel(&model);
+ tv.show();
+ tv.verticalHeader()->swapSections(0, model.rowCount() - 1);
+ tv.setCurrentIndex(model.index(model.rowCount() - 1, 0));
+
+ QTest::qWaitForWindowShown(&tv);
+ QTest::keyClick(&tv, Qt::Key_PageUp); // PageUp won't scroll when at top
+ QTRY_COMPARE(tv.rowAt(0), tv.verticalHeader()->logicalIndex(0));
+
+ int newRow = tv.rowAt(tv.viewport()->height());
+ if (newRow == tv.rowAt(tv.viewport()->height() - 1)) // Overlapping row
+ newRow++;
+ QTest::keyClick(&tv, Qt::Key_PageDown); // Scroll down and check current
+ QTRY_COMPARE(tv.currentIndex().row(), newRow);
+
+ tv.setCurrentIndex(model.index(0, 0));
+ QTest::qWait(60);
+ QTest::keyClick(&tv, Qt::Key_PageDown); // PageDown won't scroll when at the bottom
+ QTRY_COMPARE(tv.rowAt(tv.viewport()->height() - 1), tv.verticalHeader()->logicalIndex(model.rowCount() - 1));
+}
+
+template <typename T>
+struct ValueSaver {
+ T &var, value;
+ ValueSaver(T &v) : var(v), value(v) { }
+ ~ValueSaver() { var = value; }
+};
+
+void tst_QTableView::task191545_dragSelectRows()
+{
+ QStandardItemModel model(10, 10);
+ QTableView table;
+ table.setModel(&model);
+ table.setSelectionBehavior(QAbstractItemView::SelectItems);
+ table.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ table.setMinimumSize(1000, 400);
+ table.show();
+ QTest::qWait(200);
+
+ ValueSaver<Qt::KeyboardModifiers> saver(QApplicationPrivate::modifier_buttons);
+ QApplicationPrivate::modifier_buttons = Qt::ControlModifier;
+
+ {
+ QRect cellRect = table.visualRect(model.index(3, 0));
+ QHeaderView *vHeader = table.verticalHeader();
+ QWidget *vHeaderVp = vHeader->viewport();
+ QPoint rowPos(cellRect.center());
+ QMouseEvent rowPressEvent(QEvent::MouseButtonPress, rowPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(vHeaderVp, &rowPressEvent);
+
+ for (int i = 0; i < 4; ++i) {
+ rowPos.setY(rowPos.y() + cellRect.height());
+ QMouseEvent moveEvent(QEvent::MouseMove, rowPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
+ qApp->sendEvent(vHeaderVp, &moveEvent);
+ }
+ QMouseEvent rowReleaseEvent(QEvent::MouseButtonRelease, rowPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(vHeaderVp, &rowReleaseEvent);
+
+ for (int i = 0; i < 4; ++i) {
+ QModelIndex index = model.index(3 + i, 0, table.rootIndex());
+ QVERIFY(vHeader->selectionModel()->selectedRows().contains(index));
+ }
+ }
+
+ {
+ QRect cellRect = table.visualRect(model.index(0, 3));
+ QHeaderView *hHeader = table.horizontalHeader();
+ QWidget *hHeaderVp = hHeader->viewport();
+ QPoint colPos((cellRect.left() + cellRect.right()) / 2, 5);
+ QMouseEvent colPressEvent(QEvent::MouseButtonPress, colPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(hHeaderVp, &colPressEvent);
+
+ for (int i = 0; i < 4; ++i) {
+ colPos.setX(colPos.x() + cellRect.width());
+ QMouseEvent moveEvent(QEvent::MouseMove, colPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
+ qApp->sendEvent(hHeaderVp, &moveEvent);
+ }
+ QMouseEvent colReleaseEvent(QEvent::MouseButtonRelease, colPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(hHeaderVp, &colReleaseEvent);
+
+ for (int i = 0; i < 4; ++i) {
+ QModelIndex index = model.index(0, 3 + i, table.rootIndex());
+ QVERIFY(hHeader->selectionModel()->selectedColumns().contains(index));
+ }
+ }
+
+ {
+ QRect cellRect = table.visualRect(model.index(2, 2));
+ QWidget *tableVp = table.viewport();
+ QPoint cellPos = cellRect.center();
+ QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(tableVp, &cellPressEvent);
+
+ for (int i = 0; i < 6; ++i) {
+ cellPos.setX(cellPos.x() + cellRect.width());
+ cellPos.setY(cellPos.y() + cellRect.height());
+ QMouseEvent moveEvent(QEvent::MouseMove, cellPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
+ qApp->sendEvent(tableVp, &moveEvent);
+ }
+ QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(tableVp, &cellReleaseEvent);
+
+ for (int i = 0; i < 6; ++i)
+ for (int j = 0; j < 6; ++j) {
+ QModelIndex index = model.index(2 + i, 2 + j, table.rootIndex());
+ QVERIFY(table.selectionModel()->isSelected(index));
+ }
+ }
+
+ {
+ QRect cellRect = table.visualRect(model.index(3, 3));
+ QWidget *tableVp = table.viewport();
+ QPoint cellPos = cellRect.center();
+ QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(tableVp, &cellPressEvent);
+
+ for (int i = 0; i < 6; ++i) {
+ cellPos.setX(cellPos.x() + cellRect.width());
+ cellPos.setY(cellPos.y() + cellRect.height());
+ QMouseEvent moveEvent(QEvent::MouseMove, cellPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
+ qApp->sendEvent(tableVp, &moveEvent);
+ }
+ QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
+ qApp->sendEvent(tableVp, &cellReleaseEvent);
+
+ QTest::qWait(200);
+ for (int i = 0; i < 6; ++i)
+ for (int j = 0; j < 6; ++j) {
+ QModelIndex index = model.index(3 + i, 3 + j, table.rootIndex());
+ QVERIFY(!table.selectionModel()->isSelected(index));
+ }
+ }
+}
+
+void tst_QTableView::task234926_setHeaderSorting()
+{
+ QStringListModel model;
+ QStringList data;
+ data << "orange" << "apple" << "banana" << "lemon" << "pumpkin";
+ QStringList sortedDataA = data;
+ QStringList sortedDataD = data;
+ qSort(sortedDataA);
+ qSort(sortedDataD.begin(), sortedDataD.end(), qGreater<QString>());
+ model.setStringList(data);
+ QTableView view;
+ view.setModel(&model);
+// view.show();
+ QTest::qWait(20);
+ QCOMPARE(model.stringList(), data);
+ view.setSortingEnabled(true);
+ view.sortByColumn(0, Qt::AscendingOrder);
+ QApplication::processEvents();
+ QCOMPARE(model.stringList() , sortedDataA);
+
+ view.horizontalHeader()->setSortIndicator(0, Qt::DescendingOrder);
+ QApplication::processEvents();
+ QCOMPARE(model.stringList() , sortedDataD);
+
+ QHeaderView *h = new QHeaderView(Qt::Horizontal);
+ h->setModel(&model);
+ view.setHorizontalHeader(h);
+ h->setSortIndicator(0, Qt::AscendingOrder);
+ QApplication::processEvents();
+ QCOMPARE(model.stringList() , sortedDataA);
+
+ h->setSortIndicator(0, Qt::DescendingOrder);
+ QApplication::processEvents();
+ QCOMPARE(model.stringList() , sortedDataD);
+}
+
+void tst_QTableView::taskQTBUG_5062_spansInconsistency()
+{
+ const int nRows = 5;
+ const int nColumns = 5;
+
+ QtTestTableModel model(nRows, nColumns);
+ QtTestTableView view;
+ view.setModel(&model);
+
+ for (int i = 0; i < nRows; ++i)
+ view.setSpan(i, 0, 1, nColumns);
+ view.setSpan(2, 0, 1, 1);
+ view.setSpan(3, 0, 1, 1);
+
+ VERIFY_SPANS_CONSISTENCY(&view);
+}
+
+void tst_QTableView::taskQTBUG_4516_clickOnRichTextLabel()
+{
+ QTableView view;
+ QStandardItemModel model(5,5);
+ view.setModel(&model);
+ QLabel label("rich text");
+ label.setTextFormat(Qt::RichText);
+ view.setIndexWidget(model.index(1,1), &label);
+ view.setCurrentIndex(model.index(0,0));
+ QCOMPARE(view.currentIndex(), model.index(0,0));
+
+ QTest::mouseClick(&label, Qt::LeftButton);
+ QCOMPARE(view.currentIndex(), model.index(1,1));
+
+
+}
+
+
+void tst_QTableView::changeHeaderData()
+{
+ QTableView view;
+ QStandardItemModel model(5,5);
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QString text = "long long long text";
+ const int textWidth = view.verticalHeader()->fontMetrics().width(text);
+ QVERIFY(view.verticalHeader()->width() < textWidth);
+
+ model.setHeaderData(2, Qt::Vertical, text);
+ QTest::qWait(100); //leave time for layout
+
+ QVERIFY(view.verticalHeader()->width() > textWidth);
+}
+
+void tst_QTableView::taskQTBUG_5237_wheelEventOnHeader()
+{
+ QTableView view;
+ QStandardItemModel model(500,5);
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ int sbValueBefore = view.verticalScrollBar()->value();
+ QHeaderView *header = view.verticalHeader();
+ QTest::mouseMove(header);
+ QWheelEvent wheelEvent(header->geometry().center(), -720, 0, 0);
+ QApplication::sendEvent(header->viewport(), &wheelEvent);
+ int sbValueAfter = view.verticalScrollBar()->value();
+ QVERIFY(sbValueBefore != sbValueAfter);
+}
+
+class TestTableView : public QTableView {
+Q_OBJECT
+public:
+ TestTableView(QWidget *parent = 0) : QTableView(parent)
+ {
+ connect(this, SIGNAL(entered(const QModelIndex&)), this, SLOT(openEditor(const QModelIndex&)));
+ }
+ ~TestTableView(){}
+public slots:
+ void onDataChanged()
+ {
+ for (int i = 0; i < model()->rowCount(); i++) {
+ setRowHidden(i, model()->data(model()->index(i, 0)).toBool());
+ }
+ }
+
+ void openEditor(const QModelIndex& index)
+ { openPersistentEditor(index); }
+};
+
+
+void tst_QTableView::taskQTBUG_8585_crashForNoGoodReason()
+{
+ QStandardItemModel model;
+ model.insertColumn(0, QModelIndex());
+ for(int i = 0; i < 20; i++)
+ {
+ model.insertRow(i);
+ }
+
+ TestTableView w;
+ w.setMouseTracking(true);
+ w.setModel(&model);
+ connect(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), &w, SLOT(onDataChanged()));
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ for (int i = 0; i < 10; i++)
+ {
+ QTest::mouseMove(w.viewport(), QPoint(50, 20));
+ w.model()->setData(w.indexAt(QPoint(50, 20)), true);
+ QTest::mouseMove(w.viewport(), QPoint(50, 25));
+ }
+}
+
+class TableView7774 : public QTableView
+{
+public:
+ QRegion visualRegionForSelection(const QItemSelection &selection) const
+ {
+ return QTableView::visualRegionForSelection(selection);
+ }
+};
+
+void tst_QTableView::taskQTBUG_7774_RtoLVisualRegionForSelection()
+{
+ TableView7774 view;
+ QStandardItemModel model(5,5);
+ view.setModel(&model);
+ view.setLayoutDirection(Qt::RightToLeft);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QItemSelectionRange range(model.index(2, 0), model.index(2, model.columnCount() - 1));
+ QItemSelection selection;
+ selection << range;
+ QRegion region = view.visualRegionForSelection(selection);
+ QCOMPARE(region.rects().at(0), view.visualRect(range.topLeft()) | view.visualRect(range.bottomRight()));
+}
+
+void tst_QTableView::taskQTBUG_8777_scrollToSpans()
+{
+ QTableWidget table(75,5);
+ for (int i=0; i<50; i++)
+ table.setSpan(2+i, 0, 1, 5);
+ table.setCurrentCell(0,2);
+ table.show();
+
+ for (int i = 0; i < 45; ++i)
+ QTest::keyClick(&table, Qt::Key_Down);
+
+ QVERIFY(table.verticalScrollBar()->value() > 10);
+}
+
+void tst_QTableView::taskQTBUG_10169_sizeHintForRow()
+{
+ QtTestTableView tableView;
+ QStandardItemModel model(1, 3);
+ model.setData(model.index(0, 0), "Word wrapping text goes here.");
+ tableView.setModel(&model);
+ tableView.verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+ const int orderedHeight = tableView.sizeHintForRow(0);
+ tableView.horizontalHeader()->moveSection(2, 0);
+ const int reorderedHeight = tableView.sizeHintForRow(0);
+
+ //the order of the columns shouldn't matter.
+ QCOMPARE(orderedHeight, reorderedHeight);
+}
+
+QTEST_MAIN(tst_QTableView)
+#include "tst_qtableview.moc"
diff --git a/tests/auto/widgets/itemviews/qtablewidget/.gitignore b/tests/auto/widgets/itemviews/qtablewidget/.gitignore
new file mode 100644
index 0000000000..13a9c67c0a
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtablewidget/.gitignore
@@ -0,0 +1 @@
+tst_qtablewidget
diff --git a/tests/auto/widgets/itemviews/qtablewidget/qtablewidget.pro b/tests/auto/widgets/itemviews/qtablewidget/qtablewidget.pro
new file mode 100644
index 0000000000..eff12c83dc
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtablewidget/qtablewidget.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtablewidget.cpp
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
new file mode 100644
index 0000000000..6c32caadbb
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -0,0 +1,1500 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qeventloop.h>
+#include <qlist.h>
+#include <qpair.h>
+#include <qheaderview.h>
+
+#include <qtablewidget.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class QObjectTableItem : public QObject, public QTableWidgetItem
+{
+ Q_OBJECT
+};
+
+class tst_QTableWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTableWidget();
+ ~tst_QTableWidget();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void clear();
+ void clearContents();
+ void rowCount();
+ void columnCount();
+ void itemAssignment();
+ void item_data();
+ void item();
+ void takeItem_data();
+ void takeItem();
+ void selectedItems_data();
+ void selectedItems();
+ void removeRow_data();
+ void removeRow();
+ void removeColumn_data();
+ void removeColumn();
+ void insertRow_data();
+ void insertRow();
+ void insertColumn_data();
+ void insertColumn();
+ void itemStreaming_data();
+ void itemStreaming();
+ void itemOwnership();
+ void sortItems_data();
+ void sortItems();
+ void setItemWithSorting_data();
+ void setItemWithSorting();
+ void itemData();
+ void setItemData();
+ void cellWidget();
+ void task231094();
+ void task219380_removeLastRow();
+ void task262056_sortDuplicate();
+
+private:
+ QTableWidget *testWidget;
+};
+
+typedef QPair<int, int> IntPair;
+typedef QList<int> IntList;
+typedef QList<IntPair> IntIntList;
+
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(IntIntList)
+Q_DECLARE_METATYPE(QTableWidgetSelectionRange)
+Q_DECLARE_METATYPE(QModelIndex)
+
+
+// Testing get/set functions
+void tst_QTableWidget::getSetCheck()
+{
+ QTableWidget obj1;
+ // int QTableWidget::rowCount()
+ // void QTableWidget::setRowCount(int)
+ obj1.setRowCount(0);
+ QCOMPARE(0, obj1.rowCount());
+ obj1.setRowCount(INT_MIN);
+ QCOMPARE(0, obj1.rowCount()); // Row count can never be negative
+// obj1.setRowCount(INT_MAX);
+// QCOMPARE(INT_MAX, obj1.rowCount());
+ obj1.setRowCount(100);
+ QCOMPARE(100, obj1.rowCount());
+
+
+ // int QTableWidget::columnCount()
+ // void QTableWidget::setColumnCount(int)
+ obj1.setColumnCount(0);
+ QCOMPARE(0, obj1.columnCount());
+ obj1.setColumnCount(INT_MIN);
+ QCOMPARE(0, obj1.columnCount()); // Column count can never be negative
+ obj1.setColumnCount(1000);
+ QCOMPARE(1000, obj1.columnCount());
+// obj1.setColumnCount(INT_MAX);
+// QCOMPARE(INT_MAX, obj1.columnCount());
+
+ // QTableWidgetItem * QTableWidget::currentItem()
+ // void QTableWidget::setCurrentItem(QTableWidgetItem *)
+ QTableWidgetItem *var3 = new QTableWidgetItem("0,0");
+ obj1.setItem(0, 0, var3);
+ obj1.setItem(1, 1, new QTableWidgetItem("1,1"));
+ obj1.setItem(2, 2, new QTableWidgetItem("2,2"));
+ obj1.setItem(3, 3, new QTableWidgetItem("3,3"));
+ obj1.setCurrentItem(var3);
+ QCOMPARE(var3, obj1.currentItem());
+ obj1.setCurrentItem((QTableWidgetItem *)0);
+ QCOMPARE((QTableWidgetItem *)0, obj1.currentItem());
+ obj1.setItem(0, 0, 0);
+ QCOMPARE((QTableWidgetItem *)0, obj1.item(0, 0));
+
+ // const QTableWidgetItem * QTableWidget::itemPrototype()
+ // void QTableWidget::setItemPrototype(const QTableWidgetItem *)
+ const QTableWidgetItem *var4 = new QTableWidgetItem;
+ obj1.setItemPrototype(var4);
+ QCOMPARE(var4, obj1.itemPrototype());
+ obj1.setItemPrototype((QTableWidgetItem *)0);
+ QCOMPARE((const QTableWidgetItem *)0, obj1.itemPrototype());
+}
+
+tst_QTableWidget::tst_QTableWidget(): testWidget(0)
+{
+}
+
+tst_QTableWidget::~tst_QTableWidget()
+{
+}
+
+void tst_QTableWidget::initTestCase()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ testWidget = new QTableWidget();
+ testWidget->show();
+}
+
+void tst_QTableWidget::cleanupTestCase()
+{
+ delete testWidget;
+}
+
+void tst_QTableWidget::init()
+{
+ testWidget->clear();
+ testWidget->setRowCount(5);
+ testWidget->setColumnCount(5);
+
+ for (int row=0; row < testWidget->rowCount(); ++row)
+ testWidget->showRow(row);
+ for (int column=0; column < testWidget->columnCount(); ++column)
+ testWidget->showColumn(column);
+}
+
+void tst_QTableWidget::cleanup()
+{
+
+}
+
+void tst_QTableWidget::clearContents()
+{
+ QTableWidgetItem *item = new QTableWidgetItem("test");
+ testWidget->setHorizontalHeaderItem(0, item);
+ QVERIFY(testWidget->horizontalHeaderItem(0) == item);
+ testWidget->clearContents();
+ QVERIFY(testWidget->horizontalHeaderItem(0) == item);
+}
+
+void tst_QTableWidget::clear()
+{
+ QTableWidgetItem *item = new QTableWidgetItem("foo");
+ testWidget->setItem(0, 0, item);
+ testWidget->setItemSelected(item, true);
+
+ QVERIFY(testWidget->item(0, 0) == item);
+ QVERIFY(testWidget->isItemSelected(item));
+
+
+ QPointer<QObjectTableItem> bla = new QObjectTableItem();
+ testWidget->setItem(1, 1, bla);
+
+ testWidget->clear();
+
+ QVERIFY(bla.isNull());
+
+ QVERIFY(!testWidget->item(0,0));
+ QVERIFY(!testWidget->selectedRanges().count());
+ QVERIFY(!testWidget->selectedItems().count());
+}
+
+void tst_QTableWidget::rowCount()
+{
+ int rowCountBefore = 5;
+ int rowCountAfter = 10;
+
+ int rowCount = testWidget->rowCount();
+ QCOMPARE(rowCount, rowCountBefore);
+
+ testWidget->setRowCount(rowCountAfter);
+ rowCount = testWidget->rowCount();
+ QCOMPARE(rowCount, rowCountAfter);
+
+ QPersistentModelIndex index(testWidget->model()->index(rowCountAfter - 1, 0,
+ testWidget->rootIndex()));
+ QCOMPARE(index.row(), rowCountAfter - 1);
+ QCOMPARE(index.column(), 0);
+ QVERIFY(index.isValid());
+ testWidget->setRowCount(rowCountBefore);
+ QCOMPARE(index.row(), -1);
+ QCOMPARE(index.column(), -1);
+ QVERIFY(!index.isValid());
+
+ rowCountBefore = testWidget->rowCount();
+ testWidget->setRowCount(-1);
+ QCOMPARE(testWidget->rowCount(), rowCountBefore);
+}
+
+void tst_QTableWidget::columnCount()
+{
+ int columnCountBefore = 5;
+ int columnCountAfter = 10;
+
+ int columnCount = testWidget->columnCount();
+ QCOMPARE(columnCount, columnCountBefore);
+
+ testWidget->setColumnCount(columnCountAfter);
+ columnCount = testWidget->columnCount();
+ QCOMPARE(columnCount, columnCountAfter);
+
+ QPersistentModelIndex index(testWidget->model()->index(0, columnCountAfter - 1,
+ testWidget->rootIndex()));
+ QCOMPARE(index.row(), 0);
+ QCOMPARE(index.column(), columnCountAfter - 1);
+ QVERIFY(index.isValid());
+ testWidget->setColumnCount(columnCountBefore);
+ QCOMPARE(index.row(), -1);
+ QCOMPARE(index.column(), -1);
+ QVERIFY(!index.isValid());
+
+ columnCountBefore = testWidget->columnCount();
+ testWidget->setColumnCount(-1);
+ QCOMPARE(testWidget->columnCount(), columnCountBefore);
+}
+
+void tst_QTableWidget::itemAssignment()
+{
+ QTableWidgetItem itemInWidget("inWidget");
+ testWidget->setItem(0, 0, &itemInWidget);
+ itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsTristate);
+ QTableWidgetItem itemOutsideWidget("outsideWidget");
+
+ QVERIFY(itemInWidget.tableWidget());
+ QCOMPARE(itemInWidget.text(), QString("inWidget"));
+ QVERIFY(itemInWidget.flags() & Qt::ItemIsTristate);
+
+ QVERIFY(!itemOutsideWidget.tableWidget());
+ QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
+ QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsTristate));
+
+ itemOutsideWidget = itemInWidget;
+ QVERIFY(!itemOutsideWidget.tableWidget());
+ QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
+ QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsTristate);
+}
+
+void tst_QTableWidget::item_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<bool>("expectItem");
+
+ QTest::newRow("0x0 take [0,0]") << 0 << 0 << 0 << 0 << false;
+ QTest::newRow("0x0 take [4,4]") << 0 << 0 << 4 << 4 << false;
+ QTest::newRow("4x4 take [0,0]") << 4 << 4 << 0 << 0 << true;
+ QTest::newRow("4x4 take [4,4]") << 4 << 4 << 4 << 4 << false;
+ QTest::newRow("4x4 take [2,2]") << 4 << 4 << 2 << 2 << true;
+}
+
+void tst_QTableWidget::item()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(bool, expectItem);
+
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int c = 0; c < testWidget->columnCount(); ++c)
+ testWidget->setItem(r, c, new QTableWidgetItem(QString::number(r * c + c)));
+
+ for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int c = 0; c < testWidget->columnCount(); ++c)
+ QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
+
+ QTableWidgetItem *item = testWidget->item(row, column);
+ QCOMPARE(!!item, expectItem);
+ if (expectItem)
+ QCOMPARE(item->text(), QString::number(row * column + column));
+}
+
+void tst_QTableWidget::takeItem_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<bool>("expectItem");
+
+ QTest::newRow("0x0 take [0,0]") << 0 << 0 << 0 << 0 << false;
+ QTest::newRow("0x0 take [4,4]") << 0 << 0 << 4 << 4 << false;
+ QTest::newRow("4x4 take [0,0]") << 4 << 4 << 0 << 0 << true;
+ QTest::newRow("4x4 take [4,4]") << 4 << 4 << 4 << 4 << false;
+ QTest::newRow("4x4 take [2,2]") << 4 << 4 << 2 << 2 << true;
+}
+
+void tst_QTableWidget::takeItem()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(bool, expectItem);
+
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int c = 0; c < testWidget->columnCount(); ++c)
+ testWidget->setItem(r, c, new QTableWidgetItem(QString::number(r * c + c)));
+
+ for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int c = 0; c < testWidget->columnCount(); ++c)
+ QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
+
+ QTableWidgetItem *item = testWidget->takeItem(row, column);
+ QCOMPARE(!!item, expectItem);
+ if (expectItem) {
+ QCOMPARE(item->text(), QString::number(row * column + column));
+ delete item;
+ }
+ QVERIFY(!testWidget->takeItem(row, column));
+}
+
+void tst_QTableWidget::selectedItems_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<IntIntList>("createItems");
+ QTest::addColumn<IntList>("hiddenRows");
+ QTest::addColumn<IntList>("hiddenColumns");
+ QTest::addColumn<QTableWidgetSelectionRange>("selectionRange");
+ QTest::addColumn<IntIntList>("expectedItems");
+
+ QTest::newRow("3x3 empty cells, no hidden rows/columns, none selected")
+ << 3 << 3
+ << IntIntList()
+ << IntList()
+ << IntList()
+ << QTableWidgetSelectionRange()
+ << IntIntList();
+
+ QTest::newRow("3x3 empty cells,no hidden rows/columnms, all selected")
+ << 3 << 3
+ << IntIntList()
+ << IntList()
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << IntIntList();
+
+ QTest::newRow("3x3 (1,1) exists, no hidden rows/columnms, all selected")
+ << 3 << 3
+ << (IntIntList() << IntPair(1,1))
+ << IntList()
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << (IntIntList() << IntPair(1,1));
+
+ QTest::newRow("3x3 (1,1) exists, row 1 hidden, all selected")
+ << 3 << 3
+ << (IntIntList() << IntPair(1,1))
+ << (IntList() << 1)
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << IntIntList();
+
+ QTest::newRow("3x3 (1,1) exists, column 1 hidden, all selected")
+ << 3 << 3
+ << (IntIntList() << IntPair(1,1))
+ << IntList()
+ << (IntList() << 1)
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << IntIntList();
+
+ QTest::newRow("3x3 all exists, no hidden rows/columns, all selected")
+ << 3 << 3
+ << (IntIntList()
+ << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+ << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
+ << IntPair(2,0) << IntPair(2,1) << IntPair(2,2))
+ << IntList()
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << (IntIntList()
+ << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+ << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
+ << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
+
+ QTest::newRow("3x3 all exists, row 1 hidden, all selected")
+ << 3 << 3
+ << (IntIntList()
+ << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+ << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
+ << IntPair(2,0) << IntPair(2,1) << IntPair(2,2))
+ << (IntList() << 1)
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << (IntIntList()
+ << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+ << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
+
+ QTest::newRow("3x3 all exists, column 1 hidden, all selected")
+ << 3 << 3
+ << (IntIntList()
+ << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+ << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
+ << IntPair(2,0) << IntPair(2,1) << IntPair(2,2))
+ << IntList()
+ << (IntList() << 1)
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << (IntIntList()
+ << IntPair(0,0) << IntPair(0,2)
+ << IntPair(1,0) << IntPair(1,2)
+ << IntPair(2,0) << IntPair(2,2));
+
+ QTest::newRow("3x3 none exists, no hidden rows/columns, all selected")
+ << 3 << 3
+ << IntIntList()
+ << IntList()
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << IntIntList();
+// << (IntIntList()
+// << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+// << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
+// << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
+
+ QTest::newRow("3x3 none exists, row 1 hidden, all selected, filling empty cells")
+ << 3 << 3
+ << IntIntList()
+ << (IntList() << 1)
+ << IntList()
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << IntIntList();
+// << (IntIntList()
+// << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
+// << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
+
+ QTest::newRow("3x3 none exists, column 1 hidden, all selected")
+ << 3 << 3
+ << IntIntList()
+ << IntList()
+ << (IntList() << 1)
+ << QTableWidgetSelectionRange(0, 0, 2, 2)
+ << IntIntList();
+// << (IntIntList()
+// << IntPair(0,0) << IntPair(0,2)
+// << IntPair(1,0) << IntPair(1,2)
+// << IntPair(2,0) << IntPair(2,2));
+}
+
+void tst_QTableWidget::selectedItems()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(IntIntList, createItems);
+ QFETCH(IntList, hiddenRows);
+ QFETCH(IntList, hiddenColumns);
+ QFETCH(QTableWidgetSelectionRange, selectionRange);
+ QFETCH(IntIntList, expectedItems);
+
+ // set dimensions and test they are ok
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ // create and set items
+ foreach (IntPair intPair, createItems) {
+ testWidget->setItem(intPair.first, intPair.second,
+ new QTableWidgetItem(QString("Item %1 %2")
+ .arg(intPair.first).arg(intPair.second)));
+ }
+ // hide rows/columns
+ foreach (int row, hiddenRows)
+ testWidget->setRowHidden(row, true);
+ foreach (int column, hiddenColumns)
+ testWidget->setColumnHidden(column, true);
+
+ // make sure we don't have any previous selections hanging around
+ QVERIFY(!testWidget->selectedRanges().count());
+ QVERIFY(!testWidget->selectedItems().count());
+
+ // select range and check that it is set correctly
+ testWidget->setRangeSelected(selectionRange, true);
+ if (selectionRange.topRow() >= 0) {
+ QCOMPARE(testWidget->selectedRanges().count(), 1);
+ QCOMPARE(testWidget->selectedRanges().at(0).topRow(), selectionRange.topRow());
+ QCOMPARE(testWidget->selectedRanges().at(0).bottomRow(), selectionRange.bottomRow());
+ QCOMPARE(testWidget->selectedRanges().at(0).leftColumn(), selectionRange.leftColumn());
+ QCOMPARE(testWidget->selectedRanges().at(0).rightColumn(), selectionRange.rightColumn());
+ } else {
+ QCOMPARE(testWidget->selectedRanges().count(), 0);
+ }
+
+ // check that the correct number of items and the expected items are there
+ QList<QTableWidgetItem *> selectedItems = testWidget->selectedItems();
+ QCOMPARE(selectedItems.count(), expectedItems.count());
+ foreach (IntPair intPair, expectedItems)
+ QVERIFY(selectedItems.contains(testWidget->item(intPair.first, intPair.second)));
+
+ // check that setItemSelected agrees with selectedItems
+ for (int row = 0; row<testWidget->rowCount(); ++row) {
+ bool hidden = false;
+ foreach (int hiddenRow, hiddenRows){
+ if(hiddenRow == row){
+ hidden = true;
+ break;
+ }
+ }
+ if (hidden)
+ continue;
+
+ for (int column = 0; column<testWidget->columnCount(); ++column) {
+ foreach (int hiddenColumn, hiddenColumns){
+ if(hiddenColumn == column){
+ hidden = true;
+ break;
+ }
+ }
+ if (hidden)
+ continue;
+
+ QTableWidgetItem *item = testWidget->item(row, column);
+ if (item && testWidget->isItemSelected(item))
+ QVERIFY(selectedItems.contains(item));
+ }
+ }
+}
+
+void tst_QTableWidget::removeRow_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("expectedRowCount");
+ QTest::addColumn<int>("expectedColumnCount");
+
+ QTest::newRow("Empty") << 0 << 0 << 0 << 0 << 0;
+ QTest::newRow("1x1:0") << 1 << 1 << 0 << 0 << 1;
+ QTest::newRow("3x3:0") << 3 << 3 << 0 << 2 << 3;
+ QTest::newRow("3x3:1") << 3 << 3 << 1 << 2 << 3;
+ QTest::newRow("3x3:2") << 3 << 3 << 2 << 2 << 3;
+}
+
+void tst_QTableWidget::removeRow()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, expectedRowCount);
+ QFETCH(int, expectedColumnCount);
+
+ // set dimensions and test they are ok
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ // fill table with items
+ for (int r = 0; r < rowCount; ++r)
+ for (int c = 0; c < columnCount; ++c)
+ testWidget->setItem(r, c,
+ new QTableWidgetItem(
+ QString::number(r) + ":" + QString::number(c)));
+
+ // remove and compare the results
+ testWidget->removeRow(row);
+ QCOMPARE(testWidget->rowCount(), expectedRowCount);
+ QCOMPARE(testWidget->columnCount(), expectedColumnCount);
+
+ // check if the correct items were removed
+ for (int r = 0; r < expectedRowCount; ++r)
+ for (int c = 0; c < expectedColumnCount; ++c)
+ if (r < row)
+ QCOMPARE(testWidget->item(r, c)->text(),
+ QString::number(r) + ":" + QString::number(c));
+ else
+ QCOMPARE(testWidget->item(r, c)->text(),
+ QString::number(r + 1) + ":" + QString::number(c));
+}
+
+void tst_QTableWidget::removeColumn_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("expectedRowCount");
+ QTest::addColumn<int>("expectedColumnCount");
+
+ QTest::newRow("Empty") << 0 << 0 << 0 << 0 << 0;
+ QTest::newRow("1x1:0") << 1 << 1 << 0 << 1 << 0;
+ QTest::newRow("3x3:0") << 3 << 3 << 0 << 3 << 2;
+ QTest::newRow("3x3:1") << 3 << 3 << 1 << 3 << 2;
+ QTest::newRow("3x3:2") << 3 << 3 << 2 << 3 << 2;
+}
+
+void tst_QTableWidget::removeColumn()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, column);
+ QFETCH(int, expectedRowCount);
+ QFETCH(int, expectedColumnCount);
+
+ // set dimensions and test they are ok
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ // fill table with items
+ for (int r = 0; r < rowCount; ++r)
+ for (int c = 0; c < columnCount; ++c)
+ testWidget->setItem(r, c,
+ new QTableWidgetItem(
+ QString::number(r) + ":" + QString::number(c)));
+
+ // remove and compare the results
+ testWidget->removeColumn(column);
+ QCOMPARE(testWidget->rowCount(), expectedRowCount);
+ QCOMPARE(testWidget->columnCount(), expectedColumnCount);
+
+
+ // check if the correct items were removed
+ for (int r = 0; r < expectedRowCount; ++r)
+ for (int c = 0; c < expectedColumnCount; ++c)
+ if (c < column)
+ QCOMPARE(testWidget->item(r, c)->text(),
+ QString::number(r) + ":" + QString::number(c));
+ else
+ QCOMPARE(testWidget->item(r, c)->text(),
+ QString::number(r) + ":" + QString::number(c + 1));
+}
+
+void tst_QTableWidget::insertRow_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("expectedRowCount");
+ QTest::addColumn<int>("expectedColumnCount");
+
+ QTest::newRow("Empty") << 0 << 0 << 0 << 1 << 0;
+ QTest::newRow("1x1:0") << 1 << 1 << 0 << 2 << 1;
+ QTest::newRow("3x3:-1") << 3 << 3 << -1 << 3 << 3;
+ QTest::newRow("3x3:0") << 3 << 3 << 0 << 4 << 3;
+ QTest::newRow("3x3:1") << 3 << 3 << 1 << 4 << 3;
+ QTest::newRow("3x3:2") << 3 << 3 << 2 << 4 << 3;
+ QTest::newRow("3x3:3") << 3 << 3 << 3 << 4 << 3;
+ QTest::newRow("3x3:4") << 3 << 3 << 4 << 3 << 3;
+}
+
+void tst_QTableWidget::insertRow()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, row);
+ QFETCH(int, expectedRowCount);
+ QFETCH(int, expectedColumnCount);
+
+ // set dimensions and test they are ok
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ // insert and compare the results
+ testWidget->insertRow(row);
+ QCOMPARE(testWidget->rowCount(), expectedRowCount);
+ QCOMPARE(testWidget->columnCount(), expectedColumnCount);
+}
+
+void tst_QTableWidget::insertColumn_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("expectedRowCount");
+ QTest::addColumn<int>("expectedColumnCount");
+
+ QTest::newRow("Empty") << 0 << 0 << 0 << 0 << 1;
+ QTest::newRow("1x1:0") << 1 << 1 << 0 << 1 << 2;
+ QTest::newRow("3x3:-1") << 3 << 3 << -1 << 3 << 3;
+ QTest::newRow("3x3:0") << 3 << 3 << 0 << 3 << 4;
+ QTest::newRow("3x3:1") << 3 << 3 << 1 << 3 << 4;
+ QTest::newRow("3x3:2") << 3 << 3 << 2 << 3 << 4;
+ QTest::newRow("3x3:3") << 3 << 3 << 3 << 3 << 4;
+ QTest::newRow("3x3:4") << 3 << 3 << 4 << 3 << 3;
+}
+
+void tst_QTableWidget::insertColumn()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, column);
+ QFETCH(int, expectedRowCount);
+ QFETCH(int, expectedColumnCount);
+
+ // set dimensions and test they are ok
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+ QCOMPARE(testWidget->rowCount(), rowCount);
+ QCOMPARE(testWidget->columnCount(), columnCount);
+
+ // insert and compare the results
+ testWidget->insertColumn(column);
+ QCOMPARE(testWidget->rowCount(), expectedRowCount);
+ QCOMPARE(testWidget->columnCount(), expectedColumnCount);
+}
+
+void tst_QTableWidget::itemStreaming_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("toolTip");
+
+ QTest::newRow("Data") << "item text" << "tool tip text";
+}
+
+void tst_QTableWidget::itemStreaming()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, toolTip);
+
+ QTableWidgetItem item;
+ QCOMPARE(item.text(), QString());
+ QCOMPARE(item.toolTip(), QString());
+
+ item.setText(text);
+ item.setToolTip(toolTip);
+ QCOMPARE(item.text(), text);
+ QCOMPARE(item.toolTip(), toolTip);
+
+ QByteArray buffer;
+ QDataStream out(&buffer, QIODevice::WriteOnly);
+ out << item;
+
+ QTableWidgetItem item2;
+ QCOMPARE(item2.text(), QString());
+ QCOMPARE(item2.toolTip(), QString());
+
+ QVERIFY(!buffer.isEmpty());
+
+ QDataStream in(&buffer, QIODevice::ReadOnly);
+ in >> item2;
+ QCOMPARE(item2.text(), text);
+ QCOMPARE(item2.toolTip(), toolTip);
+}
+
+void tst_QTableWidget::itemOwnership()
+{
+ QPointer<QObjectTableItem> item;
+ QPointer<QObjectTableItem> headerItem;
+
+ //delete from outside
+ item = new QObjectTableItem();
+ testWidget->setItem(0, 0, item);
+ delete item;
+ QCOMPARE(testWidget->item(0, 0), (QTableWidgetItem *)0);
+
+ //delete vertical headeritem from outside
+ headerItem = new QObjectTableItem();
+ testWidget->setVerticalHeaderItem(0, headerItem);
+ delete headerItem;
+ QCOMPARE(testWidget->verticalHeaderItem(0), (QTableWidgetItem *)0);
+
+ //delete horizontal headeritem from outside
+ headerItem = new QObjectTableItem();
+ testWidget->setHorizontalHeaderItem(0, headerItem);
+ delete headerItem;
+ QCOMPARE(testWidget->horizontalHeaderItem(0), (QTableWidgetItem *)0);
+
+ //setItem
+ item = new QObjectTableItem();
+ testWidget->setItem(0, 0, item);
+ testWidget->setItem(0, 0, new QTableWidgetItem());
+ QVERIFY(item.isNull());
+
+ //setHorizontalHeaderItem
+ headerItem = new QObjectTableItem();
+ testWidget->setHorizontalHeaderItem(0, headerItem);
+ testWidget->setHorizontalHeaderItem(0, new QTableWidgetItem());
+ QVERIFY(headerItem.isNull());
+
+ //setVerticalHeaderItem
+ headerItem = new QObjectTableItem();
+ testWidget->setVerticalHeaderItem(0, headerItem);
+ testWidget->setVerticalHeaderItem(0, new QTableWidgetItem());
+ QVERIFY(headerItem.isNull());
+
+ //takeItem
+ item = new QObjectTableItem();
+ testWidget->setItem(0, 0, item);
+ testWidget->takeItem(0, 0);
+ QVERIFY(!item.isNull());
+ delete item;
+
+ // removeRow
+ item = new QObjectTableItem();
+ headerItem = new QObjectTableItem();
+ testWidget->setItem(0, 0, item);
+ testWidget->setVerticalHeaderItem(0, headerItem);
+ testWidget->removeRow(0);
+ QVERIFY(item.isNull());
+ QVERIFY(headerItem.isNull());
+
+ // removeColumn
+ item = new QObjectTableItem();
+ headerItem = new QObjectTableItem();
+ testWidget->setItem(0, 0, item);
+ testWidget->setHorizontalHeaderItem(0, headerItem);
+ testWidget->removeColumn(0);
+ QVERIFY(item.isNull());
+ QVERIFY(headerItem.isNull());
+
+ // clear
+ item = new QObjectTableItem();
+ testWidget->setItem(0, 0, item);
+ testWidget->clear();
+ QVERIFY(item.isNull());
+}
+
+void tst_QTableWidget::sortItems_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<int>("sortColumn");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+ QTest::addColumn<IntList>("rows");
+ QTest::addColumn<IntList>("initialHidden");
+ QTest::addColumn<IntList>("expectedHidden");
+
+ QTest::newRow("ascending")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "1" << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "1" << "b" << "7" << "3" << "u"
+ << "2" << "c" << "9" << "y" << "8"
+ << "3" << "d" << "k" << "o" << "6")
+ << (IntList() << 0 << 3 << 2 << 1)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("descending")
+ << 4 << 5
+ << static_cast<int>(Qt::DescendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "1" << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "1" << "b" << "7" << "3" << "u"
+ << "0" << "a" << "o" << "8" << "k")
+ << (IntList() << 3 << 0 << 1 << 2)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("empty table")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << 0 << 0 << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0)
+ << (QStringList()
+ << 0 << 0 << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0)
+ << IntList()
+ << IntList()
+ << IntList();
+
+
+ QTest::newRow("half-empty table")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << 0 << 0 << 0 << 0
+ << "3" << "d" << 0 << 0 << 0
+ << "2" << "c" << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0)
+ << (QStringList()
+ << "0" << 0 << 0 << 0 << 0
+ << "2" << "c" << 0 << 0 << 0
+ << "3" << "d" << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0)
+ << (IntList() << 0 << 2 << 1)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("empty column, should not sort.")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 3
+ << (QStringList()
+ << "0" << 0 << 0 << 0 << 0
+ << "3" << "d" << 0 << 0 << 0
+ << "2" << "c" << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0)
+ << (QStringList()
+ << "0" << 0 << 0 << 0 << 0
+ << "3" << "d" << 0 << 0 << 0
+ << "2" << "c" << 0 << 0 << 0
+ << 0 << 0 << 0 << 0 << 0)
+ << IntList()
+ << IntList()
+ << IntList();
+
+ QTest::newRow("descending with null cell, the null cell should be placed at the bottom")
+ << 4 << 5
+ << static_cast<int>(Qt::DescendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << 0 << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "0" << "a" << "o" << "8" << "k"
+ << 0 << "b" << "7" << "3" << "u")
+ << (IntList() << 2 << 0 << 1)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("ascending with null cell, the null cell should be placed at the bottom")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << 0 << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "2" << "c" << "9" << "y" << "8"
+ << "3" << "d" << "k" << "o" << "6"
+ << 0 << "b" << "7" << "3" << "u")
+ << (IntList() << 0 << 2 << 1)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("ascending with null cells, the null cells should be placed at the bottom")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << "3" << "d" << "k" << "o" << "6"
+ << "0" << "a" << "o" << "8" << "k"
+ << 0 << "c" << "9" << "y" << "8"
+ << 0 << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << 0 << "c" << "9" << "y" << "8"
+ << 0 << "b" << "7" << "3" << "u")
+ << (IntList() << 1 << 0)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("ascending... Check a bug in PersistentIndexes")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << "3" << "c" << "9" << "y" << "8"
+ << "2" << "b" << "7" << "3" << "u"
+ << "4" << "d" << "k" << "o" << "6"
+ << "1" << "a" << "o" << "8" << "k"
+ )
+ << (QStringList()
+ << "1" << "a" << "o" << "8" << "k"
+ << "2" << "b" << "7" << "3" << "u"
+ << "3" << "c" << "9" << "y" << "8"
+ << "4" << "d" << "k" << "o" << "6"
+ )
+ << (IntList() << 2 << 1 << 3 << 0)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("ascending with some null cells inbetween")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << 0 << "a" << "o" << "8" << "k"
+ << "2" << "c" << "9" << "y" << "8"
+ << 0 << "d" << "k" << "o" << "6"
+ << "1" << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "1" << "b" << "7" << "3" << "u"
+ << "2" << "c" << "9" << "y" << "8"
+ << 0 << "a" << "o" << "8" << "k"
+ << 0 << "d" << "k" << "o" << "6")
+ << (IntList() << 1 << 0)
+ << IntList()
+ << IntList();
+
+ QTest::newRow("ascending hidden")
+ << 4 << 5
+ << static_cast<int>(Qt::AscendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "1" << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "1" << "b" << "7" << "3" << "u"
+ << "2" << "c" << "9" << "y" << "8"
+ << "3" << "d" << "k" << "o" << "6")
+ << (IntList() << 0 << 3 << 2 << 1)
+ << (IntList() << 0 << 2)
+ << (IntList() << 0 << 2);
+
+ QTest::newRow("descending hidden")
+ << 4 << 5
+ << static_cast<int>(Qt::DescendingOrder)
+ << 0
+ << (QStringList()
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "1" << "b" << "7" << "3" << "u")
+ << (QStringList()
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "1" << "b" << "7" << "3" << "u"
+ << "0" << "a" << "o" << "8" << "k")
+ << (IntList() << 3 << 0 << 1 << 2)
+ << (IntList() << 0 << 2)
+ << (IntList() << 3 << 1);
+}
+
+void tst_QTableWidget::sortItems()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, sortOrder);
+ QFETCH(int, sortColumn);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ QFETCH(IntList, rows);
+ QFETCH(IntList, initialHidden);
+ QFETCH(IntList, expectedHidden);
+
+ testWidget->setRowCount(rowCount);
+ testWidget->setColumnCount(columnCount);
+
+ QAbstractItemModel *model = testWidget->model();
+ QList<QPersistentModelIndex> persistent;
+
+ int ti = 0;
+ for (int r = 0; r < rowCount; ++r) {
+ for (int c = 0; c < columnCount; ++c) {
+ QString str = initial.at(ti++);
+ if (!str.isNull()) {
+ testWidget->setItem(r, c, new QTableWidgetItem(str));
+ }
+ }
+ if (testWidget->item(r, sortColumn))
+ persistent << model->index(r, sortColumn, QModelIndex());
+ }
+
+ for (int h = 0; h < initialHidden.count(); ++h)
+ testWidget->hideRow(initialHidden.at(h));
+
+ QCOMPARE(testWidget->verticalHeader()->hiddenSectionCount(), initialHidden.count());
+
+ testWidget->sortItems(sortColumn, static_cast<Qt::SortOrder>(sortOrder));
+
+ int te = 0;
+ for (int i = 0; i < rows.count(); ++i) {
+ for (int j = 0; j < columnCount; ++j) {
+ QString value;
+ QTableWidgetItem *itm = testWidget->item(i, j);
+ if (itm) {
+ value = itm->text();
+ }
+ QCOMPARE(value, expected.at(te++));
+ }
+ QCOMPARE(persistent.at(i).row(), rows.at(i));
+ //qDebug() << "persistent" << persistent.at(i).row()
+ // << "expected" << rows.at(i);
+ }
+
+ for (int k = 0; k < expectedHidden.count(); ++k)
+ QVERIFY(testWidget->isRowHidden(expectedHidden.at(k)));
+}
+
+void tst_QTableWidget::setItemWithSorting_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("columnCount");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<int>("sortColumn");
+ QTest::addColumn<QStringList>("initialValues");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<QString>("newValue");
+ QTest::addColumn<QStringList>("expectedValues");
+ QTest::addColumn<IntList>("expectedRows");
+ QTest::addColumn<bool>("reorderingExpected");
+
+ QTest::newRow("2x1 no change (ascending)")
+ << 2 << 1
+ << static_cast<int>(Qt::AscendingOrder) << 0
+ << (QStringList() << "0" << "1")
+ << 1 << 0 << "2"
+ << (QStringList() << "0" << "2")
+ << (IntList() << 0 << 1)
+ << false;
+ QTest::newRow("2x1 no change (descending)")
+ << 2 << 1
+ << static_cast<int>(Qt::DescendingOrder) << 0
+ << (QStringList() << "1" << "0")
+ << 0 << 0 << "2"
+ << (QStringList() << "2" << "0")
+ << (IntList() << 0 << 1)
+ << false;
+ QTest::newRow("2x1 reorder (ascending)")
+ << 2 << 1
+ << static_cast<int>(Qt::AscendingOrder) << 0
+ << (QStringList() << "0" << "1")
+ << 0 << 0 << "2"
+ << (QStringList() << "1" << "2")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("2x1 reorder (descending)")
+ << 2 << 1
+ << static_cast<int>(Qt::DescendingOrder) << 0
+ << (QStringList() << "1" << "0")
+ << 1 << 0 << "2"
+ << (QStringList() << "2" << "1")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("2x2 no change (ascending)")
+ << 2 << 2
+ << static_cast<int>(Qt::AscendingOrder) << 0
+ << (QStringList()
+ << "0" << "00"
+ << "1" << "11")
+ << 1 << 0 << "2"
+ << (QStringList()
+ << "0" << "00"
+ << "2" << "11")
+ << (IntList() << 0 << 1)
+ << false;
+ QTest::newRow("2x2 reorder (ascending)")
+ << 2 << 2
+ << static_cast<int>(Qt::AscendingOrder) << 0
+ << (QStringList()
+ << "0" << "00"
+ << "1" << "11")
+ << 0 << 0 << "2"
+ << (QStringList()
+ << "1" << "11"
+ << "2" << "00")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("2x2 reorder (ascending, sortColumn = 1)")
+ << 2 << 2
+ << static_cast<int>(Qt::AscendingOrder) << 1
+ << (QStringList()
+ << "00" << "0"
+ << "11" << "1")
+ << 0 << 1 << "2"
+ << (QStringList()
+ << "11" << "1"
+ << "00" << "2")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("2x2 no change (column != sortColumn)")
+ << 2 << 2
+ << static_cast<int>(Qt::AscendingOrder) << 1
+ << (QStringList()
+ << "00" << "0"
+ << "11" << "1")
+ << 0 << 0 << "22"
+ << (QStringList()
+ << "22" << "0"
+ << "11" << "1")
+ << (IntList() << 0 << 1)
+ << false;
+ QTest::newRow("8x4 reorder (ascending, sortColumn = 3)")
+ << 8 << 4
+ << static_cast<int>(Qt::AscendingOrder) << 3
+ << (QStringList()
+ << "q" << "v" << "u" << "0"
+ << "e" << "j" << "i" << "10"
+ << "h" << "d" << "c" << "12"
+ << "k" << "g" << "f" << "14"
+ << "w" << "y" << "x" << "2"
+ << "t" << "s" << "o" << "4"
+ << "z" << "p" << "r" << "6"
+ << "n" << "m" << "l" << "8")
+ << 2 << 3 << "5"
+ << (QStringList()
+ << "q" << "v" << "u" << "0"
+ << "e" << "j" << "i" << "10"
+ << "k" << "g" << "f" << "14"
+ << "w" << "y" << "x" << "2"
+ << "t" << "s" << "o" << "4"
+ << "h" << "d" << "c" << "5"
+ << "z" << "p" << "r" << "6"
+ << "n" << "m" << "l" << "8")
+ << (IntList() << 0 << 1 << 5 << 2 << 3 << 4 << 6 << 7)
+ << true;
+}
+
+void tst_QTableWidget::setItemWithSorting()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, columnCount);
+ QFETCH(int, sortOrder);
+ QFETCH(int, sortColumn);
+ QFETCH(QStringList, initialValues);
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(QString, newValue);
+ QFETCH(QStringList, expectedValues);
+ QFETCH(IntList, expectedRows);
+ QFETCH(bool, reorderingExpected);
+
+ for (int i = 0; i < 2; ++i) {
+ QTableWidget w(rowCount, columnCount);
+
+ QAbstractItemModel *model = w.model();
+ QList<QPersistentModelIndex> persistent;
+
+ int ti = 0;
+ for (int r = 0; r < rowCount; ++r) {
+ for (int c = 0; c < columnCount; ++c) {
+ QString str = initialValues.at(ti++);
+ w.setItem(r, c, new QTableWidgetItem(str));
+ }
+ persistent << model->index(r, sortColumn);
+ }
+
+ w.sortItems(sortColumn, static_cast<Qt::SortOrder>(sortOrder));
+ w.setSortingEnabled(true);
+
+ QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+ QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
+
+ if (i == 0) {
+ // set a new item
+ QTableWidgetItem *item = new QTableWidgetItem(newValue);
+ w.setItem(row, column, item);
+ } else {
+ // change the data of existing item
+ QTableWidgetItem *item = w.item(row, column);
+ item->setText(newValue);
+ }
+
+ ti = 0;
+ for (int r = 0; r < rowCount; ++r) {
+ for (int c = 0; c < columnCount; ++c) {
+ QString str = expectedValues.at(ti++);
+ QCOMPARE(w.item(r, c)->text(), str);
+ }
+ }
+
+ for (int k = 0; k < persistent.count(); ++k) {
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+ int i = (persistent.at(k).row() * columnCount) + sortColumn;
+ QCOMPARE(persistent.at(k).data().toString(), expectedValues.at(i));
+ }
+
+ if (i == 0)
+ QCOMPARE(dataChangedSpy.count(), reorderingExpected ? 0 : 1);
+ else
+ QCOMPARE(dataChangedSpy.count(), 1);
+
+ QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
+ }
+}
+
+void tst_QTableWidget::itemData()
+{
+ QTableWidget widget(2, 2);
+ widget.setItem(0, 0, new QTableWidgetItem());
+ QTableWidgetItem *item = widget.item(0, 0);
+ QVERIFY(item);
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ item->setData(Qt::DisplayRole, QString("0"));
+ item->setData(Qt::CheckStateRole, Qt::PartiallyChecked);
+ item->setData(Qt::UserRole + 0, QString("1"));
+ item->setData(Qt::UserRole + 1, QString("2"));
+ item->setData(Qt::UserRole + 2, QString("3"));
+ item->setData(Qt::UserRole + 3, QString("4"));
+ QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
+ QCOMPARE(flags.count(), 6);
+ QCOMPARE(flags[(Qt::UserRole + 0)].toString(), QString("1"));
+}
+
+void tst_QTableWidget::setItemData()
+{
+ QTableWidget table(10, 10);
+ table.setSortingEnabled(false);
+ QSignalSpy dataChangedSpy(table.model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ QTableWidgetItem *item = new QTableWidgetItem;
+ table.setItem(0, 0, item);
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QModelIndex idx = qvariant_cast<QModelIndex>(dataChangedSpy.takeFirst().at(0));
+
+ QMap<int, QVariant> data;
+ data.insert(Qt::DisplayRole, QLatin1String("Display"));
+ data.insert(Qt::ToolTipRole, QLatin1String("ToolTip"));
+ table.model()->setItemData(idx, data);
+
+ QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("Display"));
+ QCOMPARE(table.model()->data(idx, Qt::ToolTipRole).toString(), QLatin1String("ToolTip"));
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(idx, qvariant_cast<QModelIndex>(dataChangedSpy.takeFirst().at(0)));
+
+ table.model()->setItemData(idx, data);
+ QCOMPARE(dataChangedSpy.count(), 0);
+
+ data.clear();
+ data.insert(Qt::DisplayRole, QLatin1String("dizplaye"));
+ table.model()->setItemData(idx, data);
+ QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("dizplaye"));
+ QCOMPARE(dataChangedSpy.count(), 1);
+}
+
+void tst_QTableWidget::cellWidget()
+{
+ QTableWidget table(10, 10);
+ QWidget widget;
+
+ QCOMPARE(table.cellWidget(5, 5), static_cast<QWidget*>(0));
+ table.setCellWidget(5, 5, &widget);
+ QCOMPARE(table.cellWidget(5, 5), &widget);
+ table.removeCellWidget(5, 5);
+ QCOMPARE(table.cellWidget(5, 5), static_cast<QWidget*>(0));
+}
+
+void tst_QTableWidget::task231094()
+{
+ QTableWidget tw(5, 3);
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 5; y++) {
+ QTableWidgetItem *twi = new QTableWidgetItem(QLatin1String("1"));
+ if (y == 1)
+ twi->setFlags(Qt::ItemIsEnabled);
+ else
+ twi->setFlags(0);
+ tw.setItem(y, x, twi);
+ }
+ }
+
+ tw.setCurrentCell(1, 1);
+ QCOMPARE(tw.currentRow(), 1);
+ QCOMPARE(tw.currentColumn(), 1);
+
+ //this would provoke a end-less loop
+ QTest::keyClick(&tw, '1');
+
+ //all the items are disabled: the current item shouldn't have changed
+ QCOMPARE(tw.currentRow(), 1);
+ QCOMPARE(tw.currentColumn(), 1);
+}
+
+void tst_QTableWidget::task219380_removeLastRow()
+{
+ testWidget->setColumnCount(1);
+ testWidget->setRowCount(20);
+ QTableWidgetItem item;
+ testWidget->setItem(18, 0, &item); //we put the item in the the second last row
+ testWidget->openPersistentEditor(&item);
+
+ testWidget->scrollToBottom();
+
+ testWidget->removeRow(19); //we remove the last row
+
+ //we make sure the editor is at the cell position
+ QTRY_COMPARE(testWidget->cellWidget(18, 0)->geometry(), testWidget->visualItemRect(&item));
+}
+
+void tst_QTableWidget::task262056_sortDuplicate()
+{
+ testWidget->setColumnCount(2);
+ testWidget->setRowCount(8);
+ testWidget->setSortingEnabled(true);
+ QStringList items = (QStringList() << "AAA" << "BBB" << "CCC" << "CCC" << "DDD"\
+ << "EEE" << "FFF" << "GGG");
+ for (int i = 0; i<8; i++ ) {
+ QTableWidgetItem *twi = new QTableWidgetItem(items.at(i));
+ testWidget->setItem(i,0,twi);
+ testWidget->setItem(i,1,new QTableWidgetItem(QString("item %1").arg(i)));
+ }
+ testWidget->sortItems(0, Qt::AscendingOrder);
+ QSignalSpy layoutChangedSpy(testWidget->model(), SIGNAL(layoutChanged()));
+ testWidget->item(3,0)->setBackgroundColor(Qt::red);
+
+ QCOMPARE(layoutChangedSpy.count(),0);
+
+}
+
+
+QTEST_MAIN(tst_QTableWidget)
+#include "tst_qtablewidget.moc"
diff --git a/tests/auto/widgets/itemviews/qtreeview/.gitignore b/tests/auto/widgets/itemviews/qtreeview/.gitignore
new file mode 100644
index 0000000000..4e72cdb157
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreeview/.gitignore
@@ -0,0 +1 @@
+tst_qtreeview
diff --git a/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro b/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro
new file mode 100644
index 0000000000..ea53bbdc1d
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtreeview.cpp
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
new file mode 100644
index 0000000000..d6cdf00218
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -0,0 +1,3942 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qabstractitemview.h>
+#include <QtTest/QtTest>
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QModelIndex)
+#ifndef QT_NO_DRAGANDDROP
+Q_DECLARE_METATYPE(QAbstractItemView::DragDropMode)
+#endif
+Q_DECLARE_METATYPE(QAbstractItemView::EditTriggers)
+Q_DECLARE_METATYPE(QAbstractItemView::EditTrigger)
+
+static void initStandardTreeModel(QStandardItemModel *model)
+{
+ QStandardItem *item;
+ item = new QStandardItem(QLatin1String("Row 1 Item"));
+ model->insertRow(0, item);
+
+ item = new QStandardItem(QLatin1String("Row 2 Item"));
+ item->setCheckable(true);
+ model->insertRow(1, item);
+
+ QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
+ item->setChild(0, childItem);
+
+ item = new QStandardItem(QLatin1String("Row 3 Item"));
+ item->setIcon(QIcon());
+ model->insertRow(2, item);
+}
+
+struct PublicView : public QTreeView
+{
+ inline void executeDelayedItemsLayout()
+ { QTreeView::executeDelayedItemsLayout(); }
+
+ enum PublicCursorAction {
+ MoveUp = QAbstractItemView::MoveUp,
+ MoveDown = QAbstractItemView::MoveDown,
+ MoveLeft = QAbstractItemView::MoveLeft,
+ MoveRight = QAbstractItemView::MoveRight,
+ MoveHome = QAbstractItemView::MoveHome,
+ MoveEnd = QAbstractItemView::MoveEnd,
+ MovePageUp = QAbstractItemView::MovePageUp,
+ MovePageDown = QAbstractItemView::MovePageDown,
+ MoveNext = QAbstractItemView::MoveNext,
+ MovePrevious = QAbstractItemView::MovePrevious
+ };
+
+ inline QModelIndex moveCursor(PublicCursorAction ca, Qt::KeyboardModifiers kbm)
+ { return QTreeView::moveCursor((CursorAction)ca, kbm); }
+
+ inline void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
+ {
+ QTreeView::setSelection(rect, command);
+ }
+ inline int state()
+ {
+ return QTreeView::state();
+ }
+
+ inline int rowHeight(QModelIndex idx) { return QTreeView::rowHeight(idx); }
+ inline int indexRowSizeHint(const QModelIndex &index) const { return QTreeView::indexRowSizeHint(index); }
+
+ inline QModelIndexList selectedIndexes() const { return QTreeView::selectedIndexes(); }
+
+ inline QStyleOptionViewItem viewOptions() const { return QTreeView::viewOptions(); }
+ inline int sizeHintForColumn(int column) const { return QTreeView::sizeHintForColumn(column); }
+};
+
+class tst_QTreeView : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTreeView();
+ virtual ~tst_QTreeView();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+ void selectionOrderTest();
+
+private slots:
+ void getSetCheck();
+
+ // one test per QTreeView property
+ void construction();
+ void alternatingRowColors();
+ void currentIndex_data();
+ void currentIndex();
+#ifndef QT_NO_DRAGANDDROP
+ void dragDropMode_data();
+ void dragDropMode();
+ void dragDropModeFromDragEnabledAndAcceptDrops_data();
+ void dragDropModeFromDragEnabledAndAcceptDrops();
+ void dragDropOverwriteMode();
+#endif
+ void editTriggers_data();
+ void editTriggers();
+ void hasAutoScroll();
+ void horizontalScrollMode();
+ void iconSize();
+ void indexAt();
+ void indexWidget();
+ void itemDelegate();
+ void itemDelegateForColumnOrRow();
+ void keyboardSearch();
+ void setModel();
+ void openPersistentEditor();
+ void rootIndex();
+
+ // specialized tests below
+ void setHeader();
+ void columnHidden();
+ void rowHidden();
+ void noDelegate();
+ void noModel();
+ void emptyModel();
+ void removeRows();
+ void removeCols();
+ void expandAndCollapse_data();
+ void expandAndCollapse();
+ void expandAndCollapseAll();
+ void expandWithNoChildren();
+ void keyboardNavigation();
+ void headerSections();
+ void moveCursor_data();
+ void moveCursor();
+ void setSelection_data();
+ void setSelection();
+ void extendedSelection_data();
+ void extendedSelection();
+ void indexAbove();
+ void indexBelow();
+ void clicked();
+ void mouseDoubleClick();
+ void rowsAboutToBeRemoved();
+ void headerSections_unhideSection();
+ void columnAt();
+ void scrollTo();
+ void rowsAboutToBeRemoved_move();
+ void resizeColumnToContents();
+ void insertAfterSelect();
+ void removeAfterSelect();
+ void hiddenItems();
+ void spanningItems();
+ void rowSizeHint();
+ void setSortingEnabled();
+ void headerHidden();
+
+ void selection();
+ void removeAndInsertExpandedCol0();
+ void selectionWithHiddenItems();
+ void selectAll();
+
+ void disabledButCheckable();
+ void sortByColumn_data();
+ void sortByColumn();
+
+ void evilModel_data();
+ void evilModel();
+
+ void indexRowSizeHint();
+ void addRowsWhileSectionsAreHidden();
+ void filterProxyModelCrash();
+ void styleOptionViewItem();
+ void keyboardNavigationWithDisabled();
+
+ // task-specific tests:
+ void task174627_moveLeftToRoot();
+ void task171902_expandWith1stColHidden();
+ void task203696_hidingColumnsAndRowsn();
+ void task211293_removeRootIndex();
+ void task216717_updateChildren();
+ void task220298_selectColumns();
+ void task224091_appendColumns();
+ void task225539_deleteModel();
+ void task230123_setItemsExpandable();
+ void task202039_closePersistentEditor();
+ void task238873_avoidAutoReopening();
+ void task244304_clickOnDecoration();
+ void task246536_scrollbarsNotWorking();
+ void task250683_wrongSectionSize();
+ void task239271_addRowsWithFirstColumnHidden();
+ void task254234_proxySort();
+ void task248022_changeSelection();
+ void task245654_changeModelAndExpandAll();
+ void doubleClickedWithSpans();
+ void taskQTBUG_6450_selectAllWith1stColumnHidden();
+ void taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint();
+ void taskQTBUG_11466_keyboardNavigationRegression();
+ void taskQTBUG_13567_removeLastItemRegression();
+};
+
+class QtTestModel: public QAbstractItemModel
+{
+public:
+ QtTestModel(QObject *parent = 0): QAbstractItemModel(parent),
+ fetched(false), rows(0), cols(0), levels(INT_MAX), wrongIndex(false) { init(); }
+
+ QtTestModel(int _rows, int _cols, QObject *parent = 0): QAbstractItemModel(parent),
+ fetched(false), rows(_rows), cols(_cols), levels(INT_MAX), wrongIndex(false) { init(); }
+
+ void init() {
+ decorationsEnabled = false;
+ }
+
+ inline qint32 level(const QModelIndex &index) const {
+ return index.isValid() ? qint32(index.internalId()) : qint32(-1);
+ }
+
+ bool canFetchMore(const QModelIndex &) const {
+ return !fetched;
+ }
+
+ void fetchMore(const QModelIndex &) {
+ fetched = true;
+ }
+
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const {
+ bool hasFetched = fetched;
+ fetched = true;
+ bool r = QAbstractItemModel::hasChildren(parent);
+ fetched = hasFetched;
+ return r;
+ }
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const {
+ if (!fetched)
+ qFatal("%s: rowCount should not be called before fetching", Q_FUNC_INFO);
+ if ((parent.column() > 0) || (level(parent) > levels))
+ return 0;
+ return rows;
+ }
+ int columnCount(const QModelIndex& parent = QModelIndex()) const {
+ if ((parent.column() > 0) || (level(parent) > levels))
+ return 0;
+ return cols;
+ }
+
+ bool isEditable(const QModelIndex &index) const {
+ if (index.isValid())
+ return true;
+ return false;
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+ {
+ if (row < 0 || column < 0 || (level(parent) > levels) || column >= cols || row >= rows) {
+ return QModelIndex();
+ }
+ QModelIndex i = createIndex(row, column, level(parent) + 1);
+ parentHash[i] = parent;
+ return i;
+ }
+
+ QModelIndex parent(const QModelIndex &index) const
+ {
+ if (!parentHash.contains(index))
+ return QModelIndex();
+ return parentHash[index];
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (!idx.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole) {
+ if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
+ wrongIndex = true;
+ qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(),
+ idx.internalPointer());
+ }
+ if (idx.row() & 1)
+ return QString("[%1,%2,%3] - this item is extra wide").arg(idx.row()).arg(idx.column()).arg(level(idx));
+ return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(level(idx));
+ }
+ if (decorationsEnabled && role == Qt::DecorationRole) {
+ QPixmap pm(16,16);
+ pm.fill(QColor::fromHsv((idx.column() % 16)*8 + 64, 254, (idx.row() % 16)*8 + 32));
+ return pm;
+ }
+ return QVariant();
+ }
+
+ void removeLastRow()
+ {
+ beginRemoveRows(QModelIndex(), rows - 1, rows - 1);
+ --rows;
+ endRemoveRows();
+ }
+
+ void removeAllRows()
+ {
+ beginRemoveRows(QModelIndex(), 0, rows - 1);
+ rows = 0;
+ endRemoveRows();
+ }
+
+ void removeLastColumn()
+ {
+ beginRemoveColumns(QModelIndex(), cols - 1, cols - 1);
+ --cols;
+ endRemoveColumns();
+ }
+
+ void removeAllColumns()
+ {
+ beginRemoveColumns(QModelIndex(), 0, cols - 1);
+ cols = 0;
+ endRemoveColumns();
+ }
+
+ void insertNewRow()
+ {
+ beginInsertRows(QModelIndex(), rows - 1, rows - 1);
+ ++rows;
+ endInsertRows();
+ }
+
+ void setDecorationsEnabled(bool enable)
+ {
+ decorationsEnabled = enable;
+ }
+
+ mutable bool fetched;
+ bool decorationsEnabled;
+ int rows, cols;
+ int levels;
+ mutable bool wrongIndex;
+ mutable QMap<QModelIndex,QModelIndex> parentHash;
+};
+
+tst_QTreeView::tst_QTreeView()
+{
+}
+
+tst_QTreeView::~tst_QTreeView()
+{
+}
+
+void tst_QTreeView::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+}
+
+void tst_QTreeView::cleanupTestCase()
+{
+}
+
+void tst_QTreeView::init()
+{
+}
+
+void tst_QTreeView::cleanup()
+{
+}
+
+// Testing get/set functions
+void tst_QTreeView::getSetCheck()
+{
+ QTreeView obj1;
+
+ // int QTreeView::indentation()
+ // void QTreeView::setIndentation(int)
+ QCOMPARE(obj1.indentation(), 20);
+ obj1.setIndentation(0);
+ QCOMPARE(obj1.indentation(), 0);
+ obj1.setIndentation(INT_MIN);
+ QCOMPARE(obj1.indentation(), INT_MIN);
+ obj1.setIndentation(INT_MAX);
+ QCOMPARE(obj1.indentation(), INT_MAX);
+
+ // bool QTreeView::rootIsDecorated()
+ // void QTreeView::setRootIsDecorated(bool)
+ QCOMPARE(obj1.rootIsDecorated(), true);
+ obj1.setRootIsDecorated(false);
+ QCOMPARE(obj1.rootIsDecorated(), false);
+ obj1.setRootIsDecorated(true);
+ QCOMPARE(obj1.rootIsDecorated(), true);
+
+ // bool QTreeView::uniformRowHeights()
+ // void QTreeView::setUniformRowHeights(bool)
+ QCOMPARE(obj1.uniformRowHeights(), false);
+ obj1.setUniformRowHeights(false);
+ QCOMPARE(obj1.uniformRowHeights(), false);
+ obj1.setUniformRowHeights(true);
+ QCOMPARE(obj1.uniformRowHeights(), true);
+
+ // bool QTreeView::itemsExpandable()
+ // void QTreeView::setItemsExpandable(bool)
+ QCOMPARE(obj1.itemsExpandable(), true);
+ obj1.setItemsExpandable(false);
+ QCOMPARE(obj1.itemsExpandable(), false);
+ obj1.setItemsExpandable(true);
+ QCOMPARE(obj1.itemsExpandable(), true);
+
+ // bool QTreeView::allColumnsShowFocus
+ // void QTreeView::setAllColumnsShowFocus
+ QCOMPARE(obj1.allColumnsShowFocus(), false);
+ obj1.setAllColumnsShowFocus(false);
+ QCOMPARE(obj1.allColumnsShowFocus(), false);
+ obj1.setAllColumnsShowFocus(true);
+ QCOMPARE(obj1.allColumnsShowFocus(), true);
+
+ // bool QTreeView::isAnimated
+ // void QTreeView::setAnimated
+ QCOMPARE(obj1.isAnimated(), false);
+ obj1.setAnimated(false);
+ QCOMPARE(obj1.isAnimated(), false);
+ obj1.setAnimated(true);
+ QCOMPARE(obj1.isAnimated(), true);
+
+ // bool QTreeView::setSortingEnabled
+ // void QTreeView::isSortingEnabled
+ QCOMPARE(obj1.isSortingEnabled(), false);
+ obj1.setSortingEnabled(false);
+ QCOMPARE(obj1.isSortingEnabled(), false);
+ obj1.setSortingEnabled(true);
+ QCOMPARE(obj1.isSortingEnabled(), true);
+}
+
+void tst_QTreeView::construction()
+{
+ QTreeView view;
+
+ // QAbstractItemView properties
+ QVERIFY(!view.alternatingRowColors());
+ QCOMPARE(view.currentIndex(), QModelIndex());
+#ifndef QT_NO_DRAGANDDROP
+ QCOMPARE(view.dragDropMode(), QAbstractItemView::NoDragDrop);
+ QVERIFY(!view.dragDropOverwriteMode());
+ QVERIFY(!view.dragEnabled());
+#endif
+ QCOMPARE(view.editTriggers(), QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked);
+ QVERIFY(view.hasAutoScroll());
+ QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
+ QCOMPARE(view.iconSize(), QSize());
+ QCOMPARE(view.indexAt(QPoint()), QModelIndex());
+ QVERIFY(!view.indexWidget(QModelIndex()));
+ QVERIFY(qobject_cast<QStyledItemDelegate *>(view.itemDelegate()));
+ QVERIFY(!view.itemDelegateForColumn(-1));
+ QVERIFY(!view.itemDelegateForColumn(0));
+ QVERIFY(!view.itemDelegateForColumn(1));
+ QVERIFY(!view.itemDelegateForRow(-1));
+ QVERIFY(!view.itemDelegateForRow(0));
+ QVERIFY(!view.itemDelegateForRow(1));
+ QVERIFY(!view.model());
+ QCOMPARE(view.rootIndex(), QModelIndex());
+ QCOMPARE(view.selectionBehavior(), QAbstractItemView::SelectRows);
+ QCOMPARE(view.selectionMode(), QAbstractItemView::SingleSelection);
+ QVERIFY(!view.selectionModel());
+#ifndef QT_NO_DRAGANDDROP
+ QVERIFY(view.showDropIndicator());
+#endif
+ QCOMPARE(view.QAbstractItemView::sizeHintForColumn(-1), -1); // <- protected in QTreeView
+ QCOMPARE(view.QAbstractItemView::sizeHintForColumn(0), -1); // <- protected in QTreeView
+ QCOMPARE(view.QAbstractItemView::sizeHintForColumn(1), -1); // <- protected in QTreeView
+ QCOMPARE(view.sizeHintForIndex(QModelIndex()), QSize());
+ QCOMPARE(view.sizeHintForRow(-1), -1);
+ QCOMPARE(view.sizeHintForRow(0), -1);
+ QCOMPARE(view.sizeHintForRow(1), -1);
+ QVERIFY(!view.tabKeyNavigation());
+ QCOMPARE(view.textElideMode(), Qt::ElideRight);
+ QCOMPARE(view.verticalScrollMode(), QAbstractItemView::ScrollPerItem);
+ QCOMPARE(view.visualRect(QModelIndex()), QRect());
+
+ // QTreeView properties
+ QVERIFY(!view.allColumnsShowFocus());
+ QCOMPARE(view.autoExpandDelay(), -1);
+ QCOMPARE(view.columnAt(-1), -1);
+ QCOMPARE(view.columnAt(0), -1);
+ QCOMPARE(view.columnAt(1), -1);
+ QCOMPARE(view.columnViewportPosition(-1), -1);
+ QCOMPARE(view.columnViewportPosition(0), -1);
+ QCOMPARE(view.columnViewportPosition(1), -1);
+ QCOMPARE(view.columnWidth(-1), 0);
+ QCOMPARE(view.columnWidth(0), 0);
+ QCOMPARE(view.columnWidth(1), 0);
+ QVERIFY(view.header());
+ QCOMPARE(view.indentation(), 20);
+ QCOMPARE(view.indexAbove(QModelIndex()), QModelIndex());
+ QCOMPARE(view.indexBelow(QModelIndex()), QModelIndex());
+ QVERIFY(!view.isAnimated());
+ QVERIFY(!view.isColumnHidden(-1));
+ QVERIFY(!view.isColumnHidden(0));
+ QVERIFY(!view.isColumnHidden(1));
+ QVERIFY(!view.isExpanded(QModelIndex()));
+ QVERIFY(!view.isRowHidden(-1, QModelIndex()));
+ QVERIFY(!view.isRowHidden(0, QModelIndex()));
+ QVERIFY(!view.isRowHidden(1, QModelIndex()));
+ QVERIFY(!view.isFirstColumnSpanned(-1, QModelIndex()));
+ QVERIFY(!view.isFirstColumnSpanned(0, QModelIndex()));
+ QVERIFY(!view.isFirstColumnSpanned(1, QModelIndex()));
+ QVERIFY(!view.isSortingEnabled());
+ QVERIFY(view.itemsExpandable());
+ QVERIFY(view.rootIsDecorated());
+ QVERIFY(!view.uniformRowHeights());
+ QCOMPARE(view.visualRect(QModelIndex()), QRect());
+ QVERIFY(!view.wordWrap());
+}
+
+void tst_QTreeView::alternatingRowColors()
+{
+ QTreeView view;
+ QVERIFY(!view.alternatingRowColors());
+ view.setAlternatingRowColors(true);
+ QVERIFY(view.alternatingRowColors());
+ view.setAlternatingRowColors(false);
+ QVERIFY(!view.alternatingRowColors());
+
+ // ### Test visual effect.
+}
+
+void tst_QTreeView::currentIndex_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("indexRow");
+ QTest::addColumn<int>("indexColumn");
+ QTest::addColumn<int>("parentIndexRow");
+ QTest::addColumn<int>("parentIndexColumn");
+
+ QTest::newRow("-1, -1") << -1 << -1 << -1 << -1 << -1 << -1;
+ QTest::newRow("-1, 0") << -1 << 0 << -1 << -1 << -1 << -1;
+ QTest::newRow("0, -1") << 0 << -1 << -1 << -1 << -1 << -1;
+ QTest::newRow("0, 0") << 0 << 0 << 0 << 0 << -1 << -1;
+ QTest::newRow("0, 1") << 0 << 0 << 0 << 0 << -1 << -1;
+ QTest::newRow("1, 0") << 1 << 0 << 1 << 0 << -1 << -1;
+ QTest::newRow("1, 1") << 1 << 1 << -1 << -1 << -1 << -1;
+ QTest::newRow("2, 0") << 2 << 0 << 2 << 0 << -1 << -1;
+ QTest::newRow("2, 1") << 2 << 1 << -1 << -1 << -1 << -1;
+ QTest::newRow("3, -1") << 3 << -1 << -1 << -1 << -1 << -1;
+ QTest::newRow("3, 0") << 3 << 0 << -1 << -1 << -1 << -1;
+ QTest::newRow("3, 1") << 3 << 1 << -1 << -1 << -1 << -1;
+}
+
+void tst_QTreeView::currentIndex()
+{
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, indexRow);
+ QFETCH(int, indexColumn);
+ QFETCH(int, parentIndexRow);
+ QFETCH(int, parentIndexColumn);
+
+ QTreeView view;
+ QStandardItemModel treeModel;
+ initStandardTreeModel(&treeModel);
+ view.setModel(&treeModel);
+
+ QCOMPARE(view.currentIndex(), QModelIndex());
+ view.setCurrentIndex(view.model()->index(row, column));
+ QCOMPARE(view.currentIndex().row(), indexRow);
+ QCOMPARE(view.currentIndex().column(), indexColumn);
+ QCOMPARE(view.currentIndex().parent().row(), parentIndexRow);
+ QCOMPARE(view.currentIndex().parent().column(), parentIndexColumn);
+
+ // ### Test child and grandChild indexes.
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+void tst_QTreeView::dragDropMode_data()
+{
+ QTest::addColumn<QAbstractItemView::DragDropMode>("dragDropMode");
+ QTest::addColumn<bool>("acceptDrops");
+ QTest::addColumn<bool>("dragEnabled");
+ QTest::newRow("NoDragDrop") << QAbstractItemView::NoDragDrop << false << false;
+ QTest::newRow("DragOnly") << QAbstractItemView::DragOnly << false << true;
+ QTest::newRow("DropOnly") << QAbstractItemView::DropOnly << true << false;
+ QTest::newRow("DragDrop") << QAbstractItemView::DragDrop << true << true;
+ QTest::newRow("InternalMove") << QAbstractItemView::InternalMove << true << true;
+}
+
+void tst_QTreeView::dragDropMode()
+{
+ QFETCH(QAbstractItemView::DragDropMode, dragDropMode);
+ QFETCH(bool, acceptDrops);
+ QFETCH(bool, dragEnabled);
+
+ QTreeView view;
+ QCOMPARE(view.dragDropMode(), QAbstractItemView::NoDragDrop);
+ QVERIFY(!view.acceptDrops());
+ QVERIFY(!view.dragEnabled());
+
+ view.setDragDropMode(dragDropMode);
+ QCOMPARE(view.dragDropMode(), dragDropMode);
+ QCOMPARE(view.acceptDrops(), acceptDrops);
+ QCOMPARE(view.dragEnabled(), dragEnabled);
+
+ // ### Test effects of this mode
+}
+
+void tst_QTreeView::dragDropModeFromDragEnabledAndAcceptDrops_data()
+{
+ QTest::addColumn<bool>("dragEnabled");
+ QTest::addColumn<bool>("acceptDrops");
+ QTest::addColumn<QAbstractItemView::DragDropMode>("dragDropMode");
+ QTest::addColumn<QAbstractItemView::DragDropMode>("setBehavior");
+
+ QTest::newRow("NoDragDrop -1") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DragDropMode(-1);
+ QTest::newRow("NoDragDrop 0") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::NoDragDrop;
+ QTest::newRow("NoDragDrop 1") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DragOnly;
+ QTest::newRow("NoDragDrop 2") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DropOnly;
+ QTest::newRow("NoDragDrop 3") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DragDrop;
+ QTest::newRow("NoDragDrop 4") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::InternalMove;
+ QTest::newRow("DragOnly -1") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DragDropMode(-1);
+ QTest::newRow("DragOnly 0") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::NoDragDrop;
+ QTest::newRow("DragOnly 1") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DragOnly;
+ QTest::newRow("DragOnly 2") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DropOnly;
+ QTest::newRow("DragOnly 3") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DragDrop;
+ QTest::newRow("DragOnly 4") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::InternalMove;
+ QTest::newRow("DropOnly -1") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DragDropMode(-1);
+ QTest::newRow("DropOnly 0") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::NoDragDrop;
+ QTest::newRow("DropOnly 1") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DragOnly;
+ QTest::newRow("DropOnly 2") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DropOnly;
+ QTest::newRow("DropOnly 3") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DragDrop;
+ QTest::newRow("DropOnly 4") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::InternalMove;
+ QTest::newRow("DragDrop -1") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragDropMode(-1);
+ QTest::newRow("DragDrop 0") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragDropMode(-1);
+ QTest::newRow("DragDrop 1") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::NoDragDrop;
+ QTest::newRow("DragDrop 2") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragOnly;
+ QTest::newRow("DragDrop 3") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DropOnly;
+ QTest::newRow("DragDrop 4") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragDrop;
+ QTest::newRow("DragDrop 5") << true << true << QAbstractItemView::InternalMove << QAbstractItemView::InternalMove;
+}
+
+void tst_QTreeView::dragDropModeFromDragEnabledAndAcceptDrops()
+{
+ QFETCH(bool, acceptDrops);
+ QFETCH(bool, dragEnabled);
+ QFETCH(QAbstractItemView::DragDropMode, dragDropMode);
+ QFETCH(QAbstractItemView::DragDropMode, setBehavior);
+
+ QTreeView view;
+ QCOMPARE(view.dragDropMode(), QAbstractItemView::NoDragDrop);
+
+ if (setBehavior != QAbstractItemView::DragDropMode(-1))
+ view.setDragDropMode(setBehavior);
+
+ view.setAcceptDrops(acceptDrops);
+ view.setDragEnabled(dragEnabled);
+ QCOMPARE(view.dragDropMode(), dragDropMode);
+
+ // ### Test effects of this mode
+}
+
+void tst_QTreeView::dragDropOverwriteMode()
+{
+ QTreeView view;
+ QVERIFY(!view.dragDropOverwriteMode());
+ view.setDragDropOverwriteMode(true);
+ QVERIFY(view.dragDropOverwriteMode());
+ view.setDragDropOverwriteMode(false);
+ QVERIFY(!view.dragDropOverwriteMode());
+
+ // ### This property changes the behavior of dropIndicatorPosition(),
+ // which is protected and called only from within QListWidget and
+ // QTableWidget, from their reimplementations of dropMimeData(). Hard to
+ // test.
+}
+#endif
+
+void tst_QTreeView::editTriggers_data()
+{
+ QTest::addColumn<QAbstractItemView::EditTriggers>("editTriggers");
+ QTest::addColumn<QAbstractItemView::EditTrigger>("triggeredTrigger");
+ QTest::addColumn<bool>("editorOpened");
+
+ // NoEditTriggers
+ QTest::newRow("NoEditTriggers 0") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
+ << QAbstractItemView::NoEditTriggers << false;
+ QTest::newRow("NoEditTriggers 1") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
+ << QAbstractItemView::CurrentChanged << false;
+ QTest::newRow("NoEditTriggers 2") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
+ << QAbstractItemView::DoubleClicked << false;
+ QTest::newRow("NoEditTriggers 3") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
+ << QAbstractItemView::SelectedClicked << false;
+ QTest::newRow("NoEditTriggers 4") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
+ << QAbstractItemView::EditKeyPressed << false;
+
+ // CurrentChanged
+ QTest::newRow("CurrentChanged 0") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
+ << QAbstractItemView::NoEditTriggers << false;
+ QTest::newRow("CurrentChanged 1") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
+ << QAbstractItemView::CurrentChanged << true;
+ QTest::newRow("CurrentChanged 2") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
+ << QAbstractItemView::DoubleClicked << false;
+ QTest::newRow("CurrentChanged 3") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
+ << QAbstractItemView::SelectedClicked << false;
+ QTest::newRow("CurrentChanged 4") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
+ << QAbstractItemView::EditKeyPressed << false;
+
+ // DoubleClicked
+ QTest::newRow("DoubleClicked 0") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
+ << QAbstractItemView::NoEditTriggers << false;
+ QTest::newRow("DoubleClicked 1") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
+ << QAbstractItemView::CurrentChanged << false;
+ QTest::newRow("DoubleClicked 2") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
+ << QAbstractItemView::DoubleClicked << true;
+ QTest::newRow("DoubleClicked 3") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
+ << QAbstractItemView::SelectedClicked << false;
+ QTest::newRow("DoubleClicked 4") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
+ << QAbstractItemView::EditKeyPressed << false;
+
+ // SelectedClicked
+ QTest::newRow("SelectedClicked 0") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
+ << QAbstractItemView::NoEditTriggers << false;
+ QTest::newRow("SelectedClicked 1") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
+ << QAbstractItemView::CurrentChanged << false;
+ QTest::newRow("SelectedClicked 2") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
+ << QAbstractItemView::DoubleClicked << false;
+ QTest::newRow("SelectedClicked 3") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
+ << QAbstractItemView::SelectedClicked << true;
+ QTest::newRow("SelectedClicked 4") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
+ << QAbstractItemView::EditKeyPressed << false;
+
+ // EditKeyPressed
+ QTest::newRow("EditKeyPressed 0") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
+ << QAbstractItemView::NoEditTriggers << false;
+ QTest::newRow("EditKeyPressed 1") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
+ << QAbstractItemView::CurrentChanged << false;
+ QTest::newRow("EditKeyPressed 2") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
+ << QAbstractItemView::DoubleClicked << false;
+ QTest::newRow("EditKeyPressed 3") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
+ << QAbstractItemView::SelectedClicked << false;
+ QTest::newRow("EditKeyPressed 4") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
+ << QAbstractItemView::EditKeyPressed << true;
+}
+
+void tst_QTreeView::editTriggers()
+{
+ QFETCH(QAbstractItemView::EditTriggers, editTriggers);
+ QFETCH(QAbstractItemView::EditTrigger, triggeredTrigger);
+ QFETCH(bool, editorOpened);
+
+ QTreeView view;
+ QStandardItemModel treeModel;
+ initStandardTreeModel(&treeModel);
+ view.setModel(&treeModel);
+ view.show();
+
+ QCOMPARE(view.editTriggers(), QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked);
+
+ // Initialize the first index
+ view.setCurrentIndex(view.model()->index(0, 0));
+
+ // Verify that we don't have any editor initially
+ QVERIFY(!qFindChild<QLineEdit *>(&view, QString()));
+
+ // Set the triggers
+ view.setEditTriggers(editTriggers);
+
+ // Interact with the view
+ switch (triggeredTrigger) {
+ case QAbstractItemView::NoEditTriggers:
+ // Do nothing, the editor shouldn't be there
+ break;
+ case QAbstractItemView::CurrentChanged:
+ // Change the index to open an editor
+ view.setCurrentIndex(view.model()->index(1, 0));
+ break;
+ case QAbstractItemView::DoubleClicked:
+ // Doubleclick the center of the current cell
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.visualRect(view.model()->index(0, 0)).center());
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0,
+ view.visualRect(view.model()->index(0, 0)).center());
+ break;
+ case QAbstractItemView::SelectedClicked:
+ // Click the center of the current cell
+ view.selectionModel()->select(view.model()->index(0, 0), QItemSelectionModel::Select);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.visualRect(view.model()->index(0, 0)).center());
+ QTest::qWait(int(QApplication::doubleClickInterval() * 1.5));
+ break;
+ case QAbstractItemView::EditKeyPressed:
+ view.setFocus();
+#ifdef Q_OS_MAC
+ // Mac OS X uses Enter for editing
+ QTest::keyPress(&view, Qt::Key_Enter);
+#else
+ // All other platforms use F2
+ QTest::keyPress(&view, Qt::Key_F2);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ // Check if we got an editor
+ QTRY_COMPARE(qFindChild<QLineEdit *>(&view, QString()) != 0, editorOpened);
+}
+
+void tst_QTreeView::hasAutoScroll()
+{
+ QTreeView view;
+ QVERIFY(view.hasAutoScroll());
+ view.setAutoScroll(false);
+ QVERIFY(!view.hasAutoScroll());
+ view.setAutoScroll(true);
+ QVERIFY(view.hasAutoScroll());
+}
+
+void tst_QTreeView::horizontalScrollMode()
+{
+ QStandardItemModel model;
+ for (int i = 0; i < 100; ++i) {
+ model.appendRow(QList<QStandardItem *>()
+ << new QStandardItem("An item that has very long text and should"
+ " cause the horizontal scroll bar to appear.")
+ << new QStandardItem("An item that has very long text and should"
+ " cause the horizontal scroll bar to appear."));
+ }
+
+ QTreeView view;
+ view.setModel(&model);
+ view.setFixedSize(100, 100);
+ view.header()->resizeSection(0, 200);
+ view.show();
+
+ QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
+ QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
+ QVERIFY(view.horizontalScrollBar()->maximum() > 2);
+
+ view.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
+ QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerItem);
+ QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
+ QCOMPARE(view.horizontalScrollBar()->maximum(), 1);
+
+ view.setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
+ QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
+ QVERIFY(view.horizontalScrollBar()->maximum() > 2);
+}
+
+class RepaintTreeView : public QTreeView
+{
+public:
+ RepaintTreeView() : repainted(false) { }
+ bool repainted;
+
+protected:
+ void paintEvent(QPaintEvent *event)
+ { repainted = true; QTreeView::paintEvent(event); }
+};
+
+void tst_QTreeView::iconSize()
+{
+ RepaintTreeView view;
+ QCOMPARE(view.iconSize(), QSize());
+
+ QStandardItemModel treeModel;
+ initStandardTreeModel(&treeModel);
+ view.setModel(&treeModel);
+ QCOMPARE(view.iconSize(), QSize());
+ QVERIFY(!view.repainted);
+
+ view.show();
+ view.update();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repainted);
+ QCOMPARE(view.iconSize(), QSize());
+
+ view.repainted = false;
+ view.setIconSize(QSize());
+ QTRY_VERIFY(!view.repainted);
+ QCOMPARE(view.iconSize(), QSize());
+
+ view.setIconSize(QSize(10, 10));
+ QTRY_VERIFY(view.repainted);
+ QCOMPARE(view.iconSize(), QSize(10, 10));
+
+ view.repainted = false;
+ view.setIconSize(QSize(10000, 10000));
+ QTRY_VERIFY(view.repainted);
+ QCOMPARE(view.iconSize(), QSize(10000, 10000));
+}
+
+void tst_QTreeView::indexAt()
+{
+ QtTestModel model;
+ model.rows = model.cols = 5;
+
+ QTreeView view;
+ QCOMPARE(view.indexAt(QPoint()), QModelIndex());
+ view.setModel(&model);
+ QVERIFY(view.indexAt(QPoint()) != QModelIndex());
+
+ QSize itemSize = view.visualRect(model.index(0, 0)).size();
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QPoint pos(itemSize.width() / 2, (i * itemSize.height()) + (itemSize.height() / 2));
+ QModelIndex index = view.indexAt(pos);
+ QCOMPARE(index, model.index(i, 0));
+ }
+
+ /*
+ // ### this is wrong; the widget _will_ affect the item size
+ for (int j = 0; j < model.rowCount(); ++j)
+ view.setIndexWidget(model.index(j, 0), new QPushButton);
+ */
+
+ for (int k = 0; k < model.rowCount(); ++k) {
+ QPoint pos(itemSize.width() / 2, (k * itemSize.height()) + (itemSize.height() / 2));
+ QModelIndex index = view.indexAt(pos);
+ QCOMPARE(index, model.index(k, 0));
+ }
+
+ view.show();
+ view.resize(600, 600);
+ view.header()->setStretchLastSection(false);
+ QCOMPARE(view.indexAt(QPoint(550, 20)), QModelIndex());
+}
+
+void tst_QTreeView::indexWidget()
+{
+ QTreeView view;
+ QStandardItemModel treeModel;
+ initStandardTreeModel(&treeModel);
+ view.setModel(&treeModel);
+
+ QModelIndex index = view.model()->index(0, 0);
+
+ QVERIFY(!view.indexWidget(QModelIndex()));
+ QVERIFY(!view.indexWidget(index));
+
+ QString text = QLatin1String("TestLabel");
+
+ QWidget *label = new QLabel(text);
+ view.setIndexWidget(QModelIndex(), label);
+ QVERIFY(!view.indexWidget(QModelIndex()));
+ QVERIFY(!label->parent());
+ view.setIndexWidget(index, label);
+ QCOMPARE(view.indexWidget(index), label);
+ QCOMPARE(label->parentWidget(), view.viewport());
+
+
+ QTextEdit *widget = new QTextEdit(text);
+ widget->setFixedSize(200,100);
+ view.setIndexWidget(index, widget);
+ QCOMPARE(view.indexWidget(index), static_cast<QWidget *>(widget));
+
+ QCOMPARE(widget->parentWidget(), view.viewport());
+ QCOMPARE(widget->geometry(), view.visualRect(index).intersected(widget->geometry()));
+ QCOMPARE(widget->toPlainText(), text);
+
+ //now let's try to do that later when the widget is already shown
+ view.show();
+ index = view.model()->index(1, 0);
+ QVERIFY(!view.indexWidget(index));
+
+ widget = new QTextEdit(text);
+ widget->setFixedSize(200,100);
+ view.setIndexWidget(index, widget);
+ QCOMPARE(view.indexWidget(index), static_cast<QWidget *>(widget));
+
+ QCOMPARE(widget->parentWidget(), view.viewport());
+ QCOMPARE(widget->geometry(), view.visualRect(index).intersect(widget->geometry()));
+ QCOMPARE(widget->toPlainText(), text);
+}
+
+void tst_QTreeView::itemDelegate()
+{
+ QPointer<QAbstractItemDelegate> oldDelegate;
+ QPointer<QItemDelegate> otherItemDelegate;
+
+ {
+ QTreeView view;
+ QVERIFY(qobject_cast<QStyledItemDelegate *>(view.itemDelegate()));
+ QPointer<QAbstractItemDelegate> oldDelegate = view.itemDelegate();
+
+ otherItemDelegate = new QItemDelegate;
+ view.setItemDelegate(otherItemDelegate);
+ QVERIFY(!otherItemDelegate->parent());
+ QVERIFY(oldDelegate);
+
+ QCOMPARE(view.itemDelegate(), (QAbstractItemDelegate *)otherItemDelegate);
+
+ view.setItemDelegate(0);
+ QVERIFY(!view.itemDelegate()); // <- view does its own drawing?
+ QVERIFY(otherItemDelegate);
+ }
+
+ // This is strange. Why doesn't setItemDelegate() reparent the delegate?
+ QVERIFY(!oldDelegate);
+ QVERIFY(otherItemDelegate);
+
+ delete otherItemDelegate;
+}
+
+void tst_QTreeView::itemDelegateForColumnOrRow()
+{
+ QTreeView view;
+ QAbstractItemDelegate *defaultDelegate = view.itemDelegate();
+ QVERIFY(defaultDelegate);
+
+ QVERIFY(!view.itemDelegateForRow(0));
+ QVERIFY(!view.itemDelegateForColumn(0));
+ QCOMPARE(view.itemDelegate(QModelIndex()), defaultDelegate);
+
+ QStandardItemModel model;
+ for (int i = 0; i < 100; ++i) {
+ model.appendRow(QList<QStandardItem *>()
+ << new QStandardItem("An item that has very long text and should"
+ " cause the horizontal scroll bar to appear.")
+ << new QStandardItem("An item that has very long text and should"
+ " cause the horizontal scroll bar to appear.")
+ << new QStandardItem("An item that has very long text and should"
+ " cause the horizontal scroll bar to appear."));
+ }
+ view.setModel(&model);
+
+ QVERIFY(!view.itemDelegateForRow(0));
+ QVERIFY(!view.itemDelegateForColumn(0));
+ QCOMPARE(view.itemDelegate(QModelIndex()), defaultDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(0, 0)), defaultDelegate);
+
+ QPointer<QAbstractItemDelegate> rowDelegate = new QItemDelegate;
+ view.setItemDelegateForRow(0, rowDelegate);
+ QVERIFY(!rowDelegate->parent());
+ QCOMPARE(view.itemDelegateForRow(0), (QAbstractItemDelegate *)rowDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(0, 0)), (QAbstractItemDelegate *)rowDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(0, 1)), (QAbstractItemDelegate *)rowDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(1, 0)), defaultDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(1, 1)), defaultDelegate);
+
+ QPointer<QAbstractItemDelegate> columnDelegate = new QItemDelegate;
+ view.setItemDelegateForColumn(1, columnDelegate);
+ QVERIFY(!columnDelegate->parent());
+ QCOMPARE(view.itemDelegateForColumn(1), (QAbstractItemDelegate *)columnDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(0, 0)), (QAbstractItemDelegate *)rowDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(0, 1)), (QAbstractItemDelegate *)rowDelegate); // row wins
+ QCOMPARE(view.itemDelegate(view.model()->index(1, 0)), defaultDelegate);
+ QCOMPARE(view.itemDelegate(view.model()->index(1, 1)), (QAbstractItemDelegate *)columnDelegate);
+
+ view.setItemDelegateForRow(0, 0);
+ QVERIFY(!view.itemDelegateForRow(0));
+ QVERIFY(rowDelegate); // <- wasn't deleted
+
+ view.setItemDelegateForColumn(1, 0);
+ QVERIFY(!view.itemDelegateForColumn(1));
+ QVERIFY(columnDelegate); // <- wasn't deleted
+
+ delete rowDelegate;
+ delete columnDelegate;
+}
+
+void tst_QTreeView::keyboardSearch()
+{
+ QTreeView view;
+ QStandardItemModel model;
+ model.appendRow(new QStandardItem("Andreas"));
+ model.appendRow(new QStandardItem("Baldrian"));
+ model.appendRow(new QStandardItem("Cecilie"));
+ view.setModel(&model);
+ view.show();
+
+ // Nothing is selected
+ QVERIFY(!view.selectionModel()->hasSelection());
+ QVERIFY(!view.selectionModel()->isSelected(model.index(0, 0)));
+
+ // First item is selected
+ view.keyboardSearch(QLatin1String("A"));
+ QTRY_VERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
+
+ // First item is still selected
+ view.keyboardSearch(QLatin1String("n"));
+ QVERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
+
+ // No "AnB" item - keep the same selection.
+ view.keyboardSearch(QLatin1String("B"));
+ QVERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
+
+ // Wait a bit.
+ QTest::qWait(QApplication::keyboardInputInterval() * 2);
+
+ // The item that starts with B is selected.
+ view.keyboardSearch(QLatin1String("B"));
+ QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
+}
+
+void tst_QTreeView::setModel()
+{
+ QTreeView view;
+ view.show();
+ QCOMPARE(view.model(), (QAbstractItemModel*)0);
+ QCOMPARE(view.selectionModel(), (QItemSelectionModel*)0);
+ QCOMPARE(view.header()->model(), (QAbstractItemModel*)0);
+ QCOMPARE(view.header()->selectionModel(), (QItemSelectionModel*)0);
+
+ for (int x = 0; x < 2; ++x) {
+ QtTestModel *model = new QtTestModel(10, 8);
+ QAbstractItemModel *oldModel = view.model();
+ QSignalSpy modelDestroyedSpy(oldModel ? oldModel : model, SIGNAL(destroyed()));
+ // set the same model twice
+ for (int i = 0; i < 2; ++i) {
+ QItemSelectionModel *oldSelectionModel = view.selectionModel();
+ QItemSelectionModel *dummy = new QItemSelectionModel(model);
+ QSignalSpy selectionModelDestroyedSpy(
+ oldSelectionModel ? oldSelectionModel : dummy, SIGNAL(destroyed()));
+ view.setModel(model);
+// QCOMPARE(selectionModelDestroyedSpy.count(), (x == 0 || i == 1) ? 0 : 1);
+ QCOMPARE(view.model(), (QAbstractItemModel *)model);
+ QCOMPARE(view.header()->model(), (QAbstractItemModel *)model);
+ QCOMPARE(view.selectionModel() != oldSelectionModel, (i == 0));
+ }
+ QTRY_COMPARE(modelDestroyedSpy.count(), 0);
+
+ view.setModel(0);
+ QCOMPARE(view.model(), (QAbstractItemModel*)0);
+ // ### shouldn't selectionModel also be 0 now?
+// QCOMPARE(view.selectionModel(), (QItemSelectionModel*)0);
+ delete model;
+ }
+}
+
+void tst_QTreeView::openPersistentEditor()
+{
+ QTreeView view;
+ QStandardItemModel treeModel;
+ initStandardTreeModel(&treeModel);
+ view.setModel(&treeModel);
+ view.show();
+
+ QVERIFY(!qFindChild<QLineEdit *>(view.viewport()));
+ view.openPersistentEditor(view.model()->index(0, 0));
+ QVERIFY(qFindChild<QLineEdit *>(view.viewport()));
+
+ view.closePersistentEditor(view.model()->index(0, 0));
+ QVERIFY(!qFindChild<QLineEdit *>(view.viewport())->isVisible());
+
+ qApp->sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!qFindChild<QLineEdit *>(view.viewport()));
+}
+
+void tst_QTreeView::rootIndex()
+{
+ QTreeView view;
+ QCOMPARE(view.rootIndex(), QModelIndex());
+ QStandardItemModel treeModel;
+ initStandardTreeModel(&treeModel);
+ view.setModel(&treeModel);
+ QCOMPARE(view.rootIndex(), QModelIndex());
+
+ view.setRootIndex(view.model()->index(1, 0));
+
+ QCOMPARE(view.model()->data(view.model()->index(0, view.header()->visualIndex(0), view.rootIndex()), Qt::DisplayRole)
+ .toString(), QString("Row 2 Child Item"));
+}
+
+void tst_QTreeView::setHeader()
+{
+ QTreeView view;
+ QVERIFY(view.header() != 0);
+ QCOMPARE(view.header()->orientation(), Qt::Horizontal);
+ QCOMPARE(view.header()->parent(), (QObject *)&view);
+ for (int x = 0; x < 2; ++x) {
+ QSignalSpy destroyedSpy(view.header(), SIGNAL(destroyed()));
+ Qt::Orientation orient = x ? Qt::Vertical : Qt::Horizontal;
+ QHeaderView *head = new QHeaderView(orient);
+ view.setHeader(head);
+ QCOMPARE(destroyedSpy.count(), 1);
+ QCOMPARE(head->parent(), (QObject *)&view);
+ QCOMPARE(view.header(), head);
+ view.setHeader(head);
+ QCOMPARE(view.header(), head);
+ // Itemviews in Qt < 4.2 have asserts for this. Qt >= 4.2 should handle this gracefully
+ view.setHeader((QHeaderView *)0);
+ QCOMPARE(view.header(), head);
+ }
+}
+
+void tst_QTreeView::columnHidden()
+{
+ QTreeView view;
+ QtTestModel model(10, 8);
+ view.setModel(&model);
+ view.show();
+ for (int c = 0; c < model.columnCount(); ++c)
+ QCOMPARE(view.isColumnHidden(c), false);
+ // hide even columns
+ for (int c = 0; c < model.columnCount(); c+=2)
+ view.setColumnHidden(c, true);
+ for (int c = 0; c < model.columnCount(); ++c)
+ QCOMPARE(view.isColumnHidden(c), (c & 1) == 0);
+ view.update();
+ // hide odd columns too
+ for (int c = 1; c < model.columnCount(); c+=2)
+ view.setColumnHidden(c, true);
+ for (int c = 0; c < model.columnCount(); ++c)
+ QCOMPARE(view.isColumnHidden(c), true);
+ view.update();
+}
+
+void tst_QTreeView::rowHidden()
+{
+ QtTestModel model(4, 6);
+ model.levels = 3;
+ QTreeView view;
+ view.resize(500,500);
+ view.setModel(&model);
+ view.show();
+
+ QCOMPARE(view.isRowHidden(-1, QModelIndex()), false);
+ QCOMPARE(view.isRowHidden(999999, QModelIndex()), false);
+ view.setRowHidden(-1, QModelIndex(), true);
+ view.setRowHidden(999999, QModelIndex(), true);
+ QCOMPARE(view.isRowHidden(-1, QModelIndex()), false);
+ QCOMPARE(view.isRowHidden(999999, QModelIndex()), false);
+
+ view.setRowHidden(0, QModelIndex(), true);
+ QCOMPARE(view.isRowHidden(0, QModelIndex()), true);
+ view.setRowHidden(0, QModelIndex(), false);
+ QCOMPARE(view.isRowHidden(0, QModelIndex()), false);
+
+ QStack<QModelIndex> parents;
+ parents.push(QModelIndex());
+ while (!parents.isEmpty()) {
+ QModelIndex p = parents.pop();
+ if (model.canFetchMore(p))
+ model.fetchMore(p);
+ int rows = model.rowCount(p);
+ // hide all
+ for (int r = 0; r < rows; ++r) {
+ view.setRowHidden(r, p, true);
+ QCOMPARE(view.isRowHidden(r, p), true);
+ }
+ // hide none
+ for (int r = 0; r < rows; ++r) {
+ view.setRowHidden(r, p, false);
+ QCOMPARE(view.isRowHidden(r, p), false);
+ }
+ // hide only even rows
+ for (int r = 0; r < rows; ++r) {
+ bool hide = (r & 1) == 0;
+ view.setRowHidden(r, p, hide);
+ QCOMPARE(view.isRowHidden(r, p), hide);
+ }
+ for (int r = 0; r < rows; ++r)
+ parents.push(model.index(r, 0, p));
+ }
+
+ parents.push(QModelIndex());
+ while (!parents.isEmpty()) {
+ QModelIndex p = parents.pop();
+ // all even rows should still be hidden
+ for (int r = 0; r < model.rowCount(p); ++r)
+ QCOMPARE(view.isRowHidden(r, p), (r & 1) == 0);
+ if (model.rowCount(p) > 0) {
+ for (int r = 0; r < model.rowCount(p); ++r)
+ parents.push(model.index(r, 0, p));
+ }
+ }
+}
+
+void tst_QTreeView::noDelegate()
+{
+ QtTestModel model(10, 7);
+ QTreeView view;
+ view.setModel(&model);
+ view.setItemDelegate(0);
+ QCOMPARE(view.itemDelegate(), (QAbstractItemDelegate *)0);
+}
+
+void tst_QTreeView::noModel()
+{
+ QTreeView view;
+ view.show();
+ view.setRowHidden(0, QModelIndex(), true);
+}
+
+void tst_QTreeView::emptyModel()
+{
+ QtTestModel model;
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+ QVERIFY(!model.wrongIndex);
+}
+
+void tst_QTreeView::removeRows()
+{
+ QtTestModel model(7, 10);
+
+ QTreeView view;
+
+ view.setModel(&model);
+ view.show();
+
+ model.removeLastRow();
+ QVERIFY(!model.wrongIndex);
+
+ model.removeAllRows();
+ QVERIFY(!model.wrongIndex);
+}
+
+void tst_QTreeView::removeCols()
+{
+ QtTestModel model(5, 8);
+
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+ model.fetched = true;
+ model.removeLastColumn();
+ QVERIFY(!model.wrongIndex);
+ QCOMPARE(view.header()->count(), model.cols);
+
+ model.removeAllColumns();
+ QVERIFY(!model.wrongIndex);
+ QCOMPARE(view.header()->count(), model.cols);
+}
+
+void tst_QTreeView::expandAndCollapse_data()
+{
+ QTest::addColumn<bool>("animationEnabled");
+ QTest::newRow("normal") << false;
+ QTest::newRow("animated") << true;
+
+}
+
+void tst_QTreeView::expandAndCollapse()
+{
+ QFETCH(bool, animationEnabled);
+
+ QtTestModel model(10, 9);
+
+ QTreeView view;
+ view.setUniformRowHeights(true);
+ view.setModel(&model);
+ view.setAnimated(animationEnabled);
+ view.show();
+
+ QModelIndex a = model.index(0, 0, QModelIndex());
+ QModelIndex b = model.index(0, 0, a);
+
+ QSignalSpy expandedSpy(&view, SIGNAL(expanded(const QModelIndex&)));
+ QSignalSpy collapsedSpy(&view, SIGNAL(collapsed(const QModelIndex&)));
+ QVariantList args;
+
+ for (int y = 0; y < 2; ++y) {
+ view.setVisible(y == 0);
+ for (int x = 0; x < 2; ++x) {
+ view.setItemsExpandable(x == 0);
+
+ // Test bad args
+ view.expand(QModelIndex());
+ QCOMPARE(view.isExpanded(QModelIndex()), false);
+ view.collapse(QModelIndex());
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 0);
+
+ // expand a first level item
+ QVERIFY(!view.isExpanded(a));
+ view.expand(a);
+ QVERIFY(view.isExpanded(a));
+ QCOMPARE(expandedSpy.count(), 1);
+ QCOMPARE(collapsedSpy.count(), 0);
+ args = expandedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
+
+ view.expand(a);
+ QVERIFY(view.isExpanded(a));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 0);
+
+ // expand a second level item
+ QVERIFY(!view.isExpanded(b));
+ view.expand(b);
+ QVERIFY(view.isExpanded(a));
+ QVERIFY(view.isExpanded(b));
+ QCOMPARE(expandedSpy.count(), 1);
+ QCOMPARE(collapsedSpy.count(), 0);
+ args = expandedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
+
+ view.expand(b);
+ QVERIFY(view.isExpanded(b));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 0);
+
+ // collapse the first level item
+ view.collapse(a);
+ QVERIFY(!view.isExpanded(a));
+ QVERIFY(view.isExpanded(b));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 1);
+ args = collapsedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
+
+ view.collapse(a);
+ QVERIFY(!view.isExpanded(a));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 0);
+
+ // expand the first level item again
+ view.expand(a);
+ QVERIFY(view.isExpanded(a));
+ QVERIFY(view.isExpanded(b));
+ QCOMPARE(expandedSpy.count(), 1);
+ QCOMPARE(collapsedSpy.count(), 0);
+ args = expandedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
+
+ // collapse the second level item
+ view.collapse(b);
+ QVERIFY(view.isExpanded(a));
+ QVERIFY(!view.isExpanded(b));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 1);
+ args = collapsedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
+
+ // collapse the first level item
+ view.collapse(a);
+ QVERIFY(!view.isExpanded(a));
+ QVERIFY(!view.isExpanded(b));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 1);
+ args = collapsedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
+
+ // expand and remove row
+ QPersistentModelIndex c = model.index(9, 0, b);
+ view.expand(a);
+ view.expand(b);
+ model.removeLastRow(); // remove c
+ QVERIFY(view.isExpanded(a));
+ QVERIFY(view.isExpanded(b));
+ QVERIFY(!view.isExpanded(c));
+ QCOMPARE(expandedSpy.count(), 2);
+ QCOMPARE(collapsedSpy.count(), 0);
+ args = expandedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
+ args = expandedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
+
+ view.collapse(a);
+ view.collapse(b);
+ QVERIFY(!view.isExpanded(a));
+ QVERIFY(!view.isExpanded(b));
+ QVERIFY(!view.isExpanded(c));
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(collapsedSpy.count(), 2);
+ args = collapsedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
+ args = collapsedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
+ }
+ }
+}
+
+void tst_QTreeView::expandAndCollapseAll()
+{
+ QtTestModel model(3, 2);
+ model.levels = 2;
+ QTreeView view;
+ view.setUniformRowHeights(true);
+ view.setModel(&model);
+
+ QSignalSpy expandedSpy(&view, SIGNAL(expanded(const QModelIndex&)));
+ QSignalSpy collapsedSpy(&view, SIGNAL(collapsed(const QModelIndex&)));
+
+ view.expandAll();
+ view.show();
+
+ QCOMPARE(collapsedSpy.count(), 0);
+
+ QStack<QModelIndex> parents;
+ parents.push(QModelIndex());
+ int count = 0;
+ while (!parents.isEmpty()) {
+ QModelIndex p = parents.pop();
+ int rows = model.rowCount(p);
+ for (int r = 0; r < rows; ++r)
+ QVERIFY(view.isExpanded(model.index(r, 0, p)));
+ count += rows;
+ for (int r = 0; r < rows; ++r)
+ parents.push(model.index(r, 0, p));
+ }
+// ### why is expanded() signal not emitted?
+// QCOMPARE(expandedSpy.count(), count);
+
+ view.collapseAll();
+
+ QCOMPARE(expandedSpy.count(), 0);
+
+ parents.push(QModelIndex());
+ count = 0;
+ while (!parents.isEmpty()) {
+ QModelIndex p = parents.pop();
+ int rows = model.rowCount(p);
+ for (int r = 0; r < rows; ++r)
+ QVERIFY(!view.isExpanded(model.index(r, 0, p)));
+ count += rows;
+ for (int r = 0; r < rows; ++r)
+ parents.push(model.index(r, 0, p));
+ }
+// ### why is collapsed() signal not emitted?
+// QCOMPARE(collapsedSpy.count(), count);
+}
+
+void tst_QTreeView::expandWithNoChildren()
+{
+ QTreeView tree;
+ QStandardItemModel model(1,1);
+ tree.setModel(&model);
+ tree.setAnimated(true);
+ tree.doItemsLayout();
+ //this test should not output warnings
+ tree.expand(model.index(0,0));
+}
+
+
+
+void tst_QTreeView::keyboardNavigation()
+{
+ const int rows = 10;
+ const int columns = 7;
+
+ QtTestModel model(rows, columns);
+
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+
+ QVector<Qt::Key> keymoves;
+ keymoves << Qt::Key_Down << Qt::Key_Right << Qt::Key_Right << Qt::Key_Right
+ << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down
+ << Qt::Key_Right << Qt::Key_Right << Qt::Key_Right
+ << Qt::Key_Left << Qt::Key_Up << Qt::Key_Left << Qt::Key_Left
+ << Qt::Key_Up << Qt::Key_Down << Qt::Key_Up << Qt::Key_Up
+ << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up
+ << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down;
+
+ int row = 0;
+ int column = 0;
+ QModelIndex index = model.index(row, column, QModelIndex());
+ view.setCurrentIndex(index);
+ QCOMPARE(view.currentIndex(), index);
+
+ for (int i = 0; i < keymoves.size(); ++i) {
+ Qt::Key key = keymoves.at(i);
+ QTest::keyClick(&view, key);
+
+ switch (key) {
+ case Qt::Key_Up:
+ if (row > 0) {
+ index = index.sibling(row - 1, column);
+ row -= 1;
+ } else if (index.parent() != QModelIndex()) {
+ index = index.parent();
+ row = index.row();
+ }
+ break;
+ case Qt::Key_Down:
+ if (view.isExpanded(index)) {
+ row = 0;
+ index = index.child(row, column);
+ } else {
+ row = qMin(rows - 1, row + 1);
+ index = index.sibling(row, column);
+ }
+ break;
+ case Qt::Key_Left: {
+ QScrollBar *b = view.horizontalScrollBar();
+ if (b->value() == b->minimum())
+ QVERIFY(!view.isExpanded(index));
+ // windows style right will walk to the parent
+ if (view.currentIndex() != index) {
+ QCOMPARE(view.currentIndex(), index.parent());
+ index = view.currentIndex();
+ row = index.row();
+ column = index.column();
+ }
+ break;
+ }
+ case Qt::Key_Right:
+ QVERIFY(view.isExpanded(index));
+ // windows style right will walk to the first child
+ if (view.currentIndex() != index) {
+ QCOMPARE(view.currentIndex().parent(), index);
+ row = view.currentIndex().row();
+ column = view.currentIndex().column();
+ index = view.currentIndex();
+ }
+ break;
+ default:
+ QVERIFY(false);
+ }
+
+ QCOMPARE(view.currentIndex().row(), row);
+ QCOMPARE(view.currentIndex().column(), column);
+ QCOMPARE(view.currentIndex(), index);
+ }
+}
+
+class Dmodel : public QtTestModel
+{
+public:
+ Dmodel() : QtTestModel(10, 10){}
+
+ int columnCount(const QModelIndex &parent) const
+ {
+ if (parent.row() == 5)
+ return 1;
+ return QtTestModel::columnCount(parent);
+ }
+};
+
+void tst_QTreeView::headerSections()
+{
+ Dmodel model;
+
+ QTreeView view;
+ QHeaderView *header = view.header();
+
+ view.setModel(&model);
+ QModelIndex index = model.index(5, 0);
+ view.setRootIndex(index);
+ QCOMPARE(model.columnCount(QModelIndex()), 10);
+ QCOMPARE(model.columnCount(index), 1);
+ QCOMPARE(header->count(), model.columnCount(index));
+}
+
+void tst_QTreeView::moveCursor_data()
+{
+ QTest::addColumn<bool>("uniformRowHeights");
+ QTest::addColumn<bool>("scrollPerPixel");
+ QTest::newRow("uniformRowHeights = false, scrollPerPixel = false")
+ << false << false;
+ QTest::newRow("uniformRowHeights = true, scrollPerPixel = false")
+ << true << false;
+ QTest::newRow("uniformRowHeights = false, scrollPerPixel = true")
+ << false << true;
+ QTest::newRow("uniformRowHeights = true, scrollPerPixel = true")
+ << true << true;
+}
+
+void tst_QTreeView::moveCursor()
+{
+ QFETCH(bool, uniformRowHeights);
+ QFETCH(bool, scrollPerPixel);
+ QtTestModel model(8, 6);
+
+ PublicView view;
+ view.setUniformRowHeights(uniformRowHeights);
+ view.setModel(&model);
+ view.setRowHidden(0, QModelIndex(), true);
+ view.setVerticalScrollMode(scrollPerPixel ?
+ QAbstractItemView::ScrollPerPixel :
+ QAbstractItemView::ScrollPerItem);
+ QVERIFY(view.isRowHidden(0, QModelIndex()));
+ view.setColumnHidden(0, true);
+ QVERIFY(view.isColumnHidden(0));
+ view.show();
+ qApp->setActiveWindow(&view);
+
+ //here the first visible index should be selected
+ //because the view got the focus
+ QModelIndex expected = model.index(1, 1, QModelIndex());
+ QCOMPARE(view.currentIndex(), expected);
+
+ //then pressing down should go to the next line
+ QModelIndex actual = view.moveCursor(PublicView::MoveDown, Qt::NoModifier);
+ expected = model.index(2, 1, QModelIndex());
+ QCOMPARE(actual, expected);
+
+ view.setRowHidden(0, QModelIndex(), false);
+ view.setColumnHidden(0, false);
+
+ // PageUp was broken with uniform row heights turned on
+ view.setCurrentIndex(model.index(1, 0));
+ actual = view.moveCursor(PublicView::MovePageUp, Qt::NoModifier);
+ expected = model.index(0, 0, QModelIndex());
+ QCOMPARE(actual, expected);
+
+ //let's try another column
+ view.setCurrentIndex(model.index(1, 1));
+ view.setSelectionBehavior(QAbstractItemView::SelectItems);
+ QTest::keyClick(view.viewport(), Qt::Key_Up);
+ expected = model.index(0, 1, QModelIndex());
+ QCOMPARE(view.currentIndex(), expected);
+ QTest::keyClick(view.viewport(), Qt::Key_Down);
+ expected = model.index(1, 1, QModelIndex());
+ QCOMPARE(view.currentIndex(), expected);
+ QTest::keyClick(view.viewport(), Qt::Key_Up);
+ expected = model.index(0, 1, QModelIndex());
+ QCOMPARE(view.currentIndex(), expected);
+ view.setColumnHidden(0, true);
+ QTest::keyClick(view.viewport(), Qt::Key_Left);
+ expected = model.index(0, 1, QModelIndex()); //it shouldn't have changed
+ QCOMPARE(view.currentIndex(), expected);
+ view.setColumnHidden(0, false);
+ QTest::keyClick(view.viewport(), Qt::Key_Left);
+ expected = model.index(0, 0, QModelIndex());
+ QCOMPARE(view.currentIndex(), expected);
+}
+
+class TestDelegate : public QItemDelegate
+{
+public:
+ TestDelegate(QObject *parent) : QItemDelegate(parent) {}
+ QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(200, 50); }
+};
+
+typedef QList<QPoint> PointList;
+Q_DECLARE_METATYPE(PointList)
+
+void tst_QTreeView::setSelection_data()
+{
+ QTest::addColumn<QRect>("selectionRect");
+ QTest::addColumn<int>("selectionMode");
+ QTest::addColumn<int>("selectionCommand");
+ QTest::addColumn<PointList>("expectedItems");
+ QTest::addColumn<int>("verticalOffset");
+
+ QTest::newRow("(0,0,50,20),rows") << QRect(0,0,50,20)
+ << int(QAbstractItemView::SingleSelection)
+ << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
+ << (PointList()
+ << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
+ )
+ << 0;
+
+ QTest::newRow("(0,0,50,90),rows") << QRect(0,0,50,90)
+ << int(QAbstractItemView::ExtendedSelection)
+ << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
+ << (PointList()
+ << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
+ << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
+ )
+ << 0;
+
+ QTest::newRow("(50,0,0,90),rows,invalid rect") << QRect(QPoint(50, 0), QPoint(0, 90))
+ << int(QAbstractItemView::ExtendedSelection)
+ << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
+ << (PointList()
+ << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
+ << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
+ )
+ << 0;
+
+ QTest::newRow("(0,-20,20,50),rows") << QRect(0,-20,20,50)
+ << int(QAbstractItemView::ExtendedSelection)
+ << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
+ << (PointList()
+ << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
+ << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
+ )
+ << 1;
+ QTest::newRow("(0,-50,20,90),rows") << QRect(0,-50,20,90)
+ << int(QAbstractItemView::ExtendedSelection)
+ << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
+ << (PointList()
+ << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
+ << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
+ )
+ << 1;
+
+}
+
+void tst_QTreeView::setSelection()
+{
+ QFETCH(QRect, selectionRect);
+ QFETCH(int, selectionMode);
+ QFETCH(int, selectionCommand);
+ QFETCH(PointList, expectedItems);
+ QFETCH(int, verticalOffset);
+
+ QtTestModel model(10, 5);
+ model.levels = 1;
+ model.setDecorationsEnabled(true);
+ PublicView view;
+ view.resize(400, 300);
+ view.show();
+ view.setRootIsDecorated(false);
+ view.setItemDelegate(new TestDelegate(&view));
+ view.setSelectionMode(QAbstractItemView::SelectionMode(selectionMode));
+ view.setModel(&model);
+ view.setUniformRowHeights(true);
+ view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
+ view.scrollTo(model.index(verticalOffset, 0), QAbstractItemView::PositionAtTop);
+ view.setSelection(selectionRect, QItemSelectionModel::SelectionFlags(selectionCommand));
+ QItemSelectionModel *selectionModel = view.selectionModel();
+ QVERIFY(selectionModel);
+
+ QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
+ QCOMPARE(selectedIndexes.count(), expectedItems.count());
+ for (int i = 0; i < selectedIndexes.count(); ++i) {
+ QModelIndex idx = selectedIndexes.at(i);
+ QVERIFY(expectedItems.contains(QPoint(idx.column(), idx.row())));
+ }
+}
+
+void tst_QTreeView::indexAbove()
+{
+ QtTestModel model(6, 7);
+ model.levels = 2;
+ QTreeView view;
+
+ QCOMPARE(view.indexAbove(QModelIndex()), QModelIndex());
+ view.setModel(&model);
+ QCOMPARE(view.indexAbove(QModelIndex()), QModelIndex());
+
+ QStack<QModelIndex> parents;
+ parents.push(QModelIndex());
+ while (!parents.isEmpty()) {
+ QModelIndex p = parents.pop();
+ if (model.canFetchMore(p))
+ model.fetchMore(p);
+ int rows = model.rowCount(p);
+ for (int r = rows - 1; r > 0; --r) {
+ QModelIndex idx = model.index(r, 0, p);
+ QModelIndex expected = model.index(r - 1, 0, p);
+ QCOMPARE(view.indexAbove(idx), expected);
+ }
+ // hide even rows
+ for (int r = 0; r < rows; r+=2)
+ view.setRowHidden(r, p, true);
+ for (int r = rows - 1; r > 0; r-=2) {
+ QModelIndex idx = model.index(r, 0, p);
+ QModelIndex expected = model.index(r - 2, 0, p);
+ QCOMPARE(view.indexAbove(idx), expected);
+ }
+// for (int r = 0; r < rows; ++r)
+// parents.push(model.index(r, 0, p));
+ }
+}
+
+void tst_QTreeView::indexBelow()
+{
+ QtTestModel model(2, 1);
+
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex i = model.index(0, 0, view.rootIndex());
+ QVERIFY(i.isValid());
+ QCOMPARE(i.row(), 0);
+
+ i = view.indexBelow(i);
+ QVERIFY(i.isValid());
+ QCOMPARE(i.row(), 1);
+ i = view.indexBelow(i);
+ QVERIFY(!i.isValid());
+}
+
+void tst_QTreeView::clicked()
+{
+ QtTestModel model(10, 2);
+
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex firstIndex = model.index(0, 0, QModelIndex());
+ QVERIFY(firstIndex.isValid());
+ int itemHeight = view.visualRect(firstIndex).height();
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ view.resize(200, itemHeight * (model.rows + 2));
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QPoint p(itemOffset, 1 + itemHeight * i);
+ QModelIndex index = view.indexAt(p);
+ if (!index.isValid())
+ continue;
+ QSignalSpy spy(&view, SIGNAL(clicked(const QModelIndex&)));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QTRY_COMPARE(spy.count(), 1);
+ }
+}
+
+void tst_QTreeView::mouseDoubleClick()
+{
+ // Test double clicks outside the viewport.
+ // (Should be a no-op and should not expand any item.)
+
+ QStandardItemModel model(20, 2);
+ for (int i = 0; i < model.rowCount(); i++) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.insertRows(0, 20, index);
+ model.insertColumns(0,2,index);
+ for (int i1 = 0; i1 < model.rowCount(index); i1++) {
+ QModelIndex index2 = model.index(i1, 0, index);
+ }
+ }
+
+ QTreeView view;
+ view.setModel(&model);
+
+ // make sure the viewport height is smaller than the contents height.
+ view.resize(200,200);
+ view.move(0,0);
+ view.show();
+ QModelIndex index = model.index(0, 0, QModelIndex());
+ view.setCurrentIndex(index);
+
+ view.setExpanded(model.index(0,0, QModelIndex()), true);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+
+ // Make sure all items are collapsed
+ for (int i = 0; i < model.rowCount(QModelIndex()); i++) {
+ view.setExpanded(model.index(i,0, QModelIndex()), false);
+ }
+
+ int maximum = view.verticalScrollBar()->maximum();
+
+ // Doubleclick in the bottom right corner, in the unused area between the vertical and horizontal scrollbar.
+ int vsw = view.verticalScrollBar()->width();
+ int hsh = view.horizontalScrollBar()->height();
+ QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, QPoint(view.width() - vsw + 1, view.height() - hsh + 1));
+ // Should not have expanded, thus maximum() should have the same value.
+ QCOMPARE(maximum, view.verticalScrollBar()->maximum());
+
+ view.setExpandsOnDoubleClick(false);
+ QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, view.visualRect(index).center());
+ QVERIFY(!view.isExpanded(index));
+}
+
+void tst_QTreeView::rowsAboutToBeRemoved()
+{
+ QStandardItemModel model(3, 1);
+ for (int i = 0; i < model.rowCount(); i++) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, QString("%1").arg(i));
+ model.insertRows(0, 4, index);
+ model.insertColumns(0,1,index);
+ for (int i1 = 0; i1 < model.rowCount(index); i1++) {
+ QModelIndex index2 = model.index(i1, 0, index);
+ model.setData(index2, QString("%1%2").arg(i).arg(i1));
+ }
+ }
+
+ PublicView view;
+ view.setModel(&model);
+ view.show();
+ QModelIndex index = model.index(0,0, QModelIndex());
+ view.setCurrentIndex(index);
+ view.setExpanded(model.index(0,0, QModelIndex()), true);
+
+ for (int i = 0; i < model.rowCount(QModelIndex()); i++) {
+ view.setExpanded(model.index(i,0, QModelIndex()), true);
+ }
+
+ QSignalSpy spy1(&model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+
+ model.removeRows(1,1);
+ QCOMPARE(view.state(), 0);
+ // Should not be 5 (or any other number for that sake :)
+ QCOMPARE(spy1.count(), 1);
+
+}
+
+void tst_QTreeView::headerSections_unhideSection()
+{
+ QtTestModel model(10, 7);
+
+ QTreeView view;
+
+ view.setModel(&model);
+ view.show();
+ int size = view.header()->sectionSize(0);
+ view.setColumnHidden(0, true);
+
+ // should go back to old size
+ view.setColumnHidden(0, false);
+ QCOMPARE(size, view.header()->sectionSize(0));
+}
+
+void tst_QTreeView::columnAt()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+ QTreeView view;
+ view.resize(500,500);
+ view.setModel(&model);
+
+ QCOMPARE(view.columnAt(0), 0);
+ // really this is testing the header... so not much more should be needed if the header is working...
+}
+
+void tst_QTreeView::scrollTo()
+{
+#define CHECK_VISIBLE(ROW,COL) QVERIFY(QRect(QPoint(),view.viewport()->size()).contains(\
+ view.visualRect(model.index((ROW),(COL),QModelIndex()))))
+
+ QtTestModel model;
+ model.rows = model.cols = 100;
+ QTreeView view;
+ view.setUniformRowHeights(true);
+ view.scrollTo(QModelIndex(), QTreeView::PositionAtTop);
+ view.setModel(&model);
+
+ // ### check the scrollbar values an make sure it actually scrolls to the item
+ // ### check for bot item based and pixel based scrolling
+ // ### create a data function for this test
+
+ view.scrollTo(QModelIndex());
+ view.scrollTo(model.index(0,0,QModelIndex()));
+ view.scrollTo(model.index(0,0,QModelIndex()), QTreeView::PositionAtTop);
+ view.scrollTo(model.index(0,0,QModelIndex()), QTreeView::PositionAtBottom);
+
+ //
+
+ view.show();
+ view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem); //some styles change that in Polish
+
+ view.resize(300, 200);
+ //view.verticalScrollBar()->setValue(0);
+
+ view.scrollTo(model.index(0,0,QModelIndex()));
+ CHECK_VISIBLE(0,0);
+ QCOMPARE(view.verticalScrollBar()->value(), 0);
+
+ view.header()->resizeSection(0, 5); // now we only see the branches
+ view.scrollTo(model.index(5, 0, QModelIndex()), QTreeView::PositionAtTop);
+ QCOMPARE(view.verticalScrollBar()->value(), 5);
+
+ view.scrollTo(model.index(60, 60, QModelIndex()));
+
+ CHECK_VISIBLE(60,60);
+ view.scrollTo(model.index(60, 30, QModelIndex()));
+ CHECK_VISIBLE(60,30);
+ view.scrollTo(model.index(30, 30, QModelIndex()));
+ CHECK_VISIBLE(30,30);
+
+ // TODO force it to move to the left and then the right
+}
+
+void tst_QTreeView::rowsAboutToBeRemoved_move()
+{
+ QStandardItemModel model(3,1);
+ QTreeView view;
+ view.setModel(&model);
+ QModelIndex indexThatWantsToLiveButWillDieDieITellYou;
+ QModelIndex parent = model.index(2, 0 );
+ view.expand(parent);
+ for (int i = 0; i < 6; ++i) {
+ model.insertRows(0, 1, parent);
+ model.insertColumns(0, 1, parent);
+ QModelIndex index = model.index(0, 0, parent);
+ view.expand(index);
+ if ( i == 3 )
+ indexThatWantsToLiveButWillDieDieITellYou = index;
+ model.setData(index, i);
+ parent = index;
+ }
+ view.resize(600,800);
+ view.show();
+ view.doItemsLayout();
+ static_cast<PublicView *>(&view)->executeDelayedItemsLayout();
+ parent = indexThatWantsToLiveButWillDieDieITellYou.parent();
+ QCOMPARE(view.isExpanded(indexThatWantsToLiveButWillDieDieITellYou), true);
+ QCOMPARE(parent.isValid(), true);
+ QCOMPARE(parent.parent().isValid(), true);
+ view.expand(parent);
+ QCOMPARE(view.isExpanded(parent), true);
+ QCOMPARE(view.isExpanded(indexThatWantsToLiveButWillDieDieITellYou), true);
+ model.removeRow(0, indexThatWantsToLiveButWillDieDieITellYou);
+ QCOMPARE(view.isExpanded(parent), true);
+ QCOMPARE(view.isExpanded(indexThatWantsToLiveButWillDieDieITellYou), true);
+}
+
+void tst_QTreeView::resizeColumnToContents()
+{
+ QStandardItemModel model(50,2);
+ for (int r = 0; r < model.rowCount(); ++r) {
+ for (int c = 0; c < model.columnCount(); ++c) {
+ QModelIndex idx = model.index(r, c);
+ model.setData(idx, QString::fromAscii("%1,%2").arg(r).arg(c) );
+ model.insertColumns(0, 2, idx);
+ model.insertRows(0, 6, idx);
+ for (int i = 0; i < 6; ++i) {
+ for (int j = 0; j < 2 ; ++j) {
+ model.setData(model.index(i, j, idx), QString::fromAscii("child%1%2").arg(i).arg(j));
+ }
+ }
+ }
+ }
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+ qApp->processEvents(); //must have this, or else it will not scroll
+ view.scrollToBottom();
+ view.resizeColumnToContents(0);
+ int oldColumnSize = view.header()->sectionSize(0);
+ view.setRootIndex(model.index(0, 0));
+ view.resizeColumnToContents(0); //Earlier, this gave an assert
+ QVERIFY(view.header()->sectionSize(0) > oldColumnSize);
+}
+
+void tst_QTreeView::insertAfterSelect()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+ QModelIndex firstIndex = model.index(0, 0, QModelIndex());
+ QVERIFY(firstIndex.isValid());
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ QPoint p(itemOffset, 1);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QVERIFY(view.selectionModel()->isSelected(firstIndex));
+ model.insertNewRow();
+ QVERIFY(view.selectionModel()->isSelected(firstIndex)); // Should still be selected
+}
+
+void tst_QTreeView::removeAfterSelect()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+ QModelIndex firstIndex = model.index(0, 0, QModelIndex());
+ QVERIFY(firstIndex.isValid());
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ QPoint p(itemOffset, 1);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QVERIFY(view.selectionModel()->isSelected(firstIndex));
+ model.removeLastRow();
+ QVERIFY(view.selectionModel()->isSelected(firstIndex)); // Should still be selected
+}
+
+void tst_QTreeView::hiddenItems()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+
+ QModelIndex firstIndex = model.index(1, 0, QModelIndex());
+ QVERIFY(firstIndex.isValid());
+ if (model.canFetchMore(firstIndex))
+ model.fetchMore(firstIndex);
+ for (int i=0; i < model.rowCount(firstIndex); i++)
+ view.setRowHidden(i , firstIndex, true );
+
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ int itemHeight = view.visualRect(firstIndex).height();
+ QPoint p(itemOffset, itemHeight + 1);
+ view.setExpanded(firstIndex, false);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(view.isExpanded(firstIndex), false);
+
+ p.setX( 5 );
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(view.isExpanded(firstIndex), false);
+}
+
+void tst_QTreeView::spanningItems()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+ PublicView view;
+ view.setModel(&model);
+ view.show();
+
+ int itemWidth = view.header()->sectionSize(0);
+ int itemHeight = view.visualRect(model.index(0, 0, QModelIndex())).height();
+
+ // every second row is spanning
+ for (int i = 1; i < model.rowCount(QModelIndex()); i += 2)
+ view.setFirstColumnSpanned(i , QModelIndex(), true);
+
+ // non-spanning item
+ QPoint p(itemWidth / 2, itemHeight / 2); // column 0, row 0
+ view.setCurrentIndex(QModelIndex());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(view.currentIndex(), model.index(0, 0, QModelIndex()));
+ QCOMPARE(view.header()->sectionSize(0) - view.indentation(),
+ view.visualRect(model.index(0, 0, QModelIndex())).width());
+
+ // spanning item
+ p.setX(itemWidth + (itemWidth / 2)); // column 1
+ p.setY(itemHeight + (itemHeight / 2)); // row 1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(view.currentIndex(), model.index(1, 0, QModelIndex()));
+ QCOMPARE(view.header()->length() - view.indentation(),
+ view.visualRect(model.index(1, 0, QModelIndex())).width());
+
+ // size hint
+ // every second row is un-spanned
+ QStyleOptionViewItem option = view.viewOptions();
+ int w = view.header()->sectionSizeHint(0);
+ for (int i = 0; i < model.rowCount(QModelIndex()); ++i) {
+ if (!view.isFirstColumnSpanned(i, QModelIndex())) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ w = qMax(w, view.itemDelegate(index)->sizeHint(option, index).width() + view.indentation());
+ }
+ }
+ QCOMPARE(view.sizeHintForColumn(0), w);
+}
+
+void tst_QTreeView::selectionOrderTest()
+{
+ QVERIFY(((QItemSelectionModel*)sender())->currentIndex().row() != -1);
+}
+
+void tst_QTreeView::selection()
+{
+ QTreeView treeView;
+ QStandardItemModel m(10, 2);
+ for (int i = 0;i < 10; ++i)
+ m.setData(m.index(i, 0), i);
+ treeView.setModel(&m);
+
+ treeView.setSelectionBehavior(QAbstractItemView::SelectRows);
+ treeView.setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ connect(treeView.selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
+ this, SLOT(selectionOrderTest()));
+
+ treeView.show();
+
+ QTest::mousePress(treeView.viewport(), Qt::LeftButton, 0, treeView.visualRect(m.index(1, 0)).center());
+ QTest::keyPress(treeView.viewport(), Qt::Key_Down);
+}
+
+//From task 151686 QTreeView ExtendedSelection selects hidden rows
+void tst_QTreeView::selectionWithHiddenItems()
+{
+ QStandardItemModel model;
+ for (int i = 0; i < model.rowCount(); ++i)
+ model.setData(model.index(i,0), QString("row %1").arg(i));
+
+ QStandardItem item0("row 0");
+ QStandardItem item1("row 1");
+ QStandardItem item2("row 2");
+ QStandardItem item3("row 3");
+ model.appendColumn( QList<QStandardItem*>() << &item0 << &item1 << &item2 << &item3);
+
+ QStandardItem child("child");
+ item1.appendRow( &child);
+
+ QTreeView view;
+ view.setModel(&model);
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.show();
+ qApp->processEvents();
+
+ //child should not be selected as it is hidden (its parent is not expanded)
+ view.selectAll();
+ QCOMPARE(view.selectionModel()->selection().count(), 1); //one range
+ QCOMPARE(view.selectionModel()->selectedRows().count(), 4);
+ view.expandAll();
+ QVERIFY(view.isExpanded(item1.index()));
+ QCOMPARE(view.selectionModel()->selection().count(), 1);
+ QCOMPARE(view.selectionModel()->selectedRows().count(), 4);
+ QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&child)));
+ view.clearSelection();
+ QVERIFY(view.isExpanded(item1.index()));
+
+ //child should be selected as it is visible (its parent is expanded)
+ view.selectAll();
+ QCOMPARE(view.selectionModel()->selection().count(), 2);
+ QCOMPARE(view.selectionModel()->selectedRows().count(), 5); //everything is selected
+ view.clearSelection();
+
+ //we hide the node with a child (there should then be 3 items selected in 2 ranges)
+ view.setRowHidden(1, QModelIndex(), true);
+ QVERIFY(view.isExpanded(item1.index()));
+ qApp->processEvents();
+ view.selectAll();
+ QCOMPARE(view.selectionModel()->selection().count(), 2);
+ QCOMPARE(view.selectionModel()->selectedRows().count(), 3);
+ QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&item1)));
+ QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&child)));
+
+ view.setRowHidden(1, QModelIndex(), false);
+ QVERIFY(view.isExpanded(item1.index()));
+ view.clearSelection();
+
+ //we hide a node without children (there should then be 4 items selected in 3 ranges)
+ view.setRowHidden(2, QModelIndex(), true);
+ qApp->processEvents();
+ QVERIFY(view.isExpanded(item1.index()));
+ view.selectAll();
+ QVERIFY(view.isExpanded(item1.index()));
+ QCOMPARE(view.selectionModel()->selection().count(), 3);
+ QCOMPARE(view.selectionModel()->selectedRows().count(), 4);
+ QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&item2)));
+ view.setRowHidden(2, QModelIndex(), false);
+ QVERIFY(view.isExpanded(item1.index()));
+ view.clearSelection();
+}
+
+void tst_QTreeView::selectAll()
+{
+ QStandardItemModel model(4,4);
+ PublicView view2;
+ view2.setModel(&model);
+ view2.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view2.selectAll(); // Should work with an empty model
+ //everything should be selected since we are in ExtendedSelection mode
+ QCOMPARE(view2.selectedIndexes().count(), model.rowCount() * model.columnCount());
+
+ for (int i = 0; i < model.rowCount(); ++i)
+ model.setData(model.index(i,0), QString("row %1").arg(i));
+ PublicView view;
+ view.setModel(&model);
+ int selectedCount = view.selectedIndexes().count();
+ view.selectAll();
+ QCOMPARE(view.selectedIndexes().count(), selectedCount);
+}
+
+void tst_QTreeView::extendedSelection_data()
+{
+ QTest::addColumn<QPoint>("mousePressPos");
+ QTest::addColumn<int>("selectedCount");
+
+ QTest::newRow("select") << QPoint(10, 10) << 2;
+ QTest::newRow("unselect") << QPoint(10, 150) << 0;
+}
+
+void tst_QTreeView::extendedSelection()
+{
+ QFETCH(QPoint, mousePressPos);
+ QFETCH(int, selectedCount);
+
+ QStandardItemModel model(5, 2);
+ QWidget topLevel;
+ QTreeView view(&topLevel);
+ view.resize(qMax(mousePressPos.x() * 2, 200), qMax(mousePressPos.y() * 2, 200));
+ view.setModel(&model);
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ topLevel.show();
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, mousePressPos);
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedCount);
+}
+
+void tst_QTreeView::rowSizeHint()
+{
+ //tests whether the correct visible columns are taken into account when
+ //calculating the height of a line
+ QStandardItemModel model(1,3);
+ model.setData( model.index(0,0), QSize(20,40), Qt::SizeHintRole);
+ model.setData( model.index(0,1), QSize(20,10), Qt::SizeHintRole);
+ model.setData( model.index(0,2), QSize(20,10), Qt::SizeHintRole);
+ QTreeView view;
+ view.setModel(&model);
+
+ view.header()->moveSection(1, 0); //the 2nd column goes to the 1st place
+
+ view.show();
+
+ //it must be 40 since the tallest item that defines the height of a line
+ QCOMPARE( view.visualRect(model.index(0,0)).height(), 40);
+ QCOMPARE( view.visualRect(model.index(0,1)).height(), 40);
+ QCOMPARE( view.visualRect(model.index(0,2)).height(), 40);
+}
+
+
+//From task 155449 (QTreeWidget has a large width for the first section when sorting
+//is turned on before items are added)
+void tst_QTreeView::setSortingEnabled()
+{
+ //1st the treeview is a top-level
+ {
+ QTreeView view;
+ QStandardItemModel model(1,1);
+ view.setModel(&model);
+ const int size = view.header()->sectionSize(0);
+ view.setSortingEnabled(true);
+ model.setColumnCount(3);
+ //we test that changing the column count doesn't change the 1st column size
+ QCOMPARE(view.header()->sectionSize(0), size);
+ }
+
+ //then it is no more a top-level
+ {
+ QMainWindow win;
+ QTreeView view;
+ QStandardItemModel model(1,1);
+ view.setModel(&model);
+ win.setCentralWidget(&view);
+ const int size = view.header()->sectionSize(0);
+ view.setSortingEnabled(true);
+ model.setColumnCount(3);
+ //we test that changing the column count doesn't change the 1st column size
+ QCOMPARE(view.header()->sectionSize(0), size);
+ }
+}
+
+void tst_QTreeView::headerHidden()
+{
+ QTreeView view;
+ QStandardItemModel model;
+ view.setModel(&model);
+ QCOMPARE(view.isHeaderHidden(), false);
+ QCOMPARE(view.header()->isHidden(), false);
+ view.setHeaderHidden(true);
+ QCOMPARE(view.isHeaderHidden(), true);
+ QCOMPARE(view.header()->isHidden(), true);
+}
+
+// From Task 145199 (crash when column 0 having at least one expanded item is removed and then
+// inserted). The test passes simply if it doesn't crash, hence there are no calls
+// to QCOMPARE() or QVERIFY().
+void tst_QTreeView::removeAndInsertExpandedCol0()
+{
+ QTreeView view;
+ QStandardItemModel model;
+ view.setModel(&model);
+
+ model.setColumnCount(1);
+
+ QStandardItem *item0 = new QStandardItem(QString("item 0"));
+ model.invisibleRootItem()->appendRow(item0);
+ view.expand(item0->index());
+ QStandardItem *item1 = new QStandardItem(QString("item 1"));
+ item0->appendRow(item1);
+
+ model.removeColumns(0, 1);
+ model.insertColumns(0, 1);
+
+ view.show();
+ qApp->processEvents();
+}
+
+void tst_QTreeView::disabledButCheckable()
+{
+ QTreeView view;
+ QStandardItemModel model;
+ QStandardItem *item;
+ item = new QStandardItem(QLatin1String("Row 1 Item"));
+ model.insertRow(0, item);
+
+ item = new QStandardItem(QLatin1String("Row 2 Item"));
+ item->setCheckable(true);
+ item->setEnabled(false);
+ model.insertRow(1, item);
+
+ view.setModel(&model);
+ view.setCurrentIndex(model.index(1,0));
+ QCOMPARE(item->checkState(), Qt::Unchecked);
+ view.show();
+
+ QTest::keyClick(&view, Qt::Key_Space);
+ QCOMPARE(item->checkState(), Qt::Unchecked);
+}
+
+void tst_QTreeView::sortByColumn_data()
+{
+ QTest::addColumn<bool>("sortingEnabled");
+ QTest::newRow("sorting enabled") << true;
+ QTest::newRow("sorting disabled") << false;
+}
+
+// Checks sorting and that sortByColumn also sets the sortIndicator
+void tst_QTreeView::sortByColumn()
+{
+ QFETCH(bool, sortingEnabled);
+ QTreeView view;
+ QStandardItemModel model(4,2);
+ model.setItem(0,0,new QStandardItem("b"));
+ model.setItem(1,0,new QStandardItem("d"));
+ model.setItem(2,0,new QStandardItem("c"));
+ model.setItem(3,0,new QStandardItem("a"));
+ model.setItem(0,1,new QStandardItem("e"));
+ model.setItem(1,1,new QStandardItem("g"));
+ model.setItem(2,1,new QStandardItem("h"));
+ model.setItem(3,1,new QStandardItem("f"));
+
+ view.setSortingEnabled(sortingEnabled);
+ view.setModel(&model);
+ view.sortByColumn(1);
+ QCOMPARE(view.header()->sortIndicatorSection(), 1);
+ QCOMPARE(view.model()->data(view.model()->index(0,1)).toString(), QString::fromLatin1("h"));
+ QCOMPARE(view.model()->data(view.model()->index(1,1)).toString(), QString::fromLatin1("g"));
+ view.sortByColumn(0, Qt::AscendingOrder);
+ QCOMPARE(view.header()->sortIndicatorSection(), 0);
+ QCOMPARE(view.model()->data(view.model()->index(0,0)).toString(), QString::fromLatin1("a"));
+ QCOMPARE(view.model()->data(view.model()->index(1,0)).toString(), QString::fromLatin1("b"));
+}
+
+/*
+ This is a model that every time kill() is called it will completely change
+ all of its nodes for new nodes. It then qFatal's if you later use a dead node.
+ */
+class EvilModel: public QAbstractItemModel
+{
+
+public:
+ class Node {
+ public:
+ Node(Node *p = 0, int level = 0) : parent(p), isDead(false) {
+ populate(level);
+ }
+ ~Node()
+ {
+ qDeleteAll(children.begin(), children.end());
+ qDeleteAll(deadChildren.begin(), deadChildren.end());
+ }
+
+ void populate(int level = 0) {
+ if (level < 4)
+ for (int i = 0; i < 5; ++i)
+ children.append(new Node(this, level + 1));
+ }
+ void kill() {
+ for (int i = children.count() -1; i >= 0; --i) {
+ children.at(i)->kill();
+ if (parent == 0) {
+ deadChildren.append(children.at(i));
+ children.removeAt(i);
+ }
+ }
+ if (parent == 0) {
+ if (!children.isEmpty())
+ qFatal("%s: children should be empty when parent is null", Q_FUNC_INFO);
+ populate();
+ } else {
+ isDead = true;
+ }
+ }
+
+ QList<Node*> children;
+ QList<Node*> deadChildren;
+ Node *parent;
+ bool isDead;
+ };
+
+ Node *root;
+
+ EvilModel(QObject *parent = 0): QAbstractItemModel(parent), root(new Node)
+ {
+ }
+ ~EvilModel()
+ {
+ delete root;
+ }
+
+ void change()
+ {
+ emit layoutAboutToBeChanged();
+ QModelIndexList oldList = persistentIndexList();
+ QList<QStack<int> > oldListPath;
+ for (int i = 0; i < oldList.count(); ++i) {
+ QModelIndex idx = oldList.at(i);
+ QStack<int> path;
+ while (idx.isValid()) {
+ path.push(idx.row());
+ idx = idx.parent();
+ }
+ oldListPath.append(path);
+ }
+ root->kill();
+
+ QModelIndexList newList;
+ for (int i = 0; i < oldListPath.count(); ++i) {
+ QStack<int> path = oldListPath[i];
+ QModelIndex idx;
+ while(!path.isEmpty()) {
+ idx = index(path.pop(), 0, idx);
+ }
+ newList.append(idx);
+ }
+
+ changePersistentIndexList(oldList, newList);
+ emit layoutChanged();
+ }
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const {
+ Node *parentNode = root;
+ if (parent.isValid()) {
+ parentNode = static_cast<Node*>(parent.internalPointer());
+ if (parentNode->isDead)
+ qFatal("%s: parentNode is dead!", Q_FUNC_INFO);
+ }
+ return parentNode->children.count();
+ }
+ int columnCount(const QModelIndex& parent = QModelIndex()) const {
+ if (parent.column() > 0)
+ return 0;
+ return 1;
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+ {
+ Node *grandparentNode = static_cast<Node*>(parent.internalPointer());
+ Node *parentNode = root;
+ if (parent.isValid()) {
+ if (grandparentNode->isDead)
+ qFatal("%s: grandparentNode is dead!", Q_FUNC_INFO);
+ parentNode = grandparentNode->children[parent.row()];
+ if (parentNode->isDead)
+ qFatal("%s: grandparentNode is dead!", Q_FUNC_INFO);
+ }
+ return createIndex(row, column, parentNode);
+ }
+
+ QModelIndex parent(const QModelIndex &index) const
+ {
+ Node *parent = static_cast<Node*>(index.internalPointer());
+ Node *grandparent = parent->parent;
+ if (!grandparent)
+ return QModelIndex();
+ return createIndex(grandparent->children.indexOf(parent), 0, grandparent);
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (idx.isValid() && role == Qt::DisplayRole) {
+ Node *parentNode = root;
+ if (idx.isValid()) {
+ parentNode = static_cast<Node*>(idx.internalPointer());
+ if (parentNode->isDead)
+ qFatal("%s: grandparentNode is dead!", Q_FUNC_INFO);
+ }
+ return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column())
+ .arg(parentNode->isDead ? "dead" : "alive");
+ }
+ return QVariant();
+ }
+};
+
+void tst_QTreeView::evilModel_data()
+{
+ QTest::addColumn<bool>("visible");
+ QTest::newRow("visible") << false;
+}
+
+void tst_QTreeView::evilModel()
+{
+ QFETCH(bool, visible);
+ // init
+ PublicView view;
+ EvilModel model;
+ view.setModel(&model);
+ view.setVisible(visible);
+ QPersistentModelIndex firstLevel = model.index(0, 0);
+ QPersistentModelIndex secondLevel = model.index(1, 0, firstLevel);
+ QPersistentModelIndex thirdLevel = model.index(2, 0, secondLevel);
+ view.setExpanded(firstLevel, true);
+ view.setExpanded(secondLevel, true);
+ view.setExpanded(thirdLevel, true);
+ model.change();
+
+ // tests
+ view.setRowHidden(0, firstLevel, true);
+ model.change();
+
+ return;
+ view.setFirstColumnSpanned(1, QModelIndex(), true);
+ model.change();
+
+ view.expand(secondLevel);
+ model.change();
+
+ view.collapse(secondLevel);
+ model.change();
+
+ view.isExpanded(secondLevel);
+ view.setCurrentIndex(firstLevel);
+ model.change();
+
+ view.keyboardSearch("foo");
+ model.change();
+
+ view.visualRect(secondLevel);
+ model.change();
+
+ view.scrollTo(thirdLevel);
+ model.change();
+
+ view.repaint();
+ model.change();
+
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton);
+ model.change();
+
+ view.indexAt(QPoint(10, 10));
+ model.change();
+
+ view.indexAbove(model.index(2, 0));
+ model.change();
+
+ view.indexBelow(model.index(1, 0));
+ model.change();
+
+ QRect rect(0, 0, 10, 10);
+ view.setSelection(rect, QItemSelectionModel::Select);
+ model.change();
+
+ view.moveCursor(PublicView::MoveDown, Qt::NoModifier);
+ model.change();
+
+ view.resizeColumnToContents(1);
+ model.change();
+
+ view.QAbstractItemView::sizeHintForColumn(1);
+ model.change();
+
+ view.rowHeight(secondLevel);
+ model.change();
+
+ view.setRootIsDecorated(true);
+ model.change();
+
+ view.setItemsExpandable(false);
+ model.change();
+
+ view.columnViewportPosition(0);
+ model.change();
+
+ view.columnWidth(0);
+ model.change();
+
+ view.setColumnWidth(0, 30);
+ model.change();
+
+ view.columnAt(15);
+ model.change();
+
+ view.isColumnHidden(1);
+ model.change();
+
+ view.setColumnHidden(2, true);
+ model.change();
+
+ view.isHeaderHidden();
+ model.change();
+
+ view.setHeaderHidden(true);
+ model.change();
+
+ view.isRowHidden(2, secondLevel);
+ model.change();
+
+ view.setRowHidden(3, secondLevel, true);
+ model.change();
+
+ view.isFirstColumnSpanned(3, thirdLevel);
+ model.change();
+
+ view.setSortingEnabled(true);
+ model.change();
+
+ view.isSortingEnabled();
+ model.change();
+
+ view.setAnimated(true);
+ model.change();
+
+ view.isAnimated();
+ model.change();
+
+ view.setAllColumnsShowFocus(true);
+ model.change();
+
+ view.allColumnsShowFocus();
+ model.change();
+
+ view.doItemsLayout();
+ model.change();
+
+ view.reset();
+ model.change();
+
+ view.sortByColumn(1, Qt::AscendingOrder);
+ model.change();
+
+ view.dataChanged(secondLevel, secondLevel);
+ model.change();
+
+ view.hideColumn(1);
+ model.change();
+
+ view.showColumn(1);
+ model.change();
+
+ view.resizeColumnToContents(1);
+ model.change();
+
+ view.sortByColumn(1);
+ model.change();
+
+ view.selectAll();
+ model.change();
+
+ view.expandAll();
+ model.change();
+
+ view.collapseAll();
+ model.change();
+
+ view.expandToDepth(3);
+ model.change();
+
+ view.setRootIndex(secondLevel);
+}
+
+void tst_QTreeView::indexRowSizeHint()
+{
+ QStandardItemModel model(10, 1);
+ PublicView view;
+
+ view.setModel(&model);
+
+ QModelIndex index = model.index(5, 0);
+ QPushButton *w = new QPushButton("Test");
+ view.setIndexWidget(index, w);
+
+ view.show();
+
+ QCOMPARE(view.indexRowSizeHint(index), w->sizeHint().height());
+}
+
+void tst_QTreeView::filterProxyModelCrash()
+{
+ QStandardItemModel model;
+ QList<QStandardItem *> items;
+ for (int i = 0; i < 100; i++)
+ items << new QStandardItem(QString::fromLatin1("item %1").arg(i));
+ model.appendColumn(items);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QTreeView view;
+ view.setModel(&proxy);
+ view.show();
+ QTest::qWait(30);
+ proxy.invalidate();
+ view.verticalScrollBar()->setValue(15);
+ QTest::qWait(20);
+
+ proxy.invalidate();
+ view.repaint(); //used to crash
+}
+
+void tst_QTreeView::styleOptionViewItem()
+{
+ class MyDelegate : public QStyledItemDelegate
+ {
+ public:
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
+ {
+ QVERIFY(qstyleoption_cast<const QStyleOptionViewItemV4 *>(&option));
+ QStyleOptionViewItemV4 opt(option);
+ initStyleOption(&opt, index);
+
+ QVERIFY(!opt.text.isEmpty());
+ QCOMPARE(opt.index, index);
+ //qDebug() << index << opt.text;
+
+ if (allCollapsed)
+ QCOMPARE(!(opt.features & QStyleOptionViewItemV2::Alternate), !(index.row() % 2));
+ QCOMPARE(!(opt.features & QStyleOptionViewItemV2::HasCheckIndicator), !opt.text.contains("Checkable"));
+
+ if (opt.text.contains("Beginning"))
+ QCOMPARE(opt.viewItemPosition, QStyleOptionViewItemV4::Beginning);
+
+ if (opt.text.contains("Middle"))
+ QCOMPARE(opt.viewItemPosition, QStyleOptionViewItemV4::Middle);
+
+ if (opt.text.contains("End"))
+ QCOMPARE(opt.viewItemPosition, QStyleOptionViewItemV4::End);
+
+ if (opt.text.contains("OnlyOne"))
+ QCOMPARE(opt.viewItemPosition, QStyleOptionViewItemV4::OnlyOne);
+
+ if (opt.text.contains("Checked"))
+ QCOMPARE(opt.checkState, Qt::Checked);
+ else
+ QCOMPARE(opt.checkState, Qt::Unchecked);
+
+ QCOMPARE(!(opt.state & QStyle::State_Children) , !opt.text.contains("HasChildren"));
+ QCOMPARE(!!(opt.state & QStyle::State_Sibling) , !opt.text.contains("Last"));
+
+ QVERIFY(!opt.text.contains("Assert"));
+
+ QStyledItemDelegate::paint(painter, option, index);
+ count++;
+ }
+ mutable int count;
+ bool allCollapsed;
+ };
+
+ QTreeView view;
+ QStandardItemModel model;
+ view.setModel(&model);
+ MyDelegate delegate;
+ view.setItemDelegate(&delegate);
+ model.appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") );
+ QStandardItem *par1 = new QStandardItem("Beginning HasChildren");
+ model.appendRow(QList<QStandardItem*>()
+ << par1 << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") );
+ model.appendRow(QList<QStandardItem*>()
+ << new QStandardItem("OnlyOne") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Assert") );
+ QStandardItem *checkable = new QStandardItem("Checkable");
+ checkable->setCheckable(true);
+ QStandardItem *checked = new QStandardItem("Checkable Checked");
+ checkable->setCheckable(true);
+ checked->setCheckState(Qt::Checked);
+ model.appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Beginning") << checkable << checked << new QStandardItem("End") );
+ model.appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Beginning Last") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") );
+
+ par1->appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") );
+ QStandardItem *par2 = new QStandardItem("Beginning HasChildren");
+ par1->appendRow(QList<QStandardItem*>()
+ << par2 << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") );
+ par2->appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Beginning Last") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") );
+
+ QStandardItem *par3 = new QStandardItem("Beginning Last");
+ par1->appendRow(QList<QStandardItem*>()
+ << par3 << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") );
+ par3->appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Asser") );
+ view.setRowHidden(0, par3->index(), true);
+ par1->appendRow(QList<QStandardItem*>()
+ << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Asser") );
+ view.setRowHidden(3, par1->index(), true);
+
+
+ view.setFirstColumnSpanned(2, QModelIndex(), true);
+ view.setAlternatingRowColors(true);
+
+ delegate.count = 0;
+ delegate.allCollapsed = true;
+ view.showMaximized();
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 13);
+ delegate.count = 0;
+ delegate.allCollapsed = false;
+ view.expandAll();
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 13);
+ delegate.count = 0;
+ view.collapse(par2->index());
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 4);
+
+
+ //test dynamic models
+ {
+ delegate.count = 0;
+ QStandardItemModel model2;
+ QStandardItem *item0 = new QStandardItem("OnlyOne Last");
+ model2.appendRow(QList<QStandardItem*>() << item0);
+ view.setModel(&model2);
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 1);
+ QApplication::processEvents();
+
+ QStandardItem *item00 = new QStandardItem("OnlyOne Last");
+ item0->appendRow(QList<QStandardItem*>() << item00);
+ item0->setText("OnlyOne Last HasChildren");
+ QApplication::processEvents();
+ delegate.count = 0;
+ view.expandAll();
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 2);
+ QApplication::processEvents();
+
+ QStandardItem *item1 = new QStandardItem("OnlyOne Last");
+ delegate.count = 0;
+ item0->setText("OnlyOne HasChildren");
+ model2.appendRow(QList<QStandardItem*>() << item1);
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 3);
+ QApplication::processEvents();
+
+ QStandardItem *item01 = new QStandardItem("OnlyOne Last");
+ delegate.count = 0;
+ item00->setText("OnlyOne");
+ item0->appendRow(QList<QStandardItem*>() << item01);
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 4);
+ QApplication::processEvents();
+
+ QStandardItem *item000 = new QStandardItem("OnlyOne Last");
+ delegate.count = 0;
+ item00->setText("OnlyOne HasChildren");
+ item00->appendRow(QList<QStandardItem*>() << item000);
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 5);
+ QApplication::processEvents();
+
+ delegate.count = 0;
+ item0->removeRow(0);
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 3);
+ QApplication::processEvents();
+
+ item00 = new QStandardItem("OnlyOne");
+ item0->insertRow(0, QList<QStandardItem*>() << item00);
+ QApplication::processEvents();
+ delegate.count = 0;
+ view.expandAll();
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 4);
+ QApplication::processEvents();
+
+ delegate.count = 0;
+ item0->removeRow(1);
+ item00->setText("OnlyOne Last");
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 3);
+ QApplication::processEvents();
+
+ delegate.count = 0;
+ item0->removeRow(0);
+ item0->setText("OnlyOne");
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 2);
+ QApplication::processEvents();
+
+ //with hidden items
+ item0->setText("OnlyOne HasChildren");
+ item00 = new QStandardItem("OnlyOne");
+ item0->appendRow(QList<QStandardItem*>() << item00);
+ item01 = new QStandardItem("Assert");
+ item0->appendRow(QList<QStandardItem*>() << item01);
+ view.setRowHidden(1, item0->index(), true);
+ view.expandAll();
+ QStandardItem *item02 = new QStandardItem("OnlyOne Last");
+ item0->appendRow(QList<QStandardItem*>() << item02);
+ delegate.count = 0;
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 4);
+ QApplication::processEvents();
+
+ item0->removeRow(2);
+ item00->setText("OnlyOne Last");
+ delegate.count = 0;
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.count >= 3);
+ QApplication::processEvents();
+
+ item00->setText("OnlyOne");
+ item0->insertRow(2, new QStandardItem("OnlyOne Last"));
+ view.collapse(item0->index());
+ item0->removeRow(0);
+ delegate.count = 0;
+ QTRY_VERIFY(delegate.count >= 2);
+ QApplication::processEvents();
+
+ item0->removeRow(1);
+ item0->setText("OnlyOne");
+ delegate.count = 0;
+ QTRY_VERIFY(delegate.count >= 2);
+ QApplication::processEvents();
+ }
+}
+
+class task174627_TreeView : public QTreeView
+{
+ Q_OBJECT
+protected slots:
+ void currentChanged(const QModelIndex &current, const QModelIndex &)
+ { emit currentChanged(current); }
+signals:
+ void currentChanged(const QModelIndex &);
+};
+
+void tst_QTreeView::task174627_moveLeftToRoot()
+{
+ QStandardItemModel model;
+ QStandardItem *item1 = new QStandardItem(QString("item 1"));
+ model.invisibleRootItem()->appendRow(item1);
+ QStandardItem *item2 = new QStandardItem(QString("item 2"));
+ item1->appendRow(item2);
+
+ task174627_TreeView view;
+ view.setModel(&model);
+ view.setRootIndex(item1->index());
+ view.setCurrentIndex(item2->index());
+
+ QSignalSpy spy(&view, SIGNAL(currentChanged(QModelIndex)));
+ QTest::keyClick(&view, Qt::Key_Left);
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QTreeView::task171902_expandWith1stColHidden()
+{
+ //the task was: if the first column of a treeview is hidden, the expanded state is not correctly restored
+ QStandardItemModel model;
+ QStandardItem root("root"), root2("root"),
+ subitem("subitem"), subitem2("subitem"),
+ subsubitem("subsubitem"), subsubitem2("subsubitem");
+
+ model.appendRow( QList<QStandardItem *>() << &root << &root2);
+ root.appendRow( QList<QStandardItem *>() << &subitem << &subitem2);
+ subitem.appendRow( QList<QStandardItem *>() << &subsubitem << &subsubitem2);
+
+ QTreeView view;
+ view.setModel(&model);
+
+ view.setColumnHidden(0, true);
+ view.expandAll();
+ view.collapse(root.index());
+ view.expand(root.index());
+
+ QCOMPARE(view.isExpanded(root.index()), true);
+ QCOMPARE(view.isExpanded(subitem.index()), true);
+
+}
+
+void tst_QTreeView::task203696_hidingColumnsAndRowsn()
+{
+ QTreeView view;
+ QStandardItemModel *model = new QStandardItemModel(0, 3, &view);
+ for (int i = 0; i < 3; ++i)
+ {
+ model->insertRow(model->rowCount());
+ for (int j = 0; j < model->columnCount(); ++j)
+ model->setData(model->index(i, j), QString("row %1 col %2").arg(i).arg(j));
+ }
+ view.setModel(model);
+ view.show();
+ view.setColumnHidden(0, true);
+ view.setRowHidden(0, QModelIndex(), true);
+ QCOMPARE(view.indexAt(QPoint(0, 0)), model->index(1, 1));
+}
+
+
+void tst_QTreeView::addRowsWhileSectionsAreHidden()
+{
+ QTreeView view;
+ for (int pass = 1; pass <= 2; ++pass) {
+ QStandardItemModel *model = new QStandardItemModel(6, pass, &view);
+ view.setModel(model);
+ view.show();
+
+ int i;
+ for (i = 0; i < 3; ++i)
+ {
+ model->insertRow(model->rowCount());
+ for (int j = 0; j < model->columnCount(); ++j) {
+ model->setData(model->index(i, j), QString("row %1 col %2").arg(i).arg(j));
+ }
+ }
+ int col;
+ for (col = 0; col < pass; ++col)
+ view.setColumnHidden(col, true);
+ for (i = 3; i < 6; ++i)
+ {
+ model->insertRow(model->rowCount());
+ for (int j = 0; j < model->columnCount(); ++j) {
+ model->setData(model->index(i, j), QString("row %1 col %2").arg(i).arg(j));
+ }
+ }
+ for (col = 0; col < pass; ++col)
+ view.setColumnHidden(col, false);
+ QTest::qWait(250);
+
+ for (i = 0; i < 6; ++i) {
+ QRect rect = view.visualRect(model->index(i, 0));
+ QCOMPARE(rect.isValid(), true);
+ }
+
+ delete model;
+ }
+}
+
+void tst_QTreeView::task216717_updateChildren()
+{
+ class Tree : public QTreeWidget {
+ protected:
+ void paintEvent(QPaintEvent *e)
+ {
+ QTreeWidget::paintEvent(e);
+ refreshed=true;
+ }
+ public:
+ bool refreshed;
+ } tree;
+ tree.show();
+ QTest::qWaitForWindowShown(&tree);
+ tree.refreshed = false;
+ QTreeWidgetItem *parent = new QTreeWidgetItem(QStringList() << "parent");
+ tree.addTopLevelItem(parent);
+ QTest::qWait(10);
+ QTRY_VERIFY(tree.refreshed);
+ tree.refreshed = false;
+ parent->addChild(new QTreeWidgetItem(QStringList() << "child"));
+ QTest::qWait(10);
+ QTRY_VERIFY(tree.refreshed);
+
+}
+
+void tst_QTreeView::task220298_selectColumns()
+{
+ //this is a very simple 3x3 model where the internalId of the index are different for each cell
+ class Model : public QAbstractTableModel
+ { public:
+ virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const
+ { return parent.isValid() ? 0 : 3; }
+ virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const
+ { return parent.isValid() ? 0 : 3; }
+
+ virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const
+ {
+ if(role == Qt::DisplayRole)
+ return QVariant(QString("%1-%2").arg(index.column()).arg(index.row()));
+ return QVariant();
+ }
+
+ virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const
+ {
+ return hasIndex(row, column, parent) ? createIndex(row, column, column*10+row) : QModelIndex();
+ }
+ };
+
+ class TreeView : public QTreeView { public: QModelIndexList selectedIndexes () const { return QTreeView::selectedIndexes(); } } view;
+ Model model;
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(50);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.visualRect(view.model()->index(1, 1)).center());
+ QTest::qWait(50);
+ QVERIFY(view.selectedIndexes().contains(view.model()->index(1, 2)));
+ QVERIFY(view.selectedIndexes().contains(view.model()->index(1, 1)));
+ QVERIFY(view.selectedIndexes().contains(view.model()->index(1, 0)));
+}
+
+
+void tst_QTreeView::task224091_appendColumns()
+{
+ QStandardItemModel *model = new QStandardItemModel();
+ QWidget* topLevel= new QWidget;
+ QTreeView *treeView = new QTreeView(topLevel);
+ treeView->setModel(model);
+ topLevel->show();
+ treeView->resize(50,50);
+
+ QTest::qWaitForWindowShown(treeView);
+ qApp->processEvents();
+
+ QList<QStandardItem *> projlist;
+ for (int k = 0; k < 10; ++k)
+ projlist.append(new QStandardItem(QString("Top Level %0").arg(k)));
+ model->appendColumn(projlist);
+ model->invisibleRootItem()->appendRow(new QStandardItem("end"));
+
+ QTest::qWait(50);
+ qApp->processEvents();
+
+ QTRY_VERIFY(treeView->verticalScrollBar()->isVisible());
+
+ delete topLevel;
+ delete model;
+}
+
+void tst_QTreeView::task211293_removeRootIndex()
+{
+ QTreeView view;
+ QStandardItemModel model;
+ QStandardItem *A1 = new QStandardItem("A1");
+ QStandardItem *B11 = new QStandardItem("B1.1");
+ QStandardItem *C111 = new QStandardItem("C1.1.1");
+ QStandardItem *C112 = new QStandardItem("C1.1.2");
+ QStandardItem *C113 = new QStandardItem("C1.1.3");
+ QStandardItem *D1131 = new QStandardItem("D1.1.3.1");
+ QStandardItem *E11311 = new QStandardItem("E1.1.3.1.1");
+ QStandardItem *E11312 = new QStandardItem("E1.1.3.1.2");
+ QStandardItem *E11313 = new QStandardItem("E1.1.3.1.3");
+ QStandardItem *E11314 = new QStandardItem("E1.1.3.1.4");
+ QStandardItem *D1132 = new QStandardItem("D1.1.3.2");
+ QStandardItem *E11321 = new QStandardItem("E1.1.3.2.1");
+ D1132->appendRow(E11321);
+ D1131->appendRow(E11311);
+ D1131->appendRow(E11312);
+ D1131->appendRow(E11313);
+ D1131->appendRow(E11314);
+ C113->appendRow(D1131);
+ C113->appendRow(D1132);
+ B11->appendRow(C111);
+ B11->appendRow(C112);
+ B11->appendRow(C113);
+ A1->appendRow(B11);
+ model.appendRow(A1);
+ view.setModel(&model);
+ view.setRootIndex(model.indexFromItem(B11));
+ view.setExpanded(model.indexFromItem(B11), true);
+ view.setCurrentIndex(model.indexFromItem(E11314));
+ view.setExpanded(model.indexFromItem(E11314), true);
+ view.show();
+ qApp->processEvents();
+ model.removeRows(0, 1);
+ qApp->processEvents();
+}
+
+void tst_QTreeView::task225539_deleteModel()
+{
+ QTreeView treeView;
+ treeView.show();
+ QStandardItemModel *model = new QStandardItemModel(&treeView);
+
+ QStandardItem* parentItem = model->invisibleRootItem();
+ QStandardItem* item = new QStandardItem(QString("item"));
+ parentItem->appendRow(item);
+
+ treeView.setModel(model);
+
+ QCOMPARE(item->index(), treeView.indexAt(QPoint()));
+
+ delete model;
+
+ QVERIFY(!treeView.indexAt(QPoint()).isValid());
+}
+
+void tst_QTreeView::task230123_setItemsExpandable()
+{
+ //let's check that we prevent the expansion inside a treeview
+ //when the property is set.
+ QTreeWidget tree;
+
+ QTreeWidgetItem root;
+ QTreeWidgetItem child;
+ root.addChild(&child);
+ tree.addTopLevelItem(&root);
+
+ tree.setCurrentItem(&root);
+
+ tree.setItemsExpandable(false);
+
+ QTest::keyClick(&tree, Qt::Key_Plus);
+ QVERIFY(!root.isExpanded());
+
+ QTest::keyClick(&tree, Qt::Key_Right);
+ QVERIFY(!root.isExpanded());
+
+ tree.setItemsExpandable(true);
+
+ QTest::keyClick(&tree, Qt::Key_Plus);
+ QVERIFY(root.isExpanded());
+
+ QTest::keyClick(&tree, Qt::Key_Minus);
+ QVERIFY(!root.isExpanded());
+
+ QTest::keyClick(&tree, Qt::Key_Right);
+ QVERIFY(root.isExpanded());
+
+ QTest::keyClick(&tree, Qt::Key_Left);
+ QVERIFY(!root.isExpanded());
+
+ QTest::keyClick(&tree, Qt::Key_Right);
+ QVERIFY(root.isExpanded());
+
+ const bool navToChild = tree.style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, &tree);
+ QTest::keyClick(&tree, Qt::Key_Right);
+ QCOMPARE(tree.currentItem(), navToChild ? &child : &root);
+
+ QTest::keyClick(&tree, Qt::Key_Right);
+ //it should not be expanded: it has no leaf
+ QCOMPARE(child.isExpanded(), false);
+
+ QTest::keyClick(&tree, Qt::Key_Left);
+ QCOMPARE(tree.currentItem(), &root);
+
+ QTest::keyClick(&tree, Qt::Key_Left);
+ QVERIFY(!root.isExpanded());
+
+
+}
+
+void tst_QTreeView::task202039_closePersistentEditor()
+{
+ QStandardItemModel model(1,1);
+ QTreeView view;
+ view.setModel(&model);
+
+ QModelIndex current = model.index(0,0);
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
+ QCOMPARE(view.currentIndex(), current);
+ QVERIFY(view.indexWidget(current));
+
+ view.closePersistentEditor(current);
+ QVERIFY(view.indexWidget(current) == 0);
+
+ //here was the bug: closing the persistent editor would not reset the state
+ //and it was impossible to go into editinon again
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
+ QCOMPARE(view.currentIndex(), current);
+ QVERIFY(view.indexWidget(current));
+}
+
+void tst_QTreeView::task238873_avoidAutoReopening()
+{
+ QStandardItemModel model;
+
+ QStandardItem item0("row 0");
+ QStandardItem item1("row 1");
+ QStandardItem item2("row 2");
+ QStandardItem item3("row 3");
+ model.appendColumn( QList<QStandardItem*>() << &item0 << &item1 << &item2 << &item3);
+
+ QStandardItem child("child");
+ item1.appendRow( &child);
+
+ QTreeView view;
+ view.setModel(&model);
+ view.show();
+ view.expandAll();
+ QTest::qWait(100);
+
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(child.index()).center());
+ QTest::qWait(20);
+ QCOMPARE(view.currentIndex(), child.index());
+
+ view.setExpanded(item1.index(), false);
+
+ QTest::qWait(500); //enough to trigger the delayedAutoScroll timer
+ QVERIFY(!view.isExpanded(item1.index()));
+}
+
+void tst_QTreeView::task244304_clickOnDecoration()
+{
+ QTreeView view;
+ QStandardItemModel model;
+ QStandardItem item0("row 0");
+ QStandardItem item00("row 0");
+ item0.appendRow(&item00);
+ QStandardItem item1("row 1");
+ model.appendColumn(QList<QStandardItem*>() << &item0 << &item1);
+ view.setModel(&model);
+
+ QVERIFY(!view.currentIndex().isValid());
+ QRect rect = view.visualRect(item0.index());
+ //we click on the decoration
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, rect.topLeft()+QPoint(-rect.left()/2,rect.height()/2));
+ QVERIFY(!view.currentIndex().isValid());
+ QVERIFY(view.isExpanded(item0.index()));
+
+ rect = view.visualRect(item1.index());
+ //the item has no decoration, it should get selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, rect.topLeft()+QPoint(-rect.left()/2,rect.height()/2));
+ QCOMPARE(view.currentIndex(), item1.index());
+}
+
+void tst_QTreeView::task246536_scrollbarsNotWorking()
+{
+ struct MyObject : public QObject
+ {
+ MyObject() : count(0)
+ {
+ }
+
+ bool eventFilter(QObject*, QEvent *e)
+ {
+ if (e->type() == QEvent::Paint)
+ count++;
+
+ return false;
+ }
+
+ int count;
+ };
+ QTreeView tree;
+ MyObject o;
+ tree.viewport()->installEventFilter(&o);
+ QStandardItemModel model;
+ tree.setModel(&model);
+ tree.show();
+ QTest::qWaitForWindowShown(&tree);
+ QList<QStandardItem *> items;
+ for(int i=0; i<100; ++i){
+ items << new QStandardItem(QString::fromLatin1("item %1").arg(i));
+ }
+ model.invisibleRootItem()->appendColumn(items);
+ QTest::qWait(100);
+ o.count = 0;
+ tree.verticalScrollBar()->setValue(50);
+ QTest::qWait(100);
+ QTRY_VERIFY(o.count > 0);
+}
+
+void tst_QTreeView::task250683_wrongSectionSize()
+{
+ QDirModel model;
+ QTreeView treeView;
+ treeView.header()->setResizeMode(QHeaderView::ResizeToContents);
+ treeView.setModel(&model);
+ treeView.setColumnHidden(2, true);
+ treeView.setColumnHidden(3, true);
+
+ treeView.show();
+ QTest::qWait(100);
+
+ QCOMPARE(treeView.header()->sectionSize(0) + treeView.header()->sectionSize(1), treeView.viewport()->width());
+}
+
+void tst_QTreeView::task239271_addRowsWithFirstColumnHidden()
+{
+ class MyDelegate : public QStyledItemDelegate
+ {
+ public:
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
+ {
+ paintedIndexes << index;
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+
+ mutable QSet<QModelIndex> paintedIndexes;
+ };
+
+ QTreeView view;
+ QStandardItemModel model;
+ view.setModel(&model);
+ MyDelegate delegate;
+ view.setItemDelegate(&delegate);
+ QStandardItem root0("root0"), root1("root1");
+ model.invisibleRootItem()->appendRow(QList<QStandardItem*>() << &root0 << &root1);
+ QStandardItem sub0("sub0"), sub00("sub00");
+ root0.appendRow(QList<QStandardItem*>() << &sub0 << &sub00);
+ view.expand(root0.index());
+
+ view.hideColumn(0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ delegate.paintedIndexes.clear();
+ QStandardItem sub1("sub1"), sub11("sub11");
+ root0.appendRow(QList<QStandardItem*>() << &sub1 << &sub11);
+
+ QTest::qWait(20);
+ //items in the 2nd column should have been painted
+ QTRY_VERIFY(!delegate.paintedIndexes.isEmpty());
+ QVERIFY(delegate.paintedIndexes.contains(sub00.index()));
+ QVERIFY(delegate.paintedIndexes.contains(sub11.index()));
+}
+
+void tst_QTreeView::task254234_proxySort()
+{
+ //based on tst_QTreeView::sortByColumn
+ // it used not to work when setting the source of a proxy after enabling sorting
+ QTreeView view;
+ QStandardItemModel model(4,2);
+ model.setItem(0,0,new QStandardItem("b"));
+ model.setItem(1,0,new QStandardItem("d"));
+ model.setItem(2,0,new QStandardItem("c"));
+ model.setItem(3,0,new QStandardItem("a"));
+ model.setItem(0,1,new QStandardItem("e"));
+ model.setItem(1,1,new QStandardItem("g"));
+ model.setItem(2,1,new QStandardItem("h"));
+ model.setItem(3,1,new QStandardItem("f"));
+
+ view.sortByColumn(1);
+ view.setSortingEnabled(true);
+
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ view.setModel(&proxy);
+ proxy.setSourceModel(&model);
+ QCOMPARE(view.header()->sortIndicatorSection(), 1);
+ QCOMPARE(view.model()->data(view.model()->index(0,1)).toString(), QString::fromLatin1("h"));
+ QCOMPARE(view.model()->data(view.model()->index(1,1)).toString(), QString::fromLatin1("g"));
+}
+
+class TreeView : public QTreeView
+{
+ Q_OBJECT
+public slots:
+ void handleSelectionChanged()
+ {
+ //let's select the last item
+ QModelIndex idx = model()->index(0, 0);
+ selectionModel()->select(QItemSelection(idx, idx), QItemSelectionModel::Select);
+ disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(handleSelectionChanged()));
+ }
+};
+
+void tst_QTreeView::task248022_changeSelection()
+{
+ //we check that changing the selection between the mouse press and the mouse release
+ //works correctly
+ TreeView view;
+ QStringList list = QStringList() << "1" << "2";
+ QStringListModel model(list);
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.setModel(&model);
+ view.connect(view.selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(handleSelectionChanged()));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(model.index(1)).center());
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), list.count());
+}
+
+void tst_QTreeView::task245654_changeModelAndExpandAll()
+{
+ QTreeView view;
+ QStandardItemModel *model = new QStandardItemModel;
+ QStandardItem *top = new QStandardItem("top");
+ QStandardItem *sub = new QStandardItem("sub");
+ top->appendRow(sub);
+ model->appendRow(top);
+ view.setModel(model);
+ view.expandAll();
+ QApplication::processEvents();
+ QVERIFY(view.isExpanded(top->index()));
+
+ //now let's try to delete the model
+ //then repopulate and expand again
+ delete model;
+ model = new QStandardItemModel;
+ top = new QStandardItem("top");
+ sub = new QStandardItem("sub");
+ top->appendRow(sub);
+ model->appendRow(top);
+ view.setModel(model);
+ view.expandAll();
+ QApplication::processEvents();
+ QVERIFY(view.isExpanded(top->index()));
+
+}
+
+void tst_QTreeView::doubleClickedWithSpans()
+{
+ QTreeView view;
+ QStandardItemModel model(1, 2);
+ view.setModel(&model);
+ view.setFirstColumnSpanned(0, QModelIndex(), true);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.isActiveWindow());
+
+ QPoint p(10, 10);
+ QCOMPARE(view.indexAt(p), model.index(0, 0));
+ QSignalSpy spy(&view, SIGNAL(doubleClicked(QModelIndex)));
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, p);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, p);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, p);
+ QCOMPARE(spy.count(), 1);
+
+ //let's click on the 2nd column
+ p.setX(p.x() + view.header()->sectionSize(0));
+ QCOMPARE(view.indexAt(p), model.index(0, 0));
+
+ //end the previous edition
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
+ QTest::qWait(150);
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, p);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, p);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, p);
+ QTRY_COMPARE(spy.count(), 2);
+}
+
+void tst_QTreeView::taskQTBUG_6450_selectAllWith1stColumnHidden()
+{
+ QTreeWidget tree;
+ tree.setSelectionMode(QAbstractItemView::MultiSelection);
+ tree.setColumnCount(2);
+ QList<QTreeWidgetItem *> items;
+ const int nrRows = 10;
+ for (int i = 0; i < nrRows; ++i) {
+ items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item: %1").arg(i))));
+ items.last()->setText(1, QString("is an item"));
+ }
+ tree.insertTopLevelItems(0, items);
+
+ tree.hideColumn(0);
+ tree.selectAll();
+
+ QVERIFY(tree.selectionModel()->hasSelection());
+ for (int i = 0; i < nrRows; ++i)
+ QVERIFY(tree.selectionModel()->isRowSelected(i, QModelIndex()));
+}
+
+class TreeViewQTBUG_9216 : public QTreeView
+{
+ Q_OBJECT
+public:
+ void paintEvent(QPaintEvent *event)
+ {
+ if (doCompare)
+ QCOMPARE(event->rect(), viewport()->rect());
+ QTreeView::paintEvent(event);
+ painted++;
+ }
+ int painted;
+ bool doCompare;
+};
+
+void tst_QTreeView::taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint()
+{
+ QStandardItemModel model(10, 10, this);
+ for (int row = 0; row < 10; row++)
+ for (int col = 0; col < 10; col++)
+ model.setItem(row, col, new QStandardItem(QString("row %0, col %1").arg(row).arg(col)));
+ TreeViewQTBUG_9216 view;
+ view.setUniformRowHeights(true);
+ view.setModel(&model);
+ view.painted = 0;
+ view.doCompare = false;
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.painted > 0);
+
+ QTest::qWait(100); // This one is needed to make the test fail before the patch.
+ view.painted = 0;
+ view.doCompare = true;
+ model.setData(model.index(0, 0), QVariant(QSize(50, 50)), Qt::SizeHintRole);
+ QTest::qWait(100);
+ QTRY_VERIFY(view.painted > 0);
+}
+
+void tst_QTreeView::keyboardNavigationWithDisabled()
+{
+ QWidget topLevel;
+ QTreeView view(&topLevel);
+ QStandardItemModel model(90, 0);
+ for (int i = 0; i < 90; i ++) {
+ model.setItem(i, new QStandardItem(QString::number(i)));
+ model.item(i)->setEnabled(i%6 == 0);
+ }
+ view.setModel(&model);
+
+ view.resize(200, view.visualRect(model.index(0,0)).height()*10);
+ topLevel.show();
+ QApplication::setActiveWindow(&topLevel);
+ QTest::qWaitForWindowShown(&topLevel);
+ QTRY_VERIFY(topLevel.isActiveWindow());
+
+ view.setCurrentIndex(model.index(1, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_Up);
+ QCOMPARE(view.currentIndex(), model.index(0, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_Down);
+ QCOMPARE(view.currentIndex(), model.index(6, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_PageDown);
+ QCOMPARE(view.currentIndex(), model.index(18, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_Down);
+ QCOMPARE(view.currentIndex(), model.index(24, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_PageUp);
+ QCOMPARE(view.currentIndex(), model.index(12, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_Up);
+ QCOMPARE(view.currentIndex(), model.index(6, 0));
+}
+
+class Model_11466 : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ Model_11466(QObject * /* parent */) :
+ m_block(false)
+ {
+ // set up the model to have two top level items and a few others
+ m_selectionModel = new QItemSelectionModel(this, this); // owned by this
+
+ connect(m_selectionModel, SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)),
+ this, SLOT(slotCurrentChanged(const QModelIndex &,const QModelIndex &)));
+ };
+
+ int rowCount(const QModelIndex &parent) const
+ {
+ if (parent.isValid())
+ return (parent.internalId() == 0) ? 4 : 0;
+ return 2; // two top level items
+ }
+
+ int columnCount(const QModelIndex & /* parent */) const
+ {
+ return 2;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role == Qt::DisplayRole && index.isValid()) {
+ qint64 parentRowPlusOne = index.internalId();
+ QString str;
+ QTextStream stream(&str);
+ if (parentRowPlusOne > 0)
+ stream << parentRowPlusOne << " -> " << index.row() << " : " << index.column();
+ else
+ stream << index.row() << " : " << index.column();
+ return QVariant(str);
+ }
+ return QVariant();
+ }
+
+ QModelIndex parent(const QModelIndex &index) const
+ {
+ if (index.isValid()) {
+ qint64 parentRowPlusOne = index.internalId();
+ if (parentRowPlusOne > 0) {
+ int row = static_cast<int>(parentRowPlusOne - 1);
+ return createIndex(row, 0, (quint32)0);
+ }
+ }
+ return QModelIndex();
+ }
+
+ void bindView(QTreeView *view)
+ {
+ // sets the view to this model with a shared selection model
+ QItemSelectionModel *oldModel = view->selectionModel();
+ if (oldModel != m_selectionModel)
+ delete oldModel;
+ view->setModel(this); // this creates a new selection model for the view, but we dont want it either ...
+ oldModel = view->selectionModel();
+ view->setSelectionModel(m_selectionModel);
+ delete oldModel;
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent) const
+ {
+ return createIndex(row, column, parent.isValid() ? (quint32)(parent.row() + 1) : (quint32)0);
+ }
+
+public slots:
+ void slotCurrentChanged(const QModelIndex &current,const QModelIndex &)
+ {
+ if (m_block)
+ return;
+
+ if (current.isValid()) {
+ int selectedRow = current.row();
+ quint32 parentRowPlusOne = static_cast<quint32>(current.internalId());
+
+ for (int i = 0; i < 2; ++i) {
+ // announce the removal of all non top level items
+ beginRemoveRows(createIndex(i, 0, 0), 0, 3);
+ // nothing to actually do for the removal
+ endRemoveRows();
+
+ // put them back in again
+ beginInsertRows(createIndex(i, 0, 0), 0, 3);
+ // nothing to actually do for the insertion
+ endInsertRows();
+ }
+ // reselect the current item ...
+ QModelIndex selectedIndex = createIndex(selectedRow, 0, parentRowPlusOne);
+
+ m_block = true; // recursion block
+ m_selectionModel->select(selectedIndex, QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Current|QItemSelectionModel::Rows);
+ m_selectionModel->setCurrentIndex(selectedIndex, QItemSelectionModel::NoUpdate);
+ m_block = false;
+ } else {
+ m_selectionModel->clear();
+ }
+ }
+
+private:
+ bool m_block;
+ QItemSelectionModel *m_selectionModel;
+};
+
+void tst_QTreeView::taskQTBUG_11466_keyboardNavigationRegression()
+{
+ QTreeView treeView;
+ treeView.setSelectionBehavior(QAbstractItemView::SelectRows);
+ treeView.setSelectionMode(QAbstractItemView::SingleSelection);
+ Model_11466 model(&treeView);
+ model.bindView(&treeView);
+ treeView.expandAll();
+ treeView.show();
+ QTest::qWaitForWindowShown(&treeView);
+
+ QTest::keyPress(treeView.viewport(), Qt::Key_Down);
+ QTest::qWait(10);
+ QTRY_COMPARE(treeView.currentIndex(), treeView.selectionModel()->selection().indexes().first());
+}
+
+void tst_QTreeView::taskQTBUG_13567_removeLastItemRegression()
+{
+ QtTestModel model(200, 1);
+
+ QTreeView view;
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.setModel(&model);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ view.scrollToBottom();
+ QTest::qWait(10);
+ CHECK_VISIBLE(199, 0);
+
+ view.setCurrentIndex(model.index(199, 0));
+ model.removeLastRow();
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex(), model.index(198, 0));
+ CHECK_VISIBLE(198, 0);
+}
+
+QTEST_MAIN(tst_QTreeView)
+#include "tst_qtreeview.moc"
diff --git a/tests/auto/widgets/itemviews/qtreewidget/.gitignore b/tests/auto/widgets/itemviews/qtreewidget/.gitignore
new file mode 100644
index 0000000000..08c63b4b52
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreewidget/.gitignore
@@ -0,0 +1 @@
+tst_qtreewidget
diff --git a/tests/auto/widgets/itemviews/qtreewidget/qtreewidget.pro b/tests/auto/widgets/itemviews/qtreewidget/qtreewidget.pro
new file mode 100644
index 0000000000..763c0d3c63
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreewidget/qtreewidget.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtreewidget.cpp
diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
new file mode 100644
index 0000000000..5e1faf97c4
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
@@ -0,0 +1,3349 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qtreewidget.h>
+#include <qtreewidgetitemiterator.h>
+#include <qapplication.h>
+#include <qeventloop.h>
+#include <qdebug.h>
+#include <qheaderview.h>
+#include <qlineedit.h>
+#include <QScrollBar>
+#include <QStyledItemDelegate>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class CustomTreeWidget : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ QModelIndex indexFromItem(QTreeWidgetItem *item, int column = 0) const
+ { return QTreeWidget::indexFromItem(item, column); }
+};
+
+class tst_QTreeWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTreeWidget();
+ ~tst_QTreeWidget();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void addTopLevelItem();
+ void currentItem_data();
+ void currentItem();
+ void editItem_data();
+ void editItem();
+ void takeItem_data();
+ void takeItem();
+ void removeChild_data();
+ void removeChild();
+ void setItemHidden();
+ void setItemHidden2();
+ void selectedItems_data();
+ void selectedItems();
+ void itemAssignment();
+ void clone_data();
+ void clone();
+ void expand_data();
+ void expand();
+ void checkState_data();
+ void checkState();
+ void findItems_data();
+ void findItems();
+ void findItemsInColumn();
+ void sortItems_data();
+ void sortItems();
+ void deleteItems_data();
+ void deleteItems();
+ void itemAboveOrBelow();
+ void itemStreaming_data();
+ void itemStreaming();
+ void insertTopLevelItems_data();
+ void insertTopLevelItems();
+ void keyboardNavigation();
+ void scrollToItem();
+ void setSortingEnabled();
+ void match();
+ void columnCount();
+ void setHeaderLabels();
+ void setHeaderItem();
+ void itemWidget_data();
+ void itemWidget();
+ void insertItemsWithSorting_data();
+ void insertItemsWithSorting();
+ void insertExpandedItemsWithSorting_data();
+ void insertExpandedItemsWithSorting();
+ void changeDataWithSorting_data();
+ void changeDataWithSorting();
+ void changeDataWithStableSorting_data();
+ void changeDataWithStableSorting();
+
+ void sortedIndexOfChild_data();
+ void sortedIndexOfChild();
+ void defaultRowSizes();
+
+ void task191552_rtl();
+ void task203673_selection();
+ void rootItemFlags();
+ void task218661_setHeaderData();
+ void task245280_sortChildren();
+ void task253109_itemHeight();
+
+ // QTreeWidgetItem
+ void itemOperatorLessThan();
+ void addChild();
+ void setData();
+ void enableDisable();
+
+ void expandAndCallapse();
+ void itemData();
+ void setDisabled();
+ void removeSelectedItem();
+ void removeCurrentItem();
+ void removeCurrentItem_task186451();
+ void randomExpand();
+ void crashTest();
+ void sortAndSelect();
+
+ void task206367_duplication();
+ void selectionOrder();
+
+ void setSelectionModel();
+ void task217309();
+ void setCurrentItemExpandsParent();
+ void task239150_editorWidth();
+ void setTextUpdate();
+ void taskQTBUG2844_visualItemRect();
+ void setChildIndicatorPolicy();
+
+
+public slots:
+ void itemSelectionChanged();
+ void emitDataChanged();
+
+private:
+ CustomTreeWidget *testWidget;
+};
+
+// Testing get/set functions
+void tst_QTreeWidget::getSetCheck()
+{
+ QTreeWidget obj1;
+ // int QTreeWidget::columnCount()
+ // void QTreeWidget::setColumnCount(int)
+ obj1.setColumnCount(0);
+ QCOMPARE(obj1.columnCount(), 0);
+
+ obj1.setColumnCount(INT_MIN);
+ QCOMPARE(obj1.columnCount(), 0);
+
+ //obj1.setColumnCount(INT_MAX);
+ //QCOMPARE(obj1.columnCount(), INT_MAX);
+ // Since setColumnCount allocates memory, there is no way this will succeed
+
+ obj1.setColumnCount(100);
+ QCOMPARE(obj1.columnCount(), 100);
+
+ // QTreeWidgetItem * QTreeWidget::headerItem()
+ // void QTreeWidget::setHeaderItem(QTreeWidgetItem *)
+ QTreeWidgetItem *var2 = new QTreeWidgetItem();
+ obj1.setHeaderItem(var2);
+ QCOMPARE(obj1.headerItem(), var2);
+
+ obj1.setHeaderItem((QTreeWidgetItem *)0);
+// QCOMPARE(obj1.headerItem(), (QTreeWidgetItem *)0);
+
+ // QTreeWidgetItem * QTreeWidget::currentItem()
+ // void QTreeWidget::setCurrentItem(QTreeWidgetItem *)
+ QTreeWidgetItem *var3 = new QTreeWidgetItem(&obj1);
+ obj1.setCurrentItem(var3);
+ QCOMPARE(obj1.currentItem(), var3);
+
+ obj1.setCurrentItem((QTreeWidgetItem *)0);
+ QCOMPARE(obj1.currentItem(), (QTreeWidgetItem *)0);
+}
+
+typedef QList<int> IntList;
+typedef QList<IntList> ListIntList;
+
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(ListIntList)
+Q_DECLARE_METATYPE(QModelIndex)
+Q_DECLARE_METATYPE(Qt::Orientation)
+
+typedef QTreeWidgetItem TreeItem;
+typedef QList<TreeItem*> TreeItemList;
+
+Q_DECLARE_METATYPE(QTreeWidgetItem*)
+Q_DECLARE_METATYPE(TreeItemList)
+
+tst_QTreeWidget::tst_QTreeWidget(): testWidget(0)
+{
+}
+
+tst_QTreeWidget::~tst_QTreeWidget()
+{
+}
+
+void tst_QTreeWidget::initTestCase()
+{
+ qMetaTypeId<QModelIndex>();
+ qMetaTypeId<Qt::Orientation>();
+ qRegisterMetaType<QTreeWidgetItem*>("QTreeWidgetItem*");
+
+ testWidget = new CustomTreeWidget();
+ testWidget->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(testWidget);
+#endif
+}
+
+void tst_QTreeWidget::cleanupTestCase()
+{
+ testWidget->hide();
+ delete testWidget;
+}
+
+void tst_QTreeWidget::init()
+{
+ testWidget->clear();
+ testWidget->setColumnCount(2);
+}
+
+void tst_QTreeWidget::cleanup()
+{
+}
+
+TreeItem *operator<<(TreeItem *parent, const TreeItemList &children) {
+ for (int i = 0; i < children.count(); ++i)
+ parent->addChild(children.at(i));
+ return parent;
+}
+
+static void populate(QTreeWidget *widget, const TreeItemList &topLevelItems,
+ TreeItem *headerItem = 0)
+{
+ widget->clear();
+ widget->setHeaderItem(headerItem);
+ foreach (TreeItem *item, topLevelItems)
+ widget->addTopLevelItem(item);
+}
+
+void tst_QTreeWidget::addTopLevelItem()
+{
+ QTreeWidget tree;
+ QCOMPARE(tree.topLevelItemCount(), 0);
+
+ // try to add 0
+ tree.addTopLevelItem(0);
+ QCOMPARE(tree.topLevelItemCount(), 0);
+ QCOMPARE(tree.indexOfTopLevelItem(0), -1);
+
+ // add one at a time
+ QList<TreeItem*> tops;
+ for (int i = 0; i < 10; ++i) {
+ TreeItem *ti = new TreeItem();
+ QCOMPARE(tree.indexOfTopLevelItem(ti), -1);
+ tree.addTopLevelItem(ti);
+ QCOMPARE(tree.topLevelItemCount(), i+1);
+ QCOMPARE(tree.topLevelItem(i), ti);
+ QCOMPARE(tree.topLevelItem(-1), static_cast<TreeItem*>(0));
+ QCOMPARE(tree.indexOfTopLevelItem(ti), i);
+ QCOMPARE(ti->parent(), static_cast<TreeItem*>(0));
+ tree.addTopLevelItem(ti);
+ QCOMPARE(tree.topLevelItemCount(), i+1);
+ tops.append(ti);
+ }
+
+ // delete one at a time
+ while (!tops.isEmpty()) {
+ TreeItem *ti = tops.takeFirst();
+ delete ti;
+ QCOMPARE(tree.topLevelItemCount(), tops.count());
+ for (int i = 0; i < tops.count(); ++i)
+ QCOMPARE(tree.topLevelItem(i), tops.at(i));
+ }
+
+ // add none
+ {
+ int count = tree.topLevelItemCount();
+ tree.addTopLevelItems(tops);
+ QCOMPARE(tree.topLevelItemCount(), count);
+ }
+
+ // add many at a time
+ {
+ const int count = 10;
+ for (int i = 0; i < 100; i += count) {
+ tops.clear();
+ for (int j = 0; j < count; ++j)
+ tops << new TreeItem(QStringList() << QString("%0").arg(j));
+ tree.addTopLevelItems(tops);
+ QCOMPARE(tree.topLevelItemCount(), count + i);
+ for (int j = 0; j < count; ++j)
+ QCOMPARE(tree.topLevelItem(i+j), tops.at(j));
+
+ tree.addTopLevelItems(tops);
+ QCOMPARE(tree.topLevelItemCount(), count + i);
+ }
+ }
+
+ // insert
+ {
+ tops.clear();
+ for (int i = 0; i < 10; ++i)
+ tops << new TreeItem();
+ int count = tree.topLevelItemCount();
+ tree.insertTopLevelItems(100000, tops);
+ // ### fixme
+ QCOMPARE(tree.topLevelItemCount(), count + 10);
+ }
+}
+
+void tst_QTreeWidget::currentItem_data()
+{
+ QTest::addColumn<TreeItemList>("topLevelItems");
+
+ QTest::newRow("only top-level items, 2 columns")
+ << (TreeItemList()
+ << new TreeItem(QStringList() << "a" << "b")
+ << new TreeItem(QStringList() << "c" << "d"));
+ TreeItemList lst;
+ lst << (new TreeItem(QStringList() << "a" << "b")
+ << (TreeItemList()
+ << new TreeItem(QStringList() << "c" << "d")
+ << new TreeItem(QStringList() << "c" << "d")
+ )
+ )
+ << (new TreeItem(QStringList() << "e" << "f")
+ << (TreeItemList()
+ << new TreeItem(QStringList() << "g" << "h")
+ << new TreeItem(QStringList() << "g" << "h")
+ )
+ );
+ QTest::newRow("hierarchy, 2 columns") << lst;
+}
+
+void tst_QTreeWidget::currentItem()
+{
+ QFETCH(TreeItemList, topLevelItems);
+
+ QTreeWidget tree;
+ tree.show();
+ populate(&tree, topLevelItems, new TreeItem(QStringList() << "1" << "2"));
+ QTreeWidgetItem *previous = 0;
+ for (int x = 0; x < 2; ++x) {
+ tree.setSelectionBehavior(x ? QAbstractItemView::SelectItems
+ : QAbstractItemView::SelectRows);
+ QSignalSpy currentItemChangedSpy(
+ &tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
+ QSignalSpy itemSelectionChangedSpy(
+ &tree, SIGNAL(itemSelectionChanged()));
+
+ QTreeWidgetItemIterator it(&tree);
+ // do all items
+ while (QTreeWidgetItem *item = (*it++)) {
+ tree.setCurrentItem(item);
+ QCOMPARE(tree.currentItem(), item);
+
+ QCOMPARE(currentItemChangedSpy.count(), 1);
+ QVariantList args = currentItemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(1)), previous);
+
+ QCOMPARE(itemSelectionChangedSpy.count(), 1);
+ itemSelectionChangedSpy.clear();
+
+ previous = item;
+ // do all columns
+ for (int col = 0; col < item->columnCount(); ++col) {
+ tree.setCurrentItem(item, col);
+ QCOMPARE(tree.currentItem(), item);
+ QCOMPARE(tree.currentColumn(), col);
+
+ if (!currentItemChangedSpy.isEmpty()) {
+ // ### we get a currentItemChanged() when what really
+ // changed was just currentColumn(). Should it be like this?
+ QCOMPARE(currentItemChangedSpy.count(), 1);
+ QVariantList args = currentItemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(1)), item);
+ if (tree.selectionBehavior() == QAbstractItemView::SelectItems) {
+ QCOMPARE(itemSelectionChangedSpy.count(), 1);
+ itemSelectionChangedSpy.clear();
+ } else {
+ QCOMPARE(itemSelectionChangedSpy.count(), 0);
+ }
+ }
+ }
+ }
+ }
+
+ // can't set the headerItem to be the current item
+ tree.setCurrentItem(tree.headerItem());
+ QCOMPARE(tree.currentItem(), static_cast<TreeItem*>(0));
+}
+
+void tst_QTreeWidget::editItem_data()
+{
+ QTest::addColumn<TreeItemList>("topLevelItems");
+
+ {
+ TreeItemList list;
+ for (int i = 0; i < 10; i++) {
+ TreeItem *item = new TreeItem(QStringList() << "col1" << "col2");
+ if ((i & 1) == 0)
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ else
+ item->setFlags(item->flags() & ~Qt::ItemIsEditable);
+ list << item;
+ }
+ QTest::newRow("2 columns, only even items editable")
+ << list;
+ }
+}
+
+void tst_QTreeWidget::editItem()
+{
+ QFETCH(TreeItemList, topLevelItems);
+
+ QTreeWidget tree;
+ populate(&tree, topLevelItems, new TreeItem(QStringList() << "1" << "2"));
+ tree.show();
+ QTest::qWaitForWindowShown(&tree);
+
+ QSignalSpy itemChangedSpy(
+ &tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)));
+
+ QTreeWidgetItemIterator it(&tree);
+ while (QTreeWidgetItem *item = (*it++)) {
+ for (int col = 0; col < item->columnCount(); ++col) {
+ if (!(item->flags() & Qt::ItemIsEditable))
+ QTest::ignoreMessage(QtWarningMsg, "edit: editing failed");
+ tree.editItem(item, col);
+ QApplication::instance()->processEvents();
+ QApplication::instance()->processEvents();
+ QLineEdit *editor = qFindChild<QLineEdit*>(&tree);
+ if (editor) {
+ QVERIFY(item->flags() & Qt::ItemIsEditable);
+ QCOMPARE(editor->selectedText(), editor->text());
+ QTest::keyClick(editor, Qt::Key_A);
+ QTest::keyClick(editor, Qt::Key_Enter);
+ QApplication::instance()->processEvents();
+ QCOMPARE(itemChangedSpy.count(), 1);
+ QVariantList args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), col);
+ } else {
+ QVERIFY(!(item->flags() & Qt::ItemIsEditable));
+ }
+ }
+ }
+}
+
+void tst_QTreeWidget::takeItem_data()
+{
+ QTest::addColumn<int>("index");
+ QTest::addColumn<bool>("topLevel");
+ QTest::addColumn<bool>("outOfBounds");
+
+ QTest::newRow("First, topLevel") << 0 << true << false;
+ QTest::newRow("Last, topLevel") << 2 << true << false;
+ QTest::newRow("Middle, topLevel") << 1 << true << false;
+ QTest::newRow("Out of bounds, toplevel, (index: -1)") << -1 << true << true;
+ QTest::newRow("Out of bounds, toplevel, (index: 3)") << 3 << true << true;
+
+ QTest::newRow("First, child of topLevel") << 0 << false << false;
+ QTest::newRow("Last, child of topLevel") << 2 << false << false;
+ QTest::newRow("Middle, child of topLevel") << 1 << false << false;
+ QTest::newRow("Out of bounds, child of toplevel, (index: -1)") << -1 << false << true;
+ QTest::newRow("Out of bounds, child of toplevel, (index: 3)") << 3 << false << true;
+}
+
+void tst_QTreeWidget::takeItem()
+{
+ QFETCH(int, index);
+ QFETCH(bool, topLevel);
+ QFETCH(bool, outOfBounds);
+
+ for (int i=0; i<3; ++i) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
+ top->setText(0, QString("top%1").arg(i));
+ for (int j=0; j<3; ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(top);
+ child->setText(0, QString("child%1").arg(j));
+ }
+ }
+
+ QCOMPARE(testWidget->topLevelItemCount(), 3);
+ QCOMPARE(testWidget->topLevelItem(0)->childCount(), 3);
+
+ if (topLevel) {
+ int count = testWidget->topLevelItemCount();
+ QTreeWidgetItem *item = testWidget->takeTopLevelItem(index);
+ if (outOfBounds) {
+ QCOMPARE(item, (QTreeWidgetItem *)0);
+ QCOMPARE(count, testWidget->topLevelItemCount());
+ } else {
+ QCOMPARE(item->text(0), QString("top%1").arg(index));
+ QCOMPARE(count-1, testWidget->topLevelItemCount());
+ delete item;
+ }
+ } else {
+ int count = testWidget->topLevelItem(0)->childCount();
+ QTreeWidgetItem *item = testWidget->topLevelItem(0)->takeChild(index);
+ if (outOfBounds) {
+ QCOMPARE(item, (QTreeWidgetItem *)0);
+ QCOMPARE(count, testWidget->topLevelItem(0)->childCount());
+ } else {
+ QCOMPARE(item->text(0), QString("child%1").arg(index));
+ QCOMPARE(count-1, testWidget->topLevelItem(0)->childCount());
+ delete item;
+ }
+ }
+}
+
+void tst_QTreeWidget::removeChild_data()
+{
+ QTest::addColumn<int>("childCount");
+ QTest::addColumn<int>("removeAt");
+
+ QTest::newRow("10 remove 3") << 10 << 3;
+}
+
+void tst_QTreeWidget::removeChild()
+{
+ QFETCH(int, childCount);
+ QFETCH(int, removeAt);
+
+ QTreeWidgetItem *root = new QTreeWidgetItem;
+ for (int i = 0; i < childCount; ++i)
+ new QTreeWidgetItem(root, QStringList(QString::number(i)));
+
+ QCOMPARE(root->childCount(), childCount);
+ for (int j = 0; j < childCount; ++j)
+ QCOMPARE(root->child(j)->text(0), QString::number(j));
+
+ QTreeWidgetItem *remove = root->child(removeAt);
+ root->removeChild(remove);
+
+ QCOMPARE(root->childCount(), childCount - 1);
+ for (int k = 0; k < childCount; ++k) {
+ if (k == removeAt)
+ QCOMPARE(remove->text(0), QString::number(k));
+ else if (k < removeAt)
+ QCOMPARE(root->child(k)->text(0), QString::number(k));
+ else if (k > removeAt)
+ QCOMPARE(root->child(k - 1)->text(0), QString::number(k));
+ }
+ delete root;
+}
+
+void tst_QTreeWidget::setItemHidden()
+{
+ QTreeWidgetItem *parent = new QTreeWidgetItem(testWidget);
+ parent->setText(0, "parent");
+ QTreeWidgetItem *child = new QTreeWidgetItem(parent);
+ child->setText(0, "child");
+ QVERIFY(child->parent());
+
+ testWidget->expandItem(parent);
+ testWidget->scrollToItem(child);
+
+ QVERIFY(testWidget->visualItemRect(parent).isValid()
+ && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent)));
+ QVERIFY(testWidget->visualItemRect(child).isValid()
+ && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child)));
+
+ QVERIFY(!testWidget->isItemHidden(parent));
+ QVERIFY(!testWidget->isItemHidden(child));
+
+ testWidget->setItemHidden(parent, true);
+
+ QVERIFY(!(testWidget->visualItemRect(parent).isValid()
+ && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent))));
+ QVERIFY(!(testWidget->visualItemRect(child).isValid()
+ && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child))));
+
+ QVERIFY(testWidget->isItemHidden(parent));
+ QVERIFY(!testWidget->isItemHidden(child));
+
+ // From task 78670 (This caused an core dump)
+ // Check if we can set an item visible if it already is visible.
+ testWidget->setItemHidden(parent, false);
+ testWidget->setItemHidden(parent, false);
+ QVERIFY(!testWidget->isItemHidden(parent));
+
+
+ // hide, hide and then unhide.
+ testWidget->setItemHidden(parent, true);
+ testWidget->setItemHidden(parent, true);
+ testWidget->setItemHidden(parent, false);
+ QVERIFY(!testWidget->isItemHidden(parent));
+
+
+}
+
+
+void tst_QTreeWidget::setItemHidden2()
+{
+ // From Task 78587
+ QStringList hl;
+ hl << "ID" << "Desc";
+ testWidget->setColumnCount(hl.count());
+ testWidget->setHeaderLabels(hl);
+ testWidget->setSortingEnabled(true);
+
+ QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
+ QTreeWidgetItem *leaf = 0;
+ top->setText(0, "ItemList");
+ for (int i = 1; i <= 4; i++) {
+ leaf = new QTreeWidgetItem(top);
+ leaf->setText(0, QString().sprintf("%d", i));
+ leaf->setText(1, QString().sprintf("Item %d", i));
+ }
+
+ if (testWidget->topLevelItemCount() > 0) {
+ top = testWidget->topLevelItem(0);
+ testWidget->setItemExpanded(top, true);
+ }
+
+ if (testWidget->topLevelItemCount() > 0) {
+ top = testWidget->topLevelItem(0);
+ for (int i = 0; i < top->childCount(); i++) {
+ leaf = top->child(i);
+ if (leaf->text(0).toInt() % 2 == 0) {
+ if (!testWidget->isItemHidden(leaf)) {
+ testWidget->setItemHidden(leaf, true);
+ }
+ }
+ }
+ }
+}
+
+
+void tst_QTreeWidget::selectedItems_data()
+{
+ QTest::addColumn<int>("topLevel");
+ QTest::addColumn<int>("children");
+ QTest::addColumn<bool>("closeTopLevel");
+ QTest::addColumn<ListIntList>("selectedItems");
+ QTest::addColumn<ListIntList>("hiddenItems");
+ QTest::addColumn<ListIntList>("expectedItems");
+
+ ListIntList selectedItems;
+ ListIntList hiddenItems;
+ ListIntList expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems
+ << (IntList()
+ << 0);
+ expectedItems
+ << (IntList() << 0);
+ QTest::newRow("2 top with 2 children, closed, top0 selected, no hidden")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems
+ << (IntList()
+ << 0 << 0);
+ expectedItems
+ << (IntList() << 0 << 0);
+ QTest::newRow("2 top with 2 children, closed, top0child0 selected, no hidden")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems
+ << (IntList()
+ << 0 << 0);
+ expectedItems
+ << (IntList()
+ << 0 << 0);
+ QTest::newRow("2 top with 2 children, open, top0child0 selected, no hidden")
+ << 2 << 2 << false << selectedItems << hiddenItems << expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems << (IntList() << 0);
+ hiddenItems << (IntList() << 0);
+ QTest::newRow("2 top with 2 children, closed, top0 selected, top0 hidden")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems << (IntList() << 0 << 0);
+ hiddenItems << (IntList() << 0);
+ expectedItems << (IntList() << 0 << 0);
+ QTest::newRow("2 top with 2 children, closed, top0child0 selected, top0 hidden")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems
+ << (IntList() << 0)
+ << (IntList() << 0 << 0)
+ << (IntList() << 0 << 1)
+ << (IntList() << 1)
+ << (IntList() << 1 << 0)
+ << (IntList() << 1 << 1);
+ expectedItems
+ << (IntList() << 0)
+ << (IntList() << 0 << 0)
+ << (IntList() << 0 << 1)
+ << (IntList() << 1)
+ << (IntList() << 1 << 0)
+ << (IntList() << 1 << 1);
+ QTest::newRow("2 top with 2 children, closed, all selected, no hidden")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems
+ << (IntList() << 0)
+ << (IntList() << 0 << 0)
+ << (IntList() << 0 << 1)
+ << (IntList() << 1)
+ << (IntList() << 1 << 0)
+ << (IntList() << 1 << 1);
+ hiddenItems
+ << (IntList() << 0);
+ expectedItems
+ //<< (IntList() << 0)
+ << (IntList() << 0 << 0)
+ << (IntList() << 0 << 1)
+ << (IntList() << 1)
+ << (IntList() << 1 << 0)
+ << (IntList() << 1 << 1);
+ QTest::newRow("2 top with 2 children, closed, all selected, top0 hidden")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+ selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
+ selectedItems
+ << (IntList() << 0)
+ << (IntList() << 0 << 0)
+ << (IntList() << 0 << 1)
+ << (IntList() << 1)
+ << (IntList() << 1 << 0)
+ << (IntList() << 1 << 1);
+ hiddenItems
+ << (IntList() << 0 << 1)
+ << (IntList() << 1);
+ expectedItems
+ << (IntList() << 0)
+ << (IntList() << 0 << 0)
+ //<< (IntList() << 0 << 1)
+ //<< (IntList() << 1)
+ << (IntList() << 1 << 0)
+ << (IntList() << 1 << 1);
+
+ QTest::newRow("2 top with 2 children, closed, all selected, top0child1 and top1")
+ << 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
+
+}
+
+void tst_QTreeWidget::selectedItems()
+{
+ QFETCH(int, topLevel);
+ QFETCH(int, children);
+ QFETCH(bool, closeTopLevel);
+ QFETCH(ListIntList, selectedItems);
+ QFETCH(ListIntList, hiddenItems);
+ QFETCH(ListIntList, expectedItems);
+
+ // create items
+ for (int t=0; t<topLevel; ++t) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
+ top->setText(0, QString("top%1").arg(t));
+ for (int c=0; c<children; ++c) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(top);
+ child->setText(0, QString("top%1child%2").arg(t).arg(c));
+ }
+ }
+
+ // set selected
+ foreach (IntList itemPath, selectedItems) {
+ QTreeWidgetItem *item = 0;
+ foreach(int index, itemPath) {
+ if (!item)
+ item = testWidget->topLevelItem(index);
+ else
+ item = item->child(index);
+ }
+ testWidget->setItemSelected(item, true);
+ }
+
+ // hide rows
+ foreach (IntList itemPath, hiddenItems) {
+ QTreeWidgetItem *item = 0;
+ foreach(int index, itemPath) {
+ if (!item)
+ item = testWidget->topLevelItem(index);
+ else
+ item = item->child(index);
+ }
+ testWidget->setItemHidden(item, true);
+ }
+
+ // open/close toplevel
+ for (int i=0; i<testWidget->topLevelItemCount(); ++i) {
+ if (closeTopLevel)
+ testWidget->collapseItem(testWidget->topLevelItem(i));
+ else
+ testWidget->expandItem(testWidget->topLevelItem(i));
+ }
+
+ // check selectedItems
+ QList<QTreeWidgetItem*> sel = testWidget->selectedItems();
+ QCOMPARE(sel.count(), expectedItems.count());
+ foreach (IntList itemPath, expectedItems) {
+ QTreeWidgetItem *item = 0;
+ foreach(int index, itemPath) {
+ if (!item)
+ item = testWidget->topLevelItem(index);
+ else
+ item = item->child(index);
+ }
+ if (item)
+ QVERIFY(sel.contains(item));
+ }
+
+ // compare isSelected
+ for (int t=0; t<testWidget->topLevelItemCount(); ++t) {
+ QTreeWidgetItem *top = testWidget->topLevelItem(t);
+ if (testWidget->isItemSelected(top) && !testWidget->isItemHidden(top))
+ QVERIFY(sel.contains(top));
+ for (int c=0; c<top->childCount(); ++c) {
+ QTreeWidgetItem *child = top->child(c);
+ if (testWidget->isItemSelected(child) && !testWidget->isItemHidden(child))
+ QVERIFY(sel.contains(child));
+ }
+ }
+
+ // Possible to select null without crashing?
+ testWidget->setItemSelected(0, true);
+ QVERIFY(!testWidget->isItemSelected(0));
+
+ // unselect
+ foreach (IntList itemPath, selectedItems) {
+ QTreeWidgetItem *item = 0;
+ foreach(int index, itemPath) {
+ if (!item)
+ item = testWidget->topLevelItem(index);
+ else
+ item = item->child(index);
+ }
+ testWidget->setItemSelected(item, false);
+ }
+ QCOMPARE(testWidget->selectedItems().count(), 0);
+}
+
+void tst_QTreeWidget::itemAssignment()
+{
+ // create item with children and parent but not insert in the view
+ QTreeWidgetItem grandParent;
+ QTreeWidgetItem *parent = new QTreeWidgetItem(&grandParent);
+ parent->setText(0, "foo");
+ parent->setText(1, "bar");
+ for (int i=0; i<5; ++i) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(parent);
+ child->setText(0, "bingo");
+ child->setText(1, "bango");
+ }
+ QCOMPARE(parent->parent(), &grandParent);
+ QVERIFY(!parent->treeWidget());
+ QCOMPARE(parent->columnCount(), 2);
+ QCOMPARE(parent->text(0), QString("foo"));
+ QCOMPARE(parent->childCount(), 5);
+ QCOMPARE(parent->child(0)->parent(), parent);
+
+ // create item which is inserted in the widget
+ QTreeWidgetItem item(testWidget);
+ item.setText(0, "baz");
+ QVERIFY(!item.parent());
+ QCOMPARE(item.treeWidget(), static_cast<QTreeWidget *>(testWidget));
+ QCOMPARE(item.columnCount(), 1);
+ QCOMPARE(item.text(0), QString("baz"));
+ QCOMPARE(item.childCount(), 0);
+
+ // assign and test
+ *parent = item;
+ QCOMPARE(parent->parent(), &grandParent);
+ QVERIFY(!parent->treeWidget());
+ QCOMPARE(parent->columnCount(), 1);
+ QCOMPARE(parent->text(0), QString("baz"));
+ QCOMPARE(parent->childCount(), 5);
+ QCOMPARE(parent->child(0)->parent(), parent);
+}
+
+void tst_QTreeWidget::clone_data()
+{
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("topLevelIndex");
+ QTest::addColumn<int>("childIndex");
+ QTest::addColumn<QStringList>("topLevelText");
+ QTest::addColumn<QStringList>("childText");
+ QTest::addColumn<bool>("cloneChild");
+
+ QTest::newRow("clone parent with child") << 0 << 0 << 0
+ << (QStringList() << "some text")
+ << (QStringList() << "more text")
+ << false;
+
+ QTest::newRow("clone child") << 0 << 0 << 0
+ << (QStringList() << "some text")
+ << (QStringList() << "more text")
+ << true;
+}
+
+void tst_QTreeWidget::clone()
+{
+ QFETCH(int, column);
+ QFETCH(int, topLevelIndex);
+ QFETCH(int, childIndex);
+ QFETCH(QStringList, topLevelText);
+ QFETCH(QStringList, childText);
+ QFETCH(bool, cloneChild);
+
+ for (int i = 0; i < topLevelText.count(); ++i) {
+ QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
+ item->setText(column, topLevelText.at(i));
+ for (int j = 0; j < childText.count(); ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(item);
+ child->setText(column, childText.at(j));
+ }
+ }
+
+ QTreeWidgetItem *original = testWidget->topLevelItem(topLevelIndex);
+ QTreeWidgetItem *copy = original->clone();
+ QCOMPARE(copy->text(column), original->text(column));
+ QCOMPARE(copy->childCount(), original->childCount());
+ QVERIFY(!copy->parent());
+ QVERIFY(!copy->treeWidget());
+
+ QTreeWidgetItem *originalChild = original->child(childIndex);
+ QTreeWidgetItem *copiedChild = cloneChild ? originalChild->clone() : copy->child(childIndex);
+ QVERIFY(copiedChild != originalChild);
+ QCOMPARE(copiedChild->text(column), originalChild->text(column));
+ QCOMPARE(copiedChild->childCount(), originalChild->childCount());
+ QCOMPARE(copiedChild->parent(), cloneChild ? 0 : copy);
+ QVERIFY(!copiedChild->treeWidget());
+ if (cloneChild)
+ delete copiedChild;
+ delete copy;
+}
+
+void tst_QTreeWidget::expand_data()
+{
+ QTest::addColumn<int>("topLevelIndex");
+ QTest::addColumn<int>("topLevelCount");
+ QTest::addColumn<int>("childIndex");
+ QTest::addColumn<int>("childCount");
+
+ QTest::newRow("the only test data for now") << 0 << 1 << 0 << 1;
+}
+
+void tst_QTreeWidget::expand()
+{
+ QFETCH(int, topLevelIndex);
+ QFETCH(int, topLevelCount);
+ QFETCH(int, childIndex);
+ QFETCH(int, childCount);
+
+ for (int i = 0; i < topLevelCount; ++i) {
+ QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
+ for (int j = 0; j < childCount; ++j)
+ new QTreeWidgetItem(item);
+ }
+
+ QTreeWidgetItem *topLevelItem = testWidget->topLevelItem(topLevelIndex);
+ QTreeWidgetItem *childItem = topLevelItem->child(childIndex);
+
+ QVERIFY(!testWidget->isItemExpanded(topLevelItem));
+ testWidget->setItemExpanded(topLevelItem, true);
+ QVERIFY(testWidget->isItemExpanded(topLevelItem));
+
+ QVERIFY(!testWidget->isItemExpanded(childItem));
+ testWidget->setItemExpanded(childItem, true);
+ QVERIFY(testWidget->isItemExpanded(childItem));
+
+ QVERIFY(testWidget->isItemExpanded(topLevelItem));
+ testWidget->setItemExpanded(topLevelItem, false);
+ QVERIFY(!testWidget->isItemExpanded(topLevelItem));
+
+ QVERIFY(testWidget->isItemExpanded(childItem));
+ testWidget->setItemExpanded(childItem, false);
+ QVERIFY(!testWidget->isItemExpanded(childItem));
+}
+
+void tst_QTreeWidget::checkState_data()
+{
+}
+
+void tst_QTreeWidget::checkState()
+{
+ QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
+ item->setCheckState(0, Qt::Unchecked);
+ QTreeWidgetItem *firstChild = new QTreeWidgetItem(item);
+ firstChild->setCheckState(0, Qt::Unchecked);
+ QTreeWidgetItem *seccondChild = new QTreeWidgetItem(item);
+ seccondChild->setCheckState(0, Qt::Unchecked);
+
+ QCOMPARE(item->checkState(0), Qt::Unchecked);
+ QCOMPARE(firstChild->checkState(0), Qt::Unchecked);
+ QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
+
+ firstChild->setCheckState(0, Qt::Checked);
+ QCOMPARE(item->checkState(0), Qt::Unchecked);
+ QCOMPARE(firstChild->checkState(0), Qt::Checked);
+ QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
+
+ item->setFlags(item->flags()|Qt::ItemIsTristate);
+ QCOMPARE(item->checkState(0), Qt::PartiallyChecked);
+ QCOMPARE(firstChild->checkState(0), Qt::Checked);
+ QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
+
+ seccondChild->setCheckState(0, Qt::Checked);
+ QCOMPARE(item->checkState(0), Qt::Checked);
+ QCOMPARE(firstChild->checkState(0), Qt::Checked);
+ QCOMPARE(seccondChild->checkState(0), Qt::Checked);
+
+ firstChild->setCheckState(0, Qt::Unchecked);
+ seccondChild->setCheckState(0, Qt::Unchecked);
+ QCOMPARE(item->checkState(0), Qt::Unchecked);
+ QCOMPARE(firstChild->checkState(0), Qt::Unchecked);
+ QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
+}
+
+void tst_QTreeWidget::findItems_data()
+{
+ QTest::addColumn<int>("column");
+ QTest::addColumn<QStringList>("topLevelText");
+ QTest::addColumn<QStringList>("childText");
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<int>("resultCount");
+ QTest::addColumn<QStringList>("resultText");
+
+ QTest::newRow("find in toplevel")
+ << 0
+ << (QStringList() << "This is a text" << "This is another" << "This is the one")
+ << (QStringList() << "A child" << "This is not the one" << "And yet another child")
+ << "This is the one"
+ << 1
+ << (QStringList() << "This is the one");
+
+ QTest::newRow("find child")
+ << 0
+ << (QStringList() << "This is a text" << "This is another" << "This is the one")
+ << (QStringList() << "A child" << "This is not the one" << "And yet another child")
+ << "A child"
+ << 3 // once for each branch
+ << (QStringList() << "A child");
+
+}
+
+void tst_QTreeWidget::findItems()
+{
+ QFETCH(int, column);
+ QFETCH(QStringList, topLevelText);
+ QFETCH(QStringList, childText);
+ QFETCH(QString, pattern);
+ QFETCH(int, resultCount);
+ QFETCH(QStringList, resultText);
+
+ for (int i = 0; i < topLevelText.count(); ++i) {
+ QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
+ item->setText(column, topLevelText.at(i));
+ for (int j = 0; j < childText.count(); ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(item);
+ child->setText(column, childText.at(j));
+ }
+ }
+
+ QList<QTreeWidgetItem*> result = testWidget->findItems(pattern,
+ Qt::MatchExactly|Qt::MatchRecursive);
+ QCOMPARE(result.count(), resultCount);
+
+ for (int k = 0; k < result.count() && k < resultText.count(); ++k)
+ QCOMPARE(result.at(k)->text(column), resultText.at(k));
+}
+
+void tst_QTreeWidget::findItemsInColumn()
+{
+ // Create 5 root items.
+ for (int i = 0; i < 5; i++)
+ new QTreeWidgetItem(testWidget, QStringList() << QString::number(i));
+
+ // Create a child with two columns for each root item.
+ for (int i = 0; i < 5; i++) {
+ QTreeWidgetItem * const parent = testWidget->topLevelItem(i);
+ new QTreeWidgetItem(parent, QStringList() << QString::number(i * 10) << QString::number(i * 100));
+ }
+
+ // Recursively search column one for 400.
+ QList<QTreeWidgetItem*> items = testWidget->findItems("400", Qt::MatchExactly|Qt::MatchRecursive, 1);
+ QCOMPARE(items.count(), 1);
+}
+
+void tst_QTreeWidget::sortItems_data()
+{
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("order");
+ QTest::addColumn<QStringList>("topLevelText");
+ QTest::addColumn<QStringList>("childText");
+ QTest::addColumn<QStringList>("topLevelResult");
+ QTest::addColumn<QStringList>("childResult");
+ QTest::addColumn<IntList>("expectedTopRows");
+ QTest::addColumn<IntList>("expectedChildRows");
+
+ QTest::newRow("ascending order")
+ << 0
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "d" << "a" << "b")
+ << (QStringList() << "e" << "h" << "g" << "f")
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (QStringList() << "e" << "f" << "g" << "h")
+ << (IntList() << 2 << 3 << 0 << 1)
+ << (IntList() << 0 << 3 << 2 << 1);
+
+ QTest::newRow("descending order")
+ << 0
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "c" << "d" << "a" << "b")
+ << (QStringList() << "e" << "h" << "g" << "f")
+ << (QStringList() << "d" << "c" << "b" << "a")
+ << (QStringList() << "h" << "g" << "f" << "e")
+ << (IntList() << 1 << 0 << 3 << 2)
+ << (IntList() << 3 << 0 << 1 << 2);
+}
+
+void tst_QTreeWidget::sortItems()
+{
+ QFETCH(int, column);
+ QFETCH(int, order);
+ QFETCH(QStringList, topLevelText);
+ QFETCH(QStringList, childText);
+ QFETCH(QStringList, topLevelResult);
+ QFETCH(QStringList, childResult);
+ QFETCH(IntList, expectedTopRows);
+ QFETCH(IntList, expectedChildRows);
+ testWidget->setSortingEnabled(false);
+
+ for (int i = 0; i < topLevelText.count(); ++i) {
+ QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
+ item->setText(column, topLevelText.at(i));
+ for (int j = 0; j < childText.count(); ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(item);
+ child->setText(column, childText.at(j));
+ }
+ }
+
+ QAbstractItemModel *model = testWidget->model();
+ QList<QPersistentModelIndex> tops;
+ for (int r = 0; r < model->rowCount(QModelIndex()); ++r) {
+ QPersistentModelIndex p = model->index(r, 0, QModelIndex());
+ tops << p;
+ }
+ QList<QPersistentModelIndex> children;
+ for (int s = 0; s < model->rowCount(tops.first()); ++s) {
+ QPersistentModelIndex c = model->index(s, 0, tops.first());
+ children << c;
+ }
+
+ testWidget->sortItems(column, static_cast<Qt::SortOrder>(order));
+ QCOMPARE(testWidget->sortColumn(), column);
+
+ for (int k = 0; k < topLevelResult.count(); ++k) {
+ QTreeWidgetItem *item = testWidget->topLevelItem(k);
+ QCOMPARE(item->text(column), topLevelResult.at(k));
+ for (int l = 0; l < childResult.count(); ++l)
+ QCOMPARE(item->child(l)->text(column), childResult.at(l));
+ }
+
+ for (int m = 0; m < tops.count(); ++m)
+ QCOMPARE(tops.at(m).row(), expectedTopRows.at(m));
+ for (int n = 0; n < children.count(); ++n)
+ QCOMPARE(children.at(n).row(), expectedChildRows.at(n));
+}
+
+void tst_QTreeWidget::deleteItems_data()
+{
+ QTest::addColumn<int>("topLevelCount");
+ QTest::addColumn<int>("childCount");
+ QTest::addColumn<int>("grandChildCount");
+
+ QTest::addColumn<int>("deleteTopLevelCount");
+ QTest::addColumn<int>("deleteChildCount");
+ QTest::addColumn<int>("deleteGrandChildCount");
+
+ QTest::addColumn<int>("expectedTopLevelCount");
+ QTest::addColumn<int>("expectedChildCount");
+ QTest::addColumn<int>("expectedGrandChildCount");
+
+ QTest::addColumn<int>("persistentRow");
+ QTest::addColumn<int>("persistentColumn");
+ QTest::addColumn<bool>("persistentIsValid");
+
+ QTest::newRow("start with 10, delete 1")
+ << 10 << 10 << 10
+ << 1 << 1 << 1
+ << 9 << 9 << 9
+ << 0 << 0 << false;
+ QTest::newRow("start with 10, delete 5")
+ << 10 << 10 << 10
+ << 5 << 5 << 5
+ << 5 << 5 << 5
+ << 0 << 0 << false;
+ QTest::newRow("mixed")
+ << 10 << 13 << 7
+ << 3 << 7 << 4
+ << 7 << 6 << 3
+ << 0 << 0 << false;
+ QTest::newRow("all")
+ << 10 << 10 << 10
+ << 10 << 10 << 10
+ << 0 << 0 << 0
+ << 0 << 0 << false;
+}
+
+void tst_QTreeWidget::deleteItems()
+{
+ QFETCH(int, topLevelCount);
+ QFETCH(int, childCount);
+ QFETCH(int, grandChildCount);
+
+ QFETCH(int, deleteTopLevelCount);
+ QFETCH(int, deleteChildCount);
+ QFETCH(int, deleteGrandChildCount);
+
+ QFETCH(int, expectedTopLevelCount);
+ QFETCH(int, expectedChildCount);
+ QFETCH(int, expectedGrandChildCount);
+
+ QFETCH(int, persistentRow);
+ QFETCH(int, persistentColumn);
+ QFETCH(bool, persistentIsValid);
+
+ for (int i = 0; i < topLevelCount; ++i) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
+ for (int j = 0; j < childCount; ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(top);
+ for (int k = 0; k < grandChildCount; ++k) {
+ new QTreeWidgetItem(child);
+ }
+ }
+ }
+
+ QPersistentModelIndex persistent = testWidget->model()->index(persistentRow,
+ persistentColumn);
+ QVERIFY(persistent.isValid());
+
+ QTreeWidgetItem *top = testWidget->topLevelItem(0);
+ QTreeWidgetItem *child = top->child(0);
+
+ for (int n = 0; n < deleteGrandChildCount; ++n)
+ delete child->child(0);
+ QCOMPARE(child->childCount(), expectedGrandChildCount);
+
+ for (int m = 0; m < deleteChildCount; ++m)
+ delete top->child(0);
+ QCOMPARE(top->childCount(), expectedChildCount);
+
+ for (int l = 0; l < deleteTopLevelCount; ++l)
+ delete testWidget->topLevelItem(0);
+ QCOMPARE(testWidget->topLevelItemCount(), expectedTopLevelCount);
+
+ QCOMPARE(persistent.isValid(), persistentIsValid);
+}
+
+
+void tst_QTreeWidget::itemAboveOrBelow()
+{
+ QTreeWidget tw;
+ tw.setColumnCount(1);
+ QTreeWidgetItem *twi = new QTreeWidgetItem(&tw, QStringList() << "Test");
+ QTreeWidgetItem *twi2 = new QTreeWidgetItem(&tw, QStringList() << "Test 2");
+ QTreeWidgetItem *twi3 = new QTreeWidgetItem(&tw, QStringList() << "Test 3");
+ tw.show();
+ QCOMPARE(tw.itemAbove(twi2), twi);
+ QCOMPARE(tw.itemBelow(twi2), twi3);
+}
+
+void tst_QTreeWidget::itemStreaming_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("toolTip");
+ QTest::addColumn<int>("column");
+
+ QTest::newRow("Data") << "item text" << "tool tip text" << 0;
+}
+
+void tst_QTreeWidget::itemStreaming()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, toolTip);
+ QFETCH(int, column);
+
+ QTreeWidgetItem item(testWidget);
+ QCOMPARE(item.text(column), QString());
+ QCOMPARE(item.toolTip(column), QString());
+
+ item.setText(column, text);
+ item.setToolTip(column, toolTip);
+ QCOMPARE(item.text(column), text);
+ QCOMPARE(item.toolTip(column), toolTip);
+
+ QByteArray buffer;
+ QDataStream out(&buffer, QIODevice::WriteOnly);
+ out << item;
+
+ QTreeWidgetItem item2(testWidget);
+ QCOMPARE(item2.text(column), QString());
+ QCOMPARE(item2.toolTip(column), QString());
+
+ QVERIFY(!buffer.isEmpty());
+
+ QDataStream in(&buffer, QIODevice::ReadOnly);
+ in >> item2;
+ QCOMPARE(item2.text(column), text);
+ QCOMPARE(item2.toolTip(column), toolTip);
+}
+
+void tst_QTreeWidget::insertTopLevelItems_data()
+{
+ QTest::addColumn<QStringList>("initialText");
+ QTest::addColumn<QStringList>("insertText");
+ QTest::addColumn<int>("insertTopLevelIndex");
+ QTest::addColumn<int>("expectedTopLevelIndex");
+ QTest::addColumn<int>("insertChildIndex");
+ QTest::addColumn<int>("expectedChildIndex");
+
+ QStringList initial = (QStringList() << "foo" << "bar");
+ QStringList insert = (QStringList() << "baz");
+
+ QTest::newRow("Insert at count") << initial << insert
+ << initial.count() << initial.count()
+ << initial.count() << initial.count();
+ QTest::newRow("Insert in the middle") << initial << insert
+ << (initial.count() / 2) << (initial.count() / 2)
+ << (initial.count() / 2) << (initial.count() / 2);
+ QTest::newRow("Insert less than 0") << initial << insert
+ << -1 << -1
+ << -1 << -1;
+ QTest::newRow("Insert beyond count") << initial << insert
+ << initial.count() + 1 << -1
+ << initial.count() + 1 << -1;
+}
+
+void tst_QTreeWidget::insertTopLevelItems()
+{
+ QFETCH(QStringList, initialText);
+ QFETCH(QStringList, insertText);
+ QFETCH(int, insertTopLevelIndex);
+ QFETCH(int, expectedTopLevelIndex);
+ QFETCH(int, insertChildIndex);
+ QFETCH(int, expectedChildIndex);
+ testWidget->setSortingEnabled(false);
+
+ { // insert the initial items
+ QCOMPARE(testWidget->topLevelItemCount(), 0);
+ for (int i = 0; i < initialText.count(); ++i) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(QStringList(initialText.at(i)));
+ testWidget->addTopLevelItem(top);
+ QCOMPARE(testWidget->indexOfTopLevelItem(top), i);
+ }
+ QCOMPARE(testWidget->topLevelItemCount(), initialText.count());
+ }
+
+ { // test adding children
+ QTreeWidgetItem *topLevel = testWidget->topLevelItem(0);
+ for (int i = 0; i < initialText.count(); ++i)
+ topLevel->addChild(new QTreeWidgetItem(QStringList(initialText.at(i))));
+ QCOMPARE(topLevel->childCount(), initialText.count());
+ }
+
+ { // test adding more top level items
+ QTreeWidgetItem *topsy = new QTreeWidgetItem(QStringList(insertText.at(0)));
+ testWidget->insertTopLevelItem(insertTopLevelIndex, topsy);
+ if (expectedTopLevelIndex == -1) {
+ QCOMPARE(testWidget->topLevelItemCount(), initialText.count());
+ delete topsy;
+ } else {
+ QTreeWidgetItem *item = testWidget->topLevelItem(expectedTopLevelIndex);
+ QVERIFY(item != 0);
+ QCOMPARE(item->text(0), insertText.at(0));
+ QCOMPARE(testWidget->indexOfTopLevelItem(item), expectedTopLevelIndex);
+ }
+ }
+
+ { // test adding more children
+ QTreeWidgetItem *topLevel = testWidget->topLevelItem(0);
+ QVERIFY(topLevel != 0);
+ QTreeWidgetItem *child = new QTreeWidgetItem(QStringList(insertText.at(0)));
+ topLevel->insertChild(insertChildIndex, child);
+ if (expectedChildIndex == -1) {
+ QCOMPARE(topLevel->childCount(), initialText.count());
+ delete child;
+ } else {
+ QTreeWidgetItem *item = topLevel->child(expectedChildIndex);
+ QVERIFY(item != 0);
+ QCOMPARE(item->text(0), insertText.at(0));
+ }
+ }
+}
+
+static void fillTreeWidget(QTreeWidgetItem *parent, int rows)
+{
+ const int columns = parent->treeWidget()->columnCount();
+ for (int r = 0; r < rows; ++r) {
+ QTreeWidgetItem *w = new QTreeWidgetItem(parent);
+ for ( int c = 0; c < columns; ++c ) {
+ QString s = QString("[r:%1,c:%2]").arg(r).arg(c);
+ w->setText(c, s);
+ }
+ fillTreeWidget(w, rows - r - 1);
+ }
+}
+
+static void fillTreeWidget(QTreeWidget *tree, int rows)
+{
+ for (int r = 0; r < rows; ++r) {
+ QTreeWidgetItem *w = new QTreeWidgetItem();
+ for ( int c = 0; c < tree->columnCount(); ++c ) {
+ QString s = QString("[r:%1,c:%2]").arg(r).arg(c);
+ w->setText(c, s);
+ }
+ tree->insertTopLevelItem(r, w);
+ fillTreeWidget(w, rows - r - 1);
+ }
+}
+
+void tst_QTreeWidget::keyboardNavigation()
+{
+ int rows = 8;
+
+ fillTreeWidget(testWidget, rows);
+
+ QVector<Qt::Key> keymoves;
+ keymoves << Qt::Key_Down << Qt::Key_Right << Qt::Key_Left
+ << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down
+ << Qt::Key_Right
+ << Qt::Key_Up << Qt::Key_Left << Qt::Key_Left
+ << Qt::Key_Up << Qt::Key_Down << Qt::Key_Up << Qt::Key_Up
+ << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up
+ << Qt::Key_Down << Qt::Key_Right << Qt::Key_Down << Qt::Key_Down
+ << Qt::Key_Down << Qt::Key_Right << Qt::Key_Down << Qt::Key_Down
+ << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down
+ << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Left
+ << Qt::Key_Down << Qt::Key_Right << Qt::Key_Right << Qt::Key_Right
+ << Qt::Key_Left << Qt::Key_Left << Qt::Key_Right << Qt::Key_Left;
+
+ int row = 0;
+ QTreeWidgetItem *item = testWidget->topLevelItem(0);
+ testWidget->setCurrentItem(item);
+ QCOMPARE(testWidget->currentItem(), item);
+ QApplication::instance()->processEvents();
+
+ QScrollBar *scrollBar = testWidget->horizontalScrollBar();
+ bool checkScroll = false;
+ for (int i = 0; i < keymoves.size(); ++i) {
+ Qt::Key key = keymoves.at(i);
+ int valueBeforeClick = scrollBar->value();
+ if (valueBeforeClick >= scrollBar->singleStep())
+ checkScroll = true;
+ else
+ checkScroll = false;
+ QTest::keyClick(testWidget, key);
+ QApplication::instance()->processEvents();
+
+ switch (key) {
+ case Qt::Key_Up:
+ if (row > 0) {
+ if (item->parent())
+ item = item->parent()->child(row - 1);
+ else
+ item = testWidget->topLevelItem(row - 1);
+ row -= 1;
+ } else if (item->parent()) {
+ item = item->parent();
+ row = item->parent() ? item->parent()->indexOfChild(item) : testWidget->indexOfTopLevelItem(item);
+ }
+ break;
+ case Qt::Key_Down:
+ if (testWidget->isItemExpanded(item)) {
+ row = 0;
+ item = item->child(row);
+ } else {
+ row = qMin(rows - 1, row + 1);
+ if (item->parent())
+ item = item->parent()->child(row);
+ else
+ item = testWidget->topLevelItem(row);
+ }
+ break;
+ case Qt::Key_Left:
+ if (checkScroll) {
+ QVERIFY(testWidget->isItemExpanded(item));
+ QCOMPARE(scrollBar->value(), valueBeforeClick - scrollBar->singleStep());
+ }
+ // windows style right will walk to the parent
+ if (testWidget->currentItem() != item) {
+ QCOMPARE(testWidget->currentItem(), item->parent());
+ item = testWidget->currentItem();
+ row = item->parent() ? item->parent()->indexOfChild(item) : testWidget->indexOfTopLevelItem(item);;
+ }
+ break;
+ case Qt::Key_Right:
+ if (checkScroll)
+ QCOMPARE(scrollBar->value(), valueBeforeClick + scrollBar->singleStep());
+ // windows style right will walk to the first child
+ if (testWidget->currentItem() != item) {
+ QCOMPARE(testWidget->currentItem()->parent(), item);
+ row = item->indexOfChild(testWidget->currentItem());
+ item = testWidget->currentItem();
+ QCOMPARE(row, 0);
+ }
+ break;
+ default:
+ QVERIFY(false);
+ }
+
+ QTreeWidgetItem *current = testWidget->currentItem();
+ QCOMPARE(current->text(0), QString("[r:%1,c:0]").arg(row));
+ if (current->parent())
+ QCOMPARE(current->parent()->indexOfChild(current), row);
+ else
+ QCOMPARE(testWidget->indexOfTopLevelItem(current), row);
+ }
+}
+
+void tst_QTreeWidget::scrollToItem()
+{
+ // Check if all parent nodes of the item found are expanded.
+ // Reported in task #78761
+ QTreeWidgetItem *bar;
+ QTreeWidgetItem *search;
+ for (int i=0; i<2; ++i) {
+ bar = new QTreeWidgetItem(testWidget);
+ bar->setText(0, QString::number(i));
+
+ for (int j=0; j<2; ++j) {
+ QTreeWidgetItem *foo = new QTreeWidgetItem(bar);
+ foo->setText(0, bar->text(0) + QString::number(j));
+
+ for (int k=0; k<2; ++k) {
+ QTreeWidgetItem *yo = new QTreeWidgetItem(foo);
+ yo->setText(0, foo->text(0) + QString::number(k));
+ search = yo;
+ }
+ }
+ }
+
+ testWidget->setHeaderLabels(QStringList() << "foo");
+ testWidget->scrollToItem(search);
+ QVERIFY(search->text(0) == "111");
+
+ bar = search->parent();
+ QVERIFY(testWidget->isItemExpanded(bar));
+ bar = bar->parent();
+ QVERIFY(testWidget->isItemExpanded(bar));
+}
+
+// From task #85413
+void tst_QTreeWidget::setSortingEnabled()
+{
+ QStringList hl;
+ hl << "ID";
+ testWidget->setColumnCount(hl.count());
+ testWidget->setHeaderLabels(hl);
+
+ QTreeWidgetItem *item1 = new QTreeWidgetItem(testWidget);
+ QTreeWidgetItem *item2 = new QTreeWidgetItem(testWidget);
+
+ testWidget->setSortingEnabled(true);
+ QCOMPARE(testWidget->isSortingEnabled(), true);
+ QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
+ QCOMPARE(testWidget->topLevelItem(0), item1);
+ QCOMPARE(testWidget->topLevelItem(1), item2);
+
+ // Make sure we do it twice
+ testWidget->setSortingEnabled(true);
+ QCOMPARE(testWidget->isSortingEnabled(), true);
+ QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
+
+ testWidget->setSortingEnabled(false);
+ QCOMPARE(testWidget->isSortingEnabled(), false);
+ QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
+
+ testWidget->setSortingEnabled(false);
+ QCOMPARE(testWidget->isSortingEnabled(), false);
+ QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
+
+ // And back again so that we make sure that we test the transition from false to true
+ testWidget->setSortingEnabled(true);
+ QCOMPARE(testWidget->isSortingEnabled(), true);
+ QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
+
+ testWidget->setSortingEnabled(true);
+ QCOMPARE(testWidget->isSortingEnabled(), true);
+ QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
+
+ testWidget->setSortingEnabled(false);
+}
+
+void tst_QTreeWidget::addChild()
+{
+ QTreeWidget tree;
+ for (int x = 0; x < 2; ++x) {
+ QTreeWidget *view = x ? &tree : static_cast<QTreeWidget*>(0);
+ QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)view);
+ QCOMPARE(item->childCount(), 0);
+
+ // try to add 0
+ item->addChild(0);
+ QCOMPARE(item->childCount(), 0);
+ QCOMPARE(item->indexOfChild(0), -1);
+
+ // add one at a time
+ QList<QTreeWidgetItem*> children;
+ for (int i = 0; i < 10; ++i) {
+ QTreeWidgetItem *child = new QTreeWidgetItem();
+ item->addChild(child);
+ QCOMPARE(item->childCount(), i+1);
+ QCOMPARE(item->child(i), child);
+ QCOMPARE(item->indexOfChild(child), i);
+ QCOMPARE(child->parent(), item);
+ QCOMPARE(child->treeWidget(), view);
+ item->addChild(child);
+ QCOMPARE(item->childCount(), i+1);
+ children.append(child);
+ }
+
+ // take them all
+ QList<QTreeWidgetItem*> taken = item->takeChildren();
+ QCOMPARE(taken, children);
+ QCOMPARE(item->childCount(), 0);
+ for (int i = 0; i < taken.count(); ++i) {
+ QCOMPARE(taken.at(i)->parent(), static_cast<QTreeWidgetItem*>(0));
+ QCOMPARE(taken.at(i)->treeWidget(), static_cast<QTreeWidget*>(0));
+ item->addChild(taken.at(i)); // re-add
+ }
+
+ // delete one at a time
+ while (!children.isEmpty()) {
+ QTreeWidgetItem *ti = children.takeFirst();
+ delete ti;
+ QCOMPARE(item->childCount(), children.count());
+ for (int i = 0; i < children.count(); ++i)
+ QCOMPARE(item->child(i), children.at(i));
+ }
+
+ // add none
+ {
+ int count = item->childCount();
+ item->addChildren(QList<QTreeWidgetItem*>());
+ QCOMPARE(item->childCount(), count);
+ }
+
+ // add many at a time
+ const int count = 10;
+ for (int i = 0; i < 100; i += count) {
+ QList<QTreeWidgetItem*> list;
+ for (int j = 0; j < count; ++j)
+ list << new QTreeWidgetItem(QStringList() << QString("%0").arg(j));
+ item->addChildren(list);
+ QCOMPARE(item->childCount(), count + i);
+ for (int j = 0; j < count; ++j) {
+ QCOMPARE(item->child(i+j), list.at(j));
+ QCOMPARE(item->child(i+j)->parent(), item);
+ }
+
+ item->addChildren(list);
+ QCOMPARE(item->childCount(), count + i);
+ }
+
+ if (!view)
+ delete item;
+ }
+}
+
+void tst_QTreeWidget::setData()
+{
+ {
+ QTreeWidgetItem *headerItem = new QTreeWidgetItem();
+ headerItem->setText(0, "Item1");
+ testWidget->setHeaderItem(headerItem);
+
+ QSignalSpy headerDataChangedSpy(
+ testWidget->model(), SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
+ QSignalSpy dataChangedSpy(
+ testWidget->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+ QSignalSpy itemChangedSpy(
+ testWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)));
+ headerItem->setText(0, "test");
+ QCOMPARE(dataChangedSpy.count(), 0);
+ QCOMPARE(headerDataChangedSpy.count(), 1);
+ QCOMPARE(itemChangedSpy.count(), 0); // no itemChanged() signal for header item
+
+ headerItem->setData(-1, -1, QVariant());
+ }
+
+ {
+ QSignalSpy itemChangedSpy(
+ testWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)));
+ QTreeWidgetItem *item = new QTreeWidgetItem();
+ testWidget->addTopLevelItem(item);
+ for (int x = 0; x < 2; ++x) {
+ for (int i = 1; i <= 2; ++i) {
+ for (int j = 0; j < 5; ++j) {
+ QVariantList args;
+ QString text = QString("text %0").arg(i);
+ item->setText(j, text);
+ QCOMPARE(item->text(j), text);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setText(j, text);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QPixmap pixmap(32, 32);
+ pixmap.fill((i == 1) ? Qt::red : Qt::green);
+ QIcon icon(pixmap);
+ item->setIcon(j, icon);
+ QCOMPARE(item->icon(j), icon);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setIcon(j, icon);
+ // #### shouldn't cause dataChanged()
+ QCOMPARE(itemChangedSpy.count(), 1);
+ itemChangedSpy.clear();
+
+ QString toolTip = QString("toolTip %0").arg(i);
+ item->setToolTip(j, toolTip);
+ QCOMPARE(item->toolTip(j), toolTip);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setToolTip(j, toolTip);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QString statusTip = QString("statusTip %0").arg(i);
+ item->setStatusTip(j, statusTip);
+ QCOMPARE(item->statusTip(j), statusTip);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setStatusTip(j, statusTip);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QString whatsThis = QString("whatsThis %0").arg(i);
+ item->setWhatsThis(j, whatsThis);
+ QCOMPARE(item->whatsThis(j), whatsThis);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setWhatsThis(j, whatsThis);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QSize sizeHint(64*i, 48*i);
+ item->setSizeHint(j, sizeHint);
+ QCOMPARE(item->sizeHint(j), sizeHint);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setSizeHint(j, sizeHint);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QFont font;
+ item->setFont(j, font);
+ QCOMPARE(item->font(j), font);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setFont(j, font);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ Qt::Alignment textAlignment((i == 1)
+ ? Qt::AlignLeft|Qt::AlignVCenter
+ : Qt::AlignRight);
+ item->setTextAlignment(j, textAlignment);
+ QCOMPARE(item->textAlignment(j), int(textAlignment));
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setTextAlignment(j, textAlignment);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QColor backgroundColor((i == 1) ? Qt::blue : Qt::yellow);
+ item->setBackground(j, backgroundColor);
+ QCOMPARE(item->background(j).color(), backgroundColor);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setBackground(j, backgroundColor);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QColor textColor((i == i) ? Qt::green : Qt::cyan);
+ item->setTextColor(j, textColor);
+ QCOMPARE(item->textColor(j), textColor);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setTextColor(j, textColor);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ Qt::CheckState checkState((i == 1) ? Qt::PartiallyChecked : Qt::Checked);
+ item->setCheckState(j, checkState);
+ QCOMPARE(item->checkState(j), checkState);
+ QCOMPARE(itemChangedSpy.count(), 1);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setCheckState(j, checkState);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ QCOMPARE(item->text(j), text);
+ QCOMPARE(item->icon(j), icon);
+ QCOMPARE(item->toolTip(j), toolTip);
+ QCOMPARE(item->statusTip(j), statusTip);
+ QCOMPARE(item->whatsThis(j), whatsThis);
+ QCOMPARE(item->sizeHint(j), sizeHint);
+ QCOMPARE(item->font(j), font);
+ QCOMPARE(item->textAlignment(j), int(textAlignment));
+ QCOMPARE(item->background(j).color(), backgroundColor);
+ QCOMPARE(item->textColor(j), textColor);
+ QCOMPARE(item->checkState(j), checkState);
+
+ QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::DisplayRole)), text);
+ QCOMPARE(qvariant_cast<QIcon>(item->data(j, Qt::DecorationRole)), icon);
+ QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::ToolTipRole)), toolTip);
+ QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::StatusTipRole)), statusTip);
+ QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::WhatsThisRole)), whatsThis);
+ QCOMPARE(qvariant_cast<QSize>(item->data(j, Qt::SizeHintRole)), sizeHint);
+ QCOMPARE(qvariant_cast<QFont>(item->data(j, Qt::FontRole)), font);
+ QCOMPARE(qvariant_cast<int>(item->data(j, Qt::TextAlignmentRole)), int(textAlignment));
+ QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundColorRole)), QBrush(backgroundColor));
+ QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundRole)), QBrush(backgroundColor));
+ QCOMPARE(qvariant_cast<QColor>(item->data(j, Qt::TextColorRole)), textColor);
+ QCOMPARE(qvariant_cast<int>(item->data(j, Qt::CheckStateRole)), int(checkState));
+
+ item->setBackground(j, pixmap);
+ QCOMPARE(item->background(j).texture(), pixmap);
+ QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundRole)).texture(), pixmap);
+ args = itemChangedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
+ QCOMPARE(qvariant_cast<int>(args.at(1)), j);
+ item->setBackground(j, pixmap);
+ QCOMPARE(itemChangedSpy.count(), 0);
+
+ item->setData(j, Qt::DisplayRole, QVariant());
+ item->setData(j, Qt::DecorationRole, QVariant());
+ item->setData(j, Qt::ToolTipRole, QVariant());
+ item->setData(j, Qt::StatusTipRole, QVariant());
+ item->setData(j, Qt::WhatsThisRole, QVariant());
+ item->setData(j, Qt::SizeHintRole, QVariant());
+ item->setData(j, Qt::FontRole, QVariant());
+ item->setData(j, Qt::TextAlignmentRole, QVariant());
+ item->setData(j, Qt::BackgroundColorRole, QVariant());
+ item->setData(j, Qt::TextColorRole, QVariant());
+ item->setData(j, Qt::CheckStateRole, QVariant());
+ QCOMPARE(itemChangedSpy.count(), 11);
+ itemChangedSpy.clear();
+
+ QCOMPARE(item->data(j, Qt::DisplayRole).toString(), QString());
+ QCOMPARE(item->data(j, Qt::DecorationRole), QVariant());
+ QCOMPARE(item->data(j, Qt::ToolTipRole), QVariant());
+ QCOMPARE(item->data(j, Qt::StatusTipRole), QVariant());
+ QCOMPARE(item->data(j, Qt::WhatsThisRole), QVariant());
+ QCOMPARE(item->data(j, Qt::SizeHintRole), QVariant());
+ QCOMPARE(item->data(j, Qt::FontRole), QVariant());
+ QCOMPARE(item->data(j, Qt::TextAlignmentRole), QVariant());
+ QCOMPARE(item->data(j, Qt::BackgroundColorRole), QVariant());
+ QCOMPARE(item->data(j, Qt::BackgroundRole), QVariant());
+ QCOMPARE(item->data(j, Qt::TextColorRole), QVariant());
+ QCOMPARE(item->data(j, Qt::CheckStateRole), QVariant());
+ }
+ }
+ }
+
+ // ### add more data types here
+
+ item->setData(0, Qt::DisplayRole, 5);
+ QCOMPARE(item->data(0, Qt::DisplayRole).type(), QVariant::Int);
+
+ item->setData(0, Qt::DisplayRole, "test");
+ QCOMPARE(item->data(0, Qt::DisplayRole).type(), QVariant::String);
+
+ item->setData(0, Qt::DisplayRole, 0.4);
+ QCOMPARE(item->data(0, Qt::DisplayRole).type(), QVariant::Double);
+
+ delete item;
+ }
+}
+
+void tst_QTreeWidget::itemData()
+{
+ QTreeWidget widget;
+ QTreeWidgetItem item(&widget);
+ widget.setColumnCount(2);
+ item.setFlags(item.flags() | Qt::ItemIsEditable);
+ item.setData(0, Qt::DisplayRole, QString("0"));
+ item.setData(0, Qt::CheckStateRole, Qt::PartiallyChecked);
+ item.setData(0, Qt::UserRole + 0, QString("1"));
+ item.setData(0, Qt::UserRole + 1, QString("2"));
+ item.setData(0, Qt::UserRole + 2, QString("3"));
+ item.setData(0, Qt::UserRole + 3, QString("4"));
+
+ QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
+ QCOMPARE(flags.count(), 6);
+ QCOMPARE(flags[Qt::UserRole + 0].toString(), QString("1"));
+
+ flags = widget.model()->itemData(widget.model()->index(0, 1));
+ QCOMPARE(flags.count(), 0);
+}
+
+void tst_QTreeWidget::enableDisable()
+{
+ QTreeWidgetItem *itm = new QTreeWidgetItem();
+ for (int i = 0; i < 10; ++i)
+ new QTreeWidgetItem(itm);
+
+ // make sure all items are enabled
+ QVERIFY(itm->flags() & Qt::ItemIsEnabled);
+ for (int j = 0; j < itm->childCount(); ++j)
+ QVERIFY(itm->child(j)->flags() & Qt::ItemIsEnabled);
+
+ // disable root and make sure they are all disabled
+ itm->setFlags(itm->flags() & ~Qt::ItemIsEnabled);
+ QVERIFY(!(itm->flags() & Qt::ItemIsEnabled));
+ for (int k = 0; k < itm->childCount(); ++k)
+ QVERIFY(!(itm->child(k)->flags() & Qt::ItemIsEnabled));
+
+ // disable a child and make sure they are all still disabled
+ itm->child(5)->setFlags(itm->child(5)->flags() & ~Qt::ItemIsEnabled);
+ QVERIFY(!(itm->flags() & Qt::ItemIsEnabled));
+ for (int l = 0; l < itm->childCount(); ++l)
+ QVERIFY(!(itm->child(l)->flags() & Qt::ItemIsEnabled));
+
+ // enable root and make sure all items except one are enabled
+ itm->setFlags(itm->flags() | Qt::ItemIsEnabled);
+ QVERIFY(itm->flags() & Qt::ItemIsEnabled);
+ for (int m = 0; m < itm->childCount(); ++m)
+ if (m == 5)
+ QVERIFY(!(itm->child(m)->flags() & Qt::ItemIsEnabled));
+ else
+ QVERIFY(itm->child(m)->flags() & Qt::ItemIsEnabled);
+}
+
+void tst_QTreeWidget::match()
+{
+ QTreeWidget tree;
+ QModelIndexList list = tree.model()->match(QModelIndex(), Qt::DisplayRole, QString());
+
+ QVERIFY(list.isEmpty());
+}
+
+void tst_QTreeWidget::columnCount()
+{
+ int columnCountBefore = testWidget->columnCount();
+ testWidget->setColumnCount(-1);
+ QCOMPARE(testWidget->columnCount(), columnCountBefore);
+}
+
+void tst_QTreeWidget::setHeaderLabels()
+{
+ QStringList list = QString("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z").split(",");
+ testWidget->setHeaderLabels(list);
+ QCOMPARE(testWidget->header()->count(), list.count());
+}
+
+void tst_QTreeWidget::setHeaderItem()
+{
+ testWidget->setHeaderItem(0);
+ QTreeWidgetItem *headerItem = new QTreeWidgetItem();
+
+ testWidget->setColumnCount(0);
+ QCOMPARE(testWidget->header()->count(), 0);
+ QCOMPARE(testWidget->columnCount(), 0);
+
+ headerItem->setText(0, "0");
+ headerItem->setText(1, "1");
+ testWidget->setHeaderItem(headerItem);
+ QTest::qWait(100);
+ QCOMPARE(testWidget->headerItem(), headerItem);
+ QCOMPARE(headerItem->treeWidget(), static_cast<QTreeWidget *>(testWidget));
+
+ QCOMPARE(testWidget->header()->count(), 2);
+ QCOMPARE(testWidget->columnCount(), 2);
+
+ headerItem->setText(2, "2");
+ QCOMPARE(testWidget->header()->count(), 3);
+ QCOMPARE(testWidget->columnCount(), 3);
+
+ delete headerItem;
+ testWidget->setColumnCount(3);
+ testWidget->setColumnCount(5);
+ QCOMPARE(testWidget->model()->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(), QString("1"));
+ QCOMPARE(testWidget->model()->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString(), QString("2"));
+ QCOMPARE(testWidget->model()->headerData(2, Qt::Horizontal, Qt::DisplayRole).toString(), QString("3"));
+ QCOMPARE(testWidget->model()->headerData(3, Qt::Horizontal, Qt::DisplayRole).toString(), QString("4"));
+ QCOMPARE(testWidget->model()->headerData(4, Qt::Horizontal, Qt::DisplayRole).toString(), QString("5"));
+
+ headerItem = new QTreeWidgetItem();
+ testWidget->setHeaderItem(headerItem);
+ testWidget->model()->insertColumns(0, 5, QModelIndex());
+ QCOMPARE(testWidget->model()->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(), QString("1"));
+ QCOMPARE(testWidget->model()->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString(), QString("2"));
+ QCOMPARE(testWidget->model()->headerData(2, Qt::Horizontal, Qt::DisplayRole).toString(), QString("3"));
+ QCOMPARE(testWidget->model()->headerData(3, Qt::Horizontal, Qt::DisplayRole).toString(), QString("4"));
+ QCOMPARE(testWidget->model()->headerData(4, Qt::Horizontal, Qt::DisplayRole).toString(), QString("5"));
+}
+
+void tst_QTreeWidget::itemWidget_data()
+{
+ editItem_data();
+}
+
+void tst_QTreeWidget::itemWidget()
+{
+ QFETCH(TreeItemList, topLevelItems);
+
+ QTreeWidget tree;
+ populate(&tree, topLevelItems, new TreeItem(QStringList() << "1" << "2"));
+ tree.show();
+
+ for (int x = 0; x < 2; ++x) {
+ QTreeWidgetItemIterator it(&tree);
+ while (QTreeWidgetItem *item = (*it++)) {
+ for (int col = 0; col < item->columnCount(); ++col) {
+ if (x == 0) {
+ QCOMPARE(tree.itemWidget(item, col), static_cast<QWidget*>(0));
+ QWidget *editor = new QLineEdit();
+ tree.setItemWidget(item, col, editor);
+ QCOMPARE(tree.itemWidget(item, col), editor);
+ tree.removeItemWidget(item, col);
+ QCOMPARE(tree.itemWidget(item, col), static_cast<QWidget*>(0));
+ } else {
+ // ### should you really be able to open a persistent
+ // editor for an item that isn't editable??
+ tree.openPersistentEditor(item, col);
+ QWidget *editor = qFindChild<QLineEdit*>(&tree);
+ QVERIFY(editor != 0);
+ tree.closePersistentEditor(item, col);
+ }
+ }
+ }
+ }
+}
+
+void tst_QTreeWidget::insertItemsWithSorting_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<QStringList>("insertItems");
+ QTest::addColumn<QStringList>("expectedItems");
+ QTest::addColumn<IntList>("expectedRows");
+
+ QTest::newRow("() + (a) = (a)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList()
+ << (QStringList() << "a")
+ << (QStringList() << "a")
+ << IntList();
+ QTest::newRow("() + (c, b, a) = (a, b, c)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList()
+ << (QStringList() << "c" << "b" << "a")
+ << (QStringList() << "a" << "b" << "c")
+ << IntList();
+ QTest::newRow("() + (a, b, c) = (c, b, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QStringList()
+ << (QStringList() << "a" << "b" << "c")
+ << (QStringList() << "c" << "b" << "a")
+ << IntList();
+ QTest::newRow("(a) + (b) = (a, b)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList("a")
+ << (QStringList() << "b")
+ << (QStringList() << "a" << "b")
+ << (IntList() << 0);
+ QTest::newRow("(a) + (b) = (b, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QStringList("a")
+ << (QStringList() << "b")
+ << (QStringList() << "b" << "a")
+ << (IntList() << 1);
+ QTest::newRow("(a, c, b) + (d) = (a, b, c, d)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "b")
+ << (QStringList() << "d")
+ << (QStringList() << "a" << "b" << "c" << "d")
+ << (IntList() << 0 << 1 << 2);
+ QTest::newRow("(b, c, a) + (d) = (d, c, b, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "b" << "c" << "a")
+ << (QStringList() << "d")
+ << (QStringList() << "d" << "c" << "b" << "a")
+ << (IntList() << 1 << 2 << 3);
+ {
+ IntList ascendingRows;
+ IntList reverseRows;
+ QStringList ascendingItems;
+ QStringList reverseItems;
+ for (int i = 'a'; i <= 'z'; ++i) {
+ ascendingItems << QString("%0").arg(QLatin1Char(i));
+ reverseItems << QString("%0").arg(QLatin1Char('z' - i + 'a'));
+ ascendingRows << i - 'a';
+ reverseRows << 'z' - i + 'a';
+ }
+ QTest::newRow("() + (sorted items) = (sorted items)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QStringList()
+ << ascendingItems
+ << ascendingItems
+ << IntList();
+ QTest::newRow("(sorted items) + () = (sorted items)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << ascendingItems
+ << QStringList()
+ << ascendingItems
+ << ascendingRows;
+ QTest::newRow("() + (ascending items) = (reverse items)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QStringList()
+ << ascendingItems
+ << reverseItems
+ << IntList();
+ QTest::newRow("(reverse items) + () = (ascending items)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << reverseItems
+ << QStringList()
+ << ascendingItems
+ << ascendingRows;
+ QTest::newRow("(reverse items) + () = (reverse items)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << reverseItems
+ << QStringList()
+ << reverseItems
+ << ascendingRows;
+ }
+}
+
+void tst_QTreeWidget::insertItemsWithSorting()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initialItems);
+ QFETCH(QStringList, insertItems);
+ QFETCH(QStringList, expectedItems);
+ QFETCH(IntList, expectedRows);
+
+ for (int method = 0; method < 5; ++method) {
+ QTreeWidget w;
+ w.setSortingEnabled(true);
+ w.sortItems(0, static_cast<Qt::SortOrder>(sortOrder));
+ for (int i = 0; i < initialItems.count(); ++i)
+ w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i)));
+
+ QAbstractItemModel *model = w.model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
+ persistent << model->index(j, 0, QModelIndex());
+
+ switch (method) {
+ case 0:
+ // insert using item constructor
+ for (int i = 0; i < insertItems.size(); ++i)
+ new QTreeWidgetItem(&w, QStringList() << insertItems.at(i));
+ break;
+ case 1:
+ {
+ // insert using insertTopLevelItems()
+ QList<QTreeWidgetItem*> lst;
+ for (int i = 0; i < insertItems.size(); ++i)
+ lst << new QTreeWidgetItem(QStringList() << insertItems.at(i));
+ w.insertTopLevelItems(0, lst);
+ break;
+ }
+ case 2:
+ // insert using insertTopLevelItem()
+ for (int i = 0; i < insertItems.size(); ++i)
+ w.insertTopLevelItem(0, new QTreeWidgetItem(QStringList() << insertItems.at(i)));
+ break;
+ case 3:
+ {
+ // insert using addTopLevelItems()
+ QList<QTreeWidgetItem*> lst;
+ for (int i = 0; i < insertItems.size(); ++i)
+ lst << new QTreeWidgetItem(QStringList() << insertItems.at(i));
+ w.addTopLevelItems(lst);
+ break;
+ }
+ case 4:
+ // insert using addTopLevelItem()
+ for (int i = 0; i < insertItems.size(); ++i)
+ w.addTopLevelItem(new QTreeWidgetItem(QStringList() << insertItems.at(i)));
+ break;
+ }
+ QCOMPARE(w.topLevelItemCount(), expectedItems.count());
+ for (int i = 0; i < w.topLevelItemCount(); ++i)
+ QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i));
+
+ for (int k = 0; k < persistent.count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+ }
+}
+
+void tst_QTreeWidget::insertExpandedItemsWithSorting_data()
+{
+ QTest::addColumn<QStringList>("parentText");
+ QTest::addColumn<QStringList>("childText");
+ QTest::addColumn<QStringList>("parentResult");
+ QTest::addColumn<QStringList>("childResult");
+ QTest::newRow("test 1")
+ << (QStringList() << "c" << "d" << "a" << "b")
+ << (QStringList() << "e" << "h" << "g" << "f")
+ << (QStringList() << "d" << "c" << "b" << "a")
+ << (QStringList() << "h" << "g" << "f" << "e");
+}
+
+// From Task 134978
+void tst_QTreeWidget::insertExpandedItemsWithSorting()
+{
+ QFETCH(QStringList, parentText);
+ QFETCH(QStringList, childText);
+ QFETCH(QStringList, parentResult);
+ QFETCH(QStringList, childResult);
+
+ // create a tree with autosorting enabled
+ CustomTreeWidget tree;
+ tree.setSortingEnabled(true);
+
+ // insert expanded items in unsorted order
+ QList<QTreeWidgetItem *> items;
+ for (int i = 0; i < parentText.count(); ++i) {
+ QTreeWidgetItem *parent = new QTreeWidgetItem(&tree, QStringList(parentText.at(i)));
+ parent->setExpanded(true);
+ QVERIFY(parent->isExpanded());
+ items << parent;
+ for (int j = 0; j < childText.count(); ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(parent, QStringList(childText.at(j)));
+ items << child;
+ }
+ QCOMPARE(parent->childCount(), childText.count());
+ QVERIFY(parent->isExpanded());
+ }
+ QVERIFY(tree.model()->rowCount() == parentText.count());
+
+ // verify that the items are still expanded
+ foreach (QTreeWidgetItem *item, items) {
+ if (item->childCount() > 0)
+ QVERIFY(item->isExpanded());
+ QModelIndex idx = tree.indexFromItem(const_cast<QTreeWidgetItem *>(item));
+ QVERIFY(idx.isValid());
+ //QRect rect = tree.visualRect(idx);
+ //QVERIFY(rect.isValid());
+ // ### it is not guarantied that the index is in the viewport
+ }
+
+ // verify that the tree is sorted
+ QAbstractItemModel *model = tree.model();
+ QList<QPersistentModelIndex> parents;
+ for (int i = 0; i < model->rowCount(QModelIndex()); ++i) {
+ QPersistentModelIndex parent = model->index(i, 0, QModelIndex());
+ parents << parent;
+ }
+ QList<QPersistentModelIndex> children;
+ for (int i = 0; i < model->rowCount(parents.first()); ++i) {
+ QPersistentModelIndex child = model->index(i, 0, parents.first());
+ children << child;
+ }
+ for (int i = 0; i < parentResult.count(); ++i) {
+ QTreeWidgetItem *item = tree.topLevelItem(i);
+ QCOMPARE(item->text(0), parentResult.at(i));
+ for (int j = 0; j < childResult.count(); ++j)
+ QCOMPARE(item->child(j)->text(0), childResult.at(j));
+ }
+}
+
+void tst_QTreeWidget::changeDataWithSorting_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("itemIndex");
+ QTest::addColumn<QString>("newValue");
+ QTest::addColumn<QStringList>("expectedItems");
+ QTest::addColumn<IntList>("expectedRows");
+ QTest::addColumn<bool>("reorderingExpected");
+
+ QTest::newRow("change a to b in (a)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a")
+ << 0 << "b"
+ << (QStringList() << "b")
+ << (IntList() << 0)
+ << false;
+ QTest::newRow("change a to b in (a, c)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c")
+ << 0 << "b"
+ << (QStringList() << "b" << "c")
+ << (IntList() << 0 << 1)
+ << false;
+ QTest::newRow("change a to c in (a, b)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "b")
+ << 0 << "c"
+ << (QStringList() << "b" << "c")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("change c to a in (c, b)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "c" << "b")
+ << 0 << "a"
+ << (QStringList() << "b" << "a")
+ << (IntList() << 1 << 0)
+ << true;
+ QTest::newRow("change e to i in (a, c, e, g)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "e" << "g")
+ << 2 << "i"
+ << (QStringList() << "a" << "c" << "g" << "i")
+ << (IntList() << 0 << 1 << 3 << 2)
+ << true;
+ QTest::newRow("change e to a in (c, e, g, i)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "e" << "g" << "i")
+ << 1 << "a"
+ << (QStringList() << "a" << "c" << "g" << "i")
+ << (IntList() << 1 << 0 << 2 << 3)
+ << true;
+ QTest::newRow("change e to f in (c, e, g, i)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "c" << "e" << "g" << "i")
+ << 1 << "f"
+ << (QStringList() << "c" << "f" << "g" << "i")
+ << (IntList() << 0 << 1 << 2 << 3)
+ << false;
+}
+
+void tst_QTreeWidget::changeDataWithSorting()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, itemIndex);
+ QFETCH(QString, newValue);
+ QFETCH(QStringList, expectedItems);
+ QFETCH(IntList, expectedRows);
+ QFETCH(bool, reorderingExpected);
+
+ QTreeWidget w;
+ w.setSortingEnabled(true);
+ w.sortItems(0, static_cast<Qt::SortOrder>(sortOrder));
+ for (int i = 0; i < initialItems.count(); ++i)
+ w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i)));
+
+ QAbstractItemModel *model = w.model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
+ persistent << model->index(j, 0, QModelIndex());
+
+ QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+ QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
+
+ QTreeWidgetItem *item = w.topLevelItem(itemIndex);
+ item->setText(0, newValue);
+ for (int i = 0; i < expectedItems.count(); ++i) {
+ QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i));
+ for (int j = 0; j < persistent.count(); ++j) {
+ if (persistent.at(j).row() == i) // the same toplevel row
+ QCOMPARE(persistent.at(j).internalPointer(), (void *)w.topLevelItem(i));
+ }
+ }
+
+ for (int k = 0; k < persistent.count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
+}
+
+void tst_QTreeWidget::changeDataWithStableSorting_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("itemIndex");
+ QTest::addColumn<QString>("newValue");
+ QTest::addColumn<QStringList>("expectedItems");
+ QTest::addColumn<IntList>("expectedRows");
+ QTest::addColumn<bool>("reorderingExpected");
+ QTest::addColumn<bool>("forceChange");
+
+ QTest::newRow("change a to c in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 0 << "c"
+ << (QStringList() << "c" << "c" << "c" << "c" << "e")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << false;
+ QTest::newRow("change e to c in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 4 << "c"
+ << (QStringList() << "a" << "c" << "c" << "c" << "c")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << false;
+ QTest::newRow("change 1st c to c in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 1 << "c"
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << true;
+ QTest::newRow("change 2nd c to c in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 2 << "c"
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << true;
+ QTest::newRow("change 3rd c to c in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 3 << "c"
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << true;
+ QTest::newRow("change 1st c to c in (e, c, c, c, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "e" << "c" << "c" << "c" << "a")
+ << 1 << "c"
+ << (QStringList() << "e" << "c" << "c" << "c" << "a")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << true;
+ QTest::newRow("change 2nd c to c in (e, c, c, c, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "e" << "c" << "c" << "c" << "a")
+ << 2 << "c"
+ << (QStringList() << "e" << "c" << "c" << "c" << "a")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << true;
+ QTest::newRow("change 3rd c to c in (e, c, c, c, a)")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QStringList() << "e" << "c" << "c" << "c" << "a")
+ << 3 << "c"
+ << (QStringList() << "e" << "c" << "c" << "c" << "a")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << true;
+ QTest::newRow("change 1st c to b in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 1 << "b"
+ << (QStringList() << "a" << "b" << "c" << "c" << "e")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << false;
+ QTest::newRow("change 2nd c to b in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 2 << "b"
+ << (QStringList() << "a" << "b" << "c" << "c" << "e")
+ << (IntList() << 0 << 2 << 1 << 3 << 4)
+ << true
+ << false;
+ QTest::newRow("change 3rd c to b in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 3 << "b"
+ << (QStringList() << "a" << "b" << "c" << "c" << "e")
+ << (IntList() << 0 << 2 << 3 << 1 << 4)
+ << true
+ << false;
+ QTest::newRow("change 1st c to d in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 1 << "d"
+ << (QStringList() << "a" << "c" << "c" << "d" << "e")
+ << (IntList() << 0 << 3 << 1 << 2 << 4)
+ << true
+ << false;
+ QTest::newRow("change 2nd c to d in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 2 << "d"
+ << (QStringList() << "a" << "c" << "c" << "d" << "e")
+ << (IntList() << 0 << 1 << 3 << 2 << 4)
+ << true
+ << false;
+ QTest::newRow("change 3rd c to d in (a, c, c, c, e)")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "c" << "c" << "c" << "e")
+ << 3 << "d"
+ << (QStringList() << "a" << "c" << "c" << "d" << "e")
+ << (IntList() << 0 << 1 << 2 << 3 << 4)
+ << false
+ << false;
+}
+
+void tst_QTreeWidget::changeDataWithStableSorting()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, itemIndex);
+ QFETCH(QString, newValue);
+ QFETCH(QStringList, expectedItems);
+ QFETCH(IntList, expectedRows);
+ QFETCH(bool, reorderingExpected);
+ QFETCH(bool, forceChange);
+
+ class StableItem : public QTreeWidgetItem
+ {
+ public:
+ StableItem(const QStringList &strings) : QTreeWidgetItem(strings, QTreeWidgetItem::UserType) {}
+ void forceChangeData() {
+ emitDataChanged();
+ }
+ };
+
+ QTreeWidget w;
+ w.setSortingEnabled(true);
+ w.sortItems(0, static_cast<Qt::SortOrder>(sortOrder));
+ for (int i = 0; i < initialItems.count(); ++i)
+ w.addTopLevelItem(new StableItem(QStringList() << initialItems.at(i)));
+
+ QAbstractItemModel *model = w.model();
+ QList<QPersistentModelIndex> persistent;
+ for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
+ persistent << model->index(j, 0, QModelIndex());
+
+ QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
+ QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
+
+ StableItem *item = static_cast<StableItem *>(w.topLevelItem(itemIndex));
+ item->setText(0, newValue);
+ if (forceChange)
+ item->forceChangeData();
+ for (int i = 0; i < expectedItems.count(); ++i) {
+ QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i));
+ for (int j = 0; j < persistent.count(); ++j) {
+ if (persistent.at(j).row() == i) // the same toplevel row
+ QCOMPARE(persistent.at(j).internalPointer(), (void *)w.topLevelItem(i));
+ }
+ }
+
+ for (int k = 0; k < persistent.count(); ++k)
+ QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
+
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
+}
+
+void tst_QTreeWidget::itemOperatorLessThan()
+{
+ QTreeWidget tw;
+ tw.setColumnCount(2);
+ {
+ QTreeWidgetItem item1(&tw);
+ QTreeWidgetItem item2(&tw);
+ QCOMPARE(item1 < item2, false);
+ item1.setText(1, "a");
+ item2.setText(1, "b");
+ QCOMPARE(item1 < item2, false);
+ item1.setText(0, "a");
+ item2.setText(0, "b");
+ QCOMPARE(item1 < item2, true);
+ tw.sortItems(1, Qt::AscendingOrder);
+ item1.setText(0, "b");
+ item2.setText(0, "a");
+ QCOMPARE(item1 < item2, true);
+ tw.sortItems(0, Qt::AscendingOrder);
+ item1.setData(0, Qt::DisplayRole, 11);
+ item2.setData(0, Qt::DisplayRole, 2);
+ QCOMPARE(item1 < item2, false);
+ }
+}
+
+void tst_QTreeWidget::sortedIndexOfChild_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("itemTexts");
+ QTest::addColumn<QList<int> >("expectedIndexes");
+
+ QTest::newRow("three ascending")
+ << int(Qt::AscendingOrder)
+ << (QStringList() << "A" << "B" << "C")
+ << (QList<int>() << 0 << 1 << 2);
+
+
+ QTest::newRow("three descending")
+ << int(Qt::DescendingOrder)
+ << (QStringList() << "A" << "B" << "C")
+ << (QList<int>() << 2 << 1 << 0);
+}
+
+void tst_QTreeWidget::sortedIndexOfChild()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, itemTexts);
+ QFETCH(QList<int>, expectedIndexes);
+
+ QTreeWidget tw;
+ QList<QTreeWidgetItem*> itms;
+ QTreeWidgetItem *top = new QTreeWidgetItem(&tw, QStringList() << "top");
+
+ for (int i = 0; i < itemTexts.count(); ++i)
+ itms << new QTreeWidgetItem(top, QStringList() << itemTexts.at(i));
+
+ tw.sortItems(0, (Qt::SortOrder)sortOrder);
+ tw.expandAll();
+
+ QVERIFY(itms.count() == expectedIndexes.count());
+ for (int j = 0; j < expectedIndexes.count(); ++j)
+ QCOMPARE(top->indexOfChild(itms.at(j)), expectedIndexes.at(j));
+}
+
+void tst_QTreeWidget::expandAndCallapse()
+{
+ QTreeWidget tw;
+ QTreeWidgetItem *top = new QTreeWidgetItem(&tw, QStringList() << "top");
+ QTreeWidgetItem *p;
+ for (int i = 0; i < 10; ++i) {
+ p = new QTreeWidgetItem(top, QStringList() << QString("%1").arg(i));
+ for (int j = 0; j < 10; ++j)
+ new QTreeWidgetItem(p, QStringList() << QString("%1").arg(j));
+ }
+ QSignalSpy spy0(&tw, SIGNAL(itemExpanded(QTreeWidgetItem *)));
+ QSignalSpy spy1(&tw, SIGNAL(itemCollapsed(QTreeWidgetItem *)));
+
+
+ tw.expandItem(p);
+ tw.collapseItem(p);
+ tw.expandItem(p);
+ tw.expandItem(top);
+ tw.collapseItem(top);
+ tw.collapseItem(top);
+
+ QCOMPARE(spy0.count(), 3);
+ QCOMPARE(spy1.count(), 2);
+}
+
+void tst_QTreeWidget::setDisabled()
+{
+ QTreeWidget w;
+ QTreeWidgetItem *i1 = new QTreeWidgetItem();
+ QTreeWidgetItem *i2 = new QTreeWidgetItem(i1);
+ QTreeWidgetItem *i3 = new QTreeWidgetItem(i1);
+
+ QTreeWidgetItem *top = new QTreeWidgetItem(&w);
+ top->setDisabled(true);
+ top->addChild(i1);
+ QCOMPARE(i1->isDisabled(), true);
+ QCOMPARE(i2->isDisabled(), true);
+ QCOMPARE(i3->isDisabled(), true);
+
+ i1 = top->takeChild(0);
+ QCOMPARE(i1->isDisabled(), false);
+ QCOMPARE(i2->isDisabled(), false);
+ QCOMPARE(i3->isDisabled(), false);
+
+ top->addChild(i1);
+ QCOMPARE(i1->isDisabled(), true);
+ QCOMPARE(i2->isDisabled(), true);
+ QCOMPARE(i3->isDisabled(), true);
+
+ top->setDisabled(false);
+ QCOMPARE(i1->isDisabled(), false);
+ QCOMPARE(i2->isDisabled(), false);
+ QCOMPARE(i3->isDisabled(), false);
+
+
+
+ QList<QTreeWidgetItem*> children;
+ children.append(new QTreeWidgetItem());
+ children.append(new QTreeWidgetItem());
+ children.append(new QTreeWidgetItem());
+ i1 = top->takeChild(0);
+
+ top->addChildren(children);
+ QCOMPARE(top->child(0)->isDisabled(), false);
+ QCOMPARE(top->child(1)->isDisabled(), false);
+ QCOMPARE(top->child(1)->isDisabled(), false);
+
+ top->setDisabled(true);
+ QCOMPARE(top->child(0)->isDisabled(), true);
+ QCOMPARE(top->child(1)->isDisabled(), true);
+ QCOMPARE(top->child(1)->isDisabled(), true);
+
+ children = top->takeChildren();
+ QCOMPARE(children.at(0)->isDisabled(), false);
+ QCOMPARE(children.at(1)->isDisabled(), false);
+ QCOMPARE(children.at(1)->isDisabled(), false);
+
+}
+
+void tst_QTreeWidget::removeSelectedItem()
+{
+ QTreeWidget *w = new QTreeWidget();
+ w->setSortingEnabled(true);
+
+ QTreeWidgetItem *first = new QTreeWidgetItem();
+ first->setText(0, QLatin1String("D"));
+ w->addTopLevelItem(first);
+
+ QTreeWidgetItem *itm = new QTreeWidgetItem();
+ itm->setText(0, QLatin1String("D"));
+ w->addTopLevelItem(itm);
+
+ itm = new QTreeWidgetItem();
+ itm->setText(0, QLatin1String("C"));
+ w->addTopLevelItem(itm);
+ itm->setSelected(true);
+
+ itm = new QTreeWidgetItem();
+ itm->setText(0, QLatin1String("A"));
+ w->addTopLevelItem(itm);
+
+ //w->show();
+
+ QItemSelectionModel *selModel = w->selectionModel();
+ QCOMPARE(selModel->hasSelection(), true);
+ QCOMPARE(selModel->selectedRows().count(), 1);
+
+ QTreeWidgetItem *taken = w->takeTopLevelItem(2);
+ QCOMPARE(taken->text(0), QLatin1String("C"));
+
+ QCOMPARE(selModel->hasSelection(), false);
+ QCOMPARE(selModel->selectedRows().count(), 0);
+ QItemSelection sel = selModel->selection();
+ QCOMPARE(selModel->isSelected(w->model()->index(0,0)), false);
+
+ delete w;
+}
+
+class AnotherTreeWidget : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ AnotherTreeWidget(QWidget *parent = 0) : QTreeWidget(parent) {}
+ void deleteCurrent() { if (currentItem()) delete currentItem(); }
+};
+
+void tst_QTreeWidget::removeCurrentItem()
+{
+ AnotherTreeWidget widget;
+ QObject::connect(widget.selectionModel(),
+ SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ &widget, SLOT(clear()));
+ QTreeWidgetItem *item = new QTreeWidgetItem(&widget);
+ widget.setCurrentItem(item);
+ widget.deleteCurrent();
+}
+
+void tst_QTreeWidget::removeCurrentItem_task186451()
+{
+ AnotherTreeWidget widget;
+ QTreeWidgetItem *item = new QTreeWidgetItem(&widget, QStringList() << "1");
+ QTreeWidgetItem *item2 = new QTreeWidgetItem(&widget, QStringList() << "2");
+ widget.setCurrentItem(item);
+ widget.deleteCurrent();
+
+ QVERIFY(item2->isSelected());
+ QCOMPARE(item2, widget.currentItem());
+}
+
+
+class TreeWidget : QTreeWidget {
+
+public:
+ QModelIndex indexFromItem(QTreeWidgetItem *item, int column = 0) const {
+ return QTreeWidget::indexFromItem(item, column);
+ }
+ QTreeWidgetItem *itemFromIndex(const QModelIndex &index) const {
+ return QTreeWidget::itemFromIndex(index);
+ }
+};
+
+
+void tst_QTreeWidget::randomExpand()
+{
+ QTreeWidget tree;
+ QTreeWidgetItem *item1 = new QTreeWidgetItem(&tree);
+ QTreeWidgetItem *item3 = new QTreeWidgetItem(&tree, item1);
+ new QTreeWidgetItem(item1);
+ new QTreeWidgetItem(item3);
+
+ tree.expandAll();
+
+ /*
+ item1
+ \- item2
+ item3
+ \- item4
+ */
+
+ QTreeWidgetItem *newItem1 = 0;
+ for (int i = 0; i < 100; i++) {
+ newItem1 = new QTreeWidgetItem(&tree, item1);
+ tree.setItemExpanded(newItem1, true);
+ QCOMPARE(tree.isItemExpanded(newItem1), true);
+
+ QTreeWidgetItem *x = new QTreeWidgetItem();
+ QCOMPARE(tree.isItemExpanded(newItem1), true);
+ newItem1->addChild(x);
+
+ QCOMPARE(tree.isItemExpanded(newItem1), true);
+ }
+
+}
+
+void tst_QTreeWidget::crashTest()
+{
+ QTreeWidget *tree = new QTreeWidget();
+ tree->setColumnCount(1);
+ tree->show();
+
+ QTreeWidgetItem *item1 = new QTreeWidgetItem(tree);
+ item1->setText(0, "item1");
+ tree->setItemExpanded(item1, true);
+ QTreeWidgetItem *item2 = new QTreeWidgetItem(item1);
+ item2->setText(0, "item2");
+
+ QTreeWidgetItem *item3 = new QTreeWidgetItem(tree, item1);
+ item3->setText(0, "item3");
+ tree->setItemExpanded(item3, true);
+ QTreeWidgetItem *item4 = new QTreeWidgetItem(item3);
+ item4->setText(0, "item4");
+
+ QTreeWidgetItem *item5 = new QTreeWidgetItem(tree, item3);
+ item5->setText(0, "item5");
+ tree->setItemExpanded(item5, true);
+ QTreeWidgetItem *item6 = new QTreeWidgetItem(item5);
+ item6->setText(0, "item6");
+
+ for (int i = 0; i < 1000; i++) {
+ QTreeWidgetItem *newItem1 = new QTreeWidgetItem(tree, item1);
+ newItem1->setText(0, "newItem");
+ QTreeWidgetItem *newItem2 = new QTreeWidgetItem(newItem1);
+ newItem2->setText(0, "subItem1");
+ QTreeWidgetItem *newItem3 = new QTreeWidgetItem(newItem1, newItem2);
+ newItem3->setText(0, "subItem2");
+ delete item3;
+ item3 = newItem1;
+ }
+ QApplication::instance()->processEvents();
+
+ delete tree;
+}
+
+class CrashWidget : public QTreeWidget
+{
+public:
+ CrashWidget(QWidget *parent = 0) : QTreeWidget(parent), i(0) {
+ setSortingEnabled(true);
+ timerId = startTimer(10);
+ }
+ int i;
+protected:
+ void timerEvent(QTimerEvent * event) {
+ if (event->timerId() == timerId) {
+ QTreeWidgetItem *newItem = new QTreeWidgetItem((QStringList() << QString::number(i++)));
+ m_list.append(newItem);
+ insertTopLevelItem(0, newItem);
+ while (m_list.count() > 10)
+ delete m_list.takeFirst();
+ }
+ QTreeWidget::timerEvent(event);
+ }
+private:
+ int timerId;
+ QList<QTreeWidgetItem*> m_list;
+};
+
+void tst_QTreeWidget::sortAndSelect()
+{
+ CrashWidget w;
+ w.resize(1, 1);
+ w.show();
+ while (w.i < 100) {
+ QApplication::processEvents();
+ if (w.i & 16) {
+ QPoint pt = w.viewport()->rect().center();
+ QTest::mouseClick(w.viewport(), Qt::LeftButton, Qt::NoModifier, pt);
+ }
+ }
+ QVERIFY(true);
+}
+
+void tst_QTreeWidget::defaultRowSizes()
+{
+ QTreeWidget *tw = new QTreeWidget();
+ tw->setIconSize(QSize(50, 50));
+ tw->setColumnCount(6);
+ for (int i=0; i<10; ++i) {
+ QTreeWidgetItem *it = new QTreeWidgetItem(tw);
+ for (int j=0; j<tw->columnCount() - 1; ++j) {
+ it->setText(j, "This is a test");
+ }
+ QPixmap icon = tw->style()->standardPixmap((QStyle::StandardPixmap)(i + QStyle::SP_TitleBarMenuButton));
+ if (icon.isNull())
+ QSKIP("No pixmap found on current style, skipping this test.", SkipSingle);
+ it->setIcon(tw->columnCount() - 1,
+ icon.scaled(tw->iconSize()));
+ }
+ tw->resize(100,100);
+ tw->show();
+ QApplication::processEvents();
+
+ QRect visualRect = tw->visualItemRect(tw->topLevelItem(0));
+ QVERIFY(visualRect.height() >= 50);
+}
+
+void tst_QTreeWidget::task191552_rtl()
+{
+ Qt::LayoutDirection oldDir = qApp->layoutDirection();
+ qApp->setLayoutDirection(Qt::RightToLeft);
+
+ QTreeWidget tw;
+ tw.setColumnCount(1);
+ QTreeWidgetItem *item = new QTreeWidgetItem(&tw);
+ item->setText(0, "item 1");
+ item->setCheckState(0, Qt::Checked);
+ QCOMPARE(item->checkState(0), Qt::Checked);
+ tw.show();
+ QTest::qWait(50);
+ QStyleOptionViewItem opt;
+ opt.initFrom(&tw);
+ opt.rect = tw.visualItemRect(item);
+ const QRect checkRect = tw.style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, &tw);
+ QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::NoModifier, checkRect.center());
+ QTest::qWait(200);
+ QCOMPARE(item->checkState(0), Qt::Unchecked);
+
+ qApp->setLayoutDirection(oldDir);
+}
+
+void tst_QTreeWidget::task203673_selection()
+{
+ //we try to change the selection by rightclick + ctrl
+ //it should do anything when using ExtendedSelection
+
+ QTreeWidget tw;
+ tw.setColumnCount(1);
+ QTreeWidgetItem *item1 = new QTreeWidgetItem(&tw);
+ item1->setText(0, "item 1");
+ tw.setSelectionMode(QTreeView::ExtendedSelection);
+
+ QPoint center = tw.visualItemRect(item1).center();
+ QCOMPARE(item1->isSelected(), false);
+
+ QTest::mouseClick(tw.viewport(), Qt::RightButton, Qt::ControlModifier, center);
+ QCOMPARE(item1->isSelected(), false);
+
+ QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::ControlModifier, center);
+ QCOMPARE(item1->isSelected(), true);
+
+ QTest::mouseClick(tw.viewport(), Qt::RightButton, Qt::ControlModifier, center);
+ QCOMPARE(item1->isSelected(), true); //it shouldn't change
+
+ QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::ControlModifier, center);
+ QCOMPARE(item1->isSelected(), false);
+}
+
+
+void tst_QTreeWidget::rootItemFlags()
+{
+ QTreeWidget tw;
+ tw.setColumnCount(1);
+ QTreeWidgetItem *item = new QTreeWidgetItem(&tw);
+ item->setText(0, "item 1");
+
+ QVERIFY(tw.invisibleRootItem()->flags() & Qt::ItemIsDropEnabled);
+
+ tw.invisibleRootItem()->setFlags(tw.invisibleRootItem()->flags() & ~Qt::ItemIsDropEnabled);
+
+ QVERIFY(!(tw.invisibleRootItem()->flags() & Qt::ItemIsDropEnabled));
+}
+
+void tst_QTreeWidget::task218661_setHeaderData()
+{
+ //We check that setting header data out of bounds returns false
+ //and doesn't increase the size of the model
+ QTreeWidget tw;
+ tw.setColumnCount(1);
+ QCOMPARE(tw.columnCount(), 1);
+
+ QCOMPARE(tw.model()->setHeaderData(99999, Qt::Horizontal, QVariant()), false);
+
+ QCOMPARE(tw.columnCount(), 1);
+}
+
+void tst_QTreeWidget::task245280_sortChildren()
+{
+ QTreeWidget tw;
+ tw.setColumnCount(2);
+
+ QTreeWidgetItem top(&tw);
+ top.setText(0,"Col 0");
+ top.setText(1,"Col 1");
+ QTreeWidgetItem item1(&top);
+ item1.setText(0,"X");
+ item1.setText(1,"0");
+ QTreeWidgetItem item2(&top);
+ item2.setText(0,"A");
+ item2.setText(1,"4");
+ QTreeWidgetItem item3(&top);
+ item3.setText(0,"E");
+ item3.setText(1,"1");
+ QTreeWidgetItem item4(&top);
+ item4.setText(0,"Z");
+ item4.setText(1,"3");
+ QTreeWidgetItem item5(&top);
+ item5.setText(0,"U");
+ item5.setText(1,"2");
+ tw.expandAll();
+ tw.show();
+ top.sortChildren(1,Qt::AscendingOrder);
+
+ for (int i = 0; i < top.childCount(); ++i)
+ QCOMPARE(top.child(i)->text(1), QString::number(i));
+}
+
+void tst_QTreeWidget::task253109_itemHeight()
+{
+ QTreeWidget treeWidget;
+ treeWidget.setColumnCount(1);
+ treeWidget.show();
+ QTest::qWait(200);
+
+ QTreeWidgetItem item(&treeWidget);
+ class MyWidget : public QWidget
+ {
+ virtual QSize sizeHint() const { return QSize(200,100); }
+ } w;
+ treeWidget.setItemWidget(&item, 0, &w);
+
+ QTest::qWait(200);
+ QCOMPARE(w.geometry(), treeWidget.visualItemRect(&item));
+
+}
+
+void tst_QTreeWidget::task206367_duplication()
+{
+ QWidget topLevel;
+ QTreeWidget treeWidget(&topLevel);
+ topLevel.show();
+ treeWidget.resize(200, 200);
+
+ treeWidget.setSortingEnabled(true);
+ QTreeWidgetItem* rootItem = new QTreeWidgetItem( &treeWidget, QStringList("root") );
+ for (int nFile = 0; nFile < 2; nFile++ ) {
+ QTreeWidgetItem* itemFile = new QTreeWidgetItem(rootItem, QStringList(QString::number(nFile)));
+ for (int nRecord = 0; nRecord < 2; nRecord++)
+ new QTreeWidgetItem(itemFile , QStringList(QString::number(nRecord)));
+ itemFile->setExpanded(true);
+ }
+ rootItem->setExpanded(true);
+ QTest::qWait(2000);
+
+ //there should be enough room for 2x2 items. If there is a scrollbar, it means the items are duplicated
+ QVERIFY(!treeWidget.verticalScrollBar()->isVisible());
+
+}
+
+void tst_QTreeWidget::itemSelectionChanged()
+{
+ QVERIFY(testWidget);
+ if(testWidget->topLevelItem(0))
+ QVERIFY(testWidget->topLevelItem(0)->isSelected());
+}
+
+void tst_QTreeWidget::selectionOrder()
+{
+ testWidget->setColumnCount(1);
+ QList<QTreeWidgetItem *> items;
+ for (int i = 0; i < 10; ++i)
+ items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item: %1").arg(i))));
+ testWidget->insertTopLevelItems(0, items);
+
+ QModelIndex idx = testWidget->indexFromItem(items[0]);
+ connect(testWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
+ testWidget->selectionModel()->select(idx, QItemSelectionModel::SelectCurrent);
+ disconnect(testWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
+}
+
+void tst_QTreeWidget::setSelectionModel()
+{
+ QTreeWidget tree;
+ for(int i = 0; i < 3; ++i)
+ new QTreeWidgetItem(&tree, QStringList(QString::number(i)));
+ QItemSelectionModel selection(tree.model());
+ selection.select(tree.model()->index(1,0), QItemSelectionModel::Select);
+ tree.setSelectionModel(&selection);
+ QCOMPARE(tree.topLevelItem(1)->isSelected(), true);
+}
+
+void tst_QTreeWidget::task217309()
+{
+ QTreeWidgetItem item;
+ item.setFlags(item.flags() | Qt::ItemIsTristate);
+ QTreeWidgetItem subitem1;
+ subitem1.setFlags(subitem1.flags() | Qt::ItemIsTristate);
+ QTreeWidgetItem subitem2;
+ subitem2.setFlags(subitem2.flags() | Qt::ItemIsTristate);
+ item.addChild(&subitem1);
+ item.addChild(&subitem2);
+ subitem1.setCheckState(0, Qt::Checked);
+ subitem2.setCheckState(0, Qt::Unchecked);
+
+ QVERIFY(item.data(0, Qt::CheckStateRole) == Qt::PartiallyChecked);
+
+ subitem2.setCheckState(0, Qt::PartiallyChecked);
+ QVERIFY(item.data(0, Qt::CheckStateRole) == Qt::PartiallyChecked);
+
+ subitem2.setCheckState(0, Qt::Checked);
+ QVERIFY(item.data(0, Qt::CheckStateRole) == Qt::Checked);
+}
+
+class TreeWidgetItem : public QTreeWidgetItem
+{
+
+public:
+ void _emitDataChanged() { emitDataChanged(); }
+
+};
+
+void tst_QTreeWidget::emitDataChanged()
+{
+
+ QTreeWidget *tree = new QTreeWidget;
+ QSignalSpy spy(tree, SIGNAL(itemChanged(QTreeWidgetItem *, int)));
+ TreeWidgetItem *item = new TreeWidgetItem();
+ tree->insertTopLevelItem(0, item);
+ item->_emitDataChanged();
+ QCOMPARE(spy.count(), 1);
+
+}
+
+void tst_QTreeWidget::setCurrentItemExpandsParent()
+{
+ QTreeWidget w;
+ w.setColumnCount(1);
+ QTreeWidgetItem *i1 = new QTreeWidgetItem(&w, QStringList() << "parent");
+ QTreeWidgetItem *i2 = new QTreeWidgetItem(i1, QStringList() << "child");
+ QVERIFY(!i2->isExpanded());
+ QVERIFY(w.currentItem() == 0);
+ w.setCurrentItem(i2);
+ QVERIFY(!i2->isExpanded());
+ QCOMPARE(w.currentItem(), i2);
+}
+
+void tst_QTreeWidget::task239150_editorWidth()
+{
+ //we check that an item with no text will get an editor with a correct size
+ QTreeWidget tree;
+
+ QStyleOptionFrameV2 opt;
+ opt.init(&tree);
+ const int minWidth = tree.style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(0, 0).
+ expandedTo(QApplication::globalStrut()), 0).width();
+
+ {
+ QTreeWidgetItem item;
+ item.setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
+ tree.addTopLevelItem(&item);
+ QVERIFY(tree.itemWidget(&item, 0) == 0);
+ tree.editItem(&item);
+ QVERIFY(tree.itemWidget(&item, 0));
+ QVERIFY(tree.itemWidget(&item, 0)->width() >= minWidth);
+ }
+
+ //now let's test it with an item with a lot of text
+ {
+ QTreeWidgetItem item;
+ item.setText(0, "foooooooooooooooooooooooo");
+ item.setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
+ tree.addTopLevelItem(&item);
+ QVERIFY(tree.itemWidget(&item, 0) == 0);
+ tree.editItem(&item);
+ QVERIFY(tree.itemWidget(&item, 0));
+ QVERIFY(tree.itemWidget(&item, 0)->width() >= minWidth + tree.fontMetrics().width(item.text(0)));
+ }
+}
+
+
+
+void tst_QTreeWidget::setTextUpdate()
+{
+ QTreeWidget treeWidget;
+ treeWidget.setColumnCount(2);
+
+ class MyItemDelegate : public QStyledItemDelegate
+ {
+ public:
+ MyItemDelegate() : numPaints(0) { }
+ void paint(QPainter *painter,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ numPaints++;
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+
+ mutable int numPaints;
+ } delegate;
+
+ treeWidget.setItemDelegate(&delegate);
+ treeWidget.show();
+ QStringList strList;
+ strList << "variable1" << "0";
+ QTreeWidgetItem *item = new QTreeWidgetItem(strList);
+ treeWidget.insertTopLevelItem(0, item);
+ QTest::qWait(50);
+ QTRY_VERIFY(delegate.numPaints > 0);
+ delegate.numPaints = 0;
+
+ item->setText(1, "42");
+ QApplication::processEvents();
+ QTRY_VERIFY(delegate.numPaints > 0);
+}
+
+void tst_QTreeWidget::taskQTBUG2844_visualItemRect()
+{
+ CustomTreeWidget tree;
+ tree.resize(150, 100);
+ tree.setColumnCount(3);
+ QTreeWidgetItem item(&tree);
+
+ QRect itemRect = tree.visualItemRect(&item);
+
+ QRect rectCol0 = tree.visualRect(tree.indexFromItem(&item, 0));
+ QRect rectCol1 = tree.visualRect(tree.indexFromItem(&item, 1));
+ QRect rectCol2 = tree.visualRect(tree.indexFromItem(&item, 2));
+
+ QCOMPARE(tree.visualItemRect(&item), rectCol0 | rectCol2);
+ tree.setColumnHidden(2, true);
+ QCOMPARE(tree.visualItemRect(&item), rectCol0 | rectCol1);
+}
+
+void tst_QTreeWidget::setChildIndicatorPolicy()
+{
+ QTreeWidget treeWidget;
+ treeWidget.setColumnCount(1);
+
+ class MyItemDelegate : public QStyledItemDelegate
+ {
+ public:
+ MyItemDelegate() : numPaints(0), expectChildren(false) { }
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ numPaints++;
+ QCOMPARE(!(option.state & QStyle::State_Children), !expectChildren);
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+ mutable int numPaints;
+ bool expectChildren;
+ } delegate;
+
+ treeWidget.setItemDelegate(&delegate);
+ treeWidget.show();
+
+ QTreeWidgetItem *item = new QTreeWidgetItem(QStringList("Hello"));
+ treeWidget.insertTopLevelItem(0, item);
+ QTest::qWait(50);
+ QTRY_VERIFY(delegate.numPaints > 0);
+
+ delegate.numPaints = 0;
+ delegate.expectChildren = true;
+ item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
+ QApplication::processEvents();
+ QTRY_COMPARE(delegate.numPaints, 1);
+
+ delegate.numPaints = 0;
+ delegate.expectChildren = false;
+ item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
+ QApplication::processEvents();
+ QTRY_COMPARE(delegate.numPaints, 1);
+
+ delegate.numPaints = 0;
+ delegate.expectChildren = true;
+ new QTreeWidgetItem(item);
+ QApplication::processEvents();
+ QTRY_COMPARE(delegate.numPaints, 1);
+
+ delegate.numPaints = 0;
+ delegate.expectChildren = false;
+ item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
+ QApplication::processEvents();
+ QTRY_COMPARE(delegate.numPaints, 1);
+}
+
+
+
+QTEST_MAIN(tst_QTreeWidget)
+#include "tst_qtreewidget.moc"
diff --git a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/.gitignore b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/.gitignore
new file mode 100644
index 0000000000..6595518de7
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/.gitignore
@@ -0,0 +1 @@
+tst_qtreewidgetitemiterator
diff --git a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/qtreewidgetitemiterator.pro b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/qtreewidgetitemiterator.pro
new file mode 100644
index 0000000000..de7762e773
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/qtreewidgetitemiterator.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtreewidgetitemiterator.cpp
+
+
diff --git a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp
new file mode 100644
index 0000000000..92a1b7cce3
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp
@@ -0,0 +1,1243 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qtreewidget.h>
+#include <qtreewidgetitemiterator.h>
+#include <qapplication.h>
+#include <qeventloop.h>
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTreeWidgetItemIterator : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTreeWidgetItemIterator();
+ ~tst_QTreeWidgetItemIterator();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void postincrement();
+ void preincrement();
+ void postdecrement();
+ void predecrement();
+ void plus_eq_data();
+ void plus_eq();
+ void minus_eq_data();
+ void minus_eq();
+ void iteratorflags_data();
+ void iteratorflags();
+ void updateIfModifiedFromWidget_data();
+ void updateIfModifiedFromWidget();
+ void constructIteratorWithItem_data();
+ void constructIteratorWithItem();
+ void updateIteratorAfterDeletedItem_and_ContinueIteration_data();
+ void updateIteratorAfterDeletedItem_and_ContinueIteration();
+ void initializeIterator();
+private:
+ QTreeWidget *testWidget;
+};
+
+tst_QTreeWidgetItemIterator::tst_QTreeWidgetItemIterator(): testWidget(0)
+{
+}
+
+tst_QTreeWidgetItemIterator::~tst_QTreeWidgetItemIterator()
+{
+}
+
+void tst_QTreeWidgetItemIterator::initTestCase()
+{
+ testWidget = new QTreeWidget();
+ testWidget->clear();
+ testWidget->setColumnCount(2);
+ testWidget->show();
+
+
+ /**
+ * These are default:
+ *
+ * Qt::ItemIsSelectable
+ * |Qt::ItemIsUserCheckable
+ * |Qt::ItemIsEnabled
+ * |Qt::ItemIsDragEnabled
+ * |Qt::ItemIsDropEnabled
+ *
+ */
+ for (int i=0; i <= 16; ++i) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
+ top->setText(0, QString("top%1").arg(i));
+ switch (i) {
+ case 0: testWidget->setItemHidden(top, true);break;
+ case 1: testWidget->setItemHidden(top, false);break;
+
+ case 2: testWidget->setItemSelected(top, true);break;
+ case 3: testWidget->setItemSelected(top, false);break;
+
+ case 4: top->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);break;
+ case 5: top->setFlags(Qt::ItemIsEnabled);break;
+
+ case 6: top->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);break;
+ case 7: top->setFlags(Qt::ItemIsEnabled);break;
+
+ case 8: top->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);break;
+ case 9: top->setFlags(Qt::ItemIsEnabled);break;
+
+ case 10: top->setFlags(Qt::ItemIsEnabled);break;
+ case 11:
+ top->setFlags(0);
+ break;
+
+ case 12: top->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);break;
+ case 13: top->setFlags(Qt::ItemIsEnabled);break;
+
+ case 14: top->setCheckState(0, Qt::Checked);break;
+ case 15: top->setCheckState(0, Qt::Unchecked);break;
+ case 16: top->setCheckState(0, Qt::PartiallyChecked);break;
+ }
+ for (int j=0; j <= 16; ++j) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(top);
+ child->setText(0, QString("top%1,child%2").arg(i).arg(j));
+ switch (j) {
+ case 0: testWidget->setItemHidden(child, true);break;
+ case 1: testWidget->setItemHidden(child, false);break;
+
+ case 2: testWidget->setItemSelected(child, true);break;
+ case 3: testWidget->setItemSelected(child, false);break;
+
+ case 4: child->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);break;
+ case 5: child->setFlags(Qt::ItemIsEnabled);break;
+
+ case 6: child->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);break;
+ case 7: child->setFlags(Qt::ItemIsEnabled);break;
+
+ case 8: child->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);break;
+ case 9: child->setFlags(Qt::ItemIsEnabled);break;
+
+ case 10: child->setFlags(Qt::ItemIsEnabled);break;
+ case 11: child->setFlags(0);break;
+
+ case 12: child->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);break;
+ case 13: child->setFlags(Qt::ItemIsEnabled);break;
+
+ case 14: child->setCheckState(0, Qt::Checked);break;
+ case 15: child->setCheckState(0, Qt::Unchecked);break;
+ case 16: child->setCheckState(0, Qt::PartiallyChecked);break;
+ }
+
+ }
+ }
+}
+
+void tst_QTreeWidgetItemIterator::cleanupTestCase()
+{
+ testWidget->hide();
+ delete testWidget;
+}
+
+void tst_QTreeWidgetItemIterator::init()
+{
+}
+
+void tst_QTreeWidgetItemIterator::cleanup()
+{
+}
+
+void tst_QTreeWidgetItemIterator::iteratorflags_data()
+{
+ /*
+ // Should preferably test for all these flags (and combinations).....
+
+ All = 0x00000000,
+ Hidden = 0x00000001,
+ NotHidden = 0x00000002,
+ Selected = 0x00000004,
+ Unselected = 0x00000008,
+ Selectable = 0x00000010,
+ NotSelectable = 0x00000020,
+ DragEnabled = 0x00000040,
+ DragDisabled = 0x00000080,
+ DropEnabled = 0x00000100,
+ DropDisabled = 0x00000200,
+ HasChildren = 0x00000400,
+ NoChildren = 0x00000800,
+ Checked = 0x00001000,
+ NotChecked = 0x00002000,
+ Enabled = 0x00004000,
+ Disabled = 0x00008000,
+ Editable = 0x00010000,
+ NotEditable = 0x00020000
+*/
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("iteratorflags");
+ QTest::addColumn<QStringList>("matches");
+
+ QTest::newRow("Match all") << 0 << (int)QTreeWidgetItemIterator::All
+ << (QStringList()
+ << "top0" << "top0,child0" << "top0,child1" << "top0,child2" << "top0,child3"
+ << "top0,child4" << "top0,child5" << "top0,child6" << "top0,child7"
+ << "top0,child8" << "top0,child9" << "top0,child10" << "top0,child11"
+ << "top0,child12" << "top0,child13" << "top0,child14" << "top0,child15"
+ << "top0,child16"
+ << "top1" << "top1,child0" << "top1,child1" << "top1,child2" << "top1,child3"
+ << "top1,child4" << "top1,child5" << "top1,child6" << "top1,child7"
+ << "top1,child8" << "top1,child9" << "top1,child10" << "top1,child11"
+ << "top1,child12" << "top1,child13" << "top1,child14" << "top1,child15"
+ << "top1,child16"
+ << "top2" << "top2,child0" << "top2,child1" << "top2,child2" << "top2,child3"
+ << "top2,child4" << "top2,child5" << "top2,child6" << "top2,child7"
+ << "top2,child8" << "top2,child9" << "top2,child10" << "top2,child11"
+ << "top2,child12" << "top2,child13" << "top2,child14" << "top2,child15"
+ << "top2,child16"
+ << "top3" << "top3,child0" << "top3,child1" << "top3,child2" << "top3,child3"
+ << "top3,child4" << "top3,child5" << "top3,child6" << "top3,child7"
+ << "top3,child8" << "top3,child9" << "top3,child10" << "top3,child11"
+ << "top3,child12" << "top3,child13" << "top3,child14" << "top3,child15"
+ << "top3,child16"
+ << "top4" << "top4,child0" << "top4,child1" << "top4,child2" << "top4,child3"
+ << "top4,child4" << "top4,child5" << "top4,child6" << "top4,child7"
+ << "top4,child8" << "top4,child9" << "top4,child10" << "top4,child11"
+ << "top4,child12" << "top4,child13" << "top4,child14" << "top4,child15"
+ << "top4,child16"
+ << "top5" << "top5,child0" << "top5,child1" << "top5,child2" << "top5,child3"
+ << "top5,child4" << "top5,child5" << "top5,child6" << "top5,child7"
+ << "top5,child8" << "top5,child9" << "top5,child10" << "top5,child11"
+ << "top5,child12" << "top5,child13" << "top5,child14" << "top5,child15"
+ << "top5,child16"
+ << "top6" << "top6,child0" << "top6,child1" << "top6,child2" << "top6,child3"
+ << "top6,child4" << "top6,child5" << "top6,child6" << "top6,child7"
+ << "top6,child8" << "top6,child9" << "top6,child10" << "top6,child11"
+ << "top6,child12" << "top6,child13" << "top6,child14" << "top6,child15"
+ << "top6,child16"
+ << "top7" << "top7,child0" << "top7,child1" << "top7,child2" << "top7,child3"
+ << "top7,child4" << "top7,child5" << "top7,child6" << "top7,child7"
+ << "top7,child8" << "top7,child9" << "top7,child10" << "top7,child11"
+ << "top7,child12" << "top7,child13" << "top7,child14" << "top7,child15"
+ << "top7,child16"
+ << "top8" << "top8,child0" << "top8,child1" << "top8,child2" << "top8,child3"
+ << "top8,child4" << "top8,child5" << "top8,child6" << "top8,child7"
+ << "top8,child8" << "top8,child9" << "top8,child10" << "top8,child11"
+ << "top8,child12" << "top8,child13" << "top8,child14" << "top8,child15"
+ << "top8,child16"
+ << "top9" << "top9,child0" << "top9,child1" << "top9,child2" << "top9,child3"
+ << "top9,child4" << "top9,child5" << "top9,child6" << "top9,child7"
+ << "top9,child8" << "top9,child9" << "top9,child10" << "top9,child11"
+ << "top9,child12" << "top9,child13" << "top9,child14" << "top9,child15"
+ << "top9,child16"
+ << "top10" << "top10,child0" << "top10,child1" << "top10,child2" << "top10,child3"
+ << "top10,child4" << "top10,child5" << "top10,child6" << "top10,child7"
+ << "top10,child8" << "top10,child9" << "top10,child10" << "top10,child11"
+ << "top10,child12" << "top10,child13" << "top10,child14" << "top10,child15"
+ << "top10,child16"
+ << "top11" << "top11,child0" << "top11,child1" << "top11,child2" << "top11,child3"
+ << "top11,child4" << "top11,child5" << "top11,child6" << "top11,child7"
+ << "top11,child8" << "top11,child9" << "top11,child10" << "top11,child11"
+ << "top11,child12" << "top11,child13" << "top11,child14" << "top11,child15"
+ << "top11,child16"
+ << "top12" << "top12,child0" << "top12,child1" << "top12,child2" << "top12,child3"
+ << "top12,child4" << "top12,child5" << "top12,child6" << "top12,child7"
+ << "top12,child8" << "top12,child9" << "top12,child10" << "top12,child11"
+ << "top12,child12" << "top12,child13" << "top12,child14" << "top12,child15"
+ << "top12,child16"
+ << "top13" << "top13,child0" << "top13,child1" << "top13,child2" << "top13,child3"
+ << "top13,child4" << "top13,child5" << "top13,child6" << "top13,child7"
+ << "top13,child8" << "top13,child9" << "top13,child10" << "top13,child11"
+ << "top13,child12" << "top13,child13" << "top13,child14" << "top13,child15"
+ << "top13,child16"
+ << "top14" << "top14,child0" << "top14,child1" << "top14,child2" << "top14,child3"
+ << "top14,child4" << "top14,child5" << "top14,child6" << "top14,child7"
+ << "top14,child8" << "top14,child9" << "top14,child10" << "top14,child11"
+ << "top14,child12" << "top14,child13" << "top14,child14" << "top14,child15"
+ << "top14,child16"
+ << "top15" << "top15,child0" << "top15,child1" << "top15,child2" << "top15,child3"
+ << "top15,child4" << "top15,child5" << "top15,child6" << "top15,child7"
+ << "top15,child8" << "top15,child9" << "top15,child10" << "top15,child11"
+ << "top15,child12" << "top15,child13" << "top15,child14" << "top15,child15"
+ << "top15,child16"
+ << "top16" << "top16,child0" << "top16,child1" << "top16,child2" << "top16,child3"
+ << "top16,child4" << "top16,child5" << "top16,child6" << "top16,child7"
+ << "top16,child8" << "top16,child9" << "top16,child10" << "top16,child11"
+ << "top16,child12" << "top16,child13" << "top16,child14" << "top16,child15"
+ << "top16,child16");
+
+ QTest::newRow("Match hidden") << 0 << (int)QTreeWidgetItemIterator::Hidden
+ << (QStringList()
+ << "top0" << "top0,child0" // fails due to hidden row
+ << "top1,child0"
+ << "top2,child0"
+ << "top3,child0"
+ << "top4,child0"
+ << "top5,child0"
+ << "top6,child0"
+ << "top7,child0"
+ << "top8,child0"
+ << "top9,child0"
+ << "top10,child0"
+ << "top11,child0"
+ << "top12,child0"
+ << "top13,child0"
+ << "top14,child0"
+ << "top15,child0"
+ << "top16,child0");
+
+ QTest::newRow("Match not hidden") << 0 << (int)QTreeWidgetItemIterator::NotHidden
+ << (QStringList()
+ << "top0,child1" << "top0,child2" << "top0,child3"
+ << "top0,child4" << "top0,child5" << "top0,child6" << "top0,child7"
+ << "top0,child8" << "top0,child9" << "top0,child10" << "top0,child11"
+ << "top0,child12" << "top0,child13" << "top0,child14" << "top0,child15"
+ << "top0,child16"
+ << "top1" << "top1,child1" << "top1,child2" << "top1,child3"
+ << "top1,child4" << "top1,child5" << "top1,child6" << "top1,child7"
+ << "top1,child8" << "top1,child9" << "top1,child10" << "top1,child11"
+ << "top1,child12" << "top1,child13" << "top1,child14" << "top1,child15"
+ << "top1,child16"
+ << "top2" << "top2,child1" << "top2,child2" << "top2,child3"
+ << "top2,child4" << "top2,child5" << "top2,child6" << "top2,child7"
+ << "top2,child8" << "top2,child9" << "top2,child10" << "top2,child11"
+ << "top2,child12" << "top2,child13" << "top2,child14" << "top2,child15"
+ << "top2,child16"
+ << "top3" << "top3,child1" << "top3,child2" << "top3,child3"
+ << "top3,child4" << "top3,child5" << "top3,child6" << "top3,child7"
+ << "top3,child8" << "top3,child9" << "top3,child10" << "top3,child11"
+ << "top3,child12" << "top3,child13" << "top3,child14" << "top3,child15"
+ << "top3,child16"
+ << "top4" << "top4,child1" << "top4,child2" << "top4,child3"
+ << "top4,child4" << "top4,child5" << "top4,child6" << "top4,child7"
+ << "top4,child8" << "top4,child9" << "top4,child10" << "top4,child11"
+ << "top4,child12" << "top4,child13" << "top4,child14" << "top4,child15"
+ << "top4,child16"
+ << "top5" << "top5,child1" << "top5,child2" << "top5,child3"
+ << "top5,child4" << "top5,child5" << "top5,child6" << "top5,child7"
+ << "top5,child8" << "top5,child9" << "top5,child10" << "top5,child11"
+ << "top5,child12" << "top5,child13" << "top5,child14" << "top5,child15"
+ << "top5,child16"
+ << "top6" << "top6,child1" << "top6,child2" << "top6,child3"
+ << "top6,child4" << "top6,child5" << "top6,child6" << "top6,child7"
+ << "top6,child8" << "top6,child9" << "top6,child10" << "top6,child11"
+ << "top6,child12" << "top6,child13" << "top6,child14" << "top6,child15"
+ << "top6,child16"
+ << "top7" << "top7,child1" << "top7,child2" << "top7,child3"
+ << "top7,child4" << "top7,child5" << "top7,child6" << "top7,child7"
+ << "top7,child8" << "top7,child9" << "top7,child10" << "top7,child11"
+ << "top7,child12" << "top7,child13" << "top7,child14" << "top7,child15"
+ << "top7,child16"
+ << "top8" << "top8,child1" << "top8,child2" << "top8,child3"
+ << "top8,child4" << "top8,child5" << "top8,child6" << "top8,child7"
+ << "top8,child8" << "top8,child9" << "top8,child10" << "top8,child11"
+ << "top8,child12" << "top8,child13" << "top8,child14" << "top8,child15"
+ << "top8,child16"
+ << "top9" << "top9,child1" << "top9,child2" << "top9,child3"
+ << "top9,child4" << "top9,child5" << "top9,child6" << "top9,child7"
+ << "top9,child8" << "top9,child9" << "top9,child10" << "top9,child11"
+ << "top9,child12" << "top9,child13" << "top9,child14" << "top9,child15"
+ << "top9,child16"
+ << "top10" << "top10,child1" << "top10,child2" << "top10,child3"
+ << "top10,child4" << "top10,child5" << "top10,child6" << "top10,child7"
+ << "top10,child8" << "top10,child9" << "top10,child10" << "top10,child11"
+ << "top10,child12" << "top10,child13" << "top10,child14" << "top10,child15"
+ << "top10,child16"
+ << "top11" << "top11,child1" << "top11,child2" << "top11,child3"
+ << "top11,child4" << "top11,child5" << "top11,child6" << "top11,child7"
+ << "top11,child8" << "top11,child9" << "top11,child10" << "top11,child11"
+ << "top11,child12" << "top11,child13" << "top11,child14" << "top11,child15"
+ << "top11,child16"
+ << "top12" << "top12,child1" << "top12,child2" << "top12,child3"
+ << "top12,child4" << "top12,child5" << "top12,child6" << "top12,child7"
+ << "top12,child8" << "top12,child9" << "top12,child10" << "top12,child11"
+ << "top12,child12" << "top12,child13" << "top12,child14" << "top12,child15"
+ << "top12,child16"
+ << "top13" << "top13,child1" << "top13,child2" << "top13,child3"
+ << "top13,child4" << "top13,child5" << "top13,child6" << "top13,child7"
+ << "top13,child8" << "top13,child9" << "top13,child10" << "top13,child11"
+ << "top13,child12" << "top13,child13" << "top13,child14" << "top13,child15"
+ << "top13,child16"
+ << "top14" << "top14,child1" << "top14,child2" << "top14,child3"
+ << "top14,child4" << "top14,child5" << "top14,child6" << "top14,child7"
+ << "top14,child8" << "top14,child9" << "top14,child10" << "top14,child11"
+ << "top14,child12" << "top14,child13" << "top14,child14" << "top14,child15"
+ << "top14,child16"
+ << "top15" << "top15,child1" << "top15,child2" << "top15,child3"
+ << "top15,child4" << "top15,child5" << "top15,child6" << "top15,child7"
+ << "top15,child8" << "top15,child9" << "top15,child10" << "top15,child11"
+ << "top15,child12" << "top15,child13" << "top15,child14" << "top15,child15"
+ << "top15,child16"
+ << "top16" << "top16,child1" << "top16,child2" << "top16,child3"
+ << "top16,child4" << "top16,child5" << "top16,child6" << "top16,child7"
+ << "top16,child8" << "top16,child9" << "top16,child10" << "top16,child11"
+ << "top16,child12" << "top16,child13" << "top16,child14" << "top16,child15"
+ << "top16,child16");
+
+ QTest::newRow("Match selected") << 0 << (int)QTreeWidgetItemIterator::Selected
+ << (QStringList()
+ << "top0,child2"
+ << "top1,child2"
+ << "top2" << "top2,child2"
+ << "top3,child2"
+ << "top4,child2"
+ << "top5,child2"
+ << "top6,child2"
+ << "top7,child2"
+ << "top8,child2"
+ << "top9,child2"
+ << "top10,child2"
+ << "top11,child2"
+ << "top12,child2"
+ << "top13,child2"
+ << "top14,child2"
+ << "top15,child2"
+ << "top16,child2");
+
+ QTest::newRow("Match selectable") << 0 << (int)QTreeWidgetItemIterator::Selectable
+ << (QStringList()
+ << "top0" << "top0,child0" << "top0,child1" << "top0,child2" << "top0,child3"
+ << "top0,child4"
+ << "top0,child14" << "top0,child15"
+ << "top0,child16"
+ << "top1" << "top1,child0" << "top1,child1" << "top1,child2" << "top1,child3"
+ << "top1,child4"
+ << "top1,child14" << "top1,child15"
+ << "top1,child16"
+ << "top2" << "top2,child0" << "top2,child1" << "top2,child2" << "top2,child3"
+ << "top2,child4"
+ << "top2,child14" << "top2,child15"
+ << "top2,child16"
+ << "top3" << "top3,child0" << "top3,child1" << "top3,child2" << "top3,child3"
+ << "top3,child4"
+ << "top3,child14" << "top3,child15"
+ << "top3,child16"
+ << "top4" << "top4,child0" << "top4,child1" << "top4,child2" << "top4,child3"
+ << "top4,child4"
+ << "top4,child14" << "top4,child15"
+ << "top4,child16"
+ /* "top5"*/ << "top5,child0" << "top5,child1" << "top5,child2" << "top5,child3"
+ << "top5,child4"
+ << "top5,child14" << "top5,child15"
+ << "top5,child16"
+ /* "top6"*/ << "top6,child0" << "top6,child1" << "top6,child2" << "top6,child3"
+ << "top6,child4"
+ << "top6,child14" << "top6,child15"
+ << "top6,child16"
+ /* "top7"*/ << "top7,child0" << "top7,child1" << "top7,child2" << "top7,child3"
+ << "top7,child4"
+ << "top7,child14" << "top7,child15"
+ << "top7,child16"
+ /* "top8"*/ << "top8,child0" << "top8,child1" << "top8,child2" << "top8,child3"
+ << "top8,child4"
+ << "top8,child14" << "top8,child15"
+ << "top8,child16"
+ /* "top9"*/ << "top9,child0" << "top9,child1" << "top9,child2" << "top9,child3"
+ << "top9,child4"
+ << "top9,child14" << "top9,child15"
+ << "top9,child16"
+ /* "top10*/ << "top10,child0" << "top10,child1" << "top10,child2" << "top10,child3"
+ << "top10,child4"
+ << "top10,child14" << "top10,child15"
+ << "top10,child16"
+ /* "top11*/ << "top11,child0" << "top11,child1" << "top11,child2" << "top11,child3"
+ << "top11,child4"
+ << "top11,child14" << "top11,child15"
+ << "top11,child16"
+ /* "top12*/ << "top12,child0" << "top12,child1" << "top12,child2" << "top12,child3"
+ << "top12,child4"
+ << "top12,child14" << "top12,child15"
+ << "top12,child16"
+ /* "top13*/ << "top13,child0" << "top13,child1" << "top13,child2" << "top13,child3"
+ << "top13,child4"
+ << "top13,child14" << "top13,child15"
+ << "top13,child16"
+ << "top14" << "top14,child0" << "top14,child1" << "top14,child2" << "top14,child3"
+ << "top14,child4"
+ << "top14,child14" << "top14,child15"
+ << "top14,child16"
+ << "top15" << "top15,child0" << "top15,child1" << "top15,child2" << "top15,child3"
+ << "top15,child4"
+ << "top15,child14" << "top15,child15"
+ << "top15,child16"
+ << "top16" << "top16,child0" << "top16,child1" << "top16,child2" << "top16,child3"
+ << "top16,child4"
+ << "top16,child14" << "top16,child15"
+ << "top16,child16");
+
+
+ QTest::newRow("Match DragEnabled") << 0 << (int)QTreeWidgetItemIterator::DragEnabled
+ << (QStringList()
+ << "top0" << "top0,child0" << "top0,child1" << "top0,child2" << "top0,child3"
+ << "top0,child6"
+ << "top0,child14" << "top0,child15"
+ << "top0,child16"
+ << "top1" << "top1,child0" << "top1,child1" << "top1,child2" << "top1,child3"
+ << "top1,child6"
+ << "top1,child14" << "top1,child15"
+ << "top1,child16"
+ << "top2" << "top2,child0" << "top2,child1" << "top2,child2" << "top2,child3"
+ << "top2,child6"
+ << "top2,child14" << "top2,child15"
+ << "top2,child16"
+ << "top3" << "top3,child0" << "top3,child1" << "top3,child2" << "top3,child3"
+ << "top3,child6"
+ << "top3,child14" << "top3,child15"
+ << "top3,child16"
+ /* "top4"*/ << "top4,child0" << "top4,child1" << "top4,child2" << "top4,child3"
+ << "top4,child6"
+ << "top4,child14" << "top4,child15"
+ << "top4,child16"
+ /* "top5"*/ << "top5,child0" << "top5,child1" << "top5,child2" << "top5,child3"
+ << "top5,child6"
+ << "top5,child14" << "top5,child15"
+ << "top5,child16"
+ << "top6" << "top6,child0" << "top6,child1" << "top6,child2" << "top6,child3"
+ << "top6,child6"
+ << "top6,child14" << "top6,child15"
+ << "top6,child16"
+ /* "top7"*/ << "top7,child0" << "top7,child1" << "top7,child2" << "top7,child3"
+ << "top7,child6"
+ << "top7,child14" << "top7,child15"
+ << "top7,child16"
+ /* "top8"*/ << "top8,child0" << "top8,child1" << "top8,child2" << "top8,child3"
+ << "top8,child6"
+ << "top8,child14" << "top8,child15"
+ << "top8,child16"
+ /* "top9"*/ << "top9,child0" << "top9,child1" << "top9,child2" << "top9,child3"
+ << "top9,child6"
+ << "top9,child14" << "top9,child15"
+ << "top9,child16"
+ /* "top10*/ << "top10,child0" << "top10,child1" << "top10,child2" << "top10,child3"
+ << "top10,child6"
+ << "top10,child14" << "top10,child15"
+ << "top10,child16"
+ /* "top11*/ << "top11,child0" << "top11,child1" << "top11,child2" << "top11,child3"
+ << "top11,child6"
+ << "top11,child14" << "top11,child15"
+ << "top11,child16"
+ /* "top12*/ << "top12,child0" << "top12,child1" << "top12,child2" << "top12,child3"
+ << "top12,child6"
+ << "top12,child14" << "top12,child15"
+ << "top12,child16"
+ /* "top13*/ << "top13,child0" << "top13,child1" << "top13,child2" << "top13,child3"
+ << "top13,child6"
+ << "top13,child14" << "top13,child15"
+ << "top13,child16"
+ << "top14" << "top14,child0" << "top14,child1" << "top14,child2" << "top14,child3"
+ << "top14,child6"
+ << "top14,child14" << "top14,child15"
+ << "top14,child16"
+ << "top15" << "top15,child0" << "top15,child1" << "top15,child2" << "top15,child3"
+ << "top15,child6"
+ << "top15,child14" << "top15,child15"
+ << "top15,child16"
+ << "top16" << "top16,child0" << "top16,child1" << "top16,child2" << "top16,child3"
+ << "top16,child6"
+ << "top16,child14" << "top16,child15"
+ << "top16,child16");
+
+ QTest::newRow("Match DragDisabled") << 0 << (int)QTreeWidgetItemIterator::DragDisabled
+ << (QStringList()
+
+ /* top0 */
+ << "top0,child4" << "top0,child5" << "top0,child7" << "top0,child8"
+ << "top0,child9" << "top0,child10" << "top0,child11" << "top0,child12"
+ << "top0,child13"
+ /* top1 */
+ << "top1,child4" << "top1,child5" << "top1,child7" << "top1,child8"
+ << "top1,child9" << "top1,child10" << "top1,child11" << "top1,child12"
+ << "top1,child13"
+ /* top2 */
+ << "top2,child4" << "top2,child5" << "top2,child7" << "top2,child8"
+ << "top2,child9" << "top2,child10" << "top2,child11" << "top2,child12"
+ << "top2,child13"
+ /* top3 */
+ << "top3,child4" << "top3,child5" << "top3,child7" << "top3,child8"
+ << "top3,child9" << "top3,child10" << "top3,child11" << "top3,child12"
+ << "top3,child13"
+ << "top4"
+ << "top4,child4" << "top4,child5" << "top4,child7" << "top4,child8"
+ << "top4,child9" << "top4,child10" << "top4,child11" << "top4,child12"
+ << "top4,child13"
+ << "top5"
+ << "top5,child4" << "top5,child5" << "top5,child7" << "top5,child8"
+ << "top5,child9" << "top5,child10" << "top5,child11" << "top5,child12"
+ << "top5,child13"
+ /* "top6"*/
+ << "top6,child4" << "top6,child5" << "top6,child7" << "top6,child8"
+ << "top6,child9" << "top6,child10" << "top6,child11" << "top6,child12"
+ << "top6,child13"
+ << "top7"
+ << "top7,child4" << "top7,child5" << "top7,child7" << "top7,child8"
+ << "top7,child9" << "top7,child10" << "top7,child11" << "top7,child12"
+ << "top7,child13"
+ << "top8"
+ << "top8,child4" << "top8,child5" << "top8,child7" << "top8,child8"
+ << "top8,child9" << "top8,child10" << "top8,child11" << "top8,child12"
+ << "top8,child13"
+ << "top9"
+ << "top9,child4" << "top9,child5" << "top9,child7" << "top9,child8"
+ << "top9,child9" << "top9,child10" << "top9,child11" << "top9,child12"
+ << "top9,child13"
+ << "top10"
+ << "top10,child4" << "top10,child5" << "top10,child7" << "top10,child8"
+ << "top10,child9" << "top10,child10" << "top10,child11" << "top10,child12"
+ << "top10,child13"
+ << "top11"
+ << "top11,child4" << "top11,child5" << "top11,child7" << "top11,child8"
+ << "top11,child9" << "top11,child10" << "top11,child11" << "top11,child12"
+ << "top11,child13"
+ << "top12"
+ << "top12,child4" << "top12,child5" << "top12,child7" << "top12,child8"
+ << "top12,child9" << "top12,child10" << "top12,child11" << "top12,child12"
+ << "top12,child13"
+ << "top13"
+ << "top13,child4" << "top13,child5" << "top13,child7" << "top13,child8"
+ << "top13,child9" << "top13,child10" << "top13,child11" << "top13,child12"
+ << "top13,child13"
+ /* top14 */
+ << "top14,child4" << "top14,child5" << "top14,child7" << "top14,child8"
+ << "top14,child9" << "top14,child10" << "top14,child11" << "top14,child12"
+ << "top14,child13"
+ /* top15 */
+ << "top15,child4" << "top15,child5" << "top15,child7" << "top15,child8"
+ << "top15,child9" << "top15,child10" << "top15,child11" << "top15,child12"
+ << "top15,child13"
+ /* top16 */
+ << "top16,child4" << "top16,child5" << "top16,child7" << "top16,child8"
+ << "top16,child9" << "top16,child10" << "top16,child11" << "top16,child12"
+ << "top16,child13" );
+
+
+ QTest::newRow("Match DropEnabled") << 0 << (int)QTreeWidgetItemIterator::DropEnabled
+ << (QStringList()
+ << "top0" << "top0,child0" << "top0,child1" << "top0,child2" << "top0,child3"
+ << "top0,child8"
+ << "top0,child14" << "top0,child15"
+ << "top0,child16"
+ << "top1" << "top1,child0" << "top1,child1" << "top1,child2" << "top1,child3"
+ << "top1,child8"
+ << "top1,child14" << "top1,child15"
+ << "top1,child16"
+ << "top2" << "top2,child0" << "top2,child1" << "top2,child2" << "top2,child3"
+ << "top2,child8"
+ << "top2,child14" << "top2,child15"
+ << "top2,child16"
+ << "top3" << "top3,child0" << "top3,child1" << "top3,child2" << "top3,child3"
+ << "top3,child8"
+ << "top3,child14" << "top3,child15"
+ << "top3,child16"
+ /* "top4"*/ << "top4,child0" << "top4,child1" << "top4,child2" << "top4,child3"
+ << "top4,child8"
+ << "top4,child14" << "top4,child15"
+ << "top4,child16"
+ /* "top5"*/ << "top5,child0" << "top5,child1" << "top5,child2" << "top5,child3"
+ << "top5,child8"
+ << "top5,child14" << "top5,child15"
+ << "top5,child16"
+ /* "top6"*/ << "top6,child0" << "top6,child1" << "top6,child2" << "top6,child3"
+ << "top6,child8"
+ << "top6,child14" << "top6,child15"
+ << "top6,child16"
+ /* "top7"*/ << "top7,child0" << "top7,child1" << "top7,child2" << "top7,child3"
+ << "top7,child8"
+ << "top7,child14" << "top7,child15"
+ << "top7,child16"
+ << "top8" << "top8,child0" << "top8,child1" << "top8,child2" << "top8,child3"
+ << "top8,child8"
+ << "top8,child14" << "top8,child15"
+ << "top8,child16"
+ /* "top9"*/ << "top9,child0" << "top9,child1" << "top9,child2" << "top9,child3"
+ << "top9,child8"
+ << "top9,child14" << "top9,child15"
+ << "top9,child16"
+ /* "top10*/ << "top10,child0" << "top10,child1" << "top10,child2" << "top10,child3"
+ << "top10,child8"
+ << "top10,child14" << "top10,child15"
+ << "top10,child16"
+ /* "top11*/ << "top11,child0" << "top11,child1" << "top11,child2" << "top11,child3"
+ << "top11,child8"
+ << "top11,child14" << "top11,child15"
+ << "top11,child16"
+ /* "top12*/ << "top12,child0" << "top12,child1" << "top12,child2" << "top12,child3"
+ << "top12,child8"
+ << "top12,child14" << "top12,child15"
+ << "top12,child16"
+ /* "top13*/ << "top13,child0" << "top13,child1" << "top13,child2" << "top13,child3"
+ << "top13,child8"
+ << "top13,child14" << "top13,child15"
+ << "top13,child16"
+ << "top14" << "top14,child0" << "top14,child1" << "top14,child2" << "top14,child3"
+ << "top14,child8"
+ << "top14,child14" << "top14,child15"
+ << "top14,child16"
+ << "top15" << "top15,child0" << "top15,child1" << "top15,child2" << "top15,child3"
+ << "top15,child8"
+ << "top15,child14" << "top15,child15"
+ << "top15,child16"
+ << "top16" << "top16,child0" << "top16,child1" << "top16,child2" << "top16,child3"
+ << "top16,child8"
+ << "top16,child14" << "top16,child15"
+ << "top16,child16");
+
+ QTest::newRow("Match HasChildren") << 0 << (int)QTreeWidgetItemIterator::HasChildren
+ << (QStringList() << "top0" << "top1" << "top2" << "top3" << "top4" << "top5"
+ << "top6" << "top7" << "top8" << "top9" << "top10" << "top11" << "top12"
+ << "top13" << "top14" << "top15" << "top16");
+
+ QTest::newRow("Match Checked") << 0 << (int)QTreeWidgetItemIterator::Checked
+ << (QStringList()
+ << "top0,child14" << "top0,child16"
+ << "top1,child14" << "top1,child16"
+ << "top2,child14" << "top2,child16"
+ << "top3,child14" << "top3,child16"
+ << "top4,child14" << "top4,child16"
+ << "top5,child14" << "top5,child16"
+ << "top6,child14" << "top6,child16"
+ << "top7,child14" << "top7,child16"
+ << "top8,child14" << "top8,child16"
+ << "top9,child14" << "top9,child16"
+ << "top10,child14" << "top10,child16"
+ << "top11,child14" << "top11,child16"
+ << "top12,child14" << "top12,child16"
+ << "top13,child14" << "top13,child16"
+ << "top14"
+ << "top14,child14" << "top14,child16"
+ << "top15,child14" << "top15,child16"
+ << "top16"
+ << "top16,child14" << "top16,child16");
+
+ QTest::newRow("Match NotChecked") << 0 << (int)QTreeWidgetItemIterator::NotChecked
+ << (QStringList()
+ << "top0" << "top0,child0" << "top0,child1" << "top0,child2" << "top0,child3"
+ << "top0,child4" << "top0,child5" << "top0,child6" << "top0,child7"
+ << "top0,child8" << "top0,child9" << "top0,child10" << "top0,child11"
+ << "top0,child12" << "top0,child13" << "top0,child15"
+
+ << "top1" << "top1,child0" << "top1,child1" << "top1,child2" << "top1,child3"
+ << "top1,child4" << "top1,child5" << "top1,child6" << "top1,child7"
+ << "top1,child8" << "top1,child9" << "top1,child10" << "top1,child11"
+ << "top1,child12" << "top1,child13" << "top1,child15"
+
+ << "top2" << "top2,child0" << "top2,child1" << "top2,child2" << "top2,child3"
+ << "top2,child4" << "top2,child5" << "top2,child6" << "top2,child7"
+ << "top2,child8" << "top2,child9" << "top2,child10" << "top2,child11"
+ << "top2,child12" << "top2,child13" << "top2,child15"
+
+ << "top3" << "top3,child0" << "top3,child1" << "top3,child2" << "top3,child3"
+ << "top3,child4" << "top3,child5" << "top3,child6" << "top3,child7"
+ << "top3,child8" << "top3,child9" << "top3,child10" << "top3,child11"
+ << "top3,child12" << "top3,child13" << "top3,child15"
+
+ << "top4" << "top4,child0" << "top4,child1" << "top4,child2" << "top4,child3"
+ << "top4,child4" << "top4,child5" << "top4,child6" << "top4,child7"
+ << "top4,child8" << "top4,child9" << "top4,child10" << "top4,child11"
+ << "top4,child12" << "top4,child13" << "top4,child15"
+
+ << "top5" << "top5,child0" << "top5,child1" << "top5,child2" << "top5,child3"
+ << "top5,child4" << "top5,child5" << "top5,child6" << "top5,child7"
+ << "top5,child8" << "top5,child9" << "top5,child10" << "top5,child11"
+ << "top5,child12" << "top5,child13" << "top5,child15"
+
+ << "top6" << "top6,child0" << "top6,child1" << "top6,child2" << "top6,child3"
+ << "top6,child4" << "top6,child5" << "top6,child6" << "top6,child7"
+ << "top6,child8" << "top6,child9" << "top6,child10" << "top6,child11"
+ << "top6,child12" << "top6,child13" << "top6,child15"
+
+ << "top7" << "top7,child0" << "top7,child1" << "top7,child2" << "top7,child3"
+ << "top7,child4" << "top7,child5" << "top7,child6" << "top7,child7"
+ << "top7,child8" << "top7,child9" << "top7,child10" << "top7,child11"
+ << "top7,child12" << "top7,child13" << "top7,child15"
+
+ << "top8" << "top8,child0" << "top8,child1" << "top8,child2" << "top8,child3"
+ << "top8,child4" << "top8,child5" << "top8,child6" << "top8,child7"
+ << "top8,child8" << "top8,child9" << "top8,child10" << "top8,child11"
+ << "top8,child12" << "top8,child13" << "top8,child15"
+
+ << "top9" << "top9,child0" << "top9,child1" << "top9,child2" << "top9,child3"
+ << "top9,child4" << "top9,child5" << "top9,child6" << "top9,child7"
+ << "top9,child8" << "top9,child9" << "top9,child10" << "top9,child11"
+ << "top9,child12" << "top9,child13" << "top9,child15"
+
+ << "top10" << "top10,child0" << "top10,child1" << "top10,child2" << "top10,child3"
+ << "top10,child4" << "top10,child5" << "top10,child6" << "top10,child7"
+ << "top10,child8" << "top10,child9" << "top10,child10" << "top10,child11"
+ << "top10,child12" << "top10,child13" << "top10,child15"
+
+ << "top11" << "top11,child0" << "top11,child1" << "top11,child2" << "top11,child3"
+ << "top11,child4" << "top11,child5" << "top11,child6" << "top11,child7"
+ << "top11,child8" << "top11,child9" << "top11,child10" << "top11,child11"
+ << "top11,child12" << "top11,child13" << "top11,child15"
+
+ << "top12" << "top12,child0" << "top12,child1" << "top12,child2" << "top12,child3"
+ << "top12,child4" << "top12,child5" << "top12,child6" << "top12,child7"
+ << "top12,child8" << "top12,child9" << "top12,child10" << "top12,child11"
+ << "top12,child12" << "top12,child13" << "top12,child15"
+
+ << "top13" << "top13,child0" << "top13,child1" << "top13,child2" << "top13,child3"
+ << "top13,child4" << "top13,child5" << "top13,child6" << "top13,child7"
+ << "top13,child8" << "top13,child9" << "top13,child10" << "top13,child11"
+ << "top13,child12" << "top13,child13" << "top13,child15"
+
+ /* "top14"*/<< "top14,child0" << "top14,child1" << "top14,child2" << "top14,child3"
+ << "top14,child4" << "top14,child5" << "top14,child6" << "top14,child7"
+ << "top14,child8" << "top14,child9" << "top14,child10" << "top14,child11"
+ << "top14,child12" << "top14,child13" << "top14,child15"
+
+ << "top15" << "top15,child0" << "top15,child1" << "top15,child2" << "top15,child3"
+ << "top15,child4" << "top15,child5" << "top15,child6" << "top15,child7"
+ << "top15,child8" << "top15,child9" << "top15,child10" << "top15,child11"
+ << "top15,child12" << "top15,child13" << "top15,child15"
+
+ /* "top16"*/<< "top16,child0" << "top16,child1" << "top16,child2" << "top16,child3"
+ << "top16,child4" << "top16,child5" << "top16,child6" << "top16,child7"
+ << "top16,child8" << "top16,child9" << "top16,child10" << "top16,child11"
+ << "top16,child12" << "top16,child13" << "top16,child15");
+
+
+
+ QTest::newRow("Match Disabled") << 0 << (int)QTreeWidgetItemIterator::Disabled
+ << (QStringList()
+ << "top0,child11"
+ << "top1,child11"
+ << "top2,child11"
+ << "top3,child11"
+ << "top4,child11"
+ << "top5,child11"
+ << "top6,child11"
+ << "top7,child11"
+ << "top8,child11"
+ << "top9,child11"
+ << "top10,child11"
+ << "top11"
+ << "top11,child0"
+ << "top11,child1"
+ << "top11,child2"
+ << "top11,child3"
+ << "top11,child4"
+ << "top11,child5"
+ << "top11,child6"
+ << "top11,child7"
+ << "top11,child8"
+ << "top11,child9"
+ << "top11,child10"
+ << "top11,child11"
+ << "top11,child12"
+ << "top11,child13"
+ << "top11,child14"
+ << "top11,child15"
+ << "top11,child16"
+
+ << "top12,child11"
+ << "top13,child11"
+ << "top14,child11"
+ << "top15,child11"
+ << "top16,child11");
+
+ QTest::newRow("Match Editable") << 0 << (int)QTreeWidgetItemIterator::Editable
+ << (QStringList()
+ << "top0,child12"
+ << "top1,child12"
+ << "top2,child12"
+ << "top3,child12"
+ << "top4,child12"
+ << "top5,child12"
+ << "top6,child12"
+ << "top7,child12"
+ << "top8,child12"
+ << "top9,child12"
+ << "top10,child12"
+ << "top11,child12"
+ << "top12"
+ << "top12,child12"
+ << "top13,child12"
+ << "top14,child12"
+ << "top15,child12"
+ << "top16,child12");
+
+ QTest::newRow("Match mutually exclusive Hidden|NotHidden") << 0 << (int)(QTreeWidgetItemIterator::Hidden|QTreeWidgetItemIterator::NotHidden)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive Selected|Unselected") << 0 << (int)(QTreeWidgetItemIterator::Selected|QTreeWidgetItemIterator::Unselected)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive Selectable|NotSelectable") << 0 << (int)(QTreeWidgetItemIterator::Selectable|QTreeWidgetItemIterator::NotSelectable)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive DragEnabled|DragDisabled") << 0 << (int)(QTreeWidgetItemIterator::DragEnabled|QTreeWidgetItemIterator::DragDisabled)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive DropEnabled|DropDisabled") << 0 << (int)(QTreeWidgetItemIterator::DropEnabled|QTreeWidgetItemIterator::DropDisabled)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive HasChildren|NoChildren") << 0 << (int)(QTreeWidgetItemIterator::HasChildren|QTreeWidgetItemIterator::NoChildren)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive Checked|NotChecked") << 0 << (int)(QTreeWidgetItemIterator::Checked|QTreeWidgetItemIterator::NotChecked)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive Disabled|Enabled") << 0 << (int)(QTreeWidgetItemIterator::Disabled|QTreeWidgetItemIterator::Enabled)
+ << QStringList();
+ QTest::newRow("Match mutually exclusive Editable|NotEditable") << 0 << (int)(QTreeWidgetItemIterator::Editable|QTreeWidgetItemIterator::NotEditable)
+ << QStringList();
+}
+
+void tst_QTreeWidgetItemIterator::iteratorflags()
+{
+ QFETCH(int, start);
+ QFETCH(int, iteratorflags);
+ QFETCH(QStringList, matches);
+
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::IteratorFlags(iteratorflags));
+ it+=start;
+ int iMatch = 0;
+ while (*it && iMatch < matches.count()) {
+ QTreeWidgetItem *item = *it;
+ QCOMPARE(item->text(0), matches[iMatch]);
+ ++it;
+ ++iMatch;
+ }
+ // Make sure the expected result does not contain *more* items than the actual result.
+ QCOMPARE(iMatch, matches.size());
+}
+
+void tst_QTreeWidgetItemIterator::preincrement()
+{
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::All);
+ QTreeWidgetItem *item = *(++it);
+ // should be the second one
+ QCOMPARE(item->text(0), QString("top0,child0"));
+}
+
+void tst_QTreeWidgetItemIterator::postincrement()
+{
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::All);
+ QTreeWidgetItem *item = *(it++);
+ // should be the first one
+ QCOMPARE(item->text(0), QString("top0"));
+}
+
+void tst_QTreeWidgetItemIterator::predecrement()
+{
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::All);
+ QTreeWidgetItem *item = *(++it);
+ // should be the second one
+ QCOMPARE(item->text(0), QString("top0,child0"));
+
+ item = *(--it);
+ QCOMPARE(item->text(0), QString("top0"));
+
+}
+
+void tst_QTreeWidgetItemIterator::postdecrement()
+{
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::All);
+ QTreeWidgetItem *item = *(it++);
+ // should be the first one
+ QCOMPARE(item->text(0), QString("top0"));
+
+ //Iterator points to second one
+ item = *(it--);
+ QCOMPARE(item->text(0), QString("top0,child0"));
+
+}
+
+void tst_QTreeWidgetItemIterator::plus_eq_data()
+{
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("addition");
+ QTest::addColumn<int>("iteratorflags");
+ QTest::addColumn<QString>("expecteditem");
+
+ QTest::newRow("+=0") << 0 << 0 << (int)QTreeWidgetItemIterator::All << QString("top0");
+ QTest::newRow("+=1") << 0 << 1 << (int)QTreeWidgetItemIterator::All << QString("top0,child0");
+ QTest::newRow("+=2") << 0 << 2 << (int)QTreeWidgetItemIterator::All << QString("top0,child1");
+ QTest::newRow("+=(-1)") << 1 << -1 << (int)QTreeWidgetItemIterator::All << QString("top0");
+ QTest::newRow("+=(-2)") << 3 << -2 << (int)QTreeWidgetItemIterator::All << QString("top0,child0");
+}
+
+void tst_QTreeWidgetItemIterator::plus_eq()
+{
+ QFETCH(int, start);
+ QFETCH(int, addition);
+ QFETCH(int, iteratorflags);
+ QFETCH(QString, expecteditem);
+
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::IteratorFlags(iteratorflags));
+ it+=start;
+ it+=addition;
+ QTreeWidgetItem *item = *it;
+
+ QVERIFY(item);
+ QCOMPARE(item->text(0), expecteditem);
+
+}
+
+void tst_QTreeWidgetItemIterator::minus_eq_data()
+{
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("subtraction");
+ QTest::addColumn<int>("iteratorflags");
+ QTest::addColumn<QString>("expecteditem");
+
+ QTest::newRow("-=0") << 0 << 0 << (int)QTreeWidgetItemIterator::All << QString("top0");
+ QTest::newRow("-=1") << 2 << 1 << (int)QTreeWidgetItemIterator::All << QString("top0,child0");
+ QTest::newRow("-=2") << 4 << 2 << (int)QTreeWidgetItemIterator::All << QString("top0,child1");
+ QTest::newRow("-=(-1)") << 0 << -1 << (int)QTreeWidgetItemIterator::All << QString("top0,child0");
+ QTest::newRow("-=(-2)") << 0 << -2 << (int)QTreeWidgetItemIterator::All << QString("top0,child1");
+ QTest::newRow("-=1)") << 18 << 1 << (int)QTreeWidgetItemIterator::All << QString("top0,child16");
+ QTest::newRow("-=1)") << 1 << 1 << (int)QTreeWidgetItemIterator::All << QString("top0");
+}
+
+void tst_QTreeWidgetItemIterator::minus_eq()
+{
+ QFETCH(int, start);
+ QFETCH(int, subtraction);
+ QFETCH(int, iteratorflags);
+ QFETCH(QString, expecteditem);
+
+ QTreeWidgetItemIterator it(testWidget, QTreeWidgetItemIterator::IteratorFlags(iteratorflags));
+ it+=start;
+ it-=subtraction;
+ QTreeWidgetItem *item = *it;
+ // should be the first one
+ QVERIFY(item);
+ QCOMPARE(item->text(0), expecteditem);
+}
+
+void tst_QTreeWidgetItemIterator::updateIfModifiedFromWidget_data()
+{
+ QTest::addColumn<int>("topLevelItems");
+ QTest::addColumn<int>("childItems");
+ QTest::addColumn<int>("grandChildItems");
+ QTest::addColumn<int>("iteratorflags");
+ QTest::addColumn<int>("removeindex");
+ QTest::addColumn<int>("expecteditemindex");
+ QTest::addColumn<QString>("expecteditemvalue");
+ QTest::addColumn<QString>("expectedUpdatedCurrent");
+ QTest::addColumn<int>("expecteditemIsNull");
+
+ QTest::newRow("Remove 3, check 1") << 3 << 3 << 0 << (int)QTreeWidgetItemIterator::All
+ << 3 << 1 << QString("top0,child0") << QString("top1") << 0;
+ QTest::newRow("Remove 1, check 0") << 3 << 3 << 0 << (int)QTreeWidgetItemIterator::All
+ << 1 << 0 << QString("top0") << QString("top0,child1") << 0;
+ QTest::newRow("Remove 2, check 2") << 3 << 3 << 0 << (int)QTreeWidgetItemIterator::All
+ << 2 << 2 << QString("top0,child2") << QString("top0,child2") << 0;
+ QTest::newRow("Remove 0, check 0") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 0 << 0 << QString("top1") << QString("top1") << 0;
+ QTest::newRow("Remove top1, check top1") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 13 << 13 << QString("top2") << QString("top2") << 0;
+ QTest::newRow("Remove top0, check top1") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 0 << 13 << QString("top1") << QString("top1") << 0;
+ QTest::newRow("Remove (top0,child1), check (top0,child1)") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 5 << 5 << QString("top0,child2") << QString("top0,child2") << 0;
+ QTest::newRow("Remove (t0,c0) check (t0,c0)") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 1 << 1 << QString("top0,child1") << QString("top0,child1") << 0;
+ QTest::newRow("Remove (t0,c1) check (t0,c1)") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 5 << 5 << QString("top0,child2") << QString("top0,child2") << 0;
+ QTest::newRow("Remove (t0) check (t0,c1)") << 3 << 3 << 0 << (int)QTreeWidgetItemIterator::All
+ << 0 << 4 << QString("top1") << QString("top1") << 0;
+ QTest::newRow("Remove (t0) check (t0,c0,g1)") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 0 << 3 << QString("top1") << QString("top1") << 0;
+ QTest::newRow("Remove (top2), check if top2 is null") << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All
+ << 2*13 << 2*13 << QString() << QString() << 1;
+ QTest::newRow("Remove last item, check if iterator::current returns 0")
+ << 3 << 0 << 0 << (int)QTreeWidgetItemIterator::All << 2 << 2 << QString() << QString() << 1;
+ QTest::newRow("remove 1, iterator points to 3, should move to 1")
+ << 3 << 3 << 3 << (int)QTreeWidgetItemIterator::All << 1 << 3 << QString("top0,child1") << QString("top0,child1") << 0;
+}
+
+void tst_QTreeWidgetItemIterator::updateIfModifiedFromWidget()
+{
+ QFETCH(int, topLevelItems);
+ QFETCH(int, childItems);
+ QFETCH(int, grandChildItems);
+ QFETCH(int, iteratorflags);
+ QFETCH(int, removeindex);
+ QFETCH(int, expecteditemindex);
+ QFETCH(QString, expecteditemvalue);
+ QFETCH(QString, expectedUpdatedCurrent);
+ QFETCH(int, expecteditemIsNull);
+
+ QTreeWidget tw;
+ tw.clear();
+ tw.setColumnCount(2);
+ for (int i1=0; i1 < topLevelItems; ++i1) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(&tw);
+ top->setText(0, QString("top%1").arg(i1));
+ for (int i2=0; i2 < childItems; ++i2) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(top);
+ child->setText(0, QString("top%1,child%2").arg(i1).arg(i2));
+ for (int i3=0; i3 < grandChildItems; ++i3) {
+ QTreeWidgetItem *grandChild = new QTreeWidgetItem(child);
+ grandChild->setText(0, QString("top%1,child%2,grandchild%3").arg(i1).arg(i2).arg(i3));
+ }
+ }
+ }
+
+ QTreeWidgetItemIterator it(&tw, QTreeWidgetItemIterator::IteratorFlags(iteratorflags));
+ it+=expecteditemindex;
+ QTreeWidgetItem *item = 0;
+ QTreeWidgetItemIterator itRemove(&tw, QTreeWidgetItemIterator::IteratorFlags(iteratorflags));
+ itRemove+=removeindex;
+ item = *itRemove;
+ QVERIFY(item);
+ delete item;
+ item = *it;
+ if (expecteditemIsNull) {
+ QVERIFY(item == 0);
+ } else {
+ QVERIFY(item);
+ QCOMPARE(item->text(0), expecteditemvalue);
+ item = *itRemove;
+ if (expectedUpdatedCurrent.isNull()) {
+ QVERIFY(item == 0);
+ } else {
+ QCOMPARE(item->text(0), expectedUpdatedCurrent);
+ }
+ }
+}
+
+void tst_QTreeWidgetItemIterator::updateIteratorAfterDeletedItem_and_ContinueIteration_data()
+{
+ QTest::addColumn<int>("topLevelItems");
+ QTest::addColumn<int>("childItems");
+ QTest::addColumn<int>("grandChildItems"); // Populate the tree data
+ // we have one iterator pointing to an item in the tree.
+ // This iterator will be updated if we delete the item it is pointing to.
+ //
+ QTest::addColumn<int>("removeindex"); // The index of the node we want to remove
+ QTest::addColumn<int>("iterator_initial_index"); // The new expected index of
+ QTest::addColumn<int>("iterator_advance_after_removal");
+ QTest::addColumn<QString>("iterator_new_value"); // The new current item value of the iterator
+ QTest::newRow("Remove 13, it points to 25, it-=1. We should get top0,child2,grandchild2") << 3 << 3 << 3 << 13 << 25 << -1 << QString("top0,child2,grandchild2");
+ QTest::newRow("Remove 0, it points to 12, it+=1. We should get top1,child0") << 3 << 3 << 3 << 0 << 12 << 1 << QString("top1,child0");
+ QTest::newRow("Remove 0, it points to 12, it-=1. We should get 0") << 3 << 3 << 3 << 0 << 12 << -1 << QString();
+ QTest::newRow("Remove 0, it points to 1, it+=1. We should get top2") << 4 << 0 << 0 << 0 << 1 << 1 << QString("top2");
+ QTest::newRow("Remove 2, it points to 1, it+=0. We should get top1") << 4 << 0 << 0 << 2 << 1 << 0 << QString("top1");
+ QTest::newRow("Remove 2, it points to 1, it+=1. We should get top3") << 4 << 0 << 0 << 2 << 1 << 1 << QString("top3");
+ QTest::newRow("Remove 1, it points to 2, it+=1. We should get top0,child2") << 3 << 3 << 0 << 1 << 2 << 1 << QString("top0,child2");
+ QTest::newRow("Remove 1, it points to 2, it+=0. We should get top0,child1") << 3 << 3 << 0 << 1 << 2 << 0 << QString("top0,child1");
+ QTest::newRow("Remove 1, it points to 2, it-=1. We should get top0") << 3 << 3 << 0 << 1 << 2 << -1 << QString("top0");
+}
+
+void tst_QTreeWidgetItemIterator::updateIteratorAfterDeletedItem_and_ContinueIteration()
+{
+ QFETCH(int, topLevelItems);
+ QFETCH(int, childItems);
+ QFETCH(int, grandChildItems);
+ QFETCH(int, removeindex);
+ QFETCH(int, iterator_initial_index);
+ QFETCH(int, iterator_advance_after_removal);
+ QFETCH(QString, iterator_new_value);
+
+ QTreeWidget tw;
+ tw.clear();
+ tw.setColumnCount(2);
+ for (int i1=0; i1 < topLevelItems; ++i1) {
+ QTreeWidgetItem *top = new QTreeWidgetItem(&tw);
+ top->setText(0, QString("top%1").arg(i1));
+ for (int i2=0; i2 < childItems; ++i2) {
+ QTreeWidgetItem *child = new QTreeWidgetItem(top);
+ child->setText(0, QString("top%1,child%2").arg(i1).arg(i2));
+ for (int i3=0; i3 < grandChildItems; ++i3) {
+ QTreeWidgetItem *grandChild = new QTreeWidgetItem(child);
+ grandChild->setText(0, QString("top%1,child%2,grandchild%3").arg(i1).arg(i2).arg(i3));
+ }
+ }
+ }
+
+ QTreeWidgetItemIterator it(&tw, QTreeWidgetItemIterator::All);
+ it += iterator_initial_index;
+ QTreeWidgetItem *item = 0;
+ QTreeWidgetItemIterator itRemove(&tw, QTreeWidgetItemIterator::All);
+ itRemove+=removeindex;
+ item = *itRemove;
+ QVERIFY(item);
+ delete item;
+ it+=iterator_advance_after_removal;
+ if (iterator_new_value.isNull()) {
+ QCOMPARE((*it), (QTreeWidgetItem*)0);
+ } else {
+ QCOMPARE((*it)->text(0), iterator_new_value);
+ }
+}
+
+void tst_QTreeWidgetItemIterator::constructIteratorWithItem_data()
+{
+ QTest::addColumn<int>("indextoitem");
+ QTest::addColumn<int>("iteratorflags");
+ QTest::addColumn<QString>("expecteditem");
+
+ QTest::newRow("index 0") << 0 << 0 << QString("top0");
+ QTest::newRow("index 1") << 1 << 0 << QString("top0,child0");
+ QTest::newRow("index 2") << 2 << 0 << QString("top0,child1");
+ QTest::newRow("index 30") << 30 << 0 << QString("top1,child11");
+ QTest::newRow("305 (last item)") << 305 << 0 << QString("top16,child16");
+ QTest::newRow("index 0, advance to next matching node") << 0 << (int)QTreeWidgetItemIterator::NotHidden << QString("top0,child1");
+}
+
+void tst_QTreeWidgetItemIterator::constructIteratorWithItem()
+{
+ QFETCH(int, indextoitem);
+ QFETCH(int, iteratorflags);
+ QFETCH(QString, expecteditem);
+
+ QTreeWidgetItemIterator it(testWidget);
+ it+=indextoitem;
+ QTreeWidgetItem *item = *it;
+ QTreeWidgetItemIterator it2(item, QTreeWidgetItemIterator::IteratorFlags(iteratorflags));
+ QTreeWidgetItem *item2 = *it2;
+
+ QVERIFY(item2);
+ QCOMPARE(item2->text(0), expecteditem);
+
+}
+
+void tst_QTreeWidgetItemIterator::initializeIterator()
+{
+ QTreeWidget tw;
+ QTreeWidgetItemIterator it(&tw);
+
+ QCOMPARE((*it), static_cast<QTreeWidgetItem*>(0));
+}
+
+QTEST_MAIN(tst_QTreeWidgetItemIterator)
+#include "tst_qtreewidgetitemiterator.moc"
diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro
new file mode 100644
index 0000000000..2e55f8eba2
--- /dev/null
+++ b/tests/auto/widgets/kernel/kernel.pro
@@ -0,0 +1,17 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qaction \
+ qactiongroup \
+ qapplication \
+ qboxlayout \
+ qdesktopwidget \
+ qformlayout \
+ qgridlayout \
+ qinputcontext \
+ qlayout \
+ qsound \
+ qstackedlayout \
+ qtooltip \
+ qwidget \
+ qwidget_window \
+ qwidgetaction \
diff --git a/tests/auto/widgets/kernel/qaction/.gitignore b/tests/auto/widgets/kernel/qaction/.gitignore
new file mode 100644
index 0000000000..bf81f5bf2c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qaction/.gitignore
@@ -0,0 +1 @@
+tst_qaction
diff --git a/tests/auto/widgets/kernel/qaction/qaction.pro b/tests/auto/widgets/kernel/qaction/qaction.pro
new file mode 100644
index 0000000000..9c3648d52f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qaction/qaction.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qaction.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
new file mode 100644
index 0000000000..637ec144d2
--- /dev/null
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qaction.h>
+#include <qmenu.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAction : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAction();
+ virtual ~tst_QAction();
+
+
+ void updateState(QActionEvent *e);
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+private slots:
+ void getSetCheck();
+ void setText_data();
+ void setText();
+ void setIconText_data() { setText_data(); }
+ void setIconText();
+ void actionEvent();
+ void setStandardKeys();
+ void alternateShortcuts();
+ void enabledVisibleInteraction();
+ void task200823_tooltip();
+ void task229128TriggeredSignalWithoutActiongroup();
+ void task229128TriggeredSignalWhenInActiongroup();
+
+private:
+ int m_lastEventType;
+ QAction *m_lastAction;
+ QWidget *m_tstWidget;
+};
+
+// Testing get/set functions
+void tst_QAction::getSetCheck()
+{
+ QAction obj1(0);
+ // QActionGroup * QAction::actionGroup()
+ // void QAction::setActionGroup(QActionGroup *)
+ QActionGroup *var1 = new QActionGroup(0);
+ obj1.setActionGroup(var1);
+ QCOMPARE(var1, obj1.actionGroup());
+ obj1.setActionGroup((QActionGroup *)0);
+ QCOMPARE((QActionGroup *)0, obj1.actionGroup());
+ delete var1;
+
+ // QMenu * QAction::menu()
+ // void QAction::setMenu(QMenu *)
+ QMenu *var2 = new QMenu(0);
+ obj1.setMenu(var2);
+ QCOMPARE(var2, obj1.menu());
+ obj1.setMenu((QMenu *)0);
+ QCOMPARE((QMenu *)0, obj1.menu());
+ delete var2;
+
+ QCOMPARE(obj1.priority(), QAction::NormalPriority);
+ obj1.setPriority(QAction::LowPriority);
+ QCOMPARE(obj1.priority(), QAction::LowPriority);
+}
+
+class MyWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MyWidget(tst_QAction *tst, QWidget *parent = 0) : QWidget(parent) { this->tst = tst; }
+
+protected:
+ virtual void actionEvent(QActionEvent *e) { tst->updateState(e); }
+
+private:
+ tst_QAction *tst;
+};
+
+tst_QAction::tst_QAction()
+{
+}
+
+tst_QAction::~tst_QAction()
+{
+
+}
+
+void tst_QAction::initTestCase()
+{
+ m_lastEventType = 0;
+ m_lastAction = 0;
+
+ MyWidget *mw = new MyWidget(this);
+ m_tstWidget = mw;
+ mw->show();
+ qApp->setActiveWindow(mw);
+}
+
+void tst_QAction::cleanupTestCase()
+{
+ QWidget *testWidget = m_tstWidget;
+ if (testWidget) {
+ testWidget->hide();
+ delete testWidget;
+ }
+}
+
+void tst_QAction::setText_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("iconText");
+ QTest::addColumn<QString>("textFromIconText");
+
+ //next we fill it with data
+ QTest::newRow("Normal") << "Action" << "Action" << "Action";
+ QTest::newRow("Ampersand") << "Search && Destroy" << "Search & Destroy" << "Search && Destroy";
+ QTest::newRow("Mnemonic and ellipsis") << "O&pen File ..." << "Open File" << "Open File";
+}
+
+void tst_QAction::setText()
+{
+ QFETCH(QString, text);
+
+ QAction action(0);
+ action.setText(text);
+
+ QCOMPARE(action.text(), text);
+
+ QFETCH(QString, iconText);
+ QCOMPARE(action.iconText(), iconText);
+}
+
+void tst_QAction::setIconText()
+{
+ QFETCH(QString, iconText);
+
+ QAction action(0);
+ action.setIconText(iconText);
+ QCOMPARE(action.iconText(), iconText);
+
+ QFETCH(QString, textFromIconText);
+ QCOMPARE(action.text(), textFromIconText);
+}
+
+
+void tst_QAction::updateState(QActionEvent *e)
+{
+ if (!e) {
+ m_lastEventType = 0;
+ m_lastAction = 0;
+ } else {
+ m_lastEventType = (int)e->type();
+ m_lastAction = e->action();
+ }
+}
+
+void tst_QAction::actionEvent()
+{
+ QAction a(0);
+ a.setText("action text");
+
+ // add action
+ m_tstWidget->addAction(&a);
+ qApp->processEvents();
+
+ QCOMPARE(m_lastEventType, (int)QEvent::ActionAdded);
+ QCOMPARE(m_lastAction, &a);
+
+ // change action
+ a.setText("new action text");
+ qApp->processEvents();
+
+ QCOMPARE(m_lastEventType, (int)QEvent::ActionChanged);
+ QCOMPARE(m_lastAction, &a);
+
+ // remove action
+ m_tstWidget->removeAction(&a);
+ qApp->processEvents();
+
+ QCOMPARE(m_lastEventType, (int)QEvent::ActionRemoved);
+ QCOMPARE(m_lastAction, &a);
+}
+
+//basic testing of standard keys
+void tst_QAction::setStandardKeys()
+{
+ QAction act(0);
+ act.setShortcut(QKeySequence("CTRL+L"));
+ QList<QKeySequence> list;
+ act.setShortcuts(list);
+ act.setShortcuts(QKeySequence::Copy);
+ QVERIFY(act.shortcut() == act.shortcuts().first());
+
+ QList<QKeySequence> expected;
+#if defined(Q_WS_MAC)
+ expected << QKeySequence("CTRL+C");
+#elif defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ expected << QKeySequence("CTRL+C") << QKeySequence("CTRL+INSERT");
+#else
+ expected << QKeySequence("CTRL+C") << QKeySequence("F16") << QKeySequence("CTRL+INSERT");
+#endif
+ QVERIFY(act.shortcuts() == expected);
+}
+
+
+void tst_QAction::alternateShortcuts()
+{
+ //test the alternate shortcuts (by adding more than 1 shortcut)
+
+ QWidget *wid = m_tstWidget;
+
+ {
+ QAction act(wid);
+ wid->addAction(&act);
+ QList<QKeySequence> shlist = QList<QKeySequence>() << QKeySequence("CTRL+P") << QKeySequence("CTRL+A");
+ act.setShortcuts(shlist);
+
+ QSignalSpy spy(&act, SIGNAL(triggered()));
+
+ act.setAutoRepeat(true);
+ QTest::keyClick(wid, Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 1); //act should have been triggered
+
+ act.setAutoRepeat(false);
+ QTest::keyClick(wid, Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time
+
+ //end of the scope of the action, it will be destroyed and removed from wid
+ //This action should also unregister its shortcuts
+ }
+
+
+ //this tests a crash (if the action did not unregister its alternate shortcuts)
+ QTest::keyClick(wid, Qt::Key_A, Qt::ControlModifier);
+}
+
+void tst_QAction::enabledVisibleInteraction()
+{
+ QAction act(0);
+ // check defaults
+ QVERIFY(act.isEnabled());
+ QVERIFY(act.isVisible());
+
+ // !visible => !enabled
+ act.setVisible(false);
+ QVERIFY(!act.isEnabled());
+ act.setVisible(true);
+ QVERIFY(act.isEnabled());
+ act.setEnabled(false);
+ QVERIFY(act.isVisible());
+
+ // check if shortcut is disabled if not visible
+ m_tstWidget->addAction(&act);
+ act.setShortcut(QKeySequence("Ctrl+T"));
+ QSignalSpy spy(&act, SIGNAL(triggered()));
+ act.setEnabled(true);
+ act.setVisible(false);
+ QTest::keyClick(m_tstWidget, Qt::Key_T, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger
+ act.setVisible(false);
+ act.setEnabled(true);
+ QTest::keyClick(m_tstWidget, Qt::Key_T, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger
+ act.setVisible(true);
+ act.setEnabled(true);
+ QTest::keyClick(m_tstWidget, Qt::Key_T, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 1); //act is visible and enabled, so trigger
+}
+
+void tst_QAction::task200823_tooltip()
+{
+ QAction *action = new QAction("foo", 0);
+ QString shortcut("ctrl+o");
+ action->setShortcut(shortcut);
+
+ // we want a non-standard tooltip that shows the shortcut
+ action->setToolTip(QString("%1 (%2)").arg(action->text()).arg(action->shortcut().toString()));
+
+ QString ref = QString("foo (%1)").arg(QKeySequence(shortcut).toString());
+ QCOMPARE(action->toolTip(), ref);
+}
+
+void tst_QAction::task229128TriggeredSignalWithoutActiongroup()
+{
+ // test without a group
+ QAction *actionWithoutGroup = new QAction("Test", qApp);
+ QSignalSpy spyWithoutGroup(actionWithoutGroup, SIGNAL(triggered(bool)));
+ QCOMPARE(spyWithoutGroup.count(), 0);
+ actionWithoutGroup->trigger();
+ // signal should be emitted
+ QCOMPARE(spyWithoutGroup.count(), 1);
+
+ // it is now a checkable checked action
+ actionWithoutGroup->setCheckable(true);
+ actionWithoutGroup->setChecked(true);
+ spyWithoutGroup.clear();
+ QCOMPARE(spyWithoutGroup.count(), 0);
+ actionWithoutGroup->trigger();
+ // signal should be emitted
+ QCOMPARE(spyWithoutGroup.count(), 1);
+}
+
+void tst_QAction::task229128TriggeredSignalWhenInActiongroup()
+{
+ QActionGroup ag(0);
+ QAction *action = new QAction("Test", &ag);
+ QAction *checkedAction = new QAction("Test 2", &ag);
+ ag.addAction(action);
+ action->setCheckable(true);
+ ag.addAction(checkedAction);
+ checkedAction->setCheckable(true);
+ checkedAction->setChecked(true);
+
+ QSignalSpy actionSpy(checkedAction, SIGNAL(triggered(bool)));
+ QSignalSpy actionGroupSpy(&ag, SIGNAL(triggered(QAction *)));
+ QCOMPARE(actionGroupSpy.count(), 0);
+ QCOMPARE(actionSpy.count(), 0);
+ checkedAction->trigger();
+ // check that both the group and the action have emitted the signal
+ QCOMPARE(actionGroupSpy.count(), 1);
+ QCOMPARE(actionSpy.count(), 1);
+}
+
+QTEST_MAIN(tst_QAction)
+#include "tst_qaction.moc"
diff --git a/tests/auto/widgets/kernel/qactiongroup/.gitignore b/tests/auto/widgets/kernel/qactiongroup/.gitignore
new file mode 100644
index 0000000000..daba003e96
--- /dev/null
+++ b/tests/auto/widgets/kernel/qactiongroup/.gitignore
@@ -0,0 +1 @@
+tst_qactiongroup
diff --git a/tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro b/tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro
new file mode 100644
index 0000000000..9b8636968b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qactiongroup.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
new file mode 100644
index 0000000000..406298807a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qmainwindow.h>
+#include <qmenu.h>
+#include <qaction.h>
+
+class tst_QActionGroup : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void enabledPropagation();
+ void visiblePropagation();
+ void exclusive();
+ void separators();
+ void testActionInTwoQActionGroup();
+ void unCheckCurrentAction();
+};
+
+void tst_QActionGroup::enabledPropagation()
+{
+ QActionGroup testActionGroup( 0 );
+
+ QAction* childAction = new QAction( &testActionGroup );
+ QAction* anotherChildAction = new QAction( &testActionGroup );
+ QAction* freeAction = new QAction(0);
+
+ QVERIFY( testActionGroup.isEnabled() );
+ QVERIFY( childAction->isEnabled() );
+
+ testActionGroup.setEnabled( false );
+ QVERIFY( !testActionGroup.isEnabled() );
+ QVERIFY( !childAction->isEnabled() );
+ QVERIFY( !anotherChildAction->isEnabled() );
+
+ childAction->setEnabled(true);
+ QVERIFY( !childAction->isEnabled());
+
+ anotherChildAction->setEnabled( false );
+
+ testActionGroup.setEnabled( true );
+ QVERIFY( testActionGroup.isEnabled() );
+ QVERIFY( childAction->isEnabled() );
+ QVERIFY( !anotherChildAction->isEnabled() );
+
+ testActionGroup.setEnabled( false );
+ QAction *lastChildAction = new QAction(&testActionGroup);
+
+ QVERIFY(!lastChildAction->isEnabled());
+ testActionGroup.setEnabled( true );
+ QVERIFY(lastChildAction->isEnabled());
+
+ freeAction->setEnabled(false);
+ testActionGroup.addAction(freeAction);
+ QVERIFY(!freeAction->isEnabled());
+ delete freeAction;
+}
+
+void tst_QActionGroup::visiblePropagation()
+{
+ QActionGroup testActionGroup( 0 );
+
+ QAction* childAction = new QAction( &testActionGroup );
+ QAction* anotherChildAction = new QAction( &testActionGroup );
+ QAction* freeAction = new QAction(0);
+
+ QVERIFY( testActionGroup.isVisible() );
+ QVERIFY( childAction->isVisible() );
+
+ testActionGroup.setVisible( false );
+ QVERIFY( !testActionGroup.isVisible() );
+ QVERIFY( !childAction->isVisible() );
+ QVERIFY( !anotherChildAction->isVisible() );
+
+ anotherChildAction->setVisible(false);
+
+ testActionGroup.setVisible( true );
+ QVERIFY( testActionGroup.isVisible() );
+ QVERIFY( childAction->isVisible() );
+
+ QVERIFY( !anotherChildAction->isVisible() );
+
+ testActionGroup.setVisible( false );
+ QAction *lastChildAction = new QAction(&testActionGroup);
+
+ QVERIFY(!lastChildAction->isVisible());
+ testActionGroup.setVisible( true );
+ QVERIFY(lastChildAction->isVisible());
+
+ freeAction->setVisible(false);
+ testActionGroup.addAction(freeAction);
+ QVERIFY(!freeAction->isVisible());
+ delete freeAction;
+}
+
+void tst_QActionGroup::exclusive()
+{
+ QActionGroup group(0);
+ group.setExclusive(false);
+ QVERIFY( !group.isExclusive() );
+
+ QAction* actOne = new QAction( &group );
+ actOne->setCheckable( true );
+ QAction* actTwo = new QAction( &group );
+ actTwo->setCheckable( true );
+ QAction* actThree = new QAction( &group );
+ actThree->setCheckable( true );
+
+ group.setExclusive( true );
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actOne->setChecked( true );
+ QVERIFY( actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actTwo->setChecked( true );
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+}
+
+void tst_QActionGroup::separators()
+{
+ QMainWindow mw;
+ QMenu menu(&mw);
+ QActionGroup actGroup(&mw);
+
+ mw.show();
+
+#ifdef QT_SOFTKEYS_ENABLED
+ // Softkeys add extra "Select" and "Back" actions to menu by default.
+ // Two first actions will be Select and Back when softkeys are enabled
+ int numSoftkeyActions = 2;
+#else
+ int numSoftkeyActions = 0;
+#endif
+
+ QAction *action = new QAction(&actGroup);
+ action->setText("test one");
+
+ QAction *separator = new QAction(&actGroup);
+ separator->setSeparator(true);
+ actGroup.addAction(separator);
+
+ QListIterator<QAction*> it(actGroup.actions());
+ while (it.hasNext())
+ menu.addAction(it.next());
+
+ QCOMPARE((int)menu.actions().size(), 2 + numSoftkeyActions);
+
+ it = QListIterator<QAction*>(actGroup.actions());
+ while (it.hasNext())
+ menu.removeAction(it.next());
+
+ QCOMPARE((int)menu.actions().size(), 0 + numSoftkeyActions);
+
+ action = new QAction(&actGroup);
+ action->setText("test two");
+
+ it = QListIterator<QAction*>(actGroup.actions());
+ while (it.hasNext())
+ menu.addAction(it.next());
+
+ QCOMPARE((int)menu.actions().size(), 3 + numSoftkeyActions);
+}
+
+void tst_QActionGroup::testActionInTwoQActionGroup()
+{
+ QAction action1("Action 1", this);
+
+ QActionGroup group1(this);
+ QActionGroup group2(this);
+
+ group1.addAction(&action1);
+ group2.addAction(&action1);
+
+ QCOMPARE(action1.actionGroup(), &group2);
+ QCOMPARE(group2.actions().first(), &action1);
+ QCOMPARE(group1.actions().isEmpty(), true);
+}
+
+void tst_QActionGroup::unCheckCurrentAction()
+{
+ QActionGroup group(0);
+ QAction action1(&group) ,action2(&group);
+ action1.setCheckable(true);
+ action2.setCheckable(true);
+ QVERIFY(!action1.isChecked());
+ QVERIFY(!action2.isChecked());
+ action1.setChecked(true);
+ QVERIFY(action1.isChecked());
+ QVERIFY(!action2.isChecked());
+ QAction *current = group.checkedAction();
+ QCOMPARE(current, &action1);
+ current->setChecked(false);
+ QVERIFY(!action1.isChecked());
+ QVERIFY(!action2.isChecked());
+ QVERIFY(group.checkedAction() == 0);
+}
+
+
+QTEST_MAIN(tst_QActionGroup)
+#include "tst_qactiongroup.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/.gitignore b/tests/auto/widgets/kernel/qapplication/.gitignore
new file mode 100644
index 0000000000..ca666e480a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/.gitignore
@@ -0,0 +1,3 @@
+tst_qapplication
+desktopsettingsaware/desktopsettingsaware
+wincmdline/wincmdline
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
new file mode 100644
index 0000000000..216a9710c7
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
@@ -0,0 +1,14 @@
+######################################################################
+# Automatically generated by qmake (2.00a) Mon Jul 11 11:30:34 2005
+######################################################################
+
+TEMPLATE = app
+DEPENDPATH += .
+INCLUDEPATH += .
+wince*:TARGET = ../desktopsettingsaware
+
+# Input
+QT += widgets
+SOURCES += main.cpp
+CONFIG += qt warn_on create_prl link_prl
+CONFIG -= app_bundle
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
new file mode 100644
index 0000000000..9e2172829a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QApplication>
+#include <QComboBox>
+
+int main(int argc, char **argv) {
+ QApplication::setDesktopSettingsAware(false);
+ QApplication app(argc, argv);
+ QComboBox box;
+ box.insertItem(0, "foo");
+ box.setEditable(true);
+ box.show();
+ return 0;
+}
diff --git a/tests/auto/widgets/kernel/qapplication/heart.svg b/tests/auto/widgets/kernel/qapplication/heart.svg
new file mode 100644
index 0000000000..8c982cd93c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/heart.svg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) --><svg viewBox="100 200 550 500" height="841.88976pt" id="svg1" inkscape:version="0.40+cvs" sodipodi:docbase="C:\Documents and Settings\Jon Phillips\My Documents\projects\clipart-project\submissions" sodipodi:docname="heart-left-highlight.svg" sodipodi:version="0.32" width="595.27559pt" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
+<metadata>
+<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<cc:Work rdf:about="">
+<dc:title>Heart Left-Highlight</dc:title>
+<dc:description>This is a normal valentines day heart.</dc:description>
+<dc:subject>
+<rdf:Bag>
+<rdf:li>holiday</rdf:li>
+<rdf:li>valentines</rdf:li>
+<rdf:li></rdf:li>
+<rdf:li>valentine</rdf:li>
+<rdf:li>hash(0x8a091c0)</rdf:li>
+<rdf:li>hash(0x8a0916c)</rdf:li>
+<rdf:li>signs_and_symbols</rdf:li>
+<rdf:li>hash(0x8a091f0)</rdf:li>
+<rdf:li>day</rdf:li>
+</rdf:Bag>
+</dc:subject>
+<dc:publisher>
+<cc:Agent rdf:about="http://www.openclipart.org">
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:publisher>
+<dc:creator>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:creator>
+<dc:rights>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:rights>
+<dc:date></dc:date>
+<dc:format>image/svg+xml</dc:format>
+<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+<dc:language>en</dc:language>
+</cc:Work>
+<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+</cc:License>
+</rdf:RDF>
+</metadata>
+<defs id="defs3"/>
+<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="549.40674" inkscape:cy="596.00159" inkscape:document-units="px" inkscape:guide-bbox="true" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="615" inkscape:window-width="866" inkscape:window-x="88" inkscape:window-y="116" inkscape:zoom="0.35000000" pagecolor="#ffffff" showguides="true"/>
+<g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1">
+<path d="M 263.41570,235.14588 C 197.17570,235.14588 143.41575,288.90587 143.41575,355.14588 C 143.41575,489.90139 279.34890,525.23318 371.97820,658.45392 C 459.55244,526.05056 600.54070,485.59932 600.54070,355.14588 C 600.54070,288.90588 546.78080,235.14587 480.54070,235.14588 C 432.49280,235.14588 391.13910,263.51631 371.97820,304.33338 C 352.81740,263.51630 311.46370,235.14587 263.41570,235.14588 z " id="path7" sodipodi:nodetypes="ccccccc" style="fill:#e60000;fill-opacity:1.0000000;stroke:#000000;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+<path d="M 265.00000,253.59375 C 207.04033,253.59375 160.00000,300.63407 160.00000,358.59375 C 160.00000,476.50415 278.91857,507.43251 359.96875,624.00000 C 366.52868,614.08205 220.00000,478.47309 220.00000,378.59375 C 220.00000,320.63407 267.04033,273.59375 325.00000,273.59375 C 325.50453,273.59375 325.99718,273.64912 326.50000,273.65625 C 309.22436,261.07286 288.00557,253.59374 265.00000,253.59375 z " id="path220" sodipodi:nodetypes="ccccccc" style="fill:#e6e6e6;fill-opacity:0.64556962;stroke:none;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+</g>
+</svg>
diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.cpp b/tests/auto/widgets/kernel/qapplication/modal/base.cpp
new file mode 100644
index 0000000000..2f7b4ad529
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/base.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "base.h"
+
+base::base(QWidget *parent) :
+ QWidget(parent)
+{
+ m_timer = new QTimer(this);
+ m_modalStarted = false;
+ m_timer->setSingleShot(false);
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(periodicTimer()));
+ m_timer->start(5000);
+}
+
+void base::periodicTimer()
+{
+ if(m_modalStarted)
+ exit(0);
+ m_modalDialog = new QDialog(this);
+ m_modalDialog->setModal(true);
+ m_modalDialog->show();
+ m_modalStarted = true;
+}
diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.h b/tests/auto/widgets/kernel/qapplication/modal/base.h
new file mode 100644
index 0000000000..e1f36e11bd
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/base.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BASE_H
+#define BASE_H
+
+#include <QWidget>
+#include <QTimer>
+#include <QDialog>
+
+class base : public QWidget
+{
+Q_OBJECT
+ QTimer *m_timer;
+ bool m_modalStarted;
+ QDialog *m_modalDialog;
+public:
+ explicit base(QWidget *parent = 0);
+
+signals:
+
+public slots:
+ void periodicTimer();
+};
+
+#endif // BASE_H
diff --git a/tests/auto/widgets/kernel/qapplication/modal/main.cpp b/tests/auto/widgets/kernel/qapplication/modal/main.cpp
new file mode 100644
index 0000000000..53c6008eb5
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include <QApplication>
+#include "base.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QApplication::setAttribute(Qt::AA_NativeWindows); //QTBUG-15774
+ base *b = new base();
+ Q_UNUSED(b);
+ return app.exec();
+}
diff --git a/tests/auto/widgets/kernel/qapplication/modal/modal.pro b/tests/auto/widgets/kernel/qapplication/modal/modal.pro
new file mode 100644
index 0000000000..9ed69769bb
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/modal.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+QT += widgets
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+SOURCES += main.cpp \
+ base.cpp
+DESTDIR = ./
+HEADERS += base.h
diff --git a/tests/auto/widgets/kernel/qapplication/qapplication.pro b/tests/auto/widgets/kernel/qapplication/qapplication.pro
new file mode 100644
index 0000000000..becc6c6f4b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/qapplication.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+SUBDIRS = test \
+ desktopsettingsaware \
+ modal \
+ wincmdline
+
+
diff --git a/tests/auto/widgets/kernel/qapplication/test/test.pro b/tests/auto/widgets/kernel/qapplication/test/test.pro
new file mode 100644
index 0000000000..65aae7b0b9
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/test/test.pro
@@ -0,0 +1,27 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += ../tst_qapplication.cpp
+TARGET = ../tst_qapplication
+
+wince* {
+ additional.files = ../desktopsettingsaware/desktopsettingsaware.exe
+ additional.path = desktopsettingsaware
+ someTest.files = test.pro
+ someTest.path = test
+ DEPLOYMENT += additional deploy someTest
+}
+
+win32 {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qapplication
+} else {
+ TARGET = ../../release/tst_qapplication
+ }
+}
+
+mac*:CONFIG+=insignificant_test
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/kernel/qapplication/tmp/README b/tests/auto/widgets/kernel/qapplication/tmp/README
new file mode 100644
index 0000000000..e758961ddf
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/tmp/README
@@ -0,0 +1,3 @@
+this dummy directory is needed for the QApplication::libraryPaths() autotest
+that calls QDir(applicationDirPath + "/tmp/..").canonicalPath(). canonicalPath()
+stat()'s the given directory, so if the tmp directory doesn't exist it fails...
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
new file mode 100644
index 0000000000..c37dfc609e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -0,0 +1,2107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+//#define QT_TST_QAPP_DEBUG
+#include <qdebug.h>
+
+#include <QtTest/QtTest>
+
+#include "qabstracteventdispatcher.h"
+#include <QtGui>
+#include <QtWidgets>
+
+#include "private/qapplication_p.h"
+#include "private/qstylesheetstyle_p.h"
+#ifdef Q_OS_WINCE
+#include <windows.h>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QApplication : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QApplication();
+ virtual ~tst_QApplication();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void sendEventsOnProcessEvents(); // this must be the first test
+ void getSetCheck();
+ void staticSetup();
+
+ void alert();
+
+ void multiple_data();
+ void multiple();
+
+ void nonGui();
+
+ void setFont_data();
+ void setFont();
+
+ void args_data();
+ void args();
+
+ void lastWindowClosed();
+ void quitOnLastWindowClosed();
+ void closeAllWindows();
+ void testDeleteLater();
+ void testDeleteLaterProcessEvents();
+
+ void libraryPaths();
+ void libraryPaths_qt_plugin_path();
+ void libraryPaths_qt_plugin_path_2();
+
+ void sendPostedEvents();
+
+ void thread();
+ void desktopSettingsAware();
+
+ void setActiveWindow();
+
+ void focusChanged();
+ void focusOut();
+
+ void execAfterExit();
+
+ void wheelScrollLines();
+
+ void task109149();
+
+ void style();
+
+ void allWidgets();
+ void topLevelWidgets();
+
+ void setAttribute();
+
+ void windowsCommandLine_data();
+ void windowsCommandLine();
+
+ void touchEventPropagation();
+
+ void qtbug_12673();
+
+ void globalStaticObjectDestruction(); // run this last
+};
+
+class EventSpy : public QObject
+{
+ Q_OBJECT
+
+public:
+ QList<int> recordedEvents;
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ recordedEvents.append(event->type());
+ return false;
+ }
+};
+
+void tst_QApplication::sendEventsOnProcessEvents()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ EventSpy spy;
+ app.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
+ QCoreApplication::processEvents();
+ QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : QInputContext() {}
+ QString identifierName() { return QString("NoName"); }
+ QString language() { return QString("NoLanguage"); }
+ void reset() {}
+ bool isComposing() const { return false; }
+};
+
+// Testing get/set functions
+void tst_QApplication::getSetCheck()
+{
+ int argc = 0;
+ QApplication obj1(argc, 0, QApplication::GuiServer);
+ MyInputContext *var1 = new MyInputContext;
+
+ // QApplication takes ownership, so check for reparenting:
+ obj1.setInputContext(var1);
+ QCOMPARE(var1->parent(), static_cast<QObject *>(&obj1));
+
+ // Test for self-assignment:
+ obj1.setInputContext(obj1.inputContext());
+ QVERIFY(obj1.inputContext());
+ QCOMPARE(static_cast<QInputContext *>(var1), obj1.inputContext());
+
+ // Resetting the input context to 0 is not allowed:
+ QTest::ignoreMessage(QtWarningMsg, "QApplication::setInputContext: called with 0 input context");
+ obj1.setInputContext(0);
+
+ QCOMPARE(static_cast<QInputContext *>(var1), obj1.inputContext());
+}
+
+class CloseEventTestWindow : public QWidget
+{
+public:
+ CloseEventTestWindow(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ }
+
+ void closeEvent(QCloseEvent *event)
+ {
+ QWidget dialog;
+ dialog.show();
+ dialog.close();
+
+ hide();
+ event->ignore();
+ }
+};
+
+static char *argv0;
+
+tst_QApplication::tst_QApplication()
+{
+#ifdef Q_OS_WINCE
+ // Clean up environment previously to launching test
+ qputenv("QT_PLUGIN_PATH", QByteArray());
+#endif
+}
+
+tst_QApplication::~tst_QApplication()
+{
+
+}
+
+void tst_QApplication::init()
+{
+// TODO: Add initialization code here.
+// This will be executed immediately before each test is run.
+}
+
+void tst_QApplication::cleanup()
+{
+// TODO: Add cleanup code here.
+// This will be executed immediately after each test is run.
+}
+
+void tst_QApplication::staticSetup()
+{
+ QVERIFY(!qApp);
+
+ QStyle *style = QStyleFactory::create(QLatin1String("Windows"));
+ QVERIFY(style);
+ QApplication::setStyle(style);
+
+ QPalette pal;
+ QApplication::setPalette(pal);
+
+ /*QFont font;
+ QApplication::setFont(font);*/
+
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+}
+
+
+// QApp subclass that exits the event loop after 150ms
+class TestApplication : public QApplication
+{
+public:
+ TestApplication( int &argc, char **argv )
+ : QApplication( argc, argv, QApplication::GuiServer )
+ {
+ startTimer( 150 );
+ }
+
+ void timerEvent( QTimerEvent * )
+ {
+ quit();
+ }
+};
+
+void tst_QApplication::alert()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ app.alert(0, 0);
+
+ QWidget widget;
+ QWidget widget2;
+ app.alert(&widget, 100);
+ widget.show();
+ widget2.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+ qt_x11_wait_for_window_manager(&widget2);
+#endif
+ QTest::qWait(100);
+ app.alert(&widget, -1);
+ app.alert(&widget, 250);
+ widget2.activateWindow();
+ QApplication::setActiveWindow(&widget2);
+ app.alert(&widget, 0);
+ widget.activateWindow();
+ QApplication::setActiveWindow(&widget);
+ app.alert(&widget, 200);
+ app.syncX();
+}
+
+void tst_QApplication::multiple_data()
+{
+ QTest::addColumn<QStringList>("features");
+
+ // return a list of things to try
+ QTest::newRow( "data0" ) << QStringList( "" );
+ QTest::newRow( "data1" ) << QStringList( "QFont" );
+ QTest::newRow( "data2" ) << QStringList( "QPixmap" );
+ QTest::newRow( "data3" ) << QStringList( "QWidget" );
+}
+
+void tst_QApplication::multiple()
+{
+ QFETCH(QStringList,features);
+
+ int i = 0;
+ int argc = 0;
+ while ( i++ < 5 ) {
+ TestApplication app( argc, 0 );
+
+ if ( features.contains( "QFont" ) ) {
+ // create font and force loading
+ QFont font( "Arial", 12 );
+ QFontInfo finfo( font );
+ finfo.exactMatch();
+ }
+ if ( features.contains( "QPixmap" ) ) {
+ QPixmap pix( 100, 100 );
+ pix.fill( Qt::black );
+ }
+ if ( features.contains( "QWidget" ) ) {
+ QWidget widget;
+ }
+
+ QVERIFY(!app.exec());
+ }
+}
+
+void tst_QApplication::nonGui()
+{
+#ifdef Q_OS_HPUX
+ // ### This is only to allow us to generate a test report for now.
+ QSKIP("This test shuts down the window manager on HP-UX.", SkipAll);
+#endif
+
+ int argc = 0;
+ QApplication app(argc, 0, false);
+ QCOMPARE(qApp, &app);
+}
+
+void tst_QApplication::setFont_data()
+{
+ QTest::addColumn<QString>("family");
+ QTest::addColumn<int>("pointsize");
+ QTest::addColumn<bool>("beforeAppConstructor");
+
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer); // Needed for QFontDatabase
+
+ int cnt = 0;
+ QFontDatabase fdb;
+ QStringList families = fdb.families();
+ for (QStringList::const_iterator itr = families.begin();
+ itr != families.end();
+ ++itr) {
+ if (cnt < 3) {
+ QString family = *itr;
+ QStringList styles = fdb.styles(family);
+ if (styles.size() > 0) {
+ QString style = styles.first();
+ QList<int> sizes = fdb.pointSizes(family, style);
+ if (!sizes.size())
+ sizes = fdb.standardSizes();
+ if (sizes.size() > 0) {
+ QTest::newRow(QString("data%1a").arg(cnt).toLatin1().constData())
+ << family
+ << sizes.first()
+ << false;
+ QTest::newRow(QString("data%1b").arg(cnt).toLatin1().constData())
+ << family
+ << sizes.first()
+ << true;
+ }
+ }
+ }
+ ++cnt;
+ }
+
+ QTest::newRow("nonexistingfont") << "nosuchfont_probably_quiteunlikely"
+ << 0 << false;
+ QTest::newRow("nonexistingfont") << "nosuchfont_probably_quiteunlikely"
+ << 0 << true;
+
+ QTest::newRow("largescaleable") << "smoothtimes" << 100 << false;
+ QTest::newRow("largescaleable") << "smoothtimes" << 100 << true;
+
+ QTest::newRow("largeunscaleale") << "helvetica" << 100 << false;
+ QTest::newRow("largeunscaleale") << "helvetica" << 100 << true;
+}
+
+void tst_QApplication::setFont()
+{
+ QFETCH( QString, family );
+ QFETCH( int, pointsize );
+ QFETCH( bool, beforeAppConstructor );
+
+ QFont font( family, pointsize );
+ if (beforeAppConstructor) {
+ QApplication::setFont( font );
+ QCOMPARE(QApplication::font(), font);
+ }
+
+ int argc = 0;
+ QApplication app( argc, 0, QApplication::GuiServer );
+ if (!beforeAppConstructor)
+ QApplication::setFont( font );
+
+ QCOMPARE( app.font(), font );
+}
+
+void tst_QApplication::args_data()
+{
+ QTest::addColumn<int>("argc_in");
+ QTest::addColumn<QString>("args_in");
+ QTest::addColumn<int>("argc_out");
+ QTest::addColumn<QString>("args_out");
+
+ QTest::newRow( "App name" ) << 1 << "/usr/bin/appname" << 1 << "/usr/bin/appname";
+ QTest::newRow( "No arguments" ) << 0 << QString() << 0 << QString();
+ QTest::newRow( "App name, style" ) << 3 << "/usr/bin/appname -style motif" << 1 << "/usr/bin/appname";
+ QTest::newRow( "App name, style, arbitrary, reverse" ) << 5 << "/usr/bin/appname -style motif -arbitrary -reverse"
+ << 2 << "/usr/bin/appname -arbitrary";
+}
+
+void tst_QApplication::task109149()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QApplication::setFont(QFont("helvetica", 100));
+
+ QWidget w;
+ w.setWindowTitle("hello");
+ w.show();
+
+ app.processEvents();
+}
+
+static char ** QString2cstrings( const QString &args )
+{
+ static QList<QByteArray> cache;
+
+ int i;
+ char **argarray = 0;
+ QStringList list = args.split(' ');;
+ argarray = new char*[list.count()+1];
+
+ for (i = 0; i < (int)list.count(); ++i ) {
+ QByteArray l1 = list[i].toLatin1();
+ argarray[i] = l1.data();
+ cache.append(l1);
+ }
+ argarray[i] = 0;
+
+ return argarray;
+}
+
+static QString cstrings2QString( char **args )
+{
+ QString string;
+ if ( !args )
+ return string;
+
+ int i = 0;
+ while ( args[i] ) {
+ string += args[i];
+ if ( args[i+1] )
+ string += " ";
+ ++i;
+ }
+ return string;
+}
+
+void tst_QApplication::args()
+{
+ QFETCH( int, argc_in );
+ QFETCH( QString, args_in );
+ QFETCH( int, argc_out );
+ QFETCH( QString, args_out );
+
+ char **argv = QString2cstrings( args_in );
+
+ QApplication app( argc_in, argv, QApplication::GuiServer );
+ QString argv_out = cstrings2QString(argv);
+
+ QCOMPARE( argc_in, argc_out );
+ QCOMPARE( argv_out, args_out );
+
+ delete [] argv;
+}
+
+class CloseWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ CloseWidget()
+ {
+ startTimer(500);
+ }
+
+protected:
+ void timerEvent(QTimerEvent *)
+ {
+ close();
+ }
+
+};
+
+void tst_QApplication::lastWindowClosed()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ QSignalSpy spy(&app, SIGNAL(lastWindowClosed()));
+
+ QPointer<QDialog> dialog = new QDialog;
+ QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
+ QTimer::singleShot(1000, dialog, SLOT(accept()));
+ dialog->exec();
+ QVERIFY(dialog);
+ QCOMPARE(spy.count(), 0);
+
+ QPointer<CloseWidget>widget = new CloseWidget;
+ QVERIFY(widget->testAttribute(Qt::WA_QuitOnClose));
+ QObject::connect(&app, SIGNAL(lastWindowClosed()), widget, SLOT(deleteLater()));
+ app.exec();
+ QVERIFY(!widget);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+
+#if 0
+ // everything is closed, so doing this should not emit lastWindowClosed() again
+ QMetaObject::invokeMethod(dialog, "close", Qt::QueuedConnection);
+ QTimer::singleShot(1000, &app, SLOT(quit()));
+ app.exec();
+ QCOMPARE(spy.count(), 0);
+#endif
+
+ delete dialog;
+
+ // show 3 windows, close them, should only get lastWindowClosed once
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ w1.show();
+ w2.show();
+ w3.show();
+
+ QTimer::singleShot(1000, &app, SLOT(closeAllWindows()));
+ app.exec();
+ QCOMPARE(spy.count(), 1);
+}
+
+class QuitOnLastWindowClosedDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QPushButton *okButton;
+
+ QuitOnLastWindowClosedDialog()
+ {
+ QHBoxLayout *hbox = new QHBoxLayout(this);
+ okButton = new QPushButton("&ok", this);
+
+ hbox->addWidget(okButton);
+ connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(okButton, SIGNAL(clicked()), this, SLOT(ok_clicked()));
+ }
+
+public slots:
+ void ok_clicked()
+ {
+ QDialog other;
+
+ QTimer timer;
+ connect(&timer, SIGNAL(timeout()), &other, SLOT(accept()));
+ QSignalSpy spy(&timer, SIGNAL(timeout()));
+ QSignalSpy appSpy(qApp, SIGNAL(lastWindowClosed()));
+
+ timer.start(1000);
+ other.exec();
+
+ // verify that the eventloop ran and let the timer fire
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(appSpy.count(), 1);
+ }
+};
+
+class QuitOnLastWindowClosedWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QuitOnLastWindowClosedWindow()
+ { }
+
+public slots:
+ void execDialogThenShow()
+ {
+ QDialog dialog;
+ QTimer timer1;
+ connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
+ QSignalSpy spy1(&timer1, SIGNAL(timeout()));
+ timer1.setSingleShot(true);
+ timer1.start(1000);
+ dialog.exec();
+ QCOMPARE(spy1.count(), 1);
+
+ show();
+ }
+};
+
+void tst_QApplication::quitOnLastWindowClosed()
+{
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ QuitOnLastWindowClosedDialog d;
+ d.show();
+ QTimer::singleShot(1000, d.okButton, SLOT(animateClick()));
+
+ QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
+ app.exec();
+
+ // lastWindowClosed() signal should only be sent after the last dialog is closed
+ QCOMPARE(appSpy.count(), 2);
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
+
+ QDialog dialog;
+ QTimer timer1;
+ connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
+ QSignalSpy spy1(&timer1, SIGNAL(timeout()));
+ timer1.setSingleShot(true);
+ timer1.start(1000);
+ dialog.exec();
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(appSpy.count(), 0);
+
+ QTimer timer2;
+ connect(&timer2, SIGNAL(timeout()), &app, SLOT(quit()));
+ QSignalSpy spy2(&timer2, SIGNAL(timeout()));
+ timer2.setSingleShot(true);
+ timer2.start(1000);
+ int returnValue = app.exec();
+ QCOMPARE(returnValue, 0);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(appSpy.count(), 0);
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QTimer timer;
+ timer.setInterval(100);
+
+ QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
+ QSignalSpy spy2(&timer, SIGNAL(timeout()));
+
+ QPointer<QMainWindow> mainWindow = new QMainWindow;
+ QPointer<QDialog> dialog = new QDialog(mainWindow);
+
+ QVERIFY(app.quitOnLastWindowClosed());
+ QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
+ QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
+
+ mainWindow->show();
+ dialog->show();
+
+ timer.start();
+ QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
+ QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
+
+ app.exec();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QTimer timer;
+ timer.setInterval(100);
+
+ QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
+ QSignalSpy spy2(&timer, SIGNAL(timeout()));
+
+ QPointer<CloseEventTestWindow> mainWindow = new CloseEventTestWindow;
+
+ QVERIFY(app.quitOnLastWindowClosed());
+ QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
+
+ mainWindow->show();
+
+ timer.start();
+ QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
+ QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
+
+ app.exec();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not caused the quit
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
+
+ // exec a dialog for 1 second, then show the window
+ QuitOnLastWindowClosedWindow window;
+ QTimer::singleShot(0, &window, SLOT(execDialogThenShow()));
+
+ QTimer timer;
+ QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
+ connect(&timer, SIGNAL(timeout()), &window, SLOT(close()));
+ timer.setSingleShot(true);
+ timer.start(2000);
+ int returnValue = app.exec();
+ QCOMPARE(returnValue, 0);
+ // failure here means the timer above didn't fire, and the
+ // quit was caused the the dialog being closed (not the window)
+ QCOMPARE(timerSpy.count(), 1);
+ QCOMPARE(appSpy.count(), 2);
+ }
+}
+
+class PromptOnCloseWidget : public QWidget
+{
+public:
+ void closeEvent(QCloseEvent *event)
+ {
+ QMessageBox *messageBox = new QMessageBox(this);
+ messageBox->setWindowTitle("Unsaved data");
+ messageBox->setText("Would you like to save or discard your current data?");
+ messageBox->setStandardButtons(QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel);
+ messageBox->setDefaultButton(QMessageBox::Save);
+
+ messageBox->show();
+ QTest::qWaitForWindowShown(messageBox);
+
+ // verify that all windows are visible
+ foreach (QWidget *w, qApp->topLevelWidgets())
+ QVERIFY(w->isVisible());
+ // flush event queue
+ qApp->processEvents();
+ // close all windows
+ qApp->closeAllWindows();
+
+ if (messageBox->standardButton(messageBox->clickedButton()) == QMessageBox::Cancel)
+ event->ignore();
+ else
+ event->accept();
+
+ delete messageBox;
+ }
+};
+
+void tst_QApplication::closeAllWindows()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ // create some windows
+ new QWidget;
+ new QWidget;
+ new QWidget;
+
+ // show all windows
+ foreach (QWidget *w, app.topLevelWidgets()) {
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ }
+ // verify that they are visible
+ foreach (QWidget *w, app.topLevelWidgets())
+ QVERIFY(w->isVisible());
+ // empty event queue
+ app.processEvents();
+ // close all windows
+ app.closeAllWindows();
+ // all windows should no longer be visible
+ foreach (QWidget *w, app.topLevelWidgets())
+ QVERIFY(!w->isVisible());
+
+ // add a window that prompts the user when closed
+ PromptOnCloseWidget *promptOnCloseWidget = new PromptOnCloseWidget;
+ // show all windows
+ foreach (QWidget *w, app.topLevelWidgets()) {
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ }
+ // close the last window to open the prompt (eventloop recurses)
+ promptOnCloseWidget->close();
+ // all windows should not be visible, except the one that opened the prompt
+ foreach (QWidget *w, app.topLevelWidgets()) {
+ if (w == promptOnCloseWidget)
+ QVERIFY(w->isVisible());
+ else
+ QVERIFY(!w->isVisible());
+ }
+
+ qDeleteAll(app.topLevelWidgets());
+}
+
+bool isPathListIncluded(const QStringList &l, const QStringList &r)
+{
+ int size = r.count();
+ if (size > l.count())
+ return false;
+#if defined (Q_OS_WIN)
+ Qt::CaseSensitivity cs = Qt::CaseInsensitive;
+#else
+ Qt::CaseSensitivity cs = Qt::CaseSensitive;
+#endif
+ int i = 0, j = 0;
+ for ( ; i < l.count() && j < r.count(); ++i) {
+ if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) {
+ ++j;
+ i = -1;
+ }
+ }
+ return j == r.count();
+}
+
+#define QT_TST_QAPP_DEBUG
+void tst_QApplication::libraryPaths()
+{
+ {
+#ifndef Q_OS_WINCE
+ QString testDir = QDir::current().canonicalPath() + "/test";
+#else
+ // On Windows CE we need QApplication object to have valid
+ // current Path. Therefore we need to identify it ourselves
+ // here for the test.
+ QFileInfo filePath;
+ wchar_t module_name[MAX_PATH];
+ GetModuleFileName(0, module_name, MAX_PATH);
+ filePath = QString::fromWCharArray(module_name);
+ QString testDir = filePath.path() + "/test";
+#endif
+ QApplication::setLibraryPaths(QStringList() << testDir);
+ QCOMPARE(QApplication::libraryPaths(), (QStringList() << testDir));
+
+ // creating QApplication adds the applicationDirPath to the libraryPath
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = QDir(app.applicationDirPath()).canonicalPath();
+
+ QStringList actual = QApplication::libraryPaths();
+ actual.sort();
+ QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
+ expected.sort();
+
+ QVERIFY2(isPathListIncluded(actual, expected),
+ qPrintable("actual:\n - " + actual.join("\n - ") +
+ "\nexpected:\n - " + expected.join("\n - ")));
+ }
+ {
+ // creating QApplication adds the applicationDirPath and plugin install path to the libraryPath
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = app.applicationDirPath();
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+
+ QStringList actual = QApplication::libraryPaths();
+ actual.sort();
+
+ QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
+ expected.sort();
+
+ QVERIFY2(isPathListIncluded(actual, expected),
+ qPrintable("actual:\n - " + actual.join("\n - ") +
+ "\nexpected:\n - " + expected.join("\n - ")));
+
+ // setting the library paths overrides everything
+ QString testDir = QDir::currentPath() + "/test";
+ QApplication::setLibraryPaths(QStringList() << testDir);
+ QVERIFY2(isPathListIncluded(QApplication::libraryPaths(), (QStringList() << testDir)),
+ qPrintable("actual:\n - " + QApplication::libraryPaths().join("\n - ") +
+ "\nexpected:\n - " + testDir));
+ }
+ {
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "Initial library path:" << QApplication::libraryPaths();
+#endif
+
+ int count = QApplication::libraryPaths().count();
+#if 0
+ // this test doesn't work if KDE 4 is installed
+ QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths()
+#endif
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ QApplication::addLibraryPath(installPathPlugins);
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "installPathPlugins" << installPathPlugins;
+ qDebug() << "After adding plugins path:" << QApplication::libraryPaths();
+#endif
+ QCOMPARE(QApplication::libraryPaths().count(), count);
+
+ QApplication::addLibraryPath(QDir::currentPath() + "/test");
+ QCOMPARE(QApplication::libraryPaths().count(), count + 1);
+
+ // creating QApplication adds the applicationDirPath to the libraryPath
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = app.applicationDirPath();
+ qDebug() << QApplication::libraryPaths();
+ // On Windows CE these are identical and might also be the case for other
+ // systems too
+ if (appDirPath != installPathPlugins)
+ QCOMPARE(QApplication::libraryPaths().count(), count + 2);
+ }
+ {
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "Initial library path:" << app.libraryPaths();
+#endif
+ int count = app.libraryPaths().count();
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ app.addLibraryPath(installPathPlugins);
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "installPathPlugins" << installPathPlugins;
+ qDebug() << "After adding plugins path:" << app.libraryPaths();
+#endif
+ QCOMPARE(app.libraryPaths().count(), count);
+
+ QString appDirPath = app.applicationDirPath();
+
+ app.addLibraryPath(appDirPath);
+#ifdef Q_OS_WINCE
+ app.addLibraryPath(appDirPath + "/../..");
+#else
+ app.addLibraryPath(appDirPath + "/..");
+#endif
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "appDirPath" << appDirPath;
+ qDebug() << "After adding appDirPath && appDirPath + /..:" << app.libraryPaths();
+#endif
+ QCOMPARE(app.libraryPaths().count(), count + 1);
+#ifdef Q_OS_MAC
+ app.addLibraryPath(appDirPath + "/../MacOS");
+#else
+ app.addLibraryPath(appDirPath + "/tmp/..");
+#endif
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "After adding appDirPath + /tmp/..:" << app.libraryPaths();
+#endif
+ QCOMPARE(app.libraryPaths().count(), count + 1);
+ }
+}
+
+void tst_QApplication::libraryPaths_qt_plugin_path()
+{
+ int argc = 1;
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = app.applicationDirPath();
+
+ // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
+ QString installPathPluginsDeCanon = appDirPath + QString::fromLatin1("/tmp/..");
+ QByteArray ascii = installPathPluginsDeCanon.toAscii();
+ qputenv("QT_PLUGIN_PATH", ascii);
+
+ QVERIFY(!app.libraryPaths().contains(appDirPath + QString::fromLatin1("/tmp/..")));
+}
+
+void tst_QApplication::libraryPaths_qt_plugin_path_2()
+{
+#ifdef Q_OS_UNIX
+ QByteArray validPath = QDir("/tmp").canonicalPath().toLatin1();
+ QByteArray nonExistentPath = "/nonexistent";
+ QByteArray pluginPath = validPath + ":" + nonExistentPath;
+#elif defined(Q_OS_WIN)
+# ifdef Q_OS_WINCE
+ QByteArray validPath = "/Temp";
+ QByteArray nonExistentPath = "/nonexistent";
+ QByteArray pluginPath = validPath + ";" + nonExistentPath;
+# else
+ QByteArray validPath = "C:\\windows";
+ QByteArray nonExistentPath = "Z:\\nonexistent";
+ QByteArray pluginPath = validPath + ";" + nonExistentPath;
+# endif
+#endif
+
+ {
+ // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
+ qputenv("QT_PLUGIN_PATH", pluginPath);
+
+ int argc = 1;
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // library path list should contain the default plus the one valid path
+ QStringList expected =
+ QStringList()
+ << QLibraryInfo::location(QLibraryInfo::PluginsPath)
+ << QDir(app.applicationDirPath()).canonicalPath()
+ << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath();
+# ifdef Q_OS_WINCE
+ expected = QSet<QString>::fromList(expected).toList();
+# endif
+ QVERIFY2(isPathListIncluded(app.libraryPaths(), expected),
+ qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") +
+ "\nexpected:\n - " + expected.join("\n - ")));
+ }
+
+ {
+ int argc = 1;
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // library paths are initialized by the QApplication, setting
+ // the environment variable here doesn't work
+ qputenv("QT_PLUGIN_PATH", pluginPath);
+
+ // library path list should contain the default
+ QStringList expected =
+ QStringList()
+ << QLibraryInfo::location(QLibraryInfo::PluginsPath)
+ << app.applicationDirPath();
+# ifdef Q_OS_WINCE
+ expected = QSet<QString>::fromList(expected).toList();
+# endif
+ QVERIFY(isPathListIncluded(app.libraryPaths(), expected));
+
+ qputenv("QT_PLUGIN_PATH", QByteArray());
+ }
+}
+
+class SendPostedEventsTester : public QObject
+{
+ Q_OBJECT
+public:
+ QList<int> eventSpy;
+ bool event(QEvent *e);
+private slots:
+ void doTest();
+};
+
+bool SendPostedEventsTester::event(QEvent *e)
+{
+ eventSpy.append(e->type());
+ return QObject::event(e);
+}
+
+void SendPostedEventsTester::doTest()
+{
+ QPointer<SendPostedEventsTester> p = this;
+ QApplication::postEvent(this, new QEvent(QEvent::User));
+ // DeferredDelete should not be delivered until returning from this function
+ QApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
+
+ QEventLoop eventLoop;
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p != 0);
+
+ QCOMPARE(eventSpy.count(), 2);
+ QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall));
+ QCOMPARE(eventSpy.at(1), int(QEvent::User));
+ eventSpy.clear();
+}
+
+void tst_QApplication::sendPostedEvents()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ SendPostedEventsTester *tester = new SendPostedEventsTester;
+ QMetaObject::invokeMethod(tester, "doTest", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
+ QPointer<SendPostedEventsTester> p = tester;
+ (void) app.exec();
+ QVERIFY(p == 0);
+}
+
+void tst_QApplication::thread()
+{
+ QThread *currentThread = QThread::currentThread();
+ // no app, but still have a valid thread
+ QVERIFY(currentThread != 0);
+
+ // the thread should be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // this should probably be in the tst_QObject::thread() test, but
+ // we put it here since we want to make sure that objects created
+ // *before* the QApplication has a thread
+ QObject object;
+ QObject child(&object);
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ // current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ // thread should be the same as before
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // app's thread should be the current thread
+ QCOMPARE(app.thread(), currentThread);
+
+ // the thread should still be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ QTestEventLoop::instance().enterLoop(1);
+ }
+
+ // app dead, current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // the thread should still be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // should still have a thread
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+
+ // do the test again, making sure that the thread is the same as
+ // before
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ // current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ // thread should be the same as before
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // app's thread should be the current thread
+ QCOMPARE(app.thread(), currentThread);
+
+ // the thread should be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // should still have a thread
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+
+ QTestEventLoop::instance().enterLoop(1);
+ }
+
+ // app dead, current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // the thread should still be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // should still have a thread
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+}
+
+class DeleteLaterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ DeleteLaterWidget(QApplication *_app, QWidget *parent = 0)
+ : QWidget(parent) { app = _app; child_deleted = false; }
+
+ bool child_deleted;
+ QApplication *app;
+
+public slots:
+ void runTest();
+ void checkDeleteLater();
+ void childDeleted() { child_deleted = true; }
+};
+
+
+void DeleteLaterWidget::runTest()
+{
+ QObject *stillAlive = qFindChild<QObject*>(this, "deleteLater");
+
+ QWidget *w = new QWidget(this);
+ connect(w, SIGNAL(destroyed()), this, SLOT(childDeleted()));
+
+ w->deleteLater();
+ QVERIFY(!child_deleted);
+
+ QDialog dlg;
+ QTimer::singleShot(500, &dlg, SLOT(reject()));
+ dlg.exec();
+
+ QVERIFY(!child_deleted);
+ app->processEvents();
+ QVERIFY(!child_deleted);
+
+ QTimer::singleShot(500, this, SLOT(checkDeleteLater()));
+
+ app->processEvents();
+
+ QVERIFY(!stillAlive); // verify at the end to make test terminate
+}
+
+void DeleteLaterWidget::checkDeleteLater()
+{
+ QVERIFY(child_deleted);
+
+ close();
+}
+
+void tst_QApplication::testDeleteLater()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
+
+ DeleteLaterWidget *wgt = new DeleteLaterWidget(&app);
+ QTimer::singleShot(500, wgt, SLOT(runTest()));
+
+ QObject *object = new QObject(wgt);
+ object->setObjectName("deleteLater");
+ object->deleteLater();
+
+ QObject *stillAlive = qFindChild<QObject*>(wgt, "deleteLater");
+ QVERIFY(stillAlive);
+
+ app.exec();
+
+ delete wgt;
+
+}
+
+class EventLoopNester : public QObject
+{
+ Q_OBJECT
+public slots:
+ void deleteLaterAndEnterLoop()
+ {
+ QEventLoop eventLoop;
+ QPointer<QObject> p(this);
+ deleteLater();
+ /*
+ DeferredDelete events are compressed, meaning this second
+ deleteLater() will *not* delete the object in the nested
+ event loop
+ */
+ QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
+ QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+ QVERIFY(p);
+ }
+ void deleteLaterAndExitLoop()
+ {
+ // Check that 'p' is not deleted before exec returns, since the call
+ // to QEventLoop::quit() should stop 'eventLoop' from processing
+ // any more events (that is, delete later) until we return to the
+ // _current_ event loop:
+ QEventLoop eventLoop;
+ QPointer<QObject> p(this);
+ QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p); // not dead yet
+ }
+
+ void processEventsOnly()
+ {
+ QApplication::processEvents();
+ }
+ void processEventsWithDeferredDeletion()
+ {
+ QApplication::processEvents(QEventLoop::DeferredDeletion);
+ }
+ void sendPostedEventsWithDeferredDelete()
+ {
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+ void deleteLaterAndProcessEvents1()
+ {
+ QEventLoop eventLoop;
+
+ QPointer<QObject> p = this;
+ deleteLater();
+
+ // trying to delete this object in a deeper eventloop just won't work
+ QMetaObject::invokeMethod(this,
+ "processEventsOnly",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "processEventsWithDeferredDeletion",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "sendPostedEventsWithDeferredDelete",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+
+ // trying to delete it from this eventloop still doesn't work
+ QApplication::processEvents();
+ QVERIFY(p);
+
+ // however, it *will* work with this magic incantation
+ QApplication::processEvents(QEventLoop::DeferredDeletion);
+ QVERIFY(!p);
+ }
+
+ void deleteLaterAndProcessEvents2()
+ {
+ QEventLoop eventLoop;
+
+ QPointer<QObject> p = this;
+ deleteLater();
+
+ // trying to delete this object in a deeper eventloop just won't work
+ QMetaObject::invokeMethod(this,
+ "processEventsOnly",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "processEventsWithDeferredDeletion",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "sendPostedEventsWithDeferredDelete",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+
+ // trying to delete it from this eventloop still doesn't work
+ QApplication::processEvents();
+ QVERIFY(p);
+
+ // however, it *will* work with this magic incantation
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!p);
+ }
+};
+
+void tst_QApplication::testDeleteLaterProcessEvents()
+{
+ int argc = 0;
+
+ // Calling processEvents() with no event dispatcher does nothing.
+ QObject *object = new QObject;
+ QPointer<QObject> p(object);
+ object->deleteLater();
+ QApplication::processEvents();
+ QVERIFY(p);
+ delete object;
+
+ {
+ QApplication app(argc, 0, QApplication::GuiServer);
+ // If you call processEvents() with an event dispatcher present, but
+ // outside any event loops, deferred deletes are not processed unless
+ // QEventLoop::DeferredDeletion is passed.
+ object = new QObject;
+ p = object;
+ object->deleteLater();
+ app.processEvents();
+ QVERIFY(p);
+ app.processEvents(QEventLoop::ProcessEventsFlag(0x10)); // 0x10 == QEventLoop::DeferredDeletion
+ QVERIFY(!p);
+
+ // sendPostedEvents(0, DeferredDelete); also works
+ object = new QObject;
+ p = object;
+ object->deleteLater();
+ app.processEvents();
+ QVERIFY(p);
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!p);
+
+ // If you call deleteLater() on an object when there is no parent
+ // event loop, and then enter an event loop, the object will get
+ // deleted.
+ object = new QObject;
+ p = object;
+ object->deleteLater();
+ QEventLoop loop;
+ QTimer::singleShot(1000, &loop, SLOT(quit()));
+ loop.exec();
+ QVERIFY(!p);
+ }
+ {
+ // When an object is in an event loop, then calls deleteLater() and enters
+ // an event loop recursively, it should not die until the parent event
+ // loop continues.
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester;
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndEnterLoop()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+
+ {
+ // When the event loop that calls deleteLater() is exited
+ // immediately, the object should die when returning to the
+ // parent event loop
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester;
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndExitLoop()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+
+ {
+ // when the event loop that calls deleteLater() also calls
+ // processEvents() immediately afterwards, the object should
+ // not die until the parent loop continues
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester();
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents1()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+
+ {
+ // when the event loop that calls deleteLater() also calls
+ // processEvents() immediately afterwards, the object should
+ // not die until the parent loop continues
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester();
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents2()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+}
+
+/*
+ Test for crash with QApplication::setDesktopSettingsAware(false).
+*/
+void tst_QApplication::desktopSettingsAware()
+{
+#ifndef QT_NO_PROCESS
+ QProcess testProcess;
+#ifdef Q_OS_WINCE
+ int argc = 0;
+ QApplication tmpApp(argc, 0, QApplication::GuiServer);
+ testProcess.start("desktopsettingsaware/desktopsettingsaware");
+#else
+#if defined(Q_OS_WIN) && defined(QT_DEBUG)
+ testProcess.start("desktopsettingsaware/debug/desktopsettingsaware");
+#elif defined(Q_OS_WIN)
+ testProcess.start("desktopsettingsaware/release/desktopsettingsaware");
+#else
+ testProcess.start("desktopsettingsaware/desktopsettingsaware");
+#endif
+#endif
+ QVERIFY(testProcess.waitForFinished(10000));
+ QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning));
+ QVERIFY(int(testProcess.error()) != int(QProcess::Crashed));
+#endif
+}
+
+void tst_QApplication::setActiveWindow()
+{
+ int argc = 0;
+ QApplication MyApp(argc, 0, QApplication::GuiServer);
+
+ QWidget* w = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout(w);
+
+ QLineEdit* pb1 = new QLineEdit("Testbutton1", w);
+ QLineEdit* pb2 = new QLineEdit("Test Line Edit", w);
+
+ layout->addWidget(pb1);
+ layout->addWidget(pb2);
+
+ pb2->setFocus();
+ pb2->setParent(0);
+ delete pb2;
+
+ w->show();
+ QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse)
+ QVERIFY(pb1->hasFocus());
+ delete w;
+}
+
+
+/* This might fail on some X11 window managers? */
+void tst_QApplication::focusChanged()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ QSignalSpy spy(&app, SIGNAL(focusChanged(QWidget *, QWidget *)));
+ QWidget *now = 0;
+ QWidget *old = 0;
+
+ QWidget parent1;
+ QHBoxLayout hbox1(&parent1);
+ QLabel lb1(&parent1);
+ QLineEdit le1(&parent1);
+ QPushButton pb1(&parent1);
+ hbox1.addWidget(&lb1);
+ hbox1.addWidget(&le1);
+ hbox1.addWidget(&pb1);
+
+ QCOMPARE(spy.count(), 0);
+
+ parent1.show();
+ QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).count(), 2);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == 0);
+ spy.clear();
+ QCOMPARE(spy.count(), 0);
+
+ pb1.setFocus();
+ QCOMPARE(spy.count(), 1);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le1);
+ spy.clear();
+
+ lb1.setFocus();
+ QCOMPARE(spy.count(), 1);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &lb1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb1);
+ spy.clear();
+
+ lb1.clearFocus();
+ QCOMPARE(spy.count(), 1);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &lb1);
+ spy.clear();
+
+ QWidget parent2;
+ QHBoxLayout hbox2(&parent2);
+ QLabel lb2(&parent2);
+ QLineEdit le2(&parent2);
+ QPushButton pb2(&parent2);
+ hbox2.addWidget(&lb2);
+ hbox2.addWidget(&le2);
+ hbox2.addWidget(&pb2);
+
+ parent2.show();
+ QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse)
+ QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows
+ old = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(0));
+ now = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == 0);
+ spy.clear();
+
+ QTestKeyEvent tab(QTest::Press, Qt::Key_Tab, 0, 0);
+ QTestKeyEvent backtab(QTest::Press, Qt::Key_Backtab, 0, 0);
+ QTestMouseEvent click(QTest::MouseClick, Qt::LeftButton, 0, QPoint(5, 5), 0);
+
+ bool tabAllControls = true;
+#ifdef Q_WS_MAC
+ // Mac has two modes, one where you tab to everything, one where you can
+ // only tab to input controls, here's what we get. Determine which ones we
+ // should get.
+ QSettings appleSettings(QLatin1String("apple.com"));
+ QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
+ tabAllControls = (appleValue.toInt() & 0x2);
+#endif
+
+ tab.simulate(now);
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+ }
+
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ tab.simulate(now);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb2);
+ spy.clear();
+ }
+
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ backtab.simulate(now);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+ }
+
+
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ old = &pb2;
+ } else {
+ backtab.simulate(now);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb2);
+ spy.clear();
+ }
+
+ click.simulate(old);
+ if (!(pb2.focusPolicy() & Qt::ClickFocus)) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+
+ click.simulate(old);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb2);
+ spy.clear();
+ }
+
+ parent1.activateWindow();
+ QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
+ QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows
+
+ //on windows, the change of focus is made in 2 steps
+ //(the focusChanged SIGNAL is emitted twice)
+ if (spy.count()==1)
+ old = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(0));
+ else
+ old = qVariantValue<QWidget*>(spy.at(spy.count()-2).at(0));
+ now = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(1));
+ QVERIFY(now == &le1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+}
+
+class LineEdit : public QLineEdit
+{
+public:
+ LineEdit(QWidget *parent = 0) : QLineEdit(parent) { }
+
+protected:
+ void focusOutEvent(QFocusEvent *e) {
+ QLineEdit::focusOutEvent(e);
+ if (objectName() == "le1")
+ setStyleSheet("");
+ }
+
+ void focusInEvent(QFocusEvent *e) {
+ QLineEdit::focusInEvent(e);
+ if (objectName() == "le2")
+ setStyleSheet("");
+ }
+};
+
+void tst_QApplication::focusOut()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // Tests the case where the style pointer changes when on focus in/out
+ // (the above is the case when the stylesheet changes)
+ QWidget w;
+ QLineEdit *le1 = new LineEdit(&w);
+ le1->setObjectName("le1");
+ le1->setStyleSheet("background: #fee");
+ le1->setFocus();
+
+ QLineEdit *le2 = new LineEdit(&w);
+ le2->setObjectName("le2");
+ le2->setStyleSheet("background: #fee");
+ le2->move(100, 100);
+ w.show();
+
+ QTest::qWait(2000);
+ le2->setFocus();
+ QTest::qWait(2000);
+}
+
+void tst_QApplication::execAfterExit()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
+ // this should be ignored, as exec() will reset the exitCode
+ QApplication::exit(1);
+ int exitCode = app.exec();
+ QCOMPARE(exitCode, 0);
+
+ // the quitNow flag should have been reset, so we can spin an
+ // eventloop after QApplication::exec() returns
+ QEventLoop eventLoop;
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ exitCode = eventLoop.exec();
+ QCOMPARE(exitCode, 0);
+}
+
+void tst_QApplication::wheelScrollLines()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ // If wheelScrollLines returns 0, the mose wheel will be disabled.
+ QVERIFY(app.wheelScrollLines() > 0);
+}
+
+void tst_QApplication::style()
+{
+ int argc = 1;
+
+ {
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QPointer<QStyle> style = app.style();
+ app.setStyle(new QWindowsStyle);
+ QVERIFY(style.isNull());
+ }
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // qApp style can never be 0
+ QVERIFY(QApplication::style() != 0);
+}
+
+void tst_QApplication::allWidgets()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QWidget *w = new QWidget;
+ QVERIFY(app.allWidgets().contains(w)); // uncreate widget test
+ QVERIFY(app.allWidgets().contains(w)); // created widget test
+ delete w;
+ w = 0;
+ QVERIFY(!app.allWidgets().contains(w)); // removal test
+}
+
+void tst_QApplication::topLevelWidgets()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QWidget *w = new QWidget;
+ w->show();
+#ifndef QT_NO_CLIPBOARD
+ QClipboard *clipboard = QApplication::clipboard();
+ QString originalText = clipboard->text();
+ clipboard->setText(QString("newText"));
+#endif
+ app.processEvents();
+ QVERIFY(QApplication::topLevelWidgets().contains(w));
+ QCOMPARE(QApplication::topLevelWidgets().count(), 1);
+ delete w;
+ w = 0;
+ app.processEvents();
+ QCOMPARE(QApplication::topLevelWidgets().count(), 0);
+}
+
+
+
+void tst_QApplication::setAttribute()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
+ QWidget *w = new QWidget;
+ QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
+ delete w;
+
+ QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation);
+ QVERIFY(QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
+ w = new QWidget;
+ QVERIFY(w->testAttribute(Qt::WA_WState_Created));
+ QWidget *w2 = new QWidget(w);
+ w2->setParent(0);
+ QVERIFY(w2->testAttribute(Qt::WA_WState_Created));
+ delete w;
+ delete w2;
+
+ QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation, false);
+ QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
+ w = new QWidget;
+ QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
+ delete w;
+}
+
+void tst_QApplication::windowsCommandLine_data()
+{
+#if defined(Q_OS_WIN)
+ QTest::addColumn<QString>("args");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("hello world")
+ << QString("Hello \"World\"")
+ << QString("Hello \"World\"");
+ QTest::newRow("sql")
+ << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME")
+ << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME");
+#endif
+}
+
+void tst_QApplication::windowsCommandLine()
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QFETCH(QString, args);
+ QFETCH(QString, expected);
+
+ QProcess testProcess;
+#if defined(QT_DEBUG)
+ testProcess.start("wincmdline/debug/wincmdline", QStringList(args));
+#else
+ testProcess.start("wincmdline/release/wincmdline", QStringList(args));
+#endif
+ QVERIFY(testProcess.waitForFinished(10000));
+ QByteArray error = testProcess.readAllStandardError();
+ QString procError(error);
+ QCOMPARE(procError, expected);
+#endif
+}
+
+class TouchEventPropagationTestWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent;
+
+ TouchEventPropagationTestWidget(QWidget *parent = 0)
+ : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false)
+ { }
+
+ void reset()
+ {
+ seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false;
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ // qDebug() << objectName() << "seenMouseEvent = true";
+ seenMouseEvent = true;
+ event->setAccepted(acceptMouseEvent);
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ // qDebug() << objectName() << "seenTouchEvent = true";
+ seenTouchEvent = true;
+ event->setAccepted(acceptTouchEvent);
+ break;
+ default:
+ return QWidget::event(event);
+ }
+ return true;
+ }
+};
+
+void tst_QApplication::touchEventPropagation()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ QList<QTouchEvent::TouchPoint> pressedTouchPoints;
+ QTouchEvent::TouchPoint press(0);
+ press.setState(Qt::TouchPointPressed);
+ pressedTouchPoints << press;
+
+ QList<QTouchEvent::TouchPoint> releasedTouchPoints;
+ QTouchEvent::TouchPoint release(0);
+ release.setState(Qt::TouchPointReleased);
+ releasedTouchPoints << release;
+
+ {
+ // touch event behavior on a window
+ TouchEventPropagationTestWidget window;
+ window.setObjectName("1. window");
+
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ window.setAttribute(Qt::WA_AcceptTouchEvents);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ window.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+ }
+
+ {
+ // touch event behavior on a window with a child widget
+ TouchEventPropagationTestWidget window;
+ window.setObjectName("2. window");
+ TouchEventPropagationTestWidget widget(&window);
+ widget.setObjectName("2. widget");
+
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.setAttribute(Qt::WA_AcceptTouchEvents);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptMouseEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.setAttribute(Qt::WA_AcceptTouchEvents, false);
+ window.setAttribute(Qt::WA_AcceptTouchEvents);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ window.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptMouseEvent = true; // doesn't matter, touch events are propagated first
+ window.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+ }
+}
+
+void tst_QApplication::qtbug_12673()
+{
+ QProcess testProcess;
+ QStringList arguments;
+#ifdef Q_OS_MAC
+ testProcess.start("modal/modal.app", arguments);
+#else
+ testProcess.start("modal/modal", arguments);
+#endif
+ QVERIFY(testProcess.waitForFinished(20000));
+ QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
+}
+
+/*
+ This test is meant to ensure that certain objects (public & commonly used)
+ can safely be used in a Q_GLOBAL_STATIC such that their destructors are
+ executed *after* the destruction of QApplication.
+ */
+Q_GLOBAL_STATIC(QLocale, tst_qapp_locale);
+Q_GLOBAL_STATIC(QProcess, tst_qapp_process);
+Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher);
+Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory);
+Q_GLOBAL_STATIC(QElapsedTimer, tst_qapp_elapsedTimer);
+Q_GLOBAL_STATIC(QMutex, tst_qapp_mutex);
+Q_GLOBAL_STATIC(QWidget, tst_qapp_widget);
+Q_GLOBAL_STATIC(QPixmap, tst_qapp_pixmap);
+Q_GLOBAL_STATIC(QFont, tst_qapp_font);
+Q_GLOBAL_STATIC(QRegion, tst_qapp_region);
+Q_GLOBAL_STATIC(QFontDatabase, tst_qapp_fontDatabase);
+Q_GLOBAL_STATIC(QCursor, tst_qapp_cursor);
+
+void tst_QApplication::globalStaticObjectDestruction()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QVERIFY(tst_qapp_locale());
+ QVERIFY(tst_qapp_process());
+ QVERIFY(tst_qapp_fileSystemWatcher());
+ QVERIFY(tst_qapp_sharedMemory());
+ QVERIFY(tst_qapp_elapsedTimer());
+ QVERIFY(tst_qapp_mutex());
+ QVERIFY(tst_qapp_widget());
+ QVERIFY(tst_qapp_pixmap());
+ QVERIFY(tst_qapp_font());
+ QVERIFY(tst_qapp_region());
+ QVERIFY(tst_qapp_fontDatabase());
+ QVERIFY(tst_qapp_cursor());
+}
+
+//QTEST_APPLESS_MAIN(tst_QApplication)
+int main(int argc, char *argv[])
+{
+ tst_QApplication tc;
+ argv0 = argv[0];
+ return QTest::qExec(&tc, argc, argv);
+}
+
+#include "tst_qapplication.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp b/tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp
new file mode 100644
index 0000000000..d0f802231a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QApplication>
+#include <stdio.h>
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ if (argc > 1)
+ fprintf(stderr, "%s", argv[1]);
+ else
+ fprintf(stderr, "Failed");
+ fflush(stderr);
+ return 0;
+}
+
diff --git a/tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro b/tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro
new file mode 100644
index 0000000000..3ba8f48167
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += widgets
+SOURCES += main.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qboxlayout/.gitignore b/tests/auto/widgets/kernel/qboxlayout/.gitignore
new file mode 100644
index 0000000000..034edba563
--- /dev/null
+++ b/tests/auto/widgets/kernel/qboxlayout/.gitignore
@@ -0,0 +1 @@
+tst_qboxlayout
diff --git a/tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro b/tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro
new file mode 100644
index 0000000000..c37f12f74f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qboxlayout.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
new file mode 100644
index 0000000000..4e5b357de5
--- /dev/null
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QBoxLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QBoxLayout();
+ virtual ~tst_QBoxLayout();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void insertSpacerItem();
+ void sizeHint();
+ void sizeConstraints();
+ void setGeometry();
+ void setStyleShouldChangeSpacing();
+
+ void taskQTBUG_7103_minMaxWidthNotRespected();
+};
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+};
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ break;
+ case PM_LayoutTopMargin:
+ return 3;
+ break;
+ case PM_LayoutRightMargin:
+ return 6;
+ break;
+ case PM_LayoutBottomMargin:
+ return 9;
+ break;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+
+tst_QBoxLayout::tst_QBoxLayout()
+{
+}
+
+tst_QBoxLayout::~tst_QBoxLayout()
+{
+}
+
+void tst_QBoxLayout::initTestCase()
+{
+}
+
+void tst_QBoxLayout::cleanupTestCase()
+{
+}
+
+void tst_QBoxLayout::init()
+{
+}
+
+void tst_QBoxLayout::cleanup()
+{
+}
+
+void tst_QBoxLayout::insertSpacerItem()
+{
+ QWidget *window = new QWidget;
+
+ QSpacerItem *spacer1 = new QSpacerItem(20, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QSpacerItem *spacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ QBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(new QLineEdit("Foooooooooooooooooooooooooo"));
+ layout->addSpacerItem(spacer1);
+ layout->addWidget(new QLineEdit("Baaaaaaaaaaaaaaaaaaaaaaaaar"));
+ layout->insertSpacerItem(0, spacer2);
+ window->setLayout(layout);
+
+ QVERIFY(layout->itemAt(0) == spacer2);
+ QVERIFY(layout->itemAt(2) == spacer1);
+
+ window->show();
+}
+
+void tst_QBoxLayout::sizeHint()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay1 = new QHBoxLayout;
+ QHBoxLayout *lay2 = new QHBoxLayout;
+ QLabel *label = new QLabel("widget twooooooooooooooooooooooooooooooooooooooooooooooooooooooo");
+ lay2->addWidget(label);
+ lay1->addLayout(lay2);
+ window->setLayout(lay1);
+ window->show();
+ label->setText("foooooooo baaaaaaar");
+ QSize sh = lay1->sizeHint();
+ QApplication::processEvents();
+ // Note that this is not strictly required behaviour - actually
+ // the preferred behaviour would be that sizeHint returns
+ // the same value regardless of what's lying in the event queue.
+ // (i.e. we would check for equality here instead)
+ QVERIFY(lay1->sizeHint() != sh);
+}
+
+void tst_QBoxLayout::sizeConstraints()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay = new QHBoxLayout;
+ lay->addWidget(new QLabel("foooooooooooooooooooooooooooooooooooo"));
+ lay->addWidget(new QLabel("baaaaaaaaaaaaaaaaaaaaaaaaaaaaaar"));
+ lay->setSizeConstraint(QLayout::SetFixedSize);
+ window->setLayout(lay);
+ window->show();
+ QApplication::processEvents();
+ QSize sh = window->sizeHint();
+ lay->takeAt(1);
+ QVERIFY(sh.width() >= window->sizeHint().width() &&
+ sh.height() >= window->sizeHint().height());
+
+}
+
+void tst_QBoxLayout::setGeometry()
+{
+ QWidget toplevel;
+ QWidget w(&toplevel);
+ QVBoxLayout *lay = new QVBoxLayout;
+ lay->setMargin(0);
+ lay->setSpacing(0);
+ QHBoxLayout *lay2 = new QHBoxLayout;
+ QDial *dial = new QDial;
+ lay2->addWidget(dial);
+ lay2->setAlignment(Qt::AlignTop);
+ lay2->setAlignment(Qt::AlignRight);
+ lay->addLayout(lay2);
+ w.setLayout(lay);
+ toplevel.show();
+
+ QRect newGeom(0, 0, 70, 70);
+ lay2->setGeometry(newGeom);
+ QVERIFY2(newGeom.contains(dial->geometry()), "dial->geometry() should be smaller and within newGeom");
+}
+
+void tst_QBoxLayout::setStyleShouldChangeSpacing()
+{
+
+ QWidget *window = new QWidget;
+ QHBoxLayout *hbox = new QHBoxLayout(window);
+ QPushButton *pb1 = new QPushButton(tr("The spacing between this"));
+ QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget"));;
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ pb2->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ hbox->addWidget(pb1);
+ hbox->addWidget(pb2);
+ CustomLayoutStyle *style1 = new CustomLayoutStyle;
+ style1->hspacing = 6;
+ window->setStyle(style1);
+ window->show();
+
+ QTest::qWait(100);
+ int spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
+ QCOMPARE(spacing, 6);
+
+ CustomLayoutStyle *style2 = new CustomLayoutStyle();
+ style2->hspacing = 10;
+ window->setStyle(style2);
+ QTest::qWait(100);
+ spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
+ QCOMPARE(spacing, 10);
+
+ delete window;
+ delete style1;
+ delete style2;
+}
+
+void tst_QBoxLayout::taskQTBUG_7103_minMaxWidthNotRespected()
+{
+ QLabel *label = new QLabel("Qt uses standard C++, but makes extensive use of the C pre-processor to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on all major platforms, and has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support and a unified cross-platform API for file handling.");
+ label->setWordWrap(true);
+ label->setFixedWidth(200);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(label);
+ layout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding));
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ int height = label->height();
+
+ QRect g = widget.geometry();
+ g.setWidth(600);
+ widget.setGeometry(g);
+
+ QTest::qWait(50);
+
+ QCOMPARE(label->height(), height);
+}
+
+QTEST_MAIN(tst_QBoxLayout)
+#include "tst_qboxlayout.moc"
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/.gitignore b/tests/auto/widgets/kernel/qdesktopwidget/.gitignore
new file mode 100644
index 0000000000..d6f7cc7ca9
--- /dev/null
+++ b/tests/auto/widgets/kernel/qdesktopwidget/.gitignore
@@ -0,0 +1 @@
+tst_qdesktopwidget
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro b/tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro
new file mode 100644
index 0000000000..730b273c4f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdesktopwidget.cpp
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp b/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
new file mode 100644
index 0000000000..e7e3abeb25
--- /dev/null
+++ b/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtWidgets/QDesktopWidget>
+#include <QDebug>
+
+//TESTED_CLASS=
+
+class tst_QDesktopWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QDesktopWidget();
+ virtual ~tst_QDesktopWidget();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void numScreens();
+ void primaryScreen();
+ void screenNumberForQWidget();
+ void screenNumberForQPoint();
+ void availableGeometry();
+ void screenGeometry();
+};
+
+tst_QDesktopWidget::tst_QDesktopWidget()
+{
+}
+
+tst_QDesktopWidget::~tst_QDesktopWidget()
+{
+}
+
+void tst_QDesktopWidget::init()
+{
+}
+
+void tst_QDesktopWidget::cleanup()
+{
+}
+
+void tst_QDesktopWidget::numScreens()
+{
+ QDesktopWidget desktop;
+ QVERIFY(desktop.numScreens() > 0);
+}
+
+void tst_QDesktopWidget::primaryScreen()
+{
+ QDesktopWidget desktop;
+ QVERIFY(desktop.primaryScreen() >= 0);
+ QVERIFY(desktop.primaryScreen() < desktop.numScreens());
+}
+
+void tst_QDesktopWidget::availableGeometry()
+{
+ QDesktopWidget desktop;
+ QTest::ignoreMessage(QtWarningMsg, "QDesktopWidget::availableGeometry(): Attempt "
+ "to get the available geometry of a null widget");
+ desktop.availableGeometry((QWidget *)0);
+
+ QRect total;
+ QRect available;
+
+ for (int i = 0; i < desktop.screenCount(); ++i) {
+ total = desktop.screenGeometry(i);
+ available = desktop.availableGeometry(i);
+ QVERIFY(total.contains(available));
+ }
+
+ total = desktop.screenGeometry();
+ available = desktop.availableGeometry();
+ QVERIFY(total.contains(available));
+ QCOMPARE(desktop.availableGeometry(desktop.primaryScreen()), available);
+ QCOMPARE(desktop.screenGeometry(desktop.primaryScreen()), total);
+}
+
+void tst_QDesktopWidget::screenNumberForQWidget()
+{
+ QDesktopWidget desktop;
+
+ QCOMPARE(desktop.screenNumber(0), 0);
+
+ QWidget widget;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QVERIFY(widget.isVisible());
+
+ int widgetScreen = desktop.screenNumber(&widget);
+ QVERIFY(widgetScreen > -1);
+ QVERIFY(widgetScreen < desktop.numScreens());
+}
+
+void tst_QDesktopWidget::screenNumberForQPoint()
+{
+ // make sure QDesktopWidget::screenNumber(QPoint) returns the correct screen
+ QDesktopWidget *desktopWidget = QApplication::desktop();
+ QRect allScreens;
+ for (int i = 0; i < desktopWidget->numScreens(); ++i) {
+ QRect screenGeometry = desktopWidget->screenGeometry(i);
+ QCOMPARE(desktopWidget->screenNumber(screenGeometry.center()), i);
+ allScreens |= screenGeometry;
+ }
+
+ // make sure QDesktopWidget::screenNumber(QPoint) returns a valid screen for points that aren't on any screen
+ int screen;
+ screen = desktopWidget->screenNumber(allScreens.topLeft() - QPoint(1, 1));
+
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "Task 151710", Abort);
+#endif
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+ screen = desktopWidget->screenNumber(allScreens.topRight() + QPoint(1, 1));
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+ screen = desktopWidget->screenNumber(allScreens.bottomLeft() - QPoint(1, 1));
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+ screen = desktopWidget->screenNumber(allScreens.bottomRight() + QPoint(1, 1));
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+}
+
+void tst_QDesktopWidget::screenGeometry()
+{
+ QDesktopWidget *desktopWidget = QApplication::desktop();
+ QTest::ignoreMessage(QtWarningMsg, "QDesktopWidget::screenGeometry(): Attempt "
+ "to get the screen geometry of a null widget");
+ QRect r = desktopWidget->screenGeometry((QWidget *)0);
+ QVERIFY(r.isNull());
+ QWidget widget;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ r = desktopWidget->screenGeometry(&widget);
+
+ QRect total;
+ QRect available;
+ for (int i = 0; i < desktopWidget->screenCount(); ++i) {
+ total = desktopWidget->screenGeometry(i);
+ available = desktopWidget->availableGeometry(i);
+ }
+}
+
+QTEST_MAIN(tst_QDesktopWidget)
+#include "tst_qdesktopwidget.moc"
+
diff --git a/tests/auto/widgets/kernel/qformlayout/.gitignore b/tests/auto/widgets/kernel/qformlayout/.gitignore
new file mode 100644
index 0000000000..24e93d561f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qformlayout/.gitignore
@@ -0,0 +1 @@
+tst_qformlayout
diff --git a/tests/auto/widgets/kernel/qformlayout/qformlayout.pro b/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
new file mode 100644
index 0000000000..24c452af9f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qformlayout.cpp
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
new file mode 100644
index 0000000000..4425205eb9
--- /dev/null
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -0,0 +1,913 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qwindowsstyle.h>
+#include <qsizepolicy.h>
+
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QPlastiqueStyle>
+#include <QtWidgets/QWindowsStyle>
+#include <QStyleFactory>
+
+#include <qformlayout.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFormLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QFormLayout();
+ ~tst_QFormLayout();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void rowCount();
+ void buddies();
+ void getItemPosition();
+ void wrapping();
+ void spacing();
+ void contentsRect();
+
+ void setFormStyle();
+ void setFieldGrowthPolicy();
+ void setRowWrapPolicy();
+ void setLabelAlignment();
+ void setFormAlignment();
+
+/*
+ void setHorizontalSpacing(int spacing);
+ int horizontalSpacing() const;
+ void setVerticalSpacing(int spacing);
+ int verticalSpacing() const;
+*/
+
+ void addRow();
+ void insertRow_QWidget_QWidget();
+ void insertRow_QWidget_QLayout();
+ void insertRow_QString_QWidget();
+ void insertRow_QString_QLayout();
+ void insertRow_QWidget();
+ void insertRow_QLayout();
+ void setWidget();
+ void setLayout();
+
+/*
+ QLayoutItem *itemAt(int row, ItemRole role) const;
+ void getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const;
+ void getLayoutPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const;
+ void getItemPosition(QLayoutItem *item, int *rowPtr, ItemRole *rolePtr) const;
+ QWidget *labelForField(QWidget *widget) const;
+ QWidget *labelForField(QLayoutItem *item) const;
+
+ void addItem(QLayoutItem *item);
+*/
+
+ void itemAt();
+ void takeAt();
+ void layoutAlone();
+/*
+ void setGeometry(const QRect &rect);
+ QSize minimumSize() const;
+ QSize sizeHint() const;
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int width) const;
+ Qt::Orientations expandingDirections() const;
+*/
+
+};
+
+tst_QFormLayout::tst_QFormLayout()
+{
+}
+
+tst_QFormLayout::~tst_QFormLayout()
+{
+}
+
+void tst_QFormLayout::initTestCase()
+{
+}
+
+void tst_QFormLayout::cleanupTestCase()
+{
+}
+
+void tst_QFormLayout::init()
+{
+}
+
+void tst_QFormLayout::cleanup()
+{
+}
+
+void tst_QFormLayout::rowCount()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+
+ fl->addRow(tr("Label 1"), new QLineEdit);
+ fl->addRow(tr("Label 2"), new QLineEdit);
+ fl->addRow(tr("Label 3"), new QLineEdit);
+ QCOMPARE(fl->rowCount(), 3);
+
+ fl->addRow(new QWidget);
+ fl->addRow(new QHBoxLayout);
+ QCOMPARE(fl->rowCount(), 5);
+
+ fl->insertRow(1, tr("Label 0.5"), new QLineEdit);
+ QCOMPARE(fl->rowCount(), 6);
+
+ //TODO: remove items
+
+ delete w;
+}
+
+void tst_QFormLayout::buddies()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+
+ //normal buddy case
+ QLineEdit *le = new QLineEdit;
+ fl->addRow(tr("Label 1"), le);
+ QLabel *label = qobject_cast<QLabel *>(fl->labelForField(le));
+ QVERIFY(label);
+ QWidget *lew = le;
+ QCOMPARE(label->buddy(), lew);
+
+ //null label
+ QLineEdit *le2 = new QLineEdit;
+ fl->addRow(0, le2);
+ QWidget *label2 = fl->labelForField(le2);
+ QVERIFY(label2 == 0);
+
+ //no label
+ QLineEdit *le3 = new QLineEdit;
+ fl->addRow(le3);
+ QWidget *label3 = fl->labelForField(le3);
+ QVERIFY(label3 == 0);
+
+ //TODO: empty label?
+
+ delete w;
+}
+
+void tst_QFormLayout::getItemPosition()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+
+ QList<QLabel*> labels;
+ QList<QLineEdit*> fields;
+ for (int i = 0; i < 5; ++i) {
+ labels.append(new QLabel(QString("Label %1").arg(i+1)));
+ fields.append(new QLineEdit);
+ fl->addRow(labels[i], fields[i]);
+ }
+
+ //a field
+ {
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getWidgetPosition(fields[3], &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(role, QFormLayout::FieldRole);
+ }
+
+ //a label
+ {
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getWidgetPosition(labels[2], &row, &role);
+ QCOMPARE(row, 2);
+ QCOMPARE(role, QFormLayout::LabelRole);
+ }
+
+ //a layout that's been inserted
+ {
+ QVBoxLayout *vbl = new QVBoxLayout;
+ fl->insertRow(2, "Label 1.5", vbl);
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getLayoutPosition(vbl, &row, &role);
+ QCOMPARE(row, 2);
+ QCOMPARE(role, QFormLayout::FieldRole);
+ }
+
+ delete w;
+}
+
+void tst_QFormLayout::wrapping()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+ fl->setRowWrapPolicy(QFormLayout::WrapLongRows);
+
+ QLineEdit *le = new QLineEdit;
+ QLabel *lbl = new QLabel("A long label");
+ le->setMinimumWidth(200);
+ fl->addRow(lbl, le);
+
+ w->setFixedWidth(240);
+ w->show();
+
+ QCOMPARE(le->geometry().y() > lbl->geometry().y(), true);
+
+ //TODO: additional tests covering different wrapping cases
+
+ delete w;
+}
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+};
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+void tst_QFormLayout::spacing()
+{
+ //TODO: confirm spacing behavior
+ QWidget *w = new QWidget;
+ CustomLayoutStyle *style = new CustomLayoutStyle;
+ style->hspacing = 5;
+ style->vspacing = 10;
+ w->setStyle(style);
+ QFormLayout *fl = new QFormLayout(w);
+ QCOMPARE(style->hspacing, fl->horizontalSpacing());
+ QCOMPARE(style->vspacing, fl->verticalSpacing());
+
+ //QCOMPARE(fl->spacing(), -1);
+ fl->setVerticalSpacing(5);
+ QCOMPARE(5, fl->horizontalSpacing());
+ QCOMPARE(5, fl->verticalSpacing());
+ //QCOMPARE(fl->spacing(), 5);
+ fl->setVerticalSpacing(-1);
+ QCOMPARE(style->hspacing, fl->horizontalSpacing());
+ QCOMPARE(style->vspacing, fl->verticalSpacing());
+
+ style->hspacing = 5;
+ style->vspacing = 5;
+ //QCOMPARE(fl->spacing(), 5);
+
+ fl->setHorizontalSpacing(20);
+ //QCOMPARE(fl->spacing(), -1);
+ style->vspacing = 20;
+ QCOMPARE(fl->horizontalSpacing(), 20);
+ QCOMPARE(fl->verticalSpacing(), 20);
+ //QCOMPARE(fl->spacing(), 20);
+ fl->setHorizontalSpacing(-1);
+ //QCOMPARE(fl->spacing(), -1);
+ style->hspacing = 20;
+ //QCOMPARE(fl->spacing(), 20);
+
+ delete w;
+ delete style;
+}
+
+void tst_QFormLayout::contentsRect()
+{
+ QWidget w;
+ QFormLayout form;
+ w.setLayout(&form);
+ form.addRow("Label", new QPushButton(&w));
+ w.show();
+/*#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&w); // wait for the show
+#endif*/
+ int l, t, r, b;
+ form.getContentsMargins(&l, &t, &r, &b);
+ QRect geom = form.geometry();
+
+ QCOMPARE(geom.adjusted(+l, +t, -r, -b), form.contentsRect());
+}
+
+
+class DummyMacStyle : public QCommonStyle
+{
+public:
+ virtual int styleHint ( StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0 ) const
+ {
+ switch(hint) {
+ case SH_FormLayoutFormAlignment:
+ return Qt::AlignHCenter | Qt::AlignTop;
+ case SH_FormLayoutLabelAlignment:
+ return Qt::AlignRight;
+ case SH_FormLayoutWrapPolicy:
+ return QFormLayout::DontWrapRows;
+ case SH_FormLayoutFieldGrowthPolicy:
+ return QFormLayout::FieldsStayAtSizeHint;
+ default:
+ return QCommonStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+class DummyQtopiaStyle : public QCommonStyle
+{
+public:
+ virtual int styleHint ( StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0 ) const
+ {
+ switch(hint) {
+ case SH_FormLayoutFormAlignment:
+ return Qt::AlignLeft | Qt::AlignTop;
+ case SH_FormLayoutLabelAlignment:
+ return Qt::AlignRight;
+ case SH_FormLayoutWrapPolicy:
+ return QFormLayout::WrapLongRows;
+ case SH_FormLayoutFieldGrowthPolicy:
+ return QFormLayout::AllNonFixedFieldsGrow;
+ default:
+ return QCommonStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+void tst_QFormLayout::setFormStyle()
+{
+ QWidget widget;
+ QFormLayout layout;
+ widget.setLayout(&layout);
+
+#ifndef QT_NO_STYLE_PLASTIQUE
+ widget.setStyle(new QPlastiqueStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignRight);
+ QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::ExpandingFieldsGrow);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::DontWrapRows);
+#endif
+
+ widget.setStyle(new QWindowsStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignLeft);
+ QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::AllNonFixedFieldsGrow);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::DontWrapRows);
+
+ /* can't directly create mac style or qtopia style, since
+ this test is cross platform.. so create dummy styles that
+ return all the right stylehints.
+ */
+ widget.setStyle(new DummyMacStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignRight);
+ QVERIFY(layout.formAlignment() == (Qt::AlignHCenter | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::FieldsStayAtSizeHint);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::DontWrapRows);
+
+ widget.setStyle(new DummyQtopiaStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignRight);
+ QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::AllNonFixedFieldsGrow);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::WrapLongRows);
+}
+
+void tst_QFormLayout::setFieldGrowthPolicy()
+{
+ QWidget window;
+ QLineEdit fld1, fld2, fld3;
+ fld1.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ fld2.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ fld3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ QFormLayout layout;
+ layout.addRow("One:", &fld1);
+ layout.addRow("Two:", &fld2);
+ layout.addRow("Three:", &fld3);
+ window.setLayout(&layout);
+ window.resize(1000, 200);
+
+ for (int i = 0; i < 3; ++i) {
+ layout.setFieldGrowthPolicy(i == 0 ? QFormLayout::FieldsStayAtSizeHint :
+ i == 1 ? QFormLayout::ExpandingFieldsGrow :
+ QFormLayout::AllNonFixedFieldsGrow);
+ layout.activate();
+
+ if (i == 0) {
+ QVERIFY(fld1.width() == fld2.width());
+ QVERIFY(fld2.width() == fld3.width());
+ } else if (i == 1) {
+ QVERIFY(fld1.width() == fld2.width());
+ QVERIFY(fld2.width() < fld3.width());
+ } else {
+ QVERIFY(fld1.width() < fld2.width());
+ QVERIFY(fld2.width() == fld3.width());
+ }
+ }
+}
+
+void tst_QFormLayout::setRowWrapPolicy()
+{
+}
+
+void tst_QFormLayout::setLabelAlignment()
+{
+}
+
+void tst_QFormLayout::setFormAlignment()
+{
+}
+
+void tst_QFormLayout::addRow()
+{
+ QFormLayout layout;
+ QWidget w1, w2, w3;
+ QHBoxLayout l1, l2, l3;
+ QLabel lbl1, lbl2;
+
+ QCOMPARE(layout.rowCount(), 0);
+
+ layout.addRow(&lbl1, &w1);
+ layout.addRow(&lbl2, &l1);
+ layout.addRow("Foo:", &w2);
+ layout.addRow("Bar:", &l2);
+ layout.addRow(&w3);
+ layout.addRow(&l3);
+
+ QCOMPARE(layout.rowCount(), 6);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+ QVERIFY(layout.itemAt(2, QFormLayout::LabelRole)->widget()->property("text") == "Foo:");
+ QVERIFY(layout.itemAt(3, QFormLayout::LabelRole)->widget()->property("text") == "Bar:");
+ QVERIFY(layout.itemAt(4, QFormLayout::LabelRole) == 0);
+ QVERIFY(layout.itemAt(5, QFormLayout::LabelRole) == 0);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::FieldRole)->widget() == &w1);
+ QVERIFY(layout.itemAt(1, QFormLayout::FieldRole)->layout() == &l1);
+ QVERIFY(layout.itemAt(2, QFormLayout::FieldRole)->widget() == &w2);
+ QVERIFY(layout.itemAt(3, QFormLayout::FieldRole)->layout() == &l2);
+// ### should have a third role, FullRowRole?
+// QVERIFY(layout.itemAt(4, QFormLayout::FieldRole) == 0);
+// QVERIFY(layout.itemAt(5, QFormLayout::FieldRole) == 0);
+}
+
+void tst_QFormLayout::insertRow_QWidget_QWidget()
+{
+ QFormLayout layout;
+ QLabel lbl1, lbl2, lbl3, lbl4;
+ QLineEdit fld1, fld2, fld3, fld4;
+
+ layout.insertRow(0, &lbl1, &fld1);
+ QCOMPARE(layout.rowCount(), 1);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&lbl1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&fld1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ // check that negative values append
+ layout.insertRow(-2, &lbl2, &fld2);
+ QCOMPARE(layout.rowCount(), 2);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+
+ // check that too large values append
+ layout.insertRow(100, &lbl3, &fld3);
+ QCOMPARE(layout.rowCount(), 3);
+ QCOMPARE(layout.count(), 6);
+
+ layout.insertRow(3, (QWidget *)0, (QWidget *)0);
+ QCOMPARE(layout.rowCount(), 4);
+ QCOMPARE(layout.count(), 6);
+
+ layout.insertRow(4, (QWidget *)0, &fld4);
+ QCOMPARE(layout.rowCount(), 5);
+ QCOMPARE(layout.count(), 7);
+
+ layout.insertRow(5, &lbl4, (QWidget *)0);
+ QCOMPARE(layout.rowCount(), 6);
+ QCOMPARE(layout.count(), 8);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+ QVERIFY(layout.itemAt(2, QFormLayout::LabelRole)->widget() == &lbl3);
+ QVERIFY(layout.itemAt(3, QFormLayout::LabelRole) == 0);
+ QVERIFY(layout.itemAt(4, QFormLayout::LabelRole) == 0);
+ QVERIFY(layout.itemAt(5, QFormLayout::LabelRole)->widget() == &lbl4);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::FieldRole)->widget() == &fld1);
+ QVERIFY(layout.itemAt(1, QFormLayout::FieldRole)->widget() == &fld2);
+ QVERIFY(layout.itemAt(2, QFormLayout::FieldRole)->widget() == &fld3);
+ QVERIFY(layout.itemAt(3, QFormLayout::FieldRole) == 0);
+ QVERIFY(layout.itemAt(4, QFormLayout::FieldRole)->widget() == &fld4);
+ QVERIFY(layout.itemAt(5, QFormLayout::FieldRole) == 0);
+}
+
+void tst_QFormLayout::insertRow_QWidget_QLayout()
+{
+ QFormLayout layout;
+ QLabel lbl1, lbl2, lbl3, lbl4;
+ QHBoxLayout fld1, fld2, fld3, fld4;
+
+ layout.insertRow(0, &lbl1, &fld1);
+ QCOMPARE(layout.rowCount(), 1);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&lbl1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&fld1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ // check that negative values append
+ layout.insertRow(-2, &lbl2, &fld2);
+ QCOMPARE(layout.rowCount(), 2);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+
+ // check that too large values append
+ layout.insertRow(100, &lbl3, &fld3);
+ QCOMPARE(layout.rowCount(), 3);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+ QVERIFY(layout.itemAt(2, QFormLayout::LabelRole)->widget() == &lbl3);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::FieldRole)->layout() == &fld1);
+ QVERIFY(layout.itemAt(1, QFormLayout::FieldRole)->layout() == &fld2);
+ QVERIFY(layout.itemAt(2, QFormLayout::FieldRole)->layout() == &fld3);
+}
+
+void tst_QFormLayout::insertRow_QString_QWidget()
+{
+ QFormLayout layout;
+ QLineEdit fld1, fld2, fld3;
+
+ layout.insertRow(-5, "&Name:", &fld1);
+ QLabel *label1 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label1 != 0);
+ QVERIFY(label1->buddy() == &fld1);
+
+ layout.insertRow(0, "&Email:", &fld2);
+ QLabel *label2 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label2 != 0);
+ QVERIFY(label2->buddy() == &fld2);
+
+ layout.insertRow(5, "&Age:", &fld3);
+ QLabel *label3 = qobject_cast<QLabel *>(layout.itemAt(2, QFormLayout::LabelRole)->widget());
+ QVERIFY(label3 != 0);
+ QVERIFY(label3->buddy() == &fld3);
+}
+
+void tst_QFormLayout::insertRow_QString_QLayout()
+{
+ QFormLayout layout;
+ QHBoxLayout fld1, fld2, fld3;
+
+ layout.insertRow(-5, "&Name:", &fld1);
+ QLabel *label1 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label1 != 0);
+ QVERIFY(label1->buddy() == 0);
+
+ QCOMPARE(layout.rowCount(), 1);
+
+ layout.insertRow(0, "&Email:", &fld2);
+ QLabel *label2 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label2 != 0);
+ QVERIFY(label2->buddy() == 0);
+
+ QCOMPARE(layout.rowCount(), 2);
+
+ layout.insertRow(5, "&Age:", &fld3);
+ QLabel *label3 = qobject_cast<QLabel *>(layout.itemAt(2, QFormLayout::LabelRole)->widget());
+ QVERIFY(label3 != 0);
+ QVERIFY(label3->buddy() == 0);
+
+ QCOMPARE(layout.rowCount(), 3);
+}
+
+void tst_QFormLayout::insertRow_QWidget()
+{
+ // ### come back to this later
+}
+
+void tst_QFormLayout::insertRow_QLayout()
+{
+ // ### come back to this later
+}
+
+void tst_QFormLayout::setWidget()
+{
+ QFormLayout layout;
+
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ QWidget w4;
+
+ QCOMPARE(layout.count(), 0);
+ QCOMPARE(layout.rowCount(), 0);
+
+ layout.setWidget(5, QFormLayout::LabelRole, &w1);
+ QCOMPARE(layout.count(), 1);
+ QCOMPARE(layout.rowCount(), 6);
+
+ layout.setWidget(3, QFormLayout::FieldRole, &w2);
+ layout.setWidget(3, QFormLayout::LabelRole, &w3);
+ QCOMPARE(layout.count(), 3);
+ QCOMPARE(layout.rowCount(), 6);
+
+ // should be ignored and generate warnings
+ layout.setWidget(3, QFormLayout::FieldRole, &w4);
+ layout.setWidget(-1, QFormLayout::FieldRole, &w4);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w1, &row, &role);
+ QCOMPARE(row, 5);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w2, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w3, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w4, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(0, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+}
+
+void tst_QFormLayout::setLayout()
+{
+ QFormLayout layout;
+
+ QHBoxLayout l1;
+ QHBoxLayout l2;
+ QHBoxLayout l3;
+ QHBoxLayout l4;
+
+ QCOMPARE(layout.count(), 0);
+ QCOMPARE(layout.rowCount(), 0);
+
+ layout.setLayout(5, QFormLayout::LabelRole, &l1);
+ QCOMPARE(layout.count(), 1);
+ QCOMPARE(layout.rowCount(), 6);
+
+ layout.setLayout(3, QFormLayout::FieldRole, &l2);
+ layout.setLayout(3, QFormLayout::LabelRole, &l3);
+ QCOMPARE(layout.count(), 3);
+ QCOMPARE(layout.rowCount(), 6);
+
+ // should be ignored and generate warnings
+ layout.setLayout(3, QFormLayout::FieldRole, &l4);
+ layout.setLayout(-1, QFormLayout::FieldRole, &l4);
+ QCOMPARE(layout.count(), 3);
+ QCOMPARE(layout.rowCount(), 6);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l1, &row, &role);
+ QCOMPARE(row, 5);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l2, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l3, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l4, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(0, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+}
+
+void tst_QFormLayout::itemAt()
+{
+ QFormLayout layout;
+
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ QWidget w4;
+ QWidget w5;
+ QHBoxLayout l6;
+
+ layout.setWidget(5, QFormLayout::LabelRole, &w1);
+ layout.setWidget(3, QFormLayout::FieldRole, &w2);
+ layout.setWidget(3, QFormLayout::LabelRole, &w3);
+ layout.addRow(&w4, &w5);
+ layout.addRow("Foo:", &l6);
+
+ QCOMPARE(layout.count(), 7);
+
+ QBitArray scoreBoard(7);
+ for (int i = 0; i < 7; ++i) {
+ QLayoutItem *item = layout.itemAt(i);
+ QVERIFY(item != 0);
+
+ if (item->widget() == &w1) {
+ scoreBoard[0] = true;
+ } else if (item->widget() == &w2) {
+ scoreBoard[1] = true;
+ } else if (item->widget() == &w3) {
+ scoreBoard[2] = true;
+ } else if (item->widget() == &w4) {
+ scoreBoard[3] = true;
+ } else if (item->widget() == &w5) {
+ scoreBoard[4] = true;
+ } else if (item->layout() == &l6) {
+ scoreBoard[5] = true;
+ } else if (qobject_cast<QLabel *>(item->widget())) {
+ scoreBoard[6] = true;
+ }
+ }
+ QCOMPARE(scoreBoard.count(false), 0);
+}
+
+void tst_QFormLayout::takeAt()
+{
+ QFormLayout layout;
+
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ QWidget w4;
+ QWidget w5;
+ QHBoxLayout l6;
+
+ layout.setWidget(5, QFormLayout::LabelRole, &w1);
+ layout.setWidget(3, QFormLayout::FieldRole, &w2);
+ layout.setWidget(3, QFormLayout::LabelRole, &w3);
+ layout.addRow(&w4, &w5);
+ layout.addRow("Foo:", &l6);
+
+ QCOMPARE(layout.count(), 7);
+
+ for (int i = 6; i >= 0; --i) {
+ layout.takeAt(0);
+ QCOMPARE(layout.count(), i);
+ }
+}
+
+void tst_QFormLayout::layoutAlone()
+{
+ QWidget w;
+ QFormLayout layout;
+ layout.setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+ w.setLayout(&layout);
+ QLabel label("Here is a strange test case");
+ layout.setWidget(0, QFormLayout::LabelRole, &label);
+ QHBoxLayout hlay;
+ layout.setLayout(1, QFormLayout::LabelRole, &hlay);
+ QCOMPARE(layout.count(), 2);
+ w.show();
+ layout.activate();
+ QTest::qWait(500);
+}
+
+QTEST_MAIN(tst_QFormLayout)
+
+#include "tst_qformlayout.moc"
diff --git a/tests/auto/widgets/kernel/qgridlayout/.gitignore b/tests/auto/widgets/kernel/qgridlayout/.gitignore
new file mode 100644
index 0000000000..bce8f2f91e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/.gitignore
@@ -0,0 +1 @@
+tst_qgridlayout
diff --git a/tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro b/tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro
new file mode 100644
index 0000000000..6bd42fe432
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgridlayout.cpp
+FORMS += sortdialog.ui
+
+
+
diff --git a/tests/auto/widgets/kernel/qgridlayout/sortdialog.ui b/tests/auto/widgets/kernel/qgridlayout/sortdialog.ui
new file mode 100644
index 0000000000..04af84d01b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/sortdialog.ui
@@ -0,0 +1,135 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>SortDialog</class>
+ <widget class="QDialog" name="SortDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>304</width>
+ <height>370</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Sort</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="0" column="1" >
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="okButton" >
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moreButton" >
+ <property name="text" >
+ <string>&amp;More</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="primaryGroupBox" >
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QComboBox" name="primaryColumnCombo" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <item>
+ <property name="text" >
+ <string>None</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <tabstops>
+ <tabstop>primaryColumnCombo</tabstop>
+ <tabstop>okButton</tabstop>
+ <tabstop>moreButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>okButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SortDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>257</x>
+ <y>25</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>283</x>
+ <y>268</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
new file mode 100644
index 0000000000..100b7eb892
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
@@ -0,0 +1,1646 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qwindowsstyle.h>
+#include <qsizepolicy.h>
+//#include <QtGui>
+
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QRadioButton>
+#include <QtWidgets/QWindowsStyle>
+#include <QStyleFactory>
+
+#include "../../../platformquirks.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/kernel/qlayout.cpp gui/kernel/qlayout.h
+
+
+class tst_QGridLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QGridLayout();
+ virtual ~tst_QGridLayout();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getItemPosition();
+ void itemAtPosition();
+ void badDistributionBug();
+ void setMinAndMaxSize();
+ void spacingAndSpacers();
+
+ void spacingsAndMargins();
+ void spacingsAndMargins_data();
+ void minMaxSize_data();
+ void minMaxSize();
+
+ void styleDependentSpacingsAndMargins_data();
+ void styleDependentSpacingsAndMargins();
+ void layoutSpacingImplementation_data();
+ void layoutSpacingImplementation();
+ void spacing();
+ void spacerWithSpacing();
+ void contentsRect();
+ void distributeMultiCell();
+
+private:
+ QWidget *testWidget;
+ QGridLayout *testLayout;
+ QWidget *w1;
+ QWidget *w2;
+ QWidget *w3;
+ QSpacerItem *sp;
+
+ QGridLayout *m_grid;
+ QWidget *m_toplevel;
+};
+
+
+tst_QGridLayout::tst_QGridLayout()
+{
+ m_grid = 0;
+ m_toplevel = 0;
+}
+
+tst_QGridLayout::~tst_QGridLayout()
+{
+ delete m_toplevel;
+}
+
+void tst_QGridLayout::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+ // Create the test class
+ testWidget = new QWidget(0);
+
+ testLayout = new QGridLayout(testWidget);
+
+ w1 = new QWidget(testWidget);
+ w1->setPalette(QPalette(Qt::red));
+ testLayout->addWidget(w1, 0, 0);
+
+ w2 = new QWidget(testWidget);
+ testLayout->addWidget(w2, 1, 1, 2, 2);
+ w2->setPalette(QPalette(Qt::green));
+
+ w3 = new QWidget(testWidget);
+ testLayout->addWidget(w3, 0, 1, 1, 2);
+ w3->setPalette(QPalette(Qt::blue));
+
+ sp = new QSpacerItem(4, 4);
+ testLayout->addItem(sp, 1, 3, 2, 1);
+
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+}
+
+void tst_QGridLayout::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QGridLayout::init()
+{
+}
+
+void tst_QGridLayout::cleanup()
+{
+}
+
+void tst_QGridLayout::getItemPosition()
+{
+ QLayoutItem *item;
+ int counter = 0;
+
+ bool seenW1 = false;
+ bool seenW2 = false;
+ bool seenW3 = false;
+ bool seenSpacer = false;
+
+ while ((item = testLayout->itemAt(counter))) {
+ QWidget *w = item->widget();
+ int r,c,rs,cs;
+ testLayout->getItemPosition(counter, &r, &c, &rs, &cs);
+
+// qDebug() << "item" << counter << "has" <<r << c << rs << cs;
+
+ if (w == w1) {
+ QVERIFY(!seenW1);
+ seenW1 = true;
+ QCOMPARE(r, 0);
+ QCOMPARE(c, 0);
+ QCOMPARE(rs, 1);
+ QCOMPARE(cs, 1);
+ } else if (w == w2) {
+ QVERIFY(!seenW2);
+ seenW2 = true;
+ QCOMPARE(r, 1);
+ QCOMPARE(c, 1);
+ QCOMPARE(rs, 2);
+ QCOMPARE(cs, 2);
+ } else if (w == w3) {
+ QVERIFY(!seenW3);
+ seenW3 = true;
+ QCOMPARE(r, 0);
+ QCOMPARE(c, 1);
+ QCOMPARE(rs, 1);
+ QCOMPARE(cs, 2);
+ } else {
+ QVERIFY(!w);
+ QVERIFY(!seenSpacer);
+ seenSpacer = true;
+ QCOMPARE(r, 1);
+ QCOMPARE(c, 3);
+ QCOMPARE(rs, 2);
+ QCOMPARE(cs, 1);
+ }
+ ++counter;
+ }
+ QCOMPARE(counter, 4);
+ QVERIFY(seenW1);
+ QVERIFY(seenW2);
+ QVERIFY(seenW3);
+ QVERIFY(seenSpacer);
+}
+
+void tst_QGridLayout::itemAtPosition()
+{
+ void *table[4][5] = {
+ { w1, w3, w3, 0, 0 },
+ { 0, w2, w2, sp, 0 },
+ { 0, w2, w2, sp, 0 },
+ { 0, 0, 0, 0, 0 }
+ };
+
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 5; ++col) {
+ QLayoutItem *item = testLayout->itemAtPosition(row, col);
+ QVERIFY(item == table[row][col]
+ || (item && item->widget() == table[row][col]));
+ }
+ }
+}
+
+#include "ui_sortdialog.h"
+
+void tst_QGridLayout::badDistributionBug()
+{
+ QDialog dialog;
+ Ui::SortDialog ui;
+ ui.setupUi(&dialog);
+ ui.gridLayout->setMargin(0);
+ ui.gridLayout->setSpacing(0);
+ ui.vboxLayout->setMargin(0);
+ ui.vboxLayout->setSpacing(0);
+ ui.okButton->setFixedHeight(20);
+ ui.moreButton->setFixedHeight(20);
+ ui.primaryGroupBox->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ ui.primaryGroupBox->setFixedHeight(200);
+
+ QSize minSize = dialog.layout()->minimumSize();
+ QCOMPARE(minSize.height(), 200);
+}
+
+void tst_QGridLayout::setMinAndMaxSize()
+{
+ QWidget widget;
+ QGridLayout layout(&widget);
+ layout.setMargin(0);
+ layout.setSpacing(0);
+ layout.setSizeConstraint(QLayout::SetMinAndMaxSize);
+ widget.show();
+
+ QWidget leftChild;
+ leftChild.setPalette(QPalette(Qt::red));
+ leftChild.setMinimumSize(100, 100);
+ leftChild.setMaximumSize(200, 200);
+ layout.addWidget(&leftChild, 0, 0);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ QWidget rightChild;
+ rightChild.setPalette(QPalette(Qt::green));
+ rightChild.setMinimumSize(100, 100);
+ rightChild.setMaximumSize(200, 200);
+ layout.addWidget(&rightChild, 0, 2);
+ QApplication::sendPostedEvents(0, 0);
+
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth());
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth());
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+ static const int colMin = 100;
+ layout.setColumnMinimumWidth(1, colMin);
+ QCOMPARE(layout.columnMinimumWidth(1), colMin);
+
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + colMin);
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth() + colMin);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+
+ layout.setColumnStretch(1,1);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + colMin);
+ QCOMPARE(widget.maximumWidth(), QLAYOUTSIZE_MAX);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+
+ layout.setColumnStretch(1,0);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + colMin);
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth() + colMin);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+
+ layout.setColumnMinimumWidth(1, 0);
+
+ static const int spacerS = 250;
+ QSpacerItem *spacer = new QSpacerItem(spacerS, spacerS);
+ layout.addItem(spacer, 0, 1);
+ QApplication::sendPostedEvents(0, 0);
+
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + spacerS);
+ QCOMPARE(widget.maximumWidth(), QLAYOUTSIZE_MAX);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(qMax(leftChild.minimumHeight(), rightChild.minimumHeight()), spacerS));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+ spacer->changeSize(spacerS, spacerS, QSizePolicy::Fixed, QSizePolicy::Minimum);
+ layout.invalidate();
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + spacerS);
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth() + spacerS);
+
+
+ layout.removeItem(spacer);
+
+ rightChild.hide();
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ rightChild.show();
+ layout.removeWidget(&rightChild);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ QWidget bottomChild(&widget);
+ bottomChild.setPalette(QPalette(Qt::green));
+ bottomChild.setMinimumSize(100, 100);
+ bottomChild.setMaximumSize(200, 200);
+ layout.addWidget(&bottomChild, 1, 0);
+ QApplication::sendPostedEvents(0, 0);
+
+ QCOMPARE(widget.minimumHeight(),
+ leftChild.minimumHeight() + bottomChild.minimumHeight());
+ QCOMPARE(widget.minimumWidth(),
+ qMax(leftChild.minimumWidth(), bottomChild.minimumWidth()));
+ QCOMPARE(widget.maximumHeight(),
+ leftChild.maximumHeight() + bottomChild.maximumHeight());
+ QCOMPARE(widget.maximumWidth(),
+ qMax(leftChild.maximumWidth(), bottomChild.maximumWidth()));
+
+ bottomChild.hide();
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ bottomChild.show();
+ layout.removeWidget(&bottomChild);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+}
+
+
+class SizeHinter : public QWidget
+{
+public:
+ SizeHinter(const QSize &s, QWidget *parent = 0)
+ : QWidget(parent), sh(s) { }
+ SizeHinter(int w, int h, QWidget *parent = 0)
+ : QWidget(parent), sh(QSize(w,h)) {}
+ void setSizeHint(QSize s) { sh = s; }
+ QSize sizeHint() const { return sh; }
+private:
+ QSize sh;
+};
+
+void tst_QGridLayout::spacingAndSpacers()
+{
+ QWidget widget;
+ QGridLayout layout(&widget);
+ layout.setMargin(0);
+ layout.setSpacing(0);
+ widget.show();
+
+ QSize expectedSizeHint;
+
+ SizeHinter leftChild(100,100);
+ leftChild.setPalette(QPalette(Qt::red));
+ layout.addWidget(&leftChild, 0, 0);
+ QApplication::sendPostedEvents(0, 0);
+ expectedSizeHint = leftChild.sizeHint();
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+
+ SizeHinter rightChild(200,100);
+ rightChild.setPalette(QPalette(Qt::green));
+ layout.addWidget(&rightChild, 0, 2);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(rightChild.sizeHint(), QSize(200,100));
+
+ expectedSizeHint += QSize(rightChild.sizeHint().width(), 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+ layout.setColumnMinimumWidth(1, 100);
+ widget.adjustSize();
+ expectedSizeHint += QSize(100,0);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+ rightChild.hide();
+ QApplication::sendPostedEvents(0, 0);
+ expectedSizeHint -= QSize(rightChild.sizeHint().width(), 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+
+ layout.setColumnMinimumWidth(1, 0);
+ expectedSizeHint -= QSize(100, 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+ rightChild.show();
+
+#if 0
+ leftChild.setMaximumWidth(200);
+ rightChild.setMaximumWidth(200);
+
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.maximumWidth(), leftChild.maximumWidth() + rightChild.maximumWidth());
+#endif
+
+ layout.removeWidget(&rightChild);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+
+}
+
+
+class Qt42Style : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ Qt42Style() : QWindowsStyle()
+ {
+ spacing = 6;
+ margin = 9;
+ margin_toplevel = 11;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int spacing;
+ int margin;
+ int margin_toplevel;
+
+};
+
+int Qt42Style::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_DefaultLayoutSpacing:
+ return spacing;
+ break;
+ case PM_DefaultTopLevelMargin:
+ return margin_toplevel;
+ break;
+ case PM_DefaultChildMargin:
+ return margin;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+
+typedef QList<QPoint> PointList;
+Q_DECLARE_METATYPE(PointList)
+
+
+class SizeHinterFrame : public QLabel
+{
+public:
+ SizeHinterFrame(QWidget *parent = 0)
+ : QLabel(parent)
+ {
+ init(-1);
+ }
+
+ SizeHinterFrame(const QSize &s, int numPixels = -1)
+ : QLabel(0), sh(s) {
+ init(numPixels);
+ }
+
+
+ SizeHinterFrame(int w, int h)
+ : QLabel(0), sh(QSize(w,h))
+ {
+ init(-1);
+ }
+
+ void setSizeHint(const QSize &s) { sh = s; }
+ QSize sizeHint() const { return sh; }
+ void setMinimumSizeHint(const QSize &s) { msh = s; }
+ QSize minimumSizeHint() const { return msh; }
+
+ virtual int heightForWidth(int width) const;
+
+ void setNumberOfPixels(int numPixels) {
+ m_numPixels = numPixels;
+ QSizePolicy sp = sizePolicy();
+ sp.setHeightForWidth(m_numPixels != -1);
+ setSizePolicy(sp);
+ }
+private:
+ void init(int numPixels = -1){
+ setText(QString::fromAscii("(%1,%2)").arg(sh.width()).arg(sh.height()));
+ setFrameStyle(QFrame::Box | QFrame::Plain);
+ setNumberOfPixels(numPixels);
+ }
+private:
+ QSize sh;
+ QSize msh;
+ int m_numPixels;
+};
+
+int SizeHinterFrame::heightForWidth(int width) const
+{
+ // Special hack if m_numPixels == -2 then we report that we are heightForWidth aware, but we
+ // return sizeHint().width() so that it should be laid out as if we had't any hfw.
+ // This enables us to run the tests twice and to see if we get the same results with hfw as without hfw.
+ if (m_numPixels == -2) {
+ return sizeHint().height();
+ }
+ if (m_numPixels == -1 || width == 0) return -1;
+ // this widget should always cover the same amount of pixels (provided that we don't get any rounding errors)
+ return (m_numPixels)/width;
+}
+
+void tst_QGridLayout::spacingsAndMargins_data()
+{
+ // input
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<QSize>("sizehint");
+ // expected
+ QTest::addColumn<PointList>("expectedpositions");
+
+ int child_offset_y = 11 + 100 + 6 + 9 ;
+ QTest::newRow("1x1 grid") << 1 << 1 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ // children
+ << QPoint( 20, child_offset_y)
+ );
+
+ QTest::newRow("2x1 grid") << 2 << 1 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11 + 100 + 6, 11)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20 + 100 + 6, child_offset_y)
+ );
+
+ QTest::newRow("3x1 grid") << 3 << 1 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11 + 100 + 6, 11)
+ << QPoint( 11 + 100 + 6 + 100 + 6, 11)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20 + 100 + 6, child_offset_y)
+ << QPoint( 20 + 100 + 6 + 100 + 6, child_offset_y)
+ );
+
+ child_offset_y = 11 + 9 + 100 + 6 + 100 + 6;
+ QTest::newRow("1x2 grid") << 1 << 2 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11, 11 + 100 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20, child_offset_y + 100 + 6)
+ );
+#if defined (Q_OS_WINCE) //There is not enough screenspace to run the test in original size on Windows CE. We use smaller widgets.
+ child_offset_y = 11 + 9 + 50 + 6 + 50 + 6 + 50 + 6;
+ QTest::newRow("1x3 grid") << 1 << 3 << QSize(50, 50)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11, 11 + 50 + 6)
+ << QPoint( 11, 11 + 50 + 6 + 50 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20, child_offset_y + 50 + 6)
+ << QPoint( 20, child_offset_y + 50 + 6 + 50 + 6)
+ );
+#else
+ child_offset_y = 11 + 9 + 100 + 6 + 100 + 6 + 100 + 6;
+ QTest::newRow("1x3 grid") << 1 << 3 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11, 11 + 100 + 6)
+ << QPoint( 11, 11 + 100 + 6 + 100 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20, child_offset_y + 100 + 6)
+ << QPoint( 20, child_offset_y + 100 + 6 + 100 + 6)
+ );
+#endif
+
+ child_offset_y = 11 + 9 + 100 + 6 + 100 + 6;
+ QTest::newRow("2x2 grid") << 2 << 2 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11 + 100 + 6, 11)
+ << QPoint( 11, 11 + 100 + 6)
+ << QPoint( 11 + 100 + 6, 11 + 100 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20 + 100 + 6, child_offset_y)
+ << QPoint( 20, child_offset_y + 100 + 6)
+ << QPoint( 20 + 100 + 6, child_offset_y + 100 + 6)
+ );
+}
+
+void tst_QGridLayout::spacingsAndMargins()
+{
+/*
+ The test tests a gridlayout as a child of a top-level widget,
+ and then a gridlayout as a child of a non-toplevel widget.
+
+ The expectedpositions should then contain the list of widget positions in the
+ first gridlayout, then followed by a list of widget positions in the second gridlayout.
+*/
+ QFETCH(int, columns);
+ QFETCH(int, rows);
+ QFETCH(QSize, sizehint);
+ QFETCH(PointList, expectedpositions);
+
+
+ QApplication::setStyle(new Qt42Style);
+ QWidget toplevel;
+ if(PlatformQuirks::isAutoMaximizing())
+ toplevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QVBoxLayout vbox(&toplevel);
+ QGridLayout grid1;
+ vbox.addLayout(&grid1);
+
+ // a layout with a top-level parent widget
+ QList<QPointer<SizeHinterFrame> > sizehinters;
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeHinterFrame *sh = new SizeHinterFrame(sizehint);
+ sh->setMinimumSizeHint(sizehint);
+ sizehinters.append(sh);
+ grid1.addWidget(sh, i, j);
+ }
+ }
+
+ // Add the child widget
+ QWidget widget;
+ vbox.addWidget(&widget);
+ QGridLayout grid2;
+ widget.setLayout(&grid2);
+ // add a layout to the child widget
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeHinterFrame *sh = new SizeHinterFrame(sizehint);
+ sh->setMinimumSizeHint(sizehint);
+ sizehinters.append(sh);
+ grid2.addWidget(sh, i, j);
+ }
+ }
+
+ grid1.setColumnStretch(columns-1, 1);
+ grid1.setRowStretch(rows-1, 1);
+ toplevel.show();
+ toplevel.adjustSize();
+ QApplication::processEvents();
+ QTest::qWaitForWindowShown(&toplevel);
+
+ QSize topsize = toplevel.size();
+ QSize minimumsize = vbox.totalMinimumSize();
+
+ if (topsize.width() < minimumsize.width() || topsize.height() < minimumsize.height())
+ QSKIP("The screen is too small to run this test case", SkipSingle);
+
+// We are relying on the order here...
+ for (int pi = 0; pi < sizehinters.count(); ++pi) {
+ QPoint pt = sizehinters.at(pi)->mapTo(&toplevel, QPoint(0, 0));
+ QCOMPARE(pt, expectedpositions.at(pi));
+ }
+}
+
+
+
+
+struct SizeInfo {
+ SizeInfo(const QPoint &expected, const QSize &sh, const QSize &minimumSize = QSize(),
+ const QSize &maximumSize = QSize(), int numPixelsToCover = -1)
+ {
+ expectedPos = expected;
+ sizeHint = sh;
+ minSize = minimumSize;
+ maxSize = maximumSize;
+ hfwNumPixels = numPixelsToCover;
+ }
+
+ SizeInfo(const QRect &expected, const QSize &sh, const QSize &minimumSize = QSize(),
+ const QSize &maximumSize = QSize(), int numPixelsToCover = -1)
+ {
+ expectedPos = expected.topLeft();
+ expectedSize = expected.size();
+ sizeHint = sh;
+ minSize = minimumSize;
+ maxSize = maximumSize;
+ hfwNumPixels = numPixelsToCover;
+ }
+ SizeInfo(const SizeInfo& other) {
+ (*this)=other;
+ }
+
+ SizeInfo &operator=(const SizeInfo& other) {
+ expectedPos = other.expectedPos;
+ expectedSize = other.expectedSize;
+ sizeHint = other.sizeHint;
+ minSize = other.minSize;
+ maxSize = other.maxSize;
+ hfwNumPixels = other.hfwNumPixels;
+ return (*this);
+ }
+
+ QPoint expectedPos;
+ QSize expectedSize;
+ QSize sizeHint;
+ QSize minSize;
+ QSize maxSize;
+ int hfwNumPixels;
+};
+
+
+typedef QList<SizeInfo> SizeInfoList;
+Q_DECLARE_METATYPE(SizeInfoList)
+
+
+void tst_QGridLayout::minMaxSize_data()
+{
+ // input
+ QTest::addColumn<QString>("stylename");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("sizePolicy");
+ QTest::addColumn<QSize>("fixedSize");
+ //input and expected output
+ QTest::addColumn<SizeInfoList>("sizeinfos");
+
+ QTest::newRow("3x1 grid, extend to minimumSize") << QString() << 3 << 1
+ << int(QSizePolicy::Minimum) << QSize(152, 50) << (SizeInfoList()
+ << SizeInfo(QRect(10, 10, 43, 30), QSize( 75, 75), QSize(0,0))
+ << SizeInfo(QRect(10 + 45, 10, 43, 30), QSize(75, 75), QSize( 0, 0))
+ << SizeInfo(QRect(10 + 45 + 44, 10, 42, 30), QSize(75, 75), QSize( 0, 0))
+ );
+
+ QTest::newRow("1x1 grid, extend to minimumSize") << QString() << 1 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize( 90, 90), QSize(100,100))
+ );
+ QTest::newRow("2x1 grid, extend to minimumSize") << QString() << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(10 + 100 + 1, 10), QSize( 90, 90))
+ );
+ QTest::newRow("1x2 grid, extend to minimumSize") << QString() << 1 << 2
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(10, 10 + 100 + 1), QSize( 90, 90))
+ );
+ QTest::newRow("2x1 grid, crop to maximumSize") << QString() << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize(110,110), QSize(), QSize(100, 100))
+ << SizeInfo(QPoint(10 + 100 + 1, 10), QSize( 90, 90))
+ );
+ QTest::newRow("1x2 grid, crop to maximumSize") << QString() << 1 << 2
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize(110,110), QSize(), QSize(100, 100))
+ << SizeInfo(QPoint(10, 10 + 100 + 1), QSize( 90, 90))
+ );
+ QTest::newRow("1x3 grid, heightForWidth") << QString() << 1 << 3
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize(), QSize(200,100), QSize())
+ << SizeInfo(QPoint(10, 10 + 100 + 1), QSize(100,100), QSize(), QSize(), 100*100)
+ << SizeInfo(QPoint(10, 10 + 100 + 1 + 50 + 1), QSize(100,100), QSize(), QSize(100, 100))
+ );
+ QTest::newRow("2x1 grid, extend to minimumSize") << QString::fromAscii("motif") << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(11, 11), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(11 + 100 + 6, 11), QSize( 90, 90))
+ );
+ QTest::newRow("2x1 grid, extend to minimumSize") << QString::fromAscii("windows") << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(11, 11), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(11 + 100 + 6, 11), QSize( 90, 90))
+ );
+
+}
+
+void tst_QGridLayout::minMaxSize()
+{
+/*
+ The test tests a gridlayout as a child of a top-level widget
+*/
+ // input
+ QFETCH(QString, stylename);
+ QFETCH(int, columns);
+ QFETCH(int, rows);
+ QFETCH(int, sizePolicy);
+ QFETCH(QSize, fixedSize);
+ //input and expected output
+ QFETCH(SizeInfoList, sizeinfos);
+
+ QStyle *style = 0;
+ if (stylename.isEmpty()) {
+ Qt42Style *s = new Qt42Style;
+ s->margin_toplevel = 10;
+ s->margin = 5;
+ s->spacing = 1;
+ style = static_cast<QStyle *>(s);
+ }else{
+ style = QStyleFactory::create(stylename);
+ if (!style) {
+ QSKIP( qPrintable(QString::fromLatin1("Qt has been compiled without style: %1").arg(stylename)), SkipSingle);
+ }
+ }
+ QApplication::setStyle(style);
+ if (!m_grid)
+ m_grid = new QGridLayout();
+ if (!m_toplevel)
+ m_toplevel = new QWidget();
+ if (fixedSize.isValid()) {
+ m_toplevel->setFixedSize(fixedSize);
+ } else {
+ m_toplevel->setMinimumSize(QSize(0,0));
+ m_toplevel->setMaximumSize(QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX));
+ }
+ // Do a two-pass one using the real testdata, the other pass enables heightForWidth
+ // on the widget, but the heightForWidth() function just return sizeHint().width()
+ for (int pass = 0; pass < 2; ++pass) {
+ m_toplevel->hide();
+ QApplication::processEvents();
+ QTest::qWait(20);
+ // Test if removeItem uninitializes data properly
+ while (m_grid->count()) {
+ QLayoutItem *item = m_grid->itemAt(0);
+ m_grid->removeItem(item);
+ delete item->widget();
+ delete item;
+ }
+ m_toplevel->setLayout(m_grid);
+
+ // a layout with a top-level parent widget
+ QList<QPointer<SizeHinterFrame> > sizehinters;
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeInfo si = sizeinfos.at(sizehinters.count());
+ int numpixels = si.hfwNumPixels;
+ if (pass == 1 && numpixels == -1)
+ numpixels = -2; //### yuk, (and don't fake it if it already tests sizehint)
+ SizeHinterFrame *sh = new SizeHinterFrame(si.sizeHint, numpixels);
+ QSizePolicy sp = sh->sizePolicy();
+ sp.setHorizontalPolicy((QSizePolicy::Policy)sizePolicy);
+ sh->setSizePolicy(sp);
+ sh->setParent(m_toplevel);
+ if (si.minSize.isValid())
+ sh->setMinimumSize(si.minSize);
+ if (si.maxSize.isValid())
+ sh->setMaximumSize(si.maxSize);
+ sizehinters.append(sh);
+ m_grid->addWidget(sh, i, j);
+ }
+ }
+
+ m_toplevel->show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(m_toplevel); // wait for the show
+#endif
+ QTest::qWait(40);
+ m_toplevel->adjustSize();
+ QTest::qWait(240); // wait for the implicit adjustSize
+ // If the following fails we might have to wait longer.
+ // If that does not help there is likely a problem with the implicit adjustSize in show()
+ if (!fixedSize.isValid()) {
+ // Note that this can fail if the desktop has large fonts on windows.
+ QTRY_COMPARE(m_toplevel->size(), m_toplevel->sizeHint());
+ }
+ // We are relying on the order here...
+ for (int pi = 0; pi < sizehinters.count(); ++pi) {
+ QPoint pt = sizehinters.at(pi)->mapTo(m_toplevel, QPoint(0, 0));
+ QCOMPARE(pt, sizeinfos.at(pi).expectedPos);
+ }
+ }
+}
+
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ reimplementSubelementRect = false;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+ virtual QRect subElementRect(SubElement sr, const QStyleOption *opt,
+ const QWidget *widget) const;
+
+ int hspacing;
+ int vspacing;
+ bool reimplementSubelementRect;
+
+protected slots:
+ int layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption *option = 0,
+ const QWidget *widget = 0) const;
+
+};
+
+QRect CustomLayoutStyle::subElementRect(SubElement sr, const QStyleOption *opt,
+ const QWidget *widget) const
+{
+ QRect rect;
+ if (reimplementSubelementRect) {
+ switch (sr) {
+ case SE_FrameLayoutItem:
+ rect = opt->rect;
+ rect.adjust(+4, +9, -4, 0); // The hspacing=5 and vspacing=10, so we keep it safe.
+ break;
+ case SE_GroupBoxLayoutItem:
+ rect = opt->rect.adjusted(0, +10, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ if (rect.isNull())
+ rect = QWindowsStyle::subElementRect(sr, opt, widget);
+ return rect;
+}
+
+#define CT1(c) CT2(c, c)
+#define CT2(c1, c2) ((uint)c1 << 16) | (uint)c2
+
+int CustomLayoutStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption * /*option = 0*/,
+ const QWidget * /*widget = 0*/) const
+{
+ if (orientation == Qt::Horizontal) {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::PushButton):
+ return 2;
+ break;
+ }
+ return 5;
+ } else {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::RadioButton):
+ return 2;
+ break;
+
+ }
+ return 10;
+ }
+}
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ break;
+ case PM_LayoutTopMargin:
+ return 3;
+ break;
+ case PM_LayoutRightMargin:
+ return 6;
+ break;
+ case PM_LayoutBottomMargin:
+ return 9;
+ break;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+void tst_QGridLayout::styleDependentSpacingsAndMargins_data()
+{
+ // input
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<QSize>("sizehint");
+ // expected
+ QTest::addColumn<PointList>("expectedpositions");
+
+ QTest::newRow("1x1 grid") << 1 << 1 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3) );
+ QTest::newRow("2x1 grid") << 2 << 1 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0+100+5, 3));
+ QTest::newRow("3x1 grid") << 3 << 1 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0+100+5, 3)
+ << QPoint(0 + 2*105, 3));
+ QTest::newRow("1x2 grid") << 1 << 2 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0, 3+100+10));
+ QTest::newRow("1x3 grid") << 1 << 3 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0, 3+100+10)
+ << QPoint(0, 3+2*110));
+ QTest::newRow("2x2 grid") << 2 << 2 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3) << QPoint(0+100+5, 3)
+ << QPoint(0, 3+100+10) << QPoint(0+100+5, 3+100+10));
+}
+
+
+void tst_QGridLayout::styleDependentSpacingsAndMargins()
+{
+ QFETCH(int, columns);
+ QFETCH(int, rows);
+ QFETCH(QSize, sizehint);
+ QFETCH(PointList, expectedpositions);
+
+ QApplication::setStyle(new CustomLayoutStyle());
+ QWidget widget;
+ QGridLayout layout(&widget);
+ QList<QPointer<SizeHinterFrame> > sizehinters;
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeHinterFrame *sh = new SizeHinterFrame(sizehint);
+ sh->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ sh->setParent(&widget);
+ sizehinters.append(sh);
+ layout.addWidget(sh, i, j);
+ }
+ }
+ layout.setColumnStretch(columns, 1);
+ layout.setRowStretch(rows, 1);
+ widget.show();
+ widget.adjustSize();
+ QApplication::processEvents();
+
+ for (int pi = 0; pi < expectedpositions.count(); ++pi) {
+ QCOMPARE(sizehinters.at(pi)->pos(), expectedpositions.at(pi));
+ }
+}
+
+void tst_QGridLayout::layoutSpacingImplementation_data()
+{
+ QTest::addColumn<QWidget*>("widget");
+ // expected
+ QTest::addColumn<PointList>("expectedpositions");
+ QTest::addColumn<int>("hSpacing");
+ QTest::addColumn<int>("vSpacing");
+ QTest::addColumn<bool>("customSubElementRect");
+
+ CustomLayoutStyle *style = new CustomLayoutStyle();
+ {
+ // If the layoutSpacing is negative, the layouting code will call
+ // layoutSpacingImplementation()
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QRadioButton *rb1 = new QRadioButton(QLatin1String("Radio 1"), w);
+ QRadioButton *rb2 = new QRadioButton(QLatin1String("Radio 2"), w);
+ QRadioButton *rb3 = new QRadioButton(QLatin1String("Radio 3"), w);
+ layout->addWidget(rb1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(rb2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(rb3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ QPushButton *b1 = new QPushButton(QLatin1String("Push 1"), w);
+ QPushButton *b2 = new QPushButton(QLatin1String("Push 2"), w);
+ QPushButton *b3 = new QPushButton(QLatin1String("Push 3"), w);
+ layout->addWidget(b1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ layout->addStretch(1);
+ w->setLayout(layout);
+ int rh = rb1->sizeHint().height();
+ int ph = b1->sizeHint().height();
+ QTest::newRow("1x6, radio + push buttons")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + rh + 2)
+ << QPoint(0, 3 + 2*(rh + 2))
+ << QPoint(0, 3 + 2*(rh + 2) + (rh + 10))
+ << QPoint(0, 3 + 2*(rh + 2) + (rh + 10 + ph + 10))
+ << QPoint(0, 3 + 2*(rh + 2) + rh + 10 + 2*(ph + 10)))
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+ {
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QHBoxLayout *layout = new QHBoxLayout();
+ QLineEdit *le1 = new QLineEdit(w);
+ QLineEdit *le2 = new QLineEdit(w);
+ QLineEdit *le3 = new QLineEdit(w);
+ layout->addWidget(le1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(le2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(le3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ QPushButton *b1 = new QPushButton(QLatin1String("Push 1"), w);
+ QPushButton *b2 = new QPushButton(QLatin1String("Push 2"), w);
+ QPushButton *b3 = new QPushButton(QLatin1String("Push 3"), w);
+ layout->addWidget(b1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ layout->addStretch(1);
+ w->setLayout(layout);
+ int lw = le1->sizeHint().width();
+ int pw = b1->sizeHint().width();
+ QTest::newRow("6x1, line edit + push buttons")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0 + lw + 5, 3)
+ << QPoint(0 + 2*(lw + 5), 3)
+ << QPoint(0 + 3*(lw + 5), 3)
+ << QPoint(0 + 3*(lw + 5) + 1*(pw + 2), 3)
+ << QPoint(0 + 3*(lw + 5) + 2*(pw + 2), 3))
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+
+ QGroupBox *g1 = new QGroupBox(QLatin1String("GroupBox 1"), w);
+
+ QRadioButton *rb = new QRadioButton(QLatin1String("Radio 1"), g1);
+ QVBoxLayout *g1layout = new QVBoxLayout();
+ g1layout->addWidget(rb);
+ g1->setLayout(g1layout);
+
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+
+ layout->addWidget(pb1);
+ layout->addWidget(g1 );
+ layout->addWidget(pb3);
+
+ w->setLayout(layout);
+ QSize psh = pb1->sizeHint();
+ QSize gsh = g1->sizeHint();
+
+ QTest::newRow("subElementRect1")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + psh.height() + 10 - 10)
+ << QPoint(0, 3 + psh.height() + 10 - 10 + gsh.height() + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QGridLayout *layout = new QGridLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+ QPushButton *pb2 = new QPushButton(QLatin1String("Push 2"), w);
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+ QPushButton *pb4 = new QPushButton(QLatin1String("Push 4"), w);
+
+ layout->addWidget(pb1, 0, 0);
+ layout->addWidget(pb2, 0, 1);
+ layout->addWidget(pb3, 0, 2);
+ layout->addWidget(pb4, 1, 0, Qt::AlignTop);
+
+
+ QFrame *f1 = new QFrame(w);
+ f1->setFrameStyle(QFrame::Box | QFrame::Plain);
+ f1->setMinimumSize(100, 20);
+ f1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ layout->addWidget(f1, 1, 1, Qt::AlignTop);
+
+
+ QPushButton *pb6 = new QPushButton(QLatin1String("Push 6"), w);
+ QPushButton *pb7 = new QPushButton(QLatin1String("Push 7"), w);
+ QPushButton *pb8 = new QPushButton(QLatin1String("Push 8"), w);
+ QPushButton *pb9 = new QPushButton(QLatin1String("Push 9"), w);
+ layout->addWidget(pb6, 1, 2, Qt::AlignTop);
+ layout->addWidget(pb7, 2, 0, Qt::AlignTop);
+ layout->addWidget(pb8, 2, 1, Qt::AlignTop);
+ layout->addWidget(pb9, 2, 2, Qt::AlignTop);
+
+ layout->setColumnStretch(2, 1);
+ layout->setRowStretch(2, 1);
+ w->setLayout(layout);
+ int c[3];
+ c[0] = pb1->sizeHint().width();
+ c[1] = f1->minimumSize().width() - 2*4;
+ c[2] = pb3->sizeHint().width();
+
+ int r[3];
+ r[0] = pb1->sizeHint().height();
+ r[1] = pb4->sizeHint().height();
+ r[2] = pb7->sizeHint().height();
+
+
+ QTest::newRow("subElementRect2")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0 + c[0] + 5, 3)
+ << QPoint(0 + c[0] + 5 + c[1] + 5, 3)
+
+ << QPoint(0, 3 + r[0] + 10)
+ << QPoint(0 + c[0] + 5 - 4, 3 + r[0] + 10 - 9)
+ << QPoint(0 + c[0] + 5 + c[1] + 5, 3 + r[0] + 10)
+
+ << QPoint(0, 3 + r[0] + 10 + r[1] + 10)
+ << QPoint(0 + c[0] + 5, 3 + r[0] + 10 + r[1] + 10)
+ << QPoint(0 + c[0] + 5 + c[1] + 5, 3 + r[0] + 10 + r[1] + 10)
+
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+
+ QGroupBox *g1 = new QGroupBox(QLatin1String("GroupBox 1"), w);
+
+ QRadioButton *rb = new QRadioButton(QLatin1String("Radio 1"), g1);
+ QVBoxLayout *g1layout = new QVBoxLayout();
+ g1layout->addWidget(rb);
+ g1->setLayout(g1layout);
+
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
+ g1->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
+ pb3->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
+ layout->addWidget(pb1);
+ layout->addWidget(g1 );
+ layout->addWidget(pb3);
+
+ w->setLayout(layout);
+ QSize psh = pb1->sizeHint();
+ QSize gsh = g1->sizeHint();
+
+ QTest::newRow("subElementRect1, use widgetRect")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + psh.height() + 10)
+ << QPoint(0, 3 + psh.height() + 10 + gsh.height() + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+
+ QGroupBox *g1 = new QGroupBox(QLatin1String("GroupBox 1"), w);
+
+ QRadioButton *rb = new QRadioButton(QLatin1String("Radio 1"), g1);
+ QVBoxLayout *g1layout = new QVBoxLayout();
+ g1layout->addWidget(rb);
+ g1->setLayout(g1layout);
+
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
+ g1->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
+ pb3->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
+ layout->addWidget(pb1);
+ layout->addWidget(g1 );
+ layout->addWidget(pb3);
+
+ w->setLayout(layout);
+ QSize psh = pb1->sizeHint();
+ QSize gsh = g1->sizeHint();
+
+ QTest::newRow("subElementRect1, use layoutItemRect")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + psh.height() + 10 - 10)
+ << QPoint(0, 3 + psh.height() + 10 - 10 + gsh.height() + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ /* A 3x4 gridlayout, modified arrowpad example:
+ * [PB]
+ * [PB] [PB]
+ * |PB|
+ * | |
+ * | |
+ *
+ * Here the bottom pushbutton has a span
+ */
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QGridLayout *layout = new QGridLayout();
+ QPushButton *left = new QPushButton(w);
+ QPushButton *up = new QPushButton(w);
+ QPushButton *right = new QPushButton(w);
+ QPushButton *down = new QPushButton(w);
+
+ layout->addWidget(up, 0, 1);
+ layout->addWidget(left, 1, 0);
+ layout->addWidget(right, 1, 2);
+ layout->addWidget(down, 2, 1, 3, 1);
+
+ w->setLayout(layout);
+ int pw = up->sizeHint().width();
+ int ph = up->sizeHint().height();
+ QTest::newRow("arrowpad with span")
+ << w << (PointList()
+ << QPoint(0 + pw + 5, 3)
+ << QPoint(0, 3 + ph + 10)
+ << QPoint(0 + pw + 5 + pw + 5, 3 + ph + 10)
+ << QPoint(0 + pw + 5, 3 + ph + 10 + ph + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ for (int yoff = 0; yoff < 5; ++yoff)
+ {
+ for (int xoff = 0; xoff < 5; ++xoff) {
+ /* A 3x4 gridlayout, modified arrowpad example:
+ * [empty cells]
+ * [PB]
+ * [PB] [PB]
+ * [PB]
+ *
+ * It has 0-4 empty rows at the top and 0-4 empty columns to the left.
+ */
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QGridLayout *layout = new QGridLayout();
+ QPushButton *left = new QPushButton(w);
+ QPushButton *up = new QPushButton(w);
+ QPushButton *right = new QPushButton(w);
+ QPushButton *down = new QPushButton(w);
+
+ layout->addWidget(up, yoff + 0, xoff + 1);
+ layout->addWidget(left, yoff + 1, xoff + 0);
+ layout->addWidget(right, yoff + 1, xoff + 2);
+ layout->addWidget(down, yoff + 2, xoff + 1, 3, 1);
+
+ w->setLayout(layout);
+ int pw = up->sizeHint().width();
+ int ph = up->sizeHint().height();
+ QByteArray testName = QString::fromAscii("arrowpad with %1 empty rows, %2 empty columns").arg(yoff).arg(xoff).toLatin1();
+ QTest::newRow(testName.data())
+ << w << (PointList()
+ << QPoint(0 + pw + 5, 3)
+ << QPoint(0, 3 + ph + 10)
+ << QPoint(0 + pw + 5 + pw + 5, 3 + ph + 10)
+ << QPoint(0 + pw + 5, 3 + ph + 10 + ph + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+ }
+
+}
+
+void tst_QGridLayout::layoutSpacingImplementation()
+{
+ QFETCH(QWidget *, widget);
+ QFETCH(PointList, expectedpositions);
+ QFETCH(int, hSpacing);
+ QFETCH(int, vSpacing);
+ QFETCH(bool, customSubElementRect);
+
+ QWidget toplevel;
+
+ CustomLayoutStyle *style = new CustomLayoutStyle();
+ style->hspacing = hSpacing;
+ style->vspacing = vSpacing;
+ style->reimplementSubelementRect = customSubElementRect;
+ QApplication::setStyle(style);
+ widget->setParent(&toplevel);
+ widget->resize(widget->sizeHint());
+ toplevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&toplevel); // wait for the show
+#endif
+
+ QLayout *layout = widget->layout();
+ QVERIFY(layout);
+ //QTest::qWait(2000);
+ for (int pi = 0; pi < expectedpositions.count(); ++pi) {
+ QLayoutItem *item = layout->itemAt(pi);
+ //qDebug() << item->widget()->pos();
+ QCOMPARE(item->widget()->pos(), expectedpositions.at(pi));
+ }
+}
+
+void tst_QGridLayout::spacing()
+{
+ QWidget w;
+ CustomLayoutStyle *style = new CustomLayoutStyle();
+ style->hspacing = 5;
+ style->vspacing = 10;
+ w.setStyle(style);
+ QGridLayout grid(&w);
+ QCOMPARE(style->hspacing, grid.horizontalSpacing());
+ QCOMPARE(style->vspacing, grid.verticalSpacing());
+
+ QCOMPARE(grid.spacing(), -1);
+ grid.setVerticalSpacing(5);
+ QCOMPARE(5, grid.horizontalSpacing());
+ QCOMPARE(5, grid.verticalSpacing());
+ QCOMPARE(grid.spacing(), 5);
+ grid.setVerticalSpacing(-1);
+ QCOMPARE(style->hspacing, grid.horizontalSpacing());
+ QCOMPARE(style->vspacing, grid.verticalSpacing());
+
+ style->hspacing = 5;
+ style->vspacing = 5;
+ QCOMPARE(grid.spacing(), 5);
+
+
+ grid.setHorizontalSpacing(20);
+ QCOMPARE(grid.spacing(), -1);
+ style->vspacing = 20;
+ QCOMPARE(grid.horizontalSpacing(), 20);
+ QCOMPARE(grid.verticalSpacing(), 20);
+ QCOMPARE(grid.spacing(), 20);
+ grid.setHorizontalSpacing(-1);
+ QCOMPARE(grid.spacing(), -1);
+ style->hspacing = 20;
+ QCOMPARE(grid.spacing(), 20);
+
+
+ delete style;
+}
+
+void populate(QGridLayout *layout, int row, int kind)
+{
+ if (kind == 0) {
+ QWidget *widget = new QWidget;
+ widget->setFixedSize(100, 100);
+ layout->addWidget(widget, row, 0);
+ } else if (kind == 1) {
+ layout->addItem(new QSpacerItem(10, 10), row, 0);
+ }
+}
+
+void tst_QGridLayout::spacerWithSpacing()
+{
+ // Tests all combinations of widget (w), spacer (s) and no layoutitem (-)
+ // to see if they are laid out correctly.
+ // Note that a combination of "s-" or "-s" should only give the height of "s"
+ const int expectedHeight[] = {
+ 302,// www
+ 211,// wws
+ 201,// ww-
+ 211,// wsw
+ 120,// wss
+ 110,// ws-
+ 201,// w-w
+ 110,// w-s
+ 100,// w--
+ 211,// sww
+ 120,// sws
+ 110,// sw-
+ 120,// ssw
+ 30,// sss
+ 20,// ss-
+ 110,// s-w
+ 20,// s-s
+ 10,// s--
+ 201,// -ww
+ 110,// -ws
+ 100,// -w-
+ 110,// -sw
+ 20,// -ss
+ 10,// -s-
+ 100,// --w
+ 10,// --s
+ 000 // ---
+ };
+ int ii = 0;
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ for (int k = 0; k < 3; ++k) {
+ QWidget window;
+ QGridLayout layout(&window);
+ layout.setSpacing(1);
+ layout.setMargin(0);
+ populate(&layout, 0, i);
+ populate(&layout, 1, j);
+ populate(&layout, 2, k);
+ QCOMPARE(window.sizeHint().height(), expectedHeight[ii]);
+#if 0
+ const char T[] = "ws-";
+ qWarning("%c%c%c: %.3d", i[T], j[T], k[T], window.sizeHint().height());
+#endif
+ ++ii;
+ }
+ }
+ }
+}
+
+void tst_QGridLayout::contentsRect()
+{
+ QWidget w;
+ QGridLayout grid;
+ w.setLayout(&grid);
+ grid.addWidget(new QPushButton(&w));
+ w.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&w); // wait for the show
+#endif
+ int l, t, r, b;
+ grid.getContentsMargins(&l, &t, &r, &b);
+ QRect geom = grid.geometry();
+
+ QCOMPARE(geom.adjusted(+l, +t, -r, -b), grid.contentsRect());
+
+}
+
+void tst_QGridLayout::distributeMultiCell()
+{
+ QWidget w;
+ Qt42Style *style = new Qt42Style();
+ style->spacing = 9;
+
+ w.setStyle(style);
+ QGridLayout grid;
+ w.setLayout(&grid);
+
+ SizeHinter le1(200, 20, &w);
+ le1.setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ SizeHinter le2(200, 20, &w);
+ le2.setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ SizeHinter box(80, 57, &w);
+ box.setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
+ box.setMinimumSize(80, 57);
+
+ grid.addWidget(&le1, 0, 0, 1, 1);
+ grid.addWidget(&le2, 1, 0, 1, 1);
+ grid.addWidget(&box, 0, 1, 2, 1);
+
+ QCOMPARE(box.sizeHint().height(), 57);
+ QCOMPARE(w.sizeHint().height(), 11 + 57 + 11);
+}
+
+QTEST_MAIN(tst_QGridLayout)
+#include "tst_qgridlayout.moc"
diff --git a/tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro b/tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro
new file mode 100644
index 0000000000..cdadb0c5ed
--- /dev/null
+++ b/tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qinputcontext.cpp
+
+mac*:CONFIG+=insignificant_test
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp b/tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp
new file mode 100644
index 0000000000..9b6452851e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp
@@ -0,0 +1,398 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <qinputcontext.h>
+#include <qlineedit.h>
+#include <qplaintextedit.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qwindowsstyle.h>
+#include <qdesktopwidget.h>
+#include <qpushbutton.h>
+#include <qgraphicsview.h>
+#include <qgraphicsscene.h>
+
+#ifdef QT_WEBKIT_LIB
+#include <qwebview.h>
+#include <qgraphicswebview.h>
+#endif
+
+class tst_QInputContext : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QInputContext() : m_phoneIsQwerty(false) {}
+ virtual ~tst_QInputContext() {}
+
+public slots:
+ void cleanupTestCase() {}
+ void init() {}
+ void cleanup() {}
+private slots:
+ void maximumTextLength();
+ void filterMouseEvents();
+ void requestSoftwareInputPanel();
+ void closeSoftwareInputPanel();
+ void selections();
+ void focusProxy();
+
+private:
+ bool m_phoneIsQwerty;
+};
+
+void tst_QInputContext::maximumTextLength()
+{
+ QLineEdit le;
+
+ le.setMaxLength(15);
+ QVariant variant = le.inputMethodQuery(Qt::ImMaximumTextLength);
+ QVERIFY(variant.isValid());
+ QCOMPARE(variant.toInt(), 15);
+
+ QPlainTextEdit pte;
+ // For BC/historical reasons, QPlainTextEdit::inputMethodQuery is protected.
+ variant = static_cast<QWidget *>(&pte)->inputMethodQuery(Qt::ImMaximumTextLength);
+ QVERIFY(!variant.isValid());
+}
+
+class QFilterInputContext : public QInputContext
+{
+public:
+ QFilterInputContext() {}
+ ~QFilterInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+
+ bool isComposing() const { return false; }
+
+ bool filterEvent( const QEvent *event )
+ {
+ lastTypes.append(event->type());
+ return false;
+ }
+
+public:
+ QList<QEvent::Type> lastTypes;
+};
+
+void tst_QInputContext::filterMouseEvents()
+{
+ QLineEdit le;
+ le.show();
+ QApplication::setActiveWindow(&le);
+
+ QFilterInputContext *ic = new QFilterInputContext;
+ qApp->setInputContext(ic);
+ QTest::mouseClick(&le, Qt::LeftButton);
+
+ QVERIFY(ic->lastTypes.indexOf(QEvent::MouseButtonRelease) >= 0);
+}
+
+class RequestSoftwareInputPanelStyle : public QWindowsStyle
+{
+public:
+ RequestSoftwareInputPanelStyle()
+ : m_rsipBehavior(RSIP_OnMouseClickAndAlreadyFocused)
+ {
+#ifdef Q_OS_WINCE
+ qApp->setAutoSipEnabled(true);
+#endif
+ }
+ ~RequestSoftwareInputPanelStyle()
+ {
+ }
+
+ int styleHint(StyleHint hint, const QStyleOption *opt = 0,
+ const QWidget *widget = 0, QStyleHintReturn* returnData = 0) const
+ {
+ if (hint == SH_RequestSoftwareInputPanel) {
+ return m_rsipBehavior;
+ } else {
+ return QWindowsStyle::styleHint(hint, opt, widget, returnData);
+ }
+ }
+
+ RequestSoftwareInputPanel m_rsipBehavior;
+};
+
+void tst_QInputContext::requestSoftwareInputPanel()
+{
+ QStyle *oldStyle = qApp->style();
+ oldStyle->setParent(this); // Prevent it being deleted.
+ RequestSoftwareInputPanelStyle *newStyle = new RequestSoftwareInputPanelStyle;
+ qApp->setStyle(newStyle);
+
+ QWidget w;
+ QLayout *layout = new QVBoxLayout;
+ QLineEdit *le1, *le2;
+ le1 = new QLineEdit;
+ le2 = new QLineEdit;
+ layout->addWidget(le1);
+ layout->addWidget(le2);
+ w.setLayout(layout);
+
+ QFilterInputContext *ic = new QFilterInputContext;
+ qApp->setInputContext(ic);
+
+ w.show();
+ QApplication::setActiveWindow(&w);
+
+ // Testing single click panel activation.
+ newStyle->m_rsipBehavior = QStyle::RSIP_OnMouseClick;
+ QTest::mouseClick(le2, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) >= 0);
+ ic->lastTypes.clear();
+
+ // Testing double click panel activation.
+ newStyle->m_rsipBehavior = QStyle::RSIP_OnMouseClickAndAlreadyFocused;
+ QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) < 0);
+ QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) >= 0);
+ ic->lastTypes.clear();
+
+ // Testing right mouse button
+ QTest::mouseClick(le1, Qt::RightButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) < 0);
+
+ qApp->setStyle(oldStyle);
+ oldStyle->setParent(qApp);
+}
+
+void tst_QInputContext::closeSoftwareInputPanel()
+{
+ QWidget w;
+ QLayout *layout = new QVBoxLayout;
+ QLineEdit *le1, *le2;
+ QRadioButton *rb;
+ le1 = new QLineEdit;
+ le2 = new QLineEdit;
+ rb = new QRadioButton;
+ layout->addWidget(le1);
+ layout->addWidget(le2);
+ layout->addWidget(rb);
+ w.setLayout(layout);
+
+ QFilterInputContext *ic = new QFilterInputContext;
+ qApp->setInputContext(ic);
+
+ w.show();
+ QApplication::setActiveWindow(&w);
+
+ // Testing that panel doesn't close between two input methods aware widgets.
+ QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QTest::mouseClick(le2, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::CloseSoftwareInputPanel) < 0);
+
+ // Testing that panel closes when focusing non-aware widget.
+ QTest::mouseClick(rb, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::CloseSoftwareInputPanel) >= 0);
+}
+
+void tst_QInputContext::selections()
+{
+ QLineEdit le;
+ le.setText("Test text");
+ le.setSelection(2, 2);
+ QCOMPARE(le.inputMethodQuery(Qt::ImCursorPosition).toInt(), 4);
+ QCOMPARE(le.inputMethodQuery(Qt::ImAnchorPosition).toInt(), 2);
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 5, 3, QVariant()));
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(&le, &event);
+ QCOMPARE(le.cursorPosition(), 8);
+ QCOMPARE(le.selectionStart(), 5);
+ QCOMPARE(le.inputMethodQuery(Qt::ImCursorPosition).toInt(), 8);
+ QCOMPARE(le.inputMethodQuery(Qt::ImAnchorPosition).toInt(), 5);
+}
+
+void tst_QInputContext::focusProxy()
+{
+ QWidget toplevel(0, Qt::X11BypassWindowManagerHint); toplevel.setObjectName("toplevel");
+ QWidget w(&toplevel); w.setObjectName("w");
+ QWidget proxy(&w); proxy.setObjectName("proxy");
+ QWidget proxy2(&w); proxy2.setObjectName("proxy2");
+ w.setFocusProxy(&proxy);
+ w.setAttribute(Qt::WA_InputMethodEnabled);
+ toplevel.show();
+ QApplication::setActiveWindow(&toplevel);
+ QTest::qWaitForWindowShown(&toplevel);
+ w.setFocus();
+ w.setAttribute(Qt::WA_NativeWindow); // we shouldn't crash!
+
+ proxy.setAttribute(Qt::WA_InputMethodEnabled);
+ proxy2.setAttribute(Qt::WA_InputMethodEnabled);
+
+ proxy2.setFocus();
+ w.setFocus();
+
+ QInputContext *gic = qApp->inputContext();
+ QVERIFY(gic);
+ QCOMPARE(gic->focusWidget(), &proxy);
+
+ // then change the focus proxy and check that input context is valid
+ QVERIFY(w.hasFocus());
+ QVERIFY(proxy.hasFocus());
+ QVERIFY(!proxy2.hasFocus());
+ w.setFocusProxy(&proxy2);
+ QVERIFY(!w.hasFocus());
+ QVERIFY(proxy.hasFocus());
+ QVERIFY(!proxy2.hasFocus());
+ QCOMPARE(gic->focusWidget(), &proxy);
+}
+
+#ifdef QT_WEBKIT_LIB
+class AutoWebView : public QWebView
+{
+ Q_OBJECT
+
+public:
+ AutoWebView()
+ : m_length(0)
+ , m_mode(QLineEdit::Normal)
+ {
+ updatePage();
+ }
+ ~AutoWebView() {}
+
+ void updatePage()
+ {
+ // The update might reset the input method parameters.
+ bool imEnabled = testAttribute(Qt::WA_InputMethodEnabled);
+ Qt::InputMethodHints hints = inputMethodHints();
+
+ QString page = "<html><body onLoad=\"document.forms.testform.testinput.focus()\">"
+ "<form name=\"testform\"><input name=\"testinput\" type=\"%1\" %2></form></body></html>";
+ if (m_mode == QLineEdit::Password)
+ page = page.arg("password");
+ else
+ page = page.arg("text");
+
+ if (m_length == 0)
+ page = page.arg("");
+ else
+ page = page.arg("maxlength=\"" + QString::number(m_length) + "\"");
+
+ setHtml(page);
+
+ setAttribute(Qt::WA_InputMethodEnabled, imEnabled);
+ setInputMethodHints(hints);
+ }
+ void setMaxLength(int length)
+ {
+ m_length = length;
+ updatePage();
+ }
+ void setEchoMode(QLineEdit::EchoMode mode)
+ {
+ m_mode = mode;
+ updatePage();
+ }
+
+ int m_length;
+ QLineEdit::EchoMode m_mode;
+};
+
+class AutoGraphicsWebView : public QGraphicsView
+{
+ Q_OBJECT
+
+public:
+ AutoGraphicsWebView()
+ : m_length(0)
+ , m_mode(QLineEdit::Normal)
+ {
+ m_scene.addItem(&m_view);
+ setScene(&m_scene);
+ m_view.setFocus();
+ updatePage();
+ }
+ ~AutoGraphicsWebView() {}
+
+ void updatePage()
+ {
+ // The update might reset the input method parameters.
+ bool imEnabled = testAttribute(Qt::WA_InputMethodEnabled);
+ Qt::InputMethodHints hints = inputMethodHints();
+
+ QString page = "<html><body onLoad=\"document.forms.testform.testinput.focus()\">"
+ "<form name=\"testform\"><input name=\"testinput\" type=\"%1\" %2></form></body></html>";
+ if (m_mode == QLineEdit::Password)
+ page = page.arg("password");
+ else
+ page = page.arg("text");
+
+ if (m_length == 0)
+ page = page.arg("");
+ else
+ page = page.arg("maxlength=\"" + QString::number(m_length) + "\"");
+
+ m_view.setHtml(page);
+
+ setAttribute(Qt::WA_InputMethodEnabled, imEnabled);
+ setInputMethodHints(hints);
+ }
+ void setMaxLength(int length)
+ {
+ m_length = length;
+ updatePage();
+ }
+ void setEchoMode(QLineEdit::EchoMode mode)
+ {
+ m_mode = mode;
+ updatePage();
+ }
+
+ int m_length;
+ QLineEdit::EchoMode m_mode;
+ QGraphicsScene m_scene;
+ QGraphicsWebView m_view;
+};
+#endif // QT_WEBKIT_LIB
+
+QTEST_MAIN(tst_QInputContext)
+#include "tst_qinputcontext.moc"
diff --git a/tests/auto/widgets/kernel/qlayout/.gitignore b/tests/auto/widgets/kernel/qlayout/.gitignore
new file mode 100644
index 0000000000..cc058e7cc3
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/.gitignore
@@ -0,0 +1 @@
+tst_qlayout
diff --git a/tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize b/tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize
new file mode 100644
index 0000000000..2d3ba2e72f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize
@@ -0,0 +1,1792 @@
+0 0 0 0 0 0 0
+1 0 1 0 0 0 524287
+2 0 2 0 0 0 524287
+3 0 4 0 0 0 524287
+4 0 0 0 10 0 0
+5 0 1 0 10 0 524287
+6 0 2 0 10 0 524287
+7 0 4 0 10 0 524287
+8 0 0 0 20 0 0
+9 0 1 0 20 0 524287
+10 0 2 0 20 0 524287
+11 0 4 0 20 0 524287
+12 0 0 0 16777215 0 0
+13 0 1 0 16777215 0 524287
+14 0 2 0 16777215 0 524287
+15 0 4 0 16777215 0 524287
+16 0 0 0 0 10 10
+17 0 1 0 0 10 524287
+18 0 2 0 0 10 524287
+19 0 4 0 0 10 524287
+20 0 0 0 10 10 10
+21 0 1 0 10 10 524287
+22 0 2 0 10 10 524287
+23 0 4 0 10 10 524287
+24 0 0 0 20 10 10
+25 0 1 0 20 10 524287
+26 0 2 0 20 10 524287
+27 0 4 0 20 10 524287
+28 0 0 0 16777215 10 10
+29 0 1 0 16777215 10 524287
+30 0 2 0 16777215 10 524287
+31 0 4 0 16777215 10 524287
+32 0 0 0 0 20 20
+33 0 1 0 0 20 524287
+34 0 2 0 0 20 524287
+35 0 4 0 0 20 524287
+36 0 0 0 10 20 20
+37 0 1 0 10 20 524287
+38 0 2 0 10 20 524287
+39 0 4 0 10 20 524287
+40 0 0 0 20 20 20
+41 0 1 0 20 20 524287
+42 0 2 0 20 20 524287
+43 0 4 0 20 20 524287
+44 0 0 0 16777215 20 20
+45 0 1 0 16777215 20 524287
+46 0 2 0 16777215 20 524287
+47 0 4 0 16777215 20 524287
+48 0 0 0 0 16777215 0
+49 0 1 0 0 16777215 524287
+50 0 2 0 0 16777215 524287
+51 0 4 0 0 16777215 524287
+52 0 0 0 10 16777215 10
+53 0 1 0 10 16777215 524287
+54 0 2 0 10 16777215 524287
+55 0 4 0 10 16777215 524287
+56 0 0 0 20 16777215 20
+57 0 1 0 20 16777215 524287
+58 0 2 0 20 16777215 524287
+59 0 4 0 20 16777215 524287
+60 0 0 0 16777215 16777215 16777215
+61 0 1 0 16777215 16777215 524287
+62 0 2 0 16777215 16777215 524287
+63 0 4 0 16777215 16777215 524287
+64 0 0 10 0 0 0
+65 0 1 10 0 0 524287
+66 0 2 10 0 0 524287
+67 0 4 10 0 0 524287
+68 0 0 10 10 0 0
+69 0 1 10 10 0 524287
+70 0 2 10 10 0 524287
+71 0 4 10 10 0 524287
+72 0 0 10 20 0 0
+73 0 1 10 20 0 524287
+74 0 2 10 20 0 524287
+75 0 4 10 20 0 524287
+76 0 0 10 16777215 0 0
+77 0 1 10 16777215 0 524287
+78 0 2 10 16777215 0 524287
+79 0 4 10 16777215 0 524287
+80 0 0 10 0 10 10
+81 0 1 10 0 10 524287
+82 0 2 10 0 10 524287
+83 0 4 10 0 10 524287
+84 0 0 10 10 10 10
+85 0 1 10 10 10 524287
+86 0 2 10 10 10 524287
+87 0 4 10 10 10 524287
+88 0 0 10 20 10 10
+89 0 1 10 20 10 524287
+90 0 2 10 20 10 524287
+91 0 4 10 20 10 524287
+92 0 0 10 16777215 10 10
+93 0 1 10 16777215 10 524287
+94 0 2 10 16777215 10 524287
+95 0 4 10 16777215 10 524287
+96 0 0 10 0 20 20
+97 0 1 10 0 20 524287
+98 0 2 10 0 20 524287
+99 0 4 10 0 20 524287
+100 0 0 10 10 20 20
+101 0 1 10 10 20 524287
+102 0 2 10 10 20 524287
+103 0 4 10 10 20 524287
+104 0 0 10 20 20 20
+105 0 1 10 20 20 524287
+106 0 2 10 20 20 524287
+107 0 4 10 20 20 524287
+108 0 0 10 16777215 20 20
+109 0 1 10 16777215 20 524287
+110 0 2 10 16777215 20 524287
+111 0 4 10 16777215 20 524287
+112 0 0 10 0 16777215 10
+113 0 1 10 0 16777215 524287
+114 0 2 10 0 16777215 524287
+115 0 4 10 0 16777215 524287
+116 0 0 10 10 16777215 10
+117 0 1 10 10 16777215 524287
+118 0 2 10 10 16777215 524287
+119 0 4 10 10 16777215 524287
+120 0 0 10 20 16777215 20
+121 0 1 10 20 16777215 524287
+122 0 2 10 20 16777215 524287
+123 0 4 10 20 16777215 524287
+124 0 0 10 16777215 16777215 16777215
+125 0 1 10 16777215 16777215 524287
+126 0 2 10 16777215 16777215 524287
+127 0 4 10 16777215 16777215 524287
+128 0 0 20 0 0 0
+129 0 1 20 0 0 524287
+130 0 2 20 0 0 524287
+131 0 4 20 0 0 524287
+132 0 0 20 10 0 0
+133 0 1 20 10 0 524287
+134 0 2 20 10 0 524287
+135 0 4 20 10 0 524287
+136 0 0 20 20 0 0
+137 0 1 20 20 0 524287
+138 0 2 20 20 0 524287
+139 0 4 20 20 0 524287
+140 0 0 20 16777215 0 0
+141 0 1 20 16777215 0 524287
+142 0 2 20 16777215 0 524287
+143 0 4 20 16777215 0 524287
+144 0 0 20 0 10 10
+145 0 1 20 0 10 524287
+146 0 2 20 0 10 524287
+147 0 4 20 0 10 524287
+148 0 0 20 10 10 10
+149 0 1 20 10 10 524287
+150 0 2 20 10 10 524287
+151 0 4 20 10 10 524287
+152 0 0 20 20 10 10
+153 0 1 20 20 10 524287
+154 0 2 20 20 10 524287
+155 0 4 20 20 10 524287
+156 0 0 20 16777215 10 10
+157 0 1 20 16777215 10 524287
+158 0 2 20 16777215 10 524287
+159 0 4 20 16777215 10 524287
+160 0 0 20 0 20 20
+161 0 1 20 0 20 524287
+162 0 2 20 0 20 524287
+163 0 4 20 0 20 524287
+164 0 0 20 10 20 20
+165 0 1 20 10 20 524287
+166 0 2 20 10 20 524287
+167 0 4 20 10 20 524287
+168 0 0 20 20 20 20
+169 0 1 20 20 20 524287
+170 0 2 20 20 20 524287
+171 0 4 20 20 20 524287
+172 0 0 20 16777215 20 20
+173 0 1 20 16777215 20 524287
+174 0 2 20 16777215 20 524287
+175 0 4 20 16777215 20 524287
+176 0 0 20 0 16777215 20
+177 0 1 20 0 16777215 524287
+178 0 2 20 0 16777215 524287
+179 0 4 20 0 16777215 524287
+180 0 0 20 10 16777215 20
+181 0 1 20 10 16777215 524287
+182 0 2 20 10 16777215 524287
+183 0 4 20 10 16777215 524287
+184 0 0 20 20 16777215 20
+185 0 1 20 20 16777215 524287
+186 0 2 20 20 16777215 524287
+187 0 4 20 20 16777215 524287
+188 0 0 20 16777215 16777215 16777215
+189 0 1 20 16777215 16777215 524287
+190 0 2 20 16777215 16777215 524287
+191 0 4 20 16777215 16777215 524287
+192 0 0 16777215 0 0 0
+193 0 1 16777215 0 0 524287
+194 0 2 16777215 0 0 524287
+195 0 4 16777215 0 0 524287
+196 0 0 16777215 10 0 0
+197 0 1 16777215 10 0 524287
+198 0 2 16777215 10 0 524287
+199 0 4 16777215 10 0 524287
+200 0 0 16777215 20 0 0
+201 0 1 16777215 20 0 524287
+202 0 2 16777215 20 0 524287
+203 0 4 16777215 20 0 524287
+204 0 0 16777215 16777215 0 0
+205 0 1 16777215 16777215 0 524287
+206 0 2 16777215 16777215 0 524287
+207 0 4 16777215 16777215 0 524287
+208 0 0 16777215 0 10 10
+209 0 1 16777215 0 10 524287
+210 0 2 16777215 0 10 524287
+211 0 4 16777215 0 10 524287
+212 0 0 16777215 10 10 10
+213 0 1 16777215 10 10 524287
+214 0 2 16777215 10 10 524287
+215 0 4 16777215 10 10 524287
+216 0 0 16777215 20 10 10
+217 0 1 16777215 20 10 524287
+218 0 2 16777215 20 10 524287
+219 0 4 16777215 20 10 524287
+220 0 0 16777215 16777215 10 10
+221 0 1 16777215 16777215 10 524287
+222 0 2 16777215 16777215 10 524287
+223 0 4 16777215 16777215 10 524287
+224 0 0 16777215 0 20 20
+225 0 1 16777215 0 20 524287
+226 0 2 16777215 0 20 524287
+227 0 4 16777215 0 20 524287
+228 0 0 16777215 10 20 20
+229 0 1 16777215 10 20 524287
+230 0 2 16777215 10 20 524287
+231 0 4 16777215 10 20 524287
+232 0 0 16777215 20 20 20
+233 0 1 16777215 20 20 524287
+234 0 2 16777215 20 20 524287
+235 0 4 16777215 20 20 524287
+236 0 0 16777215 16777215 20 20
+237 0 1 16777215 16777215 20 524287
+238 0 2 16777215 16777215 20 524287
+239 0 4 16777215 16777215 20 524287
+240 0 0 16777215 0 16777215 16777215
+241 0 1 16777215 0 16777215 524287
+242 0 2 16777215 0 16777215 524287
+243 0 4 16777215 0 16777215 524287
+244 0 0 16777215 10 16777215 16777215
+245 0 1 16777215 10 16777215 524287
+246 0 2 16777215 10 16777215 524287
+247 0 4 16777215 10 16777215 524287
+248 0 0 16777215 20 16777215 16777215
+249 0 1 16777215 20 16777215 524287
+250 0 2 16777215 20 16777215 524287
+251 0 4 16777215 20 16777215 524287
+252 0 0 16777215 16777215 16777215 16777215
+253 0 1 16777215 16777215 16777215 524287
+254 0 2 16777215 16777215 16777215 524287
+255 0 4 16777215 16777215 16777215 524287
+256 1 0 0 0 0 0
+257 1 1 0 0 0 524287
+258 1 2 0 0 0 524287
+259 1 4 0 0 0 524287
+260 1 0 0 10 0 0
+261 1 1 0 10 0 524287
+262 1 2 0 10 0 524287
+263 1 4 0 10 0 524287
+264 1 0 0 20 0 0
+265 1 1 0 20 0 524287
+266 1 2 0 20 0 524287
+267 1 4 0 20 0 524287
+268 1 0 0 16777215 0 0
+269 1 1 0 16777215 0 524287
+270 1 2 0 16777215 0 524287
+271 1 4 0 16777215 0 524287
+272 1 0 0 0 10 10
+273 1 1 0 0 10 524287
+274 1 2 0 0 10 524287
+275 1 4 0 0 10 524287
+276 1 0 0 10 10 10
+277 1 1 0 10 10 524287
+278 1 2 0 10 10 524287
+279 1 4 0 10 10 524287
+280 1 0 0 20 10 10
+281 1 1 0 20 10 524287
+282 1 2 0 20 10 524287
+283 1 4 0 20 10 524287
+284 1 0 0 16777215 10 10
+285 1 1 0 16777215 10 524287
+286 1 2 0 16777215 10 524287
+287 1 4 0 16777215 10 524287
+288 1 0 0 0 20 20
+289 1 1 0 0 20 524287
+290 1 2 0 0 20 524287
+291 1 4 0 0 20 524287
+292 1 0 0 10 20 20
+293 1 1 0 10 20 524287
+294 1 2 0 10 20 524287
+295 1 4 0 10 20 524287
+296 1 0 0 20 20 20
+297 1 1 0 20 20 524287
+298 1 2 0 20 20 524287
+299 1 4 0 20 20 524287
+300 1 0 0 16777215 20 20
+301 1 1 0 16777215 20 524287
+302 1 2 0 16777215 20 524287
+303 1 4 0 16777215 20 524287
+304 1 0 0 0 16777215 16777215
+305 1 1 0 0 16777215 524287
+306 1 2 0 0 16777215 524287
+307 1 4 0 0 16777215 524287
+308 1 0 0 10 16777215 16777215
+309 1 1 0 10 16777215 524287
+310 1 2 0 10 16777215 524287
+311 1 4 0 10 16777215 524287
+312 1 0 0 20 16777215 16777215
+313 1 1 0 20 16777215 524287
+314 1 2 0 20 16777215 524287
+315 1 4 0 20 16777215 524287
+316 1 0 0 16777215 16777215 16777215
+317 1 1 0 16777215 16777215 524287
+318 1 2 0 16777215 16777215 524287
+319 1 4 0 16777215 16777215 524287
+320 1 0 10 0 0 0
+321 1 1 10 0 0 524287
+322 1 2 10 0 0 524287
+323 1 4 10 0 0 524287
+324 1 0 10 10 0 0
+325 1 1 10 10 0 524287
+326 1 2 10 10 0 524287
+327 1 4 10 10 0 524287
+328 1 0 10 20 0 0
+329 1 1 10 20 0 524287
+330 1 2 10 20 0 524287
+331 1 4 10 20 0 524287
+332 1 0 10 16777215 0 0
+333 1 1 10 16777215 0 524287
+334 1 2 10 16777215 0 524287
+335 1 4 10 16777215 0 524287
+336 1 0 10 0 10 10
+337 1 1 10 0 10 524287
+338 1 2 10 0 10 524287
+339 1 4 10 0 10 524287
+340 1 0 10 10 10 10
+341 1 1 10 10 10 524287
+342 1 2 10 10 10 524287
+343 1 4 10 10 10 524287
+344 1 0 10 20 10 10
+345 1 1 10 20 10 524287
+346 1 2 10 20 10 524287
+347 1 4 10 20 10 524287
+348 1 0 10 16777215 10 10
+349 1 1 10 16777215 10 524287
+350 1 2 10 16777215 10 524287
+351 1 4 10 16777215 10 524287
+352 1 0 10 0 20 20
+353 1 1 10 0 20 524287
+354 1 2 10 0 20 524287
+355 1 4 10 0 20 524287
+356 1 0 10 10 20 20
+357 1 1 10 10 20 524287
+358 1 2 10 10 20 524287
+359 1 4 10 10 20 524287
+360 1 0 10 20 20 20
+361 1 1 10 20 20 524287
+362 1 2 10 20 20 524287
+363 1 4 10 20 20 524287
+364 1 0 10 16777215 20 20
+365 1 1 10 16777215 20 524287
+366 1 2 10 16777215 20 524287
+367 1 4 10 16777215 20 524287
+368 1 0 10 0 16777215 16777215
+369 1 1 10 0 16777215 524287
+370 1 2 10 0 16777215 524287
+371 1 4 10 0 16777215 524287
+372 1 0 10 10 16777215 16777215
+373 1 1 10 10 16777215 524287
+374 1 2 10 10 16777215 524287
+375 1 4 10 10 16777215 524287
+376 1 0 10 20 16777215 16777215
+377 1 1 10 20 16777215 524287
+378 1 2 10 20 16777215 524287
+379 1 4 10 20 16777215 524287
+380 1 0 10 16777215 16777215 16777215
+381 1 1 10 16777215 16777215 524287
+382 1 2 10 16777215 16777215 524287
+383 1 4 10 16777215 16777215 524287
+384 1 0 20 0 0 0
+385 1 1 20 0 0 524287
+386 1 2 20 0 0 524287
+387 1 4 20 0 0 524287
+388 1 0 20 10 0 0
+389 1 1 20 10 0 524287
+390 1 2 20 10 0 524287
+391 1 4 20 10 0 524287
+392 1 0 20 20 0 0
+393 1 1 20 20 0 524287
+394 1 2 20 20 0 524287
+395 1 4 20 20 0 524287
+396 1 0 20 16777215 0 0
+397 1 1 20 16777215 0 524287
+398 1 2 20 16777215 0 524287
+399 1 4 20 16777215 0 524287
+400 1 0 20 0 10 10
+401 1 1 20 0 10 524287
+402 1 2 20 0 10 524287
+403 1 4 20 0 10 524287
+404 1 0 20 10 10 10
+405 1 1 20 10 10 524287
+406 1 2 20 10 10 524287
+407 1 4 20 10 10 524287
+408 1 0 20 20 10 10
+409 1 1 20 20 10 524287
+410 1 2 20 20 10 524287
+411 1 4 20 20 10 524287
+412 1 0 20 16777215 10 10
+413 1 1 20 16777215 10 524287
+414 1 2 20 16777215 10 524287
+415 1 4 20 16777215 10 524287
+416 1 0 20 0 20 20
+417 1 1 20 0 20 524287
+418 1 2 20 0 20 524287
+419 1 4 20 0 20 524287
+420 1 0 20 10 20 20
+421 1 1 20 10 20 524287
+422 1 2 20 10 20 524287
+423 1 4 20 10 20 524287
+424 1 0 20 20 20 20
+425 1 1 20 20 20 524287
+426 1 2 20 20 20 524287
+427 1 4 20 20 20 524287
+428 1 0 20 16777215 20 20
+429 1 1 20 16777215 20 524287
+430 1 2 20 16777215 20 524287
+431 1 4 20 16777215 20 524287
+432 1 0 20 0 16777215 16777215
+433 1 1 20 0 16777215 524287
+434 1 2 20 0 16777215 524287
+435 1 4 20 0 16777215 524287
+436 1 0 20 10 16777215 16777215
+437 1 1 20 10 16777215 524287
+438 1 2 20 10 16777215 524287
+439 1 4 20 10 16777215 524287
+440 1 0 20 20 16777215 16777215
+441 1 1 20 20 16777215 524287
+442 1 2 20 20 16777215 524287
+443 1 4 20 20 16777215 524287
+444 1 0 20 16777215 16777215 16777215
+445 1 1 20 16777215 16777215 524287
+446 1 2 20 16777215 16777215 524287
+447 1 4 20 16777215 16777215 524287
+448 1 0 16777215 0 0 0
+449 1 1 16777215 0 0 524287
+450 1 2 16777215 0 0 524287
+451 1 4 16777215 0 0 524287
+452 1 0 16777215 10 0 0
+453 1 1 16777215 10 0 524287
+454 1 2 16777215 10 0 524287
+455 1 4 16777215 10 0 524287
+456 1 0 16777215 20 0 0
+457 1 1 16777215 20 0 524287
+458 1 2 16777215 20 0 524287
+459 1 4 16777215 20 0 524287
+460 1 0 16777215 16777215 0 0
+461 1 1 16777215 16777215 0 524287
+462 1 2 16777215 16777215 0 524287
+463 1 4 16777215 16777215 0 524287
+464 1 0 16777215 0 10 10
+465 1 1 16777215 0 10 524287
+466 1 2 16777215 0 10 524287
+467 1 4 16777215 0 10 524287
+468 1 0 16777215 10 10 10
+469 1 1 16777215 10 10 524287
+470 1 2 16777215 10 10 524287
+471 1 4 16777215 10 10 524287
+472 1 0 16777215 20 10 10
+473 1 1 16777215 20 10 524287
+474 1 2 16777215 20 10 524287
+475 1 4 16777215 20 10 524287
+476 1 0 16777215 16777215 10 10
+477 1 1 16777215 16777215 10 524287
+478 1 2 16777215 16777215 10 524287
+479 1 4 16777215 16777215 10 524287
+480 1 0 16777215 0 20 20
+481 1 1 16777215 0 20 524287
+482 1 2 16777215 0 20 524287
+483 1 4 16777215 0 20 524287
+484 1 0 16777215 10 20 20
+485 1 1 16777215 10 20 524287
+486 1 2 16777215 10 20 524287
+487 1 4 16777215 10 20 524287
+488 1 0 16777215 20 20 20
+489 1 1 16777215 20 20 524287
+490 1 2 16777215 20 20 524287
+491 1 4 16777215 20 20 524287
+492 1 0 16777215 16777215 20 20
+493 1 1 16777215 16777215 20 524287
+494 1 2 16777215 16777215 20 524287
+495 1 4 16777215 16777215 20 524287
+496 1 0 16777215 0 16777215 16777215
+497 1 1 16777215 0 16777215 524287
+498 1 2 16777215 0 16777215 524287
+499 1 4 16777215 0 16777215 524287
+500 1 0 16777215 10 16777215 16777215
+501 1 1 16777215 10 16777215 524287
+502 1 2 16777215 10 16777215 524287
+503 1 4 16777215 10 16777215 524287
+504 1 0 16777215 20 16777215 16777215
+505 1 1 16777215 20 16777215 524287
+506 1 2 16777215 20 16777215 524287
+507 1 4 16777215 20 16777215 524287
+508 1 0 16777215 16777215 16777215 16777215
+509 1 1 16777215 16777215 16777215 524287
+510 1 2 16777215 16777215 16777215 524287
+511 1 4 16777215 16777215 16777215 524287
+512 4 0 0 0 0 0
+513 4 1 0 0 0 524287
+514 4 2 0 0 0 524287
+515 4 4 0 0 0 524287
+516 4 0 0 10 0 0
+517 4 1 0 10 0 524287
+518 4 2 0 10 0 524287
+519 4 4 0 10 0 524287
+520 4 0 0 20 0 0
+521 4 1 0 20 0 524287
+522 4 2 0 20 0 524287
+523 4 4 0 20 0 524287
+524 4 0 0 16777215 0 0
+525 4 1 0 16777215 0 524287
+526 4 2 0 16777215 0 524287
+527 4 4 0 16777215 0 524287
+528 4 0 0 0 10 10
+529 4 1 0 0 10 524287
+530 4 2 0 0 10 524287
+531 4 4 0 0 10 524287
+532 4 0 0 10 10 10
+533 4 1 0 10 10 524287
+534 4 2 0 10 10 524287
+535 4 4 0 10 10 524287
+536 4 0 0 20 10 10
+537 4 1 0 20 10 524287
+538 4 2 0 20 10 524287
+539 4 4 0 20 10 524287
+540 4 0 0 16777215 10 10
+541 4 1 0 16777215 10 524287
+542 4 2 0 16777215 10 524287
+543 4 4 0 16777215 10 524287
+544 4 0 0 0 20 20
+545 4 1 0 0 20 524287
+546 4 2 0 0 20 524287
+547 4 4 0 0 20 524287
+548 4 0 0 10 20 20
+549 4 1 0 10 20 524287
+550 4 2 0 10 20 524287
+551 4 4 0 10 20 524287
+552 4 0 0 20 20 20
+553 4 1 0 20 20 524287
+554 4 2 0 20 20 524287
+555 4 4 0 20 20 524287
+556 4 0 0 16777215 20 20
+557 4 1 0 16777215 20 524287
+558 4 2 0 16777215 20 524287
+559 4 4 0 16777215 20 524287
+560 4 0 0 0 16777215 0
+561 4 1 0 0 16777215 524287
+562 4 2 0 0 16777215 524287
+563 4 4 0 0 16777215 524287
+564 4 0 0 10 16777215 10
+565 4 1 0 10 16777215 524287
+566 4 2 0 10 16777215 524287
+567 4 4 0 10 16777215 524287
+568 4 0 0 20 16777215 20
+569 4 1 0 20 16777215 524287
+570 4 2 0 20 16777215 524287
+571 4 4 0 20 16777215 524287
+572 4 0 0 16777215 16777215 16777215
+573 4 1 0 16777215 16777215 524287
+574 4 2 0 16777215 16777215 524287
+575 4 4 0 16777215 16777215 524287
+576 4 0 10 0 0 0
+577 4 1 10 0 0 524287
+578 4 2 10 0 0 524287
+579 4 4 10 0 0 524287
+580 4 0 10 10 0 0
+581 4 1 10 10 0 524287
+582 4 2 10 10 0 524287
+583 4 4 10 10 0 524287
+584 4 0 10 20 0 0
+585 4 1 10 20 0 524287
+586 4 2 10 20 0 524287
+587 4 4 10 20 0 524287
+588 4 0 10 16777215 0 0
+589 4 1 10 16777215 0 524287
+590 4 2 10 16777215 0 524287
+591 4 4 10 16777215 0 524287
+592 4 0 10 0 10 10
+593 4 1 10 0 10 524287
+594 4 2 10 0 10 524287
+595 4 4 10 0 10 524287
+596 4 0 10 10 10 10
+597 4 1 10 10 10 524287
+598 4 2 10 10 10 524287
+599 4 4 10 10 10 524287
+600 4 0 10 20 10 10
+601 4 1 10 20 10 524287
+602 4 2 10 20 10 524287
+603 4 4 10 20 10 524287
+604 4 0 10 16777215 10 10
+605 4 1 10 16777215 10 524287
+606 4 2 10 16777215 10 524287
+607 4 4 10 16777215 10 524287
+608 4 0 10 0 20 20
+609 4 1 10 0 20 524287
+610 4 2 10 0 20 524287
+611 4 4 10 0 20 524287
+612 4 0 10 10 20 20
+613 4 1 10 10 20 524287
+614 4 2 10 10 20 524287
+615 4 4 10 10 20 524287
+616 4 0 10 20 20 20
+617 4 1 10 20 20 524287
+618 4 2 10 20 20 524287
+619 4 4 10 20 20 524287
+620 4 0 10 16777215 20 20
+621 4 1 10 16777215 20 524287
+622 4 2 10 16777215 20 524287
+623 4 4 10 16777215 20 524287
+624 4 0 10 0 16777215 10
+625 4 1 10 0 16777215 524287
+626 4 2 10 0 16777215 524287
+627 4 4 10 0 16777215 524287
+628 4 0 10 10 16777215 10
+629 4 1 10 10 16777215 524287
+630 4 2 10 10 16777215 524287
+631 4 4 10 10 16777215 524287
+632 4 0 10 20 16777215 20
+633 4 1 10 20 16777215 524287
+634 4 2 10 20 16777215 524287
+635 4 4 10 20 16777215 524287
+636 4 0 10 16777215 16777215 16777215
+637 4 1 10 16777215 16777215 524287
+638 4 2 10 16777215 16777215 524287
+639 4 4 10 16777215 16777215 524287
+640 4 0 20 0 0 0
+641 4 1 20 0 0 524287
+642 4 2 20 0 0 524287
+643 4 4 20 0 0 524287
+644 4 0 20 10 0 0
+645 4 1 20 10 0 524287
+646 4 2 20 10 0 524287
+647 4 4 20 10 0 524287
+648 4 0 20 20 0 0
+649 4 1 20 20 0 524287
+650 4 2 20 20 0 524287
+651 4 4 20 20 0 524287
+652 4 0 20 16777215 0 0
+653 4 1 20 16777215 0 524287
+654 4 2 20 16777215 0 524287
+655 4 4 20 16777215 0 524287
+656 4 0 20 0 10 10
+657 4 1 20 0 10 524287
+658 4 2 20 0 10 524287
+659 4 4 20 0 10 524287
+660 4 0 20 10 10 10
+661 4 1 20 10 10 524287
+662 4 2 20 10 10 524287
+663 4 4 20 10 10 524287
+664 4 0 20 20 10 10
+665 4 1 20 20 10 524287
+666 4 2 20 20 10 524287
+667 4 4 20 20 10 524287
+668 4 0 20 16777215 10 10
+669 4 1 20 16777215 10 524287
+670 4 2 20 16777215 10 524287
+671 4 4 20 16777215 10 524287
+672 4 0 20 0 20 20
+673 4 1 20 0 20 524287
+674 4 2 20 0 20 524287
+675 4 4 20 0 20 524287
+676 4 0 20 10 20 20
+677 4 1 20 10 20 524287
+678 4 2 20 10 20 524287
+679 4 4 20 10 20 524287
+680 4 0 20 20 20 20
+681 4 1 20 20 20 524287
+682 4 2 20 20 20 524287
+683 4 4 20 20 20 524287
+684 4 0 20 16777215 20 20
+685 4 1 20 16777215 20 524287
+686 4 2 20 16777215 20 524287
+687 4 4 20 16777215 20 524287
+688 4 0 20 0 16777215 20
+689 4 1 20 0 16777215 524287
+690 4 2 20 0 16777215 524287
+691 4 4 20 0 16777215 524287
+692 4 0 20 10 16777215 20
+693 4 1 20 10 16777215 524287
+694 4 2 20 10 16777215 524287
+695 4 4 20 10 16777215 524287
+696 4 0 20 20 16777215 20
+697 4 1 20 20 16777215 524287
+698 4 2 20 20 16777215 524287
+699 4 4 20 20 16777215 524287
+700 4 0 20 16777215 16777215 16777215
+701 4 1 20 16777215 16777215 524287
+702 4 2 20 16777215 16777215 524287
+703 4 4 20 16777215 16777215 524287
+704 4 0 16777215 0 0 0
+705 4 1 16777215 0 0 524287
+706 4 2 16777215 0 0 524287
+707 4 4 16777215 0 0 524287
+708 4 0 16777215 10 0 0
+709 4 1 16777215 10 0 524287
+710 4 2 16777215 10 0 524287
+711 4 4 16777215 10 0 524287
+712 4 0 16777215 20 0 0
+713 4 1 16777215 20 0 524287
+714 4 2 16777215 20 0 524287
+715 4 4 16777215 20 0 524287
+716 4 0 16777215 16777215 0 0
+717 4 1 16777215 16777215 0 524287
+718 4 2 16777215 16777215 0 524287
+719 4 4 16777215 16777215 0 524287
+720 4 0 16777215 0 10 10
+721 4 1 16777215 0 10 524287
+722 4 2 16777215 0 10 524287
+723 4 4 16777215 0 10 524287
+724 4 0 16777215 10 10 10
+725 4 1 16777215 10 10 524287
+726 4 2 16777215 10 10 524287
+727 4 4 16777215 10 10 524287
+728 4 0 16777215 20 10 10
+729 4 1 16777215 20 10 524287
+730 4 2 16777215 20 10 524287
+731 4 4 16777215 20 10 524287
+732 4 0 16777215 16777215 10 10
+733 4 1 16777215 16777215 10 524287
+734 4 2 16777215 16777215 10 524287
+735 4 4 16777215 16777215 10 524287
+736 4 0 16777215 0 20 20
+737 4 1 16777215 0 20 524287
+738 4 2 16777215 0 20 524287
+739 4 4 16777215 0 20 524287
+740 4 0 16777215 10 20 20
+741 4 1 16777215 10 20 524287
+742 4 2 16777215 10 20 524287
+743 4 4 16777215 10 20 524287
+744 4 0 16777215 20 20 20
+745 4 1 16777215 20 20 524287
+746 4 2 16777215 20 20 524287
+747 4 4 16777215 20 20 524287
+748 4 0 16777215 16777215 20 20
+749 4 1 16777215 16777215 20 524287
+750 4 2 16777215 16777215 20 524287
+751 4 4 16777215 16777215 20 524287
+752 4 0 16777215 0 16777215 16777215
+753 4 1 16777215 0 16777215 524287
+754 4 2 16777215 0 16777215 524287
+755 4 4 16777215 0 16777215 524287
+756 4 0 16777215 10 16777215 16777215
+757 4 1 16777215 10 16777215 524287
+758 4 2 16777215 10 16777215 524287
+759 4 4 16777215 10 16777215 524287
+760 4 0 16777215 20 16777215 16777215
+761 4 1 16777215 20 16777215 524287
+762 4 2 16777215 20 16777215 524287
+763 4 4 16777215 20 16777215 524287
+764 4 0 16777215 16777215 16777215 16777215
+765 4 1 16777215 16777215 16777215 524287
+766 4 2 16777215 16777215 16777215 524287
+767 4 4 16777215 16777215 16777215 524287
+768 5 0 0 0 0 0
+769 5 1 0 0 0 524287
+770 5 2 0 0 0 524287
+771 5 4 0 0 0 524287
+772 5 0 0 10 0 0
+773 5 1 0 10 0 524287
+774 5 2 0 10 0 524287
+775 5 4 0 10 0 524287
+776 5 0 0 20 0 0
+777 5 1 0 20 0 524287
+778 5 2 0 20 0 524287
+779 5 4 0 20 0 524287
+780 5 0 0 16777215 0 0
+781 5 1 0 16777215 0 524287
+782 5 2 0 16777215 0 524287
+783 5 4 0 16777215 0 524287
+784 5 0 0 0 10 10
+785 5 1 0 0 10 524287
+786 5 2 0 0 10 524287
+787 5 4 0 0 10 524287
+788 5 0 0 10 10 10
+789 5 1 0 10 10 524287
+790 5 2 0 10 10 524287
+791 5 4 0 10 10 524287
+792 5 0 0 20 10 10
+793 5 1 0 20 10 524287
+794 5 2 0 20 10 524287
+795 5 4 0 20 10 524287
+796 5 0 0 16777215 10 10
+797 5 1 0 16777215 10 524287
+798 5 2 0 16777215 10 524287
+799 5 4 0 16777215 10 524287
+800 5 0 0 0 20 20
+801 5 1 0 0 20 524287
+802 5 2 0 0 20 524287
+803 5 4 0 0 20 524287
+804 5 0 0 10 20 20
+805 5 1 0 10 20 524287
+806 5 2 0 10 20 524287
+807 5 4 0 10 20 524287
+808 5 0 0 20 20 20
+809 5 1 0 20 20 524287
+810 5 2 0 20 20 524287
+811 5 4 0 20 20 524287
+812 5 0 0 16777215 20 20
+813 5 1 0 16777215 20 524287
+814 5 2 0 16777215 20 524287
+815 5 4 0 16777215 20 524287
+816 5 0 0 0 16777215 16777215
+817 5 1 0 0 16777215 524287
+818 5 2 0 0 16777215 524287
+819 5 4 0 0 16777215 524287
+820 5 0 0 10 16777215 16777215
+821 5 1 0 10 16777215 524287
+822 5 2 0 10 16777215 524287
+823 5 4 0 10 16777215 524287
+824 5 0 0 20 16777215 16777215
+825 5 1 0 20 16777215 524287
+826 5 2 0 20 16777215 524287
+827 5 4 0 20 16777215 524287
+828 5 0 0 16777215 16777215 16777215
+829 5 1 0 16777215 16777215 524287
+830 5 2 0 16777215 16777215 524287
+831 5 4 0 16777215 16777215 524287
+832 5 0 10 0 0 0
+833 5 1 10 0 0 524287
+834 5 2 10 0 0 524287
+835 5 4 10 0 0 524287
+836 5 0 10 10 0 0
+837 5 1 10 10 0 524287
+838 5 2 10 10 0 524287
+839 5 4 10 10 0 524287
+840 5 0 10 20 0 0
+841 5 1 10 20 0 524287
+842 5 2 10 20 0 524287
+843 5 4 10 20 0 524287
+844 5 0 10 16777215 0 0
+845 5 1 10 16777215 0 524287
+846 5 2 10 16777215 0 524287
+847 5 4 10 16777215 0 524287
+848 5 0 10 0 10 10
+849 5 1 10 0 10 524287
+850 5 2 10 0 10 524287
+851 5 4 10 0 10 524287
+852 5 0 10 10 10 10
+853 5 1 10 10 10 524287
+854 5 2 10 10 10 524287
+855 5 4 10 10 10 524287
+856 5 0 10 20 10 10
+857 5 1 10 20 10 524287
+858 5 2 10 20 10 524287
+859 5 4 10 20 10 524287
+860 5 0 10 16777215 10 10
+861 5 1 10 16777215 10 524287
+862 5 2 10 16777215 10 524287
+863 5 4 10 16777215 10 524287
+864 5 0 10 0 20 20
+865 5 1 10 0 20 524287
+866 5 2 10 0 20 524287
+867 5 4 10 0 20 524287
+868 5 0 10 10 20 20
+869 5 1 10 10 20 524287
+870 5 2 10 10 20 524287
+871 5 4 10 10 20 524287
+872 5 0 10 20 20 20
+873 5 1 10 20 20 524287
+874 5 2 10 20 20 524287
+875 5 4 10 20 20 524287
+876 5 0 10 16777215 20 20
+877 5 1 10 16777215 20 524287
+878 5 2 10 16777215 20 524287
+879 5 4 10 16777215 20 524287
+880 5 0 10 0 16777215 16777215
+881 5 1 10 0 16777215 524287
+882 5 2 10 0 16777215 524287
+883 5 4 10 0 16777215 524287
+884 5 0 10 10 16777215 16777215
+885 5 1 10 10 16777215 524287
+886 5 2 10 10 16777215 524287
+887 5 4 10 10 16777215 524287
+888 5 0 10 20 16777215 16777215
+889 5 1 10 20 16777215 524287
+890 5 2 10 20 16777215 524287
+891 5 4 10 20 16777215 524287
+892 5 0 10 16777215 16777215 16777215
+893 5 1 10 16777215 16777215 524287
+894 5 2 10 16777215 16777215 524287
+895 5 4 10 16777215 16777215 524287
+896 5 0 20 0 0 0
+897 5 1 20 0 0 524287
+898 5 2 20 0 0 524287
+899 5 4 20 0 0 524287
+900 5 0 20 10 0 0
+901 5 1 20 10 0 524287
+902 5 2 20 10 0 524287
+903 5 4 20 10 0 524287
+904 5 0 20 20 0 0
+905 5 1 20 20 0 524287
+906 5 2 20 20 0 524287
+907 5 4 20 20 0 524287
+908 5 0 20 16777215 0 0
+909 5 1 20 16777215 0 524287
+910 5 2 20 16777215 0 524287
+911 5 4 20 16777215 0 524287
+912 5 0 20 0 10 10
+913 5 1 20 0 10 524287
+914 5 2 20 0 10 524287
+915 5 4 20 0 10 524287
+916 5 0 20 10 10 10
+917 5 1 20 10 10 524287
+918 5 2 20 10 10 524287
+919 5 4 20 10 10 524287
+920 5 0 20 20 10 10
+921 5 1 20 20 10 524287
+922 5 2 20 20 10 524287
+923 5 4 20 20 10 524287
+924 5 0 20 16777215 10 10
+925 5 1 20 16777215 10 524287
+926 5 2 20 16777215 10 524287
+927 5 4 20 16777215 10 524287
+928 5 0 20 0 20 20
+929 5 1 20 0 20 524287
+930 5 2 20 0 20 524287
+931 5 4 20 0 20 524287
+932 5 0 20 10 20 20
+933 5 1 20 10 20 524287
+934 5 2 20 10 20 524287
+935 5 4 20 10 20 524287
+936 5 0 20 20 20 20
+937 5 1 20 20 20 524287
+938 5 2 20 20 20 524287
+939 5 4 20 20 20 524287
+940 5 0 20 16777215 20 20
+941 5 1 20 16777215 20 524287
+942 5 2 20 16777215 20 524287
+943 5 4 20 16777215 20 524287
+944 5 0 20 0 16777215 16777215
+945 5 1 20 0 16777215 524287
+946 5 2 20 0 16777215 524287
+947 5 4 20 0 16777215 524287
+948 5 0 20 10 16777215 16777215
+949 5 1 20 10 16777215 524287
+950 5 2 20 10 16777215 524287
+951 5 4 20 10 16777215 524287
+952 5 0 20 20 16777215 16777215
+953 5 1 20 20 16777215 524287
+954 5 2 20 20 16777215 524287
+955 5 4 20 20 16777215 524287
+956 5 0 20 16777215 16777215 16777215
+957 5 1 20 16777215 16777215 524287
+958 5 2 20 16777215 16777215 524287
+959 5 4 20 16777215 16777215 524287
+960 5 0 16777215 0 0 0
+961 5 1 16777215 0 0 524287
+962 5 2 16777215 0 0 524287
+963 5 4 16777215 0 0 524287
+964 5 0 16777215 10 0 0
+965 5 1 16777215 10 0 524287
+966 5 2 16777215 10 0 524287
+967 5 4 16777215 10 0 524287
+968 5 0 16777215 20 0 0
+969 5 1 16777215 20 0 524287
+970 5 2 16777215 20 0 524287
+971 5 4 16777215 20 0 524287
+972 5 0 16777215 16777215 0 0
+973 5 1 16777215 16777215 0 524287
+974 5 2 16777215 16777215 0 524287
+975 5 4 16777215 16777215 0 524287
+976 5 0 16777215 0 10 10
+977 5 1 16777215 0 10 524287
+978 5 2 16777215 0 10 524287
+979 5 4 16777215 0 10 524287
+980 5 0 16777215 10 10 10
+981 5 1 16777215 10 10 524287
+982 5 2 16777215 10 10 524287
+983 5 4 16777215 10 10 524287
+984 5 0 16777215 20 10 10
+985 5 1 16777215 20 10 524287
+986 5 2 16777215 20 10 524287
+987 5 4 16777215 20 10 524287
+988 5 0 16777215 16777215 10 10
+989 5 1 16777215 16777215 10 524287
+990 5 2 16777215 16777215 10 524287
+991 5 4 16777215 16777215 10 524287
+992 5 0 16777215 0 20 20
+993 5 1 16777215 0 20 524287
+994 5 2 16777215 0 20 524287
+995 5 4 16777215 0 20 524287
+996 5 0 16777215 10 20 20
+997 5 1 16777215 10 20 524287
+998 5 2 16777215 10 20 524287
+999 5 4 16777215 10 20 524287
+1000 5 0 16777215 20 20 20
+1001 5 1 16777215 20 20 524287
+1002 5 2 16777215 20 20 524287
+1003 5 4 16777215 20 20 524287
+1004 5 0 16777215 16777215 20 20
+1005 5 1 16777215 16777215 20 524287
+1006 5 2 16777215 16777215 20 524287
+1007 5 4 16777215 16777215 20 524287
+1008 5 0 16777215 0 16777215 16777215
+1009 5 1 16777215 0 16777215 524287
+1010 5 2 16777215 0 16777215 524287
+1011 5 4 16777215 0 16777215 524287
+1012 5 0 16777215 10 16777215 16777215
+1013 5 1 16777215 10 16777215 524287
+1014 5 2 16777215 10 16777215 524287
+1015 5 4 16777215 10 16777215 524287
+1016 5 0 16777215 20 16777215 16777215
+1017 5 1 16777215 20 16777215 524287
+1018 5 2 16777215 20 16777215 524287
+1019 5 4 16777215 20 16777215 524287
+1020 5 0 16777215 16777215 16777215 16777215
+1021 5 1 16777215 16777215 16777215 524287
+1022 5 2 16777215 16777215 16777215 524287
+1023 5 4 16777215 16777215 16777215 524287
+1024 7 0 0 0 0 0
+1025 7 1 0 0 0 524287
+1026 7 2 0 0 0 524287
+1027 7 4 0 0 0 524287
+1028 7 0 0 10 0 0
+1029 7 1 0 10 0 524287
+1030 7 2 0 10 0 524287
+1031 7 4 0 10 0 524287
+1032 7 0 0 20 0 0
+1033 7 1 0 20 0 524287
+1034 7 2 0 20 0 524287
+1035 7 4 0 20 0 524287
+1036 7 0 0 16777215 0 0
+1037 7 1 0 16777215 0 524287
+1038 7 2 0 16777215 0 524287
+1039 7 4 0 16777215 0 524287
+1040 7 0 0 0 10 10
+1041 7 1 0 0 10 524287
+1042 7 2 0 0 10 524287
+1043 7 4 0 0 10 524287
+1044 7 0 0 10 10 10
+1045 7 1 0 10 10 524287
+1046 7 2 0 10 10 524287
+1047 7 4 0 10 10 524287
+1048 7 0 0 20 10 10
+1049 7 1 0 20 10 524287
+1050 7 2 0 20 10 524287
+1051 7 4 0 20 10 524287
+1052 7 0 0 16777215 10 10
+1053 7 1 0 16777215 10 524287
+1054 7 2 0 16777215 10 524287
+1055 7 4 0 16777215 10 524287
+1056 7 0 0 0 20 20
+1057 7 1 0 0 20 524287
+1058 7 2 0 0 20 524287
+1059 7 4 0 0 20 524287
+1060 7 0 0 10 20 20
+1061 7 1 0 10 20 524287
+1062 7 2 0 10 20 524287
+1063 7 4 0 10 20 524287
+1064 7 0 0 20 20 20
+1065 7 1 0 20 20 524287
+1066 7 2 0 20 20 524287
+1067 7 4 0 20 20 524287
+1068 7 0 0 16777215 20 20
+1069 7 1 0 16777215 20 524287
+1070 7 2 0 16777215 20 524287
+1071 7 4 0 16777215 20 524287
+1072 7 0 0 0 16777215 16777215
+1073 7 1 0 0 16777215 524287
+1074 7 2 0 0 16777215 524287
+1075 7 4 0 0 16777215 524287
+1076 7 0 0 10 16777215 16777215
+1077 7 1 0 10 16777215 524287
+1078 7 2 0 10 16777215 524287
+1079 7 4 0 10 16777215 524287
+1080 7 0 0 20 16777215 16777215
+1081 7 1 0 20 16777215 524287
+1082 7 2 0 20 16777215 524287
+1083 7 4 0 20 16777215 524287
+1084 7 0 0 16777215 16777215 16777215
+1085 7 1 0 16777215 16777215 524287
+1086 7 2 0 16777215 16777215 524287
+1087 7 4 0 16777215 16777215 524287
+1088 7 0 10 0 0 0
+1089 7 1 10 0 0 524287
+1090 7 2 10 0 0 524287
+1091 7 4 10 0 0 524287
+1092 7 0 10 10 0 0
+1093 7 1 10 10 0 524287
+1094 7 2 10 10 0 524287
+1095 7 4 10 10 0 524287
+1096 7 0 10 20 0 0
+1097 7 1 10 20 0 524287
+1098 7 2 10 20 0 524287
+1099 7 4 10 20 0 524287
+1100 7 0 10 16777215 0 0
+1101 7 1 10 16777215 0 524287
+1102 7 2 10 16777215 0 524287
+1103 7 4 10 16777215 0 524287
+1104 7 0 10 0 10 10
+1105 7 1 10 0 10 524287
+1106 7 2 10 0 10 524287
+1107 7 4 10 0 10 524287
+1108 7 0 10 10 10 10
+1109 7 1 10 10 10 524287
+1110 7 2 10 10 10 524287
+1111 7 4 10 10 10 524287
+1112 7 0 10 20 10 10
+1113 7 1 10 20 10 524287
+1114 7 2 10 20 10 524287
+1115 7 4 10 20 10 524287
+1116 7 0 10 16777215 10 10
+1117 7 1 10 16777215 10 524287
+1118 7 2 10 16777215 10 524287
+1119 7 4 10 16777215 10 524287
+1120 7 0 10 0 20 20
+1121 7 1 10 0 20 524287
+1122 7 2 10 0 20 524287
+1123 7 4 10 0 20 524287
+1124 7 0 10 10 20 20
+1125 7 1 10 10 20 524287
+1126 7 2 10 10 20 524287
+1127 7 4 10 10 20 524287
+1128 7 0 10 20 20 20
+1129 7 1 10 20 20 524287
+1130 7 2 10 20 20 524287
+1131 7 4 10 20 20 524287
+1132 7 0 10 16777215 20 20
+1133 7 1 10 16777215 20 524287
+1134 7 2 10 16777215 20 524287
+1135 7 4 10 16777215 20 524287
+1136 7 0 10 0 16777215 16777215
+1137 7 1 10 0 16777215 524287
+1138 7 2 10 0 16777215 524287
+1139 7 4 10 0 16777215 524287
+1140 7 0 10 10 16777215 16777215
+1141 7 1 10 10 16777215 524287
+1142 7 2 10 10 16777215 524287
+1143 7 4 10 10 16777215 524287
+1144 7 0 10 20 16777215 16777215
+1145 7 1 10 20 16777215 524287
+1146 7 2 10 20 16777215 524287
+1147 7 4 10 20 16777215 524287
+1148 7 0 10 16777215 16777215 16777215
+1149 7 1 10 16777215 16777215 524287
+1150 7 2 10 16777215 16777215 524287
+1151 7 4 10 16777215 16777215 524287
+1152 7 0 20 0 0 0
+1153 7 1 20 0 0 524287
+1154 7 2 20 0 0 524287
+1155 7 4 20 0 0 524287
+1156 7 0 20 10 0 0
+1157 7 1 20 10 0 524287
+1158 7 2 20 10 0 524287
+1159 7 4 20 10 0 524287
+1160 7 0 20 20 0 0
+1161 7 1 20 20 0 524287
+1162 7 2 20 20 0 524287
+1163 7 4 20 20 0 524287
+1164 7 0 20 16777215 0 0
+1165 7 1 20 16777215 0 524287
+1166 7 2 20 16777215 0 524287
+1167 7 4 20 16777215 0 524287
+1168 7 0 20 0 10 10
+1169 7 1 20 0 10 524287
+1170 7 2 20 0 10 524287
+1171 7 4 20 0 10 524287
+1172 7 0 20 10 10 10
+1173 7 1 20 10 10 524287
+1174 7 2 20 10 10 524287
+1175 7 4 20 10 10 524287
+1176 7 0 20 20 10 10
+1177 7 1 20 20 10 524287
+1178 7 2 20 20 10 524287
+1179 7 4 20 20 10 524287
+1180 7 0 20 16777215 10 10
+1181 7 1 20 16777215 10 524287
+1182 7 2 20 16777215 10 524287
+1183 7 4 20 16777215 10 524287
+1184 7 0 20 0 20 20
+1185 7 1 20 0 20 524287
+1186 7 2 20 0 20 524287
+1187 7 4 20 0 20 524287
+1188 7 0 20 10 20 20
+1189 7 1 20 10 20 524287
+1190 7 2 20 10 20 524287
+1191 7 4 20 10 20 524287
+1192 7 0 20 20 20 20
+1193 7 1 20 20 20 524287
+1194 7 2 20 20 20 524287
+1195 7 4 20 20 20 524287
+1196 7 0 20 16777215 20 20
+1197 7 1 20 16777215 20 524287
+1198 7 2 20 16777215 20 524287
+1199 7 4 20 16777215 20 524287
+1200 7 0 20 0 16777215 16777215
+1201 7 1 20 0 16777215 524287
+1202 7 2 20 0 16777215 524287
+1203 7 4 20 0 16777215 524287
+1204 7 0 20 10 16777215 16777215
+1205 7 1 20 10 16777215 524287
+1206 7 2 20 10 16777215 524287
+1207 7 4 20 10 16777215 524287
+1208 7 0 20 20 16777215 16777215
+1209 7 1 20 20 16777215 524287
+1210 7 2 20 20 16777215 524287
+1211 7 4 20 20 16777215 524287
+1212 7 0 20 16777215 16777215 16777215
+1213 7 1 20 16777215 16777215 524287
+1214 7 2 20 16777215 16777215 524287
+1215 7 4 20 16777215 16777215 524287
+1216 7 0 16777215 0 0 0
+1217 7 1 16777215 0 0 524287
+1218 7 2 16777215 0 0 524287
+1219 7 4 16777215 0 0 524287
+1220 7 0 16777215 10 0 0
+1221 7 1 16777215 10 0 524287
+1222 7 2 16777215 10 0 524287
+1223 7 4 16777215 10 0 524287
+1224 7 0 16777215 20 0 0
+1225 7 1 16777215 20 0 524287
+1226 7 2 16777215 20 0 524287
+1227 7 4 16777215 20 0 524287
+1228 7 0 16777215 16777215 0 0
+1229 7 1 16777215 16777215 0 524287
+1230 7 2 16777215 16777215 0 524287
+1231 7 4 16777215 16777215 0 524287
+1232 7 0 16777215 0 10 10
+1233 7 1 16777215 0 10 524287
+1234 7 2 16777215 0 10 524287
+1235 7 4 16777215 0 10 524287
+1236 7 0 16777215 10 10 10
+1237 7 1 16777215 10 10 524287
+1238 7 2 16777215 10 10 524287
+1239 7 4 16777215 10 10 524287
+1240 7 0 16777215 20 10 10
+1241 7 1 16777215 20 10 524287
+1242 7 2 16777215 20 10 524287
+1243 7 4 16777215 20 10 524287
+1244 7 0 16777215 16777215 10 10
+1245 7 1 16777215 16777215 10 524287
+1246 7 2 16777215 16777215 10 524287
+1247 7 4 16777215 16777215 10 524287
+1248 7 0 16777215 0 20 20
+1249 7 1 16777215 0 20 524287
+1250 7 2 16777215 0 20 524287
+1251 7 4 16777215 0 20 524287
+1252 7 0 16777215 10 20 20
+1253 7 1 16777215 10 20 524287
+1254 7 2 16777215 10 20 524287
+1255 7 4 16777215 10 20 524287
+1256 7 0 16777215 20 20 20
+1257 7 1 16777215 20 20 524287
+1258 7 2 16777215 20 20 524287
+1259 7 4 16777215 20 20 524287
+1260 7 0 16777215 16777215 20 20
+1261 7 1 16777215 16777215 20 524287
+1262 7 2 16777215 16777215 20 524287
+1263 7 4 16777215 16777215 20 524287
+1264 7 0 16777215 0 16777215 16777215
+1265 7 1 16777215 0 16777215 524287
+1266 7 2 16777215 0 16777215 524287
+1267 7 4 16777215 0 16777215 524287
+1268 7 0 16777215 10 16777215 16777215
+1269 7 1 16777215 10 16777215 524287
+1270 7 2 16777215 10 16777215 524287
+1271 7 4 16777215 10 16777215 524287
+1272 7 0 16777215 20 16777215 16777215
+1273 7 1 16777215 20 16777215 524287
+1274 7 2 16777215 20 16777215 524287
+1275 7 4 16777215 20 16777215 524287
+1276 7 0 16777215 16777215 16777215 16777215
+1277 7 1 16777215 16777215 16777215 524287
+1278 7 2 16777215 16777215 16777215 524287
+1279 7 4 16777215 16777215 16777215 524287
+1280 3 0 0 0 0 0
+1281 3 1 0 0 0 524287
+1282 3 2 0 0 0 524287
+1283 3 4 0 0 0 524287
+1284 3 0 0 10 0 0
+1285 3 1 0 10 0 524287
+1286 3 2 0 10 0 524287
+1287 3 4 0 10 0 524287
+1288 3 0 0 20 0 0
+1289 3 1 0 20 0 524287
+1290 3 2 0 20 0 524287
+1291 3 4 0 20 0 524287
+1292 3 0 0 16777215 0 0
+1293 3 1 0 16777215 0 524287
+1294 3 2 0 16777215 0 524287
+1295 3 4 0 16777215 0 524287
+1296 3 0 0 0 10 10
+1297 3 1 0 0 10 524287
+1298 3 2 0 0 10 524287
+1299 3 4 0 0 10 524287
+1300 3 0 0 10 10 10
+1301 3 1 0 10 10 524287
+1302 3 2 0 10 10 524287
+1303 3 4 0 10 10 524287
+1304 3 0 0 20 10 10
+1305 3 1 0 20 10 524287
+1306 3 2 0 20 10 524287
+1307 3 4 0 20 10 524287
+1308 3 0 0 16777215 10 10
+1309 3 1 0 16777215 10 524287
+1310 3 2 0 16777215 10 524287
+1311 3 4 0 16777215 10 524287
+1312 3 0 0 0 20 20
+1313 3 1 0 0 20 524287
+1314 3 2 0 0 20 524287
+1315 3 4 0 0 20 524287
+1316 3 0 0 10 20 20
+1317 3 1 0 10 20 524287
+1318 3 2 0 10 20 524287
+1319 3 4 0 10 20 524287
+1320 3 0 0 20 20 20
+1321 3 1 0 20 20 524287
+1322 3 2 0 20 20 524287
+1323 3 4 0 20 20 524287
+1324 3 0 0 16777215 20 20
+1325 3 1 0 16777215 20 524287
+1326 3 2 0 16777215 20 524287
+1327 3 4 0 16777215 20 524287
+1328 3 0 0 0 16777215 16777215
+1329 3 1 0 0 16777215 524287
+1330 3 2 0 0 16777215 524287
+1331 3 4 0 0 16777215 524287
+1332 3 0 0 10 16777215 16777215
+1333 3 1 0 10 16777215 524287
+1334 3 2 0 10 16777215 524287
+1335 3 4 0 10 16777215 524287
+1336 3 0 0 20 16777215 16777215
+1337 3 1 0 20 16777215 524287
+1338 3 2 0 20 16777215 524287
+1339 3 4 0 20 16777215 524287
+1340 3 0 0 16777215 16777215 16777215
+1341 3 1 0 16777215 16777215 524287
+1342 3 2 0 16777215 16777215 524287
+1343 3 4 0 16777215 16777215 524287
+1344 3 0 10 0 0 0
+1345 3 1 10 0 0 524287
+1346 3 2 10 0 0 524287
+1347 3 4 10 0 0 524287
+1348 3 0 10 10 0 0
+1349 3 1 10 10 0 524287
+1350 3 2 10 10 0 524287
+1351 3 4 10 10 0 524287
+1352 3 0 10 20 0 0
+1353 3 1 10 20 0 524287
+1354 3 2 10 20 0 524287
+1355 3 4 10 20 0 524287
+1356 3 0 10 16777215 0 0
+1357 3 1 10 16777215 0 524287
+1358 3 2 10 16777215 0 524287
+1359 3 4 10 16777215 0 524287
+1360 3 0 10 0 10 10
+1361 3 1 10 0 10 524287
+1362 3 2 10 0 10 524287
+1363 3 4 10 0 10 524287
+1364 3 0 10 10 10 10
+1365 3 1 10 10 10 524287
+1366 3 2 10 10 10 524287
+1367 3 4 10 10 10 524287
+1368 3 0 10 20 10 10
+1369 3 1 10 20 10 524287
+1370 3 2 10 20 10 524287
+1371 3 4 10 20 10 524287
+1372 3 0 10 16777215 10 10
+1373 3 1 10 16777215 10 524287
+1374 3 2 10 16777215 10 524287
+1375 3 4 10 16777215 10 524287
+1376 3 0 10 0 20 20
+1377 3 1 10 0 20 524287
+1378 3 2 10 0 20 524287
+1379 3 4 10 0 20 524287
+1380 3 0 10 10 20 20
+1381 3 1 10 10 20 524287
+1382 3 2 10 10 20 524287
+1383 3 4 10 10 20 524287
+1384 3 0 10 20 20 20
+1385 3 1 10 20 20 524287
+1386 3 2 10 20 20 524287
+1387 3 4 10 20 20 524287
+1388 3 0 10 16777215 20 20
+1389 3 1 10 16777215 20 524287
+1390 3 2 10 16777215 20 524287
+1391 3 4 10 16777215 20 524287
+1392 3 0 10 0 16777215 16777215
+1393 3 1 10 0 16777215 524287
+1394 3 2 10 0 16777215 524287
+1395 3 4 10 0 16777215 524287
+1396 3 0 10 10 16777215 16777215
+1397 3 1 10 10 16777215 524287
+1398 3 2 10 10 16777215 524287
+1399 3 4 10 10 16777215 524287
+1400 3 0 10 20 16777215 16777215
+1401 3 1 10 20 16777215 524287
+1402 3 2 10 20 16777215 524287
+1403 3 4 10 20 16777215 524287
+1404 3 0 10 16777215 16777215 16777215
+1405 3 1 10 16777215 16777215 524287
+1406 3 2 10 16777215 16777215 524287
+1407 3 4 10 16777215 16777215 524287
+1408 3 0 20 0 0 0
+1409 3 1 20 0 0 524287
+1410 3 2 20 0 0 524287
+1411 3 4 20 0 0 524287
+1412 3 0 20 10 0 0
+1413 3 1 20 10 0 524287
+1414 3 2 20 10 0 524287
+1415 3 4 20 10 0 524287
+1416 3 0 20 20 0 0
+1417 3 1 20 20 0 524287
+1418 3 2 20 20 0 524287
+1419 3 4 20 20 0 524287
+1420 3 0 20 16777215 0 0
+1421 3 1 20 16777215 0 524287
+1422 3 2 20 16777215 0 524287
+1423 3 4 20 16777215 0 524287
+1424 3 0 20 0 10 10
+1425 3 1 20 0 10 524287
+1426 3 2 20 0 10 524287
+1427 3 4 20 0 10 524287
+1428 3 0 20 10 10 10
+1429 3 1 20 10 10 524287
+1430 3 2 20 10 10 524287
+1431 3 4 20 10 10 524287
+1432 3 0 20 20 10 10
+1433 3 1 20 20 10 524287
+1434 3 2 20 20 10 524287
+1435 3 4 20 20 10 524287
+1436 3 0 20 16777215 10 10
+1437 3 1 20 16777215 10 524287
+1438 3 2 20 16777215 10 524287
+1439 3 4 20 16777215 10 524287
+1440 3 0 20 0 20 20
+1441 3 1 20 0 20 524287
+1442 3 2 20 0 20 524287
+1443 3 4 20 0 20 524287
+1444 3 0 20 10 20 20
+1445 3 1 20 10 20 524287
+1446 3 2 20 10 20 524287
+1447 3 4 20 10 20 524287
+1448 3 0 20 20 20 20
+1449 3 1 20 20 20 524287
+1450 3 2 20 20 20 524287
+1451 3 4 20 20 20 524287
+1452 3 0 20 16777215 20 20
+1453 3 1 20 16777215 20 524287
+1454 3 2 20 16777215 20 524287
+1455 3 4 20 16777215 20 524287
+1456 3 0 20 0 16777215 16777215
+1457 3 1 20 0 16777215 524287
+1458 3 2 20 0 16777215 524287
+1459 3 4 20 0 16777215 524287
+1460 3 0 20 10 16777215 16777215
+1461 3 1 20 10 16777215 524287
+1462 3 2 20 10 16777215 524287
+1463 3 4 20 10 16777215 524287
+1464 3 0 20 20 16777215 16777215
+1465 3 1 20 20 16777215 524287
+1466 3 2 20 20 16777215 524287
+1467 3 4 20 20 16777215 524287
+1468 3 0 20 16777215 16777215 16777215
+1469 3 1 20 16777215 16777215 524287
+1470 3 2 20 16777215 16777215 524287
+1471 3 4 20 16777215 16777215 524287
+1472 3 0 16777215 0 0 0
+1473 3 1 16777215 0 0 524287
+1474 3 2 16777215 0 0 524287
+1475 3 4 16777215 0 0 524287
+1476 3 0 16777215 10 0 0
+1477 3 1 16777215 10 0 524287
+1478 3 2 16777215 10 0 524287
+1479 3 4 16777215 10 0 524287
+1480 3 0 16777215 20 0 0
+1481 3 1 16777215 20 0 524287
+1482 3 2 16777215 20 0 524287
+1483 3 4 16777215 20 0 524287
+1484 3 0 16777215 16777215 0 0
+1485 3 1 16777215 16777215 0 524287
+1486 3 2 16777215 16777215 0 524287
+1487 3 4 16777215 16777215 0 524287
+1488 3 0 16777215 0 10 10
+1489 3 1 16777215 0 10 524287
+1490 3 2 16777215 0 10 524287
+1491 3 4 16777215 0 10 524287
+1492 3 0 16777215 10 10 10
+1493 3 1 16777215 10 10 524287
+1494 3 2 16777215 10 10 524287
+1495 3 4 16777215 10 10 524287
+1496 3 0 16777215 20 10 10
+1497 3 1 16777215 20 10 524287
+1498 3 2 16777215 20 10 524287
+1499 3 4 16777215 20 10 524287
+1500 3 0 16777215 16777215 10 10
+1501 3 1 16777215 16777215 10 524287
+1502 3 2 16777215 16777215 10 524287
+1503 3 4 16777215 16777215 10 524287
+1504 3 0 16777215 0 20 20
+1505 3 1 16777215 0 20 524287
+1506 3 2 16777215 0 20 524287
+1507 3 4 16777215 0 20 524287
+1508 3 0 16777215 10 20 20
+1509 3 1 16777215 10 20 524287
+1510 3 2 16777215 10 20 524287
+1511 3 4 16777215 10 20 524287
+1512 3 0 16777215 20 20 20
+1513 3 1 16777215 20 20 524287
+1514 3 2 16777215 20 20 524287
+1515 3 4 16777215 20 20 524287
+1516 3 0 16777215 16777215 20 20
+1517 3 1 16777215 16777215 20 524287
+1518 3 2 16777215 16777215 20 524287
+1519 3 4 16777215 16777215 20 524287
+1520 3 0 16777215 0 16777215 16777215
+1521 3 1 16777215 0 16777215 524287
+1522 3 2 16777215 0 16777215 524287
+1523 3 4 16777215 0 16777215 524287
+1524 3 0 16777215 10 16777215 16777215
+1525 3 1 16777215 10 16777215 524287
+1526 3 2 16777215 10 16777215 524287
+1527 3 4 16777215 10 16777215 524287
+1528 3 0 16777215 20 16777215 16777215
+1529 3 1 16777215 20 16777215 524287
+1530 3 2 16777215 20 16777215 524287
+1531 3 4 16777215 20 16777215 524287
+1532 3 0 16777215 16777215 16777215 16777215
+1533 3 1 16777215 16777215 16777215 524287
+1534 3 2 16777215 16777215 16777215 524287
+1535 3 4 16777215 16777215 16777215 524287
+1536 13 0 0 0 0 0
+1537 13 1 0 0 0 524287
+1538 13 2 0 0 0 524287
+1539 13 4 0 0 0 524287
+1540 13 0 0 10 0 0
+1541 13 1 0 10 0 524287
+1542 13 2 0 10 0 524287
+1543 13 4 0 10 0 524287
+1544 13 0 0 20 0 0
+1545 13 1 0 20 0 524287
+1546 13 2 0 20 0 524287
+1547 13 4 0 20 0 524287
+1548 13 0 0 16777215 0 0
+1549 13 1 0 16777215 0 524287
+1550 13 2 0 16777215 0 524287
+1551 13 4 0 16777215 0 524287
+1552 13 0 0 0 10 10
+1553 13 1 0 0 10 524287
+1554 13 2 0 0 10 524287
+1555 13 4 0 0 10 524287
+1556 13 0 0 10 10 10
+1557 13 1 0 10 10 524287
+1558 13 2 0 10 10 524287
+1559 13 4 0 10 10 524287
+1560 13 0 0 20 10 10
+1561 13 1 0 20 10 524287
+1562 13 2 0 20 10 524287
+1563 13 4 0 20 10 524287
+1564 13 0 0 16777215 10 10
+1565 13 1 0 16777215 10 524287
+1566 13 2 0 16777215 10 524287
+1567 13 4 0 16777215 10 524287
+1568 13 0 0 0 20 20
+1569 13 1 0 0 20 524287
+1570 13 2 0 0 20 524287
+1571 13 4 0 0 20 524287
+1572 13 0 0 10 20 20
+1573 13 1 0 10 20 524287
+1574 13 2 0 10 20 524287
+1575 13 4 0 10 20 524287
+1576 13 0 0 20 20 20
+1577 13 1 0 20 20 524287
+1578 13 2 0 20 20 524287
+1579 13 4 0 20 20 524287
+1580 13 0 0 16777215 20 20
+1581 13 1 0 16777215 20 524287
+1582 13 2 0 16777215 20 524287
+1583 13 4 0 16777215 20 524287
+1584 13 0 0 0 16777215 16777215
+1585 13 1 0 0 16777215 524287
+1586 13 2 0 0 16777215 524287
+1587 13 4 0 0 16777215 524287
+1588 13 0 0 10 16777215 16777215
+1589 13 1 0 10 16777215 524287
+1590 13 2 0 10 16777215 524287
+1591 13 4 0 10 16777215 524287
+1592 13 0 0 20 16777215 16777215
+1593 13 1 0 20 16777215 524287
+1594 13 2 0 20 16777215 524287
+1595 13 4 0 20 16777215 524287
+1596 13 0 0 16777215 16777215 16777215
+1597 13 1 0 16777215 16777215 524287
+1598 13 2 0 16777215 16777215 524287
+1599 13 4 0 16777215 16777215 524287
+1600 13 0 10 0 0 0
+1601 13 1 10 0 0 524287
+1602 13 2 10 0 0 524287
+1603 13 4 10 0 0 524287
+1604 13 0 10 10 0 0
+1605 13 1 10 10 0 524287
+1606 13 2 10 10 0 524287
+1607 13 4 10 10 0 524287
+1608 13 0 10 20 0 0
+1609 13 1 10 20 0 524287
+1610 13 2 10 20 0 524287
+1611 13 4 10 20 0 524287
+1612 13 0 10 16777215 0 0
+1613 13 1 10 16777215 0 524287
+1614 13 2 10 16777215 0 524287
+1615 13 4 10 16777215 0 524287
+1616 13 0 10 0 10 10
+1617 13 1 10 0 10 524287
+1618 13 2 10 0 10 524287
+1619 13 4 10 0 10 524287
+1620 13 0 10 10 10 10
+1621 13 1 10 10 10 524287
+1622 13 2 10 10 10 524287
+1623 13 4 10 10 10 524287
+1624 13 0 10 20 10 10
+1625 13 1 10 20 10 524287
+1626 13 2 10 20 10 524287
+1627 13 4 10 20 10 524287
+1628 13 0 10 16777215 10 10
+1629 13 1 10 16777215 10 524287
+1630 13 2 10 16777215 10 524287
+1631 13 4 10 16777215 10 524287
+1632 13 0 10 0 20 20
+1633 13 1 10 0 20 524287
+1634 13 2 10 0 20 524287
+1635 13 4 10 0 20 524287
+1636 13 0 10 10 20 20
+1637 13 1 10 10 20 524287
+1638 13 2 10 10 20 524287
+1639 13 4 10 10 20 524287
+1640 13 0 10 20 20 20
+1641 13 1 10 20 20 524287
+1642 13 2 10 20 20 524287
+1643 13 4 10 20 20 524287
+1644 13 0 10 16777215 20 20
+1645 13 1 10 16777215 20 524287
+1646 13 2 10 16777215 20 524287
+1647 13 4 10 16777215 20 524287
+1648 13 0 10 0 16777215 16777215
+1649 13 1 10 0 16777215 524287
+1650 13 2 10 0 16777215 524287
+1651 13 4 10 0 16777215 524287
+1652 13 0 10 10 16777215 16777215
+1653 13 1 10 10 16777215 524287
+1654 13 2 10 10 16777215 524287
+1655 13 4 10 10 16777215 524287
+1656 13 0 10 20 16777215 16777215
+1657 13 1 10 20 16777215 524287
+1658 13 2 10 20 16777215 524287
+1659 13 4 10 20 16777215 524287
+1660 13 0 10 16777215 16777215 16777215
+1661 13 1 10 16777215 16777215 524287
+1662 13 2 10 16777215 16777215 524287
+1663 13 4 10 16777215 16777215 524287
+1664 13 0 20 0 0 0
+1665 13 1 20 0 0 524287
+1666 13 2 20 0 0 524287
+1667 13 4 20 0 0 524287
+1668 13 0 20 10 0 0
+1669 13 1 20 10 0 524287
+1670 13 2 20 10 0 524287
+1671 13 4 20 10 0 524287
+1672 13 0 20 20 0 0
+1673 13 1 20 20 0 524287
+1674 13 2 20 20 0 524287
+1675 13 4 20 20 0 524287
+1676 13 0 20 16777215 0 0
+1677 13 1 20 16777215 0 524287
+1678 13 2 20 16777215 0 524287
+1679 13 4 20 16777215 0 524287
+1680 13 0 20 0 10 10
+1681 13 1 20 0 10 524287
+1682 13 2 20 0 10 524287
+1683 13 4 20 0 10 524287
+1684 13 0 20 10 10 10
+1685 13 1 20 10 10 524287
+1686 13 2 20 10 10 524287
+1687 13 4 20 10 10 524287
+1688 13 0 20 20 10 10
+1689 13 1 20 20 10 524287
+1690 13 2 20 20 10 524287
+1691 13 4 20 20 10 524287
+1692 13 0 20 16777215 10 10
+1693 13 1 20 16777215 10 524287
+1694 13 2 20 16777215 10 524287
+1695 13 4 20 16777215 10 524287
+1696 13 0 20 0 20 20
+1697 13 1 20 0 20 524287
+1698 13 2 20 0 20 524287
+1699 13 4 20 0 20 524287
+1700 13 0 20 10 20 20
+1701 13 1 20 10 20 524287
+1702 13 2 20 10 20 524287
+1703 13 4 20 10 20 524287
+1704 13 0 20 20 20 20
+1705 13 1 20 20 20 524287
+1706 13 2 20 20 20 524287
+1707 13 4 20 20 20 524287
+1708 13 0 20 16777215 20 20
+1709 13 1 20 16777215 20 524287
+1710 13 2 20 16777215 20 524287
+1711 13 4 20 16777215 20 524287
+1712 13 0 20 0 16777215 16777215
+1713 13 1 20 0 16777215 524287
+1714 13 2 20 0 16777215 524287
+1715 13 4 20 0 16777215 524287
+1716 13 0 20 10 16777215 16777215
+1717 13 1 20 10 16777215 524287
+1718 13 2 20 10 16777215 524287
+1719 13 4 20 10 16777215 524287
+1720 13 0 20 20 16777215 16777215
+1721 13 1 20 20 16777215 524287
+1722 13 2 20 20 16777215 524287
+1723 13 4 20 20 16777215 524287
+1724 13 0 20 16777215 16777215 16777215
+1725 13 1 20 16777215 16777215 524287
+1726 13 2 20 16777215 16777215 524287
+1727 13 4 20 16777215 16777215 524287
+1728 13 0 16777215 0 0 0
+1729 13 1 16777215 0 0 524287
+1730 13 2 16777215 0 0 524287
+1731 13 4 16777215 0 0 524287
+1732 13 0 16777215 10 0 0
+1733 13 1 16777215 10 0 524287
+1734 13 2 16777215 10 0 524287
+1735 13 4 16777215 10 0 524287
+1736 13 0 16777215 20 0 0
+1737 13 1 16777215 20 0 524287
+1738 13 2 16777215 20 0 524287
+1739 13 4 16777215 20 0 524287
+1740 13 0 16777215 16777215 0 0
+1741 13 1 16777215 16777215 0 524287
+1742 13 2 16777215 16777215 0 524287
+1743 13 4 16777215 16777215 0 524287
+1744 13 0 16777215 0 10 10
+1745 13 1 16777215 0 10 524287
+1746 13 2 16777215 0 10 524287
+1747 13 4 16777215 0 10 524287
+1748 13 0 16777215 10 10 10
+1749 13 1 16777215 10 10 524287
+1750 13 2 16777215 10 10 524287
+1751 13 4 16777215 10 10 524287
+1752 13 0 16777215 20 10 10
+1753 13 1 16777215 20 10 524287
+1754 13 2 16777215 20 10 524287
+1755 13 4 16777215 20 10 524287
+1756 13 0 16777215 16777215 10 10
+1757 13 1 16777215 16777215 10 524287
+1758 13 2 16777215 16777215 10 524287
+1759 13 4 16777215 16777215 10 524287
+1760 13 0 16777215 0 20 20
+1761 13 1 16777215 0 20 524287
+1762 13 2 16777215 0 20 524287
+1763 13 4 16777215 0 20 524287
+1764 13 0 16777215 10 20 20
+1765 13 1 16777215 10 20 524287
+1766 13 2 16777215 10 20 524287
+1767 13 4 16777215 10 20 524287
+1768 13 0 16777215 20 20 20
+1769 13 1 16777215 20 20 524287
+1770 13 2 16777215 20 20 524287
+1771 13 4 16777215 20 20 524287
+1772 13 0 16777215 16777215 20 20
+1773 13 1 16777215 16777215 20 524287
+1774 13 2 16777215 16777215 20 524287
+1775 13 4 16777215 16777215 20 524287
+1776 13 0 16777215 0 16777215 16777215
+1777 13 1 16777215 0 16777215 524287
+1778 13 2 16777215 0 16777215 524287
+1779 13 4 16777215 0 16777215 524287
+1780 13 0 16777215 10 16777215 16777215
+1781 13 1 16777215 10 16777215 524287
+1782 13 2 16777215 10 16777215 524287
+1783 13 4 16777215 10 16777215 524287
+1784 13 0 16777215 20 16777215 16777215
+1785 13 1 16777215 20 16777215 524287
+1786 13 2 16777215 20 16777215 524287
+1787 13 4 16777215 20 16777215 524287
+1788 13 0 16777215 16777215 16777215 16777215
+1789 13 1 16777215 16777215 16777215 524287
+1790 13 2 16777215 16777215 16777215 524287
+1791 13 4 16777215 16777215 16777215 524287
diff --git a/tests/auto/widgets/kernel/qlayout/qlayout.pro b/tests/auto/widgets/kernel/qlayout/qlayout.pro
new file mode 100644
index 0000000000..28ca9dc86d
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/qlayout.pro
@@ -0,0 +1,16 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+
+SOURCES += tst_qlayout.cpp
+wince* {
+ addFiles.files = baseline
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+ test_data.files = baseline/*
+ test_data.path = $${target.path}/baseline
+ INSTALLS += test_data
+}
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
new file mode 100644
index 0000000000..ea25700568
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qboxlayout.h>
+#include <qmenubar.h>
+#include <qdialog.h>
+#include <qsizegrip.h>
+#include <qlabel.h>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QWindowsStyle>
+#include <QtWidgets/QSizePolicy>
+#include <QPushButton>
+#include <QRadioButton>
+#include <private/qlayoutengine_p.h>
+
+#ifdef Q_WS_MAC
+# include <QtGui/QMacStyle>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QLayout();
+ virtual ~tst_QLayout();
+
+private slots:
+ void getSetCheck();
+ void geometry();
+ void smartMaxSize();
+ void setLayoutBugs();
+ void setContentsMargins();
+ void layoutItemRect();
+ void warnIfWrongParent();
+ void controlTypes();
+ void adjustSizeShouldMakeSureLayoutIsActivated();
+};
+
+tst_QLayout::tst_QLayout()
+{
+}
+
+tst_QLayout::~tst_QLayout()
+{
+}
+
+// Testing get/set functions
+void tst_QLayout::getSetCheck()
+{
+ QBoxLayout obj1(QBoxLayout::LeftToRight);
+ // QWidget * QLayout::menuBar()
+ // void QLayout::setMenuBar(QWidget *)
+ QMenuBar *var1 = new QMenuBar();
+ obj1.setMenuBar(var1);
+ QCOMPARE(static_cast<QWidget *>(var1), obj1.menuBar());
+ obj1.setMenuBar((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.menuBar());
+ delete var1;
+}
+
+class SizeHinterFrame : public QFrame
+{
+public:
+ SizeHinterFrame(const QSize &sh, const QSize &msh = QSize())
+ : QFrame(0), sh(sh), msh(msh) {
+ setFrameStyle(QFrame::Box | QFrame::Plain);
+ }
+
+
+
+ void setSizeHint(const QSize &s) { sh = s; }
+ QSize sizeHint() const { return sh; }
+ QSize minimumSizeHint() const { return msh; }
+
+private:
+ QSize sh;
+ QSize msh;
+};
+
+
+void tst_QLayout::geometry()
+{
+ // For QWindowsStyle we know that QWidgetItem::geometry() and QWidget::geometry()
+ // should be the same.
+ QApplication::setStyle(new QWindowsStyle);
+ QWidget topLevel;
+ QWidget w(&topLevel);
+ QVBoxLayout layout(&w);
+ SizeHinterFrame widget(QSize(100,100));
+ layout.addWidget(&widget);
+ QLayoutItem *item = layout.itemAt(0);
+ topLevel.show();
+ QApplication::processEvents();
+ QCOMPARE(item->geometry().size(), QSize(100,100));
+
+ widget.setMinimumSize(QSize(110,110));
+ QCOMPARE(item->geometry().size(), QSize(110,110));
+
+ widget.setMinimumSize(QSize(0,0));
+ widget.setMaximumSize(QSize(90,90));
+ widget.setSizeHint(QSize(100,100));
+ QCOMPARE(item->geometry().size(), QSize(90,90));
+}
+
+void tst_QLayout::smartMaxSize()
+{
+ QVector<int> expectedWidths;
+
+ QFile f(QLatin1String(SRCDIR "/baseline/smartmaxsize"));
+
+ QCOMPARE(f.open(QIODevice::ReadOnly | QIODevice::Text), true);
+
+ QTextStream stream(&f);
+
+ while(!stream.atEnd()) {
+ QString line = stream.readLine(200);
+ expectedWidths.append(line.section(QLatin1Char(' '), 6, -1, QString::SectionSkipEmpty).toInt());
+ }
+ f.close();
+
+ int sizeCombinations[] = { 0, 10, 20, QWIDGETSIZE_MAX};
+ QSizePolicy::Policy policies[] = { QSizePolicy::Fixed,
+ QSizePolicy::Minimum,
+ QSizePolicy::Maximum,
+ QSizePolicy::Preferred,
+ QSizePolicy::Expanding,
+ QSizePolicy::MinimumExpanding,
+ QSizePolicy::Ignored
+ };
+ Qt::Alignment alignments[] = { 0,
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter
+ };
+
+ int expectedIndex = 0;
+ int regressionCount = 0;
+ for (size_t p = 0; p < sizeof(policies)/sizeof(QSizePolicy::Policy); ++p) {
+ QSizePolicy sizePolicy;
+ sizePolicy.setHorizontalPolicy(policies[p]);
+ for (size_t min = 0; min < sizeof(sizeCombinations)/sizeof(int); ++min) {
+ int minSize = sizeCombinations[min];
+ for (size_t max = 0; max < sizeof(sizeCombinations)/sizeof(int); ++max) {
+ int maxSize = sizeCombinations[max];
+ for (size_t sh = 0; sh < sizeof(sizeCombinations)/sizeof(int); ++sh) {
+ int sizeHint = sizeCombinations[sh];
+ for (size_t a = 0; a < sizeof(alignments)/sizeof(int); ++a) {
+ Qt::Alignment align = alignments[a];
+ QSize sz = qSmartMaxSize(QSize(sizeHint, 1), QSize(minSize, 1), QSize(maxSize, 1), sizePolicy, align);
+ int width = sz.width();
+#if 0
+ qDebug() << expectedIndex << sizePolicy.horizontalPolicy() << align << minSize << sizeHint << maxSize << width;
+#else
+ int expectedWidth = expectedWidths[expectedIndex];
+ if (width != expectedWidth) {
+ qDebug() << "error at index" << expectedIndex << ":" << sizePolicy.horizontalPolicy() << align << minSize << sizeHint << maxSize << width;
+ ++regressionCount;
+ }
+#endif
+ ++expectedIndex;
+ }
+ }
+ }
+ }
+ }
+ QCOMPARE(regressionCount, 0);
+}
+
+void tst_QLayout::setLayoutBugs()
+{
+ QWidget widget(0);
+ QHBoxLayout *hBoxLayout = new QHBoxLayout(&widget);
+
+ for(int i = 0; i < 6; ++i) {
+ QPushButton *pushButton = new QPushButton("Press me!", &widget);
+ hBoxLayout->addWidget(pushButton);
+ }
+
+ widget.setLayout(hBoxLayout);
+ QVERIFY(widget.layout() == hBoxLayout);
+
+ QWidget containerWidget(0);
+ containerWidget.setLayout(widget.layout());
+ QVERIFY(widget.layout() == 0);
+ QVERIFY(containerWidget.layout() == hBoxLayout);
+}
+
+class MyLayout : public QLayout
+{
+ public:
+ MyLayout() : invalidated(false) {}
+ virtual void invalidate() {invalidated = true;}
+ bool invalidated;
+ QSize sizeHint() const {return QSize();}
+ void addItem(QLayoutItem*) {}
+ QLayoutItem* itemAt(int) const {return 0;}
+ QLayoutItem* takeAt(int) {return 0;}
+ int count() const {return 0;}
+};
+
+void tst_QLayout::setContentsMargins()
+{
+ MyLayout layout;
+ layout.invalidated = false;
+ int left, top, right, bottom;
+
+ layout.setContentsMargins(52, 53, 54, 55);
+ QVERIFY(layout.invalidated);
+ layout.invalidated = false;
+
+ layout.getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(left, 52);
+ QCOMPARE(top, 53);
+ QCOMPARE(right, 54);
+ QCOMPARE(bottom, 55);
+
+ layout.setContentsMargins(52, 53, 54, 55);
+ QVERIFY(!layout.invalidated);
+}
+
+class EventReceiver : public QObject
+{
+public:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ if (event->type() == QEvent::Show) {
+ geom = static_cast<QWidget*>(watched)->geometry();
+ }
+ return false;
+ }
+ QRect geom;
+};
+
+void tst_QLayout::layoutItemRect()
+{
+#ifdef Q_WS_MAC
+ if (qobject_cast<QMacStyle*>(QApplication::style())) {
+ QWidget *window = new QWidget;
+ QRadioButton *radio = new QRadioButton(window);
+ QWidgetItem item(radio);
+ EventReceiver eventReceiver;
+ radio->installEventFilter(&eventReceiver);
+
+ radio->show();
+ QApplication::processEvents();
+ QApplication::processEvents();
+ QSize s = item.sizeHint();
+
+ item.setAlignment(Qt::AlignVCenter);
+ item.setGeometry(QRect(QPoint(0, 0), s));
+
+ QCOMPARE(radio->geometry().size(), radio->sizeHint());
+ delete radio;
+ }
+#endif
+}
+
+void tst_QLayout::warnIfWrongParent()
+{
+ QWidget root;
+ QHBoxLayout lay;
+ lay.setParent(&root);
+ QTest::ignoreMessage(QtWarningMsg, "QLayout::parentWidget: A layout can only have another layout as a parent.");
+ QCOMPARE(lay.parentWidget(), static_cast<QWidget*>(0));
+}
+
+void tst_QLayout::controlTypes()
+{
+ QVBoxLayout layout;
+ QCOMPARE(layout.controlTypes(), QSizePolicy::DefaultType);
+ QSizePolicy p;
+ QCOMPARE(p.controlType(),QSizePolicy::DefaultType);
+
+}
+
+void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated()
+{
+ QWidget main;
+
+ QVBoxLayout *const layout = new QVBoxLayout(&main);
+ layout->setMargin(0);
+ SizeHinterFrame *frame = new SizeHinterFrame(QSize(200, 10), QSize(200, 8));
+ frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ layout->addWidget(frame);
+
+ SizeHinterFrame *frame2 = new SizeHinterFrame(QSize(200, 10), QSize(200, 8));
+ frame2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ layout->addWidget(frame2);
+
+ main.show();
+
+ frame2->hide();
+ main.adjustSize();
+ QCOMPARE(main.size(), QSize(200, 10));
+}
+
+QTEST_MAIN(tst_QLayout)
+#include "tst_qlayout.moc"
diff --git a/tests/auto/widgets/kernel/qsound/.gitignore b/tests/auto/widgets/kernel/qsound/.gitignore
new file mode 100644
index 0000000000..c9d313c2cf
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/.gitignore
@@ -0,0 +1 @@
+tst_qsound
diff --git a/tests/auto/widgets/kernel/qsound/4.wav b/tests/auto/widgets/kernel/qsound/4.wav
new file mode 100644
index 0000000000..e31b060908
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/4.wav
Binary files differ
diff --git a/tests/auto/widgets/kernel/qsound/qsound.pro b/tests/auto/widgets/kernel/qsound/qsound.pro
new file mode 100644
index 0000000000..18ebaf16a4
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/qsound.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+SOURCES += tst_qsound.cpp
+
+wince* {
+ deploy.files += 4.wav
+ DEPLOYMENT += deploy
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
diff --git a/tests/auto/widgets/kernel/qsound/tst_qsound.cpp b/tests/auto/widgets/kernel/qsound/tst_qsound.cpp
new file mode 100644
index 0000000000..7450549f47
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/tst_qsound.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+
+class tst_QSound : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSound( QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void checkFinished();
+
+ // Manual tests
+ void staticPlay();
+};
+
+void tst_QSound::checkFinished()
+{
+#if defined(Q_WS_QPA)
+ QSKIP("QSound is not implemented on Lighthouse", SkipAll);
+#else
+ QSound sound(SRCDIR"4.wav");
+ sound.setLoops(3);
+ sound.play();
+ QTest::qWait(5000);
+
+#if defined(Q_WS_QWS)
+ QEXPECT_FAIL("", "QSound buggy on embedded (task QTBUG-157)", Abort);
+#endif
+ QVERIFY(sound.isFinished() );
+#endif
+}
+
+void tst_QSound::staticPlay()
+{
+ QSKIP("Test disabled -- only for manual purposes", SkipAll);
+#if !defined(Q_WS_QPA)
+ // Check that you hear sound with static play also.
+ QSound::play(SRCDIR"4.wav");
+ QTest::qWait(2000);
+#endif
+}
+
+QTEST_MAIN(tst_QSound);
+#include "tst_qsound.moc"
diff --git a/tests/auto/widgets/kernel/qstackedlayout/.gitignore b/tests/auto/widgets/kernel/qstackedlayout/.gitignore
new file mode 100644
index 0000000000..4dca3e87bd
--- /dev/null
+++ b/tests/auto/widgets/kernel/qstackedlayout/.gitignore
@@ -0,0 +1 @@
+tst_qstackedlayout
diff --git a/tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro b/tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro
new file mode 100644
index 0000000000..30f074d9b1
--- /dev/null
+++ b/tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qstackedlayout.cpp
+
+
+
diff --git a/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
new file mode 100644
index 0000000000..de734877d7
--- /dev/null
+++ b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QLineEdit>
+#include <QStackedLayout>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <QPushButton>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/kernel/qlayout.cpp gui/kernel/qlayout.h
+
+class tst_QStackedLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QStackedLayout();
+ virtual ~tst_QStackedLayout();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void testCase();
+ void deleteCurrent();
+ void removeWidget();
+ void keepFocusAfterSetCurrent();
+
+private:
+ QWidget *testWidget;
+};
+
+// Testing get/set functions
+void tst_QStackedLayout::getSetCheck()
+{
+ QStackedLayout obj1;
+ // int QStackedLayout::currentIndex()
+ // void QStackedLayout::setCurrentIndex(int)
+ obj1.setCurrentIndex(0);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(-1, obj1.currentIndex());
+
+ // QWidget * QStackedLayout::currentWidget()
+ // void QStackedLayout::setCurrentWidget(QWidget *)
+ QWidget *var2 = new QWidget();
+ obj1.addWidget(var2);
+ obj1.setCurrentWidget(var2);
+ QCOMPARE(var2, obj1.currentWidget());
+
+ obj1.setCurrentWidget((QWidget *)0);
+ QCOMPARE(obj1.currentWidget(), var2);
+
+ delete var2;
+}
+
+
+tst_QStackedLayout::tst_QStackedLayout()
+ : testWidget(0)
+{
+}
+
+tst_QStackedLayout::~tst_QStackedLayout()
+{
+}
+
+void tst_QStackedLayout::initTestCase()
+{
+}
+
+void tst_QStackedLayout::cleanupTestCase()
+{
+}
+
+void tst_QStackedLayout::init()
+{
+ if (testWidget) {
+ delete testWidget;
+ testWidget = 0;
+ }
+ testWidget = new QWidget(0);
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+
+ // make sure the tests work with focus follows mouse
+ QCursor::setPos(testWidget->geometry().center());
+ testWidget->activateWindow();
+ QApplication::syncX();
+ QTest::qWait(250);
+}
+
+void tst_QStackedLayout::cleanup()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+
+void tst_QStackedLayout::testCase()
+{
+ QStackedLayout onStack(testWidget);
+ QStackedLayout *testLayout = &onStack;
+ testWidget->setLayout(testLayout);
+
+ QSignalSpy spy(testLayout,SIGNAL(currentChanged(int)));
+
+ // Nothing in layout
+ QCOMPARE(testLayout->currentIndex(), -1);
+ QCOMPARE(testLayout->currentWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(testLayout->count(), 0);
+
+ // One widget added to layout
+ QWidget *w1 = new QWidget(testWidget);
+ testLayout->addWidget(w1);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), 0);
+ spy.clear();
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ QCOMPARE(testLayout->count(), 1);
+
+ // Another widget added to layout
+ QWidget *w2 = new QWidget(testWidget);
+ testLayout->addWidget(w2);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ QCOMPARE(testLayout->indexOf(w2), 1);
+ QCOMPARE(testLayout->count(), 2);
+
+ // Change the current index
+ testLayout->setCurrentIndex(1);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), 1);
+ spy.clear();
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w2);
+
+ // First widget removed from layout
+ testLayout->removeWidget(w1);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w2);
+ QCOMPARE(testLayout->count(), 1);
+
+ // Second widget removed from layout; back to nothing
+ testLayout->removeWidget(w2);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), -1);
+ spy.clear();
+ QCOMPARE(testLayout->currentIndex(), -1);
+ QCOMPARE(testLayout->currentWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(testLayout->count(), 0);
+
+ // Another widget inserted at current index.
+ // Current index should become current index + 1, but the
+ // current widget should stay the same
+ testLayout->addWidget(w1);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ testLayout->insertWidget(0, w2);
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ QVERIFY(w1->isVisible());
+ QVERIFY(!w2->isVisible());
+
+ testLayout->setCurrentWidget(w2);
+ // Another widget added, so we have: w2, w1, w3 with w2 current
+ QWidget *w3 = new QWidget(testWidget);
+ testLayout->addWidget(w3);
+ QCOMPARE(testLayout->indexOf(w2), 0);
+ QCOMPARE(testLayout->indexOf(w1), 1);
+ QCOMPARE(testLayout->indexOf(w3), 2);
+
+ // Set index to 1 and remove that widget (w1).
+ // Then, current index should still be 1, but w3
+ // should be the new current widget.
+ testLayout->setCurrentIndex(1);
+ testLayout->removeWidget(w1);
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w3);
+ QVERIFY(w3->isVisible());
+
+ // Remove the current widget (w3).
+ // Since it's the last one in the list, current index should now
+ // become 0 and w2 becomes the current widget.
+ testLayout->removeWidget(w3);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w2);
+ QVERIFY(w2->isVisible());
+
+ // Make sure index is decremented when we remove a widget at index < current index
+ testLayout->addWidget(w1);
+ testLayout->addWidget(w3);
+ testLayout->setCurrentIndex(2);
+ testLayout->removeWidget(w2); // At index 0
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w3);
+ QVERIFY(w3->isVisible());
+ testLayout->removeWidget(w1); // At index 0
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w3);
+ QVERIFY(w3->isVisible());
+ testLayout->removeWidget(w3);
+ QCOMPARE(testLayout->currentIndex(), -1);
+ QCOMPARE(testLayout->currentWidget(), static_cast<QWidget*>(0));
+}
+
+void tst_QStackedLayout::deleteCurrent()
+{
+ QStackedLayout *testLayout = new QStackedLayout(testWidget);
+
+ QWidget *w1 = new QWidget;
+ testLayout->addWidget(w1);
+ QWidget *w2 = new QWidget;
+ testLayout->addWidget(w2);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ delete testLayout->currentWidget();
+ QCOMPARE(testLayout->currentWidget(), w2);
+}
+
+void tst_QStackedLayout::removeWidget()
+{
+ if (testWidget->layout()) delete testWidget->layout();
+ QVBoxLayout *vbox = new QVBoxLayout(testWidget);
+
+ QPushButton *top = new QPushButton("top", testWidget); //add another widget that can receive focus
+ top->setObjectName("top");
+ vbox->addWidget(top);
+
+ QStackedLayout *testLayout = new QStackedLayout();
+ QPushButton *w1 = new QPushButton("1st", testWidget);
+ w1->setObjectName("1st");
+ testLayout->addWidget(w1);
+ QPushButton *w2 = new QPushButton("2nd", testWidget);
+ w2->setObjectName("2nd");
+ testLayout->addWidget(w2);
+ vbox->addLayout(testLayout);
+ top->setFocus();
+ QTest::qWait(100);
+ top->activateWindow();
+ QTest::qWait(100);
+ int i =0;
+ for (;;) {
+ if (QApplication::focusWidget() == top)
+ break;
+ else if (i >= 5)
+ QSKIP("Can't get focus", SkipSingle);
+ QTest::qWait(100);
+ ++i;
+ }
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(top));
+
+ // focus should stay at the 'top' widget
+ testLayout->removeWidget(w1);
+
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(top));
+}
+
+class LineEdit : public QLineEdit
+{
+public:
+ LineEdit() : hasFakeEditFocus(false)
+ { }
+
+ bool hasFakeEditFocus;
+
+protected:
+ bool isSingleFocusWidget() const
+ {
+ const QWidget *w = this;
+ while ((w = w->nextInFocusChain()) != this) {
+ if (w->isVisible() && static_cast<const QWidget*>(w->focusProxy()) != this
+ && w->focusPolicy() & Qt::TabFocus) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void focusInEvent(QFocusEvent *event)
+ {
+ QLineEdit::focusInEvent(event);
+ hasFakeEditFocus = isSingleFocusWidget();
+ }
+
+ void focusOutEvent(QFocusEvent *event)
+ {
+ hasFakeEditFocus = false;
+ QLineEdit::focusOutEvent(event);
+ }
+};
+
+void tst_QStackedLayout::keepFocusAfterSetCurrent()
+{
+ if (testWidget->layout()) delete testWidget->layout();
+ QStackedLayout *stackLayout = new QStackedLayout(testWidget);
+ testWidget->setFocusPolicy(Qt::NoFocus);
+
+ LineEdit *edit1 = new LineEdit;
+ LineEdit *edit2 = new LineEdit;
+ stackLayout->addWidget(edit1);
+ stackLayout->addWidget(edit2);
+
+ stackLayout->setCurrentIndex(0);
+
+ testWidget->show();
+ QApplication::setActiveWindow(testWidget);
+ QTest::qWaitForWindowShown(testWidget);
+ QApplication::processEvents();
+
+ edit1->setFocus();
+ edit1->activateWindow();
+ QTest::qWait(25);
+
+ QTRY_VERIFY(edit1->hasFocus());
+
+ stackLayout->setCurrentIndex(1);
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QVERIFY(edit2->hasFakeEditFocus);
+}
+
+QTEST_MAIN(tst_QStackedLayout)
+#include "tst_qstackedlayout.moc"
+
diff --git a/tests/auto/widgets/kernel/qtooltip/.gitignore b/tests/auto/widgets/kernel/qtooltip/.gitignore
new file mode 100644
index 0000000000..552a2a5dc6
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/.gitignore
@@ -0,0 +1 @@
+tst_qtooltip
diff --git a/tests/auto/widgets/kernel/qtooltip/qtooltip.pro b/tests/auto/widgets/kernel/qtooltip/qtooltip.pro
new file mode 100644
index 0000000000..4da8917921
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/qtooltip.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtooltip.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
new file mode 100644
index 0000000000..3ff31ead62
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qtooltip.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QToolTip : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QToolTip() {}
+ virtual ~tst_QToolTip() {}
+
+public slots:
+ void initTestCase() {}
+ void cleanupTestCase() {}
+ void init() {}
+ void cleanup() {}
+
+private slots:
+
+ // task-specific tests below me
+ void task183679_data();
+ void task183679();
+ void whatsThis();
+ void setPalette();
+};
+
+class Widget_task183679 : public QWidget
+{
+ Q_OBJECT
+public:
+ Widget_task183679(QWidget *parent = 0) : QWidget(parent) {}
+
+ void showDelayedToolTip(int msecs)
+ {
+ QTimer::singleShot(msecs, this, SLOT(showToolTip()));
+ }
+
+private slots:
+ void showToolTip()
+ {
+ QToolTip::showText(mapToGlobal(QPoint(0, 0)), "tool tip text", this);
+ }
+};
+
+Q_DECLARE_METATYPE(Qt::Key)
+
+void tst_QToolTip::task183679_data()
+{
+ QTest::addColumn<Qt::Key>("key");
+ QTest::addColumn<bool>("visible");
+#ifdef Q_WS_MAC
+ const bool visibleAfterNonModifier = false;
+#else
+ const bool visibleAfterNonModifier = true;
+#endif
+ QTest::newRow("non-modifier") << Qt::Key_A << visibleAfterNonModifier;
+ QTest::newRow("Shift") << Qt::Key_Shift << true;
+ QTest::newRow("Control") << Qt::Key_Control << true;
+ QTest::newRow("Alt") << Qt::Key_Alt << true;
+ QTest::newRow("Meta") << Qt::Key_Meta << true;
+}
+
+void tst_QToolTip::task183679()
+{
+ QFETCH(Qt::Key, key);
+ QFETCH(bool, visible);
+
+ Widget_task183679 widget;
+ widget.show();
+ QApplication::setActiveWindow(&widget);
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(30);
+
+
+ widget.showDelayedToolTip(100);
+ QTest::qWait(300);
+ QTRY_VERIFY(QToolTip::isVisible());
+
+ QTest::keyPress(&widget, key);
+
+ // Important: the following delay must be larger than the duration of the timer potentially
+ // initiated by the key press (currently 300 msecs), but smaller than the minimum
+ // auto-close timeout (currently 10000 msecs)
+ QTest::qWait(1500);
+
+ QCOMPARE(QToolTip::isVisible(), visible);
+}
+
+#include <QWhatsThis>
+
+void tst_QToolTip::whatsThis()
+{
+ qApp->setStyleSheet( "QWidget { font-size: 72px; }" );
+ QWhatsThis::showText(QPoint(0,0), "THis is text");
+ QTest::qWait(400);
+ QWidget *whatsthis = 0;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget->inherits("QWhatsThat")) {
+ whatsthis = widget;
+ break;
+ }
+ }
+ QVERIFY(whatsthis);
+ QVERIFY(whatsthis->isVisible());
+ QVERIFY(whatsthis->height() > 100); // Test QTBUG-2416
+ qApp->setStyleSheet("");
+}
+
+
+void tst_QToolTip::setPalette()
+{
+ //the previous test may still have a tooltip pending for deletion
+ QVERIFY(!QToolTip::isVisible());
+
+ QToolTip::showText(QPoint(), "tool tip text", 0);
+
+ QTRY_VERIFY(QToolTip::isVisible());
+
+ QWidget *toolTip = 0;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget->windowType() == Qt::ToolTip
+ && widget->objectName() == QLatin1String("qtooltip_label"))
+ {
+ toolTip = widget;
+ break;
+ }
+ }
+
+ QVERIFY(toolTip);
+ QTRY_VERIFY(toolTip->isVisible());
+
+ const QPalette oldPalette = toolTip->palette();
+ QPalette newPalette = oldPalette;
+ newPalette.setColor(QPalette::ToolTipBase, Qt::red);
+ newPalette.setColor(QPalette::ToolTipText, Qt::blue);
+ QToolTip::setPalette(newPalette);
+ QCOMPARE(toolTip->palette(), newPalette);
+}
+
+QTEST_MAIN(tst_QToolTip)
+#include "tst_qtooltip.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/.gitignore b/tests/auto/widgets/kernel/qwidget/.gitignore
new file mode 100644
index 0000000000..82a0ac9eba
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/.gitignore
@@ -0,0 +1 @@
+tst_qwidget
diff --git a/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat b/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat
new file mode 100644
index 0000000000..9802ee8b9e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat b/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat
new file mode 100644
index 0000000000..df5bc2f94e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/geometry.dat b/tests/auto/widgets/kernel/qwidget/geometry.dat
new file mode 100644
index 0000000000..e5dcb2dc44
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/geometry.dat
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
new file mode 100644
index 0000000000..9c34e0c254
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -0,0 +1,23 @@
+load(qttest_p4)
+
+QT += widgets core-private gui-private widgets-private
+
+SOURCES += tst_qwidget.cpp
+RESOURCES = qwidget.qrc
+
+aix-g++*:QMAKE_CXXFLAGS+=-fpermissive
+
+CONFIG += x11inc
+
+mac:!qpa {
+ LIBS += -framework Security -framework AppKit -framework Carbon
+ OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm
+}
+
+x11 {
+ LIBS += $$QMAKE_LIBS_X11
+}
+
+!wince*:win32: LIBS += -luser32 -lgdi32
+
+CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.qrc b/tests/auto/widgets/kernel/qwidget/qwidget.qrc
new file mode 100644
index 0000000000..1399c4c9db
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>geometry.dat</file>
+ <file>geometry-maximized.dat</file>
+ <file>geometry-fullscreen.dat</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap
new file mode 100644
index 0000000000..b3473cdefe
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap
new file mode 100644
index 0000000000..10007733ca
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap
new file mode 100644
index 0000000000..cde5964a30
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap
new file mode 100644
index 0000000000..23ea1410e4
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap
new file mode 100644
index 0000000000..a8918c1d1b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap
new file mode 100644
index 0000000000..0981cf5dd1
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap
new file mode 100644
index 0000000000..75d09136cf
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap
new file mode 100644
index 0000000000..f58f74d030
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
new file mode 100644
index 0000000000..ded0c5e061
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -0,0 +1,9472 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qboxlayout.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qdebug.h>
+#include <qeventloop.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qmessagebox.h>
+#include <qpainter.h>
+#include <qpoint.h>
+#include <qpushbutton.h>
+#include <qstyle.h>
+#include <qwidget.h>
+#include <qwindowsstyle.h>
+#include <qinputcontext.h>
+#include <qdesktopwidget.h>
+#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
+#include <qcalendarwidget.h>
+#include <qmainwindow.h>
+#include <qdockwidget.h>
+#include <qtoolbar.h>
+#include <QtGui/qpaintengine.h>
+#include <QtGui/qbackingstore.h>
+#include <QtGui/qguiapplication.h>
+#include <qmenubar.h>
+#include <qtableview.h>
+
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QGraphicsProxyWidget>
+
+#ifdef Q_WS_QWS
+# include <qscreen_qws.h>
+#endif
+
+// I *MUST* have QtTest afterwards or this test won't work with newer headers
+#if defined(Q_WS_MAC)
+# include <private/qt_mac_p.h>
+#undef verify
+#include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
+#endif
+
+#include <QtTest/QtTest>
+
+#if defined(Q_OS_WIN)
+# include <QtCore/qt_windows.h>
+# include <QtGui/private/qguiapplication_p.h>
+# include <QtGui/QPlatformNativeInterface>
+# include <QtGui/QPlatformIntegration>
+
+static HWND winHandleOf(const QWidget *w)
+{
+ static QPlatformNativeInterface *nativeInterface
+ = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
+ if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
+ return reinterpret_cast<HWND>(handle);
+ qWarning() << "Cannot obtain native handle for " << w;
+ return 0;
+}
+#endif
+
+#if defined(Q_WS_WIN)
+# include <qt_windows.h>
+# if !defined(Q_OS_WINCE)
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("desktop is not visible, this test would fail", SkipSingle);
+# else
+# define Q_CHECK_PAINTEVENTS
+# endif
+#elif defined(Q_WS_X11)
+# include <private/qt_x11_p.h>
+# include <qx11info_x11.h>
+#elif defined(Q_WS_QWS)
+# include <qwindowsystem_qws.h>
+#endif
+
+#if !defined(Q_WS_WIN)
+#define Q_CHECK_PAINTEVENTS
+#endif
+
+#if defined(Q_OS_WINCE_WM)
+#include <qguifunctions_wince.h>
+// taken from qguifunctions_wce.cpp
+#define SPI_GETPLATFORMTYPE 257
+bool qt_wince_is_platform(const QString &platformString) {
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
+ sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
+ return true;
+ return false;
+}
+bool qt_wince_is_smartphone() {
+ return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
+}
+#endif
+
+#ifdef Q_WS_MAC
+#include <Security/AuthSession.h>
+bool macHasAccessToWindowsServer()
+{
+ SecuritySessionId mySession;
+ SessionAttributeBits sessionInfo;
+ SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
+ return (sessionInfo & sessionHasGraphicAccess);
+}
+#endif
+
+
+#if defined(Bool)
+#undef Bool
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWidget();
+ virtual ~tst_QWidget();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void fontPropagation();
+ void fontPropagation2();
+ void palettePropagation();
+ void palettePropagation2();
+ void enabledPropagation();
+#ifndef QT_NO_DRAGANDDROP
+ void acceptDropsPropagation();
+#endif
+ void isEnabledTo();
+ void visible();
+ void visible_setWindowOpacity();
+ void isVisibleTo();
+ void isHidden();
+ void fonts();
+ void mapFromAndTo_data();
+ void mapFromAndTo();
+ void focusChainOnHide();
+ void focusChainOnReparent();
+ void setTabOrder();
+#ifdef Q_WS_WIN
+ void activation();
+#endif
+ void reparent();
+#ifndef Q_WS_X11
+ void windowState();
+#endif
+ void showMaximized();
+ void showFullScreen();
+ void showMinimized();
+ void showMinimizedKeepsFocus();
+#ifndef Q_WS_QWS
+ void icon();
+#endif
+ void hideWhenFocusWidgetIsChild();
+#ifndef Q_OS_IRIX
+ void normalGeometry();
+#endif
+ void setGeometry();
+#ifndef Q_OS_WINCE
+ void windowOpacity();
+#endif
+ void raise();
+ void lower();
+#ifndef QT_MAC_USE_COCOA
+ void stackUnder();
+#endif
+ void testContentsPropagation();
+#ifndef Q_OS_IRIX
+ void saveRestoreGeometry();
+ void restoreVersion1Geometry_data();
+ void restoreVersion1Geometry();
+#endif
+
+ void widgetAt();
+#ifdef Q_WS_MAC
+ void retainHIView();
+ void sheetOpacity();
+ void setMask();
+#endif
+ void optimizedResizeMove();
+ void optimizedResize_topLevel();
+ void resizeEvent();
+ void task110173();
+
+ void testDeletionInEventHandlers();
+
+ void childDeletesItsSibling();
+
+ void setMinimumSize();
+ void setMaximumSize();
+ void setFixedSize();
+
+ void ensureCreated();
+ void winIdChangeEvent();
+ void persistentWinId();
+ void showNativeChild();
+ void qobject_castInDestroyedSlot();
+
+ void showHideEvent_data();
+ void showHideEvent();
+
+ void lostUpdatesOnHide();
+
+ void update();
+ void isOpaque();
+
+#ifndef Q_WS_MAC
+ void scroll();
+#endif
+
+#ifndef Q_WS_X11
+ // tests QWidget::setGeometry()
+ void setWindowGeometry_data();
+ void setWindowGeometry();
+#endif
+
+#if !defined(Q_WS_X11) && !defined(Q_OS_IRIX)
+ // tests QWidget::move() and resize()
+ void windowMoveResize_data();
+ void windowMoveResize();
+#endif
+
+ void moveChild_data();
+ void moveChild();
+ void showAndMoveChild();
+
+#ifndef QT_MAC_USE_COCOA
+ void subtractOpaqueSiblings();
+#endif
+
+#ifdef Q_WS_WIN
+ void getDC();
+#ifndef Q_OS_WINCE
+ void setGeometry_win();
+#endif
+#endif
+
+ void setLocale();
+ void deleteStyle();
+ void multipleToplevelFocusCheck();
+ void setFocus();
+ void setCursor();
+ void setToolTip();
+ void testWindowIconChangeEventPropagation();
+#ifdef Q_WS_X11
+ void minAndMaxSizeWithX11BypassWindowManagerHint();
+ void showHideShow();
+ void clean_qt_x11_enforce_cursor();
+#endif
+
+ void compatibilityChildInsertedEvents();
+ void render();
+ void renderInvisible();
+ void renderWithPainter();
+ void render_task188133();
+ void render_task211796();
+ void render_task217815();
+#ifndef Q_OS_WINCE
+ void render_windowOpacity();
+#endif
+ void render_systemClip();
+ void render_systemClip2_data();
+ void render_systemClip2();
+ void render_systemClip3_data();
+ void render_systemClip3();
+ void render_task252837();
+ void render_worldTransform();
+
+ void setContentsMargins();
+
+#ifndef Q_OS_IRIX
+ void moveWindowInShowEvent_data();
+ void moveWindowInShowEvent();
+#endif
+
+ void repaintWhenChildDeleted();
+ void hideOpaqueChildWhileHidden();
+#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
+ void updateWhileMinimized();
+#endif
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ void alienWidgets();
+#endif
+ void adjustSize();
+ void adjustSize_data();
+ void updateGeometry();
+ void updateGeometry_data();
+ void sendUpdateRequestImmediately();
+#ifndef Q_OS_IRIX
+ void doubleRepaint();
+#endif
+#ifndef Q_WS_MAC
+ void resizeInPaintEvent();
+ void opaqueChildren();
+#endif
+
+ void setMaskInResizeEvent();
+ void moveInResizeEvent();
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ // We don't support immediate repaint right after show on
+ // other platforms. Must be compatible with Qt 4.3.
+ void immediateRepaintAfterShow();
+ void immediateRepaintAfterInvalidateBuffer();
+#endif
+ void effectiveWinId();
+ void effectiveWinId2();
+ void customDpi();
+ void customDpiProperty();
+
+ void quitOnCloseAttribute();
+ void moveRect();
+
+#if defined (Q_WS_WIN)
+ void gdiPainting();
+ void paintOnScreenPossible();
+#endif
+ void reparentStaticWidget();
+ void QTBUG6883_reparentStaticWidget2();
+#ifdef Q_WS_QWS
+ void updateOutsideSurfaceClip();
+#endif
+ void translucentWidget();
+
+ void setClearAndResizeMask();
+ void maskedUpdate();
+#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE_WM)) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ void syntheticEnterLeave();
+ void taskQTBUG_4055_sendSyntheticEnterLeave();
+#endif
+ void windowFlags();
+ void initialPosForDontShowOnScreenWidgets();
+#ifdef Q_WS_X11
+ void paintOutsidePaintEvent();
+#endif
+ void updateOnDestroyedSignal();
+ void toplevelLineEditFocus();
+ void inputFocus_task257832();
+
+ void focusWidget_task254563();
+#ifndef Q_OS_WINCE_WM
+ void rectOutsideCoordinatesLimit_task144779();
+#endif
+ void setGraphicsEffect();
+
+#ifdef QT_BUILD_INTERNAL
+ void destroyBackingStore();
+#endif
+
+ void activateWindow();
+
+ void openModal_taskQTBUG_5804();
+
+ void focusProxyAndInputMethods();
+#ifdef QT_BUILD_INTERNAL
+ void scrollWithoutBackingStore();
+#endif
+
+ void taskQTBUG_7532_tabOrderWithFocusProxy();
+ void movedAndResizedAttributes();
+ void childAt();
+#ifdef Q_WS_MAC
+ void childAt_unifiedToolBar();
+ void taskQTBUG_11373();
+#endif
+ void taskQTBUG_17333_ResizeInfiniteRecursion();
+
+ void nativeChildFocus();
+
+private:
+ bool ensureScreenSize(int width, int height);
+ QWidget *testWidget;
+};
+
+bool tst_QWidget::ensureScreenSize(int width, int height)
+{
+ QSize available;
+#ifdef Q_WS_QWS
+ available = QDesktopWidget().availableGeometry().size();
+ if (available.width() < width || available.height() < height) {
+ QScreen *screen = QScreen::instance();
+ if (!screen)
+ return false;
+ screen->setMode(width, height, screen->depth());
+ }
+#endif // Q_WS_QWS
+
+ available = QDesktopWidget().availableGeometry().size();
+ return (available.width() >= width && available.height() >= height);
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : QInputContext() {}
+ QString identifierName() { return QString("NoName"); }
+ QString language() { return QString("NoLanguage"); }
+ void reset() {}
+ bool isComposing() const { return false; }
+};
+
+// Testing get/set functions
+void tst_QWidget::getSetCheck()
+{
+ QWidget obj1;
+ QWidget child1(&obj1);
+ // QStyle * QWidget::style()
+ // void QWidget::setStyle(QStyle *)
+ QWindowsStyle *var1 = new QWindowsStyle;
+ obj1.setStyle(var1);
+ QCOMPARE(static_cast<QStyle *>(var1), obj1.style());
+ obj1.setStyle((QStyle *)0);
+ QVERIFY(var1 != obj1.style());
+ QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
+
+ // int QWidget::minimumWidth()
+ // void QWidget::setMinimumWidth(int)
+ obj1.setMinimumWidth(0);
+ QCOMPARE(obj1.minimumWidth(), 0);
+ obj1.setMinimumWidth(INT_MIN);
+ QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
+ obj1.setMinimumWidth(INT_MAX);
+#ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen
+ QCOMPARE(obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+#endif
+
+ child1.setMinimumWidth(0);
+ QCOMPARE(child1.minimumWidth(), 0);
+ child1.setMinimumWidth(INT_MIN);
+ QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
+ child1.setMinimumWidth(INT_MAX);
+ QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+
+ // int QWidget::minimumHeight()
+ // void QWidget::setMinimumHeight(int)
+ obj1.setMinimumHeight(0);
+ QCOMPARE(obj1.minimumHeight(), 0);
+ obj1.setMinimumHeight(INT_MIN);
+ QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
+ obj1.setMinimumHeight(INT_MAX);
+#ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen
+ QCOMPARE(obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+#endif
+
+ child1.setMinimumHeight(0);
+ QCOMPARE(child1.minimumHeight(), 0);
+ child1.setMinimumHeight(INT_MIN);
+ QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
+ child1.setMinimumHeight(INT_MAX);
+ QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+
+ // int QWidget::maximumWidth()
+ // void QWidget::setMaximumWidth(int)
+ obj1.setMaximumWidth(0);
+ QCOMPARE(obj1.maximumWidth(), 0);
+ obj1.setMaximumWidth(INT_MIN);
+ QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
+ obj1.setMaximumWidth(INT_MAX);
+ QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
+
+ // int QWidget::maximumHeight()
+ // void QWidget::setMaximumHeight(int)
+ obj1.setMaximumHeight(0);
+ QCOMPARE(obj1.maximumHeight(), 0);
+ obj1.setMaximumHeight(INT_MIN);
+ QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
+ obj1.setMaximumHeight(INT_MAX);
+ QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
+
+ // back to normal
+ obj1.setMinimumWidth(0);
+ obj1.setMinimumHeight(0);
+ obj1.setMaximumWidth(QWIDGETSIZE_MAX);
+ obj1.setMaximumHeight(QWIDGETSIZE_MAX);
+
+ // const QPalette & QWidget::palette()
+ // void QWidget::setPalette(const QPalette &)
+ QPalette var6;
+ obj1.setPalette(var6);
+ QCOMPARE(var6, obj1.palette());
+ obj1.setPalette(QPalette());
+ QCOMPARE(QPalette(), obj1.palette());
+
+ // const QFont & QWidget::font()
+ // void QWidget::setFont(const QFont &)
+ QFont var7;
+ obj1.setFont(var7);
+ QCOMPARE(var7, obj1.font());
+ obj1.setFont(QFont());
+ QCOMPARE(QFont(), obj1.font());
+
+ // qreal QWidget::windowOpacity()
+ // void QWidget::setWindowOpacity(qreal)
+ obj1.setWindowOpacity(0.0);
+ QCOMPARE(0.0, obj1.windowOpacity());
+ obj1.setWindowOpacity(1.1f);
+ QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
+
+ // QWidget * QWidget::focusProxy()
+ // void QWidget::setFocusProxy(QWidget *)
+ QWidget *var9 = new QWidget();
+ obj1.setFocusProxy(var9);
+ QCOMPARE(var9, obj1.focusProxy());
+ obj1.setFocusProxy((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.focusProxy());
+ delete var9;
+
+ // const QRect & QWidget::geometry()
+ // void QWidget::setGeometry(const QRect &)
+ qApp->processEvents();
+ QRect var10(10, 10, 100, 100);
+ obj1.setGeometry(var10);
+ qApp->processEvents();
+ qDebug() << obj1.geometry();
+ QCOMPARE(var10, obj1.geometry());
+ obj1.setGeometry(QRect(0,0,0,0));
+ qDebug() << obj1.geometry();
+ QCOMPARE(QRect(0,0,0,0), obj1.geometry());
+
+ // QLayout * QWidget::layout()
+ // void QWidget::setLayout(QLayout *)
+ QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
+ obj1.setLayout(var11);
+ QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
+ obj1.setLayout((QLayout *)0);
+ QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
+ delete var11; // This will remove the layout from the widget
+ QCOMPARE((QLayout *)0, obj1.layout());
+
+ // bool QWidget::acceptDrops()
+ // void QWidget::setAcceptDrops(bool)
+ obj1.setAcceptDrops(false);
+ QCOMPARE(false, obj1.acceptDrops());
+ obj1.setAcceptDrops(true);
+ QCOMPARE(true, obj1.acceptDrops());
+
+ // QInputContext * QWidget::inputContext()
+ MyInputContext *var13 = new MyInputContext;
+ qApp->setInputContext(var13);
+ QCOMPARE((QInputContext *)0, obj1.inputContext()); // The widget by default doesn't have the WA_InputMethodEnabled attribute
+ obj1.setAttribute(Qt::WA_InputMethodEnabled);
+ QCOMPARE(static_cast<QInputContext *>(var13), obj1.inputContext());
+
+ // bool QWidget::autoFillBackground()
+ // void QWidget::setAutoFillBackground(bool)
+ obj1.setAutoFillBackground(false);
+ QCOMPARE(false, obj1.autoFillBackground());
+ obj1.setAutoFillBackground(true);
+ QCOMPARE(true, obj1.autoFillBackground());
+
+ delete var1;
+#if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
+ obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
+ HWND handle = obj1.winId();
+ long flags = GetWindowLong(handle, GWL_STYLE);
+ QVERIFY(flags & WS_POPUP);
+#endif
+}
+
+tst_QWidget::tst_QWidget()
+{
+ QFont font;
+ font.setBold(true);
+ font.setPointSize(42);
+ qApp->setFont(font, "QPropagationTestWidget");
+
+ QPalette palette;
+ palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
+ palette.setColor(QPalette::Text, QColor(21, 22, 23));
+ qApp->setPalette(palette, "QPropagationTestWidget");
+
+ testWidget = 0;
+}
+
+tst_QWidget::~tst_QWidget()
+{
+}
+
+class BezierViewer : public QWidget {
+public:
+ BezierViewer( QWidget* parent=0, const char* name=0 );
+ void paintEvent( QPaintEvent* );
+ void setPoints( const QPolygonF& poly );
+private:
+ QPolygonF points;
+
+};
+
+void tst_QWidget::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+ // Create the test class
+ testWidget = new BezierViewer( 0, "testObject");
+ testWidget->resize(200,200);
+ testWidget->show();
+ QTest::qWaitForWindowShown(testWidget);
+ QTest::qWait(50);
+}
+
+void tst_QWidget::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QWidget::init()
+{
+// TODO: Add initialization code here.
+// This will be executed immediately before each test is run.
+ testWidget->setFont(QFont());
+ testWidget->setPalette(QPalette());
+}
+
+void tst_QWidget::cleanup()
+{
+}
+
+// Helper class...
+
+BezierViewer::BezierViewer( QWidget* parent, const char* name )
+ : QWidget( parent )
+{
+ setObjectName(name);
+ QPalette pal;
+ pal.setColor(backgroundRole(), Qt::white);
+ setPalette(pal);
+}
+
+
+void BezierViewer::setPoints( const QPolygonF& a )
+{
+ points = a;
+}
+
+#include "private/qbezier_p.h"
+void BezierViewer::paintEvent( QPaintEvent* )
+{
+ if ( points.size() != 4 ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QPolygon::bezier: The array must have 4 control points" );
+#endif
+ return;
+ }
+
+ /* Calculate Bezier curve */
+ QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
+
+ QPainter painter( this );
+
+ /* Calculate scale to fit in window */
+ QRectF br = bezier.boundingRect() | points.boundingRect();
+ QRectF pr = rect();
+ int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
+ int border = scl-1;
+
+ /* Scale Bezier curve vertices */
+ for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
+ it->setX( (it->x()-br.x()) * scl + border );
+ it->setY( (it->y()-br.y()) * scl + border );
+ }
+
+ /* Draw grid */
+ painter.setPen( Qt::lightGray );
+ int i;
+ for ( i = border; i <= pr.width(); i += scl ) {
+ painter.drawLine( i, 0, i, pr.height() );
+ }
+ for ( int j = border; j <= pr.height(); j += scl ) {
+ painter.drawLine( 0, j, pr.width(), j );
+ }
+
+ /* Write number of vertices */
+ painter.setPen( Qt::red );
+ painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, TRUE ) );
+ QString caption;
+ caption.setNum( bezier.size() );
+ caption += QString::fromLatin1( " vertices" );
+ painter.drawText( 10, pr.height()-10, caption );
+
+ /* Draw Bezier curve */
+ painter.setPen( Qt::black );
+ painter.drawPolyline( bezier );
+
+ /* Scale and draw control points */
+ painter.setPen( Qt::darkGreen );
+ for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
+ int x = (p1->x()-br.x()) * scl + border;
+ int y = (p1->y()-br.y()) * scl + border;
+ painter.drawLine( x-4, y-4, x+4, y+4 );
+ painter.drawLine( x+4, y-4, x-4, y+4 );
+ }
+
+ /* Draw vertices */
+ painter.setPen( Qt::red );
+ painter.setBrush( Qt::red );
+ for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
+ painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
+}
+
+void tst_QWidget::fontPropagation()
+{
+ QFont font = testWidget->font();
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QCOMPARE( font, childWidget->font() );
+
+ font.setBold( TRUE );
+ testWidget->setFont( font );
+ QCOMPARE( font, testWidget->font() );
+ QCOMPARE( font, childWidget->font() );
+
+ QFont newFont = font;
+ newFont.setItalic( TRUE );
+ childWidget->setFont( newFont );
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QCOMPARE( font, testWidget->font() );
+ QCOMPARE( newFont, grandChildWidget->font() );
+
+ font.setUnderline( TRUE );
+ testWidget->setFont( font );
+
+ // the child and grand child should now have merged bold and
+ // underline
+ newFont.setUnderline( TRUE );
+
+ QCOMPARE( newFont, childWidget->font() );
+ QCOMPARE( newFont, grandChildWidget->font() );
+
+ // make sure font propagation continues working after reparenting
+ font = testWidget->font();
+ font.setPointSize(font.pointSize() + 2);
+ testWidget->setFont(font);
+
+ QWidget *one = new QWidget(testWidget);
+ QWidget *two = new QWidget(one);
+ QWidget *three = new QWidget(two);
+ QWidget *four = new QWidget(two);
+
+ four->setParent(three);
+ four->move(QPoint(0,0));
+
+ font.setPointSize(font.pointSize() + 2);
+ testWidget->setFont(font);
+
+ QCOMPARE(testWidget->font(), one->font());
+ QCOMPARE(one->font(), two->font());
+ QCOMPARE(two->font(), three->font());
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! one->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! two->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ one->setFont(font);
+
+ QCOMPARE(one->font(), two->font());
+ QCOMPARE(two->font(), three->font());
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(one->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! two->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ two->setFont(font);
+
+ QCOMPARE(two->font(), three->font());
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(two->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ three->setFont(font);
+
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ four->setFont(font);
+
+ QVERIFY(four->testAttribute(Qt::WA_SetFont));
+}
+
+class QPropagationTestWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ QPropagationTestWidget(QWidget *parent = 0)
+ : QWidget(parent)
+ { }
+};
+
+void tst_QWidget::fontPropagation2()
+{
+ // ! Note, the code below is executed in tst_QWidget's constructor.
+ // QFont font;
+ // font.setBold(true);
+ // font.setPointSize(42);
+ // qApp->setFont(font, "QPropagationTestWidget");
+
+ QWidget *root = new QWidget;
+ QWidget *child0 = new QWidget(root);
+ QWidget *child1 = new QWidget(child0);
+ QWidget *child2 = new QPropagationTestWidget(child1);
+ QWidget *child3 = new QWidget(child2);
+ QWidget *child4 = new QWidget(child3);
+ QWidget *child5 = new QWidget(child4);
+ root->show();
+
+ // Check that only the application fonts apply.
+ QCOMPARE(root->font(), QApplication::font());
+ QCOMPARE(child0->font(), QApplication::font());
+ QCOMPARE(child1->font(), QApplication::font());
+ QCOMPARE(child2->font().pointSize(), 42);
+ QVERIFY(child2->font().bold());
+ QCOMPARE(child3->font().pointSize(), 42);
+ QVERIFY(child3->font().bold());
+ QCOMPARE(child4->font().pointSize(), 42);
+ QVERIFY(child4->font().bold());
+ QCOMPARE(child5->font().pointSize(), 42);
+ QVERIFY(child5->font().bold());
+
+ // Set child0's font size to 15, and remove bold on child4.
+ QFont font;
+ font.setPointSize(15);
+ child0->setFont(font);
+ QFont unboldFont;
+ unboldFont.setBold(false);
+ child4->setFont(unboldFont);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->font(), QApplication::font());
+ QCOMPARE(child0->font().pointSize(), 15);
+ QVERIFY(!child0->font().bold());
+ QCOMPARE(child1->font().pointSize(), 15);
+ QVERIFY(!child1->font().bold());
+ QCOMPARE(child2->font().pointSize(), 15);
+ QVERIFY(child2->font().bold());
+ QCOMPARE(child3->font().pointSize(), 15);
+ QVERIFY(child3->font().bold());
+ QCOMPARE(child4->font().pointSize(), 15);
+ QVERIFY(!child4->font().bold());
+ QCOMPARE(child5->font().pointSize(), 15);
+ QVERIFY(!child5->font().bold());
+
+ // Replace the app font for child2. Italic should propagate
+ // but the size should still be ignored. The previous bold
+ // setting is gone.
+ QFont italicSizeFont;
+ italicSizeFont.setItalic(true);
+ italicSizeFont.setPointSize(33);
+ qApp->setFont(italicSizeFont, "QPropagationTestWidget");
+
+ // Check that this propagates correctly.
+ QCOMPARE(root->font(), QApplication::font());
+ QCOMPARE(child0->font().pointSize(), 15);
+ QVERIFY(!child0->font().bold());
+ QVERIFY(!child0->font().italic());
+ QCOMPARE(child1->font().pointSize(), 15);
+ QVERIFY(!child1->font().bold());
+ QVERIFY(!child1->font().italic());
+ QCOMPARE(child2->font().pointSize(), 15);
+ QVERIFY(!child2->font().bold());
+ QVERIFY(child2->font().italic());
+ QCOMPARE(child3->font().pointSize(), 15);
+ QVERIFY(!child3->font().bold());
+ QVERIFY(child3->font().italic());
+ QCOMPARE(child4->font().pointSize(), 15);
+ QVERIFY(!child4->font().bold());
+ QVERIFY(child4->font().italic());
+ QCOMPARE(child5->font().pointSize(), 15);
+ QVERIFY(!child5->font().bold());
+ QVERIFY(child5->font().italic());
+}
+
+void tst_QWidget::palettePropagation()
+{
+ QPalette palette = testWidget->palette();
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QCOMPARE( palette, childWidget->palette() );
+
+ palette.setColor( QPalette::Base, Qt::red );
+ testWidget->setPalette( palette );
+ QCOMPARE( palette, testWidget->palette() );
+ QCOMPARE( palette, childWidget->palette() );
+
+ QPalette newPalette = palette;
+ newPalette.setColor( QPalette::Highlight, Qt::green );
+ childWidget->setPalette( newPalette );
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QCOMPARE( palette, testWidget->palette() );
+ QCOMPARE( newPalette, grandChildWidget->palette() );
+
+ palette.setColor( QPalette::Text, Qt::blue );
+ testWidget->setPalette( palette );
+
+ // the child and grand child should now have merged green
+ // highlight and blue text
+ newPalette.setColor( QPalette::Text, Qt::blue);
+
+ QCOMPARE( newPalette, childWidget->palette() );
+ QCOMPARE( newPalette, grandChildWidget->palette() );
+}
+
+void tst_QWidget::palettePropagation2()
+{
+ // ! Note, the code below is executed in tst_QWidget's constructor.
+ // QPalette palette;
+ // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
+ // font.setColor(QPalette::Text, QColor(21, 22, 23));
+ // qApp->setPalette(palette, "QPropagationTestWidget");
+
+ QWidget *root = new QWidget;
+ QWidget *child0 = new QWidget(root);
+ QWidget *child1 = new QWidget(child0);
+ QWidget *child2 = new QPropagationTestWidget(child1);
+ QWidget *child3 = new QWidget(child2);
+ QWidget *child4 = new QWidget(child3);
+ QWidget *child5 = new QWidget(child4);
+ root->show();
+ QTest::qWait(100);
+
+ // These colors are unlikely to be imposed on the default palette of
+ // QWidget ;-).
+ QColor sysPalText(21, 22, 23);
+ QColor sysPalToolTipBase(12, 13, 14);
+ QColor overridePalText(42, 43, 44);
+ QColor overridePalToolTipBase(45, 46, 47);
+ QColor sysPalButton(99, 98, 97);
+
+ // Check that only the application fonts apply.
+ QPalette appPal = QApplication::palette();
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette(), appPal);
+ QCOMPARE(child1->palette(), appPal);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+
+ // Set child0's Text, and set ToolTipBase on child4.
+ QPalette textPalette;
+ textPalette.setColor(QPalette::Text, overridePalText);
+ child0->setPalette(textPalette);
+ QPalette toolTipPalette;
+ toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
+ child4->setPalette(toolTipPalette);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+
+ // Replace the app palette for child2. Button should propagate but Text
+ // should still be ignored. The previous ToolTipBase setting is gone.
+ QPalette buttonPalette;
+ buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
+ qApp->setPalette(buttonPalette, "QPropagationTestWidget");
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
+ QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
+ QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
+ QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
+}
+
+void tst_QWidget::enabledPropagation()
+{
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ testWidget->setEnabled( FALSE );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ testWidget->setDisabled( FALSE );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( grandChildWidget->isEnabled() );
+
+ testWidget->setDisabled( TRUE );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( FALSE );
+ testWidget->setEnabled( TRUE );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( TRUE );
+ testWidget->setEnabled( FALSE );
+ childWidget->setDisabled( TRUE );
+ testWidget->setEnabled( TRUE );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+}
+
+// Drag'n drop disabled in this build.
+#ifndef QT_NO_DRAGANDDROP
+void tst_QWidget::acceptDropsPropagation()
+{
+ QWidget *childWidget = new QWidget(testWidget);
+ childWidget->show();
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+
+ testWidget->setAcceptDrops(true);
+ QVERIFY(testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ testWidget->setAcceptDrops(false);
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ QWidget *grandChildWidget = new QWidget(childWidget);
+ QVERIFY(!grandChildWidget->acceptDrops());
+ QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ testWidget->setAcceptDrops(true);
+ QVERIFY(testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
+ QVERIFY(!grandChildWidget->acceptDrops());
+ QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ grandChildWidget->setAcceptDrops(true);
+ testWidget->setAcceptDrops(false);
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(grandChildWidget->acceptDrops());
+ QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ grandChildWidget->setAcceptDrops(false);
+ QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+ testWidget->setAcceptDrops(true);
+ childWidget->setAcceptDrops(true);
+ testWidget->setAcceptDrops(false);
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(childWidget->acceptDrops());
+ QVERIFY(!grandChildWidget->acceptDrops());
+ QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+}
+#endif
+
+void tst_QWidget::isEnabledTo()
+{
+ QWidget* childWidget = new QWidget( testWidget );
+ QWidget* grandChildWidget = new QWidget( childWidget );
+
+ QVERIFY( childWidget->isEnabledTo( testWidget ) );
+ QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
+
+ childWidget->setEnabled( FALSE );
+ QVERIFY( !childWidget->isEnabledTo( testWidget ) );
+ QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
+ QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
+}
+
+void tst_QWidget::visible()
+{
+ // Ensure that the testWidget is hidden for this test at the
+ // start
+
+ testWidget->hide();
+ QVERIFY( !testWidget->isVisible() );
+ QWidget* childWidget = new QWidget( testWidget );
+ QVERIFY( !childWidget->isVisible() );
+
+ testWidget->show();
+ QVERIFY( testWidget->isVisible() );
+ QVERIFY( childWidget->isVisible() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( !grandChildWidget->isVisible() );
+ grandChildWidget->show();
+ QVERIFY( grandChildWidget->isVisible() );
+
+ grandChildWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( !grandChildWidget->isVisible() );
+ QVERIFY( testWidget->isVisible() );
+ QVERIFY( childWidget->isVisible() );
+
+ grandChildWidget->show();
+ childWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( testWidget->isVisible() );
+ QVERIFY( !childWidget->isVisible() );
+ QVERIFY( !grandChildWidget->isVisible() );
+
+ grandChildWidget->show();
+ QVERIFY( !grandChildWidget->isVisible() );
+}
+
+void tst_QWidget::setLocale()
+{
+ QWidget w;
+ QCOMPARE(w.locale(), QLocale());
+
+ w.setLocale(QLocale::Italian);
+ QCOMPARE(w.locale(), QLocale(QLocale::Italian));
+
+ QWidget child1(&w);
+ QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
+
+ w.unsetLocale();
+ QCOMPARE(w.locale(), QLocale());
+ QCOMPARE(child1.locale(), QLocale());
+
+ w.setLocale(QLocale::French);
+ QCOMPARE(w.locale(), QLocale(QLocale::French));
+ QCOMPARE(child1.locale(), QLocale(QLocale::French));
+
+ child1.setLocale(QLocale::Italian);
+ QCOMPARE(w.locale(), QLocale(QLocale::French));
+ QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
+
+ child1.unsetLocale();
+ QCOMPARE(w.locale(), QLocale(QLocale::French));
+ QCOMPARE(child1.locale(), QLocale(QLocale::French));
+
+ QWidget child2;
+ QCOMPARE(child2.locale(), QLocale());
+ child2.setParent(&w);
+ QCOMPARE(child2.locale(), QLocale(QLocale::French));
+}
+
+void tst_QWidget::visible_setWindowOpacity()
+{
+ testWidget->hide();
+ QVERIFY( !testWidget->isVisible() );
+ testWidget->setWindowOpacity(0.5);
+#ifdef Q_OS_WIN
+ QVERIFY(::IsWindowVisible(winHandleOf(testWidget)) == FALSE);
+#endif
+ testWidget->setWindowOpacity(1.0);
+}
+
+void tst_QWidget::isVisibleTo()
+{
+ // Ensure that the testWidget is hidden for this test at the
+ // start
+
+ testWidget->hide();
+ QWidget* childWidget = new QWidget( testWidget );
+ QVERIFY( childWidget->isVisibleTo( testWidget ) );
+ childWidget->hide();
+ QVERIFY( !childWidget->isVisibleTo( testWidget ) );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
+ QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
+
+ testWidget->show();
+ childWidget->show();
+
+ QVERIFY( childWidget->isVisibleTo( testWidget ) );
+ grandChildWidget->hide();
+ QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
+ QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
+
+}
+
+void tst_QWidget::isHidden()
+{
+ // Ensure that the testWidget is hidden for this test at the
+ // start
+
+ testWidget->hide();
+ QVERIFY( testWidget->isHidden() );
+ QWidget* childWidget = new QWidget( testWidget );
+ QVERIFY( !childWidget->isHidden() );
+
+ testWidget->show();
+ QVERIFY( !testWidget->isHidden() );
+ QVERIFY( !childWidget->isHidden() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( grandChildWidget->isHidden() );
+ grandChildWidget->show();
+ QVERIFY( !grandChildWidget->isHidden() );
+
+ grandChildWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( grandChildWidget->isHidden() );
+ QVERIFY( !testWidget->isHidden() );
+ QVERIFY( !childWidget->isHidden() );
+
+ grandChildWidget->show();
+ childWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( !testWidget->isHidden() );
+ QVERIFY( childWidget->isHidden() );
+ QVERIFY( !grandChildWidget->isHidden() );
+
+ grandChildWidget->show();
+ QVERIFY( !grandChildWidget->isHidden() );
+}
+
+void tst_QWidget::fonts()
+{
+ // Tests setFont(), ownFont() and unsetFont()
+ QWidget* cleanTestWidget = new QWidget( testWidget );
+ QFont originalFont = cleanTestWidget->font();
+
+ QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+ cleanTestWidget->setFont(QFont());
+ QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+
+ QFont newFont( "times", 18 );
+ cleanTestWidget->setFont( newFont );
+ newFont = newFont.resolve( testWidget->font() );
+
+ QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+ QVERIFY( cleanTestWidget->font() == newFont );
+
+ cleanTestWidget->setFont(QFont());
+ QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+ QVERIFY( cleanTestWidget->font() == originalFont );
+}
+
+void tst_QWidget::mapFromAndTo_data()
+{
+ QTest::addColumn<bool>("windowHidden");
+ QTest::addColumn<bool>("subWindow1Hidden");
+ QTest::addColumn<bool>("subWindow2Hidden");
+ QTest::addColumn<bool>("subSubWindowHidden");
+ QTest::addColumn<bool>("windowMinimized");
+ QTest::addColumn<bool>("subWindow1Minimized");
+
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
+
+
+}
+
+void tst_QWidget::mapFromAndTo()
+{
+ QFETCH(bool, windowHidden);
+ QFETCH(bool, subWindow1Hidden);
+ QFETCH(bool, subWindow2Hidden);
+ QFETCH(bool, subSubWindowHidden);
+ QFETCH(bool, windowMinimized);
+ QFETCH(bool, subWindow1Minimized);
+
+ // create a toplevel and two overlapping siblings
+ QWidget window;
+ window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
+ QWidget *subWindow1 = new QWidget(&window);
+ QWidget *subWindow2 = new QWidget(&window);
+ QWidget *subSubWindow = new QWidget(subWindow1);
+
+ // set their geometries
+ window.setGeometry(100, 100, 100, 100);
+ subWindow1->setGeometry(50, 50, 100, 100);
+ subWindow2->setGeometry(75, 75, 100, 100);
+ subSubWindow->setGeometry(10, 10, 10, 10);
+
+#if !defined (Q_OS_WINCE) //still no proper minimizing
+ //update visibility
+ if (windowMinimized) {
+ if (!windowHidden) {
+ window.showMinimized();
+ QVERIFY(window.isMinimized());
+ }
+ } else {
+ window.setVisible(!windowHidden);
+ }
+ if (subWindow1Minimized) {
+ subWindow1->hide();
+ subWindow1->showMinimized();
+ QVERIFY(subWindow1->isMinimized());
+ } else {
+ subWindow1->setVisible(!subWindow1Hidden);
+ }
+#else
+ Q_UNUSED(windowHidden);
+ Q_UNUSED(subWindow1Hidden);
+ Q_UNUSED(windowMinimized);
+ Q_UNUSED(subWindow1Minimized);
+#endif
+
+ subWindow2->setVisible(!subWindow2Hidden);
+ subSubWindow->setVisible(!subSubWindowHidden);
+
+ // window
+ QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
+ QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
+ QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
+ QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
+ QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
+ QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
+ QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
+ QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
+ QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
+ QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
+ QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
+ QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
+ QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
+ QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
+ QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
+ QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
+ QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
+ QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
+ QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
+ QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
+ QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
+ QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
+ QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
+ QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
+ QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
+ QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
+ QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
+ QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
+ QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
+ QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
+ QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
+ QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
+
+ // first subwindow
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
+ QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
+ QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
+ QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
+ QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
+ QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
+ QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
+ QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
+ QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
+
+ // subsubwindow
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
+}
+
+void tst_QWidget::focusChainOnReparent()
+{
+ QWidget window;
+ QWidget *child1 = new QWidget(&window);
+ QWidget *child2 = new QWidget(&window);
+ QWidget *child3 = new QWidget(&window);
+ QWidget *child21 = new QWidget(child2);
+ QWidget *child22 = new QWidget(child2);
+ QWidget *child4 = new QWidget(&window);
+
+ QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window};
+ QWidget *w = &window;
+ for (int i = 0; i <8; ++i) {
+ QCOMPARE(w, expectedOriginalChain[i]);
+ w = w->nextInFocusChain();
+ }
+ for (int i = 7; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedOriginalChain[i]);
+ }
+
+ QWidget window2;
+ child2->setParent(&window2);
+
+ QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
+ w = &window2;
+ for (int i = 0; i <5; ++i) {
+ QCOMPARE(w, expectedNewChain[i]);
+ w = w->nextInFocusChain();
+ }
+ for (int i = 4; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedNewChain[i]);
+ }
+
+ QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
+ w = &window;
+ for (int i = 0; i <5; ++i) {
+ QCOMPARE(w, expectedOldChain[i]);
+ w = w->nextInFocusChain();
+ }
+ for (int i = 4; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedOldChain[i]);
+ }
+}
+
+
+void tst_QWidget::focusChainOnHide()
+{
+ testWidget->hide(); // We do not want to get disturbed by other widgets
+ // focus should move to the next widget in the focus chain when we hide it.
+ QWidget *parent = new QWidget();
+ parent->setObjectName(QLatin1String("Parent"));
+ parent->setFocusPolicy(Qt::StrongFocus);
+ QWidget *child = new QWidget(parent);
+ child->setObjectName(QLatin1String("child"));
+ child->setFocusPolicy(Qt::StrongFocus);
+ QWidget::setTabOrder(child, parent);
+
+ parent->show();
+ qApp->setActiveWindow(parent->window());
+ child->activateWindow();
+ child->setFocus();
+ qApp->processEvents();
+
+ QTRY_COMPARE(child->hasFocus(), true);
+ child->hide();
+ qApp->processEvents();
+
+ QTRY_COMPARE(parent->hasFocus(), true);
+ QCOMPARE(parent, qApp->focusWidget());
+
+ delete parent;
+ testWidget->show(); //don't disturb later tests
+}
+
+class Container : public QWidget
+{
+public:
+ QVBoxLayout* box;
+
+ Container()
+ {
+ box = new QVBoxLayout(this);
+ //(new QVBoxLayout(this))->setAutoAdd(true);
+ }
+
+ void tab()
+ {
+ focusNextPrevChild(TRUE);
+ }
+
+ void backTab()
+ {
+ focusNextPrevChild(FALSE);
+ }
+};
+
+class Composite : public QFrame
+{
+public:
+ Composite(QWidget* parent = 0, const char* name = 0)
+ : QFrame(parent)
+ {
+ setObjectName(name);
+ //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
+ //hbox->setAutoAdd(true);
+ QHBoxLayout* hbox = new QHBoxLayout(this);
+
+ lineEdit = new QLineEdit(this);
+ hbox->addWidget(lineEdit);
+
+ button = new QPushButton(this);
+ hbox->addWidget(button);
+ button->setFocusPolicy( Qt::NoFocus );
+
+ setFocusProxy( lineEdit );
+ setFocusPolicy( Qt::StrongFocus );
+
+ setTabOrder(lineEdit, button);
+ }
+
+private:
+ QLineEdit* lineEdit;
+ QPushButton* button;
+};
+
+#define NUM_WIDGETS 4
+
+void tst_QWidget::setTabOrder()
+{
+ QTest::qWait(100);
+
+ Container container;
+
+ Composite* comp[NUM_WIDGETS];
+
+ QLineEdit *firstEdit = new QLineEdit(&container);
+ container.box->addWidget(firstEdit);
+
+ int i = 0;
+ for(i = 0; i < NUM_WIDGETS; i++) {
+ comp[i] = new Composite(&container);
+ container.box->addWidget(comp[i]);
+ }
+
+ QLineEdit *lastEdit = new QLineEdit(&container);
+ container.box->addWidget(lastEdit);
+
+ container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
+ for(i = NUM_WIDGETS-1; i > 0; i--) {
+ container.setTabOrder(comp[i], comp[i-1]);
+ }
+ container.setTabOrder(comp[0], firstEdit);
+
+ int current = NUM_WIDGETS-1;
+ lastEdit->setFocus();
+
+ container.show();
+ container.activateWindow();
+ qApp->setActiveWindow(&container);
+#ifdef Q_WS_X11
+ QTest::qWaitForWindowShown(&container);
+ QTest::qWait(50);
+#endif
+
+ QTest::qWait(100);
+
+ QTRY_VERIFY(lastEdit->hasFocus());
+ container.tab();
+ do {
+ QVERIFY(comp[current]->focusProxy()->hasFocus());
+ container.tab();
+ current--;
+ } while (current >= 0);
+
+ QVERIFY(firstEdit->hasFocus());
+}
+
+#ifdef Q_WS_WIN
+void tst_QWidget::activation()
+{
+ Q_CHECK_PAINTEVENTS
+
+#if defined(Q_OS_WINCE)
+ int waitTime = 1000;
+#else
+ int waitTime = 100;
+#endif
+
+#ifdef Q_OS_WINCE
+ qApp->processEvents();
+#endif
+ QWidget widget1;
+ widget1.setWindowTitle("Widget1");
+
+ QWidget widget2;
+ widget2.setWindowTitle("Widget2");
+
+ widget1.show();
+ widget2.show();
+
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget2);
+ widget2.showMinimized();
+ QTest::qWait(waitTime);
+
+ QVERIFY(qApp->activeWindow() == &widget1);
+ widget2.showMaximized();
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget2);
+ widget2.showMinimized();
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget1);
+ widget2.showNormal();
+ QTest::qWait(waitTime);
+#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
+ QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
+#endif
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget2);
+ widget2.hide();
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget1);
+}
+#endif
+
+// Many window managers do not support window state properly, which causes this test to fail.
+#ifndef Q_WS_X11
+void tst_QWidget::windowState()
+{
+#ifdef Q_OS_WINCE_WM
+ QPoint pos(500, 500);
+ QSize size(200, 200);
+ if (qt_wince_is_smartphone()) { //small screen
+ pos = QPoint(10,10);
+ size = QSize(100,100);
+ }
+#else
+ const QPoint pos(500, 500);
+ const QSize size(200, 200);
+#endif
+
+ QWidget widget1;
+ widget1.move(pos);
+ widget1.resize(size);
+ QCOMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.size(), size);
+ QTest::qWait(100);
+ widget1.setWindowTitle("Widget1");
+ QCOMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.size(), size);
+
+#define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
+
+ const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
+
+ widget1.setWindowState(Qt::WindowMaximized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.show();
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ widget1.setWindowState(Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMinimized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
+ QTRY_COMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ widget1.setWindowState(Qt::WindowFullScreen);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowFullScreen);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowFullScreen);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(Qt::WindowNoState);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowNoState);
+ QTRY_COMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ widget1.setWindowState(Qt::WindowFullScreen);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowFullScreen);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ QVERIFY(!(widget1.windowState() & stateMask));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ QTRY_COMPARE(widget1.pos(), pos);
+ QTRY_COMPARE(widget1.size(), size);
+}
+#endif
+
+void tst_QWidget::showMaximized()
+{
+ QWidget plain;
+ QHBoxLayout *layout;
+ layout = new QHBoxLayout;
+ QWidget layouted;
+ QLineEdit le;
+ QLineEdit le2;
+ QLineEdit le3;
+
+ layout->addWidget(&le);
+ layout->addWidget(&le2);
+ layout->addWidget(&le3);
+
+ layouted.setLayout(layout);
+
+ plain.showMaximized();
+ QVERIFY(plain.windowState() & Qt::WindowMaximized);
+
+ plain.showNormal();
+ QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
+
+ layouted.showMaximized();
+ QVERIFY(layouted.windowState() & Qt::WindowMaximized);
+
+ layouted.showNormal();
+ QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
+
+#if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE) && !defined(Q_WS_QPA)
+//embedded may choose a different size to fit on the screen.
+ QCOMPARE(layouted.size(), layouted.sizeHint());
+#endif
+ layouted.showMaximized();
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ layouted.hide();
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(!layouted.isVisible());
+
+ layouted.showMaximized();
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+
+ layouted.showMaximized();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+
+ layouted.showMaximized();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ {
+ QWidget frame;
+ QWidget widget(&frame);
+ widget.showMaximized();
+ QVERIFY(widget.isMaximized());
+ }
+
+ {
+ QWidget widget;
+ widget.setGeometry(0, 0, 10, 10);
+ widget.showMaximized();
+ QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
+ }
+}
+
+void tst_QWidget::showFullScreen()
+{
+ QWidget plain;
+ QHBoxLayout *layout;
+ QWidget layouted;
+ QLineEdit le;
+ QLineEdit le2;
+ QLineEdit le3;
+ layout = new QHBoxLayout;
+
+ layout->addWidget(&le);
+ layout->addWidget(&le2);
+ layout->addWidget(&le3);
+
+ layouted.setLayout(layout);
+
+ plain.showFullScreen();
+ QVERIFY(plain.windowState() & Qt::WindowFullScreen);
+
+ plain.showNormal();
+ QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
+
+ layouted.showFullScreen();
+ QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
+
+ layouted.showNormal();
+ QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
+
+#if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE) && !defined(Q_WS_QPA)
+//embedded may choose a different size to fit on the screen.
+ QCOMPARE(layouted.size(), layouted.sizeHint());
+#endif
+
+ layouted.showFullScreen();
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ layouted.hide();
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(!layouted.isVisible());
+
+ layouted.showFullScreen();
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+
+ layouted.showFullScreen();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+
+ layouted.showFullScreen();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ {
+ QWidget frame;
+ QWidget widget(&frame);
+ widget.showFullScreen();
+ QVERIFY(widget.isFullScreen());
+ }
+}
+
+class ResizeWidget : public QWidget {
+public:
+ ResizeWidget(QWidget *p = 0) : QWidget(p)
+ {
+ m_resizeEventCount = 0;
+ }
+protected:
+ void resizeEvent(QResizeEvent *e){
+ QCOMPARE(size(), e->size());
+ ++m_resizeEventCount;
+ }
+
+public:
+ int m_resizeEventCount;
+};
+
+void tst_QWidget::resizeEvent()
+{
+ {
+ QWidget wParent;
+ ResizeWidget wChild(&wParent);
+ wParent.show();
+ QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
+ wParent.hide();
+ QSize safeSize(640,480);
+ if (wChild.size() == safeSize)
+ safeSize.setWidth(639);
+ wChild.resize(safeSize);
+ QCOMPARE (wChild.m_resizeEventCount, 1);
+ wParent.show();
+ QCOMPARE (wChild.m_resizeEventCount, 2);
+ }
+
+ {
+ ResizeWidget wTopLevel;
+ wTopLevel.show();
+ QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
+ wTopLevel.hide();
+ QSize safeSize(640,480);
+ if (wTopLevel.size() == safeSize)
+ safeSize.setWidth(639);
+ wTopLevel.resize(safeSize);
+ QCOMPARE (wTopLevel.m_resizeEventCount, 1);
+ wTopLevel.show();
+ QCOMPARE (wTopLevel.m_resizeEventCount, 2);
+ }
+}
+
+void tst_QWidget::showMinimized()
+{
+ QWidget plain;
+ plain.move(100, 100);
+ plain.resize(200, 200);
+ QPoint pos = plain.pos();
+
+ plain.showMinimized();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(plain.isVisible());
+ QCOMPARE(plain.pos(), pos);
+
+ plain.showNormal();
+ QVERIFY(!plain.isMinimized());
+ QVERIFY(plain.isVisible());
+ QCOMPARE(plain.pos(), pos);
+
+ plain.showMinimized();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(plain.isVisible());
+ QCOMPARE(plain.pos(), pos);
+
+ plain.hide();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(!plain.isVisible());
+
+ plain.showMinimized();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(plain.isVisible());
+
+ plain.setGeometry(200, 200, 300, 300);
+ plain.showNormal();
+ QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
+
+ {
+ QWidget frame;
+ QWidget widget(&frame);
+ widget.showMinimized();
+ QVERIFY(widget.isMinimized());
+ }
+}
+
+void tst_QWidget::showMinimizedKeepsFocus()
+{
+ //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
+ {
+ QWidget window;
+ QWidget child1(&window), child2(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+ child2.setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child2.setFocus();
+ QTest::qWait(50);
+
+ QTRY_COMPARE(window.focusWidget(), &child2);
+ QTRY_COMPARE(qApp->focusWidget(), &child2);
+
+ window.showMinimized();
+ QTest::qWait(10);
+ QTRY_VERIFY(window.isMinimized());
+ QTRY_COMPARE(window.focusWidget(), &child2);
+
+ window.showNormal();
+ QTest::qWait(10);
+ QTRY_COMPARE(window.focusWidget(), &child2);
+ }
+
+ //testing deletion of the focusWidget
+ {
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(50);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ delete child;
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+ }
+
+ //testing reparenting the focus widget
+ {
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(50);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ child->setParent(0);
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+ }
+
+ //testing setEnabled(false)
+ {
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(10);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ child->setEnabled(false);
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+ }
+
+ //testing clearFocus
+ {
+ QWidget window;
+ QWidget *firstchild = new QWidget(&window);
+ firstchild->setFocusPolicy(Qt::StrongFocus);
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(10);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ child->clearFocus();
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+
+ window.showMinimized();
+ QTest::qWait(30);
+ QTRY_VERIFY(window.isMinimized());
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue);
+#endif
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue);
+#endif
+ QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+
+ window.showNormal();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ QTest::qWait(30);
+#ifdef Q_WS_MAC
+ if (!macHasAccessToWindowsServer())
+ QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
+#endif
+ QTRY_COMPARE(window.focusWidget(), firstchild);
+#ifdef Q_WS_MAC
+ if (!macHasAccessToWindowsServer())
+ QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
+#endif
+ QTRY_COMPARE(qApp->focusWidget(), firstchild);
+ }
+}
+
+
+void tst_QWidget::reparent()
+{
+ QWidget parent;
+ parent.setWindowTitle("Toplevel");
+ parent.setGeometry(300, 300, 200, 150);
+
+ QWidget child(0);
+ child.setObjectName("child");
+ child.setGeometry(10, 10, 180, 130);
+ QPalette pal1;
+ pal1.setColor(child.backgroundRole(), Qt::white);
+ child.setPalette(pal1);
+
+ QWidget childTLW(&child, Qt::Window);
+ childTLW.setObjectName("childTLW");
+ childTLW.setGeometry(100, 100, 50, 50);
+ QPalette pal2;
+ pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
+ childTLW.setPalette(pal2);
+
+ parent.show();
+ childTLW.show();
+ QTest::qWaitForWindowShown(&parent);
+
+#ifdef Q_OS_WINCE
+ parent.move(50, 50);
+#else
+ parent.move(300, 300);
+#endif
+
+ QPoint childPos = parent.mapToGlobal(child.pos());
+ QPoint tlwPos = childTLW.pos();
+
+ child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
+ child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
+ child.show();
+
+#ifdef Q_WS_X11
+ // On X11, the window manager will apply NorthWestGravity rules to 'child', which
+ // means the top-left corner of the window frame will be placed at 'childPos',
+ // causing this test to fail
+#else
+ QCOMPARE(child.geometry().topLeft(), childPos);
+#endif
+ QTRY_COMPARE(childTLW.pos(), tlwPos);
+
+ // This following part of the test only makes sense on Windows.
+#ifdef Q_WS_WIN
+ QWidget childTLWChild(&childTLW);
+ childTLWChild.setObjectName("childTLWChild");
+
+ QWidget grandChild(&child);
+ grandChild.setObjectName("grandChild");
+ grandChild.setGeometry(10, 10, 160, 110);
+ QPalette pal3;
+ pal3.setColor(grandChild.backgroundRole(), Qt::red);
+ grandChild.setPalette(pal3);
+ //grandChild.setPaletteBackgroundColor(Qt::red);
+
+ QWidget grandChildTLW(&grandChild, Qt::Window);
+ grandChildTLW.setObjectName("grandChildTLW");
+ grandChildTLW.setGeometry(200, 200, 50, 50);
+ QPalette pal4;
+ pal4.setColor(grandChildTLW.backgroundRole(), Qt::yellow);
+ grandChildTLW.setPalette(pal4);
+ //grandChildTLW.setPaletteBackgroundColor(Qt::yellow);
+
+ QWidget grandChildTLWChild(&grandChildTLW);
+ grandChildTLWChild.setObjectName("grandChildTLWChild");
+
+ QVERIFY(IsWindow(childTLW.winId()));
+ QVERIFY(IsWindow(childTLWChild.winId()));
+ QVERIFY(IsWindow(grandChildTLW.winId()));
+ QVERIFY(IsWindow(grandChildTLWChild.winId()));
+
+ parent.show();
+
+ QVERIFY(IsWindow(childTLW.winId()));
+ QVERIFY(IsWindow(childTLWChild.winId()));
+ QVERIFY(IsWindow(grandChildTLW.winId()));
+ QVERIFY(IsWindow(grandChildTLWChild.winId()));
+
+ child.setParent(&parent);
+ child.move(10,10);
+ child.show();
+
+ // this appears to stabelize results
+ qApp->processEvents();
+
+ QVERIFY(IsWindow(childTLW.winId()));
+ QVERIFY(IsWindow(childTLWChild.winId()));
+
+ QVERIFY(IsWindow(grandChildTLW.winId()));
+ QVERIFY(IsWindow(grandChildTLWChild.winId()));
+#endif
+}
+
+// Qt/Embedded does it differently.
+#ifndef Q_WS_QWS
+void tst_QWidget::icon()
+{
+ QPixmap p(20,20);
+ p.fill(Qt::red);
+ testWidget->setWindowIcon(p);
+
+ QVERIFY(!testWidget->windowIcon().isNull());
+ testWidget->show();
+ QVERIFY(!testWidget->windowIcon().isNull());
+ testWidget->showFullScreen();
+ QVERIFY(!testWidget->windowIcon().isNull());
+ testWidget->showNormal();
+ QVERIFY(!testWidget->windowIcon().isNull());
+}
+#endif
+
+void tst_QWidget::hideWhenFocusWidgetIsChild()
+{
+ testWidget->activateWindow();
+ QWidget *parentWidget = new QWidget(testWidget);
+ parentWidget->setObjectName("parentWidget");
+ parentWidget->setGeometry(0, 0, 100, 100);
+ QLineEdit *edit = new QLineEdit(parentWidget);
+ edit->setObjectName("edit1");
+ QLineEdit *edit3 = new QLineEdit(parentWidget);
+ edit3->setObjectName("edit3");
+ edit3->move(0,50);
+ parentWidget->show();
+ QLineEdit *edit2 = new QLineEdit(testWidget);
+ edit2->setObjectName("edit2");
+ edit2->show();
+ edit2->move(110, 100);
+ edit->setFocus();
+ qApp->processEvents();
+ QString actualFocusWidget, expectedFocusWidget;
+#ifdef Q_WS_X11
+ if (!qApp->focusWidget())
+ QSKIP("Your window manager is too broken for this test", SkipAll);
+#endif
+ QVERIFY(qApp->focusWidget());
+ actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
+ expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
+ QCOMPARE(actualFocusWidget, expectedFocusWidget);
+
+ parentWidget->hide();
+ qApp->processEvents();
+ actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
+ expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
+ QCOMPARE(actualFocusWidget, expectedFocusWidget);
+
+ delete edit2;
+ delete parentWidget;
+}
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::normalGeometry()
+{
+ QWidget parent;
+ parent.setWindowTitle("NormalGeometry parent");
+ QWidget *child = new QWidget(&parent);
+
+ QCOMPARE(parent.normalGeometry(), parent.geometry());
+ QCOMPARE(child->normalGeometry(), QRect());
+
+ parent.setGeometry(100, 100, 200, 200);
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QApplication::processEvents();
+
+ QRect geom = parent.geometry();
+ // ### the window manager places the top-left corner at
+ // ### 100,100... making geom something like 102,124 (offset by
+ // ### the frame/frame)... this indicates a rather large different
+ // ### between how X11 and Windows works
+ // QCOMPARE(geom, QRect(100, 100, 200, 200));
+ QCOMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showMaximized();
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QCOMPARE(parent.normalGeometry(), geom);
+
+ parent.showNormal();
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QCOMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(10);
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
+ // ### when minimized and maximized at the same time, the geometry
+ // ### does *NOT* have to be the normal geometry, it could be the
+ // ### maximized geometry.
+ // QCOMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
+ QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(10);
+ QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showFullScreen();
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showNormal();
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showNormal();
+ parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
+ parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
+ parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+}
+#endif
+
+void tst_QWidget::setGeometry()
+{
+ QWidget tlw;
+ QWidget child(&tlw);
+
+ QRect tr(100,100,200,200);
+ QRect cr(50,50,50,50);
+ tlw.setGeometry(tr);
+ child.setGeometry(cr);
+ tlw.show();
+ QTest::qWait(50);
+ QCOMPARE(tlw.geometry().size(), tr.size());
+ QCOMPARE(child.geometry(), cr);
+
+ tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
+ tr = QRect(0,0,100,100);
+ tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
+ tlw.setGeometry(tr);
+ QCOMPARE(tlw.geometry(), tr);
+ tlw.show();
+ QTest::qWait(50);
+ if (tlw.frameGeometry() != tlw.geometry())
+ QSKIP("Your window manager is too broken for this test", SkipAll);
+ QCOMPARE(tlw.geometry(), tr);
+
+}
+
+// Windows CE does not support windowOpacity.
+#ifndef Q_OS_WINCE
+void tst_QWidget::windowOpacity()
+{
+ QWidget widget;
+ QWidget child(&widget);
+
+ // Initial value should be 1.0
+ QCOMPARE(widget.windowOpacity(), 1.0);
+ // children should always return 1.0
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(0.0);
+ QCOMPARE(widget.windowOpacity(), 0.0);
+ child.setWindowOpacity(0.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(1.0);
+ QCOMPARE(widget.windowOpacity(), 1.0);
+ child.setWindowOpacity(1.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(2.0);
+ QCOMPARE(widget.windowOpacity(), 1.0);
+ child.setWindowOpacity(2.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(-1.0);
+ QCOMPARE(widget.windowOpacity(), 0.0);
+ child.setWindowOpacity(-1.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+}
+#endif
+
+class UpdateWidget : public QWidget
+{
+public:
+ UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
+ reset();
+ }
+
+ void paintEvent(QPaintEvent *e) {
+ paintedRegion += e->region();
+ ++numPaintEvents;
+ if (resizeInPaintEvent) {
+ resizeInPaintEvent = false;
+ resize(size() + QSize(2, 2));
+ }
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::ZOrderChange:
+ ++numZOrderChangeEvents;
+ break;
+ case QEvent::UpdateRequest:
+ ++numUpdateRequestEvents;
+ break;
+ case QEvent::ActivationChange:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ if (!updateOnActivationChangeAndFocusIn)
+ return true; // Filter out to avoid update() calls in QWidget.
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+ }
+
+ void reset() {
+ numPaintEvents = 0;
+ numZOrderChangeEvents = 0;
+ numUpdateRequestEvents = 0;
+ updateOnActivationChangeAndFocusIn = false;
+ resizeInPaintEvent = false;
+ paintedRegion = QRegion();
+ }
+
+ int numPaintEvents;
+ int numZOrderChangeEvents;
+ int numUpdateRequestEvents;
+ bool updateOnActivationChangeAndFocusIn;
+ bool resizeInPaintEvent;
+ QRegion paintedRegion;
+};
+
+void tst_QWidget::lostUpdatesOnHide()
+{
+#ifndef Q_WS_MAC
+ UpdateWidget widget;
+ widget.setAttribute(Qt::WA_DontShowOnScreen);
+ widget.show();
+ widget.hide();
+ QTest::qWait(50);
+ widget.show();
+ QTest::qWait(50);
+
+ QCOMPARE(widget.numPaintEvents, 1);
+#endif
+}
+
+void tst_QWidget::raise()
+{
+ QTest::qWait(10);
+ QWidget *parent = new QWidget(0);
+ QList<UpdateWidget *> allChildren;
+
+ UpdateWidget *child1 = new UpdateWidget(parent);
+ child1->setAutoFillBackground(true);
+ allChildren.append(child1);
+
+ UpdateWidget *child2 = new UpdateWidget(parent);
+ child2->setAutoFillBackground(true);
+ allChildren.append(child2);
+
+ UpdateWidget *child3 = new UpdateWidget(parent);
+ child3->setAutoFillBackground(true);
+ allChildren.append(child3);
+
+ UpdateWidget *child4 = new UpdateWidget(parent);
+ child4->setAutoFillBackground(true);
+ allChildren.append(child4);
+
+ parent->show();
+ QTest::qWaitForWindowShown(parent);
+ QTest::qWait(10);
+
+#ifdef Q_OS_MAC
+ if (child1->internalWinId()) {
+ QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.", SkipAll);
+ }
+#endif
+
+ QList<QObject *> list1;
+ list1 << child1 << child2 << child3 << child4;
+ QVERIFY(parent->children() == list1);
+ QCOMPARE(allChildren.count(), list1.count());
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child4 ? 1 : 0;
+ if (expectedPaintEvents == 0) {
+ QVERIFY(child->numPaintEvents == 0);
+ } else {
+ // show() issues multiple paint events on some window managers
+ QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
+ }
+ QCOMPARE(child->numZOrderChangeEvents, 0);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child2->raise();
+ QTest::qWait(50);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child2 ? 1 : 0;
+ int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
+#ifdef Q_OS_MAC
+ QSKIP("Not yet sure why this fails.", SkipSingle);
+#endif
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+
+ QList<QObject *> list2;
+ list2 << child1 << child3 << child4 << child2;
+ QVERIFY(parent->children() == list2);
+
+ // Creates a widget on top of all the children and checks that raising one of
+ // the children underneath doesn't trigger a repaint on the covering widget.
+ QWidget topLevel;
+ parent->setParent(&topLevel);
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTest::qWait(50);
+
+ UpdateWidget *onTop = new UpdateWidget(&topLevel);
+ onTop->reset();
+ onTop->resize(topLevel.size());
+ onTop->setAutoFillBackground(true);
+ onTop->show();
+ QTest::qWait(50);
+ QTRY_VERIFY(onTop->numPaintEvents > 0);
+ onTop->reset();
+
+ // Reset all the children.
+ foreach (UpdateWidget *child, allChildren)
+ child->reset();
+
+ for (int i = 0; i < 5; ++i)
+ child3->raise();
+ QTest::qWait(50);
+
+ QCOMPARE(onTop->numPaintEvents, 0);
+ QCOMPARE(onTop->numZOrderChangeEvents, 0);
+
+ QList<QObject *> list3;
+ list3 << child1 << child4 << child2 << child3;
+ QVERIFY(parent->children() == list3);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = 0;
+ int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+}
+
+// Cocoa has no Z-Order for views, we hack it, but it results in paint events.
+#ifndef QT_OS_MAC
+void tst_QWidget::lower()
+{
+ QWidget *parent = new QWidget(0);
+ QList<UpdateWidget *> allChildren;
+
+ UpdateWidget *child1 = new UpdateWidget(parent);
+ child1->setAutoFillBackground(true);
+ allChildren.append(child1);
+
+ UpdateWidget *child2 = new UpdateWidget(parent);
+ child2->setAutoFillBackground(true);
+ allChildren.append(child2);
+
+ UpdateWidget *child3 = new UpdateWidget(parent);
+ child3->setAutoFillBackground(true);
+ allChildren.append(child3);
+
+ UpdateWidget *child4 = new UpdateWidget(parent);
+ child4->setAutoFillBackground(true);
+ allChildren.append(child4);
+
+ parent->show();
+ QTest::qWaitForWindowShown(parent);
+ QTest::qWait(100);
+
+ QList<QObject *> list1;
+ list1 << child1 << child2 << child3 << child4;
+ QVERIFY(parent->children() == list1);
+ QCOMPARE(allChildren.count(), list1.count());
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child4 ? 1 : 0;
+ if (expectedPaintEvents == 0) {
+ QVERIFY(child->numPaintEvents == 0);
+ } else {
+ // show() issues multiple paint events on some window managers
+ QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
+ }
+ QCOMPARE(child->numZOrderChangeEvents, 0);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child4->lower();
+
+ QTest::qWait(100);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child3 ? 1 : 0;
+ int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
+ QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ child->reset();
+ }
+
+ QList<QObject *> list2;
+ list2 << child4 << child1 << child2 << child3;
+ QVERIFY(parent->children() == list2);
+
+ delete parent;
+}
+#endif
+
+// Cocoa has no Z-Order for views, we hack it, but it results in paint events.
+#ifndef QT_OS_MAC
+void tst_QWidget::stackUnder()
+{
+ QTest::qWait(10);
+ QWidget *parent = new QWidget(0);
+ QList<UpdateWidget *> allChildren;
+
+ UpdateWidget *child1 = new UpdateWidget(parent);
+ child1->setAutoFillBackground(true);
+ allChildren.append(child1);
+
+ UpdateWidget *child2 = new UpdateWidget(parent);
+ child2->setAutoFillBackground(true);
+ allChildren.append(child2);
+
+ UpdateWidget *child3 = new UpdateWidget(parent);
+ child3->setAutoFillBackground(true);
+ allChildren.append(child3);
+
+ UpdateWidget *child4 = new UpdateWidget(parent);
+ child4->setAutoFillBackground(true);
+ allChildren.append(child4);
+
+ parent->show();
+ QTest::qWaitForWindowShown(parent);
+ QTest::qWait(10);
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+
+ QList<QObject *> list1;
+ list1 << child1 << child2 << child3 << child4;
+ QVERIFY(parent->children() == list1);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child4 ? 1 : 0;
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+ if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
+ QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
+#endif
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QCOMPARE(child->numZOrderChangeEvents, 0);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child4->stackUnder(child2);
+ QTest::qWait(10);
+
+ QList<QObject *> list2;
+ list2 << child1 << child4 << child2 << child3;
+ QVERIFY(parent->children() == list2);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child3 ? 1 : 0;
+ int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child1->stackUnder(child3);
+ QTest::qWait(10);
+
+ QList<QObject *> list3;
+ list3 << child4 << child2 << child1 << child3;
+ QVERIFY(parent->children() == list3);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
+ if (child == child3) {
+#ifdef Q_OS_WINCE
+ qApp->processEvents();
+#endif
+#ifndef Q_WS_MAC
+ QEXPECT_FAIL(0, "See QTBUG-493", Continue);
+#endif
+ QCOMPARE(child->numPaintEvents, 0);
+ } else {
+ QCOMPARE(child->numPaintEvents, 0);
+ }
+ QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+
+ delete parent;
+}
+#endif
+
+void drawPolygon(QPaintDevice *dev, int w, int h)
+{
+ QPainter p(dev);
+ p.fillRect(0, 0, w, h, Qt::white);
+
+ QPolygon a;
+ a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
+ << QPoint(w/2, h) << QPoint(0, 0);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::DiagCrossPattern);
+ p.drawPolygon(a);
+}
+
+class ContentsPropagationWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
+ {
+ QWidget *child = this;
+ for (int i=0; i<32; ++i) {
+ child = new QWidget(child);
+ child->setGeometry(i, i, 400 - i*2, 400 - i*2);
+ }
+ }
+
+ void setContentsPropagation(bool enable) {
+ foreach (QObject *child, children())
+ qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
+ }
+
+protected:
+ void paintEvent(QPaintEvent *)
+ {
+ int w = width(), h = height();
+ drawPolygon(this, w, h);
+ }
+
+ QSize sizeHint() const { return QSize(500, 500); }
+};
+
+void tst_QWidget::testContentsPropagation()
+{
+ ContentsPropagationWidget widget;
+#ifdef Q_WS_QWS
+ widget.resize(500,500);
+#else
+ widget.setFixedSize(500, 500);
+#endif
+ widget.setContentsPropagation(false);
+ QPixmap widgetSnapshot = QPixmap::grabWidget(&widget);
+
+ QPixmap correct(500, 500);
+ drawPolygon(&correct, 500, 500);
+ //correct.save("correct.png", "PNG");
+
+ //widgetSnapshot.save("snap1.png", "PNG");
+ QVERIFY(widgetSnapshot.toImage() != correct.toImage());
+
+ widget.setContentsPropagation(true);
+ widgetSnapshot = QPixmap::grabWidget(&widget);
+ //widgetSnapshot.save("snap2.png", "PNG");
+
+ QCOMPARE(widgetSnapshot, correct);
+}
+
+/*
+ Test that saving and restoring window geometry with
+ saveGeometry() and restoreGeometry() works.
+*/
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::saveRestoreGeometry()
+{
+ const QPoint position(100, 100);
+ const QSize size(200, 200);
+
+ QByteArray savedGeometry;
+
+ {
+ QWidget widget;
+ widget.move(position);
+ widget.resize(size);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ QTRY_COMPARE(widget.pos(), position);
+ QCOMPARE(widget.size(), size);
+ savedGeometry = widget.saveGeometry();
+ }
+
+ {
+ QWidget widget;
+
+ const QByteArray empty;
+ const QByteArray one("a");
+ const QByteArray two("ab");
+ const QByteArray three("abc");
+ const QByteArray four("abca");
+ const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
+
+ QVERIFY(widget.restoreGeometry(empty) == false);
+ QVERIFY(widget.restoreGeometry(one) == false);
+ QVERIFY(widget.restoreGeometry(two) == false);
+ QVERIFY(widget.restoreGeometry(three) == false);
+ QVERIFY(widget.restoreGeometry(four) == false);
+ QVERIFY(widget.restoreGeometry(garbage) == false);
+
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ QTRY_COMPARE(widget.pos(), position);
+ QCOMPARE(widget.size(), size);
+ widget.show();
+ QCOMPARE(widget.pos(), position);
+ QCOMPARE(widget.size(), size);
+ }
+
+ {
+ QWidget widget;
+ widget.move(position);
+ widget.resize(size);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(500);
+ QTRY_COMPARE(widget.geometry().size(), size);
+
+ QRect geom;
+
+ //Restore from Full screen
+ savedGeometry = widget.saveGeometry();
+ geom = widget.geometry();
+ widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(500);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(widget.geometry(), geom);
+
+ //Restore to full screen
+ widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(500);
+ savedGeometry = widget.saveGeometry();
+ geom = widget.geometry();
+ widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(400);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(widget.geometry(), geom);
+ QVERIFY((widget.windowState() & Qt::WindowFullScreen));
+ widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(120);
+
+ //Restore from Maximised
+ widget.move(position);
+ widget.resize(size);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.size(), size);
+ QTest::qWait(500);
+ savedGeometry = widget.saveGeometry();
+ geom = widget.geometry();
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
+ QTRY_VERIFY(widget.geometry() != geom);
+ QTest::qWait(500);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_COMPARE(widget.geometry(), geom);
+
+ QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
+
+ //Restore to maximised
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
+ QTest::qWait(500);
+ geom = widget.geometry();
+ savedGeometry = widget.saveGeometry();
+ widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
+ QTest::qWait(500);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(widget.geometry(), geom);
+ }
+}
+#endif
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::restoreVersion1Geometry_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<uint>("expectedWindowState");
+ QTest::addColumn<QPoint>("expectedPosition");
+ QTest::addColumn<QSize>("expectedSize");
+ QTest::addColumn<QRect>("expectedNormalGeometry");
+ const QPoint position(100, 100);
+ const QSize size(200, 200);
+ const QRect normalGeometry(102, 124, 200, 200);
+
+ QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
+ QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
+ QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
+}
+
+/*
+ Test that the current version of restoreGeometry() can restore geometry
+ saved width saveGeometry() version 1.0.
+*/
+void tst_QWidget::restoreVersion1Geometry()
+{
+ QFETCH(QString, fileName);
+ QFETCH(uint, expectedWindowState);
+ QFETCH(QPoint, expectedPosition);
+ QFETCH(QSize, expectedSize);
+ QFETCH(QRect, expectedNormalGeometry);
+
+ // WindowActive is uninteresting for this test
+ const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
+
+ QFile f(fileName);
+ QVERIFY(f.exists());
+ f.open(QIODevice::ReadOnly);
+ const QByteArray savedGeometry = f.readAll();
+ QCOMPARE(savedGeometry.count(), 46);
+ f.close();
+
+ QWidget widget;
+
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+
+ QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
+ if (expectedWindowState == Qt::WindowNoState) {
+ QCOMPARE(widget.pos(), expectedPosition);
+ QCOMPARE(widget.size(), expectedSize);
+ }
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(100);
+
+ if (expectedWindowState == Qt::WindowNoState) {
+ QTRY_COMPARE(widget.pos(), expectedPosition);
+ QTRY_COMPARE(widget.size(), expectedSize);
+ }
+
+ widget.showNormal();
+ QTest::qWait(10);
+
+ if (expectedWindowState != Qt::WindowNoState) {
+ // restoring from maximized or fullscreen, we can only restore to the normal geometry
+ QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
+ } else {
+ QTRY_COMPARE(widget.pos(), expectedPosition);
+ QTRY_COMPARE(widget.size(), expectedSize);
+ }
+
+#if 0
+ // Code for saving a new geometry*.dat files
+ {
+ QWidget widgetToSave;
+ widgetToSave.move(expectedPosition);
+ widgetToSave.resize(expectedSize);
+ widgetToSave.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QTest::qWait(500); // stabilize
+ widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
+ QTest::qWait(500); // stabilize
+
+ QByteArray geometryToSave = widgetToSave.saveGeometry();
+
+ // Code for saving a new geometry.dat file.
+ f.setFileName(fileName.mid(1));
+ QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
+ f.write(geometryToSave);
+ f.close();
+ }
+#endif
+}
+#endif
+
+void tst_QWidget::widgetAt()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QWidget *w1 = new QWidget(0, Qt::X11BypassWindowManagerHint);
+ w1->setGeometry(0,0,150,150);
+ w1->setObjectName("w1");
+
+ QWidget *w2 = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint);
+ w2->setGeometry(50,50,100,100);
+ w2->setObjectName("w2");
+ w1->show();
+ QTest::qWaitForWindowShown(w1);
+ qApp->processEvents();
+ QWidget *wr;
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
+ QCOMPARE(wr->objectName(), QString("w1"));
+
+ w2->show();
+ QTest::qWaitForWindowShown(w2);
+ qApp->processEvents();
+ qApp->processEvents();
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
+ QCOMPARE(wr->objectName(), QString("w2"));
+
+ w2->lower();
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
+ w2->raise();
+
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
+
+ QWidget *w3 = new QWidget(w2);
+ w3->setGeometry(10,10,50,50);
+ w3->setObjectName("w3");
+ w3->show();
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
+
+ w3->setAttribute(Qt::WA_TransparentForMouseEvents);
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
+
+ QRegion rgn = QRect(QPoint(0,0), w2->size());
+ QPoint point = w2->mapFromGlobal(QPoint(100,100));
+ rgn -= QRect(point, QSize(1,1));
+ w2->setMask(rgn);
+ qApp->processEvents();
+ QTest::qWait(10);
+#if defined(Q_OS_WINCE)
+ QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
+#endif
+#if defined(Q_WS_QPA)
+ QEXPECT_FAIL("", "Window mask not implemented on Lighthouse", Continue);
+#endif
+
+ QTRY_COMPARE(QApplication::widgetAt(100,100)->objectName(), w1->objectName());
+ QTRY_COMPARE(QApplication::widgetAt(101,101)->objectName(), w2->objectName());
+
+ QBitmap bitmap(w2->size());
+ QPainter p(&bitmap);
+ p.fillRect(bitmap.rect(), Qt::color1);
+ p.setPen(Qt::color0);
+ p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
+ p.end();
+ w2->setMask(bitmap);
+ qApp->processEvents();
+ QTest::qWait(10);
+#if defined(Q_OS_WINCE)
+ QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
+#endif
+#if defined(Q_WS_QPA)
+ QEXPECT_FAIL("", "Window mask not implemented on Lighthouse", Continue);
+#endif
+ QTRY_VERIFY(QApplication::widgetAt(100,100) == w1);
+ QTRY_VERIFY(QApplication::widgetAt(101,101) == w2);
+
+ delete w2;
+ delete w1;
+}
+
+#if defined(Q_WS_X11)
+bool getProperty(Display *display, Window target, Atom type, Atom property,
+ unsigned char** data, unsigned long* count)
+{
+ Atom atom_return;
+ int size;
+ unsigned long nitems, bytes_left;
+
+ int ret = XGetWindowProperty(display, target, property,
+ 0l, 1l, false,
+ type, &atom_return, &size,
+ &nitems, &bytes_left, data);
+ if (ret != Success || nitems < 1)
+ return false;
+
+ if (bytes_left != 0) {
+ XFree(*data);
+ unsigned long remain = ((size / 8) * nitems) + bytes_left;
+ ret = XGetWindowProperty(display, target,
+ property, 0l, remain, false,
+ type, &atom_return, &size,
+ &nitems, &bytes_left, data);
+ if (ret != Success)
+ return false;
+ }
+
+ *count = nitems;
+ return true;
+}
+
+QString textPropertyToString(Display *display, XTextProperty& text_prop)
+{
+ QString ret;
+ if (text_prop.value && text_prop.nitems > 0) {
+ if (text_prop.encoding == XA_STRING) {
+ ret = reinterpret_cast<char *>(text_prop.value);
+ } else {
+ text_prop.nitems = strlen(reinterpret_cast<char *>(text_prop.value));
+ char **list;
+ int num;
+ if (XmbTextPropertyToTextList(display, &text_prop, &list, &num) == Success
+ && num > 0 && *list) {
+ ret = QString::fromLocal8Bit(*list);
+ XFreeStringList(list);
+ }
+ }
+ }
+ return ret;
+}
+#endif
+
+void tst_QWidget::task110173()
+{
+ QWidget w;
+
+ QPushButton *pb1 = new QPushButton("click", &w);
+ pb1->setFocusPolicy(Qt::ClickFocus);
+ pb1->move(100, 100);
+
+ QPushButton *pb2 = new QPushButton("push", &w);
+ pb2->setFocusPolicy(Qt::ClickFocus);
+ pb2->move(300, 300);
+
+ QTest::keyClick( &w, Qt::Key_Tab );
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(200);
+}
+
+class Widget : public QWidget
+{
+public:
+ Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
+ void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
+ void changeEvent(QEvent *) { if (deleteThis) delete this; }
+ void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
+ void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
+ void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
+ void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
+ void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
+ void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
+ void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
+ void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
+ void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
+
+ bool deleteThis;
+};
+
+void tst_QWidget::testDeletionInEventHandlers()
+{
+ // closeEvent
+ QPointer<Widget> w = new Widget;
+ w->deleteThis = true;
+ w->close();
+ QVERIFY(w == 0);
+ delete w;
+
+ // focusOut (crashes)
+ //w = new Widget;
+ //w->show();
+ //w->setFocus();
+ //QVERIFY(qApp->focusWidget() == w);
+ //w->deleteThis = true;
+ //w->clearFocus();
+ //QVERIFY(w == 0);
+
+ // key press
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::keyPress(w, Qt::Key_A);
+ QVERIFY(w == 0);
+ delete w;
+
+ // key release
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::keyRelease(w, Qt::Key_A);
+ QVERIFY(w == 0);
+ delete w;
+
+ // mouse press
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::mousePress(w, Qt::LeftButton);
+ QVERIFY(w == 0);
+ delete w;
+
+ // mouse release
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::mouseRelease(w, Qt::LeftButton);
+ QVERIFY(w == 0);
+ delete w;
+
+ // mouse double click
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::mouseDClick(w, Qt::LeftButton);
+ QVERIFY(w == 0);
+ delete w;
+
+ // hide event (crashes)
+ //w = new Widget;
+ //w->show();
+ //w->deleteThis = true;
+ //w->hide();
+ //QVERIFY(w == 0);
+
+ // action event
+ w = new Widget;
+ w->deleteThis = true;
+ w->addAction(new QAction(w));
+ QVERIFY(w == 0);
+ delete w;
+
+ // change event
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ w->setMouseTracking(true);
+ QVERIFY(w == 0);
+ delete w;
+
+ w = new Widget;
+ w->setMouseTracking(true);
+ w->show();
+ w->deleteThis = true;
+ QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
+ QApplication::sendEvent(w, &me);
+ QVERIFY(w == 0);
+ delete w;
+}
+
+#ifdef Q_WS_MAC
+
+/*
+ Test that retaining and releasing the HIView returned by QWidget::winId()
+ works even if the widget itself is deleted.
+*/
+void tst_QWidget::retainHIView()
+{
+ // Single window
+ {
+ const WidgetViewPair window = createAndRetain();
+ delete window.first;
+ QVERIFY(testAndRelease(window.second));
+ }
+
+ // Child widget
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent.first);
+
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ QVERIFY(testAndRelease(child.second));
+ }
+
+ // Multiple children
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child1 = createAndRetain(parent.first);
+ const WidgetViewPair child2 = createAndRetain(parent.first);
+
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ QVERIFY(testAndRelease(child1.second));
+ QVERIFY(testAndRelease(child2.second));
+ }
+
+ // Grandchild widget
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent.first);
+ const WidgetViewPair grandchild = createAndRetain(child.first);
+
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ QVERIFY(testAndRelease(child.second));
+ QVERIFY(testAndRelease(grandchild.second));
+ }
+
+ // Reparent child widget
+ {
+ const WidgetViewPair parent1 = createAndRetain();
+ const WidgetViewPair parent2 = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent1.first);
+
+ child.first->setParent(parent2.first);
+
+ delete parent1.first;
+ QVERIFY(testAndRelease(parent1.second));
+ delete parent2.first;
+ QVERIFY(testAndRelease(parent2.second));
+ QVERIFY(testAndRelease(child.second));
+ }
+
+ // Reparent window
+ {
+ const WidgetViewPair window1 = createAndRetain();
+ const WidgetViewPair window2 = createAndRetain();
+ const WidgetViewPair child1 = createAndRetain(window1.first);
+ const WidgetViewPair child2 = createAndRetain(window2.first);
+
+ window2.first->setParent(window1.first);
+
+ delete window2.first;
+ QVERIFY(testAndRelease(window2.second));
+ QVERIFY(testAndRelease(child2.second));
+ delete window1.first;
+ QVERIFY(testAndRelease(window1.second));
+ QVERIFY(testAndRelease(child1.second));
+ }
+
+ // Delete child widget
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent.first);
+
+ delete child.first;
+ QVERIFY(testAndRelease(child.second));
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ }
+}
+
+void tst_QWidget::sheetOpacity()
+{
+ QWidget tmpWindow;
+ QWidget sheet(&tmpWindow, Qt::Sheet);
+ tmpWindow.show();
+ sheet.show();
+ QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
+ sheet.setParent(0, Qt::Dialog);
+ QCOMPARE(int(sheet.windowOpacity() * 255), 255);
+}
+
+class MaskedPainter : public QWidget
+{
+public:
+ QRect mask;
+
+ MaskedPainter()
+ : mask(20, 20, 50, 50)
+ {
+ setMask(mask);
+ }
+
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter p(this);
+ p.fillRect(mask, QColor(Qt::red));
+ }
+};
+
+/*
+ Verifies that the entire area inside the mask is painted red.
+*/
+bool verifyWidgetMask(QWidget *widget, QRect mask)
+{
+ const QImage image = QPixmap::grabWindow(widget->winId()).toImage();
+
+ const QImage masked = image.copy(mask);
+ QImage red(masked);
+ red.fill(QColor(Qt::red).rgb());
+
+ return (masked == red);
+}
+
+void tst_QWidget::setMask()
+{
+ testWidget->hide(); // get this out of the way.
+
+ {
+ MaskedPainter w;
+ w.resize(200, 200);
+ w.show();
+ QTest::qWait(100);
+ QVERIFY(verifyWidgetMask(&w, w.mask));
+ }
+ {
+ MaskedPainter w;
+ w.resize(200, 200);
+ w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
+ w.show();
+ QTest::qWait(100);
+ QRect mask = w.mask;
+
+ QVERIFY(verifyWidgetMask(&w, mask));
+ }
+}
+#endif
+
+class StaticWidget : public QWidget
+{
+Q_OBJECT
+public:
+ bool partial;
+ bool gotPaintEvent;
+ QRegion paintedRegion;
+
+ StaticWidget(QWidget *parent = 0)
+ :QWidget(parent)
+ {
+ setAttribute(Qt::WA_StaticContents);
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setPalette(Qt::red); // Make sure we have an opaque palette.
+ setAutoFillBackground(true);
+ gotPaintEvent = false;
+ }
+
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ gotPaintEvent = true;
+// qDebug() << "paint" << e->region();
+ // Look for a full update, set partial to false if found.
+ foreach(QRect r, e->region().rects()) {
+ partial = (r != rect());
+ if (partial == false)
+ break;
+ }
+ }
+};
+
+/*
+ Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
+ and WA_OpaquePaintEvent is set. Test is mac-only for now.
+*/
+void tst_QWidget::optimizedResizeMove()
+{
+ QWidget parent;
+ parent.resize(400, 400);
+
+ StaticWidget staticWidget(&parent);
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(150, 150);
+ staticWidget.resize(150, 150);
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QTest::qWait(20);
+ QTRY_COMPARE(staticWidget.gotPaintEvent, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.resize(staticWidget.size() + QSize(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.resize(staticWidget.size() + QSize(10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ staticWidget.resize(staticWidget.size() + QSize(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.setAttribute(Qt::WA_StaticContents, false);
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, false);
+ staticWidget.setAttribute(Qt::WA_StaticContents, true);
+
+ staticWidget.setAttribute(Qt::WA_StaticContents, false);
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+ staticWidget.setAttribute(Qt::WA_StaticContents, true);
+}
+
+void tst_QWidget::optimizedResize_topLevel()
+{
+#if defined(Q_WS_MAC) || defined(Q_WS_QWS)
+ QSKIP("We do not yet have static contents support for *top-levels* on this platform", SkipAll);
+#endif
+
+ StaticWidget topLevel;
+ topLevel.gotPaintEvent = false;
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTest::qWait(10);
+ QTRY_COMPARE(topLevel.gotPaintEvent, true);
+
+ topLevel.gotPaintEvent = false;
+ topLevel.partial = false;
+ topLevel.paintedRegion = QRegion();
+
+#ifndef Q_WS_WIN
+ topLevel.resize(topLevel.size() + QSize(10, 10));
+#else
+ // Static contents does not work when programmatically resizing
+ // top-levels with QWidget::resize. We do some funky stuff in
+ // setGeometry_sys. However, resizing it with the mouse or with
+ // a native function call works (it basically has to go through
+ // WM_RESIZE in QApplication). This is a corner case, though.
+ // See task 243708
+ const QRect frame = topLevel.frameGeometry();
+ MoveWindow(topLevel.winId(), frame.x(), frame.y(),
+ frame.width() + 10, frame.height() + 10,
+ true);
+#endif
+
+ QTest::qWait(100);
+
+ // Expected update region: New rect - old rect.
+ QRegion expectedUpdateRegion(topLevel.rect());
+ expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
+
+ QTRY_COMPARE(topLevel.gotPaintEvent, true);
+ QCOMPARE(topLevel.partial, true);
+ QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
+}
+
+class SiblingDeleter : public QWidget
+{
+public:
+ inline SiblingDeleter(QWidget *sibling, QWidget *parent)
+ : QWidget(parent), sibling(sibling) {}
+ inline virtual ~SiblingDeleter() { delete sibling; }
+
+private:
+ QPointer<QWidget> sibling;
+};
+
+
+void tst_QWidget::childDeletesItsSibling()
+{
+ QWidget *commonParent = new QWidget(0);
+ QPointer<QWidget> child = new QWidget(0);
+ QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
+ child->setParent(commonParent);
+ delete commonParent; // don't crash
+ QVERIFY(!child);
+ QVERIFY(!siblingDeleter);
+
+}
+
+#ifdef Q_WS_QWS
+# define SET_SAFE_SIZE(w) \
+ do { \
+ QSize safeSize(qt_screen->width() - 250, qt_screen->height() - 250); \
+ if (!safeSize.isValid()) \
+ QSKIP("Screen size too small", SkipAll); \
+ if (defaultSize.width() > safeSize.width() || defaultSize.height() > safeSize.height()) { \
+ defaultSize = safeSize; \
+ w.resize(defaultSize); \
+ w.setAttribute(Qt::WA_Resized, false); \
+ } \
+ } while (false)
+#else
+# define SET_SAFE_SIZE(w)
+#endif
+
+
+void tst_QWidget::setMinimumSize()
+{
+ QWidget w;
+ QSize defaultSize = w.size();
+ SET_SAFE_SIZE(w);
+
+ w.setMinimumSize(defaultSize + QSize(100, 100));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setMinimumSize(defaultSize + QSize(50, 50));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setMinimumSize(defaultSize + QSize(200, 200));
+ QCOMPARE(w.size(), defaultSize + QSize(200, 200));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ // Setting a minimum size larger than the desktop does not work on WinCE,
+ // so skip this part of the test.
+#ifndef Q_OS_WINCE
+ QSize nonDefaultSize = defaultSize + QSize(5,5);
+ w.setMinimumSize(nonDefaultSize);
+ w.show();
+ QTest::qWait(50);
+ QVERIFY(w.height() >= nonDefaultSize.height());
+ QVERIFY(w.width() >= nonDefaultSize.width());
+#endif
+}
+
+void tst_QWidget::setMaximumSize()
+{
+ QWidget w;
+ QSize defaultSize = w.size();
+ SET_SAFE_SIZE(w);
+
+ w.setMinimumSize(defaultSize + QSize(100, 100));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+ w.setMinimumSize(defaultSize);
+
+ w.setMaximumSize(defaultSize + QSize(200, 200));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setMaximumSize(defaultSize + QSize(50, 50));
+ QCOMPARE(w.size(), defaultSize + QSize(50, 50));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+#if 0
+ //we don't enforce maximum size on show, apparently
+ QSize nonDefaultSize = defaultSize - QSize(5,5);
+ w.setMaximumSize(nonDefaultSize);
+ w.show();
+ QTest::qWait(50);
+ qDebug() << nonDefaultSize << w.size();
+ QVERIFY(w.height() <= nonDefaultSize.height());
+ QVERIFY(w.width() <= nonDefaultSize.width());
+#endif
+}
+
+void tst_QWidget::setFixedSize()
+{
+ QWidget w;
+ QSize defaultSize = w.size();
+ SET_SAFE_SIZE(w);
+
+ w.setFixedSize(defaultSize + QSize(100, 100));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+
+ w.setFixedSize(defaultSize + QSize(200, 200));
+
+ QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
+ QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
+ QCOMPARE(w.size(), defaultSize + QSize(200, 200));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+
+ w.setFixedSize(defaultSize + QSize(50, 50));
+ QCOMPARE(w.size(), defaultSize + QSize(50, 50));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+
+ w.setAttribute(Qt::WA_Resized, false);
+ w.setFixedSize(defaultSize + QSize(50, 50));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setFixedSize(defaultSize + QSize(150, 150));
+ w.show();
+ QTest::qWait(50);
+ QVERIFY(w.size() == defaultSize + QSize(150,150));
+}
+
+void tst_QWidget::ensureCreated()
+{
+ {
+ QWidget widget;
+ WId widgetWinId = widget.winId();
+ Q_UNUSED(widgetWinId);
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ }
+
+ {
+ QWidget window;
+
+ QDialog dialog(&window);
+ dialog.setWindowModality(Qt::NonModal);
+
+ WId dialogWinId = dialog.winId();
+ Q_UNUSED(dialogWinId);
+ QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(window.testAttribute(Qt::WA_WState_Created));
+ }
+
+ {
+ QWidget window;
+
+ QDialog dialog(&window);
+ dialog.setWindowModality(Qt::WindowModal);
+
+ WId dialogWinId = dialog.winId();
+ Q_UNUSED(dialogWinId);
+ QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(window.testAttribute(Qt::WA_WState_Created));
+ }
+
+ {
+ QWidget window;
+
+ QDialog dialog(&window);
+ dialog.setWindowModality(Qt::ApplicationModal);
+
+ WId dialogWinId = dialog.winId();
+ Q_UNUSED(dialogWinId);
+ QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(window.testAttribute(Qt::WA_WState_Created));
+ }
+}
+
+class WinIdChangeWidget : public QWidget {
+public:
+ WinIdChangeWidget(QWidget *p = 0)
+ : QWidget(p)
+ {
+
+ }
+protected:
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::WinIdChange) {
+ m_winIdList.append(internalWinId());
+ return true;
+ }
+ return QWidget::event(e);
+ }
+public:
+ QList<WId> m_winIdList;
+ int winIdChangeEventCount() const { return m_winIdList.count(); }
+};
+
+void tst_QWidget::winIdChangeEvent()
+{
+ {
+ // Transforming an alien widget into a native widget
+ WinIdChangeWidget widget;
+ const WId winIdBefore = widget.internalWinId();
+ const WId winIdAfter = widget.winId();
+ QVERIFY(winIdBefore != winIdAfter);
+ QCOMPARE(widget.winIdChangeEventCount(), 1);
+ }
+
+ {
+ // Changing parent of a native widget
+ // Should cause winId of child to change, on all platforms
+ QWidget parent1, parent2;
+ WinIdChangeWidget child(&parent1);
+ const WId winIdBefore = child.winId();
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ child.setParent(&parent2);
+ const WId winIdAfter = child.internalWinId();
+ QVERIFY(winIdBefore != winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 3);
+ // winId is set to zero during reparenting
+ QVERIFY(0 == child.m_winIdList[1]);
+ }
+
+ {
+ // Changing grandparent of a native widget
+ QWidget grandparent1, grandparent2;
+ QWidget parent(&grandparent1);
+ WinIdChangeWidget child(&parent);
+ const WId winIdBefore = child.winId();
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ parent.setParent(&grandparent2);
+ const WId winIdAfter = child.internalWinId();
+ QCOMPARE(winIdBefore, winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ }
+
+ {
+ // Changing parent of an alien widget
+ QWidget parent1, parent2;
+ WinIdChangeWidget child(&parent1);
+ const WId winIdBefore = child.internalWinId();
+ child.setParent(&parent2);
+ const WId winIdAfter = child.internalWinId();
+ QCOMPARE(winIdBefore, winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 0);
+ }
+
+ {
+ // Making native child widget into a top-level window
+ QWidget parent;
+ WinIdChangeWidget child(&parent);
+ child.winId();
+ const WId winIdBefore = child.internalWinId();
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ const Qt::WindowFlags flags = child.windowFlags();
+ child.setWindowFlags(flags | Qt::Window);
+ const WId winIdAfter = child.internalWinId();
+ QVERIFY(winIdBefore != winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 3);
+ // winId is set to zero during reparenting
+ QVERIFY(0 == child.m_winIdList[1]);
+ }
+}
+
+void tst_QWidget::persistentWinId()
+{
+ QWidget *parent = new QWidget;
+ QWidget *w1 = new QWidget;
+ QWidget *w2 = new QWidget;
+ QWidget *w3 = new QWidget;
+ w1->setParent(parent);
+ w2->setParent(w1);
+ w3->setParent(w2);
+
+ WId winId1 = w1->winId();
+ WId winId2 = w2->winId();
+ WId winId3 = w3->winId();
+
+ // reparenting should change the winId of the widget being reparented, but not of its children
+ w1->setParent(0);
+ QVERIFY(w1->winId() != winId1);
+ winId1 = w1->winId();
+ QCOMPARE(w2->winId(), winId2);
+ QCOMPARE(w3->winId(), winId3);
+
+ w1->setParent(parent);
+ QVERIFY(w1->winId() != winId1);
+ winId1 = w1->winId();
+ QCOMPARE(w2->winId(), winId2);
+ QCOMPARE(w3->winId(), winId3);
+
+ w2->setParent(0);
+ QVERIFY(w2->winId() != winId2);
+ winId2 = w2->winId();
+ QCOMPARE(w3->winId(), winId3);
+
+ w2->setParent(parent);
+ QVERIFY(w2->winId() != winId2);
+ winId2 = w2->winId();
+ QCOMPARE(w3->winId(), winId3);
+
+ w2->setParent(w1);
+ QVERIFY(w2->winId() != winId2);
+ winId2 = w2->winId();
+ QCOMPARE(w3->winId(), winId3);
+
+ w3->setParent(0);
+ QVERIFY(w3->winId() != winId3);
+ winId3 = w3->winId();
+
+ w3->setParent(w1);
+ QVERIFY(w3->winId() != winId3);
+ winId3 = w3->winId();
+
+ w3->setParent(w2);
+ QVERIFY(w3->winId() != winId3);
+ winId3 = w3->winId();
+
+ delete parent;
+}
+
+void tst_QWidget::showNativeChild()
+{
+ QWidget topLevel;
+ topLevel.setGeometry(0, 0, 100, 100);
+ QWidget child(&topLevel);
+ child.winId();
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+}
+
+class ShowHideEventWidget : public QWidget
+{
+public:
+ int numberOfShowEvents, numberOfHideEvents;
+
+ ShowHideEventWidget(QWidget *parent = 0)
+ : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
+ { }
+
+ void create()
+ { QWidget::create(); }
+
+ void showEvent(QShowEvent *)
+ { ++numberOfShowEvents; }
+
+ void hideEvent(QHideEvent *)
+ { ++numberOfHideEvents; }
+};
+
+void tst_QWidget::showHideEvent_data()
+{
+ QTest::addColumn<bool>("show");
+ QTest::addColumn<bool>("hide");
+ QTest::addColumn<bool>("create");
+ QTest::addColumn<int>("expectedShowEvents");
+ QTest::addColumn<int>("expectedHideEvents");
+
+ QTest::newRow("window: only show")
+ << true
+ << false
+ << false
+ << 1
+ << 0;
+ QTest::newRow("window: show/hide")
+ << true
+ << true
+ << false
+ << 1
+ << 1;
+ QTest::newRow("window: show/hide/create")
+ << true
+ << true
+ << true
+ << 1
+ << 1;
+ QTest::newRow("window: hide/create")
+ << false
+ << true
+ << true
+ << 0
+ << 0;
+ QTest::newRow("window: only hide")
+ << false
+ << true
+ << false
+ << 0
+ << 0;
+ QTest::newRow("window: nothing")
+ << false
+ << false
+ << false
+ << 0
+ << 0;
+}
+
+void tst_QWidget::showHideEvent()
+{
+ QFETCH(bool, show);
+ QFETCH(bool, hide);
+ QFETCH(bool, create);
+ QFETCH(int, expectedShowEvents);
+ QFETCH(int, expectedHideEvents);
+
+ ShowHideEventWidget widget;
+ if (show)
+ widget.show();
+ if (hide)
+ widget.hide();
+ if (create && !widget.testAttribute(Qt::WA_WState_Created))
+ widget.create();
+
+ QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
+ QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
+}
+
+void tst_QWidget::update()
+{
+ QTest::qWait(10); // Wait for the initStuff to do it's stuff.
+ Q_CHECK_PAINTEVENTS
+
+ UpdateWidget w;
+ w.setGeometry(50, 50, 100, 100);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+#ifdef Q_OS_MAC
+ QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
+#endif
+ QTRY_COMPARE(w.numPaintEvents, 1);
+
+ QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
+ QCOMPARE(w.paintedRegion, w.visibleRegion());
+ w.reset();
+
+ UpdateWidget child(&w);
+ child.setGeometry(10, 10, 80, 80);
+ child.show();
+
+ QPoint childOffset = child.mapToParent(QPoint());
+
+ // widgets are transparent by default, so both should get repaints
+ {
+ QApplication::processEvents();
+ QApplication::processEvents();
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
+ QCOMPARE(child.paintedRegion, child.visibleRegion());
+ QCOMPARE(w.numPaintEvents, 1);
+ QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
+ QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
+
+ w.reset();
+ child.reset();
+
+ w.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
+ QCOMPARE(child.paintedRegion, child.visibleRegion());
+ QCOMPARE(w.numPaintEvents, 1);
+ QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
+ QCOMPARE(w.paintedRegion, w.visibleRegion());
+ }
+
+ QPalette opaquePalette = child.palette();
+ opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
+
+ // setting an opaque background on the child should prevent paint-events
+ // for the parent in the child area
+ {
+ child.setPalette(opaquePalette);
+ child.setAutoFillBackground(true);
+ QApplication::processEvents();
+
+ w.reset();
+ child.reset();
+
+ w.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ QCOMPARE(w.numPaintEvents, 1);
+ QRegion expectedVisible = QRegion(w.rect())
+ - child.visibleRegion().translated(childOffset);
+ QCOMPARE(w.visibleRegion(), expectedVisible);
+ QCOMPARE(w.paintedRegion, expectedVisible);
+ QCOMPARE(child.numPaintEvents, 0);
+
+ w.reset();
+ child.reset();
+
+ child.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ QCOMPARE(w.numPaintEvents, 0);
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.paintedRegion, child.visibleRegion());
+
+ w.reset();
+ child.reset();
+ }
+
+ // overlapping sibling
+ UpdateWidget sibling(&w);
+ child.setGeometry(10, 10, 20, 20);
+ sibling.setGeometry(15, 15, 20, 20);
+ sibling.show();
+
+ QApplication::processEvents();
+ w.reset();
+ child.reset();
+ sibling.reset();
+
+ const QPoint siblingOffset = sibling.mapToParent(QPoint());
+
+ sibling.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ // child is opaque, sibling transparent
+ {
+ QCOMPARE(sibling.numPaintEvents, 1);
+ QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
+
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.paintedRegion.translated(childOffset),
+ child.visibleRegion().translated(childOffset)
+ & sibling.visibleRegion().translated(siblingOffset));
+
+ QCOMPARE(w.numPaintEvents, 1);
+ QCOMPARE(w.paintedRegion,
+ w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
+ QCOMPARE(w.paintedRegion,
+ (w.visibleRegion() - child.visibleRegion().translated(childOffset))
+ & sibling.visibleRegion().translated(siblingOffset));
+
+ }
+ w.reset();
+ child.reset();
+ sibling.reset();
+
+ sibling.setPalette(opaquePalette);
+ sibling.setAutoFillBackground(true);
+
+ sibling.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ // child opaque, sibling opaque
+ {
+ QCOMPARE(sibling.numPaintEvents, 1);
+ QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
+
+#ifdef Q_OS_MAC
+ if (child.internalWinId()) // child is native
+ QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
+#endif
+ QCOMPARE(child.numPaintEvents, 0);
+ QCOMPARE(child.visibleRegion(),
+ QRegion(child.rect())
+ - sibling.visibleRegion().translated(siblingOffset - childOffset));
+
+ QCOMPARE(w.numPaintEvents, 0);
+ QCOMPARE(w.visibleRegion(),
+ QRegion(w.rect())
+ - child.visibleRegion().translated(childOffset)
+ - sibling.visibleRegion().translated(siblingOffset));
+ }
+}
+
+static inline bool isOpaque(QWidget *widget)
+{
+ if (!widget)
+ return false;
+ return qt_widget_private(widget)->isOpaque;
+}
+
+void tst_QWidget::isOpaque()
+{
+#ifndef Q_WS_MAC
+ QWidget w;
+ QVERIFY(::isOpaque(&w));
+
+ QWidget child(&w);
+ QVERIFY(!::isOpaque(&child));
+
+ child.setAutoFillBackground(true);
+ QVERIFY(::isOpaque(&child));
+
+ QPalette palette;
+
+ // background color
+
+ palette = child.palette();
+ palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
+ child.setPalette(palette);
+ QVERIFY(!::isOpaque(&child));
+
+ palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
+ child.setPalette(palette);
+ QVERIFY(::isOpaque(&child));
+
+ palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
+ w.setPalette(palette);
+
+ QVERIFY(!::isOpaque(&w));
+
+ child.setAutoFillBackground(false);
+ QVERIFY(!::isOpaque(&child));
+
+ // Qt::WA_OpaquePaintEvent
+
+ child.setAttribute(Qt::WA_OpaquePaintEvent);
+ QVERIFY(::isOpaque(&child));
+
+ child.setAttribute(Qt::WA_OpaquePaintEvent, false);
+ QVERIFY(!::isOpaque(&child));
+
+ // Qt::WA_NoSystemBackground
+
+ child.setAttribute(Qt::WA_NoSystemBackground);
+ QVERIFY(!::isOpaque(&child));
+
+ child.setAttribute(Qt::WA_NoSystemBackground, false);
+ QVERIFY(!::isOpaque(&child));
+
+ palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
+ w.setPalette(palette);
+ QVERIFY(::isOpaque(&w));
+
+ w.setAttribute(Qt::WA_NoSystemBackground);
+ QVERIFY(!::isOpaque(&w));
+
+ w.setAttribute(Qt::WA_NoSystemBackground, false);
+ QVERIFY(::isOpaque(&w));
+
+ {
+ QPalette palette = QApplication::palette();
+ QPalette old = palette;
+ palette.setColor(QPalette::Window, Qt::transparent);
+ QApplication::setPalette(palette);
+
+ QWidget widget;
+ QVERIFY(!::isOpaque(&widget));
+
+ QApplication::setPalette(old);
+ QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
+ }
+#endif
+}
+
+#ifndef Q_WS_MAC
+/*
+ Test that scrolling of a widget invalidates the correct regions
+*/
+void tst_QWidget::scroll()
+{
+ UpdateWidget updateWidget;
+ updateWidget.resize(500, 500);
+ updateWidget.reset();
+ updateWidget.show();
+ QTest::qWaitForWindowShown(&updateWidget);
+ QTest::qWait(50);
+ qApp->processEvents();
+ QTRY_VERIFY(updateWidget.numPaintEvents > 0);
+
+ {
+ updateWidget.reset();
+ updateWidget.scroll(10, 10);
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 500, 10));
+ dirty += QRegion(QRect(0, 10, 10, 490));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+
+ {
+ updateWidget.reset();
+ updateWidget.update(0, 0, 10, 10);
+ updateWidget.scroll(0, 10);
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 500, 10));
+ dirty += QRegion(QRect(0, 10, 10, 10));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+
+ {
+ updateWidget.reset();
+ updateWidget.update(0, 0, 100, 100);
+ updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 100, 50));
+ dirty += QRegion(QRect(0, 50, 150, 10));
+ dirty += QRegion(QRect(0, 60, 110, 40));
+ dirty += QRegion(QRect(50, 100, 60, 10));
+ dirty += QRegion(QRect(50, 110, 10, 40));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+
+ {
+ updateWidget.reset();
+ updateWidget.update(0, 0, 100, 100);
+ updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 100, 100));
+ dirty += QRegion(QRect(100, 100, 100, 10));
+ dirty += QRegion(QRect(100, 110, 10, 90));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+}
+#endif
+
+class DestroyedSlotChecker : public QObject
+{
+ Q_OBJECT
+
+public:
+ bool wasQWidget;
+
+ DestroyedSlotChecker()
+ : wasQWidget(false)
+ {
+ }
+
+public slots:
+ void destroyedSlot(QObject *object)
+ {
+ wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
+ }
+};
+
+/*
+ Test that qobject_cast<QWidget*> returns 0 in a slot
+ connected to QObject::destroyed.
+*/
+void tst_QWidget::qobject_castInDestroyedSlot()
+{
+ DestroyedSlotChecker checker;
+ QWidget *widget = new QWidget();
+
+ QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *)));
+ delete widget;
+
+ QVERIFY(checker.wasQWidget == true);
+}
+
+Q_DECLARE_METATYPE(QList<QRect>)
+
+// Since X11 WindowManager operations are all async, and we have no way to know if the window
+// manager has finished playing with the window geometry, this test can't be reliable on X11.
+#ifndef Q_WS_X11
+void tst_QWidget::setWindowGeometry_data()
+{
+ QTest::addColumn<QList<QRect> >("rects");
+ QTest::addColumn<int>("windowFlags");
+
+ QList<QList<QRect> > rects;
+ rects << (QList<QRect>()
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0))
+ << (QList<QRect>()
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200))
+ << (QList<QRect>()
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
+ << (QList<QRect>()
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200))
+ << (QList<QRect>()
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0));
+
+ QList<int> windowFlags;
+ windowFlags << 0 << Qt::FramelessWindowHint;
+
+ foreach (QList<QRect> l, rects) {
+ QRect rect = l.first();
+ foreach (int windowFlag, windowFlags) {
+ QTest::newRow(QString("%1,%2 %3x%4, flags %5")
+ .arg(rect.x())
+ .arg(rect.y())
+ .arg(rect.width())
+ .arg(rect.height())
+ .arg(windowFlag, 0, 16).toAscii())
+ << l
+ << windowFlag;
+ }
+ }
+}
+
+void tst_QWidget::setWindowGeometry()
+{
+ QFETCH(QList<QRect>, rects);
+ QFETCH(int, windowFlags);
+ QRect rect = rects.takeFirst();
+
+ {
+ // test setGeometry() without actually showing the window
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.setGeometry(rect);
+ QTest::qWait(100);
+ QCOMPARE(widget.geometry(), rect);
+
+ // setGeometry() without showing
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(100);
+ QCOMPARE(widget.geometry(), r);
+ }
+ }
+
+ {
+ // setGeometry() first, then show()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.setGeometry(rect);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(20);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() while shown
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(20);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // now hide
+ widget.hide();
+ QTest::qWait(20);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() after hide()
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // show() again, geometry() should still be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // final hide(), again geometry() should be unchanged
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+ }
+
+ {
+ // show() first, then setGeometry()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() while shown
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // now hide
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() after hide()
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // show() again, geometry() should still be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // final hide(), again geometry() should be unchanged
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+ }
+}
+#endif
+
+#if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
+void tst_QWidget::setGeometry_win()
+{
+ QWidget widget;
+ widget.setGeometry(0, 600, 100,100);
+ widget.show();
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ QRect geom = widget.normalGeometry();
+ widget.close();
+ widget.setGeometry(geom);
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ widget.show();
+ RECT rt;
+ ::GetWindowRect(widget.internalWinId(), &rt);
+ QVERIFY(rt.left <= 0);
+ QVERIFY(rt.top <= 0);
+}
+#endif
+
+// Since X11 WindowManager operation are all async, and we have no way to know if the window
+// manager has finished playing with the window geometry, this test can't be reliable on X11.
+// 4DWM issues on IRIX also makes this test fail.
+#if !defined(Q_WS_X11) && !defined(Q_OS_IRIX)
+void tst_QWidget::windowMoveResize_data()
+{
+ setWindowGeometry_data();
+}
+
+void tst_QWidget::windowMoveResize()
+{
+ QFETCH(QList<QRect>, rects);
+ QFETCH(int, windowFlags);
+
+ QRect rect = rects.takeFirst();
+
+ {
+ // test setGeometry() without actually showing the window
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() without showing
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ }
+
+ {
+ // move() first, then show()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ widget.show();
+
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() while shown
+ foreach (QRect r, rects) {
+#ifdef Q_WS_X11
+ if ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0) {
+ QEXPECT_FAIL("130,100 0x200, flags 0",
+ "First resize after show of zero-sized gets wrong win_gravity.",
+ Continue);
+ QEXPECT_FAIL("100,50 200x0, flags 0",
+ "First resize after show of zero-sized gets wrong win_gravity.",
+ Continue);
+ QEXPECT_FAIL("130,50 0x0, flags 0",
+ "First resize after show of zero-sized gets wrong win_gravity.",
+ Continue);
+ }
+#endif
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // now hide
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() after hide()
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+#if defined(Q_WS_MAC)
+ if (r.width() == 0 && r.height() > 0) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ }
+#endif
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // show() again, pos() should be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // final hide(), again pos() should be unchanged
+ widget.hide();
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+ }
+
+ {
+ // show() first, then move()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() while shown
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // now hide
+ widget.hide();
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() after hide()
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+#if defined(Q_WS_MAC)
+ if (r.width() == 0 && r.height() > 0) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ }
+#endif
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // show() again, pos() should be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // final hide(), again pos() should be unchanged
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+ }
+}
+#endif
+
+class ColorWidget : public QWidget
+{
+public:
+ ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
+ : QWidget(parent, Qt::FramelessWindowHint), color(c)
+ {
+ QPalette opaquePalette = palette();
+ opaquePalette.setColor(backgroundRole(), color);
+ setPalette(opaquePalette);
+ setAutoFillBackground(true);
+ }
+
+ void paintEvent(QPaintEvent *e) {
+ r += e->region();
+ }
+
+ void reset() {
+ r = QRegion();
+ }
+
+ QColor color;
+ QRegion r;
+};
+
+#define VERIFY_COLOR(region, color) { \
+ const QRegion r = QRegion(region); \
+ for (int i = 0; i < r.rects().size(); ++i) { \
+ const QRect rect = r.rects().at(i); \
+ for (int t = 0; t < 5; t++) { \
+ const QPixmap pixmap = QPixmap::grabWindow(QDesktopWidget().winId(), \
+ rect.left(), rect.top(), \
+ rect.width(), rect.height()); \
+ QCOMPARE(pixmap.size(), rect.size()); \
+ QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
+ expectedPixmap.detach(); \
+ expectedPixmap.fill(color); \
+ QImage image = pixmap.toImage(); \
+ uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
+ uint firstPixel = image.pixel(0,0) | alphaCorrection; \
+ if ( firstPixel != QColor(color).rgb() && t < 4 ) \
+ { QTest::qWait(200); continue; } \
+ QCOMPARE(firstPixel, QColor(color).rgb()); \
+ QCOMPARE(pixmap, expectedPixmap); \
+ break; \
+ } \
+ } \
+}
+
+void tst_QWidget::moveChild_data()
+{
+ QTest::addColumn<QPoint>("offset");
+
+ QTest::newRow("right") << QPoint(20, 0);
+ QTest::newRow("down") << QPoint(0, 20);
+ QTest::newRow("left") << QPoint(-20, 0);
+ QTest::newRow("up") << QPoint(0, -20);
+}
+
+void tst_QWidget::moveChild()
+{
+ QFETCH(QPoint, offset);
+
+ ColorWidget parent;
+ // prevent custom styles
+ parent.setStyle(new QWindowsStyle);
+ ColorWidget child(&parent, Qt::blue);
+
+#ifndef Q_OS_WINCE
+ parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
+ QSize(100, 100)));
+#else
+ parent.setGeometry(60, 60, 150, 150);
+#endif
+ child.setGeometry(25, 25, 50, 50);
+ QPoint childOffset = child.mapToGlobal(QPoint());
+
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QTest::qWait(30);
+ const QPoint tlwOffset = parent.geometry().topLeft();
+
+ QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
+ QTRY_COMPARE(child.r, QRegion(child.rect()));
+ VERIFY_COLOR(child.geometry().translated(tlwOffset),
+ child.color);
+ VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
+ parent.color);
+ parent.reset();
+ child.reset();
+
+ // move
+
+ const QRect oldGeometry = child.geometry();
+
+ QPoint pos = child.pos() + offset;
+ child.move(pos);
+ QTest::qWait(100);
+ QTRY_COMPARE(pos, child.pos());
+
+ QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
+#if !defined(Q_WS_MAC)
+ // should be scrolled in backingstore
+ QCOMPARE(child.r, QRegion());
+#endif
+ VERIFY_COLOR(child.geometry().translated(tlwOffset),
+ child.color);
+ VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
+ parent.color);
+}
+
+void tst_QWidget::showAndMoveChild()
+{
+ QWidget parent(0, Qt::FramelessWindowHint);
+ // prevent custom styles
+ parent.setStyle(new QWindowsStyle);
+
+ QDesktopWidget desktop;
+ QRect desktopDimensions = desktop.availableGeometry(&parent);
+ desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
+
+ parent.setGeometry(desktopDimensions);
+ parent.setPalette(Qt::red);
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QTest::qWait(10);
+
+ const QPoint tlwOffset = parent.geometry().topLeft();
+ QWidget child(&parent);
+ child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
+ child.setPalette(Qt::blue);
+ child.setAutoFillBackground(true);
+
+ // Ensure that the child is repainted correctly when moved right after show.
+ // NB! Do NOT processEvents() (or qWait()) in between show() and move().
+ child.show();
+ child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
+ qApp->processEvents();
+
+ VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
+ VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
+}
+
+// Cocoa only has rect granularity.
+#ifndef QT_OS_MAC
+void tst_QWidget::subtractOpaqueSiblings()
+{
+ QWidget w;
+ w.setGeometry(50, 50, 300, 300);
+
+ ColorWidget *large = new ColorWidget(&w, Qt::red);
+ large->setGeometry(50, 50, 200, 200);
+
+ ColorWidget *medium = new ColorWidget(large, Qt::gray);
+ medium->setGeometry(50, 50, 100, 100);
+
+ ColorWidget *tall = new ColorWidget(&w, Qt::blue);
+ tall->setGeometry(100, 30, 50, 100);
+
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+
+ large->reset();
+ medium->reset();
+ tall->reset();
+
+ medium->update();
+ QTest::qWait(10);
+
+ // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
+ // to be repainted and tall from be repainted at all.
+
+ QTRY_COMPARE(large->r, QRegion());
+ QTRY_COMPARE(tall->r, QRegion());
+ QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
+ QRegion(medium->geometry().translated(large->pos()))
+ - tall->geometry());
+}
+#endif
+
+void tst_QWidget::deleteStyle()
+{
+ QWidget widget;
+ widget.setStyle(new QWindowsStyle);
+ widget.show();
+ delete widget.style();
+ qApp->processEvents();
+}
+
+#ifdef Q_WS_WIN
+void tst_QWidget::getDC()
+{
+ QWidget widget;
+ widget.setGeometry(0, 0, 2, 4);
+
+ HDC dc = widget.getDC();
+ QVERIFY(dc != 0);
+
+ widget.releaseDC(dc);
+}
+#endif
+
+class TopLevelFocusCheck: public QWidget
+{
+ Q_OBJECT
+public:
+ QLineEdit* edit;
+ TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
+ {
+ edit = new QLineEdit(this);
+ edit->hide();
+ edit->installEventFilter(this);
+ }
+
+public slots:
+ void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
+ {
+ edit->show();
+ edit->setFocus(Qt::OtherFocusReason);
+ qApp->processEvents();
+ }
+ bool eventFilter(QObject *obj, QEvent *event)
+ {
+ if (obj == edit && event->type()== QEvent::FocusOut) {
+ edit->hide();
+ return true;
+ }
+ return false;
+ }
+};
+
+void tst_QWidget::multipleToplevelFocusCheck()
+{
+ TopLevelFocusCheck w1;
+ TopLevelFocusCheck w2;
+
+ w1.resize(200, 200);
+ w1.show();
+ QTest::qWaitForWindowShown(&w1);
+ w2.resize(200,200);
+ w2.show();
+ QTest::qWaitForWindowShown(&w2);
+
+ QTest::qWait(100);
+
+ QApplication::setActiveWindow(&w1);
+ w1.activateWindow();
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
+ QTest::qWait(50);
+ QTest::mouseDClick(&w1, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
+
+ w2.activateWindow();
+ QApplication::setActiveWindow(&w2);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
+ QTest::mouseClick(&w2, Qt::LeftButton);
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "embedded toplevels take focus anyway", Continue);
+#endif
+ QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
+
+ QTest::mouseDClick(&w2, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
+
+ w1.activateWindow();
+ QApplication::setActiveWindow(&w1);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
+ QTest::mouseDClick(&w1, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
+
+ w2.activateWindow();
+ QApplication::setActiveWindow(&w2);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
+ QTest::mouseClick(&w2, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
+}
+
+void tst_QWidget::setFocus()
+{
+ {
+ // move focus to another window
+ testWidget->activateWindow();
+ QApplication::setActiveWindow(testWidget);
+ if (testWidget->focusWidget())
+ testWidget->focusWidget()->clearFocus();
+ else
+ testWidget->clearFocus();
+
+ // window and children never shown, nobody gets focus
+ QWidget window;
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+ }
+
+ {
+ // window and children show, but window not active, nobody gets focus
+ QWidget window;
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ window.show();
+
+ // note: window may be active, but we don't want it to be
+ testWidget->activateWindow();
+ QApplication::setActiveWindow(testWidget);
+ if (testWidget->focusWidget())
+ testWidget->focusWidget()->clearFocus();
+ else
+ testWidget->clearFocus();
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+ }
+
+ {
+ // window and children show, but window *is* active, children get focus
+ QWidget window;
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ window.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+#else
+ window.activateWindow();
+ QApplication::processEvents();
+#endif
+
+ child1.setFocus();
+ QTRY_VERIFY(child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), &child1);
+
+ child2.setFocus();
+ QVERIFY(child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), &child2);
+ }
+
+ {
+ // window shown and active, children created, don't get focus, but get focus when shown
+ QWidget window;
+
+ window.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+#else
+ window.activateWindow();
+#endif
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child1.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&child1);
+ child1.activateWindow();
+#endif
+ QApplication::processEvents();
+ QTRY_VERIFY(child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), &child1);
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), &child1);
+
+ child2.show();
+ QVERIFY(child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), &child2);
+ }
+
+ {
+ // window shown and active, children created, don't get focus,
+ // even after setFocus(), hide(), then show()
+ QWidget window;
+
+ window.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+#else
+ window.activateWindow();
+#endif
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child1.hide();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child1.show();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.hide();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.show();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+ }
+}
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QWidget *widget, QEvent::Type event)
+ : m_widget(widget), eventToSpy(event), m_count(0)
+ {
+ if (m_widget)
+ m_widget->installEventFilter(this);
+ }
+
+ QWidget *widget() const { return m_widget; }
+ int count() const { return m_count; }
+ void clear() { m_count = 0; }
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ if (event->type() == eventToSpy)
+ ++m_count;
+ return QObject::eventFilter(object, event);
+ }
+
+private:
+ QWidget *m_widget;
+ QEvent::Type eventToSpy;
+ int m_count;
+};
+
+void tst_QWidget::setCursor()
+{
+#ifndef QT_NO_CURSOR
+ {
+ QWidget window;
+ QWidget child(&window);
+
+ QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+
+ window.setCursor(window.cursor());
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+ // do it again, but with window show()n
+ {
+ QWidget window;
+ QWidget child(&window);
+ window.show();
+
+ QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+
+ window.setCursor(window.cursor());
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+
+ {
+ QWidget window;
+ QWidget child(&window);
+
+ window.setCursor(Qt::WaitCursor);
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+ // same thing again, just with window show()n
+ {
+ QWidget window;
+ QWidget child(&window);
+
+ window.show();
+ window.setCursor(Qt::WaitCursor);
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+ // reparenting child should not cause the WA_SetCursor to become set
+ {
+ QWidget window;
+ QWidget window2;
+ QWidget child(&window);
+
+ window.setCursor(Qt::WaitCursor);
+
+ child.setParent(0);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), QCursor().shape());
+
+ child.setParent(&window2);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+
+ window2.setCursor(Qt::WaitCursor);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+ }
+
+ // again, with windows show()n
+ {
+ QWidget window;
+ QWidget window2;
+ QWidget child(&window);
+
+ window.setCursor(Qt::WaitCursor);
+ window.show();
+
+ child.setParent(0);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), QCursor().shape());
+
+ child.setParent(&window2);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+
+ window2.show();
+ window2.setCursor(Qt::WaitCursor);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+ }
+
+ // test if CursorChange is sent
+ {
+ QWidget widget;
+ EventSpy spy(&widget, QEvent::CursorChange);
+ QCOMPARE(spy.count(), 0);
+ widget.setCursor(QCursor(Qt::WaitCursor));
+ QCOMPARE(spy.count(), 1);
+ widget.unsetCursor();
+ QCOMPARE(spy.count(), 2);
+ }
+#endif
+}
+
+void tst_QWidget::setToolTip()
+{
+ QWidget widget;
+ EventSpy spy(&widget, QEvent::ToolTipChange);
+ QCOMPARE(spy.count(), 0);
+
+ QCOMPARE(widget.toolTip(), QString());
+ widget.setToolTip(QString("Hello"));
+ QCOMPARE(widget.toolTip(), QString("Hello"));
+ QCOMPARE(spy.count(), 1);
+ widget.setToolTip(QString());
+ QCOMPARE(widget.toolTip(), QString());
+ QCOMPARE(spy.count(), 2);
+
+ // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
+#ifndef Q_OS_WINCE_WM
+ for (int pass = 0; pass < 2; ++pass) {
+ QWidget *popup = new QWidget(0, Qt::Popup);
+ popup->resize(150, 50);
+ QFrame *frame = new QFrame(popup);
+ frame->setGeometry(0, 0, 50, 50);
+ frame->setFrameStyle(QFrame::Box | QFrame::Plain);
+ EventSpy spy1(frame, QEvent::ToolTip);
+ EventSpy spy2(popup, QEvent::ToolTip);
+ frame->setMouseTracking(pass == 0 ? false : true);
+ frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
+ popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
+ popup->show();
+ QTest::qWaitForWindowShown(popup);
+ QTest::qWait(10);
+ QTest::mouseMove(frame);
+ QTest::qWait(900); // delay is 700
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 0);
+ if (pass == 0)
+ QTest::qWait(2200); // delay is 2000
+ QTest::mouseMove(popup);
+ delete popup;
+ }
+#endif
+}
+
+void tst_QWidget::testWindowIconChangeEventPropagation()
+{
+ // Create widget hierarchy.
+ QWidget topLevelWidget;
+ QWidget topLevelChild(&topLevelWidget);
+
+ QDialog dialog(&topLevelWidget);
+ QWidget dialogChild(&dialog);
+
+ QWidgetList widgets;
+ widgets << &topLevelWidget << &topLevelChild
+ << &dialog << &dialogChild;
+ QCOMPARE(widgets.count(), 4);
+
+ // Create spy lists.
+ QList <EventSpy *> applicationEventSpies;
+ QList <EventSpy *> widgetEventSpies;
+ foreach (QWidget *widget, widgets) {
+ applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange));
+ widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange));
+ }
+
+ // QApplication::setWindowIcon
+ const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
+ qApp->setWindowIcon(windowIcon);
+
+ for (int i = 0; i < widgets.count(); ++i) {
+ // Check QEvent::ApplicationWindowIconChange
+ EventSpy *spy = applicationEventSpies.at(i);
+ QWidget *widget = spy->widget();
+ if (widget->isWindow()) {
+ QCOMPARE(spy->count(), 1);
+ QCOMPARE(widget->windowIcon(), windowIcon);
+ } else {
+ QCOMPARE(spy->count(), 0);
+ }
+ spy->clear();
+
+ // Check QEvent::WindowIconChange
+ spy = widgetEventSpies.at(i);
+ QCOMPARE(spy->count(), 1);
+ spy->clear();
+ }
+
+ // Set icon on a top-level widget.
+ topLevelWidget.setWindowIcon(*new QIcon);
+
+ for (int i = 0; i < widgets.count(); ++i) {
+ // Check QEvent::ApplicationWindowIconChange
+ EventSpy *spy = applicationEventSpies.at(i);
+ QCOMPARE(spy->count(), 0);
+ spy->clear();
+
+ // Check QEvent::WindowIconChange
+ spy = widgetEventSpies.at(i);
+ QWidget *widget = spy->widget();
+ if (widget == &topLevelWidget) {
+ QCOMPARE(widget->windowIcon(), QIcon());
+ QCOMPARE(spy->count(), 1);
+ } else if (topLevelWidget.isAncestorOf(widget)) {
+ QCOMPARE(spy->count(), 1);
+ } else {
+ QCOMPARE(spy->count(), 0);
+ }
+ spy->clear();
+ }
+
+ // Cleanup.
+ for (int i = 0; i < widgets.count(); ++i) {
+ delete applicationEventSpies.at(i);
+ delete widgetEventSpies.at(i);
+ }
+ qApp->setWindowIcon(QIcon());
+}
+
+#ifdef Q_WS_X11
+void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
+{
+ // Same size as in QWidget::create_sys().
+ const QSize desktopSize = QApplication::desktop()->size();
+ const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
+
+ { // Maximum size.
+ QWidget widget(0, Qt::X11BypassWindowManagerHint);
+
+ const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
+ widget.setMaximumSize(newMaximumSize);
+ QCOMPARE(widget.size(), newMaximumSize);
+
+ widget.show();
+ qt_x11_wait_for_window_manager(&widget);
+ QCOMPARE(widget.size(), newMaximumSize);
+ }
+
+ { // Minimum size.
+ QWidget widget(0, Qt::X11BypassWindowManagerHint);
+
+ const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
+ widget.setMinimumSize(newMinimumSize);
+ QCOMPARE(widget.size(), newMinimumSize);
+
+ widget.show();
+ qt_x11_wait_for_window_manager(&widget);
+ QCOMPARE(widget.size(), newMinimumSize);
+ }
+}
+
+class ShowHideShowWidget : public QWidget
+{
+ Q_OBJECT
+
+ int state;
+public:
+ bool gotExpectedMapNotify;
+
+ ShowHideShowWidget()
+ : state(0), gotExpectedMapNotify(false)
+ {
+ startTimer(1000);
+ }
+
+ void timerEvent(QTimerEvent *)
+ {
+ switch (state++) {
+ case 0:
+ show();
+ break;
+ case 1:
+ emit done();
+ break;
+ }
+ }
+
+ bool x11Event(XEvent *event)
+ {
+ if (state == 1 && event->type == MapNotify)
+ gotExpectedMapNotify = true;
+ return false;
+ }
+
+signals:
+ void done();
+};
+
+void tst_QWidget::showHideShow()
+{
+ ShowHideShowWidget w;
+ w.show();
+ w.hide();
+
+ QEventLoop eventLoop;
+ connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+
+ QVERIFY(w.gotExpectedMapNotify);
+}
+
+void tst_QWidget::clean_qt_x11_enforce_cursor()
+{
+ {
+ QWidget window;
+ QWidget *w = new QWidget(&window);
+ QWidget *child = new QWidget(w);
+ child->setAttribute(Qt::WA_SetCursor, true);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ QTest::qWait(100);
+ QCursor::setPos(window.geometry().center());
+ QTest::qWait(100);
+
+ child->setFocus();
+ QApplication::processEvents();
+ QTest::qWait(100);
+
+ delete w;
+ }
+
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ scene.addWidget(edit);
+
+ // If the test didn't crash, then it passed.
+}
+#endif
+
+class EventRecorder : public QObject
+{
+ Q_OBJECT
+
+public:
+ typedef QList<QPair<QWidget *, QEvent::Type> > EventList;
+
+ EventRecorder(QObject *parent = 0)
+ : QObject(parent)
+ { }
+
+ EventList eventList()
+ {
+ return events;
+ }
+
+ void clear()
+ {
+ events.clear();
+ }
+
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ QWidget *widget = qobject_cast<QWidget *>(object);
+ if (widget && !event->spontaneous())
+ events.append(qMakePair(widget, event->type()));
+ return false;
+ }
+
+private:
+ EventList events;
+};
+
+void tst_QWidget::compatibilityChildInsertedEvents()
+{
+ EventRecorder::EventList expected;
+ bool accessibilityEnabled = false;
+
+ // Move away the cursor; otherwise it might result in an enter event if it's
+ // inside the widget when the widget is shown.
+ QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
+ QTest::qWait(100);
+
+ {
+ // no children created, not shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QCoreApplication::sendPostedEvents();
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // no children, shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ widget.show();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::WinIdChange)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::Move)
+ << qMakePair(&widget, QEvent::Resize)
+ << qMakePair(&widget, QEvent::Show);
+
+ if (accessibilityEnabled)
+ expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
+ expected << qMakePair(&widget, QEvent::ShowToParent);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
+
+#ifdef Q_OS_MAC
+ expected << qMakePair(&widget, QEvent::UpdateLater);
+#endif
+ expected << qMakePair(&widget, QEvent::UpdateRequest);
+
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, not shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, widget shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ widget.show();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::WinIdChange)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Move)
+ << qMakePair(&widget, QEvent::Resize)
+ << qMakePair(&widget, QEvent::Show);
+
+ if (accessibilityEnabled)
+ expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
+ expected << qMakePair(&widget, QEvent::ShowToParent);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+
+#ifdef Q_OS_MAC
+ expected << qMakePair(&widget, QEvent::UpdateLater);
+#endif
+ expected << qMakePair(&widget, QEvent::UpdateRequest);
+
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, but one is reparented away, not shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+ child2.setParent(0);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildRemoved);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, but one is reparented away, then widget is shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+ child2.setParent(0);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildRemoved);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ widget.show();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::WinIdChange)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Move)
+ << qMakePair(&widget, QEvent::Resize)
+ << qMakePair(&widget, QEvent::Show);
+
+ if (accessibilityEnabled)
+ expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
+ expected << qMakePair(&widget, QEvent::ShowToParent);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+
+#ifdef Q_OS_MAC
+ expected << qMakePair(&widget, QEvent::UpdateLater);
+#endif
+ expected << qMakePair(&widget, QEvent::UpdateRequest);
+
+ QCOMPARE(spy.eventList(), expected);
+ }
+}
+
+class RenderWidget : public QWidget
+{
+public:
+ RenderWidget(QWidget *source)
+ : source(source), ellipse(false) {}
+
+ void setEllipseEnabled(bool enable = true)
+ {
+ ellipse = enable;
+ update();
+ }
+
+protected:
+ void paintEvent(QPaintEvent *)
+ {
+ if (ellipse) {
+ QPainter painter(this);
+ painter.fillRect(rect(), Qt::red);
+ painter.end();
+ QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
+ QRegion::Ellipse);
+ source->render(this, QPoint(0, 30), regionToRender);
+ } else {
+ source->render(this);
+ }
+ }
+
+private:
+ QWidget *source;
+ bool ellipse;
+};
+
+void tst_QWidget::render()
+{
+ return;
+ QCalendarWidget source;
+ // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
+ // is enabled on the screen
+ QFont f;
+ f.setStyleStrategy(QFont::NoAntialias);
+ source.setFont(f);
+ source.show();
+ QTest::qWaitForWindowShown(&source);
+
+ // Render the entire source into target.
+ RenderWidget target(&source);
+ target.resize(source.size());
+ target.show();
+
+ qApp->processEvents();
+ qApp->sendPostedEvents();
+ QTest::qWait(250);
+
+ QImage sourceImage = QPixmap::grabWidget(&source).toImage();
+ qApp->processEvents();
+ QImage targetImage = QPixmap::grabWidget(&target).toImage();
+ qApp->processEvents();
+ QCOMPARE(sourceImage, targetImage);
+
+ // Fill target.rect() will Qt::red and render
+ // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
+ // of source into target with offset (0, 30).
+ target.setEllipseEnabled();
+ qApp->processEvents();
+ qApp->sendPostedEvents();
+
+ targetImage = QPixmap::grabWidget(&target).toImage();
+ QVERIFY(sourceImage != targetImage);
+
+ QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
+ QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
+
+ // Test that a child widget properly fills its background
+ {
+ QWidget window;
+ window.resize(100, 100);
+ // prevent custom styles
+ window.setStyle(new QWindowsStyle);
+ window.show();
+ QTest::qWaitForWindowShown(&window);
+ QWidget child(&window);
+ child.resize(window.size());
+ child.show();
+
+ qApp->processEvents();
+ QCOMPARE(QPixmap::grabWidget(&child), QPixmap::grabWidget(&window));
+ }
+
+ { // Check that the target offset is correct.
+ QWidget widget;
+ widget.resize(200, 200);
+ widget.setAutoFillBackground(true);
+ widget.setPalette(Qt::red);
+ // prevent custom styles
+ widget.setStyle(new QWindowsStyle);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QImage image(widget.size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::blue).rgb());
+
+ // Target offset (0, 0)
+ widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
+ QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
+
+ // Target offset (20, 20).
+ image.fill(QColor(Qt::blue).rgb());
+ widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
+ QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
+ QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
+ QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
+ }
+}
+
+// On Windows the active palette is used instead of the inactive palette even
+// though the widget is invisible. This is probably related to task 178507/168682,
+// but for the renderInvisible test it doesn't matter, we're mostly interested
+// in testing the geometry so just workaround the palette issue for now.
+static void workaroundPaletteIssue(QWidget *widget)
+{
+#ifndef Q_WS_WIN
+ return;
+#endif
+ if (!widget)
+ return;
+
+ QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
+ QVERIFY(navigationBar);
+
+ QPalette palette = navigationBar->palette();
+ const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
+ const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
+ palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
+ palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
+ navigationBar->setPalette(palette);
+}
+
+//#define RENDER_DEBUG
+void tst_QWidget::renderInvisible()
+{
+ QCalendarWidget *calendar = new QCalendarWidget;
+ // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
+ // is enabled on the screen
+ QFont f;
+ f.setStyleStrategy(QFont::NoAntialias);
+ calendar->setFont(f);
+ calendar->show();
+ QTest::qWaitForWindowShown(calendar);
+
+ // Create a dummy focus widget to get rid of focus rect in reference image.
+ QLineEdit dummyFocusWidget;
+ dummyFocusWidget.show();
+ QTest::qWaitForWindowShown(&dummyFocusWidget);
+ qApp->processEvents();
+ QTest::qWait(120);
+
+ // Create normal reference image.
+ const QSize calendarSize = calendar->size();
+ QImage referenceImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&referenceImage);
+#ifdef RENDER_DEBUG
+ referenceImage.save("referenceImage.png");
+#endif
+ QVERIFY(!referenceImage.isNull());
+
+ // Create resized reference image.
+ const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
+ calendar->resize(calendarSizeResized);
+ qApp->processEvents();
+ QTest::qWait(30);
+ QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
+ calendar->render(&referenceImageResized);
+#ifdef RENDER_DEBUG
+ referenceImageResized.save("referenceImageResized.png");
+#endif
+ QVERIFY(!referenceImageResized.isNull());
+
+ // Explicitly hide the calendar.
+ calendar->hide();
+ qApp->processEvents();
+ QTest::qWait(30);
+ workaroundPaletteIssue(calendar);
+
+ { // Make sure we get the same image when the calendar is explicitly hidden.
+ QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("explicitlyHiddenCalendarResized.png");
+#endif
+ QCOMPARE(testImage, referenceImageResized);
+ }
+
+ // Now that we have reference images we can delete the source and re-create
+ // the calendar and check that we get the same images from a calendar which has never
+ // been visible, laid out or created (Qt::WA_WState_Created).
+ delete calendar;
+ calendar = new QCalendarWidget;
+ calendar->setFont(f);
+ workaroundPaletteIssue(calendar);
+
+ { // Never been visible, created or laid out.
+ QImage testImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
+#endif
+ QCOMPARE(testImage, referenceImage);
+ }
+
+ calendar->hide();
+ qApp->processEvents();
+ QTest::qWait(30);
+
+ { // Calendar explicitly hidden.
+ QImage testImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("explicitlyHiddenCalendar.png");
+#endif
+ QCOMPARE(testImage, referenceImage);
+ }
+
+ // Get navigation bar and explicitly hide it.
+ QWidget *navigationBar = qFindChild<QWidget *>(calendar, QLatin1String("qt_calendar_navigationbar"));
+ QVERIFY(navigationBar);
+ navigationBar->hide();
+
+ { // Check that the navigation bar isn't drawn when rendering the entire calendar.
+ QImage testImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("calendarWithoutNavigationBar.png");
+#endif
+ QVERIFY(testImage != referenceImage);
+ }
+
+ { // Make sure the navigation bar renders correctly even though it's hidden.
+ QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
+ navigationBar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("explicitlyHiddenNavigationBar.png");
+#endif
+ QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
+ }
+
+ // Get next month button.
+ QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
+ QVERIFY(nextMonthButton);
+
+ { // Render next month button.
+ // Fill test image with correct background color.
+ QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
+ navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
+#ifdef RENDER_DEBUG
+ testImage.save("nextMonthButtonBackground.png");
+#endif
+
+ // Set the button's background color to Qt::transparent; otherwise it will fill the
+ // background with QPalette::Window.
+ const QPalette originalPalette = nextMonthButton->palette();
+ QPalette palette = originalPalette;
+ palette.setColor(QPalette::Window, Qt::transparent);
+ nextMonthButton->setPalette(palette);
+
+ // Render the button on top of the background.
+ nextMonthButton->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("nextMonthButton.png");
+#endif
+ const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size());
+ QCOMPARE(testImage, referenceImage.copy(buttonRect));
+
+ // Restore palette.
+ nextMonthButton->setPalette(originalPalette);
+ }
+
+ // Navigation bar isn't explicitly hidden anymore.
+ navigationBar->show();
+ qApp->processEvents();
+ QTest::qWait(30);
+ QVERIFY(!calendar->isVisible());
+
+ // Now, completely mess up the layout. This will trigger an update on the layout
+ // when the calendar is visible or shown, but it's not. QWidget::render must therefore
+ // make sure the layout is activated before rendering.
+ QVERIFY(!calendar->isVisible());
+ calendar->resize(calendarSizeResized);
+ qApp->processEvents();
+
+ { // Make sure we get an image equal to the resized reference image.
+ QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("calendarResized.png");
+#endif
+ QCOMPARE(testImage, referenceImageResized);
+ }
+
+ { // Make sure we lay out the widget correctly the first time it's rendered.
+ QCalendarWidget calendar;
+ const QSize calendarSize = calendar.sizeHint();
+
+ QImage image(2 * calendarSize, QImage::Format_ARGB32);
+ image.fill(QColor(Qt::red).rgb());
+ calendar.render(&image);
+
+ for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
+ for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+
+ { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
+ // right after widgets have been added/removed to/from its layout.
+ QWidget topLevel;
+ topLevel.setLayout(new QVBoxLayout);
+
+ QWidget *widget = new QLineEdit;
+ topLevel.layout()->addWidget(widget);
+
+ const QSize initialSize = topLevel.size();
+ QPixmap pixmap(topLevel.sizeHint());
+ topLevel.render(&pixmap); // triggers adjustSize()
+ const QSize finalSize = topLevel.size();
+ QVERIFY(finalSize != initialSize);
+
+ topLevel.layout()->removeWidget(widget);
+ QCOMPARE(topLevel.size(), finalSize);
+ topLevel.render(&pixmap);
+ QCOMPARE(topLevel.size(), finalSize);
+
+ topLevel.layout()->addWidget(widget);
+ QCOMPARE(topLevel.size(), finalSize);
+ topLevel.render(&pixmap);
+ QCOMPARE(topLevel.size(), finalSize);
+ }
+}
+
+void tst_QWidget::renderWithPainter()
+{
+ QWidget widget;
+ // prevent custom styles
+ widget.setStyle(new QWindowsStyle);
+ widget.show();
+ widget.resize(70, 50);
+ widget.setAutoFillBackground(true);
+ widget.setPalette(Qt::black);
+
+ // Render the entire widget onto the image.
+ QImage image(QSize(70, 50), QImage::Format_ARGB32);
+ image.fill(QColor(Qt::red).rgb());
+ QPainter painter(&image);
+ widget.render(&painter);
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+
+ // Translate painter (10, 10).
+ painter.save();
+ image.fill(QColor(Qt::red).rgb());
+ painter.translate(10, 10);
+ widget.render(&painter);
+ painter.restore();
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 10 || j < 10)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+ }
+
+ // Pass target offset (10, 10) (the same as QPainter::translate).
+ image.fill(QColor(Qt::red).rgb());
+ widget.render(&painter, QPoint(10, 10));
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 10 || j < 10)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+ }
+
+ // Translate (10, 10) and pass target offset (10, 10).
+ painter.save();
+ image.fill(QColor(Qt::red).rgb());
+ painter.translate(10, 10);
+ widget.render(&painter, QPoint(10, 10));
+ painter.restore();
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 20 || j < 20)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+ }
+
+ // Rotate painter 90 degrees.
+ painter.save();
+ image.fill(QColor(Qt::red).rgb());
+ painter.rotate(90);
+ widget.render(&painter);
+ painter.restore();
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+
+ // Translate and rotate.
+ image.fill(QColor(Qt::red).rgb());
+ widget.resize(40, 10);
+ painter.translate(10, 10);
+ painter.rotate(90);
+ widget.render(&painter);
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i >= 10 && j >= 0 && j < 10)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+
+ // Make sure QWidget::render does not modify the render hints set on the painter.
+ painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
+ | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
+ QPainter::RenderHints oldRenderHints = painter.renderHints();
+ widget.render(&painter);
+ QCOMPARE(painter.renderHints(), oldRenderHints);
+}
+
+void tst_QWidget::render_task188133()
+{
+ QMainWindow mainWindow;
+
+ // Make sure QWidget::render does not trigger QWidget::repaint/update
+ // and asserts for Qt::WA_WState_Created.
+ QPixmap pixmap = QPixmap::grabWidget(&mainWindow);
+}
+
+void tst_QWidget::render_task211796()
+{
+ class MyWidget : public QWidget
+ {
+ void resizeEvent(QResizeEvent *)
+ {
+ QPixmap pixmap(size());
+ render(&pixmap);
+ }
+ };
+
+ { // Please don't die in a resize recursion.
+ MyWidget widget;
+ widget.resize(200, 200);
+ widget.show();
+ }
+
+ { // Same check with a deeper hierarchy.
+ QWidget widget;
+ widget.show();
+ QWidget child(&widget);
+ MyWidget grandChild;
+ grandChild.setParent(&child);
+ grandChild.resize(100, 100);
+ child.show();
+ }
+}
+
+void tst_QWidget::render_task217815()
+{
+ // Make sure we don't change the size of the widget when calling
+ // render() and the widget has an explicit size set.
+ // This was a problem on Windows because we called createWinId(),
+ // which in turn enforced the size to be bigger than the smallest
+ // possible native window size (which is (115,something) on WinXP).
+ QWidget widget;
+ const QSize explicitSize(80, 20);
+ widget.resize(explicitSize);
+ QCOMPARE(widget.size(), explicitSize);
+
+ QPixmap pixmap(explicitSize);
+ widget.render(&pixmap);
+
+ QCOMPARE(widget.size(), explicitSize);
+}
+
+// Window Opacity is not supported on Windows CE.
+#ifndef Q_OS_WINCE
+void tst_QWidget::render_windowOpacity()
+{
+ const qreal opacity = 0.5;
+
+ { // Check that the painter opacity effects the widget drawing.
+ QWidget topLevel;
+ QWidget child(&topLevel);
+ child.resize(50, 50);
+ child.setPalette(Qt::red);
+ child.setAutoFillBackground(true);
+
+ QPixmap expected(child.size());
+#ifdef Q_WS_X11
+ if (expected.depth() < 24) {
+ QSKIP("This test won't give correct results with dithered pixmaps", SkipAll);
+ }
+#endif
+ expected.fill(Qt::green);
+ QPainter painter(&expected);
+ painter.setOpacity(opacity);
+ painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
+ painter.end();
+
+ QPixmap result(child.size());
+ result.fill(Qt::green);
+ painter.begin(&result);
+ painter.setOpacity(opacity);
+ child.render(&painter);
+ painter.end();
+ QCOMPARE(result, expected);
+ }
+
+ { // Combine the opacity set on the painter with the widget opacity.
+ class MyWidget : public QWidget
+ {
+ public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ painter.setOpacity(opacity);
+ QCOMPARE(painter.opacity(), opacity);
+ painter.fillRect(rect(), Qt::red);
+ }
+ qreal opacity;
+ };
+
+ MyWidget widget;
+ widget.resize(50, 50);
+ widget.opacity = opacity;
+ widget.setPalette(Qt::blue);
+ widget.setAutoFillBackground(true);
+
+ QPixmap expected(widget.size());
+ expected.fill(Qt::green);
+ QPainter painter(&expected);
+ painter.setOpacity(opacity);
+ QPixmap pixmap(widget.size());
+ pixmap.fill(Qt::blue);
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setOpacity(opacity);
+ pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
+ painter.drawPixmap(QPoint(), pixmap);
+ painter.end();
+
+ QPixmap result(widget.size());
+ result.fill(Qt::green);
+ painter.begin(&result);
+ painter.setOpacity(opacity);
+ widget.render(&painter);
+ painter.end();
+ QCOMPARE(result, expected);
+ }
+}
+#endif
+
+void tst_QWidget::render_systemClip()
+{
+ QWidget widget;
+ widget.setPalette(Qt::blue);
+ widget.resize(100, 100);
+
+ QImage image(widget.size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::red).rgb());
+
+ QPaintEngine *paintEngine = image.paintEngine();
+ QVERIFY(paintEngine);
+ paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
+
+ QPainter painter(&image);
+ // Make sure we're using the same paint engine and has the right clip set.
+ QCOMPARE(painter.paintEngine(), paintEngine);
+ QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
+
+ // Translate painter outside system clip.
+ painter.translate(50, 0);
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ image.save("outside_systemclip.png");
+#endif
+
+ // All pixels should be red.
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+
+ // Restore painter and refill image with red.
+ image.fill(QColor(Qt::red).rgb());
+ painter.translate(-50, 0);
+
+ // Set transform on the painter.
+ QTransform transform;
+ transform.shear(0, 1);
+ painter.setTransform(transform);
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ image.save("blue_triangle.png");
+#endif
+
+ // We should now have a blue triangle starting at scan line 1, and the rest should be red.
+ // rrrrrrrrrr
+ // brrrrrrrrr
+ // bbrrrrrrrr
+ // bbbrrrrrrr
+ // bbbbrrrrrr
+ // rrrrrrrrrr
+ // ...
+
+#ifndef Q_WS_MAC
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 50 && j < i)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+#else
+ // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
+ // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
+ // expected image by first painting on a pixmap, and then draw the pixmap onto
+ // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
+ // The check is basically the same, except that it takes the smoothening into account.
+ QPixmap pixmap(50, 50);
+ const QRegion sysClip(0, 0, 50, 50);
+ widget.render(&pixmap, QPoint(), sysClip);
+
+ QImage expectedImage(widget.size(), QImage::Format_RGB32);
+ expectedImage.fill(QColor(Qt::red).rgb());
+ expectedImage.paintEngine()->setSystemClip(sysClip);
+
+ QPainter expectedImagePainter(&expectedImage);
+ expectedImagePainter.setTransform(QTransform().shear(0, 1));
+ // NB! This is the important part (SmoothPixmapTransform).
+ expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
+ expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
+ expectedImagePainter.end();
+
+ QCOMPARE(image, expectedImage);
+#endif
+}
+
+void tst_QWidget::render_systemClip2_data()
+{
+ QTest::addColumn<bool>("autoFillBackground");
+ QTest::addColumn<bool>("usePaintEvent");
+ QTest::addColumn<QColor>("expectedColor");
+
+ QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
+ QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
+ QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
+}
+
+void tst_QWidget::render_systemClip2()
+{
+ QFETCH(bool, autoFillBackground);
+ QFETCH(bool, usePaintEvent);
+ QFETCH(QColor, expectedColor);
+
+ QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
+
+ class MyWidget : public QWidget
+ {
+ public:
+ bool usePaintEvent;
+ void paintEvent(QPaintEvent *)
+ {
+ if (usePaintEvent)
+ QPainter(this).fillRect(rect(), Qt::green);
+ }
+ };
+
+ MyWidget widget;
+ widget.usePaintEvent = usePaintEvent;
+ widget.setPalette(Qt::blue);
+ // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
+ // trick here since the widget is a top-level. The background is filled
+ // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
+ // is set. We therefore use the opaque attribute to turn off auto-fill.
+ if (!autoFillBackground)
+ widget.setAttribute(Qt::WA_OpaquePaintEvent);
+ widget.resize(100, 100);
+
+ QImage image(widget.size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::red).rgb());
+
+ QPaintEngine *paintEngine = image.paintEngine();
+ QVERIFY(paintEngine);
+
+ QRegion systemClip(QRegion(50, 0, 50, 10));
+ systemClip += QRegion(90, 10, 10, 40);
+ paintEngine->setSystemClip(systemClip);
+
+ // Render entire widget directly onto device.
+ widget.render(&image);
+
+#ifdef RENDER_DEBUG
+ image.save("systemclip_with_device.png");
+#endif
+ // All pixels within the system clip should now be
+ // the expectedColor, and the rest should be red.
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (systemClip.contains(QPoint(j, i)))
+ QCOMPARE(image.pixel(j, i), expectedColor.rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+
+ // Refill image with red.
+ image.fill(QColor(Qt::red).rgb());
+ paintEngine->setSystemClip(systemClip);
+
+ // Do the same with an untransformed painter.
+ QPainter painter(&image);
+ //Make sure we're using the same paint engine and has the right clip set.
+ QCOMPARE(painter.paintEngine(), paintEngine);
+ QCOMPARE(paintEngine->systemClip(), systemClip);
+
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ image.save("systemclip_with_untransformed_painter.png");
+#endif
+ // All pixels within the system clip should now be
+ // the expectedColor, and the rest should be red.
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (systemClip.contains(QPoint(j, i)))
+ QCOMPARE(image.pixel(j, i), expectedColor.rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+}
+
+void tst_QWidget::render_systemClip3_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<bool>("useSystemClip");
+
+ // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
+ QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
+ QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
+}
+
+// This test ensures that the current engine clip (systemClip + painter clip)
+// is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
+void tst_QWidget::render_systemClip3()
+{
+ QFETCH(QSize, size);
+ QFETCH(bool, useSystemClip);
+
+ // Calculate the inner/outer cross of the flag.
+ QRegion outerCross(0, 0, size.width(), size.height());
+ outerCross -= QRect(0, 0, 60, 60);
+ outerCross -= QRect(100, 0, size.width() - 100, 60);
+ outerCross -= QRect(0, 100, 60, 60);
+ outerCross -= QRect(100, 100, size.width() - 100, 60);
+
+ QRegion innerCross(0, 0, size.width(), size.height());
+ innerCross -= QRect(0, 0, 70, 70);
+ innerCross -= QRect(90, 0, size.width() - 90, 70);
+ innerCross -= QRect(0, 90, 70, 70);
+ innerCross -= QRect(90, 90, size.width() - 90, 70);
+
+ const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
+ const QRegion whiteArea(outerCross - innerCross);
+ const QRegion blueArea(innerCross);
+ QRegion systemClip;
+
+ // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
+ QImage flag(size, QImage::Format_ARGB32);
+ flag.fill(QColor(Qt::transparent).rgba());
+
+ if (useSystemClip) {
+ QPainterPath warClip(QPoint(size.width(), 0));
+ warClip.lineTo(size.width() - 110, 60);
+ warClip.lineTo(size.width(), 80);
+ warClip.lineTo(size.width() - 110, 100);
+ warClip.lineTo(size.width(), 160);
+ warClip.closeSubpath();
+ systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
+ flag.paintEngine()->setSystemClip(systemClip);
+ }
+
+ QPainter painter(&flag);
+ painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
+ painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
+
+ // Here's the widget that's supposed to draw the inner/outer cross of the flag.
+ // The outer cross (white) should be drawn when the background is auto-filled, and
+ // the inner cross (blue) should be drawn in the paintEvent.
+ class MyWidget : public QWidget
+ { public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ // Be evil and try to paint outside the outer cross. This should not be
+ // possible since the shared painter is clipped to the outer cross.
+ painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
+ painter.fillRect(rect(), Qt::green);
+ painter.setClipRegion(clip, Qt::ReplaceClip);
+ painter.fillRect(rect(), Qt::blue);
+ }
+ QRegion clip;
+ };
+
+ MyWidget widget;
+ widget.clip = innerCross;
+ widget.setFixedSize(size);
+ widget.setPalette(Qt::white);
+ widget.setAutoFillBackground(true);
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ flag.save("flag.png");
+#endif
+
+ // Let's make sure we got a Norwegian flag.
+ for (int i = 0; i < flag.height(); ++i) {
+ for (int j = 0; j < flag.width(); ++j) {
+ const QPoint pixel(j, i);
+ const QRgb pixelValue = flag.pixel(pixel);
+ if (useSystemClip && !systemClip.contains(pixel))
+ QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
+ else if (redArea.contains(pixel))
+ QCOMPARE(pixelValue, QColor(Qt::red).rgba());
+ else if (whiteArea.contains(pixel))
+ QCOMPARE(pixelValue, QColor(Qt::white).rgba());
+ else
+ QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
+ }
+ }
+}
+
+void tst_QWidget::render_task252837()
+{
+ QWidget widget;
+ widget.resize(200, 200);
+
+ QPixmap pixmap(widget.size());
+ QPainter painter(&pixmap);
+ // Please do not crash.
+ widget.render(&painter);
+}
+
+void tst_QWidget::render_worldTransform()
+{
+ class MyWidget : public QWidget
+ { public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ // Make sure world transform is identity.
+ QCOMPARE(painter.worldTransform(), QTransform());
+
+ // Make sure device transform is correct.
+ const QPoint widgetOffset = geometry().topLeft();
+ QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
+ expectedDeviceTransform.rotate(90);
+ expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
+ QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
+
+ // Set new world transform.
+ QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
+ newWorldTransform.rotate(90);
+ painter.setWorldTransform(newWorldTransform);
+ QCOMPARE(painter.worldTransform(), newWorldTransform);
+
+ // Again, check device transform.
+ expectedDeviceTransform.translate(10, 10);
+ expectedDeviceTransform.rotate(90);
+ QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
+
+ painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ }
+ };
+
+ MyWidget widget;
+ widget.setFixedSize(100, 100);
+ widget.setPalette(Qt::red);
+ widget.setAutoFillBackground(true);
+
+ MyWidget child;
+ child.setParent(&widget);
+ child.move(50, 50);
+ child.setFixedSize(50, 50);
+ child.setPalette(Qt::blue);
+ child.setAutoFillBackground(true);
+
+ QImage image(QSize(110, 110), QImage::Format_RGB32);
+ image.fill(QColor(Qt::black).rgb());
+
+ QPainter painter(&image);
+ painter.translate(105, 5);
+ painter.rotate(90);
+
+ const QTransform worldTransform = painter.worldTransform();
+ const QTransform deviceTransform = painter.deviceTransform();
+
+ // Render widgets onto image.
+ widget.render(&painter);
+#ifdef RENDER_DEBUG
+ image.save("render_worldTransform_image.png");
+#endif
+
+ // Ensure the transforms are unchanged after render.
+ QCOMPARE(painter.worldTransform(), painter.worldTransform());
+ QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
+ painter.end();
+
+ // Paint expected image.
+ QImage expected(QSize(110, 110), QImage::Format_RGB32);
+ expected.fill(QColor(Qt::black).rgb());
+
+ QPainter expectedPainter(&expected);
+ expectedPainter.translate(105, 5);
+ expectedPainter.rotate(90);
+ expectedPainter.save();
+ expectedPainter.fillRect(widget.rect(),Qt::red);
+ expectedPainter.translate(10, 10);
+ expectedPainter.rotate(90);
+ expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ expectedPainter.restore();
+ expectedPainter.translate(50, 50);
+ expectedPainter.fillRect(child.rect(),Qt::blue);
+ expectedPainter.translate(10, 10);
+ expectedPainter.rotate(90);
+ expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ expectedPainter.end();
+
+#ifdef RENDER_DEBUG
+ expected.save("render_worldTransform_expected.png");
+#endif
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QWidget::setContentsMargins()
+{
+ QLabel label("why does it always rain on me?");
+ QSize oldSize = label.sizeHint();
+ label.setFrameStyle(QFrame::Sunken | QFrame::Box);
+ QSize newSize = label.sizeHint();
+ QVERIFY(oldSize != newSize);
+
+ QLabel label2("why does it always rain on me?");
+ label2.show();
+ label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
+ QCOMPARE(newSize, label2.sizeHint());
+
+ QLabel label3("why does it always rain on me?");
+ label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
+ QCOMPARE(newSize, label3.sizeHint());
+}
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::moveWindowInShowEvent_data()
+{
+ QTest::addColumn<QPoint>("initial");
+ QTest::addColumn<QPoint>("position");
+
+ QPoint p = QApplication::desktop()->availableGeometry().topLeft();
+
+ QTest::newRow("1") << p << (p + QPoint(10, 10));
+ QTest::newRow("2") << (p + QPoint(10,10)) << p;
+}
+
+void tst_QWidget::moveWindowInShowEvent()
+{
+ QFETCH(QPoint, initial);
+ QFETCH(QPoint, position);
+
+ class MoveWindowInShowEventWidget : public QWidget
+ {
+ public:
+ QPoint position;
+ void showEvent(QShowEvent *)
+ {
+ move(position);
+ }
+ };
+
+ MoveWindowInShowEventWidget widget;
+ widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
+ // move to this position in showEvent()
+ widget.position = position;
+
+ // put the widget in it's starting position
+ widget.move(initial);
+ QCOMPARE(widget.pos(), initial);
+
+ // show it
+ widget.show();
+ #ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+ #endif
+ QTest::qWait(100);
+ // it should have moved
+ QCOMPARE(widget.pos(), position);
+}
+#endif
+
+void tst_QWidget::repaintWhenChildDeleted()
+{
+#ifdef Q_WS_WIN
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
+ QTest::qWait(1000);
+ }
+#endif
+ ColorWidget w(0, Qt::red);
+#if !defined(Q_OS_WINCE)
+ QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
+ startPoint.rx() += 50;
+ startPoint.ry() += 50;
+ w.setGeometry(QRect(startPoint, QSize(100, 100)));
+#else
+ w.setGeometry(60, 60, 110, 110);
+#endif
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+ QTRY_COMPARE(w.r, QRegion(w.rect()));
+ w.r = QRegion();
+
+ {
+ const QPoint tlwOffset = w.geometry().topLeft();
+ ColorWidget child(&w, Qt::blue);
+ child.setGeometry(10, 10, 10, 10);
+ child.show();
+ QTest::qWait(10);
+ QTRY_COMPARE(child.r, QRegion(child.rect()));
+ w.r = QRegion();
+ }
+
+ QTest::qWait(10);
+ QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
+}
+
+// task 175114
+void tst_QWidget::hideOpaqueChildWhileHidden()
+{
+ ColorWidget w(0, Qt::red);
+#if !defined(Q_OS_WINCE)
+ QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
+ startPoint.rx() += 50;
+ startPoint.ry() += 50;
+ w.setGeometry(QRect(startPoint, QSize(100, 100)));
+#else
+ w.setGeometry(60, 60, 110, 110);
+#endif
+
+ ColorWidget child(&w, Qt::blue);
+ child.setGeometry(10, 10, 80, 80);
+
+ ColorWidget child2(&child, Qt::white);
+ child2.setGeometry(10, 10, 60, 60);
+
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+ QTRY_COMPARE(child2.r, QRegion(child2.rect()));
+ child.r = QRegion();
+ child2.r = QRegion();
+ w.r = QRegion();
+
+ child.hide();
+ child2.hide();
+ QTest::qWait(100);
+
+ QCOMPARE(w.r, QRegion(child.geometry()));
+
+ child.show();
+ QTest::qWait(100);
+ QCOMPARE(child.r, QRegion(child.rect()));
+ QCOMPARE(child2.r, QRegion());
+}
+
+// This test doesn't make sense without support for showMinimized().
+#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
+void tst_QWidget::updateWhileMinimized()
+{
+ UpdateWidget widget;
+ // Filter out activation change and focus events to avoid update() calls in QWidget.
+ widget.updateOnActivationChangeAndFocusIn = false;
+ widget.reset();
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget.numPaintEvents > 0);
+ QTest::qWait(150);
+
+ // Minimize window.
+ widget.showMinimized();
+ QTest::qWait(110);
+
+ widget.reset();
+
+ // The widget is not visible on the screen (but isVisible() still returns true).
+ // Make sure update requests are discarded until the widget is shown again.
+ widget.update(0, 0, 50, 50);
+ QTest::qWait(10);
+ QCOMPARE(widget.numPaintEvents, 0);
+
+ // Restore window.
+ widget.showNormal();
+ QTest::qWait(30);
+ QTRY_COMPARE(widget.numPaintEvents, 1);
+ QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
+}
+#endif
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+class PaintOnScreenWidget: public QWidget
+{
+public:
+ PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
+ :QWidget(parent, f)
+ {
+ }
+#if defined(Q_WS_WIN)
+ // This is the only way to enable PaintOnScreen on Windows.
+ QPaintEngine * paintEngine () const {return 0;}
+#endif
+};
+
+void tst_QWidget::alienWidgets()
+{
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ QWidget parent;
+ QWidget child(&parent);
+ QWidget grandChild(&child);
+ QWidget greatGrandChild(&grandChild);
+ parent.show();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&parent);
+#endif
+
+ // Verify that the WA_WState_Created attribute is set
+ // and the top-level is the only native window.
+ QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(parent.internalWinId());
+
+ QVERIFY(child.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!child.internalWinId());
+
+ QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!grandChild.internalWinId());
+
+ QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!greatGrandChild.internalWinId());
+
+ // Enforce native windows all the way up in the parent hierarchy
+ // if not WA_DontCreateNativeAncestors is set.
+ grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
+ greatGrandChild.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(greatGrandChild.internalWinId());
+ QVERIFY(grandChild.internalWinId());
+ QVERIFY(!child.internalWinId());
+
+ {
+ // Ensure that hide() on an ancestor of a widget with
+ // Qt::WA_DontCreateNativeAncestors still gets unmapped
+ QWidget window;
+ QWidget widget(&window);
+ QWidget child(&widget);
+ child.setAttribute(Qt::WA_NativeWindow);
+ child.setAttribute(Qt::WA_DontCreateNativeAncestors);
+ window.show();
+ QVERIFY(child.testAttribute(Qt::WA_Mapped));
+ widget.hide();
+ QVERIFY(!child.testAttribute(Qt::WA_Mapped));
+ }
+
+ // Enforce a native window when calling QWidget::winId.
+ QVERIFY(child.winId());
+ QVERIFY(child.internalWinId());
+
+ // Check that paint on screen widgets (incl. children) are native.
+ PaintOnScreenWidget paintOnScreen(&parent);
+ QWidget paintOnScreenChild(&paintOnScreen);
+ paintOnScreen.show();
+ QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!paintOnScreen.internalWinId());
+ QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!paintOnScreenChild.internalWinId());
+
+ paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(paintOnScreen.internalWinId());
+ QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(paintOnScreenChild.internalWinId());
+
+ // Check that widgets with the Qt::MSWindowsOwnDC attribute set
+ // are native.
+ QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
+ msWindowsOwnDC.show();
+ QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(msWindowsOwnDC.internalWinId());
+
+ { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
+ QWidget widget(&parent);
+ widget.show();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!widget.internalWinId());
+#ifdef Q_WS_X11
+ widget.handle();
+#else
+ widget.getDC();
+#endif
+ QVERIFY(widget.internalWinId());
+ }
+
+#ifdef Q_WS_X11
+#ifndef QT_NO_XRENDER
+ { // Enforce a native window when calling QWidget::x11PictureHandle().
+ QWidget widget(&parent);
+ widget.show();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!widget.internalWinId());
+ widget.x11PictureHandle();
+ QVERIFY(widget.internalWinId());
+ }
+#endif
+
+ { // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
+ // on alien widgets (see task 194231).
+ QWidget dummy;
+ QVERIFY(dummy.winId());
+ QWidget widget(&dummy);
+ widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
+ QVERIFY(!widget.internalWinId());
+ }
+#endif
+
+
+ { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
+ QWidget topLevel;
+ QWidget child(&topLevel);
+ QWidget grandChild(&child);
+ PaintOnScreenWidget greatGrandChild(&grandChild);
+
+ greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(!child.internalWinId());
+ QVERIFY(!grandChild.internalWinId());
+ QVERIFY(!greatGrandChild.internalWinId());
+
+ topLevel.show();
+ QVERIFY(child.internalWinId());
+ QVERIFY(grandChild.internalWinId());
+ QVERIFY(greatGrandChild.internalWinId());
+ }
+
+ { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
+ QWidget topLevel;
+ QWidget *widget = new PaintOnScreenWidget(&topLevel);
+ widget->setAttribute(Qt::WA_PaintOnScreen);
+ QWidget *child = new QWidget;
+ QWidget *dummy = new QWidget(child);
+ QWidget *grandChild = new QWidget(child);
+ QWidget *dummy2 = new QWidget(grandChild);
+
+ child->setParent(widget);
+
+ QVERIFY(!topLevel.internalWinId());
+ QVERIFY(!child->internalWinId());
+ QVERIFY(!dummy->internalWinId());
+ QVERIFY(!grandChild->internalWinId());
+ QVERIFY(!dummy2->internalWinId());
+
+ topLevel.show();
+ QVERIFY(topLevel.internalWinId());
+ QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(child->internalWinId());
+ QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
+ QVERIFY(!dummy->internalWinId());
+ QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!grandChild->internalWinId());
+ QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!dummy2->internalWinId());
+ QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
+ }
+
+ { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
+ // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
+ QWidget window;
+ QWidget child(&window);
+
+ QWidget grandChild;
+ grandChild.setWindowTitle("This causes the widget to be created");
+
+ PaintOnScreenWidget paintOnScreenWidget;
+ paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
+ paintOnScreenWidget.setParent(&grandChild);
+
+ grandChild.setParent(&child);
+
+ window.show();
+
+ QVERIFY(window.internalWinId());
+ QVERIFY(child.internalWinId());
+ QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(grandChild.internalWinId());
+ QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(paintOnScreenWidget.internalWinId());
+ QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
+ }
+
+ { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
+ QWidget mainWindow;
+ QWidget *toolBar = new QWidget(&mainWindow);
+ QWidget *dockWidget = new QWidget(&mainWindow);
+ QWidget *centralWidget = new QWidget(&mainWindow);
+
+ QWidget *button = new QWidget(centralWidget);
+ QWidget *mdiArea = new QWidget(centralWidget);
+
+ QWidget *horizontalScroll = new QWidget(mdiArea);
+ QWidget *verticalScroll = new QWidget(mdiArea);
+ QWidget *viewport = new QWidget(mdiArea);
+
+ viewport->setAttribute(Qt::WA_NativeWindow);
+ mainWindow.show();
+
+ // Ensure that the viewport and its siblings are native:
+ QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
+
+ // Ensure that the mdi area and its siblings are native:
+ QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
+
+ // Ensure that the central widget and its siblings are native:
+ QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
+ }
+}
+#endif // Q_WS_WIN / Q_WS_X11
+
+class ASWidget : public QWidget
+{
+public:
+ ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
+ : QWidget(parent), mySizeHint(sizeHint)
+ {
+ setSizePolicy(sizePolicy);
+ if (layout) {
+ QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(hfwLayout);
+
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->setMargin(0);
+ vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
+ setLayout(vbox);
+ }
+ }
+
+ QSize sizeHint() const {
+ if (layout())
+ return layout()->totalSizeHint();
+ return mySizeHint;
+ }
+ int heightForWidth(int width) const {
+ if (sizePolicy().hasHeightForWidth()) {
+ return width * 2;
+ } else {
+ return -1;
+ }
+ }
+
+ QSize mySizeHint;
+};
+
+void tst_QWidget::adjustSize_data()
+{
+ const int MagicW = 200;
+ const int MagicH = 100;
+
+ QTest::addColumn<QSize>("sizeHint");
+ QTest::addColumn<int>("hPolicy");
+ QTest::addColumn<int>("vPolicy");
+ QTest::addColumn<bool>("hfwSP");
+ QTest::addColumn<bool>("layout");
+ QTest::addColumn<bool>("hfwLayout");
+ QTest::addColumn<bool>("haveParent");
+ QTest::addColumn<QSize>("expectedSize");
+
+ QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << false << QSize(5, qMax(6, MagicH));
+ QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << false << QSize(5, qMax(10, MagicH));
+ QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << false << QSize(35, 26);
+ QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << false << QSize(35, 70);
+ QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << false << QSize(100000, 100000);
+ QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << false << QSize(100000, 100000);
+ QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << false << QSize(100000, 100000);
+ QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << false << QSize(100000, 100000);
+ QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
+ << true << false << false << false << QSize(qMax(5, MagicW), 10);
+
+ QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << true << QSize(5, 6);
+ QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
+ QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << true << QSize(35, 26);
+ QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << true << QSize(35, 70);
+ QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << true << QSize(40001, 30001);
+ QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
+ QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << true << QSize(40001 + 30, 30001 + 20);
+ QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << true << QSize(40001 + 30, 80002 + 60);
+ QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
+ << true << false << false << true << QSize(5, 6);
+}
+
+void tst_QWidget::adjustSize()
+{
+ QFETCH(QSize, sizeHint);
+ QFETCH(int, hPolicy);
+ QFETCH(int, vPolicy);
+ QFETCH(bool, hfwSP);
+ QFETCH(bool, layout);
+ QFETCH(bool, hfwLayout);
+ QFETCH(bool, haveParent);
+ QFETCH(QSize, expectedSize);
+
+ QWidget *parent = new QWidget;
+
+ QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
+ sp.setHeightForWidth(hfwSP);
+
+ QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0);
+ child->resize(123, 456);
+ child->adjustSize();
+ if (expectedSize == QSize(100000, 100000)) {
+ QVERIFY(child->size().width() < sizeHint.width());
+ QVERIFY(child->size().height() < sizeHint.height());
+ } else {
+#if defined (Q_OS_WINCE)
+ if (!haveParent) {
+ const QRect& desktopRect = qApp->desktop()->availableGeometry();
+ expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
+ expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
+ }
+#endif
+ QCOMPARE(child->size(), expectedSize);
+ }
+
+ delete parent;
+}
+
+class TestLayout : public QVBoxLayout
+{
+ Q_OBJECT
+public:
+ TestLayout(QWidget *w = 0) : QVBoxLayout(w)
+ {
+ invalidated = false;
+ }
+
+ void invalidate()
+ {
+ invalidated = true;
+ }
+
+ bool invalidated;
+};
+
+void tst_QWidget::updateGeometry_data()
+{
+ QTest::addColumn<QSize>("minSize");
+ QTest::addColumn<bool>("shouldInvalidate");
+ QTest::addColumn<QSize>("maxSize");
+ QTest::addColumn<bool>("shouldInvalidate2");
+ QTest::addColumn<int>("verticalSizePolicy");
+ QTest::addColumn<bool>("shouldInvalidate3");
+ QTest::addColumn<bool>("setVisible");
+ QTest::addColumn<bool>("shouldInvalidate4");
+
+ QTest::newRow("setMinimumSize")
+ << QSize(100, 100) << true
+ << QSize() << false
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMaximumSize")
+ << QSize() << false
+ << QSize(100, 100) << true
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMinimumSize, then maximumSize to a different size")
+ << QSize(100, 100) << true
+ << QSize(300, 300) << true
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMinimumSize, then maximumSize to the same size")
+ << QSize(100, 100) << true
+ << QSize(100, 100) << true
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
+ << QSize(100, 100) << true
+ << QSize(100, 100) << true
+ << int(QSizePolicy::Preferred) << false
+ << false << true;
+ QTest::newRow("Change sizePolicy")
+ << QSize() << false
+ << QSize() << false
+ << int(QSizePolicy::Minimum) << true
+ << true << false;
+
+}
+
+void tst_QWidget::updateGeometry()
+{
+ QFETCH(QSize, minSize);
+ QFETCH(bool, shouldInvalidate);
+ QFETCH(QSize, maxSize);
+ QFETCH(bool, shouldInvalidate2);
+ QFETCH(int, verticalSizePolicy);
+ QFETCH(bool, shouldInvalidate3);
+ QFETCH(bool, setVisible);
+ QFETCH(bool, shouldInvalidate4);
+ QWidget parent;
+ parent.resize(200, 200);
+ TestLayout *lout = new TestLayout();
+ parent.setLayout(lout);
+ QWidget *child = new QWidget(&parent);
+ lout->addWidget(child);
+ parent.show();
+ QApplication::processEvents();
+
+ lout->invalidated = false;
+ if (minSize.isValid())
+ child->setMinimumSize(minSize);
+ QCOMPARE(lout->invalidated, shouldInvalidate);
+
+ lout->invalidated = false;
+ if (maxSize.isValid())
+ child->setMaximumSize(maxSize);
+ QCOMPARE(lout->invalidated, shouldInvalidate2);
+
+ lout->invalidated = false;
+ child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
+ if (shouldInvalidate3)
+ QCOMPARE(lout->invalidated, true);
+
+ lout->invalidated = false;
+ if (!setVisible)
+ child->setVisible(false);
+ QCOMPARE(lout->invalidated, shouldInvalidate4);
+}
+
+void tst_QWidget::sendUpdateRequestImmediately()
+{
+#ifdef Q_WS_MAC
+ if (!QApplicationPrivate::graphicsSystem())
+ QSKIP("We only send update requests on the Mac when passing -graphicssystem", SkipAll);
+#endif
+
+ UpdateWidget updateWidget;
+ updateWidget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&updateWidget);
+#endif
+
+ qApp->processEvents();
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+ updateWidget.reset();
+
+ QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
+ updateWidget.repaint();
+ QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
+}
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::doubleRepaint()
+{
+#if defined(Q_WS_MAC)
+ if (!macHasAccessToWindowsServer())
+ QSKIP("Not having window server access causes the wrong number of repaints to be issues", SkipAll);
+#endif
+ UpdateWidget widget;
+ widget.setFocusPolicy(Qt::StrongFocus);
+ // Filter out activation change and focus events to avoid update() calls in QWidget.
+ widget.updateOnActivationChangeAndFocusIn = false;
+
+ // Show: 1 repaint
+ int expectedRepaints = 1;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
+ widget.numPaintEvents = 0;
+
+ // Minmize: Should not trigger a repaint.
+ widget.showMinimized();
+ QTest::qWait(10);
+ QCOMPARE(widget.numPaintEvents, 0);
+ widget.numPaintEvents = 0;
+
+ // Restore: Should not trigger a repaint.
+ widget.showNormal();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QCOMPARE(widget.numPaintEvents, 0);
+}
+#endif
+
+#ifndef Q_WS_MAC
+// This test only makes sense on the Mac when passing -graphicssystem.
+void tst_QWidget::resizeInPaintEvent()
+{
+ QWidget window;
+ UpdateWidget widget(&window);
+ window.show();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(widget.numPaintEvents > 0);
+
+ widget.reset();
+ QCOMPARE(widget.numPaintEvents, 0);
+
+ widget.resizeInPaintEvent = true;
+ // This will call resize in the paintEvent, which in turn will call
+ // invalidateBuffer() and a new update request should be posted.
+ widget.repaint();
+ QCOMPARE(widget.numPaintEvents, 1);
+ widget.numPaintEvents = 0;
+
+ QTest::qWait(10);
+ // Make sure the resize triggers another update.
+ QTRY_COMPARE(widget.numPaintEvents, 1);
+}
+
+void tst_QWidget::opaqueChildren()
+{
+ QWidget widget;
+ widget.resize(200, 200);
+
+ QWidget child(&widget);
+ child.setGeometry(-700, -700, 200, 200);
+
+ QWidget grandChild(&child);
+ grandChild.resize(200, 200);
+
+ QWidget greatGrandChild(&grandChild);
+ greatGrandChild.setGeometry(50, 50, 200, 200);
+ greatGrandChild.setPalette(Qt::red);
+ greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
+
+ widget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QTest::qWait(100);
+
+ // Child, grandChild and greatGrandChild are outside the ancestor clip.
+ QRegion expectedOpaqueRegion(50, 50, 150, 150);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
+
+ // Now they are all inside the ancestor clip.
+ child.setGeometry(50, 50, 150, 150);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
+
+ // Set mask on greatGrandChild.
+ const QRegion mask(10, 10, 50, 50);
+ greatGrandChild.setMask(mask);
+ expectedOpaqueRegion &= mask.translated(50, 50);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
+
+ // Make greatGrandChild "transparent".
+ greatGrandChild.setAutoFillBackground(false);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
+}
+#endif
+
+
+class MaskSetWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MaskSetWidget(QWidget* p =0)
+ : QWidget(p) {}
+
+ void paintEvent(QPaintEvent* event) {
+ QPainter p(this);
+
+ paintedRegion += event->region();
+ foreach(QRect r, event->region().rects())
+ p.fillRect(r, Qt::red);
+ }
+
+ void resizeEvent(QResizeEvent*) {
+ setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
+ }
+
+ QRegion paintedRegion;
+
+public slots:
+ void resizeDown() {
+ setGeometry(QRect(0, 50, 50, 50));
+ }
+
+ void resizeUp() {
+ setGeometry(QRect(0, 50, 150, 50));
+ }
+
+};
+
+void tst_QWidget::setMaskInResizeEvent()
+{
+ UpdateWidget w;
+ w.reset();
+ w.resize(200, 200);
+ w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ w.raise();
+
+ MaskSetWidget testWidget(&w);
+ testWidget.setGeometry(0, 0, 100, 100);
+ testWidget.setMask(QRegion(QRect(0,0,100,10)));
+ testWidget.show();
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(30);
+ QTRY_VERIFY(w.numPaintEvents > 0);
+
+ w.reset();
+ testWidget.paintedRegion = QRegion();
+ QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
+ QTest::qWait(100);
+
+ QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
+ expectedParentUpdate += testWidget.geometry(); // New testWidget area.
+ QCOMPARE(w.paintedRegion, expectedParentUpdate);
+ QCOMPARE(testWidget.paintedRegion, testWidget.mask());
+
+ testWidget.paintedRegion = QRegion();
+ // Now resize the widget again, but in the oposite direction
+ QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
+ QTest::qWait(100);
+
+ QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
+}
+
+class MoveInResizeWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MoveInResizeWidget(QWidget* p = 0)
+ : QWidget(p)
+ {
+ setWindowFlags(Qt::FramelessWindowHint);
+ }
+
+ void resizeEvent(QResizeEvent*) {
+
+ move(QPoint(100,100));
+
+ static bool firstTime = true;
+ if (firstTime)
+ QTimer::singleShot(250, this, SLOT(resizeMe()));
+
+ firstTime = false;
+ }
+
+public slots:
+ void resizeMe() {
+ resize(100, 100);
+ }
+};
+
+void tst_QWidget::moveInResizeEvent()
+{
+ MoveInResizeWidget testWidget;
+ testWidget.setGeometry(50, 50, 200, 200);
+ testWidget.show();
+ QTest::qWaitForWindowShown(&testWidget);
+ QTest::qWait(300);
+
+ QRect expectedGeometry(100,100, 100, 100);
+ QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
+}
+
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+void tst_QWidget::immediateRepaintAfterShow()
+{
+ UpdateWidget widget;
+ widget.show();
+ qApp->processEvents();
+ // On X11 in particular, we are now waiting for a MapNotify event before
+ // syncing the backing store. However, if someone request a repaint()
+ // we must repaint immediately regardless of the current state.
+ widget.numPaintEvents = 0;
+ widget.repaint();
+ QCOMPARE(widget.numPaintEvents, 1);
+}
+
+void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
+{
+ QWidget *widget = new UpdateWidget;
+ widget->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(widget);
+#endif
+ QTest::qWait(200);
+
+ static_cast<UpdateWidget *>(widget)->numPaintEvents = 0;
+
+ // Marks the area covered by the widget as dirty in the backing store and
+ // posts an UpdateRequest event.
+ qt_widget_private(widget)->invalidateBuffer(widget->rect());
+ QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 0);
+
+ // The entire widget is already dirty, but this time we want to update immediately
+ // by calling repaint(), and thus we have to repaint the widget and not wait for
+ // the UpdateRequest to be sent when we get back to the event loop.
+ widget->repaint();
+ QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 1);
+
+ delete widget;
+}
+#endif
+
+void tst_QWidget::effectiveWinId()
+{
+ QWidget parent;
+ QWidget child(&parent);
+
+ // Shouldn't crash.
+ QVERIFY(!parent.effectiveWinId());
+ QVERIFY(!child.effectiveWinId());
+
+ parent.show();
+
+ QVERIFY(parent.effectiveWinId());
+ QVERIFY(child.effectiveWinId());
+}
+
+void tst_QWidget::effectiveWinId2()
+{
+ QWidget parent;
+
+ class MyWidget : public QWidget {
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::WinIdChange) {
+ // Shouldn't crash.
+ effectiveWinId();
+ }
+
+ return QWidget::event(e);
+ }
+ };
+
+ MyWidget child;
+ child.setParent(&parent);
+ parent.show();
+
+ child.setParent(0);
+ child.setParent(&parent);
+}
+
+class CustomWidget : public QWidget
+{
+public:
+ mutable int metricCallCount;
+
+ CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
+
+ virtual int metric(PaintDeviceMetric metric) const {
+ ++metricCallCount;
+ return QWidget::metric(metric);
+ }
+};
+
+void tst_QWidget::customDpi()
+{
+ QWidget *topLevel = new QWidget;
+ CustomWidget *custom = new CustomWidget(topLevel);
+ QWidget *child = new QWidget(custom);
+
+ custom->metricCallCount = 0;
+ topLevel->logicalDpiX();
+ QCOMPARE(custom->metricCallCount, 0);
+ custom->logicalDpiX();
+ QCOMPARE(custom->metricCallCount, 1);
+ child->logicalDpiX();
+ QCOMPARE(custom->metricCallCount, 2);
+
+ delete topLevel;
+}
+
+void tst_QWidget::customDpiProperty()
+{
+ QWidget *topLevel = new QWidget;
+ QWidget *middle = new CustomWidget(topLevel);
+ QWidget *child = new QWidget(middle);
+
+ const int initialDpiX = topLevel->logicalDpiX();
+ const int initialDpiY = topLevel->logicalDpiY();
+
+ middle->setProperty("_q_customDpiX", 300);
+ middle->setProperty("_q_customDpiY", 400);
+
+ QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
+ QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
+
+ QCOMPARE(middle->logicalDpiX(), 300);
+ QCOMPARE(middle->logicalDpiY(), 400);
+
+ QCOMPARE(child->logicalDpiX(), 300);
+ QCOMPARE(child->logicalDpiY(), 400);
+
+ middle->setProperty("_q_customDpiX", QVariant());
+ middle->setProperty("_q_customDpiY", QVariant());
+
+ QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
+ QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
+
+ QCOMPARE(middle->logicalDpiX(), initialDpiX);
+ QCOMPARE(middle->logicalDpiY(), initialDpiY);
+
+ QCOMPARE(child->logicalDpiX(), initialDpiX);
+ QCOMPARE(child->logicalDpiY(), initialDpiY);
+
+ delete topLevel;
+}
+
+void tst_QWidget::quitOnCloseAttribute()
+{
+ QWidget w;
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
+ w.setAttribute(Qt::WA_QuitOnClose, false);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::Tool);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::Popup);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::ToolTip);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::SplashScreen);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::SubWindow);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::Dialog);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
+ w.show();
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
+ w.setWindowFlags(Qt::Tool);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+}
+
+void tst_QWidget::moveRect()
+{
+ QWidget widget;
+ widget.setUpdatesEnabled(false);
+ QWidget child(&widget);
+ child.setUpdatesEnabled(false);
+ child.setAttribute(Qt::WA_OpaquePaintEvent);
+ widget.show();
+ QTest::qWait(200);
+ child.move(10, 10); // Don't crash.
+}
+
+#ifdef Q_WS_WIN
+class GDIWidget : public QDialog
+{
+public:
+ GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); }
+ QPaintEngine *paintEngine() const { return 0; }
+
+
+ void paintEvent(QPaintEvent *) {
+ HDC hdc = getDC();
+ SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
+ Rectangle(hdc, 0, 0, 10, 10);
+
+ releaseDC(hdc);
+
+ QImage im = QPixmap::grabWindow(winId(), 0, 0, width(), height()).toImage();
+ color = im.pixel(1, 1);
+
+ accept();
+ }
+
+ QSize sizeHint() const {
+ return QSize(400, 300);
+ }
+
+ QColor color;
+};
+
+void tst_QWidget::gdiPainting()
+{
+ GDIWidget w;
+ w.exec();
+
+ QCOMPARE(w.color, QColor(255, 0, 0));
+
+}
+
+void tst_QWidget::paintOnScreenPossible()
+{
+ QWidget w1;
+ w1.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
+
+ GDIWidget w2;
+ w2.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
+}
+#endif
+
+void tst_QWidget::reparentStaticWidget()
+{
+ QWidget window1;
+
+ QWidget *child = new QWidget(&window1);
+ child->setPalette(Qt::red);
+ child->setAutoFillBackground(true);
+ child->setAttribute(Qt::WA_StaticContents);
+ child->resize(100, 100);
+
+ QWidget *grandChild = new QWidget(child);
+ grandChild->setPalette(Qt::blue);
+ grandChild->setAutoFillBackground(true);
+ grandChild->resize(50, 50);
+ grandChild->setAttribute(Qt::WA_StaticContents);
+ window1.show();
+ QTest::qWaitForWindowShown(&window1);
+
+ QWidget window2;
+ window2.show();
+ QTest::qWaitForWindowShown(&window2);
+ QTest::qWait(20);
+
+ // Reparent into another top-level.
+ child->setParent(&window2);
+ child->show();
+
+ // Please don't crash.
+ window1.resize(window1.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+ // Make sure we move all static children even though
+ // the reparented widget itself is non-static.
+ child->setAttribute(Qt::WA_StaticContents, false);
+ child->setParent(&window1);
+ child->show();
+
+ // Please don't crash.
+ window2.resize(window2.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+ child->setParent(0);
+ child->show();
+ QTest::qWait(20);
+
+ // Please don't crash.
+ child->resize(child->size() + QSize(2, 2));
+ window2.resize(window2.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+ QWidget *siblingOfGrandChild = new QWidget(child);
+ siblingOfGrandChild->show();
+ QTest::qWait(20);
+
+ // Nothing should happen when reparenting within the same top-level.
+ grandChild->setParent(siblingOfGrandChild);
+ grandChild->show();
+ QTest::qWait(20);
+
+ QWidget paintOnScreen;
+ paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
+ paintOnScreen.show();
+ QTest::qWaitForWindowShown(&paintOnScreen);
+ QTest::qWait(20);
+
+ child->setParent(&paintOnScreen);
+ child->show();
+ QTest::qWait(20);
+
+ // Please don't crash.
+ paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+}
+
+void tst_QWidget::QTBUG6883_reparentStaticWidget2()
+{
+ QMainWindow mw;
+ QDockWidget *one = new QDockWidget("one", &mw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
+
+ QWidget *child = new QWidget();
+ child->setPalette(Qt::red);
+ child->setAutoFillBackground(true);
+ child->setAttribute(Qt::WA_StaticContents);
+ child->resize(100, 100);
+ one->setWidget(child);
+
+ QToolBar *mainTools = mw.addToolBar("Main Tools");
+ mainTools->addWidget(new QLineEdit);
+
+ mw.show();
+ QTest::qWaitForWindowShown(&mw);
+
+ one->setFloating(true);
+ QTest::qWait(20);
+ //do not crash
+}
+
+#ifdef Q_WS_QWS
+void tst_QWidget::updateOutsideSurfaceClip()
+{
+ UpdateWidget widget;
+ widget.setWindowFlags(Qt::FramelessWindowHint);
+ widget.resize(100, 100);
+ widget.raise();
+ widget.show();
+ QTest::qWait(200);
+ widget.reset();
+
+ // Move widget partially outside buffer and change the surface clip.
+ widget.move(-50, 0);
+ QTest::qWait(100);
+
+ // Update region is outside the surface clip and should not trigger a repaint.
+ widget.update(0, 0, 20, 20);
+ QTest::qWait(100);
+ QCOMPARE(widget.numPaintEvents, 0);
+
+ // Now, move the widget back so that the update region is inside the clip
+ // and make sure we get a repaint of the dirty area.
+ widget.move(0, 0);
+ QTest::qWait(100);
+ QCOMPARE(widget.numPaintEvents, 1);
+ QCOMPARE(widget.paintedRegion, QRegion(0, 0, 20, 20));
+}
+#endif
+class ColorRedWidget : public QWidget
+{
+public:
+ ColorRedWidget(QWidget *parent = 0)
+ : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
+ {
+ }
+
+ void paintEvent(QPaintEvent *) {
+ QPainter p(this);
+ p.fillRect(rect(),Qt::red);
+ }
+};
+
+void tst_QWidget::translucentWidget()
+{
+ QPixmap pm(16,16);
+ pm.fill(Qt::red);
+ ColorRedWidget label;
+ label.setFixedSize(16,16);
+ label.setAttribute(Qt::WA_TranslucentBackground);
+ label.move(qApp->desktop()->availableGeometry().topLeft());
+ label.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&label);
+#endif
+ QTest::qWait(200);
+
+ QPixmap widgetSnapshot;
+
+#ifdef Q_WS_WIN
+ QWidget *desktopWidget = QApplication::desktop()->screen(0);
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
+ widgetSnapshot = QPixmap::grabWindow(desktopWidget->winId(), 0,0, label.width(), label.height());
+ else
+#endif
+ widgetSnapshot = QPixmap::grabWindow(label.winId());
+ QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
+ QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(actual.size(),expected.size());
+ QCOMPARE(actual,expected);
+}
+
+class MaskResizeTestWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MaskResizeTestWidget(QWidget* p =0)
+ : QWidget(p) {
+ setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
+ }
+
+ void paintEvent(QPaintEvent* event) {
+ QPainter p(this);
+
+ paintedRegion += event->region();
+ foreach(QRect r, event->region().rects())
+ p.fillRect(r, Qt::red);
+ }
+
+ QRegion paintedRegion;
+
+public slots:
+ void enlargeMask() {
+ QRegion newMask(QRect(0, 0, 150, 150).normalized());
+ setMask(newMask);
+ }
+
+ void shrinkMask() {
+ QRegion newMask(QRect(0, 0, 50, 50).normalized());
+ setMask(newMask);
+ }
+
+};
+
+void tst_QWidget::setClearAndResizeMask()
+{
+ UpdateWidget topLevel;
+ topLevel.resize(150, 150);
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTRY_VERIFY(topLevel.numPaintEvents > 0);
+ topLevel.reset();
+
+ // Mask top-level widget
+ const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
+ topLevel.setMask(topLevelMask);
+ QCOMPARE(topLevel.mask(), topLevelMask);
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms.
+ // and ensure that the top-level doesn't get any update.
+ QCOMPARE(topLevel.numPaintEvents, 0);
+#endif
+
+ topLevel.reset();
+
+ // Clear top-level mask
+ topLevel.clearMask();
+ QCOMPARE(topLevel.mask(), QRegion());
+ QTest::qWait(10);
+ QRegion outsideOldMask(topLevel.rect());
+ outsideOldMask -= topLevelMask;
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms.
+ // and ensure that the top-level gets an update for the area outside the old mask.
+ QTRY_VERIFY(topLevel.numPaintEvents > 0);
+ QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
+#endif
+
+ UpdateWidget child(&topLevel);
+ child.setAutoFillBackground(true); // NB! Opaque child.
+ child.setPalette(Qt::red);
+ child.resize(100, 100);
+ child.show();
+ QTest::qWait(10);
+
+ child.reset();
+ topLevel.reset();
+
+ // Mask child widget with a mask that is smaller than the rect
+ const QRegion childMask(0, 0, 50, 50);
+ child.setMask(childMask);
+ QTRY_COMPARE(child.mask(), childMask);
+ QTest::qWait(50);
+ // and ensure that the child widget doesn't get any update.
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QCOMPARE(child.numPaintEvents, 1);
+ else
+#endif
+ QCOMPARE(child.numPaintEvents, 0);
+ // and the parent widget gets an update for the newly exposed area.
+ QTRY_COMPARE(topLevel.numPaintEvents, 1);
+ QRegion expectedParentExpose(child.rect());
+ expectedParentExpose -= childMask;
+ QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
+
+ child.reset();
+ topLevel.reset();
+
+ // Clear child widget mask
+ child.clearMask();
+ QTRY_COMPARE(child.mask(), QRegion());
+ QTest::qWait(10);
+ // and ensure that that the child widget gets an update for the area outside the old mask.
+ QTRY_COMPARE(child.numPaintEvents, 1);
+ outsideOldMask = child.rect();
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (!child.internalWinId())
+#endif
+ outsideOldMask -= childMask;
+ QCOMPARE(child.paintedRegion, outsideOldMask);
+ // and the parent widget doesn't get any update.
+ QCOMPARE(topLevel.numPaintEvents, 0);
+
+ child.reset();
+ topLevel.reset();
+
+ // Mask child widget with a mask that is bigger than the rect
+ child.setMask(QRegion(0, 0, 1000, 1000));
+ QTest::qWait(100);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_COMPARE(child.numPaintEvents, 1);
+ else
+#endif
+ // and ensure that we don't get any updates at all.
+ QTRY_COMPARE(child.numPaintEvents, 0);
+ QCOMPARE(topLevel.numPaintEvents, 0);
+
+ // ...and the same applies when clearing the mask.
+ child.clearMask();
+ QTest::qWait(100);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_VERIFY(child.numPaintEvents > 0);
+ else
+#endif
+ QCOMPARE(child.numPaintEvents, 0);
+ QCOMPARE(topLevel.numPaintEvents, 0);
+
+ QWidget resizeParent;
+ MaskResizeTestWidget resizeChild(&resizeParent);
+
+ resizeParent.resize(300,300);
+ resizeParent.raise();
+ resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
+ resizeChild.setGeometry(50,50,200,200);
+ QPalette pal = resizeParent.palette();
+ pal.setColor(QPalette::Window, QColor(Qt::white));
+ resizeParent.setPalette(pal);
+
+ resizeParent.show();
+ QTest::qWaitForWindowShown(&resizeParent);
+ // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
+ resizeParent.setFixedSize(resizeParent.size());
+ resizeChild.show();
+ QTest::qWait(100);
+ resizeChild.paintedRegion = QRegion();
+
+ QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
+ QTest::qWait(200);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
+ else
+#endif
+ QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
+
+ resizeChild.paintedRegion = QRegion();
+ const QRegion oldMask = resizeChild.mask();
+ QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
+ QTest::qWait(100);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
+ else
+#endif
+ QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
+}
+
+void tst_QWidget::maskedUpdate()
+{
+ UpdateWidget topLevel;
+ topLevel.resize(200, 200);
+ const QRegion topLevelMask(50, 50, 70, 70);
+ topLevel.setMask(topLevelMask);
+
+ UpdateWidget child(&topLevel);
+ child.setGeometry(20, 20, 180, 180);
+ const QRegion childMask(60, 60, 30, 30);
+ child.setMask(childMask);
+
+ UpdateWidget grandChild(&child);
+ grandChild.setGeometry(50, 50, 100, 100);
+ const QRegion grandChildMask(20, 20, 10, 10);
+ grandChild.setMask(grandChildMask);
+
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTRY_VERIFY(topLevel.numPaintEvents > 0);
+
+
+#define RESET_WIDGETS \
+ topLevel.reset(); \
+ child.reset(); \
+ grandChild.reset();
+
+#define CLEAR_MASK(widget) \
+ widget.clearMask(); \
+ QTest::qWait(100); \
+ RESET_WIDGETS;
+
+ // All widgets are transparent at this point, so any call to update() will result
+ // in composition, i.e. the update propagates to ancestors and children.
+
+ // TopLevel update.
+ RESET_WIDGETS;
+ topLevel.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
+ QTRY_COMPARE(child.paintedRegion, childMask);
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ // Child update.
+ RESET_WIDGETS;
+ child.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
+ QTRY_COMPARE(child.paintedRegion, childMask);
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ // GrandChild update.
+ RESET_WIDGETS;
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
+ QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
+ child.setAttribute(Qt::WA_OpaquePaintEvent);
+ grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
+
+ // All widgets are now opaque, which means no composition, i.e.
+ // the update does not propate to ancestors and children.
+
+ // TopLevel update.
+ RESET_WIDGETS;
+ topLevel.update();
+ QTest::qWait(10);
+
+ QRegion expectedTopLevelUpdate = topLevelMask;
+ expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
+ QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion());
+
+ // Child update.
+ RESET_WIDGETS;
+ child.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QRegion expectedChildUpdate = childMask;
+ expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
+ QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion());
+
+ // GrandChild update.
+ RESET_WIDGETS;
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ // GrandChild update.
+ CLEAR_MASK(grandChild);
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QRegion expectedGrandChildUpdate = grandChild.rect();
+ // Clip with parent's mask.
+ expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
+ QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
+
+ // GrandChild update.
+ CLEAR_MASK(child);
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ expectedGrandChildUpdate = grandChild.rect();
+ // Clip with parent's mask.
+ expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
+ QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
+
+ // Child update.
+ RESET_WIDGETS;
+ child.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ expectedChildUpdate = child.rect();
+ // Clip with parent's mask.
+ expectedChildUpdate &= topLevelMask.translated(-child.pos());
+ expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
+ QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion());
+
+ // GrandChild update.
+ CLEAR_MASK(topLevel);
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
+}
+
+// Windows Mobile has no proper cursor support, so skip this test on that platform.
+#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE_WM)) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+void tst_QWidget::syntheticEnterLeave()
+{
+ class MyWidget : public QWidget
+ {
+ public:
+ MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
+ void enterEvent(QEvent *) { ++numEnterEvents; }
+ void leaveEvent(QEvent *) { ++numLeaveEvents; }
+ int numEnterEvents;
+ int numLeaveEvents;
+ };
+
+ QCursor::setPos(QPoint(0,0));
+
+ MyWidget window;
+ window.setWindowFlags(Qt::WindowStaysOnTopHint);
+ window.resize(200, 200);
+
+ MyWidget *child1 = new MyWidget(&window);
+ child1->setPalette(Qt::blue);
+ child1->setAutoFillBackground(true);
+ child1->resize(200, 200);
+ child1->setCursor(Qt::OpenHandCursor);
+
+ MyWidget *child2 = new MyWidget(&window);
+ child2->resize(200, 200);
+
+ MyWidget *grandChild = new MyWidget(child2);
+ grandChild->setPalette(Qt::red);
+ grandChild->setAutoFillBackground(true);
+ grandChild->resize(200, 200);
+ grandChild->setCursor(Qt::WaitCursor);
+
+ window.show();
+ window.raise();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&window);
+#endif
+ QTest::qWait(300);
+
+#define RESET_EVENT_COUNTS \
+ window.numEnterEvents = 0; \
+ window.numLeaveEvents = 0; \
+ child1->numEnterEvents = 0; \
+ child1->numLeaveEvents = 0; \
+ child2->numEnterEvents = 0; \
+ child2->numLeaveEvents = 0; \
+ grandChild->numEnterEvents = 0; \
+ grandChild->numLeaveEvents = 0;
+
+ // Position the cursor in the middle of the window.
+ const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
+ QCursor::setPos(globalPos); // Enter child2 and grandChild.
+ QTest::qWait(300);
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child2->numLeaveEvents, 0);
+ QCOMPARE(grandChild->numLeaveEvents, 0);
+ QCOMPARE(child1->numLeaveEvents, 0);
+
+ // This event arrives asynchronously
+ QTRY_COMPARE(window.numEnterEvents, 1);
+ QCOMPARE(child2->numEnterEvents, 1);
+ QCOMPARE(grandChild->numEnterEvents, 1);
+ QCOMPARE(child1->numEnterEvents, 0);
+
+ RESET_EVENT_COUNTS;
+ child2->hide(); // Leave child2 and grandChild, enter child1.
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child2->numLeaveEvents, 1);
+ QCOMPARE(grandChild->numLeaveEvents, 1);
+ QCOMPARE(child1->numLeaveEvents, 0);
+
+ QCOMPARE(window.numEnterEvents, 0);
+ QCOMPARE(child2->numEnterEvents, 0);
+ QCOMPARE(grandChild->numEnterEvents, 0);
+ QCOMPARE(child1->numEnterEvents, 1);
+
+ RESET_EVENT_COUNTS;
+ child2->show(); // Leave child1, enter child2 and grandChild.
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child2->numLeaveEvents, 0);
+ QCOMPARE(grandChild->numLeaveEvents, 0);
+ QCOMPARE(child1->numLeaveEvents, 1);
+
+ QCOMPARE(window.numEnterEvents, 0);
+ QCOMPARE(child2->numEnterEvents, 1);
+ QCOMPARE(grandChild->numEnterEvents, 1);
+ QCOMPARE(child1->numEnterEvents, 0);
+
+ RESET_EVENT_COUNTS;
+ delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child1->numLeaveEvents, 0);
+
+ QCOMPARE(window.numEnterEvents, 0);
+ QCOMPARE(child1->numEnterEvents, 1);
+}
+#endif
+
+// Windows Mobile has no proper cursor support, so skip this test on that platform.
+#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE_WM)) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
+{
+ class SELParent : public QWidget
+ {
+ public:
+ SELParent(QWidget *parent = 0): QWidget(parent) { }
+
+ void mousePressEvent(QMouseEvent *) { child->show(); }
+ QWidget *child;
+ };
+
+ class SELChild : public QWidget
+ {
+ public:
+ SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
+ void enterEvent(QEvent *) { ++numEnterEvents; }
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ QCOMPARE(event->button(), Qt::NoButton);
+ QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
+ ++numMouseMoveEvents;
+ }
+ void reset() { numEnterEvents = numMouseMoveEvents = 0; }
+ int numEnterEvents, numMouseMoveEvents;
+ };
+
+ QCursor::setPos(QPoint(0,0));
+
+ SELParent parent;
+ parent.resize(200, 200);
+ SELChild child(&parent);
+ child.resize(200, 200);
+ parent.show();
+ #ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&parent);
+ #endif
+ QTest::qWait(150);
+
+ QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
+ // Make sure the cursor has entered the child.
+ QTRY_VERIFY(child.numEnterEvents > 0);
+
+ child.hide();
+ child.reset();
+ child.show();
+
+ // Make sure the child gets enter event and no mouse move event.
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
+
+ child.hide();
+ child.reset();
+ child.setMouseTracking(true);
+ child.show();
+
+ // Make sure the child gets enter event and mouse move event.
+ // Note that we verify event->button() and event->buttons()
+ // in SELChild::mouseMoveEvent().
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 1);
+
+ // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
+ parent.child = &child;
+
+ child.hide();
+ child.reset();
+ QTest::mouseClick(&parent, Qt::LeftButton);
+
+ // Make sure the child gets enter event and one mouse move event.
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 1);
+
+ child.hide();
+ child.reset();
+ child.setMouseTracking(false);
+ QTest::mouseClick(&parent, Qt::LeftButton);
+
+ // Make sure the child gets enter event and no mouse move event.
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
+ }
+#endif
+
+void tst_QWidget::windowFlags()
+{
+ QWidget w;
+ w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
+ QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
+}
+
+void tst_QWidget::initialPosForDontShowOnScreenWidgets()
+{
+ { // Check default position.
+ const QPoint expectedPos(0, 0);
+ QWidget widget;
+ widget.setAttribute(Qt::WA_DontShowOnScreen);
+ widget.winId(); // Make sure create_sys is called.
+ QCOMPARE(widget.pos(), expectedPos);
+ QCOMPARE(widget.geometry().topLeft(), expectedPos);
+ }
+
+ { // Explicitly move to a position.
+ const QPoint expectedPos(100, 100);
+ QWidget widget;
+ widget.setAttribute(Qt::WA_DontShowOnScreen);
+ widget.move(expectedPos);
+ widget.winId(); // Make sure create_sys is called.
+ QCOMPARE(widget.pos(), expectedPos);
+ QCOMPARE(widget.geometry().topLeft(), expectedPos);
+ }
+}
+
+#ifdef Q_WS_X11
+void tst_QWidget::paintOutsidePaintEvent()
+{
+ QWidget widget;
+ widget.resize(200, 200);
+
+ QWidget child1(&widget);
+ child1.resize(100, 100);
+ child1.setPalette(Qt::red);
+ child1.setAutoFillBackground(true);
+
+ QWidget child2(&widget);
+ child2.setGeometry(50, 50, 100, 100);
+ child2.setPalette(Qt::blue);
+ child2.setAutoFillBackground(true);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(60);
+
+ const QPixmap before = QPixmap::grabWindow(widget.winId());
+
+ // Child 1 should be clipped by child 2, so nothing should change.
+ child1.setAttribute(Qt::WA_PaintOutsidePaintEvent);
+ QPainter painter(&child1);
+ painter.fillRect(child1.rect(), Qt::red);
+ painter.end();
+ XSync(QX11Info::display(), false); // Flush output buffer.
+ QTest::qWait(60);
+
+ const QPixmap after = QPixmap::grabWindow(widget.winId());
+
+ QCOMPARE(before, after);
+}
+#endif
+
+class MyEvilObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
+ {
+ connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
+ delete widget;
+ }
+ QWidget *widget;
+
+private slots:
+ void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
+};
+
+void tst_QWidget::updateOnDestroyedSignal()
+{
+ QWidget widget;
+
+ QWidget *child = new QWidget(&widget);
+ child->resize(100, 100);
+ child->setAutoFillBackground(true);
+ child->setPalette(Qt::red);
+
+ widget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QTest::qWait(200);
+
+ // Please do not crash.
+ MyEvilObject evil(child);
+ QTest::qWait(200);
+}
+
+void tst_QWidget::toplevelLineEditFocus()
+{
+ testWidget->hide();
+
+ QLineEdit w;
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(20);
+
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
+ QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
+}
+
+void tst_QWidget::focusWidget_task254563()
+{
+ //having different visibility for widget is important
+ QWidget top;
+ top.show();
+ QWidget container(&top);
+ QWidget *widget = new QWidget(&container);
+ widget->show();
+
+ widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
+ container.setFocus();
+ delete widget; // will call clearFocus but that doesn't help
+ QVERIFY(top.focusWidget() != widget); //dangling pointer
+}
+
+// This test case relies on developer build (AUTOTEST_EXPORT).
+#ifdef QT_BUILD_INTERNAL
+void tst_QWidget::destroyBackingStore()
+{
+ UpdateWidget w;
+ w.reset();
+ w.show();
+
+ QTest::qWaitForWindowShown(&w);
+ QApplication::processEvents();
+ QTRY_VERIFY(w.numPaintEvents > 0);
+ w.reset();
+ w.update();
+ qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
+
+ w.update();
+ QApplication::processEvents();
+#ifdef Q_WS_QWS
+ QApplication::processEvents();
+#endif
+ QCOMPARE(w.numPaintEvents, 1);
+
+ // Check one more time, because the second time around does more caching.
+ w.update();
+ QApplication::processEvents();
+ QCOMPARE(w.numPaintEvents, 2);
+}
+#endif
+
+// Helper function
+QWidgetBackingStore* backingStore(QWidget &widget)
+{
+ QWidgetBackingStore *backingStore = 0;
+#ifdef QT_BUILD_INTERNAL
+ if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
+ backingStore = topExtra->backingStoreTracker.data();
+#endif
+ return backingStore;
+}
+
+// Tables of 5000 elements do not make sense on Windows Mobile.
+#ifndef Q_OS_WINCE_WM
+void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
+{
+ QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
+ QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
+ QPalette palette;
+ palette.setColor(QPalette::Window, Qt::red);
+ main.setPalette(palette);
+
+ QDesktopWidget desktop;
+ QRect desktopDimensions = desktop.availableGeometry(&main);
+ QSize mainSize(400, 400);
+ mainSize = mainSize.boundedTo(desktopDimensions.size());
+ main.resize(mainSize);
+
+ QWidget *offsetWidget = new QWidget(&main);
+ offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
+
+ // big widget is too big for the coordinates, it must be limited by wrect
+ // if wrect is not at the right position because of offsetWidget, bigwidget
+ // is not painted correctly
+ QWidget *bigWidget = new QWidget(offsetWidget);
+ bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
+ palette.setColor(QPalette::Window, Qt::green);
+ bigWidget->setPalette(palette);
+ bigWidget->setAutoFillBackground(true);
+
+ main.show();
+ QTest::qWaitForWindowShown(&main);
+
+ QPixmap correct(main.size());
+ correct.fill(Qt::green);
+
+ QTRY_COMPARE(QPixmap::grabWindow(main.winId()).toImage().convertToFormat(QImage::Format_RGB32),
+ correct.toImage().convertToFormat(QImage::Format_RGB32));
+ QApplication::restoreOverrideCursor();
+}
+#endif
+
+void tst_QWidget::inputFocus_task257832()
+{
+ QLineEdit *widget = new QLineEdit;
+ QInputContext *context = widget->inputContext();
+ if (!context)
+ QSKIP("No input context", SkipSingle);
+ widget->setFocus();
+ widget->winId(); // make sure, widget has been created
+ context->setFocusWidget(widget);
+ QCOMPARE(context->focusWidget(), static_cast<QWidget*>(widget));
+ widget->setReadOnly(true);
+ QVERIFY(!context->focusWidget());
+ delete widget;
+}
+
+void tst_QWidget::setGraphicsEffect()
+{
+ // Check that we don't have any effect by default.
+ QWidget *widget = new QWidget;
+ QVERIFY(!widget->graphicsEffect());
+
+ // SetGet check.
+ QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
+ widget->setGraphicsEffect(blurEffect);
+ QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
+
+ // Ensure the existing effect is deleted when setting a new one.
+ QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
+ widget->setGraphicsEffect(shadowEffect);
+ QVERIFY(!blurEffect);
+ QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
+ blurEffect = new QGraphicsBlurEffect;
+
+ // Ensure the effect is uninstalled when setting it on a new target.
+ QWidget *anotherWidget = new QWidget;
+ anotherWidget->setGraphicsEffect(blurEffect);
+ widget->setGraphicsEffect(blurEffect);
+ QVERIFY(!anotherWidget->graphicsEffect());
+ QVERIFY(!shadowEffect);
+
+ // Ensure the existing effect is deleted when deleting the widget.
+ delete widget;
+ QVERIFY(!blurEffect);
+ delete anotherWidget;
+
+ // Ensure the effect is uninstalled when deleting it
+ widget = new QWidget;
+ blurEffect = new QGraphicsBlurEffect;
+ widget->setGraphicsEffect(blurEffect);
+ delete blurEffect;
+ QVERIFY(!widget->graphicsEffect());
+
+ // Ensure the existing effect is uninstalled and deleted when setting a null effect
+ blurEffect = new QGraphicsBlurEffect;
+ widget->setGraphicsEffect(blurEffect);
+ widget->setGraphicsEffect(0);
+ QVERIFY(!widget->graphicsEffect());
+ QVERIFY(!blurEffect);
+
+ delete widget;
+}
+
+void tst_QWidget::activateWindow()
+{
+ // Test case for task 260685
+
+ // Create first mainwindow and set it active
+ QMainWindow* mainwindow = new QMainWindow();
+ QLabel* label = new QLabel(mainwindow);
+ mainwindow->setCentralWidget(label);
+ mainwindow->setVisible(true);
+ mainwindow->activateWindow();
+ QTest::qWaitForWindowShown(mainwindow);
+ qApp->processEvents();
+
+ QTRY_VERIFY(mainwindow->isActiveWindow());
+
+ // Create second mainwindow and set it active
+ QMainWindow* mainwindow2 = new QMainWindow();
+ QLabel* label2 = new QLabel(mainwindow2);
+ mainwindow2->setCentralWidget(label2);
+ mainwindow2->setVisible(true);
+ mainwindow2->activateWindow();
+ qApp->processEvents();
+
+ QTRY_VERIFY(!mainwindow->isActiveWindow());
+ QTRY_VERIFY(mainwindow2->isActiveWindow());
+
+ // Revert first mainwindow back to visible active
+ mainwindow->setVisible(true);
+ mainwindow->activateWindow();
+ qApp->processEvents();
+
+ QTRY_VERIFY(mainwindow->isActiveWindow());
+ QTRY_VERIFY(!mainwindow2->isActiveWindow());
+}
+
+void tst_QWidget::openModal_taskQTBUG_5804()
+{
+ class Widget : public QWidget
+ {
+ public:
+ Widget(QWidget *parent) : QWidget(parent)
+ {
+ }
+ ~Widget()
+ {
+ QMessageBox msgbox;
+ QTimer::singleShot(10, &msgbox, SLOT(accept()));
+ msgbox.exec(); //open a modal dialog
+ }
+ };
+
+ QWidget *win = new QWidget;
+ new Widget(win);
+ win->show();
+ QTest::qWaitForWindowShown(win);
+ delete win;
+}
+
+class InputContextTester : public QInputContext
+{
+ Q_OBJECT
+public:
+ QString identifierName() { return QString(); }
+ bool isComposing() const { return false; }
+ QString language() { return QString(); }
+ void reset() { ++resets; }
+ int resets;
+};
+
+void tst_QWidget::focusProxyAndInputMethods()
+{
+ InputContextTester *inputContext = new InputContextTester;
+ QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
+ toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
+ qApp->setInputContext(inputContext); // ownership is transferred
+
+ QWidget *child = new QWidget(toplevel);
+ child->setFocusProxy(toplevel);
+ child->setAttribute(Qt::WA_InputMethodEnabled, true);
+
+ toplevel->setFocusPolicy(Qt::WheelFocus);
+ child->setFocusPolicy(Qt::WheelFocus);
+
+ QVERIFY(!child->hasFocus());
+ QVERIFY(!toplevel->hasFocus());
+
+ toplevel->show();
+ QTest::qWaitForWindowShown(toplevel);
+ QApplication::setActiveWindow(toplevel);
+ QVERIFY(toplevel->hasFocus());
+ QVERIFY(child->hasFocus());
+
+ // verify that toggling input methods on the child widget
+ // correctly propagate to the focus proxy's input method
+ // and that the input method gets the focus proxy passed
+ // as the focus widget instead of the child widget.
+ // otherwise input method queries go to the wrong widget
+
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ child->setAttribute(Qt::WA_InputMethodEnabled, false);
+ QVERIFY(!inputContext->focusWidget());
+
+ child->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ child->setEnabled(false);
+ QVERIFY(!inputContext->focusWidget());
+
+ child->setEnabled(true);
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ delete toplevel;
+}
+
+#ifdef QT_BUILD_INTERNAL
+class scrollWidgetWBS : public QWidget
+{
+public:
+ void deleteBackingStore()
+ {
+ static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
+ }
+ void enableBackingStore()
+ {
+ if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
+ static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
+ static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
+ repaint();
+ }
+ }
+};
+#endif
+
+// Test case relies on developer build (AUTOTEST_EXPORT).
+#ifdef QT_BUILD_INTERNAL
+void tst_QWidget::scrollWithoutBackingStore()
+{
+ scrollWidgetWBS scrollable;
+ scrollable.resize(100,100);
+ QLabel child(QString("@"),&scrollable);
+ child.resize(50,50);
+ scrollable.show();
+ QTest::qWaitForWindowShown(&scrollable);
+ scrollable.scroll(50,50);
+ QCOMPARE(child.pos(),QPoint(50,50));
+ scrollable.deleteBackingStore();
+ scrollable.scroll(-25,-25);
+ QCOMPARE(child.pos(),QPoint(25,25));
+ scrollable.enableBackingStore();
+ QCOMPARE(child.pos(),QPoint(25,25));
+}
+#endif
+
+void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
+{
+ QWidget w;
+ w.setFocusPolicy(Qt::TabFocus);
+ QWidget *fp = new QWidget(&w);
+ fp->setFocusPolicy(Qt::TabFocus);
+ w.setFocusProxy(fp);
+ QWidget::setTabOrder(&w, fp);
+
+ // In debug mode, no assertion failure means it's alright.
+}
+
+void tst_QWidget::movedAndResizedAttributes()
+{
+#if defined (Q_OS_MAC) || defined(Q_WS_QWS)
+ QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
+ QVERIFY(false);
+#else
+ QWidget w;
+ w.show();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setWindowState(Qt::WindowFullScreen);
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setWindowState(Qt::WindowMaximized);
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setWindowState(Qt::WindowMinimized);
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showNormal();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showMaximized();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showFullScreen();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showNormal();
+ w.move(10,10);
+ QVERIFY(w.testAttribute(Qt::WA_Moved));
+#if defined(Q_OS_WIN)
+ QEXPECT_FAIL("", "FixMe, QTBUG-8911", Abort);
+#endif
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.resize(100, 100);
+ QVERIFY(w.testAttribute(Qt::WA_Moved));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+#endif
+}
+
+void tst_QWidget::childAt()
+{
+ QWidget parent(0, Qt::FramelessWindowHint);
+ parent.resize(200, 200);
+
+ QWidget *child = new QWidget(&parent);
+ child->setPalette(Qt::red);
+ child->setAutoFillBackground(true);
+ child->setGeometry(20, 20, 160, 160);
+
+ QWidget *grandChild = new QWidget(child);
+ grandChild->setPalette(Qt::blue);
+ grandChild->setAutoFillBackground(true);
+ grandChild->setGeometry(-20, -20, 220, 220);
+
+ QVERIFY(!parent.childAt(19, 19));
+ QVERIFY(!parent.childAt(180, 180));
+ QCOMPARE(parent.childAt(20, 20), grandChild);
+ QCOMPARE(parent.childAt(179, 179), grandChild);
+
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
+ QCOMPARE(parent.childAt(20, 20), child);
+ QCOMPARE(parent.childAt(179, 179), child);
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
+
+ child->setMask(QRect(50, 50, 60, 60));
+
+ QVERIFY(!parent.childAt(69, 69));
+ QVERIFY(!parent.childAt(130, 130));
+ QCOMPARE(parent.childAt(70, 70), grandChild);
+ QCOMPARE(parent.childAt(129, 129), grandChild);
+
+ child->setAttribute(Qt::WA_MouseNoMask);
+ QCOMPARE(parent.childAt(69, 69), grandChild);
+ QCOMPARE(parent.childAt(130, 130), grandChild);
+ child->setAttribute(Qt::WA_MouseNoMask, false);
+
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
+ QCOMPARE(parent.childAt(70, 70), child);
+ QCOMPARE(parent.childAt(129, 129), child);
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
+
+ grandChild->setMask(QRect(80, 80, 40, 40));
+
+ QCOMPARE(parent.childAt(79, 79), child);
+ QCOMPARE(parent.childAt(120, 120), child);
+ QCOMPARE(parent.childAt(80, 80), grandChild);
+ QCOMPARE(parent.childAt(119, 119), grandChild);
+
+ grandChild->setAttribute(Qt::WA_MouseNoMask);
+
+ QCOMPARE(parent.childAt(79, 79), grandChild);
+ QCOMPARE(parent.childAt(120, 120), grandChild);
+}
+
+#ifdef Q_WS_MAC
+void tst_QWidget::childAt_unifiedToolBar()
+{
+ QLabel *label = new QLabel(QLatin1String("foo"));
+ QToolBar *toolBar = new QToolBar;
+ toolBar->addWidget(new QLabel("dummy"));
+ toolBar->addWidget(label);
+
+ QMainWindow mainWindow;
+ mainWindow.addToolBar(toolBar);
+ mainWindow.show();
+
+ // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
+ QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
+ QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
+
+ QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
+ QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
+
+ // Enable unified tool bars.
+ mainWindow.setUnifiedTitleAndToolBarOnMac(true);
+ QTest::qWait(50);
+
+ // The tool bar is now in the "non-client" area of QMainWindow, i.e.
+ // outside the mainWindow's rect(), and since mapTo et al. doesn't work
+ // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
+ // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
+ QPoint oldToolBarTopLeft = toolBarTopLeft;
+ toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
+ QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
+ QVERIFY(toolBarTopLeft.y() < 0);
+ labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
+
+ QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
+ QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
+}
+
+void tst_QWidget::taskQTBUG_11373()
+{
+ QMainWindow * myWindow = new QMainWindow();
+ QWidget * center = new QWidget();
+ myWindow -> setCentralWidget(center);
+ QWidget * drawer = new QWidget(myWindow, Qt::Drawer);
+ drawer -> hide();
+ QCOMPARE(drawer->isVisible(), false);
+ myWindow -> show();
+ myWindow -> raise();
+ // The drawer shouldn't be visible now.
+ QCOMPARE(drawer->isVisible(), false);
+ myWindow -> setWindowState(Qt::WindowFullScreen);
+ myWindow -> setWindowState(Qt::WindowNoState);
+ // The drawer should still not be visible, since we haven't shown it.
+ QCOMPARE(drawer->isVisible(), false);
+}
+#endif
+
+void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
+{
+ QTableView tb;
+ const char *s = "border: 1px solid;";
+ tb.setStyleSheet(s);
+ tb.show();
+
+ QTest::qWaitForWindowShown(&tb);
+ tb.setGeometry(QRect(100, 100, 0, 100));
+ // No crash, it works.
+}
+
+void tst_QWidget::nativeChildFocus()
+{
+ QWidget w;
+ QLayout *layout = new QVBoxLayout;
+ w.setLayout(layout);
+ QLineEdit *p1 = new QLineEdit;
+ QLineEdit *p2 = new QLineEdit;
+ layout->addWidget(p1);
+ layout->addWidget(p2);
+#if 1
+ p1->setObjectName("p1");
+ p2->setObjectName("p2");
+#endif
+ w.show();
+#if 1
+ w.activateWindow();
+ p1->setFocus();
+ p1->setAttribute(Qt::WA_NativeWindow);
+ p2->setAttribute(Qt::WA_NativeWindow);
+ QApplication::processEvents();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+
+ qDebug() << "checking active window:" << QApplication::activeWindow();
+ QCOMPARE(QApplication::activeWindow(), &w);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
+#endif
+
+ QTest::qWait(1000);
+}
+
+QTEST_MAIN(tst_QWidget)
+#include "tst_qwidget.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h
new file mode 100644
index 0000000000..d7bc3f33c7
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/QString>
+#include <QtCore/QPair>
+#include <QtGui/QWidget>
+
+#pragma once // Yeah, it's deprecated in general, but it's standard practive for Mac OS X.
+
+QString nativeWindowTitle(QWidget *widget, Qt::WindowState state);
+bool nativeWindowModified(QWidget *widget);
+
+typedef QPair<QWidget *, WId> WidgetViewPair;
+bool testAndRelease(const WId);
+WidgetViewPair createAndRetain(QWidget * const parent = 0);
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm
new file mode 100644
index 0000000000..10e137c06c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tst_qwidget_mac_helpers.h"
+#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+
+
+QString nativeWindowTitle(QWidget *window, Qt::WindowState state)
+{
+ OSWindowRef windowRef = qt_mac_window_for(window);
+ QCFString macTitle;
+ if (state == Qt::WindowMinimized) {
+ macTitle = reinterpret_cast<CFStringRef>([[windowRef miniwindowTitle] retain]);
+ } else {
+ macTitle = reinterpret_cast<CFStringRef>([[windowRef title] retain]);
+ }
+ return macTitle;
+}
+
+bool nativeWindowModified(QWidget *widget)
+{
+ return [qt_mac_window_for(widget) isDocumentEdited];
+}
+
+bool testAndRelease(const WId view)
+{
+ if ([id(view) retainCount] != 2)
+ return false;
+ [id(view) release];
+ [id(view) release];
+ return true;
+}
+
+WidgetViewPair createAndRetain(QWidget * const parent)
+{
+ QWidget * const widget = new QWidget(parent);
+ const WId view = widget->winId();
+ // Retain twice so we can safely call retainCount even if the retain count
+ // is off by one because of a double release.
+ [id(view) retain];
+ [id(view) retain];
+ return qMakePair(widget, view);
+}
+
diff --git a/tests/auto/widgets/kernel/qwidget_window/.gitignore b/tests/auto/widgets/kernel/qwidget_window/.gitignore
new file mode 100644
index 0000000000..7f0bd8d631
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget_window/.gitignore
@@ -0,0 +1 @@
+tst_qwidget_window
diff --git a/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
new file mode 100644
index 0000000000..dd5837012c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qwidget_window.cpp
+
+x11 {
+ LIBS += $$QMAKE_LIBS_X11
+}
+
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
new file mode 100644
index 0000000000..eb8b555bd6
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui/QtGui>
+#include <qeventloop.h>
+#include <qlist.h>
+
+#include <qlistwidget.h>
+
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <QX11Info>
+#endif // Q_WS_X11
+
+class tst_QWidget_window : public QWidget
+{
+ Q_OBJECT
+
+public:
+ tst_QWidget_window(){};
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void tst_move_show();
+ void tst_show_move();
+ void tst_show_move_hide_show();
+
+ void tst_resize_show();
+ void tst_show_resize();
+ void tst_show_resize_hide_show();
+
+ void tst_windowFilePathAndwindowTitle_data();
+ void tst_windowFilePathAndwindowTitle();
+ void tst_windowFilePath_data();
+ void tst_windowFilePath();
+
+#ifdef Q_WS_X11
+ void tst_showWithoutActivating();
+#endif
+ void tst_paintEventOnSecondShow();
+};
+
+void tst_QWidget_window::initTestCase()
+{
+}
+
+void tst_QWidget_window::cleanupTestCase()
+{
+}
+
+void tst_QWidget_window::tst_move_show()
+{
+ QWidget w;
+ w.move(100, 100);
+ w.show();
+ QCOMPARE(w.pos(), QPoint(100, 100));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 3000);
+}
+
+void tst_QWidget_window::tst_show_move()
+{
+ QWidget w;
+ w.show();
+ w.move(100, 100);
+ QCOMPARE(w.pos(), QPoint(100, 100));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_show_move_hide_show()
+{
+ QWidget w;
+ w.show();
+ w.move(100, 100);
+ w.hide();
+ w.show();
+ QCOMPARE(w.pos(), QPoint(100, 100));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_resize_show()
+{
+ QWidget w;
+ w.resize(200, 200);
+ w.show();
+ QCOMPARE(w.size(), QSize(200, 200));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_show_resize()
+{
+ QWidget w;
+ w.show();
+ w.resize(200, 200);
+ QCOMPARE(w.size(), QSize(200, 200));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_show_resize_hide_show()
+{
+ QWidget w;
+ w.show();
+ w.resize(200, 200);
+ w.hide();
+ w.show();
+ QCOMPARE(w.size(), QSize(200, 200));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+class TestWidget : public QWidget
+{
+public:
+ int m_first, m_next;
+ bool paintEventReceived;
+
+ void reset(){ m_first = m_next = 0; paintEventReceived = false; }
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ case QEvent::Hide:
+ case QEvent::Show:
+ if (m_first)
+ m_next = event->type();
+ else
+ m_first = event->type();
+ break;
+ case QEvent::Paint:
+ paintEventReceived = true;
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+ }
+};
+
+void tst_QWidget_window::tst_windowFilePathAndwindowTitle_data()
+{
+ QTest::addColumn<bool>("setWindowTitleBefore");
+ QTest::addColumn<bool>("setWindowTitleAfter");
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QString>("applicationName");
+ QTest::addColumn<QString>("indyWindowTitle");
+ QTest::addColumn<QString>("finalTitleBefore");
+ QTest::addColumn<QString>("finalTitleAfter");
+
+ QString validPath = QApplication::applicationFilePath();
+ QString appName = QLatin1String("Killer App");
+ QString fileNameOnly = QFileInfo(validPath).fileName() + QLatin1String("[*]");
+ QString fileAndApp = fileNameOnly + QLatin1String(" ") + QChar(0x2014) + QLatin1String(" ") + appName;
+ QString windowTitle = QLatin1String("Here is a Window Title");
+
+ QTest::newRow("never Set Title nor AppName") << false << false << validPath << QString() << windowTitle << fileNameOnly << fileNameOnly;
+ QTest::newRow("set title after only, but no AppName") << false << true << validPath << QString() << windowTitle << fileNameOnly << windowTitle;
+ QTest::newRow("set title before only, not AppName") << true << false << validPath << QString() << windowTitle << windowTitle << windowTitle;
+ QTest::newRow("always set title, not appName") << true << true << validPath << QString() << windowTitle << windowTitle << windowTitle;
+
+ QString platString =
+#ifdef Q_WS_MAC
+ fileNameOnly;
+#else
+ fileAndApp;
+#endif
+
+ QTest::newRow("never Set Title, yes AppName") << false << false << validPath << appName << windowTitle << platString << platString;
+ QTest::newRow("set title after only, yes AppName") << false << true << validPath << appName << windowTitle << platString << windowTitle;
+ QTest::newRow("set title before only, yes AppName") << true << false << validPath << appName << windowTitle << windowTitle << windowTitle;
+ QTest::newRow("always set title, yes appName") << true << true << validPath << appName << windowTitle << windowTitle << windowTitle;
+}
+
+void tst_QWidget_window::tst_windowFilePathAndwindowTitle()
+{
+ QFETCH(bool, setWindowTitleBefore);
+ QFETCH(bool, setWindowTitleAfter);
+ QFETCH(QString, filePath);
+ QFETCH(QString, applicationName);
+ QFETCH(QString, indyWindowTitle);
+ QFETCH(QString, finalTitleBefore);
+ QFETCH(QString, finalTitleAfter);
+
+
+ QWidget widget;
+ QCOMPARE(widget.windowFilePath(), QString());
+
+ if (!applicationName.isEmpty())
+ qApp->setApplicationName(applicationName);
+ else
+ qApp->setApplicationName(QString());
+
+ if (setWindowTitleBefore) {
+ widget.setWindowTitle(indyWindowTitle);
+ }
+ widget.setWindowFilePath(filePath);
+ QCOMPARE(finalTitleBefore, widget.windowTitle());
+ QCOMPARE(widget.windowFilePath(), filePath);
+
+ if (setWindowTitleAfter) {
+ widget.setWindowTitle(indyWindowTitle);
+ }
+ QCOMPARE(finalTitleAfter, widget.windowTitle());
+ QCOMPARE(widget.windowFilePath(), filePath);
+}
+
+void tst_QWidget_window::tst_windowFilePath_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QString>("result");
+ QTest::addColumn<bool>("again");
+ QTest::addColumn<QString>("filePath2");
+ QTest::addColumn<QString>("result2");
+
+ QString validPath = QApplication::applicationFilePath();
+ QString invalidPath = QLatin1String("::**Never a Real Path**::");
+
+ QTest::newRow("never Set Path") << QString() << QString() << false << QString() << QString();
+ QTest::newRow("never EVER Set Path") << QString() << QString() << true << QString() << QString();
+ QTest::newRow("Valid Path") << validPath << validPath << false << QString() << QString();
+ QTest::newRow("invalid Path") << invalidPath << invalidPath << false << QString() << QString();
+ QTest::newRow("Valid Path then empty") << validPath << validPath << true << QString() << QString();
+ QTest::newRow("invalid Path then empty") << invalidPath << invalidPath << true << QString() << QString();
+ QTest::newRow("invalid Path then valid") << invalidPath << invalidPath << true << validPath << validPath;
+ QTest::newRow("valid Path then invalid") << validPath << validPath << true << invalidPath << invalidPath;
+}
+
+void tst_QWidget_window::tst_windowFilePath()
+{
+ QFETCH(QString, filePath);
+ QFETCH(QString, result);
+ QFETCH(bool, again);
+ QFETCH(QString, filePath2);
+ QFETCH(QString, result2);
+
+ QWidget widget;
+ QCOMPARE(widget.windowFilePath(), QString());
+ widget.setWindowFilePath(filePath);
+ QCOMPARE(widget.windowFilePath(), result);
+ if (again) {
+ widget.setWindowFilePath(filePath2);
+ QCOMPARE(widget.windowFilePath(), result2);
+ }
+}
+
+#ifdef Q_WS_X11
+void tst_QWidget_window::tst_showWithoutActivating()
+{
+ QWidget w;
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QApplication::processEvents();
+
+ QApplication::clipboard();
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setAttribute(Qt::WA_ShowWithoutActivating, true);
+ lineEdit->show();
+ lineEdit->setAttribute(Qt::WA_ShowWithoutActivating, false);
+ lineEdit->raise();
+ lineEdit->activateWindow();
+
+ Window window;
+ int revertto;
+ QTRY_COMPARE(lineEdit->winId(),
+ (XGetInputFocus(QX11Info::display(), &window, &revertto), window) );
+ // Note the use of the , before window because we want the XGetInputFocus to be re-executed
+ // in each iteration of the inside loop of the QTRY_COMPARE macro
+}
+#endif
+
+void tst_QWidget_window::tst_paintEventOnSecondShow()
+{
+ TestWidget w;
+ w.show();
+ w.hide();
+
+ w.reset();
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QApplication::processEvents();
+ QTRY_VERIFY(w.paintEventReceived);
+}
+
+QTEST_MAIN(tst_QWidget_window)
+#include "tst_qwidget_window.moc"
diff --git a/tests/auto/widgets/kernel/qwidgetaction/.gitignore b/tests/auto/widgets/kernel/qwidgetaction/.gitignore
new file mode 100644
index 0000000000..56d519d851
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidgetaction/.gitignore
@@ -0,0 +1 @@
+tst_qwidgetaction
diff --git a/tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro b/tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro
new file mode 100644
index 0000000000..3e037c2efb
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qwidgetaction.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
new file mode 100644
index 0000000000..5f51f6d316
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qapplication.h>
+#include <qtoolbar.h>
+#include <qcombobox.h>
+#include <qwidgetaction.h>
+#include <qlabel.h>
+#include <qmenu.h>
+#include <qmainwindow.h>
+#include <qmenubar.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QWidgetAction : public QObject
+{
+ Q_OBJECT
+private slots:
+ void defaultWidget();
+ void visibilityUpdate();
+ void customWidget();
+ void keepOwnership();
+ void visibility();
+ void setEnabled();
+ void popup();
+ void releaseWidgetCrash();
+};
+
+void tst_QWidgetAction::defaultWidget()
+{
+ {
+ QToolBar tb1;
+
+ QPointer<QComboBox> combo = new QComboBox(&tb1);
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ QVERIFY(!combo->isVisible());
+ QVERIFY(!combo->parent());
+ QVERIFY(action->isVisible());
+
+ delete action;
+ QVERIFY(!combo);
+ }
+ {
+ QToolBar tb1;
+
+ QPointer<QComboBox> combo = new QComboBox(&tb1);
+ combo->hide();
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ // explicitly hidden widgets should also set the action invisible
+ QVERIFY(!action->isVisible());
+
+ delete action;
+ }
+ {
+ QPointer<QComboBox> combo = new QComboBox(0);
+ combo->show();
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ QVERIFY(action->isVisible());
+ QVERIFY(!combo->isVisible());
+
+ delete action;
+ }
+ {
+ QToolBar tb1;
+ tb1.show();
+ QToolBar tb2;
+ tb2.show();
+
+ QPointer<QComboBox> combo = new QComboBox(0);
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ tb1.addAction(action);
+ QVERIFY(combo->parent() == &tb1);
+ qApp->processEvents();
+ qApp->processEvents();
+ QVERIFY(combo->isVisible());
+
+ // not supported, not supposed to work, hence the parent() check
+ tb2.addAction(action);
+ QVERIFY(combo->parent() == &tb1);
+
+ tb2.removeAction(action);
+ tb1.removeAction(action);
+
+ qApp->processEvents(); //the call to hide is delayd by the toolbar layout
+ QVERIFY(!combo->isVisible());
+
+ tb2.addAction(action);
+ qApp->processEvents(); //the call to hide is delayd by the toolbar layout
+ qApp->processEvents();
+ QVERIFY(combo->parent() == &tb2);
+ QVERIFY(combo->isVisible());
+
+ tb1.addAction(action);
+ QVERIFY(combo->parent() == &tb2);
+
+ delete action;
+ QVERIFY(!combo);
+ }
+ {
+ QWidgetAction *a = new QWidgetAction(0);
+ QVERIFY(!a->defaultWidget());
+
+ QPointer<QComboBox> combo1 = new QComboBox;
+ a->setDefaultWidget(combo1);
+ QVERIFY(a->defaultWidget() == combo1);
+ a->setDefaultWidget(combo1);
+ QVERIFY(combo1);
+ QVERIFY(a->defaultWidget() == combo1);
+
+ QPointer<QComboBox> combo2 = new QComboBox;
+ QVERIFY(combo1 != combo2);
+
+ a->setDefaultWidget(combo2);
+ QVERIFY(!combo1);
+ QVERIFY(a->defaultWidget() == combo2);
+
+ delete a;
+ QVERIFY(!combo2);
+ }
+}
+
+void tst_QWidgetAction::visibilityUpdate()
+{
+ // actually keeping the widget's state in sync with the
+ // action in terms of visibility is QToolBar's responsibility.
+ QToolBar tb;
+ tb.show();
+
+ QComboBox *combo = new QComboBox(0);
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ tb.addAction(action);
+ //the call to show is delayed by the toolbar layout
+ QTRY_VERIFY(combo->isVisible());
+ QVERIFY(action->isVisible());
+
+ action->setVisible(false);
+ //the call to hide is delayed by the toolbar layout
+ QTRY_VERIFY(!combo->isVisible());
+
+ delete action;
+ // action also deletes combo
+}
+
+class ComboAction : public QWidgetAction
+{
+public:
+ inline ComboAction(QObject *parent) : QWidgetAction(parent) {}
+
+ QList<QWidget *> createdWidgets() const { return QWidgetAction::createdWidgets(); }
+
+protected:
+ virtual QWidget *createWidget(QWidget *parent);
+};
+
+QWidget *ComboAction::createWidget(QWidget *parent)
+{
+ return new QComboBox(parent);
+}
+
+void tst_QWidgetAction::customWidget()
+{
+ QToolBar tb1;
+ tb1.show();
+ QToolBar tb2;
+ tb2.show();
+
+ ComboAction *action = new ComboAction(0);
+
+ tb1.addAction(action);
+
+ QList<QWidget *> combos = action->createdWidgets();
+ QCOMPARE(combos.count(), 1);
+
+ QPointer<QComboBox> combo1 = qobject_cast<QComboBox *>(combos.at(0));
+ QVERIFY(combo1);
+
+ tb2.addAction(action);
+
+ combos = action->createdWidgets();
+ QCOMPARE(combos.count(), 2);
+
+ QVERIFY(combos.at(0) == combo1);
+ QPointer<QComboBox> combo2 = qobject_cast<QComboBox *>(combos.at(1));
+ QVERIFY(combo2);
+
+ tb2.removeAction(action);
+ QVERIFY(combo2);
+ // widget is deleted using deleteLater(), so process that posted event
+ QCoreApplication::sendPostedEvents(combo2, QEvent::DeferredDelete);
+ QVERIFY(!combo2);
+
+ delete action;
+ QVERIFY(!combo1);
+ QVERIFY(!combo2);
+}
+
+void tst_QWidgetAction::keepOwnership()
+{
+ QPointer<QComboBox> combo = new QComboBox;
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ {
+ QToolBar *tb = new QToolBar;
+ tb->addAction(action);
+ QVERIFY(combo->parent() == tb);
+ delete tb;
+ }
+
+ QVERIFY(combo);
+ delete action;
+ QVERIFY(!combo);
+}
+
+void tst_QWidgetAction::visibility()
+{
+ {
+ QWidgetAction *a = new QWidgetAction(0);
+ QComboBox *combo = new QComboBox;
+ a->setDefaultWidget(combo);
+
+ QToolBar *tb = new QToolBar;
+ tb->addAction(a);
+ QVERIFY(!combo->isVisible());
+ tb->show();
+ QVERIFY(combo->isVisible());
+
+ delete tb;
+
+ delete a;
+ }
+ {
+ QWidgetAction *a = new QWidgetAction(0);
+ QComboBox *combo = new QComboBox;
+ a->setDefaultWidget(combo);
+
+ QToolBar *tb = new QToolBar;
+ tb->addAction(a);
+ QVERIFY(!combo->isVisible());
+
+ QToolBar *tb2 = new QToolBar;
+ tb->removeAction(a);
+ tb2->addAction(a);
+ QVERIFY(!combo->isVisible());
+ tb2->show();
+ QVERIFY(combo->isVisible());
+
+ delete tb;
+ delete tb2;
+
+ delete a;
+ }
+}
+
+void tst_QWidgetAction::setEnabled()
+{
+ QToolBar toolbar;
+ QComboBox *combobox = new QComboBox;
+ QAction *action = toolbar.addWidget(combobox);
+ toolbar.show();
+
+ QVERIFY(action->isEnabled());
+ QVERIFY(combobox->isEnabled());
+
+ action->setEnabled(false);
+ QVERIFY(!action->isEnabled());
+ QVERIFY(!combobox->isEnabled());
+
+ action->setEnabled(true);
+ QVERIFY(action->isEnabled());
+ QVERIFY(combobox->isEnabled());
+
+ combobox->setEnabled(false);
+ QVERIFY(!combobox->isEnabled());
+
+ combobox->setEnabled(true);
+ QVERIFY(action->isEnabled());
+ QVERIFY(combobox->isEnabled());
+
+
+ QWidgetAction aw(0);
+ aw.setEnabled(false);
+ QVERIFY(!aw.isEnabled());
+
+ combobox = new QComboBox;
+ aw.setDefaultWidget(combobox);
+ QVERIFY(!aw.isEnabled());
+ QVERIFY(!combobox->isEnabled());
+
+ // Make sure we don't change the default widget's Qt::WA_ForceDisabled attribute
+ // during a normal disable/enable operation (task 207433).
+ {
+ QToolBar toolBar;
+ QWidget widget;
+ toolBar.addWidget(&widget); // creates a QWidgetAction and sets 'widget' as the default widget.
+ QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled));
+
+ toolBar.setEnabled(false);
+ QVERIFY(toolBar.testAttribute(Qt::WA_ForceDisabled));
+ QVERIFY(!widget.isEnabled());
+ QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled));
+
+ toolBar.setEnabled(true);
+ QVERIFY(widget.isEnabled());
+ QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled));
+ }
+}
+
+void tst_QWidgetAction::popup()
+{
+ QPointer<QLabel> l = new QLabel("test");
+ QWidgetAction action(0);
+ action.setDefaultWidget(l);
+
+ {
+ QMenu menu;
+ menu.addAction(&action);
+ QTimer::singleShot(0, &menu, SLOT(close()));
+ menu.exec();
+ }
+
+ QVERIFY(!l.isNull());
+ delete l;
+}
+
+class CrashedAction : public QWidgetAction
+{
+public:
+ inline CrashedAction(QObject *parent) : QWidgetAction(parent) { }
+
+ virtual QWidget *createWidget(QWidget *parent) {
+ return new QWidget(parent);
+ }
+};
+
+void tst_QWidgetAction::releaseWidgetCrash()
+{
+ // this should not crash!
+ QMainWindow *w = new QMainWindow;
+ QAction *a = new CrashedAction(w);
+ QMenu *menu = w->menuBar()->addMenu("Test");
+ menu->addAction("foo");
+ menu->addAction(a);
+ menu->addAction("bar");
+ delete w;
+}
+
+QTEST_MAIN(tst_QWidgetAction)
+#include "tst_qwidgetaction.moc"
diff --git a/tests/auto/widgets/styles/qmacstyle/.gitignore b/tests/auto/widgets/styles/qmacstyle/.gitignore
new file mode 100644
index 0000000000..9abe0ad6ab
--- /dev/null
+++ b/tests/auto/widgets/styles/qmacstyle/.gitignore
@@ -0,0 +1 @@
+tst_qmacstyle
diff --git a/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro b/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro
new file mode 100644
index 0000000000..5aad7368c6
--- /dev/null
+++ b/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qmacstyle.cpp
+
+
+mac*:CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
new file mode 100644
index 0000000000..a262712abc
--- /dev/null
+++ b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtWidgets>
+
+#include <qmacstyle_mac.h>
+
+const int N = 1;
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/styles/qmacstyle_mac.h gui/styles/qmacstyle_mac.cpp
+
+enum Size { Normal, Small, Mini };
+
+Q_DECLARE_METATYPE(Size);
+
+#define CT(E) \
+ static const ControlType E = QSizePolicy::E;
+
+typedef QSizePolicy::ControlType ControlType;
+
+CT(DefaultType)
+CT(ButtonBox)
+CT(CheckBox)
+CT(ComboBox)
+CT(Frame)
+CT(GroupBox)
+CT(Label)
+CT(Line)
+CT(LineEdit)
+CT(PushButton)
+CT(RadioButton)
+CT(Slider)
+CT(SpinBox)
+CT(TabWidget)
+CT(ToolButton)
+
+
+class tst_QMacStyle : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QMacStyle() { qRegisterMetaType<Size>("Size"); }
+
+private slots:
+ void sizeHints_data();
+ void sizeHints();
+ void layoutMargins_data();
+ void layoutMargins();
+ void layoutSpacings_data();
+ void layoutSpacings();
+ void smallMiniNormalExclusivity_data();
+ void smallMiniNormalExclusivity();
+
+private:
+ static QSize msh(QWidget *widget);
+ static QSize sh(QWidget *widget);
+ static QRect geo(QWidget *widget);
+ static QPoint pos(QWidget *widget) { return geo(widget).topLeft(); }
+ static QSize size(QWidget *widget) { return geo(widget).size(); }
+ static QSize gap(QWidget *widget1, QWidget *widget2);
+ static int hgap(QWidget *widget1, QWidget *widget2) { return gap(widget1, widget2).width(); }
+ static int vgap(QWidget *widget1, QWidget *widget2) { return gap(widget1, widget2).height(); }
+ static void setSize(QWidget *widget, Size size);
+ static int spacing(ControlType control1, ControlType control2, Qt::Orientation orientation,
+ QStyleOption *option = 0, QWidget *widget = 0);
+ static int hspacing(ControlType control1, ControlType control2, Size size = Normal);
+ static int vspacing(ControlType control1, ControlType control2, Size size = Normal);
+};
+
+#define SIZE(x, y, z) \
+ ((size == Normal) ? (x) : (size == Small) ? (y) : (z))
+
+void tst_QMacStyle::sizeHints_data()
+{
+ QTest::addColumn<Size>("size");
+ QTest::newRow("normal") << Normal;
+// QTest::newRow("small") << Small;
+// QTest::newRow("mini") << Mini;
+}
+
+void tst_QMacStyle::sizeHints()
+{
+ QFETCH(Size, size);
+ QDialog w;
+ setSize(&w, size);
+
+ QLineEdit lineEdit1(&w);
+ QCOMPARE(sh(&lineEdit1).height(), SIZE(22, 19, 16)); // 16 in Builder, 15 in AHIG
+
+ QProgressBar progress1(&w);
+ progress1.setOrientation(Qt::Horizontal);
+ qDebug() << "sh" << progress1.sizeHint();
+ QCOMPARE(sh(&progress1).height(), SIZE(16, 10, 10)); // Builder
+
+ progress1.setOrientation(Qt::Vertical);
+ QCOMPARE(sh(&progress1).width(), SIZE(16, 10, 10)); // Builder
+
+ QRadioButton radio1("Radio", &w);
+ QCOMPARE(sh(&radio1).height(), SIZE(15, 12, 10)); // Builder
+
+ QCheckBox checkBox1("Switch", &w);
+ QCOMPARE(sh(&checkBox1).height(), SIZE(14, 12, 10)); // Builder
+
+ QComboBox comboBox1(&w);
+ comboBox1.setEditable(false);
+ comboBox1.addItem("Foo");
+ QCOMPARE(sh(&comboBox1).height(), SIZE(20, 17, 15));
+
+ QComboBox comboBox2(&w);
+ comboBox2.setEditable(true);
+ comboBox2.addItem("Foo");
+ QCOMPARE(sh(&comboBox2).height(), SIZE(20, 17, 15));
+
+ // Combos in toolbars use the actual widget rect to
+ // avoid faulty clipping:
+ QToolBar tb;
+ setSize(&tb, size);
+ QComboBox comboBox3(&tb);
+ comboBox3.addItem("Foo");
+ QCOMPARE(sh(&comboBox3).height(), SIZE(26, -1, -1));
+
+ QSlider slider1(Qt::Horizontal, &w);
+ QCOMPARE(sh(&slider1).height(), SIZE(15, 12, 10));
+
+ slider1.setTickPosition(QSlider::TicksAbove);
+ QCOMPARE(sh(&slider1).height(), SIZE(24, 17, 16)); // Builder
+
+ slider1.setTickPosition(QSlider::TicksBelow);
+ QCOMPARE(sh(&slider1).height(), SIZE(24, 17, 16)); // Builder
+
+ slider1.setTickPosition(QSlider::TicksBothSides);
+ QVERIFY(sh(&slider1).height() > SIZE(15, 12, 10)); // common sense
+
+ QPushButton ok1("OK", &w);
+ QPushButton cancel1("Cancel", &w);
+
+ QSize s1 = sh(&ok1);
+ if (size == Normal) {
+ // AHIG says 68, Builder does 70, and Qt seems to do 69
+ QVERIFY(s1.width() >= 68 && s1.width() <= 70);
+ }
+ QCOMPARE(s1.height(), SIZE(20, 17, 14)); // 14 in Builder, 15 in AHIG
+
+ // Cancel should be identical to OK, no matter what
+ QCOMPARE(s1, sh(&cancel1));
+
+ // Play with auto-default and default
+ cancel1.setAutoDefault(false);
+ QCOMPARE(s1, sh(&cancel1));
+ cancel1.setAutoDefault(true);
+ QCOMPARE(s1, sh(&cancel1));
+ cancel1.setDefault(true);
+ QCOMPARE(s1, sh(&cancel1));
+
+ QDialogButtonBox bbox(&w);
+ bbox.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ QCOMPARE(s1, sh(bbox.button(QDialogButtonBox::Ok)));
+ QCOMPARE(s1, sh(bbox.button(QDialogButtonBox::Cancel)));
+
+ QMessageBox mbox(&w);
+ mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+ QCOMPARE(s1, sh(mbox.button(QMessageBox::Ok)));
+ QCOMPARE(s1, sh(mbox.button(QMessageBox::Cancel)));
+
+ /*
+ QSpinBox spinBox1(&w);
+ int h1 = sh(&spinBox1).height();
+ QCOMPARE(h1, SIZE(22, 19, 15));
+
+ QDateEdit date1(&w);
+ QCOMPARE(sh(&date1).height(), h1);
+
+ QTimeEdit time1(&w);
+ QCOMPARE(sh(&time1).height(), h1);
+
+ QDateTimeEdit dateTime1(&w);
+ QCOMPARE(sh(&dateTime1).height(), h1);
+
+ ok1.setAttribute(Qt::WA_MacMetalStyle, true);
+ QSize s2 = sh(&ok1);
+ if (size == Normal) {
+ QVERIFY(s2.height() >= 21 && s2.height() <= 32);
+ } else {
+ QVERIFY(s2.height() >= 18 && s2.height() <= 24);
+ }
+ */
+
+ // QMacStyle bug: label doesn't react to Small and Mini
+ QLabel label1("Blah", &w);
+ QCOMPARE(sh(&label1).height(), SIZE(17, 14, 11));
+}
+
+void tst_QMacStyle::layoutMargins_data()
+{
+ tst_QMacStyle::sizeHints_data();
+}
+
+void tst_QMacStyle::layoutMargins()
+{
+ QFETCH(Size, size);
+ QWidget w;
+ setSize(&w, size);
+
+}
+
+void tst_QMacStyle::layoutSpacings_data()
+{
+ tst_QMacStyle::sizeHints_data();
+}
+
+void tst_QMacStyle::layoutSpacings()
+{
+ QFETCH(Size, size);
+
+ /*
+ Constraints specified by AHIG.
+ */
+
+ for (int i = 0; i < 4; ++i) {
+ ControlType c1 = (i % 2 == 0) ? PushButton : ButtonBox;
+ ControlType c2 = (i / 2 == 0) ? PushButton : ButtonBox;
+ QCOMPARE(hspacing(c1, c2, size), SIZE(14, 8, 8));
+ QCOMPARE(vspacing(c1, c2, size), SIZE(14, 8, 8));
+ }
+
+ QCOMPARE(hspacing(Label, RadioButton, size), SIZE(8, 6, 5));
+ QCOMPARE(vspacing(RadioButton, RadioButton, size), SIZE(5, 5, 5)); // Builder, guess, AHIG
+
+ QCOMPARE(hspacing(Label, CheckBox, size), SIZE(8, 6, 5));
+ QCOMPARE(vspacing(CheckBox, CheckBox, size), SIZE(8, 8, 7));
+
+ QCOMPARE(hspacing(Label, ComboBox, size), SIZE(8, 6, 5));
+
+ QCOMPARE(hspacing(LineEdit, LineEdit, size), SIZE(10, 8, 8));
+
+ /*
+ Common sense constraints, for when AHIG seems to make no sense (e.g., disagrees
+ too much with Builder or looks improper).
+ */
+
+ // Comboboxes are a special pain, because AHIG and Builder can't agree,
+ // and because they can be editable or not, with two totally different looks
+ QVERIFY(vspacing(ComboBox, ComboBox, size) >= SIZE(8, 6, 5));
+ QVERIFY(vspacing(ComboBox, ComboBox, size) <= SIZE(12, 10, 8));
+
+ // Make sure button boxes get the respect they deserve, when they occur
+ // in the bottom or right side of a dialog
+ QCOMPARE(hspacing(ButtonBox, LineEdit), SIZE(20, 8, 8));
+ QCOMPARE(vspacing(ButtonBox, LineEdit), SIZE(20, 7, 7));
+
+ QCOMPARE(hspacing(LineEdit, ButtonBox), SIZE(8, 8, 8));
+ QCOMPARE(vspacing(LineEdit, ButtonBox), SIZE(8, 8, 8));
+}
+
+// helper functions
+
+QSize tst_QMacStyle::msh(QWidget *widget)
+{
+ QWidgetItem item(widget);
+ return item.sizeHint();
+}
+
+QSize tst_QMacStyle::sh(QWidget *widget)
+{
+ QWidgetItem item(widget);
+ return item.sizeHint();
+}
+
+QRect tst_QMacStyle::geo(QWidget *widget)
+{
+ QWidgetItem item(widget);
+ return item.geometry();
+}
+
+QSize tst_QMacStyle::gap(QWidget *widget1, QWidget *widget2)
+{
+ QPoint d = pos(widget2) - pos(widget1);
+ QSize s = size(widget1);
+ return s + QSize(d.x(), d.y());
+}
+
+void tst_QMacStyle::setSize(QWidget *widget, Size size)
+{
+ switch (size) {
+ case Normal:
+ QMacStyle::setWidgetSizePolicy(widget, QMacStyle::SizeDefault);
+ break;
+ case Small:
+ QMacStyle::setWidgetSizePolicy(widget, QMacStyle::SizeSmall);
+ break;
+ case Mini:
+ QMacStyle::setWidgetSizePolicy(widget, QMacStyle::SizeMini);
+ }
+}
+
+int tst_QMacStyle::spacing(ControlType control1, ControlType control2, Qt::Orientation orientation,
+ QStyleOption *option, QWidget *widget)
+{
+ return QApplication::style()->layoutSpacing(control1, control2, orientation, option, widget);
+}
+
+int tst_QMacStyle::hspacing(ControlType control1, ControlType control2, Size size)
+{
+ QWidget w;
+ setSize(&w, size);
+
+ QStyleOption opt;
+ opt.initFrom(&w);
+
+ return spacing(control1, control2, Qt::Horizontal, &opt);
+}
+
+int tst_QMacStyle::vspacing(ControlType control1, ControlType control2, Size size)
+{
+ QWidget w;
+ setSize(&w, size);
+
+ QStyleOption opt;
+ opt.initFrom(&w);
+
+ return spacing(control1, control2, Qt::Vertical, &opt);
+}
+
+
+void tst_QMacStyle::smallMiniNormalExclusivity_data()
+{
+
+ QTest::addColumn<int>("size1");
+ QTest::addColumn<int>("size2");
+ QTest::addColumn<int>("size3");
+ QTest::addColumn<int>("expectedHeight1");
+ QTest::addColumn<int>("expectedHeight2");
+ QTest::addColumn<int>("expectedHeight3");
+
+ QTest::newRow("normal small mini") << int(Qt::WA_MacNormalSize) << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacMiniSize) << 32 << 16 << 24;
+ QTest::newRow("normal mini small") << int(Qt::WA_MacNormalSize) <<int(Qt::WA_MacMiniSize) << int(Qt::WA_MacSmallSize) << 32 << 24 << 16;
+ QTest::newRow("small normal mini") << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacNormalSize) << int(Qt::WA_MacMiniSize) << 16 << 32 << 24;
+ QTest::newRow("small mini normal") << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacMiniSize) << int(Qt::WA_MacNormalSize) << 16 << 24 << 32;
+ QTest::newRow("mini small normal") << int(Qt::WA_MacMiniSize) << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacNormalSize) << 24 << 16 << 32;
+ QTest::newRow("mini normal small") << int(Qt::WA_MacMiniSize) << int(Qt::WA_MacNormalSize) << int(Qt::WA_MacSmallSize) << 24 << 32 << 16;
+}
+
+void tst_QMacStyle::smallMiniNormalExclusivity()
+{
+
+ QFETCH(int, size1);
+ QFETCH(int, size2);
+ QFETCH(int, size3);
+ QFETCH(int, expectedHeight1);
+ QFETCH(int, expectedHeight2);
+ QFETCH(int, expectedHeight3);
+
+ static const int TotalSizes = 3;
+ int attrs[TotalSizes] = { size1, size2, size3 };
+ int expected[TotalSizes] = { expectedHeight1, expectedHeight2, expectedHeight3 };
+
+ QPushButton dummyWidget;
+ QStyleOptionButton opt;
+
+ for (int i = 0; i < TotalSizes; ++i) {
+ dummyWidget.setAttribute(Qt::WidgetAttribute(attrs[i]));
+ opt.initFrom(&dummyWidget);
+ QSize size = dummyWidget.style()->sizeFromContents(QStyle::CT_PushButton, &opt,
+ QSize(0, 0), &dummyWidget);
+ QCOMPARE(size.height(), expected[i]);
+ }
+}
+
+QTEST_MAIN(tst_QMacStyle)
+#include "tst_qmacstyle.moc"
+
diff --git a/tests/auto/widgets/styles/qstyle/.gitignore b/tests/auto/widgets/styles/qstyle/.gitignore
new file mode 100644
index 0000000000..64709f11f7
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/.gitignore
@@ -0,0 +1 @@
+tst_qstyle
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/button.png b/tests/auto/widgets/styles/qstyle/images/mac/button.png
new file mode 100644
index 0000000000..7b11325e87
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/button.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/combobox.png b/tests/auto/widgets/styles/qstyle/images/mac/combobox.png
new file mode 100644
index 0000000000..ded0b11f29
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/combobox.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png b/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png
new file mode 100644
index 0000000000..8d2861b65b
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/mdi.png b/tests/auto/widgets/styles/qstyle/images/mac/mdi.png
new file mode 100644
index 0000000000..8c09ae4338
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/mdi.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/menu.png b/tests/auto/widgets/styles/qstyle/images/mac/menu.png
new file mode 100644
index 0000000000..5dd9111d69
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/menu.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png b/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png
new file mode 100644
index 0000000000..8828e220a2
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/slider.png b/tests/auto/widgets/styles/qstyle/images/mac/slider.png
new file mode 100644
index 0000000000..fc65035631
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/slider.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png b/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png
new file mode 100644
index 0000000000..ee88441ecb
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/button.png b/tests/auto/widgets/styles/qstyle/images/vista/button.png
new file mode 100644
index 0000000000..a6c45276ca
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/button.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/combobox.png b/tests/auto/widgets/styles/qstyle/images/vista/combobox.png
new file mode 100644
index 0000000000..9b82f64d32
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/combobox.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png b/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png
new file mode 100644
index 0000000000..b2c6ac1ae4
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/menu.png b/tests/auto/widgets/styles/qstyle/images/vista/menu.png
new file mode 100644
index 0000000000..b114099cc3
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/menu.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png b/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png
new file mode 100644
index 0000000000..c8aa7864df
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/slider.png b/tests/auto/widgets/styles/qstyle/images/vista/slider.png
new file mode 100644
index 0000000000..7c156ded9d
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/slider.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png b/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png
new file mode 100644
index 0000000000..b8d0823ab2
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/qstyle.pro b/tests/auto/widgets/styles/qstyle/qstyle.pro
new file mode 100644
index 0000000000..2016316737
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/qstyle.pro
@@ -0,0 +1,13 @@
+load(qttest_p4)
+TARGET.EPOCHEAPSIZE = 0x200000 0x800000
+QT += widgets
+SOURCES += tst_qstyle.cpp
+
+wince* {
+ DEFINES += SRCDIR=\\\".\\\"
+ addPixmap.files = task_25863.png
+ addPixmap.path = .
+ DEPLOYMENT += addPixmap
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
diff --git a/tests/auto/widgets/styles/qstyle/task_25863.png b/tests/auto/widgets/styles/qstyle/task_25863.png
new file mode 100644
index 0000000000..a2de8d6f78
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/task_25863.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
new file mode 100644
index 0000000000..0045dbbb52
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
@@ -0,0 +1,794 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qlayout.h>
+#include "qstyle.h"
+#include <qevent.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qstyleoption.h>
+#include <qscrollbar.h>
+#include <qprogressbar.h>
+#include <qtoolbutton.h>
+#include <qtoolbar.h>
+
+#include <qplastiquestyle.h>
+#include <qwindowsstyle.h>
+#include <qcdestyle.h>
+#include <qmotifstyle.h>
+#include <qcommonstyle.h>
+#include <qproxystyle.h>
+#include <qstylefactory.h>
+
+#include <qimagereader.h>
+#include <qimagewriter.h>
+#include <qmenu.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qcombobox.h>
+#include <qradiobutton.h>
+#include <qlineedit.h>
+#include <qmdiarea.h>
+
+#include <QCleanlooksStyle>
+
+#ifdef Q_WS_MAC
+#include <QMacStyle>
+#endif
+
+#ifdef Q_WS_WIN
+#include <QWindowsXPStyle>
+#include <QWindowsVistaStyle>
+#endif
+
+#ifdef Q_OS_WINCE
+#include <QWindowsCEStyle>
+#endif
+
+#ifdef Q_OS_WINCE_WM
+#include <QWindowsMobileStyle>
+#include <windows.h>
+
+static bool qt_wince_is_smartphone() {
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
+ sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (QString::fromLatin1("Smartphone").utf16()), tszPlatform))
+ return true;
+ return false;
+}
+#endif
+
+#include <qwidget.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/styles/qstyle.h gui/styles/qstyle.cpp gui/styles/qplastiquestyle.cpp gui/styles/qwindowsstyle.cpp gui/styles/qwindowsxpstyle.cpp gui/styles/qwindowsvistastyle.cpp gui/styles/qmotifstyle.cpp
+
+class tst_QStyle : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QStyle();
+ virtual ~tst_QStyle();
+private:
+ void testAllFunctions(QStyle *);
+ void testScrollBarSubControls(QStyle *);
+ void testPainting(QStyle *style, const QString &platform);
+private slots:
+ void drawItemPixmap();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+#ifndef QT_NO_STYLE_MOTIF
+ void testMotifStyle();
+#endif
+#ifndef QT_NO_STYLE_PLASTIQUE
+ void testPlastiqueStyle();
+#endif
+ void testWindowsStyle();
+#ifndef QT_NO_STYLE_CDE
+ void testCDEStyle();
+#endif
+#if defined(Q_WS_WIN) && !defined(QT_NO_STYLE_WINDOWSXP)
+ void testWindowsXPStyle();
+#endif
+ void testWindowsVistaStyle();
+#ifndef QT_NO_STYLE_CLEANLOOKS
+ void testCleanlooksStyle();
+#endif
+ void testMacStyle();
+#ifdef Q_OS_WINCE
+ void testWindowsCEStyle();
+#endif
+#ifdef Q_OS_WINCE_WM
+ void testWindowsMobileStyle();
+#endif
+ void testStyleFactory();
+ void testProxyStyle();
+ void pixelMetric();
+#if !defined(QT_NO_STYLE_PLASTIQUE) && !defined(QT_NO_STYLE_WINDOWS)
+ void progressBarChangeStyle();
+#endif
+ void defaultFont();
+ void testDrawingShortcuts();
+private:
+ void lineUpLayoutTest(QStyle *);
+ QWidget *testWidget;
+};
+
+
+tst_QStyle::tst_QStyle()
+{
+ testWidget = 0;
+}
+
+tst_QStyle::~tst_QStyle()
+{
+}
+
+class MyWidget : public QWidget
+{
+public:
+ MyWidget( QWidget* QWidget=0, const char* name=0 );
+protected:
+ void paintEvent( QPaintEvent* );
+};
+
+void tst_QStyle::init()
+{
+ testWidget = new MyWidget( 0, "testObject");
+}
+
+void tst_QStyle::cleanup()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QStyle::initTestCase()
+{
+}
+
+void tst_QStyle::cleanupTestCase()
+{
+}
+
+void tst_QStyle::testStyleFactory()
+{
+ QStringList keys = QStyleFactory::keys();
+#ifndef QT_NO_STYLE_MOTIF
+ QVERIFY(keys.contains("Motif"));
+#endif
+#ifndef QT_NO_STYLE_CLEANLOOKS
+ QVERIFY(keys.contains("Cleanlooks"));
+#endif
+#ifndef QT_NO_STYLE_PLASTIQUE
+ QVERIFY(keys.contains("Plastique"));
+#endif
+#ifndef QT_NO_STYLE_CDE
+ QVERIFY(keys.contains("CDE"));
+#endif
+#ifndef QT_NO_STYLE_WINDOWS
+ QVERIFY(keys.contains("Windows"));
+#endif
+#ifndef QT_NO_STYLE_MOTIF
+ QVERIFY(keys.contains("Motif"));
+#endif
+#ifdef Q_WS_WIN
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP &&
+ QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ QVERIFY(keys.contains("WindowsXP"));
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA &&
+ QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ QVERIFY(keys.contains("WindowsVista"));
+#endif
+
+ foreach (QString styleName , keys) {
+ QStyle *style = QStyleFactory::create(styleName);
+ QVERIFY2(style != 0, qPrintable(QString::fromLatin1("Fail to load style '%1'").arg(styleName)));
+ delete style;
+ }
+}
+
+class CustomProxy : public QProxyStyle
+{
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption *option = 0,
+ const QWidget *widget = 0) const
+ {
+ if (metric == QStyle::PM_ButtonIconSize)
+ return 13;
+ return QProxyStyle::pixelMetric(metric, option, widget);
+ }
+};
+
+void tst_QStyle::testProxyStyle()
+{
+ QProxyStyle *proxyStyle = new QProxyStyle();
+ QVERIFY(proxyStyle->baseStyle());
+ QStyle *style = new QWindowsStyle;
+ QVERIFY(style->proxy() == style);
+
+ proxyStyle->setBaseStyle(style);
+ QVERIFY(style->proxy() == proxyStyle);
+ QVERIFY(style->parent() == proxyStyle);
+ QVERIFY(proxyStyle->baseStyle() == style);
+
+ testAllFunctions(proxyStyle);
+ proxyStyle->setBaseStyle(0);
+ QVERIFY(proxyStyle->baseStyle());
+ qApp->setStyle(proxyStyle);
+
+ QProxyStyle doubleProxy(new QProxyStyle(new QWindowsStyle()));
+ testAllFunctions(&doubleProxy);
+
+ CustomProxy customStyle;
+ QLineEdit edit;
+ edit.setStyle(&customStyle);
+ QVERIFY(!customStyle.parent());
+ QVERIFY(edit.style()->pixelMetric(QStyle::PM_ButtonIconSize) == 13);
+}
+
+void tst_QStyle::drawItemPixmap()
+{
+ testWidget->resize(300, 300);
+ testWidget->show();
+
+ QPixmap p(QString(SRCDIR) + "/task_25863.png", "PNG");
+ QPixmap actualPix = QPixmap::grabWidget(testWidget);
+
+ QVERIFY(pixmapsAreEqual(&actualPix,&p));
+ testWidget->hide();
+}
+
+void tst_QStyle::testAllFunctions(QStyle *style)
+{
+ QStyleOption opt;
+ opt.init(testWidget);
+
+ testWidget->setStyle(style);
+
+ //Tests styleHint with default arguments for potential crashes
+ for ( int hint = 0 ; hint < int(QStyle::SH_Menu_Mask); ++hint) {
+ style->styleHint(QStyle::StyleHint(hint));
+ style->styleHint(QStyle::StyleHint(hint), &opt, testWidget);
+ }
+
+ //Tests pixelMetric with default arguments for potential crashes
+ for ( int pm = 0 ; pm < int(QStyle::PM_LayoutVerticalSpacing); ++pm) {
+ style->pixelMetric(QStyle::PixelMetric(pm));
+ style->pixelMetric(QStyle::PixelMetric(pm), &opt, testWidget);
+ }
+
+ //Tests drawControl with default arguments for potential crashes
+ for ( int control = 0 ; control < int(QStyle::CE_ColumnViewGrip); ++control) {
+ QPixmap surface(QSize(200, 200));
+ QPainter painter(&surface);
+ style->drawControl(QStyle::ControlElement(control), &opt, &painter, 0);
+ }
+
+ //Tests drawComplexControl with default arguments for potential crashes
+ {
+ QPixmap surface(QSize(200, 200));
+ QPainter painter(&surface);
+ QStyleOptionComboBox copt1;
+ copt1.init(testWidget);
+
+ QStyleOptionGroupBox copt2;
+ copt2.init(testWidget);
+ QStyleOptionSizeGrip copt3;
+ copt3.init(testWidget);
+ QStyleOptionSlider copt4;
+ copt4.init(testWidget);
+ copt4.minimum = 0;
+ copt4.maximum = 100;
+ copt4.tickInterval = 25;
+ copt4.sliderValue = 50;
+ QStyleOptionSpinBox copt5;
+ copt5.init(testWidget);
+ QStyleOptionTitleBar copt6;
+ copt6.init(testWidget);
+ QStyleOptionToolButton copt7;
+ copt7.init(testWidget);
+ QStyleOptionComplex copt9;
+ copt9.initFrom(testWidget);
+
+ style->drawComplexControl(QStyle::CC_SpinBox, &copt5, &painter, 0);
+ style->drawComplexControl(QStyle::CC_ComboBox, &copt1, &painter, 0);
+ style->drawComplexControl(QStyle::CC_ScrollBar, &copt4, &painter, 0);
+ style->drawComplexControl(QStyle::CC_Slider, &copt4, &painter, 0);
+ style->drawComplexControl(QStyle::CC_ToolButton, &copt7, &painter, 0);
+ style->drawComplexControl(QStyle::CC_TitleBar, &copt6, &painter, 0);
+ style->drawComplexControl(QStyle::CC_GroupBox, &copt2, &painter, 0);
+ style->drawComplexControl(QStyle::CC_Dial, &copt4, &painter, 0);
+ }
+
+ //Check standard pixmaps/icons
+ for ( int i = 0 ; i < int(QStyle::SP_ToolBarVerticalExtensionButton); ++i) {
+ QPixmap pixmap = style->standardPixmap(QStyle::StandardPixmap(i));
+ if (pixmap.isNull()) {
+ qWarning("missing StandardPixmap: %d", i);
+ }
+ QIcon icn = style->standardIcon(QStyle::StandardPixmap(i));
+ if (icn.isNull()) {
+ qWarning("missing StandardIcon: %d", i);
+ }
+ }
+
+ style->itemPixmapRect(QRect(0, 0, 100, 100), Qt::AlignHCenter, QPixmap(200, 200));
+ style->itemTextRect(QFontMetrics(qApp->font()), QRect(0, 0, 100, 100), Qt::AlignHCenter, true, QString("Test"));
+
+ testScrollBarSubControls(style);
+}
+
+void tst_QStyle::testScrollBarSubControls(QStyle* style)
+{
+#ifdef Q_OS_WINCE_WM
+ if (qobject_cast<QWindowsMobileStyle*>(style) && qt_wince_is_smartphone())
+ QSKIP("SmartPhone doesn't have scrollbar subcontrols.", SkipAll);
+#else
+ Q_UNUSED(style);
+#endif
+
+ QScrollBar scrollBar;
+ scrollBar.show();
+ const QStyleOptionSlider opt = qt_qscrollbarStyleOption(&scrollBar);
+ foreach (int subControl, QList<int>() << 1 << 2 << 4 << 8) {
+ QRect sr = testWidget->style()->subControlRect(QStyle::CC_ScrollBar, &opt,
+ QStyle::SubControl(subControl), &scrollBar);
+ QVERIFY(sr.isNull() == false);
+ }
+}
+
+#ifndef QT_NO_STYLE_PLASTIQUE
+void tst_QStyle::testPlastiqueStyle()
+{
+ QPlastiqueStyle pstyle;
+ testAllFunctions(&pstyle);
+ lineUpLayoutTest(&pstyle);
+}
+#endif
+
+#ifndef QT_NO_STYLE_CLEANLOOKS
+void tst_QStyle::testCleanlooksStyle()
+{
+ QCleanlooksStyle cstyle;
+ testAllFunctions(&cstyle);
+ lineUpLayoutTest(&cstyle);
+}
+#endif
+
+void tst_QStyle::testWindowsStyle()
+{
+ QWindowsStyle wstyle;
+ testAllFunctions(&wstyle);
+ lineUpLayoutTest(&wstyle);
+
+ // Tests drawing indeterminate progress with 0 size: QTBUG-15973
+ QStyleOptionProgressBar pb;
+ pb.rect = QRect(0,0,-9,0);
+ QPixmap surface(QSize(200, 200));
+ QPainter painter(&surface);
+ wstyle.drawControl(QStyle::CE_ProgressBar, &pb, &painter, 0);
+}
+
+#if defined(Q_WS_WIN) && !defined(QT_NO_STYLE_WINDOWSXP)
+void tst_QStyle::testWindowsXPStyle()
+{
+ QWindowsXPStyle xpstyle;
+ testAllFunctions(&xpstyle);
+ lineUpLayoutTest(&xpstyle);
+}
+#endif
+
+void writeImage(const QString &fileName, QImage image)
+{
+ QImageWriter imageWriter(fileName);
+ imageWriter.setFormat("png");
+ qDebug() << "result " << imageWriter.write(image);
+}
+
+QImage readImage(const QString &fileName)
+{
+ QImageReader reader(fileName);
+ return reader.read();
+}
+
+
+void tst_QStyle::testWindowsVistaStyle()
+{
+#if defined(Q_WS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA)
+ QWindowsVistaStyle vistastyle;
+ testAllFunctions(&vistastyle);
+
+ if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA)
+ testPainting(&vistastyle, "vista");
+ else if (QSysInfo::WindowsVersion == QSysInfo::WV_XP)
+ testPainting(&vistastyle, "xp");
+#endif
+}
+
+void comparePixmap(const QString &filename, const QPixmap &pixmap)
+{
+ QImage oldFile = readImage(filename);
+ QPixmap oldPixmap = QPixmap::fromImage(oldFile);
+ if (!oldFile.isNull())
+ QVERIFY(pixmapsAreEqual(&pixmap, &oldPixmap));
+ else
+ writeImage(filename, pixmap.toImage());
+}
+
+void tst_QStyle::testPainting(QStyle *style, const QString &platform)
+{
+qDebug("TEST PAINTING");
+ //Test Menu
+ QString fileName = "images/" + platform + "/menu.png";
+ QMenu menu;
+ menu.setStyle(style);
+ menu.show();
+ menu.addAction(new QAction("Test 1", &menu));
+ menu.addAction(new QAction("Test 2", &menu));
+ QPixmap pixmap = QPixmap::grabWidget(&menu);
+ comparePixmap(fileName, pixmap);
+
+ //Push button
+ fileName = "images/" + platform + "/button.png";
+ QPushButton button("OK");
+ button.setStyle(style);
+ button.show();
+ pixmap = QPixmap::grabWidget(&button);
+ button.hide();
+ comparePixmap(fileName, pixmap);
+
+ //Push button
+ fileName = "images/" + platform + "/radiobutton.png";
+ QRadioButton radiobutton("Check");
+ radiobutton.setStyle(style);
+ radiobutton.show();
+ pixmap = QPixmap::grabWidget(&radiobutton);
+ radiobutton.hide();
+ comparePixmap(fileName, pixmap);
+
+ //Combo box
+ fileName = "images/" + platform + "/combobox.png";
+ QComboBox combobox;
+ combobox.setStyle(style);
+ combobox.addItem("Test 1");
+ combobox.addItem("Test 2");
+ combobox.show();
+ pixmap = QPixmap::grabWidget(&combobox);
+ combobox.hide();
+ comparePixmap(fileName, pixmap);
+
+ //Spin box
+ fileName = "images/" + platform + "/spinbox.png";
+ QDoubleSpinBox spinbox;
+ spinbox.setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
+ spinbox.setStyle(style);
+ spinbox.show();
+ pixmap = QPixmap::grabWidget(&spinbox);
+ spinbox.hide();
+ comparePixmap(fileName, pixmap);
+ QLocale::setDefault(QLocale::system());
+
+ //Slider
+ fileName = "images/" + platform + "/slider.png";
+ QSlider slider;
+ slider.setStyle(style);
+ slider.show();
+ pixmap = QPixmap::grabWidget(&slider);
+ slider.hide();
+ comparePixmap(fileName, pixmap);
+
+ //Line edit
+ fileName = "images/" + platform + "/lineedit.png";
+ QLineEdit lineedit("Test text");
+ lineedit.setStyle(style);
+ lineedit.show();
+ pixmap = QPixmap::grabWidget(&lineedit);
+ lineedit.hide();
+ comparePixmap(fileName, pixmap);
+
+ //MDI
+ fileName = "images/" + platform + "/mdi.png";
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget(&mdiArea));
+ mdiArea.resize(200, 200);
+ mdiArea.setStyle(style);
+ mdiArea.show();
+ pixmap = QPixmap::grabWidget(&mdiArea);
+ mdiArea.hide();
+ comparePixmap(fileName, pixmap);
+
+ // QToolButton
+ fileName = "images/" + platform + "/toolbutton.png";
+ QToolButton tb;
+ tb.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ tb.setText("AaQqPpXx");
+ tb.setIcon(style->standardPixmap(QStyle::SP_DirHomeIcon));
+ tb.setStyle(style);
+ tb.show();
+ pixmap = QPixmap::grabWidget(&tb);
+ tb.hide();
+ comparePixmap(fileName, pixmap);
+
+}
+
+void tst_QStyle::testMacStyle()
+{
+#ifdef Q_WS_MAC
+ QMacStyle mstyle;
+ testAllFunctions(&mstyle);
+#endif
+}
+
+#ifndef QT_NO_STYLE_MOTIF
+void tst_QStyle::testMotifStyle()
+{
+ QMotifStyle mstyle;
+ testAllFunctions(&mstyle);
+}
+#endif
+
+#ifndef QT_NO_STYLE_CDE
+void tst_QStyle::testCDEStyle()
+{
+ QCDEStyle cstyle;
+ testAllFunctions(&cstyle);
+}
+#endif
+
+#ifdef Q_OS_WINCE
+void tst_QStyle::testWindowsCEStyle()
+{
+ QWindowsCEStyle cstyle;
+ testAllFunctions(&cstyle);
+}
+#endif
+
+#ifdef Q_OS_WINCE_WM
+void tst_QStyle::testWindowsMobileStyle()
+{
+ QWindowsMobileStyle cstyle;
+ testAllFunctions(&cstyle);
+}
+#endif
+
+// Helper class...
+
+MyWidget::MyWidget( QWidget* parent, const char* name )
+ : QWidget( parent )
+{
+ setObjectName(name);
+}
+
+void MyWidget::paintEvent( QPaintEvent* )
+{
+ QPainter p(this);
+ QPixmap big(400,400);
+ big.fill(Qt::green);
+ style()->drawItemPixmap(&p, rect(), Qt::AlignCenter, big);
+}
+
+
+class Qt42Style : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ Qt42Style() : QWindowsStyle()
+ {
+ margin_toplevel = 10;
+ margin = 5;
+ spacing = 0;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int margin_toplevel;
+ int margin;
+ int spacing;
+
+};
+
+int Qt42Style::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case QStyle::PM_DefaultTopLevelMargin:
+ return margin_toplevel;
+ break;
+ case QStyle::PM_DefaultChildMargin:
+ return margin;
+ break;
+ case QStyle::PM_DefaultLayoutSpacing:
+ return spacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+
+void tst_QStyle::pixelMetric()
+{
+ Qt42Style *style = new Qt42Style();
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultTopLevelMargin), 10);
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultChildMargin), 5);
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultLayoutSpacing), 0);
+
+ style->margin_toplevel = 0;
+ style->margin = 0;
+ style->spacing = 0;
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultTopLevelMargin), 0);
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultChildMargin), 0);
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultLayoutSpacing), 0);
+
+ style->margin_toplevel = -1;
+ style->margin = -1;
+ style->spacing = -1;
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultTopLevelMargin), -1);
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultChildMargin), -1);
+ QCOMPARE(style->pixelMetric(QStyle::PM_DefaultLayoutSpacing), -1);
+
+ delete style;
+}
+
+#if !defined(QT_NO_STYLE_PLASTIQUE) && !defined(QT_NO_STYLE_WINDOWS)
+void tst_QStyle::progressBarChangeStyle()
+{
+ //test a crashing situation (task 143530)
+ //where changing the styles and deleting a progressbar would crash
+
+ QWindowsStyle style1;
+ QPlastiqueStyle style2;
+
+ QProgressBar *progress=new QProgressBar;
+ progress->setStyle(&style1);
+
+ progress->show();
+
+ progress->setStyle(&style2);
+
+ QTest::qWait(100);
+ delete progress;
+
+ QTest::qWait(100);
+
+ //before the correction, there would be a crash here
+}
+#endif
+
+void tst_QStyle::lineUpLayoutTest(QStyle *style)
+{
+ QWidget widget;
+ QHBoxLayout layout;
+ QFont font;
+ font.setPointSize(9); //Plastique is lined up for odd numbers...
+ widget.setFont(font);
+ QSpinBox spinbox(&widget);
+ QLineEdit lineedit(&widget);
+ QComboBox combo(&widget);
+ combo.setEditable(true);
+ layout.addWidget(&spinbox);
+ layout.addWidget(&lineedit);
+ layout.addWidget(&combo);
+ widget.setLayout(&layout);
+ widget.setStyle(style);
+ // propagate the style.
+ foreach (QWidget *w, qFindChildren<QWidget *>(&widget))
+ w->setStyle(style);
+ widget.show();
+ QTest::qWait( 500 );
+
+ QVERIFY(qAbs(spinbox.height() - lineedit.height()) <= 1);
+ QVERIFY(qAbs(spinbox.height() - combo.height()) <= 1);
+}
+
+void tst_QStyle::defaultFont()
+{
+ QFont defaultFont = qApp->font();
+ QFont pointFont = defaultFont;
+ pointFont.setPixelSize(9);
+ qApp->setFont(pointFont);
+ QPushButton button;
+ button.show();
+ qApp->processEvents();
+ qApp->setFont(defaultFont);
+}
+
+class DrawTextStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ DrawTextStyle(QStyle *base = 0) : QProxyStyle(), alignment(0) { setBaseStyle(base); }
+ void drawItemText(QPainter *painter, const QRect &rect,
+ int flags, const QPalette &pal, bool enabled,
+ const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const
+ {
+ DrawTextStyle *that = (DrawTextStyle *)this;
+ that->alignment = flags;
+ QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
+ }
+ int alignment;
+};
+
+void tst_QStyle::testDrawingShortcuts()
+{
+ {
+ QWidget w;
+ QToolButton *tb = new QToolButton(&w);
+ tb->setText("&abc");
+ DrawTextStyle *dts = new DrawTextStyle;
+ w.show();
+ tb->setStyle(dts);
+ QPixmap::grabWidget(tb);
+ QStyleOptionToolButton sotb;
+ sotb.initFrom(tb);
+ bool showMnemonic = dts->styleHint(QStyle::SH_UnderlineShortcut, &sotb, tb);
+ QVERIFY(dts->alignment & (showMnemonic ? Qt::TextShowMnemonic : Qt::TextHideMnemonic));
+ delete dts;
+ }
+ {
+ QToolBar w;
+ QToolButton *tb = new QToolButton(&w);
+ tb->setText("&abc");
+ DrawTextStyle *dts = new DrawTextStyle;
+ w.addWidget(tb);
+ w.show();
+ tb->setStyle(dts);
+ QPixmap::grabWidget(tb);
+ QStyleOptionToolButton sotb;
+ sotb.initFrom(tb);
+ bool showMnemonic = dts->styleHint(QStyle::SH_UnderlineShortcut, &sotb, tb);
+ QVERIFY(dts->alignment & (showMnemonic ? Qt::TextShowMnemonic : Qt::TextHideMnemonic));
+ delete dts;
+ }
+}
+
+QTEST_MAIN(tst_QStyle)
+#include "tst_qstyle.moc"
diff --git a/tests/auto/widgets/styles/qstyleoption/.gitignore b/tests/auto/widgets/styles/qstyleoption/.gitignore
new file mode 100644
index 0000000000..70bf7781ce
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyleoption/.gitignore
@@ -0,0 +1 @@
+tst_qstyleoption
diff --git a/tests/auto/widgets/styles/qstyleoption/qstyleoption.pro b/tests/auto/widgets/styles/qstyleoption/qstyleoption.pro
new file mode 100644
index 0000000000..ccbb39d55b
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyleoption/qstyleoption.pro
@@ -0,0 +1,11 @@
+######################################################################
+# Automatically generated by qmake (2.00a) ti 8. mar 16:20:21 2005
+######################################################################
+
+load(qttest_p4)
+TEMPLATE = app
+QT += widgets
+# Input
+SOURCES += tst_qstyleoption.cpp
+
+
diff --git a/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp b/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp
new file mode 100644
index 0000000000..c1d4bd8166
--- /dev/null
+++ b/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QStyleOption>
+
+
+class tst_QStyleOption: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void qstyleoptioncast_data();
+ void qstyleoptioncast();
+ void copyconstructors();
+};
+
+// Just a simple container for QStyleOption-pointer
+struct StyleOptionPointerBase
+{
+ QStyleOption *pointer;
+
+ StyleOptionPointerBase(QStyleOption *p = 0) : pointer(p) { }
+
+ virtual ~StyleOptionPointerBase() { pointer = 0; }
+};
+
+template <typename T>
+struct StyleOptionPointer: public StyleOptionPointerBase
+{
+ StyleOptionPointer(T *p = 0): StyleOptionPointerBase(p) {}
+ ~StyleOptionPointer() { delete static_cast<T *>(pointer); pointer = 0; }
+};
+
+Q_DECLARE_METATYPE(StyleOptionPointerBase*)
+
+template <typename T>
+inline StyleOptionPointerBase *stylePtr(T *ptr) { return new StyleOptionPointer<T>(ptr); }
+
+void tst_QStyleOption::qstyleoptioncast_data()
+{
+ QTest::addColumn<StyleOptionPointerBase *>("testOption");
+ QTest::addColumn<bool>("canCastToComplex");
+ QTest::addColumn<int>("type");
+
+ QTest::newRow("optionDefault") << stylePtr(new QStyleOption) << false << int(QStyleOption::SO_Default);
+ QTest::newRow("optionButton") << stylePtr(new QStyleOptionButton) << false << int(QStyleOption::SO_Button);
+ QTest::newRow("optionComboBox") << stylePtr(new QStyleOptionComboBox) << true << int(QStyleOption::SO_ComboBox);
+ QTest::newRow("optionComplex") << stylePtr(new QStyleOptionComplex) << true << int(QStyleOption::SO_Complex);
+ QTest::newRow("optionDockWidget") << stylePtr(new QStyleOptionDockWidget) << false << int(QStyleOption::SO_DockWidget);
+ QTest::newRow("optionFocusRect") << stylePtr(new QStyleOptionFocusRect) << false << int(QStyleOption::SO_FocusRect);
+ QTest::newRow("optionFrame") << stylePtr(new QStyleOptionFrame) << false << int(QStyleOption::SO_Frame);
+ QTest::newRow("optionHeader") << stylePtr(new QStyleOptionHeader) << false << int(QStyleOption::SO_Header);
+ QTest::newRow("optionMenuItem") << stylePtr(new QStyleOptionMenuItem) << false << int(QStyleOption::SO_MenuItem);
+ QTest::newRow("optionProgressBar") << stylePtr(new QStyleOptionProgressBar) << false << int(QStyleOption::SO_ProgressBar);
+ QTest::newRow("optionSlider") << stylePtr(new QStyleOptionSlider) << true << int(QStyleOption::SO_Slider);
+ QTest::newRow("optionSpinBox") << stylePtr(new QStyleOptionSpinBox) << true << int(QStyleOption::SO_SpinBox);
+ QTest::newRow("optionTab") << stylePtr(new QStyleOptionTab) << false << int(QStyleOption::SO_Tab);
+ QTest::newRow("optionTitleBar") << stylePtr(new QStyleOptionTitleBar) << true << int(QStyleOption::SO_TitleBar);
+ QTest::newRow("optionToolBox") << stylePtr(new QStyleOptionToolBox) << false << int(QStyleOption::SO_ToolBox);
+ QTest::newRow("optionToolButton") << stylePtr(new QStyleOptionToolButton) << true << int(QStyleOption::SO_ToolButton);
+ QTest::newRow("optionViewItem") << stylePtr(new QStyleOptionViewItem) << false << int(QStyleOption::SO_ViewItem);
+ QTest::newRow("optionGraphicsItem") << stylePtr(new QStyleOptionGraphicsItem) << false << int(QStyleOption::SO_GraphicsItem);
+}
+
+void tst_QStyleOption::qstyleoptioncast()
+{
+ QFETCH(StyleOptionPointerBase *, testOption);
+ QFETCH(bool, canCastToComplex);
+ QFETCH(int, type);
+
+ QVERIFY(testOption->pointer != 0);
+
+ QCOMPARE(testOption->pointer->type, type);
+
+ // Cast to common base class
+ QStyleOption *castOption = qstyleoption_cast<QStyleOption*>(testOption->pointer);
+ QVERIFY(castOption != 0);
+
+ // Cast to complex base class
+ castOption = qstyleoption_cast<QStyleOptionComplex*>(testOption->pointer);
+ QCOMPARE(canCastToComplex, (castOption != 0));
+
+ // Cast to combo box
+ castOption = qstyleoption_cast<QStyleOptionComboBox*>(testOption->pointer);
+ QCOMPARE((castOption != 0),(testOption->pointer->type == QStyleOption::SO_ComboBox));
+
+ // Cast to button
+ castOption = qstyleoption_cast<QStyleOptionButton*>(testOption->pointer);
+ QCOMPARE((castOption != 0),(testOption->pointer->type == QStyleOption::SO_Button));
+
+ // Cast to lower version
+ testOption->pointer->version += 1;
+ castOption = qstyleoption_cast<QStyleOption*>(testOption->pointer);
+ QVERIFY(castOption);
+
+ // Cast a null pointer
+ castOption = qstyleoption_cast<QStyleOption*>((QStyleOption*)0);
+ QCOMPARE(castOption,(QStyleOption*)0);
+
+ // Deallocate
+ delete testOption;
+}
+
+void tst_QStyleOption::copyconstructors()
+{
+ QStyleOptionFrame frame;
+ QStyleOptionFrameV2 frame2(frame);
+ QCOMPARE(frame2.version, int(QStyleOptionFrameV2::Version));
+ frame2 = frame;
+ QCOMPARE(frame2.version, int(QStyleOptionFrameV2::Version));
+
+ QStyleOptionProgressBar bar;
+ QStyleOptionProgressBarV2 bar2(bar);
+ QCOMPARE(bar2.version, int(QStyleOptionProgressBarV2::Version));
+ bar2 = bar;
+ QCOMPARE(bar2.version, int(QStyleOptionProgressBarV2::Version));
+}
+
+QTEST_MAIN(tst_QStyleOption)
+#include "tst_qstyleoption.moc"
+
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/.gitignore b/tests/auto/widgets/styles/qstylesheetstyle/.gitignore
new file mode 100644
index 0000000000..df0251385e
--- /dev/null
+++ b/tests/auto/widgets/styles/qstylesheetstyle/.gitignore
@@ -0,0 +1 @@
+tst_qstylesheetstyle
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png
new file mode 100644
index 0000000000..06fb34f0d6
--- /dev/null
+++ b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro b/tests/auto/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro
new file mode 100644
index 0000000000..9dc296a51c
--- /dev/null
+++ b/tests/auto/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += gui-private
+# Input
+SOURCES += tst_qstylesheetstyle.cpp
+RESOURCES += resources.qrc
+requires(contains(QT_CONFIG,private_tests))
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc b/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc
new file mode 100644
index 0000000000..248bf80f50
--- /dev/null
+++ b/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>images/testimage.png</file>
+ </qresource>
+</RCC> \ No newline at end of file
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
new file mode 100644
index 0000000000..c5591c48ab
--- /dev/null
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -0,0 +1,1644 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore>
+#include <QtGui>
+#include <QtWidgets>
+#include <QtTest/QtTest>
+#include <QtDebug>
+#include <QMetaObject>
+
+#include <private/qstylesheetstyle_p.h>
+#include "../../../platformquirks.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QStyleSheetStyle : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QStyleSheetStyle();
+ ~tst_QStyleSheetStyle();
+
+private slots:
+ void repolish();
+ void numinstances();
+ void widgetsBeforeAppStyleSheet();
+ void widgetsAfterAppStyleSheet();
+ void applicationStyleSheet();
+ void windowStyleSheet();
+ void widgetStyleSheet();
+ void reparentWithNoChildStyleSheet();
+ void reparentWithChildStyleSheet();
+ void dynamicProperty();
+ // NB! Invoking this slot after layoutSpacing crashes on Mac.
+ void namespaces();
+#ifdef Q_OS_MAC
+ void layoutSpacing();
+#endif
+ void qproperty();
+ void palettePropagation();
+ void fontPropagation();
+ void onWidgetDestroyed();
+ void fontPrecedence();
+#if defined(Q_OS_WIN32) || defined(Q_OS_MAC) || (defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
+ void focusColors();
+#endif
+ void hoverColors();
+ void background();
+ void tabAlignement();
+ void attributesList();
+ void minmaxSizes();
+ void task206238_twice();
+ void transparent();
+ void proxyStyle();
+ void dialogButtonBox();
+ void emptyStyleSheet();
+ void toolTip();
+ void embeddedFonts();
+ void opaquePaintEvent_data();
+ void opaquePaintEvent();
+ void complexWidgetFocus();
+ void task188195_baseBackground();
+ void task232085_spinBoxLineEditBg();
+ void changeStyleInChangeEvent();
+ void QTBUG15910_crashNullWidget();
+
+ //at the end because it mess with the style.
+ void widgetStyle();
+ void appStyle();
+ void QTBUG11658_cachecrash();
+private:
+ QColor COLOR(const QWidget& w) {
+ w.ensurePolished();
+ return w.palette().color(w.foregroundRole());
+ }
+ QColor APPCOLOR(const QWidget& w) {
+ w.ensurePolished();
+ return qApp->palette(&w).color(w.foregroundRole());
+ }
+ QColor BACKGROUND(const QWidget& w) {
+ w.ensurePolished();
+ return w.palette().color(w.backgroundRole());
+ }
+ QColor APPBACKGROUND(const QWidget& w) {
+ w.ensurePolished();
+ return qApp->palette(&w).color(w.backgroundRole());
+ }
+ int FONTSIZE(const QWidget &w) {
+ w.ensurePolished();
+ return w.font().pointSize();
+ }
+ int APPFONTSIZE(const QWidget &w) {
+ return qApp->font(&w).pointSize();
+ }
+};
+
+tst_QStyleSheetStyle::tst_QStyleSheetStyle()
+{
+}
+
+tst_QStyleSheetStyle::~tst_QStyleSheetStyle()
+{
+}
+
+void tst_QStyleSheetStyle::numinstances()
+{
+ QWidget w;
+ QCommonStyle *style = new QCommonStyle;
+ style->setParent(&w);
+ QWidget c(&w);
+ w.show();
+
+ // set and unset application stylesheet
+ QCOMPARE(QStyleSheetStyle::numinstances, 0);
+ qApp->setStyleSheet("* { color: red; }");
+ QCOMPARE(QStyleSheetStyle::numinstances, 1);
+ qApp->setStyleSheet("");
+ QCOMPARE(QStyleSheetStyle::numinstances, 0);
+
+ // set and unset application stylesheet+widget
+ qApp->setStyleSheet("* { color: red; }");
+ w.setStyleSheet("color: red;");
+ QCOMPARE(QStyleSheetStyle::numinstances, 2);
+ w.setStyle(style);
+ QCOMPARE(QStyleSheetStyle::numinstances, 2);
+ qApp->setStyleSheet("");
+ QCOMPARE(QStyleSheetStyle::numinstances, 1);
+ w.setStyleSheet("");
+ QCOMPARE(QStyleSheetStyle::numinstances, 0);
+
+ // set and unset widget stylesheet
+ w.setStyle(0);
+ w.setStyleSheet("color: red");
+ QCOMPARE(QStyleSheetStyle::numinstances, 1);
+ c.setStyle(style);
+ QCOMPARE(QStyleSheetStyle::numinstances, 2);
+ w.setStyleSheet("");
+ QCOMPARE(QStyleSheetStyle::numinstances, 0);
+}
+
+void tst_QStyleSheetStyle::widgetsBeforeAppStyleSheet()
+{
+ QPushButton w1; // widget with no stylesheet
+ qApp->setStyleSheet("* { color: red; }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+ w1.setStyleSheet("color: white");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ qApp->setStyleSheet("");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ w1.setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+}
+
+class FriendlySpinBox : public QSpinBox { friend class tst_QStyleSheetStyle; };
+
+void tst_QStyleSheetStyle::widgetsAfterAppStyleSheet()
+{
+ qApp->setStyleSheet("* { color: red; font-size: 32pt; }");
+ QPushButton w1;
+ FriendlySpinBox spin;
+ QVERIFY(COLOR(w1) == QColor("red"));
+ QVERIFY(COLOR(spin) == QColor("red"));
+ QVERIFY(COLOR(*spin.lineEdit()) == QColor("red"));
+ QCOMPARE(FONTSIZE(w1), 32);
+ QCOMPARE(FONTSIZE(spin), 32);
+ QCOMPARE(FONTSIZE(*spin.lineEdit()), 32);
+ w1.setStyleSheet("color: white");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ QVERIFY(COLOR(spin) == QColor("red"));
+ QVERIFY(COLOR(*spin.lineEdit()) == QColor("red"));
+ w1.setStyleSheet("");
+ QVERIFY(COLOR(w1) == QColor("red"));
+ QVERIFY(COLOR(spin) == QColor("red"));
+ QVERIFY(COLOR(*spin.lineEdit()) == QColor("red"));
+ w1.setStyleSheet("color: white");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ qApp->setStyleSheet("");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ QVERIFY(COLOR(spin) == APPCOLOR(spin));
+ QVERIFY(COLOR(*spin.lineEdit()) == APPCOLOR(*spin.lineEdit()));
+ w1.setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+ // QCOMPARE(FONTSIZE(w1), APPFONTSIZE(w1)); //### task 244261
+ QCOMPARE(FONTSIZE(spin), APPFONTSIZE(spin));
+ //QCOMPARE(FONTSIZE(*spin.lineEdit()), APPFONTSIZE(*spin.lineEdit())); //### task 244261
+}
+
+void tst_QStyleSheetStyle::applicationStyleSheet()
+{
+ QPushButton w1;
+ qApp->setStyleSheet("* { color: red; }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+ qApp->setStyleSheet("* { color: white; }");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ qApp->setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+ qApp->setStyleSheet("* { color: red }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+}
+
+void tst_QStyleSheetStyle::windowStyleSheet()
+{
+ QPushButton w1;
+ qApp->setStyleSheet("");
+ w1.setStyleSheet("* { color: red; }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+ w1.setStyleSheet("* { color: white; }");
+ QVERIFY(COLOR(w1) == QColor("white"));
+ w1.setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+ w1.setStyleSheet("* { color: red }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+
+ qApp->setStyleSheet("* { color: green }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+ w1.setStyleSheet("");
+ QVERIFY(COLOR(w1) == QColor("green"));
+ qApp->setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+}
+
+void tst_QStyleSheetStyle::widgetStyleSheet()
+{
+ QPushButton w1;
+ QPushButton *pb = new QPushButton(&w1);
+ QPushButton &w2 = *pb;
+
+ qApp->setStyleSheet("");
+ w1.setStyleSheet("* { color: red }");
+ QVERIFY(COLOR(w1) == QColor("red"));
+ QVERIFY(COLOR(w2) == QColor("red"));
+
+ w2.setStyleSheet("* { color: white }");
+ QVERIFY(COLOR(w2) == QColor("white"));
+
+ w1.setStyleSheet("* { color: blue }");
+ QVERIFY(COLOR(w1) == QColor("blue"));
+ QVERIFY(COLOR(w2) == QColor("white"));
+
+ w1.setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+ QVERIFY(COLOR(w2) == QColor("white"));
+
+ w2.setStyleSheet("");
+ QVERIFY(COLOR(w1) == APPCOLOR(w1));
+ QVERIFY(COLOR(w2) == APPCOLOR(w2));
+}
+
+void tst_QStyleSheetStyle::reparentWithNoChildStyleSheet()
+{
+ QPushButton p1, p2;
+ QPushButton *pb = new QPushButton(&p1);
+ QPushButton &c1 = *pb; // child with no stylesheet
+
+ qApp->setStyleSheet("");
+ p1.setStyleSheet("* { color: red }");
+ QVERIFY(COLOR(c1) == QColor("red"));
+ c1.setParent(&p2);
+ QVERIFY(COLOR(c1) == APPCOLOR(c1));
+
+ p2.setStyleSheet("* { color: white }");
+ QVERIFY(COLOR(c1) == QColor("white"));
+
+ c1.setParent(&p1);
+ QVERIFY(COLOR(c1) == QColor("red"));
+
+ qApp->setStyleSheet("* { color: blue }");
+ c1.setParent(0);
+ QVERIFY(COLOR(c1) == QColor("blue"));
+ delete pb;
+}
+
+void tst_QStyleSheetStyle::reparentWithChildStyleSheet()
+{
+ qApp->setStyleSheet("");
+ QPushButton p1, p2;
+ QPushButton *pb = new QPushButton(&p1);
+ QPushButton &c1 = *pb;
+
+ c1.setStyleSheet("background: gray");
+ QVERIFY(BACKGROUND(c1) == QColor("gray"));
+ c1.setParent(&p2);
+ QVERIFY(BACKGROUND(c1) == QColor("gray"));
+
+ qApp->setStyleSheet("* { color: white }");
+ c1.setParent(&p1);
+ QVERIFY(BACKGROUND(c1) == QColor("gray"));
+ QVERIFY(COLOR(c1) == QColor("white"));
+}
+
+void tst_QStyleSheetStyle::repolish()
+{
+ qApp->setStyleSheet("");
+ QPushButton p1;
+ p1.setStyleSheet("color: red; background: white");
+ QVERIFY(BACKGROUND(p1) == QColor("white"));
+ p1.setStyleSheet("background: white");
+ QVERIFY(COLOR(p1) == APPCOLOR(p1));
+ p1.setStyleSheet("color: red");
+ QVERIFY(COLOR(p1) == QColor("red"));
+ QVERIFY(BACKGROUND(p1) == APPBACKGROUND(p1));
+ p1.setStyleSheet("");
+ QVERIFY(COLOR(p1) == APPCOLOR(p1));
+ QVERIFY(BACKGROUND(p1) == APPBACKGROUND(p1));
+}
+
+void tst_QStyleSheetStyle::widgetStyle()
+{
+ qApp->setStyleSheet("");
+
+ QWidget *window1 = new QWidget;
+ window1->setObjectName("window1");
+ QWidget *widget1 = new QWidget(window1);
+ widget1->setObjectName("widget1");
+ QWidget *widget2 = new QWidget;
+ widget2->setObjectName("widget2");
+ QWidget *window2 = new QWidget;
+ window2->setObjectName("window2");
+ window1->ensurePolished();
+ window2->ensurePolished();
+ widget1->ensurePolished();
+ widget2->ensurePolished();
+
+ QWindowsStyle style1, style2;
+ QPointer<QStyle> pstyle1 = &style1;
+ QPointer<QStyle> pstyle2 = &style2;
+
+ QStyle *appStyle = qApp->style();
+
+ // Sanity: By default, a window inherits the application style
+ QCOMPARE(appStyle, window1->style());
+
+ // Setting a custom style on a widget
+ window1->setStyle(&style1);
+ QCOMPARE(static_cast<QStyle *>(&style1), window1->style());
+
+ // Setting another style must not delete the older style
+ window1->setStyle(&style2);
+ QCOMPARE(static_cast<QStyle *>(&style2), window1->style());
+ QVERIFY(!pstyle1.isNull()); // case we have not already crashed
+
+ // Setting null style must make it follow the qApp style
+ window1->setStyle(0);
+ QCOMPARE(window1->style(), appStyle);
+ QVERIFY(!pstyle2.isNull()); // case we have not already crashed
+ QVERIFY(!pstyle2.isNull()); // case we have not already crashed
+
+ // Sanity: Set the stylesheet
+ window1->setStyleSheet(":x { }");
+
+ QPointer<QStyleSheetStyle> proxy = (QStyleSheetStyle *)window1->style();
+ QVERIFY(!proxy.isNull());
+ QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle"); // must be our proxy
+ QVERIFY(proxy->base == 0); // and follows the application
+
+ // Set the stylesheet
+ window1->setStyle(&style1);
+ QVERIFY(proxy.isNull()); // we create a new one each time
+ proxy = (QStyleSheetStyle *)window1->style();
+ QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle"); // it is a proxy
+ QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(&style1)); // must have been replaced with the new one
+
+ // Update the stylesheet and check nothing changes
+ window1->setStyleSheet(":y { }");
+ QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // it is a proxy
+ QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(&style1)); // the same guy
+
+ // Remove the stylesheet
+ proxy = (QStyleSheetStyle *)window1->style();
+ window1->setStyleSheet("");
+ QVERIFY(proxy.isNull()); // should have disappeared
+ QCOMPARE(window1->style(), static_cast<QStyle *>(&style1)); // its restored
+
+ // Style Sheet existing children propagation
+ window1->setStyleSheet(":z { }");
+ proxy = (QStyleSheetStyle *)window1->style();
+ QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle");
+ QCOMPARE(window1->style(), widget1->style()); // proxy must have propagated
+ QCOMPARE(widget2->style(), appStyle); // widget2 is following the app style
+
+ // Style Sheet automatic propagation to new children
+ widget2->setParent(window1); // reparent in!
+ QCOMPARE(window1->style(), widget2->style()); // proxy must have propagated
+
+ // Style Sheet automatic removal from children who abandoned their parents
+ window2->setStyle(&style2);
+ widget2->setParent(window2); // reparent
+ QCOMPARE(widget2->style(), appStyle); // widget2 is following the app style
+
+ // Style Sheet propagation on a child widget with a custom style
+ widget2->setStyle(&style1);
+ window2->setStyleSheet(":x { }");
+ proxy = (QStyleSheetStyle *)widget2->style();
+ QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle");
+ QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(&style1));
+
+ // Style Sheet propagation on a child widget with a custom style already set
+ window2->setStyleSheet("");
+ QCOMPARE(window2->style(), static_cast<QStyle *>(&style2));
+ QCOMPARE(widget2->style(), static_cast<QStyle *>(&style1));
+ widget2->setStyle(0);
+ window2->setStyleSheet(":x { }");
+ widget2->setStyle(&style1);
+ proxy = (QStyleSheetStyle *)widget2->style();
+ QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle");
+
+ // QApplication, QWidget both having a style sheet
+
+ // clean everything out
+ window1->setStyle(0);
+ window1->setStyleSheet("");
+ window2->setStyle(0);
+ window2->setStyleSheet("");
+ qApp->setStyle(0);
+
+ qApp->setStyleSheet("may_insanity_prevail { }"); // app has stylesheet
+ QCOMPARE(window1->style(), qApp->style());
+ QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle");
+ QCOMPARE(widget1->style()->metaObject()->className(), "QStyleSheetStyle"); // check the child
+ window1->setStyleSheet("may_more_insanity_prevail { }"); // window has stylesheet
+ QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // a new one
+ QCOMPARE(widget1->style(), window1->style()); // child follows...
+ proxy = (QStyleSheetStyle *) window1->style();
+ QWindowsStyle *newStyle = new QWindowsStyle;
+ qApp->setStyle(newStyle); // set a custom style on app
+ proxy = (QStyleSheetStyle *) window1->style();
+ QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(newStyle)); // magic ;) the widget still follows the application
+ QCOMPARE(static_cast<QStyle *>(proxy), widget1->style()); // child still follows...
+
+ window1->setStyleSheet(""); // remove stylesheet
+ QCOMPARE(window1->style(), qApp->style()); // is this cool or what
+ QCOMPARE(widget1->style(), qApp->style()); // annoying child follows...
+ QWindowsStyle wndStyle;
+ window1->setStyle(&wndStyle);
+ QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // auto wraps it
+ QCOMPARE(widget1->style(), window1->style()); // and auto propagates to child
+ qApp->setStyleSheet(""); // remove the app stylesheet
+ QCOMPARE(window1->style(), static_cast<QStyle *>(&wndStyle)); // auto dewrap
+ QCOMPARE(widget1->style(), qApp->style()); // and child state is restored
+ window1->setStyle(0); // let sanity prevail
+ qApp->setStyle(0);
+
+ delete window1;
+ delete widget2;
+ delete window2;
+}
+
+void tst_QStyleSheetStyle::appStyle()
+{
+ qApp->setStyleSheet("");
+ // qApp style can never be 0
+ QVERIFY(QApplication::style() != 0);
+ QPointer<QStyle> style1 = new QWindowsStyle;
+ QPointer<QStyle> style2 = new QWindowsStyle;
+ qApp->setStyle(style1);
+ // Basic sanity
+ QVERIFY(qApp->style() == style1);
+ qApp->setStyle(style2);
+ QVERIFY(style1.isNull()); // qApp must have taken ownership and deleted it
+ // Setting null should not crash
+ qApp->setStyle(0);
+ QVERIFY(qApp->style() == style2);
+
+ // Set the stylesheet
+ qApp->setStyleSheet("whatever");
+ QPointer<QStyleSheetStyle> sss = (QStyleSheetStyle *)qApp->style();
+ QVERIFY(!sss.isNull());
+ QCOMPARE(sss->metaObject()->className(), "QStyleSheetStyle"); // must be our proxy now
+ QVERIFY(!style2.isNull()); // this should exist as it is the base of the proxy
+ QVERIFY(sss->baseStyle() == style2);
+ style1 = new QWindowsStyle;
+ qApp->setStyle(style1);
+ QVERIFY(style2.isNull()); // should disappear automatically
+ QVERIFY(sss.isNull()); // should disappear automatically
+
+ // Update the stylesheet and check nothing changes
+ sss = (QStyleSheetStyle *)qApp->style();
+ qApp->setStyleSheet("whatever2");
+ QVERIFY(qApp->style() == sss);
+ QVERIFY(sss->baseStyle() == style1);
+
+ // Revert the stylesheet
+ qApp->setStyleSheet("");
+ QVERIFY(sss.isNull()); // should have disappeared
+ QVERIFY(qApp->style() == style1);
+
+ qApp->setStyleSheet("");
+ QVERIFY(qApp->style() == style1);
+}
+
+void tst_QStyleSheetStyle::dynamicProperty()
+{
+ qApp->setStyleSheet(QString());
+
+ QString appStyle = qApp->style()->metaObject()->className();
+ QPushButton pb1, pb2;
+ pb1.setProperty("type", "critical");
+ qApp->setStyleSheet("*[class~=\"QPushButton\"] { color: red; } *[type=\"critical\"] { background: white; }");
+ QVERIFY(COLOR(pb1) == Qt::red);
+ QVERIFY(BACKGROUND(pb1) == Qt::white);
+
+ pb2.setProperty("class", "critical"); // dynamic class
+ pb2.setStyleSheet(QLatin1String(".critical[style~=\"") + appStyle + "\"] { color: blue }");
+ pb2.show();
+
+ QVERIFY(COLOR(pb2) == Qt::blue);
+}
+
+#ifdef Q_OS_MAC
+void tst_QStyleSheetStyle::layoutSpacing()
+{
+ qApp->setStyleSheet("* { color: red }");
+ QCheckBox ck1;
+ QCheckBox ck2;
+ QWidget window;
+ int spacing_widgetstyle = window.style()->layoutSpacing(ck1.sizePolicy().controlType(), ck2.sizePolicy().controlType(), Qt::Vertical);
+ int spacing_style = window.style()->layoutSpacing(ck1.sizePolicy().controlType(), ck2.sizePolicy().controlType(), Qt::Vertical);
+ QCOMPARE(spacing_widgetstyle, spacing_style);
+}
+#endif
+
+void tst_QStyleSheetStyle::qproperty()
+{
+ QPushButton pb;
+ pb.setStyleSheet("QPushButton { qproperty-text: hello; qproperty-checkable: true; qproperty-checked: 1}");
+ pb.ensurePolished();
+ QCOMPARE(pb.text(), QString("hello"));
+ QCOMPARE(pb.isCheckable(), true);
+ QCOMPARE(pb.isChecked(), true);
+}
+
+namespace ns {
+ class PushButton1 : public QPushButton {
+ Q_OBJECT
+ public:
+ PushButton1() { }
+ };
+ class PushButton2 : public PushButton1 {
+ Q_OBJECT
+ public:
+ PushButton2() { setProperty("class", "PushButtonTwo PushButtonDuo"); }
+ };
+}
+
+void tst_QStyleSheetStyle::namespaces()
+{
+ ns::PushButton1 pb1;
+ qApp->setStyleSheet("ns--PushButton1 { background: white }");
+ QVERIFY(BACKGROUND(pb1) == QColor("white"));
+ qApp->setStyleSheet(".ns--PushButton1 { background: red }");
+ QVERIFY(BACKGROUND(pb1) == QColor("red"));
+
+ ns::PushButton2 pb2;
+ qApp->setStyleSheet("ns--PushButton1 { background: blue}");
+ QVERIFY(BACKGROUND(pb2) == QColor("blue"));
+ qApp->setStyleSheet("ns--PushButton2 { background: magenta }");
+ QVERIFY(BACKGROUND(pb2) == QColor("magenta"));
+ qApp->setStyleSheet(".PushButtonTwo { background: white; }");
+ QVERIFY(BACKGROUND(pb2) == QColor("white"));
+ qApp->setStyleSheet(".PushButtonDuo { background: red; }");
+ QVERIFY(BACKGROUND(pb2) == QColor("red"));
+}
+
+void tst_QStyleSheetStyle::palettePropagation()
+{
+ qApp->setStyleSheet("");
+ QGroupBox gb;
+ QPushButton *push = new QPushButton(&gb);
+ QPushButton &pb = *push;
+ push->setText("AsdF");
+
+ gb.setStyleSheet("QGroupBox { color: red }");
+ QVERIFY(COLOR(gb) == Qt::red);
+ QVERIFY(COLOR(pb) == APPCOLOR(pb)); // palette shouldn't propagate
+ gb.setStyleSheet("QGroupBox * { color: red }");
+
+ QVERIFY(COLOR(pb) == Qt::red);
+ QVERIFY(COLOR(gb) == APPCOLOR(gb));
+
+ QWidget window;
+ window.setStyleSheet("* { color: white; }");
+ pb.setParent(&window);
+ QVERIFY(COLOR(pb) == Qt::white);
+}
+
+void tst_QStyleSheetStyle::fontPropagation()
+{
+ qApp->setStyleSheet("");
+ QComboBox cb;
+ cb.addItem("item1");
+ cb.addItem("item2");
+
+ QAbstractItemView *popup = cb.view();
+ int viewFontSize = FONTSIZE(*popup);
+
+ cb.setStyleSheet("QComboBox { font-size: 20pt; }");
+ QVERIFY(FONTSIZE(cb) == 20);
+ QVERIFY(FONTSIZE(*popup) == viewFontSize);
+ QGroupBox gb;
+ QPushButton *push = new QPushButton(&gb);
+ QPushButton &pb = *push;
+ int buttonFontSize = FONTSIZE(pb);
+ int gbFontSize = FONTSIZE(gb);
+
+ gb.setStyleSheet("QGroupBox { font-size: 20pt }");
+ QVERIFY(FONTSIZE(gb) == 20);
+ QVERIFY(FONTSIZE(pb) == buttonFontSize); // font does not propagate
+ gb.setStyleSheet("QGroupBox * { font-size: 20pt; }");
+ QVERIFY(FONTSIZE(gb) == gbFontSize);
+ QVERIFY(FONTSIZE(pb) == 20);
+
+ QWidget window;
+ window.setStyleSheet("* { font-size: 10pt }");
+ pb.setParent(&window);
+ QCOMPARE(FONTSIZE(pb), 10);
+ window.setStyleSheet("");
+ QVERIFY(FONTSIZE(pb) == buttonFontSize);
+
+ QTabWidget tw;
+ tw.setStyleSheet("QTabWidget { font-size: 20pt; }");
+ QVERIFY(FONTSIZE(tw) == 20);
+ QWidget *child = qFindChild<QWidget *>(&tw, "qt_tabwidget_tabbar");
+ QVERIFY2(child, "QTabWidget did not contain a widget named \"qt_tabwidget_tabbar\"");
+ QVERIFY(FONTSIZE(*child) == 20);
+}
+
+void tst_QStyleSheetStyle::onWidgetDestroyed()
+{
+ qApp->setStyleSheet("");
+ QLabel *l = new QLabel;
+ l->setStyleSheet("QLabel { color: red }");
+ QPointer<QStyleSheetStyle> ss = (QStyleSheetStyle *) l->style();
+ delete l;
+ QVERIFY(ss.isNull());
+}
+
+void tst_QStyleSheetStyle::fontPrecedence()
+{
+ QLineEdit edit;
+ edit.show();
+ QFont font;
+ QVERIFY(FONTSIZE(edit) != 22); // Sanity check to make sure this test makes sense.
+ edit.setStyleSheet("QLineEdit { font-size: 22pt; }");
+ QCOMPARE(FONTSIZE(edit), 22);
+ font.setPointSize(16);
+ edit.setFont(font);
+ QCOMPARE(FONTSIZE(edit), 22);
+ edit.setStyleSheet("");
+ QCOMPARE(FONTSIZE(edit), 16);
+ font.setPointSize(18);
+ edit.setFont(font);
+ QCOMPARE(FONTSIZE(edit), 18);
+ edit.setStyleSheet("QLineEdit { font-size: 20pt; }");
+ QCOMPARE(FONTSIZE(edit), 20);
+ edit.setStyleSheet("");
+ QCOMPARE(FONTSIZE(edit), 18);
+ edit.hide();
+
+ QLineEdit edit2;
+ edit2.setReadOnly(true);
+ edit2.setStyleSheet("QLineEdit { font-size: 24pt; } QLineEdit:read-only { font-size: 26pt; }");
+ QCOMPARE(FONTSIZE(edit2), 26);
+}
+
+// Ensure primary will only return true if the color covers more than 50% of pixels
+static bool testForColors(const QImage& image, const QColor& color, bool ensurePrimary=false)
+{
+ int count = 0;
+ QRgb rgb = color.rgba();
+ int totalCount = image.height()*image.width();
+ for (int y = 0; y < image.height(); ++y) {
+ for (int x = 0; x < image.width(); ++x) {
+ // Because of antialiasing we allow a certain range of errors here.
+ QRgb pixel = image.pixel(x, y);
+
+ if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
+ qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
+ qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
+ count++;
+ if (!ensurePrimary && count >=10 )
+ return true;
+ else if (count > totalCount/2)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// This is a fragile test which fails on many esoteric platforms
+// because of focus problems. Test only on Windows, Mac, and Linux/gcc.
+#if defined(Q_OS_WIN32) || defined(Q_OS_MAC) || (defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
+void tst_QStyleSheetStyle::focusColors()
+{
+ // Tests if colors can be changed by altering the focus of the widget.
+ // To avoid messy pixel-by-pixel comparison, we assume that the goal
+ // is reached if at least ten pixels of the right color can be found in
+ // the image.
+ // For this reason, we use unusual and extremely ugly colors! :-)
+ QList<QWidget *> widgets;
+ widgets << new QPushButton("TESTING");
+ widgets << new QLineEdit("TESTING");
+ widgets << new QLabel("TESTING");
+ QSpinBox *spinbox = new QSpinBox;
+ spinbox->setValue(8888);
+ widgets << spinbox;
+ QComboBox *combobox = new QComboBox;
+ combobox->setEditable(true);
+ combobox->addItems(QStringList() << "TESTING");
+ widgets << combobox;
+ widgets << new QLabel("TESTING");
+
+#ifdef Q_WS_QWS
+ // QWS has its own special focus logic which is slightly different
+ // and I don't dare change it at this point, because someone will
+ // be relying on it. It means that setFocus() on a NoFocus widget (i.e.
+ // a QLabel) will not work before the window is activated.
+ widgets[2]->setFocusPolicy(Qt::StrongFocus);
+#endif
+
+ foreach (QWidget *widget, widgets) {
+ QDialog frame;
+ QLayout* layout = new QGridLayout;
+
+ QLineEdit* dummy = new QLineEdit; // Avoids initial focus.
+
+ widget->setStyleSheet("*:focus { border:none; background: #e8ff66; color: #ff0084 }");
+
+ layout->addWidget(dummy);
+ layout->addWidget(widget);
+ frame.setLayout(layout);
+
+ frame.show();
+ QTest::qWaitForWindowShown(&frame);
+ QApplication::setActiveWindow(&frame);
+ widget->setFocus();
+ QApplication::processEvents();
+
+ QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
+ frame.render(&image);
+ if (image.depth() < 24) {
+ QSKIP("Test doesn't support color depth < 24", SkipAll);
+ }
+
+ QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain background color #e8ff66, using style "
+ + QString::fromLatin1(qApp->style()->metaObject()->className()))
+ .toLocal8Bit().constData());
+ QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain text color #ff0084, using style "
+ + QString::fromLatin1(qApp->style()->metaObject()->className()))
+ .toLocal8Bit().constData());
+ }
+}
+#endif
+
+void tst_QStyleSheetStyle::hoverColors()
+{
+ if (!PlatformQuirks::haveMouseCursor())
+ QSKIP("No mouse Cursor on this platform",SkipAll);
+ QList<QWidget *> widgets;
+ widgets << new QPushButton("TESTING");
+ widgets << new QLineEdit("TESTING");
+ widgets << new QLabel("TESTING");
+ QSpinBox *spinbox = new QSpinBox;
+ spinbox->setValue(8888);
+ widgets << spinbox;
+ QComboBox *combobox = new QComboBox;
+ combobox->setEditable(true);
+ combobox->addItems(QStringList() << "TESTING");
+ widgets << combobox;
+ widgets << new QLabel("<b>TESTING</b>");
+
+ foreach (QWidget *widget, widgets) {
+ //without Qt::X11BypassWindowManagerHint the window manager may move the window after we moved the cursor
+ QDialog frame(0, Qt::X11BypassWindowManagerHint);
+ QLayout* layout = new QGridLayout;
+
+ QLineEdit* dummy = new QLineEdit;
+
+ widget->setStyleSheet("*:hover { border:none; background: #e8ff66; color: #ff0084 }");
+
+ layout->addWidget(dummy);
+ layout->addWidget(widget);
+ frame.setLayout(layout);
+
+ frame.show();
+#ifdef Q_WS_QWS
+//QWS does not implement enter/leave when windows are shown underneath the cursor
+ QCursor::setPos(QPoint(0,0));
+#endif
+
+ QTest::qWaitForWindowShown(&frame);
+ QApplication::setActiveWindow(&frame);
+ QTest::qWait(60);
+ //move the mouse inside the widget, it should be colored
+ QTest::mouseMove ( widget, QPoint(6,6));
+ QTest::qWait(60);
+
+ QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
+
+ QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
+ frame.render(&image);
+
+ QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain background color #e8ff66").toLocal8Bit().constData());
+ QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain text color #ff0084").toLocal8Bit().constData());
+
+ //move the mouse outside the widget, it should NOT be colored
+ QTest::mouseMove ( dummy, QPoint(5,5));
+ QTest::qWait(60);
+
+ frame.render(&image);
+
+ QVERIFY2(!testForColors(image, QColor(0xe8, 0xff, 0x66)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did contain background color #e8ff66").toLocal8Bit().constData());
+ QVERIFY2(!testForColors(image, QColor(0xff, 0x00, 0x84)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did contain text color #ff0084").toLocal8Bit().constData());
+
+ //move the mouse again inside the widget, it should be colored
+ QTest::mouseMove (widget, QPoint(5,5));
+ QTest::qWait(60);
+
+ QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
+
+ frame.render(&image);
+
+ QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain background color #e8ff66").toLocal8Bit().constData());
+ QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain text color #ff0084").toLocal8Bit().constData());
+ }
+
+}
+
+class SingleInheritanceDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ SingleInheritanceDialog(QWidget *w = 0) :
+ QDialog(w)
+ {
+ }
+};
+
+class DoubleInheritanceDialog : public SingleInheritanceDialog
+{
+ Q_OBJECT
+public:
+ DoubleInheritanceDialog(QWidget *w = 0) :
+ SingleInheritanceDialog(w)
+ {
+ }
+};
+
+void tst_QStyleSheetStyle::background()
+{
+ const int number = 4;
+ QWidget* widgets[number];
+ // Testing inheritance styling of QDialog.
+ widgets[0] = new SingleInheritanceDialog;
+ widgets[0]->setStyleSheet("* { background-color: #e8ff66; }");
+ widgets[1] = new DoubleInheritanceDialog;
+ widgets[1]->setStyleSheet("* { background-color: #e8ff66; }");
+
+ // Testing gradients in QComboBox.
+ QLayout* layout;
+ QComboBox* cb;
+ // First color
+ widgets[2] = new QDialog;
+ layout = new QGridLayout;
+ cb = new QComboBox;
+ cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
+ layout->addWidget(cb);
+ widgets[2]->setLayout(layout);
+ // Second color
+ widgets[3] = new QDialog;
+ layout = new QGridLayout;
+ cb = new QComboBox;
+ cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
+ layout->addWidget(cb);
+ widgets[3]->setLayout(layout);
+
+ for (int c = 0; c < number; ++c) {
+ QWidget* widget = widgets[c];
+
+ widget->show();
+ QTest::qWaitForWindowShown(widget);
+
+ QImage image(widget->width(), widget->height(), QImage::Format_ARGB32);
+ widget->render(&image);
+ if (image.depth() < 24) {
+ QSKIP("Test doesn't support color depth < 24", SkipAll);
+ }
+
+ QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain background image with color #e8ff66")
+ .toLocal8Bit().constData());
+
+ delete widget;
+ }
+}
+
+void tst_QStyleSheetStyle::tabAlignement()
+{
+ QWidget topLevel;
+ QTabWidget tabWidget(&topLevel);
+ tabWidget.addTab(new QLabel("tab1"),"tab1");
+ tabWidget.resize(QSize(400,400));
+ topLevel.show();
+ QTest::qWaitForWindowShown(&tabWidget);
+ QTest::qWait(50);
+ QTabBar *bar = qFindChild<QTabBar*>(&tabWidget);
+ QVERIFY(bar);
+ //check the tab is on the right
+ tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: right ; }");
+ qApp->processEvents();
+ QVERIFY(bar->geometry().right() > 380);
+ QVERIFY(bar->geometry().left() > 200);
+ //check the tab is on the middle
+ tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: center ; }");
+ QVERIFY(bar->geometry().right() < 300);
+ QVERIFY(bar->geometry().left() > 100);
+ //check the tab is on the left
+ tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: left ; }");
+ QVERIFY(bar->geometry().left() < 20);
+ QVERIFY(bar->geometry().right() < 200);
+
+ tabWidget.setTabPosition(QTabWidget::West);
+ //check the tab is on the top
+ QVERIFY(bar->geometry().top() < 20);
+ QVERIFY(bar->geometry().bottom() < 200);
+ //check the tab is on the bottom
+ tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: right ; }");
+ QVERIFY(bar->geometry().bottom() > 380);
+ QVERIFY(bar->geometry().top() > 200);
+ //check the tab is on the middle
+ tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: center ; }");
+ QVERIFY(bar->geometry().bottom() < 300);
+ QVERIFY(bar->geometry().top() > 100);
+}
+
+void tst_QStyleSheetStyle::attributesList()
+{
+ QWidget w;
+ QPushButton *p1=new QPushButton(&w);
+ QPushButton *p2=new QPushButton(&w);
+ QPushButton *p3=new QPushButton(&w);
+ QPushButton *p4=new QPushButton(&w);
+ p1->setProperty("prop", QStringList() << "red");
+ p2->setProperty("prop", QStringList() << "foo" << "red");
+ p3->setProperty("prop", QStringList() << "foo" << "bar");
+
+ w.setStyleSheet(" QPushButton{ background-color:blue; } QPushButton[prop~=red] { background-color:red; }");
+ QCOMPARE(BACKGROUND(*p1) , QColor("red"));
+ QCOMPARE(BACKGROUND(*p2) , QColor("red"));
+ QCOMPARE(BACKGROUND(*p3) , QColor("blue"));
+ QCOMPARE(BACKGROUND(*p4) , QColor("blue"));
+}
+
+void tst_QStyleSheetStyle::minmaxSizes()
+{
+ QTabWidget tabWidget;
+ tabWidget.setObjectName("tabWidget");
+ int index1 = tabWidget.addTab(new QLabel("Tab1"),"a");
+
+ QWidget *page2=new QLabel("page2");
+ page2->setObjectName("page2");
+ page2->setStyleSheet("* {background-color: white; min-width: 250px; max-width:500px }");
+ tabWidget.addTab(page2,"Tab2");
+ QWidget *page3=new QLabel("plop");
+ page3->setObjectName("Page3");
+ page3->setStyleSheet("* {background-color: yellow; min-height: 250px; max-height:500px }");
+ int index3 = tabWidget.addTab(page3,"very_long_long_long_long_caption");
+
+ tabWidget.setStyleSheet("QTabBar::tab { min-width:100px; max-width:130px; }");
+
+ tabWidget.show();
+ QTest::qWait(50);
+ //i allow 4px additional border from the native style (hence the -2, <=2)
+ QVERIFY(qAbs(page2->maximumSize().width() - 500 - 2) <= 2);
+ QVERIFY(qAbs(page2->minimumSize().width() - 250 - 2) <= 2);
+ QVERIFY(qAbs(page3->maximumSize().height() - 500 - 2) <= 2);
+ QVERIFY(qAbs(page3->minimumSize().height() - 250 - 2) <= 2);
+ QVERIFY(qAbs(page3->minimumSize().height() - 250 - 2) <= 2);
+ QTabBar *bar = qFindChild<QTabBar*>(&tabWidget);
+ QVERIFY(bar);
+ QVERIFY(qAbs(bar->tabRect(index1).width() - 100 - 2) <= 2);
+ QVERIFY(qAbs(bar->tabRect(index3).width() - 130 - 2) <= 2);
+}
+
+void tst_QStyleSheetStyle::task206238_twice()
+{
+ QMainWindow w;
+ QTabWidget* tw = new QTabWidget;
+ tw->addTab(new QLabel("foo"), "test");
+ w.setCentralWidget(tw);
+ w.setStyleSheet("background: red;");
+ w.show();
+ QTest::qWait(20);
+ QCOMPARE(BACKGROUND(w) , QColor("red"));
+ QCOMPARE(BACKGROUND(*tw), QColor("red"));
+ w.setStyleSheet("background: red;");
+ QTest::qWait(20);
+ QCOMPARE(BACKGROUND(w) , QColor("red"));
+ QCOMPARE(BACKGROUND(*tw), QColor("red"));
+}
+
+void tst_QStyleSheetStyle::transparent()
+{
+ QWidget w;
+ QPushButton *p1=new QPushButton(&w);
+ QPushButton *p2=new QPushButton(&w);
+ QPushButton *p3=new QPushButton(&w);
+ p1->setStyleSheet("background:transparent");
+ p2->setStyleSheet("background-color:transparent");
+ p3->setStyleSheet("background:rgb(0,0,0,0)");
+ QCOMPARE(BACKGROUND(*p1) , QColor(0,0,0,0));
+ QCOMPARE(BACKGROUND(*p2) , QColor(0,0,0,0));
+ QCOMPARE(BACKGROUND(*p3) , QColor(0,0,0,0));
+}
+
+
+
+class ProxyStyle : public QStyle
+{
+ public:
+ ProxyStyle(QStyle *s)
+ {
+ style = s;
+ }
+
+ void drawControl(ControlElement ce, const QStyleOption *opt,
+ QPainter *painter, const QWidget *widget = 0) const;
+
+ void drawPrimitive(QStyle::PrimitiveElement pe,
+ const QStyleOption* opt,
+ QPainter* p ,
+ const QWidget* w) const
+ {
+ style->drawPrimitive(pe, opt, p, w);
+ }
+
+ QRect subElementRect(QStyle::SubElement se,
+ const QStyleOption* opt,
+ const QWidget* w) const
+ {
+ Q_UNUSED(se);
+ Q_UNUSED(opt);
+ Q_UNUSED(w);
+ return QRect(0, 0, 3, 3);
+ }
+
+ void drawComplexControl(QStyle::ComplexControl cc,
+ const QStyleOptionComplex* opt,
+ QPainter* p,
+ const QWidget* w) const
+ {
+ style->drawComplexControl(cc, opt, p, w);
+ }
+
+
+ SubControl hitTestComplexControl(QStyle::ComplexControl cc,
+ const QStyleOptionComplex* opt,
+ const QPoint& pt,
+ const QWidget* w) const
+ {
+ return style->hitTestComplexControl(cc, opt, pt, w);
+ }
+
+ QRect subControlRect(QStyle::ComplexControl cc,
+ const QStyleOptionComplex* opt,
+ QStyle::SubControl sc,
+ const QWidget* w) const
+ {
+ return style->subControlRect(cc, opt, sc, w);
+ }
+
+ int pixelMetric(QStyle::PixelMetric pm,
+ const QStyleOption* opt,
+ const QWidget* w) const
+ {
+ return style->pixelMetric(pm, opt, w);
+ }
+
+
+ QSize sizeFromContents(QStyle::ContentsType ct,
+ const QStyleOption* opt,
+ const QSize& size,
+ const QWidget* w) const
+ {
+ return style->sizeFromContents(ct, opt, size, w);
+ }
+
+ int styleHint(QStyle::StyleHint sh,
+ const QStyleOption* opt,
+ const QWidget* w,
+ QStyleHintReturn* shr) const
+ {
+ return style->styleHint(sh, opt, w, shr);
+ }
+
+ QPixmap standardPixmap(QStyle::StandardPixmap spix,
+ const QStyleOption* opt,
+ const QWidget* w) const
+ {
+ return style->standardPixmap(spix, opt, w);
+ }
+
+ QPixmap generatedIconPixmap(QIcon::Mode mode,
+ const QPixmap& pix,
+ const QStyleOption* opt) const
+ {
+ return style->generatedIconPixmap(mode, pix, opt);
+ }
+
+ private:
+ QStyle *style;
+};
+
+void ProxyStyle::drawControl(ControlElement ce, const QStyleOption *opt,
+ QPainter *painter, const QWidget *widget) const
+{
+ if(ce == CE_PushButton)
+ {
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt))
+ {
+ QRect r = btn->rect;
+ painter->fillRect(r, Qt::green);
+
+ if(btn->state & QStyle::State_HasFocus)
+ painter->fillRect(r.adjusted(5, 5, -5, -5), Qt::yellow);
+
+
+ painter->drawText(r, Qt::AlignCenter, btn->text);
+ }
+ }
+ else
+ {
+ style->drawControl(ce, opt, painter, widget);
+ }
+}
+
+void tst_QStyleSheetStyle::proxyStyle()
+{
+ //Should not crash; task 158984
+
+ ProxyStyle *proxy = new ProxyStyle(qApp->style());
+ QString styleSheet("QPushButton {background-color: red; }");
+
+ QWidget *w = new QWidget;
+ QVBoxLayout *layout = new QVBoxLayout(w);
+
+ QPushButton *pb1 = new QPushButton(qApp->style()->objectName(), w);
+ layout->addWidget(pb1);
+
+ QPushButton *pb2 = new QPushButton("ProxyStyle", w);
+ pb2->setStyle(proxy);
+ layout->addWidget(pb2);
+
+ QPushButton *pb3 = new QPushButton("StyleSheet", w);
+ pb3->setStyleSheet(styleSheet);
+ layout->addWidget(pb3);
+
+ QPushButton *pb4 = new QPushButton("StyleSheet then ProxyStyle ", w);
+ pb4->setStyleSheet(styleSheet);
+
+ // We are creating our Proxy based on current style...
+ // In this case it would be the QStyleSheetStyle that is deleted
+ // later on. We need to get access to the "real" QStyle to be able to
+ // draw correctly.
+ ProxyStyle* newProxy = new ProxyStyle(qApp->style());
+ pb4->setStyle(newProxy);
+
+ layout->addWidget(pb4);
+
+ QPushButton *pb5 = new QPushButton("ProxyStyle then StyleSheet ", w);
+ pb5->setStyle(proxy);
+ pb5->setStyleSheet(styleSheet);
+ layout->addWidget(pb5);
+
+ w->show();
+
+ QTest::qWait(100);
+
+ // Test for QTBUG-7198 - style sheet overrides custom element size
+ QStyleOptionViewItemV4 opt;
+ opt.initFrom(w);
+ opt.features |= QStyleOptionViewItemV2::HasCheckIndicator;
+ QVERIFY(pb5->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator,
+ &opt, pb5).width() == 3);
+ delete w;
+ delete proxy;
+ delete newProxy;
+}
+
+void tst_QStyleSheetStyle::dialogButtonBox()
+{
+ QDialogButtonBox box;
+ box.addButton(QDialogButtonBox::Ok);
+ box.addButton(QDialogButtonBox::Cancel);
+ box.setStyleSheet("/** */ ");
+ box.setStyleSheet(QString()); //should not crash
+}
+
+void tst_QStyleSheetStyle::emptyStyleSheet()
+{
+ //empty stylesheet should not change anything
+ qApp->setStyleSheet(QString());
+ QWidget w;
+ QHBoxLayout layout(&w);
+ w.setLayout(&layout);
+ layout.addWidget(new QPushButton("push", &w));
+ layout.addWidget(new QToolButton(&w));
+ QLabel label("toto", &w);
+ label.setFrameShape(QLabel::Panel);
+ label.setFrameShadow(QLabel::Sunken);
+ layout.addWidget(&label); //task 231137
+ layout.addWidget(new QTableWidget(200,200, &w));
+ layout.addWidget(new QProgressBar(&w));
+ layout.addWidget(new QLineEdit(&w));
+ layout.addWidget(new QSpinBox(&w));
+ layout.addWidget(new QComboBox(&w));
+ layout.addWidget(new QDateEdit(&w));
+ layout.addWidget(new QGroupBox("some text", &w));
+
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ //workaround the fact that the label sizehint is one pixel different the first time.
+ label.setIndent(0); //force to recompute the sizeHint:
+ w.setFocus();
+ QTest::qWait(100);
+
+ QImage img1(w.size(), QImage::Format_ARGB32);
+ w.render(&img1);
+
+ w.setStyleSheet("/* */");
+ QTest::qWait(100);
+
+ QImage img2(w.size(), QImage::Format_ARGB32);
+ w.render(&img2);
+
+ if(img1 != img2) {
+ img1.save("emptyStyleSheet_img1.png");
+ img2.save("emptyStyleSheet_img2.png");
+ }
+
+ QCOMPARE(img1,img2);
+}
+
+void tst_QStyleSheetStyle::toolTip()
+{
+ qApp->setStyleSheet(QString());
+ QWidget w;
+ QHBoxLayout layout(&w);
+ w.setLayout(&layout);
+
+ QWidget *wid1 = new QGroupBox(&w);
+ layout.addWidget(wid1);
+ wid1->setStyleSheet("QToolTip { background: #ae2; } #wid3 > QToolTip { background: #0b8; } ");
+ QVBoxLayout *layout1 = new QVBoxLayout(wid1);
+ wid1->setLayout(layout1);
+ wid1->setToolTip("this is wid1");
+ wid1->setObjectName("wid1");
+
+ QWidget *wid2 = new QPushButton("wid2", wid1);
+ layout1->addWidget(wid2);
+ wid2->setStyleSheet("QToolTip { background: #f81; } ");
+ wid2->setToolTip("this is wid2");
+ wid2->setObjectName("wid2");
+
+ QWidget *wid3 = new QPushButton("wid3", wid1);
+ layout1->addWidget(wid3);
+ wid3->setToolTip("this is wid3");
+ wid3->setObjectName("wid3");
+
+ QWidget *wid4 = new QPushButton("wid4", &w);
+ layout.addWidget(wid4);
+ wid4->setToolTip("this is wid4");
+ wid4->setObjectName("wid4");
+
+ w.show();
+ QTest::qWait(100);
+
+ QColor normalToolTip = qApp->palette().toolTipBase().color();
+ QList<QWidget *> widgets;
+ QList<QColor> colors;
+
+
+ //tooltip on the widget without stylesheet, then to othes widget, including one without stylesheet
+ //(the tooltip will be reused but his colour must change)
+ widgets << wid4 << wid1 << wid2 << wid3 << wid4;
+ colors << normalToolTip << "#ae2" << "#f81" << "#0b8" << normalToolTip;
+
+ for (int i = 0; i < widgets.count() ; i++)
+ {
+ QWidget *wid = widgets.at(i);
+ QColor col = colors.at(i);
+
+ QToolTip::showText( QPoint(0,0) , "This is " + wid->objectName(), wid);
+
+ QWidget *tooltip = 0;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget->inherits("QTipLabel") && widget->isVisible()) {
+ tooltip = widget;
+ break;
+ }
+ }
+ QVERIFY(tooltip);
+ QCOMPARE(tooltip->palette().color(tooltip->backgroundRole()), col);
+ }
+
+ QToolTip::showText( QPoint(0,0) , "This is " + wid3->objectName(), wid3);
+ QTest::qWait(100);
+ delete wid3; //should not crash;
+ QTest::qWait(10);
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ widget->update(); //should not crash either
+ }
+}
+
+void tst_QStyleSheetStyle::embeddedFonts()
+{
+ //task 235622 and 210551
+ QSpinBox spin;
+ spin.show();
+ spin.setStyleSheet("QSpinBox { font-size: 32px; }");
+ QTest::qWait(20);
+ QLineEdit *embedded = spin.findChild<QLineEdit *>();
+ QVERIFY(embedded);
+ QCOMPARE(spin.font().pixelSize(), 32);
+ QCOMPARE(embedded->font().pixelSize(), 32);
+
+ QMenu *menu = embedded->createStandardContextMenu();
+ menu->show();
+ QTest::qWait(20);
+ QVERIFY(menu);
+ QVERIFY(menu->font().pixelSize() != 32);
+ QCOMPARE(menu->font().pixelSize(), qApp->font(menu).pixelSize());
+
+ //task 242556
+ QComboBox box;
+ box.setEditable(true);
+ box.addItems(QStringList() << "First" << "Second" << "Third");
+ box.setStyleSheet("QComboBox { font-size: 32px; }");
+ box.show();
+ embedded = box.findChild<QLineEdit *>();
+ QVERIFY(embedded);
+ QTest::qWait(20);
+ QCOMPARE(box.font().pixelSize(), 32);
+ QCOMPARE(embedded->font().pixelSize(), 32);
+}
+
+void tst_QStyleSheetStyle::opaquePaintEvent_data()
+{
+ QTest::addColumn<QString>("stylesheet");
+ QTest::addColumn<bool>("transparent");
+ QTest::addColumn<bool>("styled");
+
+ QTest::newRow("none") << QString::fromLatin1("/* */") << false << false;
+ QTest::newRow("background black ") << QString::fromLatin1("background: black;") << false << true;
+ QTest::newRow("background qrgba") << QString::fromLatin1("background: rgba(125,0,0,125);") << true << true;
+ QTest::newRow("background transparent") << QString::fromLatin1("background: transparent;") << true << true;
+ QTest::newRow("border native") << QString::fromLatin1("border: native;") << false << false;
+ QTest::newRow("border solid") << QString::fromLatin1("border: 2px solid black;") << true << true;
+ QTest::newRow("border transparent") << QString::fromLatin1("background: black; border: 2px solid rgba(125,0,0,125);") << true << true;
+ QTest::newRow("margin") << QString::fromLatin1("margin: 25px;") << true << true;
+ QTest::newRow("focus") << QString::fromLatin1("*:focus { background: rgba(125,0,0,125) }") << true << true;
+}
+
+void tst_QStyleSheetStyle::opaquePaintEvent()
+{
+ QFETCH(QString, stylesheet);
+ QFETCH(bool, transparent);
+ QFETCH(bool, styled);
+
+ QWidget tl;
+ QWidget cl(&tl);
+ cl.setAttribute(Qt::WA_OpaquePaintEvent, true);
+ cl.setAutoFillBackground(true);
+ cl.setStyleSheet(stylesheet);
+ cl.ensurePolished();
+ QCOMPARE(cl.testAttribute(Qt::WA_OpaquePaintEvent), !transparent);
+ QCOMPARE(cl.testAttribute(Qt::WA_StyledBackground), styled);
+ QCOMPARE(cl.autoFillBackground(), !styled );
+}
+
+void tst_QStyleSheetStyle::complexWidgetFocus()
+{
+ // This test is a simplified version of the focusColors() test above.
+
+ // Tests if colors can be changed by altering the focus of the widget.
+ // To avoid messy pixel-by-pixel comparison, we assume that the goal
+ // is reached if at least ten pixels of the right color can be found in
+ // the image.
+ // For this reason, we use unusual and extremely ugly colors! :-)
+
+ QDialog frame;
+ frame.setStyleSheet("*:focus { background: black; color: black } "
+ "QSpinBox::up-arrow:focus, QSpinBox::down-arrow:focus { width: 7px; height: 7px; background: #ff0084 } "
+ "QComboBox::down-arrow:focus { width: 7px; height: 7px; background: #ff0084 }"
+ "QSlider::handle:horizontal:focus { width: 7px; height: 7px; background: #ff0084 } ");
+
+ QList<QWidget *> widgets;
+ widgets << new QSpinBox;
+ widgets << new QComboBox;
+ widgets << new QSlider(Qt::Horizontal);
+
+ QLayout* layout = new QGridLayout;
+ layout->addWidget(new QLineEdit); // Avoids initial focus.
+ foreach (QWidget *widget, widgets)
+ layout->addWidget(widget);
+ frame.setLayout(layout);
+
+ frame.show();
+ QTest::qWaitForWindowShown(&frame);
+ QApplication::setActiveWindow(&frame);
+ foreach (QWidget *widget, widgets) {
+ widget->setFocus();
+ QApplication::processEvents();
+
+ QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
+ frame.render(&image);
+ if (image.depth() < 24) {
+ QSKIP("Test doesn't support color depth < 24", SkipAll);
+ }
+
+ QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
+ (QString::fromLatin1(widget->metaObject()->className())
+ + " did not contain text color #ff0084, using style "
+ + QString::fromLatin1(qApp->style()->metaObject()->className()))
+ .toLocal8Bit().constData());
+ }
+}
+
+void tst_QStyleSheetStyle::task188195_baseBackground()
+{
+ QTreeView tree;
+ tree.setStyleSheet( "QTreeView:disabled { background-color:#ab1251; }" );
+ tree.show();
+ QTest::qWait(20);
+ QImage image(tree.width(), tree.height(), QImage::Format_ARGB32);
+
+ tree.render(&image);
+ QVERIFY(testForColors(image, tree.palette().base().color()));
+ QVERIFY(!testForColors(image, QColor(0xab, 0x12, 0x51)));
+
+ tree.setEnabled(false);
+ tree.render(&image);
+ QVERIFY(testForColors(image, QColor(0xab, 0x12, 0x51)));
+
+ tree.setEnabled(true);
+ tree.render(&image);
+ QVERIFY(testForColors(image, tree.palette().base().color()));
+ QVERIFY(!testForColors(image, QColor(0xab, 0x12, 0x51)));
+
+ QTableWidget table(12, 12);
+ table.setItem(0, 0, new QTableWidgetItem());
+ table.setStyleSheet( "QTableView {background-color: #ff0000}" );
+ table.show();
+ QTest::qWait(20);
+ image = QImage(table.width(), table.height(), QImage::Format_ARGB32);
+ table.render(&image);
+ QVERIFY(testForColors(image, Qt::red, true));
+}
+
+void tst_QStyleSheetStyle::task232085_spinBoxLineEditBg()
+{
+ // This test is a simplified version of the focusColors() test above.
+
+ // Tests if colors can be changed by altering the focus of the widget.
+ // To avoid messy pixel-by-pixel comparison, we assume that the goal
+ // is reached if at least ten pixels of the right color can be found in
+ // the image.
+ // For this reason, we use unusual and extremely ugly colors! :-)
+
+ QSpinBox *spinbox = new QSpinBox;
+ spinbox->setValue(8888);
+
+ QDialog frame;
+ QLayout* layout = new QGridLayout;
+
+ QLineEdit* dummy = new QLineEdit; // Avoids initial focus.
+
+ // We only want to test the line edit colors.
+ spinbox->setStyleSheet("QSpinBox:focus { background: #e8ff66; color: #ff0084 } "
+ "QSpinBox::up-button, QSpinBox::down-button { background: black; }");
+
+ layout->addWidget(dummy);
+ layout->addWidget(spinbox);
+ frame.setLayout(layout);
+
+ frame.show();
+ QTest::qWaitForWindowShown(&frame);
+ QApplication::setActiveWindow(&frame);
+ spinbox->setFocus();
+ QApplication::processEvents();
+
+ QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
+ frame.render(&image);
+ if (image.depth() < 24) {
+ QSKIP("Test doesn't support color depth < 24", SkipAll);
+ }
+
+ QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
+ (QString::fromLatin1(spinbox->metaObject()->className())
+ + " did not contain background color #e8ff66, using style "
+ + QString::fromLatin1(qApp->style()->metaObject()->className()))
+ .toLocal8Bit().constData());
+ QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
+ (QString::fromLatin1(spinbox->metaObject()->className())
+ + " did not contain text color #ff0084, using style "
+ + QString::fromLatin1(qApp->style()->metaObject()->className()))
+ .toLocal8Bit().constData());
+}
+
+class ChangeEventWidget : public QWidget
+{ public:
+ void changeEvent(QEvent * event)
+ {
+ if(event->type() == QEvent::StyleChange) {
+ static bool recurse = false;
+ if (!recurse) {
+ recurse = true;
+ QStyle *style = new QMotifStyle;
+ style->setParent(this);
+ setStyle(style);
+ recurse = false;
+ }
+ }
+ QWidget::changeEvent(event);
+ }
+};
+
+void tst_QStyleSheetStyle::changeStyleInChangeEvent()
+{ //must not crash;
+ ChangeEventWidget wid;
+ wid.ensurePolished();
+ wid.setStyleSheet(" /* */ ");
+ wid.ensurePolished();
+ wid.setStyleSheet(" /* ** */ ");
+ wid.ensurePolished();
+}
+
+void tst_QStyleSheetStyle::QTBUG11658_cachecrash()
+{
+ //should not crash
+ class Widget : public QWidget
+ {
+ public:
+ Widget(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ QVBoxLayout* pLayout = new QVBoxLayout(this);
+ QCheckBox* pCheckBox = new QCheckBox(this);
+ pLayout->addWidget(pCheckBox);
+ setLayout(pLayout);
+
+ QString szStyleSheet = QLatin1String("* { color: red; }");
+ qApp->setStyleSheet(szStyleSheet);
+ qApp->setStyle(QStyleFactory::create(QLatin1String("Windows")));
+ }
+ };
+
+ Widget *w = new Widget();
+ delete w;
+ w = new Widget();
+ w->show();
+
+ QTest::qWaitForWindowShown(w);
+ delete w;
+ qApp->setStyleSheet(QString());
+}
+
+void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget()
+{
+ struct Widget : QWidget {
+ virtual void paintEvent(QPaintEvent* ) {
+ QStyleOption opt;
+ opt.init(this);
+ QPainter p(this);
+ style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, 0);
+ style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, 0);
+ style()->drawControl(QStyle::CE_PushButton, &opt, &p, 0);
+ }
+ } w;
+ w.setStyleSheet("* { background-color: white; color:black; border 3px solid yellow }");
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+}
+
+
+QTEST_MAIN(tst_QStyleSheetStyle)
+#include "tst_qstylesheetstyle.moc"
+
diff --git a/tests/auto/widgets/styles/styles.pro b/tests/auto/widgets/styles/styles.pro
new file mode 100644
index 0000000000..7e931582db
--- /dev/null
+++ b/tests/auto/widgets/styles/styles.pro
@@ -0,0 +1,13 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qmacstyle \
+ qstyle \
+ qstyleoption \
+ qstylesheetstyle \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qstylesheetstyle \
+
+# This test can only be run on Mac OS:
+!mac:SUBDIRS -= \
+ qmacstyle \
diff --git a/tests/auto/widgets/util/qcompleter/.gitignore b/tests/auto/widgets/util/qcompleter/.gitignore
new file mode 100644
index 0000000000..4db1c0d5c2
--- /dev/null
+++ b/tests/auto/widgets/util/qcompleter/.gitignore
@@ -0,0 +1 @@
+tst_qcompleter
diff --git a/tests/auto/widgets/util/qcompleter/qcompleter.pro b/tests/auto/widgets/util/qcompleter/qcompleter.pro
new file mode 100644
index 0000000000..4d58e6b813
--- /dev/null
+++ b/tests/auto/widgets/util/qcompleter/qcompleter.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qcompleter
+QT += widgets
+DEPENDPATH += .
+INCLUDEPATH += . ..
+
+# Input
+SOURCES += tst_qcompleter.cpp
+
+CONFIG += insignificant_test # QTBUG-21424
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
new file mode 100644
index 0000000000..ccf3c449b3
--- /dev/null
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -0,0 +1,1519 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+#include <QtDebug>
+#include <QPair>
+#include <QList>
+#include <QPointer>
+
+#include "../../../../shared/filesystem.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class CsvCompleter : public QCompleter
+{
+ Q_OBJECT
+public:
+ CsvCompleter(QObject *parent = 0) : QCompleter(parent), csv(true) { }
+
+ QString pathFromIndex(const QModelIndex& sourceIndex) const;
+
+ void setCsvCompletion(bool set) { csv = set; }
+
+protected:
+ QStringList splitPath(const QString &path) const {
+ return csv ? path.split(",") : QCompleter::splitPath(path);
+ }
+
+private:
+ bool csv;
+};
+
+QString CsvCompleter::pathFromIndex(const QModelIndex& si) const
+{
+ if (!csv)
+ return QCompleter::pathFromIndex(si);
+
+ if (!si.isValid())
+ return QString();
+
+ QModelIndex idx = si;
+ QStringList list;
+ do {
+ QString t = model()->data(idx, completionRole()).toString();
+ list.prepend(t);
+ QModelIndex parent = idx.parent();
+ idx = parent.sibling(parent.row(), si.column());
+ } while (idx.isValid());
+
+ if (list.count() == 1)
+ return list[0];
+ return list.join(",");
+}
+
+class tst_QCompleter : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QCompleter();
+ ~tst_QCompleter();
+
+private slots:
+ void getSetCheck();
+
+ void multipleWidgets();
+ void focusIn();
+
+ void csMatchingOnCsSortedModel_data();
+ void csMatchingOnCsSortedModel();
+ void ciMatchingOnCiSortedModel_data();
+ void ciMatchingOnCiSortedModel();
+
+ void ciMatchingOnCsSortedModel_data();
+ void ciMatchingOnCsSortedModel();
+ void csMatchingOnCiSortedModel_data();
+ void csMatchingOnCiSortedModel();
+
+ void directoryModel_data();
+ void directoryModel();
+ void fileSystemModel_data();
+ void fileSystemModel();
+
+ void changingModel_data();
+ void changingModel();
+
+ void sortedEngineRowCount_data();
+ void sortedEngineRowCount();
+ void unsortedEngineRowCount_data();
+ void unsortedEngineRowCount();
+
+ void currentRow();
+ void sortedEngineMapFromSource();
+ void unsortedEngineMapFromSource();
+
+ void historySearch();
+
+ void modelDeletion();
+ void setters();
+
+ void dynamicSortOrder();
+ void disabledItems();
+
+ // task-specific tests below me
+ void task178797_activatedOnReturn();
+ void task189564_omitNonSelectableItems();
+ void task246056_setCompletionPrefix();
+ void task250064_lostFocus();
+
+ void task253125_lineEditCompletion_data();
+ void task253125_lineEditCompletion();
+ void task247560_keyboardNavigation();
+ void QTBUG_14292_filesystem();
+
+private:
+ void filter(bool assync = false);
+ void testRowCount();
+ enum ModelType {
+ CASE_SENSITIVELY_SORTED_MODEL,
+ CASE_INSENSITIVELY_SORTED_MODEL,
+ DIRECTORY_MODEL,
+ HISTORY_MODEL,
+ FILESYSTEM_MODEL
+ };
+ void setSourceModel(ModelType);
+
+ CsvCompleter *completer;
+ QTreeWidget *treeWidget;
+ const int completionColumn;
+ const int columnCount;
+};
+
+tst_QCompleter::tst_QCompleter() : completer(0), completionColumn(0), columnCount(3)
+{
+ treeWidget = new QTreeWidget;
+ treeWidget->setColumnCount(columnCount);
+}
+
+tst_QCompleter::~tst_QCompleter()
+{
+ delete treeWidget;
+ delete completer;
+}
+
+void tst_QCompleter::setSourceModel(ModelType type)
+{
+ QString text;
+ QTreeWidgetItem *parent, *child;
+ treeWidget->clear();
+ switch(type) {
+ case CASE_SENSITIVELY_SORTED_MODEL:
+ // Creates a tree model with top level items P0, P1, .., p0, p1,..
+ // Each of these items parents have children (for P0 - c0P0, c1P0,...)
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 5; j++) {
+ parent = new QTreeWidgetItem(treeWidget);
+ text.sprintf("%c%i", i == 0 ? 'P' : 'p', j);
+ parent->setText(completionColumn, text);
+ for (int k = 0; k < 5; k++) {
+ child = new QTreeWidgetItem(parent);
+ QString t = QString().sprintf("c%i", k) + text;
+ child->setText(completionColumn, t);
+ }
+ }
+ }
+ completer->setModel(treeWidget->model());
+ completer->setCompletionColumn(completionColumn);
+ break;
+ case CASE_INSENSITIVELY_SORTED_MODEL:
+ case HISTORY_MODEL:
+ // Creates a tree model with top level items P0, p0, P1, p1,...
+ // Each of these items have children c0p0, c1p0,..
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 2; j++) {
+ parent = new QTreeWidgetItem(treeWidget);
+ text.sprintf("%c%i", j == 0 ? 'P' : 'p', i);
+ parent->setText(completionColumn, text);
+ for (int k = 0; k < 5; k++) {
+ child = new QTreeWidgetItem(parent);
+ QString t = QString().sprintf("c%i", k) + text;
+ child->setText(completionColumn, t);
+ }
+ }
+ }
+ completer->setModel(treeWidget->model());
+ completer->setCompletionColumn(completionColumn);
+ if (type == CASE_INSENSITIVELY_SORTED_MODEL)
+ break;
+ parent = new QTreeWidgetItem(treeWidget);
+ parent->setText(completionColumn, QLatin1String("p3,c3p3"));
+ parent = new QTreeWidgetItem(treeWidget);
+ parent->setText(completionColumn, QLatin1String("p2,c4p2"));
+ break;
+ case DIRECTORY_MODEL:
+ completer->setCsvCompletion(false);
+ completer->setModel(new QDirModel(completer));
+ completer->setCompletionColumn(0);
+ break;
+ case FILESYSTEM_MODEL:
+ completer->setCsvCompletion(false);
+ {
+ QFileSystemModel *m = new QFileSystemModel(completer);
+ m->setRootPath("/");
+ completer->setModel(m);
+ }
+ completer->setCompletionColumn(0);
+ break;
+ default:
+ qDebug() << "Invalid type";
+ }
+}
+
+void tst_QCompleter::filter(bool assync)
+{
+ QFETCH(QString, filterText);
+ QFETCH(QString, step);
+ QFETCH(QString, completion);
+ QFETCH(QString, completionText);
+
+ if (filterText.compare("FILTERING_OFF", Qt::CaseInsensitive) == 0) {
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ return;
+ }
+
+ int times = 0;
+retry:
+
+ completer->setCompletionPrefix(filterText);
+
+ for (int i = 0; i < step.length(); i++) {
+ int row = completer->currentRow();
+ switch (step[i].toUpper().toAscii()) {
+ case 'P': --row; break;
+ case 'N': ++row; break;
+ case 'L': row = completer->completionCount() - 1; break;
+ case 'F': row = 0; break;
+ default:
+ QFAIL(qPrintable(QString(
+ "Problem with 'step' value in test data: %1 (only P, N, L and F are allowed)."
+ ).arg(step[i])));
+ }
+ completer->setCurrentRow(row);
+ }
+
+ int r = QString::compare(completer->currentCompletion(), completionText, completer->caseSensitivity());
+ if (assync && r && times < 10) {
+ times++;
+ QTest::qWait(50*times);
+ goto retry;
+ }
+ QVERIFY(!r);
+}
+
+// Testing get/set functions
+void tst_QCompleter::getSetCheck()
+{
+ QStandardItemModel model(3,3);
+ QCompleter completer(&model);
+
+ // QString QCompleter::completionPrefix()
+ // void QCompleter::setCompletionPrefix(QString)
+ completer.setCompletionPrefix(QString("te"));
+ QCOMPARE(completer.completionPrefix(), QString("te"));
+ completer.setCompletionPrefix(QString());
+ QCOMPARE(completer.completionPrefix(), QString());
+
+ // ModelSorting QCompleter::modelSorting()
+ // void QCompleter::setModelSorting(ModelSorting)
+ completer.setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ QCOMPARE(completer.modelSorting(), QCompleter::CaseSensitivelySortedModel);
+ completer.setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ QCOMPARE(completer.modelSorting(), QCompleter::CaseInsensitivelySortedModel);
+ completer.setModelSorting(QCompleter::UnsortedModel);
+ QCOMPARE(completer.modelSorting(), QCompleter::UnsortedModel);
+
+ // CompletionMode QCompleter::completionMode()
+ // void QCompleter::setCompletionMode(CompletionMode)
+ QCOMPARE(completer.completionMode(), QCompleter::PopupCompletion); // default value
+ completer.setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ QCOMPARE(completer.completionMode(), QCompleter::UnfilteredPopupCompletion);
+ completer.setCompletionMode(QCompleter::InlineCompletion);
+ QCOMPARE(completer.completionMode(), QCompleter::InlineCompletion);
+
+ // int QCompleter::completionColumn()
+ // void QCompleter::setCompletionColumn(int)
+ completer.setCompletionColumn(2);
+ QCOMPARE(completer.completionColumn(), 2);
+ completer.setCompletionColumn(1);
+ QCOMPARE(completer.completionColumn(), 1);
+
+ // int QCompleter::completionRole()
+ // void QCompleter::setCompletionRole(int)
+ QCOMPARE(completer.completionRole(), static_cast<int>(Qt::EditRole)); // default value
+ completer.setCompletionRole(Qt::DisplayRole);
+ QCOMPARE(completer.completionRole(), static_cast<int>(Qt::DisplayRole));
+
+ // int QCompleter::maxVisibleItems()
+ // void QCompleter::setMaxVisibleItems(int)
+ QCOMPARE(completer.maxVisibleItems(), 7); // default value
+ completer.setMaxVisibleItems(10);
+ QCOMPARE(completer.maxVisibleItems(), 10);
+ QTest::ignoreMessage(QtWarningMsg, "QCompleter::setMaxVisibleItems: "
+ "Invalid max visible items (-2147483648) must be >= 0");
+ completer.setMaxVisibleItems(INT_MIN);
+ QCOMPARE(completer.maxVisibleItems(), 10); // Cannot be set to something negative => old value
+
+ // Qt::CaseSensitivity QCompleter::caseSensitivity()
+ // void QCompleter::setCaseSensitivity(Qt::CaseSensitivity)
+ QCOMPARE(completer.caseSensitivity(), Qt::CaseSensitive); // default value
+ completer.setCaseSensitivity(Qt::CaseInsensitive);
+ QCOMPARE(completer.caseSensitivity(), Qt::CaseInsensitive);
+
+ // bool QCompleter::wrapAround()
+ // void QCompleter::setWrapAround(bool)
+ QCOMPARE(completer.wrapAround(), true); // default value
+ completer.setWrapAround(false);
+ QCOMPARE(completer.wrapAround(), false);
+}
+
+void tst_QCompleter::csMatchingOnCsSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()N") << "" << "N" << "P1" << "P1";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "P4" << "P4";
+ QTest::newRow("(p)") << "p" << "" << "p0" << "p0";
+ QTest::newRow("(p)N") << "p" << "N" << "p1" << "p1";
+ QTest::newRow("(p)NN") << "p" << "NN" << "p2" << "p2";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "p3" << "p3";
+ QTest::newRow("(p)NNNN") << "p" << "NNNN" << "p4" << "p4";
+ QTest::newRow("(p1)") << "p1" << "" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ // Tree filter
+ QTest::newRow("(P0,)") << "P0," << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(P0,c)") << "P0,c" << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(P0,c1)") << "P0,c1" << "" << "c1P0" << "P0,c1P0";
+ QTest::newRow("(P0,c3P0)") << "P0,c3P0" << "" << "c3P0" << "P0,c3P0";
+ QTest::newRow("(P3,c)F") << "P3,c" << "F" << "c0P3" << "P3,c0P3";
+ QTest::newRow("(P3,c)L") << "P3,c" << "L" << "c4P3" << "P3,c4P3";
+ QTest::newRow("(P3,c)N") << "P3,c" << "N" << "c1P3" << "P3,c1P3";
+ QTest::newRow("(P3,c)NN") << "P3,c" << "NN" << "c2P3" << "P3,c2P3";
+ QTest::newRow("(P3,,c)") << "P3,,c" << "" << "" << "";
+ QTest::newRow("(P3,c0P3,)") << "P3,c0P3," << "" << "" << "";
+ QTest::newRow("(P,)") << "P," << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::csMatchingOnCsSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::ciMatchingOnCiSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()N") << "" << "N" << "p0" << "p0";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "p4" << "p4";
+ QTest::newRow("(p)") << "p" << "" << "P0" << "P0";
+ QTest::newRow("(p)N") << "p" << "N" << "p0" << "p0";
+ QTest::newRow("(p)NN") << "p" << "NN" << "P1" << "P1";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "p1" << "p1";
+ QTest::newRow("(p1)") << "p1" << "" << "P1" << "P1";
+ QTest::newRow("(p1)N") << "p1" << "N" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ //// Tree filter
+ QTest::newRow("(p0,)") << "p0," << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c)") << "p0,c" << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1P0" << "P0,c1P0";
+ QTest::newRow("(p0,c3P0)") << "p0,c3P0" << "" << "c3P0" << "P0,c3P0";
+ QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0P3" << "P3,c0P3";
+ QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4P3" << "P3,c4P3";
+ QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1P3" << "P3,c1P3";
+ QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2P3" << "P3,c2P3";
+ QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
+ QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
+ QTest::newRow("(p,)") << "p," << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::ciMatchingOnCiSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::ciMatchingOnCsSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "p4" << "p4";
+ QTest::newRow("(p)") << "p" << "" << "P0" << "P0";
+ QTest::newRow("(p)N") << "p" << "N" << "P1" << "P1";
+ QTest::newRow("(p)NN") << "p" << "NN" << "P2" << "P2";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "P3" << "P3";
+ QTest::newRow("(p1)") << "p1" << "" << "P1" << "P1";
+ QTest::newRow("(p1)N") << "p1" << "N" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ // Tree filter
+ QTest::newRow("(p0,)") << "p0," << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c)") << "p0,c" << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1P0" << "P0,c1P0";
+ QTest::newRow("(p0,c3P0)") << "p0,c3P0" << "" << "c3P0" << "P0,c3P0";
+ QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0P3" << "P3,c0P3";
+ QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4P3" << "P3,c4P3";
+ QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1P3" << "P3,c1P3";
+ QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2P3" << "P3,c2P3";
+ QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
+ QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
+ QTest::newRow("(p,)") << "p," << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::ciMatchingOnCsSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::csMatchingOnCiSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()N") << "" << "N" << "p0" << "p0";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "P4" << "P4";
+ QTest::newRow("(p)") << "p" << "" << "p0" << "p0";
+ QTest::newRow("(p)N") << "p" << "N" << "p1" << "p1";
+ QTest::newRow("(p)NN") << "p" << "NN" << "p2" << "p2";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "p3" << "p3";
+ QTest::newRow("(p1)") << "p1" << "" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ //// Tree filter
+ QTest::newRow("(p0,)") << "p0," << "" << "c0p0" << "p0,c0p0";
+ QTest::newRow("(p0,c)") << "p0,c" << "" << "c0p0" << "p0,c0p0";
+ QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1p0" << "p0,c1p0";
+ QTest::newRow("(p0,c3P0)") << "p0,c3p0" << "" << "c3p0" << "p0,c3p0";
+ QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0p3" << "p3,c0p3";
+ QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4p3" << "p3,c4p3";
+ QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1p3" << "p3,c1p3";
+ QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2p3" << "p3,c2p3";
+ QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
+ QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
+ QTest::newRow("(p,)") << "p," << "" << "" << "";
+
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::csMatchingOnCiSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::directoryModel_data()
+{
+ delete completer;
+
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ setSourceModel(DIRECTORY_MODEL);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ // NOTE: Add tests carefully, ensurely the paths exist on all systems
+ // Output is the sourceText; currentCompletionText()
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+#if defined(Q_OS_WINCE)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("()") << "\\Program" << "" << "Program Files" << "\\Program Files";
+#elif defined(Q_OS_WIN)
+ QTest::newRow("()") << "C" << "" << "C:" << "C:";
+ QTest::newRow("()") << "C:\\Program" << "" << "Program Files" << "C:\\Program Files";
+#elif defined (Q_OS_MAC)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications";
+ QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer";
+#else
+ QTest::newRow("()") << "" << "" << "/" << "/";
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX)
+ QTest::newRow("(/h)") << "/h" << "" << "home" << "/home";
+#endif
+ QTest::newRow("(/et)") << "/et" << "" << "etc" << "/etc";
+ QTest::newRow("(/etc/passw)") << "/etc/passw" << "" << "passwd" << "/etc/passwd";
+#endif
+ }
+}
+
+void tst_QCompleter::directoryModel()
+{
+ filter();
+}
+
+void tst_QCompleter::fileSystemModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ setSourceModel(FILESYSTEM_MODEL);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ // NOTE: Add tests carefully, ensurely the paths exist on all systems
+ // Output is the sourceText; currentCompletionText()
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+#if defined(Q_OS_WINCE)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("()") << "\\Program" << "" << "Program Files" << "\\Program Files";
+#elif defined(Q_OS_WIN)
+ QTest::newRow("()") << "C" << "" << "C:" << "C:";
+ QTest::newRow("()") << "C:\\Program" << "" << "Program Files" << "C:\\Program Files";
+#elif defined (Q_OS_MAC)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications";
+// QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer";
+#else
+ QTest::newRow("()") << "" << "" << "/" << "/";
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX)
+ QTest::newRow("(/h)") << "/h" << "" << "home" << "/home";
+#endif
+ QTest::newRow("(/et)") << "/et" << "" << "etc" << "/etc";
+ QTest::newRow("(/etc/passw)") << "/etc/passw" << "" << "passwd" << "/etc/passwd";
+#endif
+ }
+}
+
+void tst_QCompleter::fileSystemModel()
+{
+ //QFileSystemModel is assync.
+ filter(true);
+}
+
+
+void tst_QCompleter::changingModel_data()
+{
+}
+
+void tst_QCompleter::changingModel()
+{
+ for (int i = 0; i < 2; i++) {
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
+
+ if (i == 1) {
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ }
+
+ completer->setCompletionPrefix("p");
+ completer->setCurrentRow(completer->completionCount() - 1);
+ QCOMPARE(completer->currentCompletion(), QString("p4"));
+
+ // Test addition of data
+ QTreeWidgetItem p5item;
+ p5item.setText(completionColumn, "p5");
+ treeWidget->addTopLevelItem(&p5item);
+ completer->setCompletionPrefix("p5");
+ QCOMPARE(completer->currentCompletion(), QString("p5"));
+
+ // Test removal of data
+ int p5index = treeWidget->indexOfTopLevelItem(&p5item);
+ treeWidget->takeTopLevelItem(p5index);
+ QCOMPARE(completer->currentCompletion(), QString(""));
+
+ // Test clear
+ treeWidget->clear();
+ QCOMPARE(completer->currentIndex(), QModelIndex());
+ }
+}
+
+void tst_QCompleter::testRowCount()
+{
+ QFETCH(QString, filterText);
+ QFETCH(bool, hasChildren);
+ QFETCH(int, rowCount);
+ QFETCH(int, completionCount);
+
+ if (filterText.compare("FILTERING_OFF", Qt::CaseInsensitive) == 0) {
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ return;
+ }
+
+ completer->setCompletionPrefix(filterText);
+ const QAbstractItemModel *completionModel = completer->completionModel();
+ QCOMPARE(completionModel->rowCount(), rowCount);
+ QCOMPARE(completionCount, completionCount);
+ QCOMPARE(completionModel->hasChildren(), hasChildren);
+ QCOMPARE(completionModel->columnCount(), columnCount);
+}
+
+void tst_QCompleter::sortedEngineRowCount_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<bool>("hasChildren");
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("completionCount");
+
+ QTest::newRow("whatever") << "whatever" << false << 0 << 0;
+ QTest::newRow("p") << "p" << true << 10 << 10;
+ QTest::newRow("p1") << "p1" << true << 2 << 2;
+ QTest::newRow("P1,") << "P1," << true << 5 << 5;
+ QTest::newRow("P1,c") << "P1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc") << "P1,cc" << false << 0 << 0;
+
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << false << 0 << 0;
+
+ QTest::newRow("whatever(filter off)") << "whatever" << true << 10 << 0;
+ QTest::newRow("p1(filter off)") << "p1" << true << 10 << 2;
+ QTest::newRow("p1,(filter off)") << "p1," << true << 5 << 5;
+ QTest::newRow("p1,c(filter off)") << "p1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc(filter off)") << "P1,cc" << true << 5 << 0;
+}
+
+void tst_QCompleter::sortedEngineRowCount()
+{
+ testRowCount();
+}
+
+void tst_QCompleter::unsortedEngineRowCount_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<bool>("hasChildren");
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("completionCount");
+
+ QTest::newRow("whatever") << "whatever" << false << 0 << 0;
+ QTest::newRow("p") << "p" << true << 5 << 5;
+ QTest::newRow("p1") << "p1" << true << 1 << 1;
+ QTest::newRow("P1,") << "P1," << true << 5 << 5;
+ QTest::newRow("P1,c") << "P1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc") << "P1,cc" << false << 0 << 0;
+
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << false << 0 << 0;
+
+ QTest::newRow("whatever(filter off)") << "whatever" << true << 10 << 0;
+ QTest::newRow("p1(filter off)") << "p1" << true << 10 << 1;
+ QTest::newRow("p1,(filter off)") << "p1," << true << 5 << 5;
+ QTest::newRow("p1,c(filter off)") << "p1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc(filter off)") << "P1,cc" << true << 5 << 0;
+}
+
+void tst_QCompleter::unsortedEngineRowCount()
+{
+ testRowCount();
+}
+
+void tst_QCompleter::currentRow()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ // blank text
+ completer->setCompletionPrefix("");
+ QCOMPARE(completer->currentRow(), 0);
+ QVERIFY(completer->setCurrentRow(4));
+ QCOMPARE(completer->currentRow(), 4);
+ QVERIFY(!completer->setCurrentRow(13));
+ QVERIFY(completer->setCurrentRow(4));
+
+ // some text
+ completer->setCompletionPrefix("p1");
+ QCOMPARE(completer->currentRow(), 0);
+ QVERIFY(completer->setCurrentRow(1));
+ QCOMPARE(completer->currentRow(), 1);
+ QVERIFY(!completer->setCurrentRow(2));
+ QCOMPARE(completer->currentRow(), 1);
+
+ // invalid text
+ completer->setCompletionPrefix("well");
+ QCOMPARE(completer->currentRow(), -1);
+}
+
+void tst_QCompleter::sortedEngineMapFromSource()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QModelIndex si1, si2, pi;
+ QAbstractItemModel *sourceModel = completer->model();
+ const QAbstractProxyModel *completionModel =
+ qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
+
+ // Fitering ON
+ // empty
+ si1 = sourceModel->index(4, completionColumn); // "P2"
+ si2 = sourceModel->index(2, 0, si1); // "P2,c0P2"
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // some text
+ completer->setCompletionPrefix("p");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si1);
+ QVERIFY(!pi.isValid());
+
+ // Fitering OFF
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ // empty
+ si1 = sourceModel->index(4, completionColumn); // "P2"
+ si2 = sourceModel->index(2, 0, si1); // "P2,c0P2"
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // some text
+ completer->setCompletionPrefix("p");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+}
+
+void tst_QCompleter::unsortedEngineMapFromSource()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(HISTORY_MODEL); // case insensitively sorted model
+ completer->setModelSorting(QCompleter::UnsortedModel);
+
+ QModelIndex si, si2, si3, pi;
+ QAbstractItemModel *sourceModel = completer->model();
+ const QAbstractProxyModel *completionModel =
+ qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
+
+ si = sourceModel->index(6, completionColumn); // "P3"
+ QCOMPARE(si.data().toString(), QLatin1String("P3"));
+ si2 = sourceModel->index(3, completionColumn, sourceModel->index(0, completionColumn)); // "P0,c3P0"
+ QCOMPARE(si2.data().toString(), QLatin1String("c3P0"));
+ si3 = sourceModel->index(10, completionColumn); // "p3,c3p3" (history)
+ QCOMPARE(si3.data().toString(), QLatin1String("p3,c3p3"));
+
+ // FILTERING ON
+ // empty
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
+
+ // some text
+ completer->setCompletionPrefix("P");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si);
+ QVERIFY(!pi.isValid());
+ pi = completionModel->mapFromSource(si2);
+ QVERIFY(!pi.isValid());
+
+ // tree matching
+ completer->setCompletionPrefix("P0,c");
+ pi = completionModel->mapFromSource(si);
+ QVERIFY(!pi.isValid());
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("c3P0"));
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(pi.isValid(), false);
+
+ // more tree matching
+ completer->setCompletionPrefix("p3,");
+ pi = completionModel->mapFromSource(si2);
+ QVERIFY(!pi.isValid());
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
+
+ // FILTERING OFF
+ // empty
+ completer->setCompletionPrefix("");
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+
+ // some text
+ completer->setCompletionPrefix("P");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+
+ // more text
+ completer->setCompletionPrefix("P3");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+}
+
+void tst_QCompleter::historySearch()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(HISTORY_MODEL);
+
+ const QAbstractProxyModel *completionModel =
+ qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
+
+ // "p3,c3p3" and "p2,c4p2" are added in the tree root
+
+ // FILTERING ON
+ // empty
+ completer->setCurrentRow(10);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p3,c3p3"));
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ completer->setCurrentRow(1);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
+
+ // comma separated text
+ completer->setCompletionPrefix("p2,c4");
+ completer->setCurrentRow(1);
+ QCOMPARE(completionModel->rowCount(), 2);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ QCOMPARE(completer->currentCompletion(), QString());
+
+ // FILTERING OFF
+ completer->setCompletionPrefix("");
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ completer->setCurrentRow(10);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p3,c3p3"));
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ completer->setCurrentRow(1);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
+
+ // comma separated text
+ completer->setCompletionPrefix("p2,c4");
+ QCOMPARE(completionModel->rowCount(), 5);
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ QCOMPARE(completer->currentCompletion(), QString());
+}
+
+void tst_QCompleter::setters()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ QVERIFY(completer->popup() != 0);
+ QPointer<QDirModel> dirModel = new QDirModel(completer);
+ QAbstractItemModel *oldModel = completer->model();
+ completer->setModel(dirModel);
+ QVERIFY(completer->popup()->model() != oldModel);
+ QVERIFY(completer->popup()->model() == completer->completionModel());
+ completer->setPopup(new QListView);
+ QVERIFY(completer->popup()->model() == completer->completionModel());
+ completer->setModel(new QStringListModel(completer));
+ QVERIFY(dirModel == 0); // must have been deleted
+
+ completer->setModel(0);
+ completer->setWidget(0);
+}
+
+void tst_QCompleter::modelDeletion()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ QStringList list;
+ list << "item1" << "item2" << "item3";
+ QStringListModel *listModel = new QStringListModel(list);
+ completer->setCompletionPrefix("i");
+ completer->setModel(listModel);
+ QVERIFY(completer->completionCount() == 3);
+ QListView *view = new QListView;
+ view->setModel(completer->completionModel());
+ delete listModel;
+ view->show();
+ qApp->processEvents();
+ delete view;
+ QVERIFY(completer->completionCount() == 0);
+ QVERIFY(completer->currentRow() == -1);
+}
+
+void tst_QCompleter::multipleWidgets()
+{
+ QStringList list;
+ list << "item1" << "item2" << "item2";
+ QCompleter completer(list);
+ completer.setCompletionMode(QCompleter::InlineCompletion);
+
+ QWidget window;
+ window.show();
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(qApp->activeWindow() == &window);
+
+ QFocusEvent focusIn(QEvent::FocusIn);
+ QFocusEvent focusOut(QEvent::FocusOut);
+
+ QComboBox *comboBox = new QComboBox(&window);
+ comboBox->setEditable(true);
+ comboBox->setCompleter(&completer);
+ comboBox->setFocus();
+ comboBox->show();
+ window.activateWindow();
+ QApplication::setActiveWindow(&window);
+ QTest::qWait(50);
+ QTRY_VERIFY(qApp->focusWidget() == comboBox);
+ comboBox->lineEdit()->setText("it");
+ QCOMPARE(comboBox->currentText(), QString("it")); // should not complete with setText
+ QTest::keyPress(comboBox, 'e');
+ QCOMPARE(comboBox->currentText(), QString("item1"));
+ comboBox->clearEditText();
+ QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
+
+ QLineEdit *lineEdit = new QLineEdit(&window);
+ lineEdit->setCompleter(&completer);
+ lineEdit->show();
+ lineEdit->setFocus();
+ QTest::qWait(50);
+ QTRY_VERIFY(qApp->focusWidget() == lineEdit);
+ lineEdit->setText("it");
+ QCOMPARE(lineEdit->text(), QString("it")); // should not completer with setText
+ QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
+ QTest::keyPress(lineEdit, 'e');
+ QCOMPARE(lineEdit->text(), QString("item1"));
+ QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
+}
+
+void tst_QCompleter::focusIn()
+{
+ QStringList list;
+ list << "item1" << "item2" << "item2";
+ QCompleter completer(list);
+
+ QWidget window;
+ window.show();
+ QTest::qWait(100);
+ window.activateWindow();
+ QApplication::setActiveWindow(&window);
+ QTest::qWait(100);
+
+ QTRY_COMPARE(qApp->activeWindow(), &window);
+
+ QComboBox *comboBox = new QComboBox(&window);
+ comboBox->setEditable(true);
+ comboBox->setCompleter(&completer);
+ comboBox->show();
+ comboBox->lineEdit()->setText("it");
+
+ QLineEdit *lineEdit = new QLineEdit(&window);
+ lineEdit->setCompleter(&completer);
+ lineEdit->setText("it");
+ lineEdit->show();
+
+ QLineEdit *lineEdit2 = new QLineEdit(&window); // has no completer!
+ lineEdit2->show();
+
+ comboBox->setFocus();
+ QTRY_VERIFY(completer.widget() == comboBox);
+ lineEdit->setFocus();
+ QTRY_VERIFY(completer.widget() == lineEdit);
+ comboBox->setFocus();
+ QTRY_VERIFY(completer.widget() == comboBox);
+ lineEdit2->setFocus();
+ QTRY_VERIFY(completer.widget() == comboBox);
+}
+
+void tst_QCompleter::dynamicSortOrder()
+{
+ QStandardItemModel model;
+ QCompleter completer(&model);
+ completer.setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ QStandardItem *root = model.invisibleRootItem();
+ for (int i = 0; i < 20; i++) {
+ root->appendRow(new QStandardItem(QString("%1").arg(i)));
+ }
+ root->appendRow(new QStandardItem("13"));
+ root->sortChildren(0, Qt::AscendingOrder);
+ completer.setCompletionPrefix("1");
+ QCOMPARE(completer.completionCount(), 12);
+ completer.setCompletionPrefix("13");
+ QCOMPARE(completer.completionCount(), 2);
+
+ root->sortChildren(0, Qt::DescendingOrder);
+ completer.setCompletionPrefix("13");
+ QCOMPARE(completer.completionCount(), 2);
+ completer.setCompletionPrefix("1");
+ QCOMPARE(completer.completionCount(), 12);
+}
+
+void tst_QCompleter::disabledItems()
+{
+ QLineEdit lineEdit;
+ QStandardItemModel *model = new QStandardItemModel(&lineEdit);
+ QStandardItem *suggestions = new QStandardItem("suggestions");
+ suggestions->setEnabled(false);
+ model->appendRow(suggestions);
+ model->appendRow(new QStandardItem("suggestions Enabled"));
+ QCompleter *completer = new QCompleter(model, &lineEdit);
+ QSignalSpy spy(completer, SIGNAL(activated(const QString &)));
+ lineEdit.setCompleter(completer);
+ lineEdit.show();
+
+ QTest::keyPress(&lineEdit, Qt::Key_S);
+ QTest::keyPress(&lineEdit, Qt::Key_U);
+ QAbstractItemView *view = lineEdit.completer()->popup();
+ QVERIFY(view->isVisible());
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->visualRect(view->model()->index(0, 0)).center());
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(view->isVisible());
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->visualRect(view->model()->index(1, 0)).center());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!view->isVisible());
+}
+
+void tst_QCompleter::task178797_activatedOnReturn()
+{
+ QStringList words;
+ words << "foobar1" << "foobar2";
+ QLineEdit *ledit = new QLineEdit;
+ QCompleter *completer = new QCompleter(words);
+ ledit->setCompleter(completer);
+ QSignalSpy spy(completer, SIGNAL(activated(const QString)));
+ QCOMPARE(spy.count(), 0);
+ ledit->show();
+ QTest::keyClick(ledit, Qt::Key_F);
+ qApp->processEvents();
+ QVERIFY(qApp->activePopupWidget());
+ QTest::keyClick(qApp->activePopupWidget(), Qt::Key_Down);
+ qApp->processEvents();
+ QTest::keyClick(qApp->activePopupWidget(), Qt::Key_Return);
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+}
+
+class task189564_StringListModel : public QStringListModel
+{
+ const QString omitString;
+ Qt::ItemFlags flags(const QModelIndex &index) const
+ {
+ Qt::ItemFlags flags = Qt::ItemIsEnabled;
+ if (data(index, Qt::DisplayRole).toString() != omitString)
+ flags |= Qt::ItemIsSelectable;
+ return flags;
+ }
+public:
+ task189564_StringListModel(const QString &omitString, QObject *parent = 0)
+ : QStringListModel(parent)
+ , omitString(omitString)
+ {
+ }
+};
+
+void tst_QCompleter::task189564_omitNonSelectableItems()
+{
+ const QString prefix("a");
+ const int n = 5;
+
+ QStringList strings;
+ for (int i = 0; i < n; ++i)
+ strings << QString("%1%2").arg(prefix).arg(i);
+ const QString omitString(strings.at(n / 2));
+ task189564_StringListModel model(omitString);
+ model.setStringList(strings);
+ QCompleter completer_(&model);
+ completer_.setCompletionPrefix(prefix);
+
+ QAbstractItemModel *completionModel = completer_.completionModel();
+ QModelIndexList matches1 =
+ completionModel->match(completionModel->index(0, 0), Qt::DisplayRole, prefix, -1);
+ QCOMPARE(matches1.size(), n - 1);
+ QModelIndexList matches2 =
+ completionModel->match(completionModel->index(0, 0), Qt::DisplayRole, omitString);
+ QVERIFY(matches2.isEmpty());
+}
+
+class task246056_ComboBox : public QComboBox
+{
+ Q_OBJECT
+public:
+ task246056_ComboBox()
+ {
+ setEditable(true);
+ setInsertPolicy(NoInsert);
+ if (completer()) {
+ completer()->setCompletionMode(QCompleter::PopupCompletion);
+ completer()->setCompletionRole(Qt::DisplayRole);
+ connect(lineEdit(), SIGNAL(editingFinished()), SLOT(setCompletionPrefix()));
+ }
+ }
+private slots:
+ void setCompletionPrefix() { completer()->setCompletionPrefix(lineEdit()->text()); }
+};
+
+void tst_QCompleter::task246056_setCompletionPrefix()
+{
+ task246056_ComboBox *comboBox = new task246056_ComboBox;
+ QVERIFY(comboBox->completer());
+ comboBox->addItem("");
+ comboBox->addItem("a1");
+ comboBox->addItem("a2");
+ comboBox->show();
+ comboBox->setFocus();
+ QTest::qWait(100);
+ QTest::keyPress(comboBox, 'a');
+ QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Down);
+ QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Down);
+ QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Enter); // don't crash!
+}
+
+class task250064_TextEdit : public QTextEdit
+{
+public:
+ QCompleter *completer;
+
+ task250064_TextEdit()
+ {
+ completer = new QCompleter;
+ completer->setWidget(this);
+ }
+
+ void keyPressEvent (QKeyEvent *e)
+ {
+ completer->popup();
+ QTextEdit::keyPressEvent(e);
+ }
+};
+
+class task250064_Widget : public QWidget
+{
+ Q_OBJECT
+public:
+ task250064_TextEdit *textEdit;
+
+ task250064_Widget(task250064_TextEdit *textEdit)
+ : textEdit(textEdit)
+ {
+ QTabWidget *tabWidget = new QTabWidget;
+ tabWidget->setFocusPolicy(Qt::ClickFocus);
+ tabWidget->addTab(textEdit, "untitled");
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(tabWidget);
+
+ textEdit->setPlainText("bla bla bla");
+ textEdit->setFocus();
+ }
+
+ void setCompletionModel()
+ {
+ textEdit->completer->setModel(0);
+ }
+};
+
+void tst_QCompleter::task250064_lostFocus()
+{
+ task250064_TextEdit *textEdit = new task250064_TextEdit;
+ task250064_Widget *widget = new task250064_Widget(textEdit);
+ widget->show();
+ QTest::qWait(100);
+ QTest::keyPress(textEdit, 'a');
+ Qt::FocusPolicy origPolicy = textEdit->focusPolicy();
+ QVERIFY(origPolicy != Qt::NoFocus);
+ widget->setCompletionModel();
+ QCOMPARE(textEdit->focusPolicy(), origPolicy);
+}
+
+void tst_QCompleter::task253125_lineEditCompletion_data()
+{
+ QTest::addColumn<QStringList>("list");
+ QTest::addColumn<int>("completionMode");
+
+ QStringList list = QStringList()
+ << "alpha" << "beta" << "gamma" << "delta" << "epsilon" << "zeta"
+ << "eta" << "theta" << "iota" << "kappa" << "lambda" << "mu"
+ << "nu" << "xi" << "omicron" << "pi" << "rho" << "sigma"
+ << "tau" << "upsilon" << "phi" << "chi" << "psi" << "omega";
+
+ QTest::newRow("Inline") << list << (int)QCompleter::InlineCompletion;
+ QTest::newRow("Filtered") << list << (int)QCompleter::PopupCompletion;
+ QTest::newRow("Unfiltered") << list << (int)QCompleter::UnfilteredPopupCompletion;
+}
+
+void tst_QCompleter::task253125_lineEditCompletion()
+{
+ QFETCH(QStringList, list);
+ QFETCH(int, completionMode);
+
+ QStringListModel *model = new QStringListModel;
+ model->setStringList(list);
+
+ QCompleter *completer = new QCompleter(list);
+ completer->setModel(model);
+ completer->setCompletionMode((QCompleter::CompletionMode)completionMode);
+
+ QLineEdit edit;
+ edit.setCompleter(completer);
+ edit.show();
+ edit.setFocus();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&edit);
+#endif
+ QTest::qWait(10);
+ QApplication::setActiveWindow(&edit);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&edit));
+
+ QTest::keyClick(&edit, 'i');
+ QCOMPARE(edit.completer()->currentCompletion(), QString("iota"));
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
+
+ QCOMPARE(edit.text(), QString("iota"));
+
+ delete completer;
+ delete model;
+}
+
+void tst_QCompleter::task247560_keyboardNavigation()
+{
+ QStandardItemModel model;
+
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ model.setItem(i, j, new QStandardItem(QString("row %1 column %2").arg(i).arg(j)));
+ }
+ }
+
+
+ QCompleter completer(&model);
+ completer.setCompletionColumn(1);
+
+ QLineEdit edit;
+ edit.setCompleter(&completer);
+ edit.show();
+ edit.setFocus();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&edit);
+#endif
+
+ QTest::qWait(10);
+ QApplication::setActiveWindow(&edit);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&edit));
+
+ QTest::keyClick(&edit, 'r');
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
+
+ QCOMPARE(edit.text(), QString("row 1 column 1"));
+
+ edit.clear();
+
+ QTest::keyClick(&edit, 'r');
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Up);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Up);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
+
+ QCOMPARE(edit.text(), QString("row 3 column 1"));
+}
+
+void tst_QCompleter::QTBUG_14292_filesystem()
+{
+ FileSystem fs;
+ QDir tmpDir = QDir::currentPath();
+
+ qsrand(QTime::currentTime().msec());
+ QString d = "tst_QCompleter_" + QString::number(qrand());
+ QVERIFY(fs.createDirectory(tmpDir.filePath(d)));
+
+ QVERIFY(tmpDir.cd(d));
+ QVERIFY(fs.createDirectory(tmpDir.filePath("hello")));
+ QVERIFY(fs.createDirectory(tmpDir.filePath("holla")));
+
+ QLineEdit edit;
+ QCompleter comp;
+ QFileSystemModel model;
+ model.setRootPath(tmpDir.path());
+ comp.setModel(&model);
+ edit.setCompleter(&comp);
+
+ edit.show();
+ QApplication::setActiveWindow(&edit);
+ QTest::qWaitForWindowShown(&edit);
+ QTRY_VERIFY(QApplication::activeWindow() == &edit);
+ edit.setFocus();
+ QTRY_VERIFY(edit.hasFocus());
+
+ QVERIFY(!comp.popup()->isVisible());
+ edit.setText(tmpDir.path());
+ QTest::keyClick(&edit, '/');
+ QTRY_VERIFY(comp.popup()->isVisible());
+ QCOMPARE(comp.popup()->model()->rowCount(), 2);
+ QApplication::processEvents();
+ QTest::keyClick(&edit, 'h');
+ QCOMPARE(comp.popup()->model()->rowCount(), 2);
+ QTest::keyClick(&edit, 'e');
+ QCOMPARE(comp.popup()->model()->rowCount(), 1);
+ QTest::keyClick(&edit, 'r');
+ QTRY_VERIFY(!comp.popup()->isVisible());
+ QVERIFY(fs.createDirectory(tmpDir.filePath("hero")));
+ QTRY_VERIFY(comp.popup()->isVisible());
+ QCOMPARE(comp.popup()->model()->rowCount(), 1);
+ QTest::keyClick(comp.popup(), Qt::Key_Escape);
+ QTRY_VERIFY(!comp.popup()->isVisible());
+ QVERIFY(fs.createDirectory(tmpDir.filePath("nothingThere")));
+ //there is no reason creating a file should open a popup, it did in Qt 4.7.0
+ QTest::qWait(60);
+ QVERIFY(!comp.popup()->isVisible());
+
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QTRY_VERIFY(comp.popup()->isVisible());
+ QCOMPARE(comp.popup()->model()->rowCount(), 2);
+ QTest::keyClick(&edit, 'm');
+ QTRY_VERIFY(!comp.popup()->isVisible());
+
+ QWidget w;
+ w.show();
+ QApplication::setActiveWindow(&w);
+ QTest::qWaitForWindowShown(&w);
+ QTRY_VERIFY(!edit.hasFocus() && !comp.popup()->hasFocus());
+
+ QVERIFY(fs.createDirectory(tmpDir.filePath("hemo")));
+ //there is no reason creating a file should open a popup, it did in Qt 4.7.0
+ QTest::qWait(60);
+ QVERIFY(!comp.popup()->isVisible());
+}
+
+QTEST_MAIN(tst_QCompleter)
+#include "tst_qcompleter.moc"
diff --git a/tests/auto/widgets/util/qscroller/qscroller.pro b/tests/auto/widgets/util/qscroller/qscroller.pro
new file mode 100644
index 0000000000..de202d66aa
--- /dev/null
+++ b/tests/auto/widgets/util/qscroller/qscroller.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+
+QT += widgets
+SOURCES += tst_qscroller.cpp
diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
new file mode 100644
index 0000000000..9ed4965d45
--- /dev/null
+++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
@@ -0,0 +1,530 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QtWidgets>
+#include <QtTest>
+// #include <QDebug>
+
+class tst_QScrollerWidget : public QWidget
+{
+public:
+ tst_QScrollerWidget()
+ : QWidget()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ receivedPrepare = false;
+ receivedScroll = false;
+ receivedFirst = false;
+ receivedLast = false;
+ receivedOvershoot = false;
+ }
+
+ bool event(QEvent *e)
+ {
+ switch (e->type()) {
+ case QEvent::Gesture:
+ e->setAccepted(false); // better reject the event or QGestureManager will make trouble
+ return false;
+
+ case QEvent::ScrollPrepare:
+ {
+ receivedPrepare = true;
+ QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(e);
+ se->setViewportSize(QSizeF(100,100));
+ se->setContentPosRange(scrollArea);
+ se->setContentPos(scrollPosition);
+ se->accept();
+ return true;
+ }
+
+ case QEvent::Scroll:
+ {
+ receivedScroll = true;
+ QScrollEvent *se = static_cast<QScrollEvent *>(e);
+ // qDebug() << "Scroll for"<<this<<"pos"<<se->scrollPos()<<"ov"<<se->overshoot()<<"first"<<se->isFirst()<<"last"<<se->isLast();
+
+ if (se->scrollState() == QScrollEvent::ScrollStarted)
+ receivedFirst = true;
+ if (se->scrollState() == QScrollEvent::ScrollFinished)
+ receivedLast = true;
+
+ currentPos = se->contentPos();
+ overshoot = se->overshootDistance();
+ if (!qFuzzyCompare( overshoot.x() + 1.0, 1.0 ) ||
+ !qFuzzyCompare( overshoot.y() + 1.0, 1.0 ))
+ receivedOvershoot = true;
+ return true;
+ }
+
+ default:
+ return QObject::event(e);
+ }
+ }
+
+
+ QRectF scrollArea;
+ QPointF scrollPosition;
+
+ bool receivedPrepare;
+ bool receivedScroll;
+ bool receivedFirst;
+ bool receivedLast;
+ bool receivedOvershoot;
+
+ QPointF currentPos;
+ QPointF overshoot;
+};
+
+
+class tst_QScroller : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QScroller() { }
+ ~tst_QScroller() { }
+
+private:
+ void kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd);
+ void kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd);
+
+private slots:
+ void staticScrollers();
+ void scrollerProperties();
+ void scrollTo();
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+ void scroll();
+ void overshoot();
+#endif
+};
+
+/*! \internal
+ Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling.
+ Tests some in between states but does not wait until scrolling is finished.
+*/
+void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd)
+{
+ sw->scrollPosition = from;
+ sw->currentPos= from;
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ QScrollerProperties sp1 = QScroller::scroller(sw)->scrollerProperties();
+ int fps = 60;
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // send the touch begin event
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(touchStart);
+ touchPoint.setScenePos(touchStart);
+ touchPoint.setScreenPos(touchStart);
+ QTouchEvent touchEvent1(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent1);
+
+ QCOMPARE( s1->state(), QScroller::Pressed );
+
+ // send the touch update far enough to trigger a scroll
+ QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second.
+ touchPoint.setPos(touchUpdate);
+ touchPoint.setScenePos(touchUpdate);
+ touchPoint.setScreenPos(touchUpdate);
+ QTouchEvent touchEvent2(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent2);
+
+ QCOMPARE( s1->state(), QScroller::Dragging );
+ QCOMPARE( sw->receivedPrepare, true );
+
+
+ QTest::qWait(1000 / fps * 2); // wait until the first scroll move
+ QCOMPARE( sw->receivedFirst, true );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // note that the scrolling goes in a different direction than the mouse move
+ QPoint calculatedPos = from.toPoint() - touchUpdate - touchStart;
+ QVERIFY(qAbs(sw->currentPos.x() - calculatedPos.x()) < 1.0);
+ QVERIFY(qAbs(sw->currentPos.y() - calculatedPos.y()) < 1.0);
+
+ // send the touch end
+ touchPoint.setPos(touchEnd);
+ touchPoint.setScenePos(touchEnd);
+ touchPoint.setScreenPos(touchEnd);
+ QTouchEvent touchEvent5(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent5);
+}
+
+/*! \internal
+ Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling.
+ This function does not have any in between tests, it does not expect the scroller to actually scroll.
+*/
+void tst_QScroller::kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd)
+{
+ sw->scrollPosition = from;
+ sw->currentPos = from;
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ QScrollerProperties sp1 = s1->scrollerProperties();
+ int fps = 60;
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // send the touch begin event
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(touchStart);
+ touchPoint.setScenePos(touchStart);
+ touchPoint.setScreenPos(touchStart);
+ QTouchEvent touchEvent1(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent1);
+
+ // send the touch update far enough to trigger a scroll
+ QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second.
+ touchPoint.setPos(touchUpdate);
+ touchPoint.setScenePos(touchUpdate);
+ touchPoint.setScreenPos(touchUpdate);
+ QTouchEvent touchEvent2(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent2);
+
+ QTest::qWait(1000 / fps * 2); // wait until the first scroll move
+
+ // send the touch end
+ touchPoint.setPos(touchEnd);
+ touchPoint.setScenePos(touchEnd);
+ touchPoint.setScreenPos(touchEnd);
+ QTouchEvent touchEvent5(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent5);
+}
+
+
+void tst_QScroller::staticScrollers()
+{
+ // scrollers
+ {
+ QObject *o1 = new QObject(this);
+ QObject *o2 = new QObject(this);
+
+ // get scroller for object
+ QScroller *s1 = QScroller::scroller(o1);
+ QScroller *s2 = QScroller::scroller(o2);
+
+ QVERIFY(s1);
+ QVERIFY(s2);
+ QVERIFY(s1 != s2);
+
+ QVERIFY(!QScroller::scroller(static_cast<const QObject*>(0)));
+ QCOMPARE(QScroller::scroller(o1), s1);
+
+ delete o1;
+ delete o2;
+ }
+
+ // the same for properties
+ {
+ QObject *o1 = new QObject(this);
+ QObject *o2 = new QObject(this);
+
+ // get scroller for object
+ QScrollerProperties sp1 = QScroller::scroller(o1)->scrollerProperties();
+ QScrollerProperties sp2 = QScroller::scroller(o2)->scrollerProperties();
+
+ // default properties should be the same
+ QVERIFY(sp1 == sp2);
+
+ QCOMPARE(QScroller::scroller(o1)->scrollerProperties(), sp1);
+
+ delete o1;
+ delete o2;
+ }
+}
+
+void tst_QScroller::scrollerProperties()
+{
+ QObject *o1 = new QObject(this);
+ QScrollerProperties sp1 = QScroller::scroller(o1)->scrollerProperties();
+
+ QScrollerProperties::ScrollMetric metrics[] =
+ {
+ QScrollerProperties::MousePressEventDelay, // qreal [s]
+ QScrollerProperties::DragStartDistance, // qreal [m]
+ QScrollerProperties::DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF)
+ QScrollerProperties::AxisLockThreshold, // qreal [0..1] atan(|min(dx,dy)|/|max(dx,dy)|)
+
+ QScrollerProperties::DecelerationFactor, // slope of the curve
+
+ QScrollerProperties::MinimumVelocity, // qreal [m/s]
+ QScrollerProperties::MaximumVelocity, // qreal [m/s]
+ QScrollerProperties::MaximumClickThroughVelocity, // qreal [m/s]
+
+ QScrollerProperties::AcceleratingFlickMaximumTime, // qreal [s]
+ QScrollerProperties::AcceleratingFlickSpeedupFactor, // qreal [1..]
+
+ QScrollerProperties::SnapPositionRatio, // qreal [0..1]
+ QScrollerProperties::SnapTime, // qreal [s]
+
+ QScrollerProperties::OvershootDragResistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootDragDistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootScrollDistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootScrollTime, // qreal [s]
+ };
+
+ for (unsigned int i = 0; i < sizeof(metrics) / sizeof(metrics[0]); i++) {
+ sp1.setScrollMetric(metrics[i], 0.9);
+ QCOMPARE(sp1.scrollMetric(metrics[i]).toDouble(), 0.9);
+ }
+ sp1.setScrollMetric(QScrollerProperties::ScrollingCurve, QEasingCurve(QEasingCurve::OutQuart));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::ScrollingCurve).toEasingCurve().type(), QEasingCurve::OutQuart);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::HorizontalOvershootPolicy).value<QScrollerProperties::OvershootPolicy>(), QScrollerProperties::OvershootAlwaysOff);
+
+ sp1.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::VerticalOvershootPolicy).value<QScrollerProperties::OvershootPolicy>(), QScrollerProperties::OvershootAlwaysOn);
+
+ sp1.setScrollMetric(QScrollerProperties::FrameRate, QVariant::fromValue(QScrollerProperties::Fps20));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::FrameRate).value<QScrollerProperties::FrameRates>(), QScrollerProperties::Fps20);
+}
+
+void tst_QScroller::scrollTo()
+{
+ {
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF( 0, 0, 1000, 1000 );
+ sw->scrollPosition = QPointF( 500, 500 );
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ // a normal scroll
+ s1->scrollTo(QPointF(100,100), 100);
+ QTest::qWait(200);
+
+ QCOMPARE( sw->receivedPrepare, true );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedFirst, true );
+ QCOMPARE( sw->receivedLast, true );
+ QCOMPARE( sw->receivedOvershoot, false );
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 100 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 100 ));
+
+ delete sw;
+ }
+}
+
+// Mac OS X < 10.6 does not support QTouchEvents.
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+void tst_QScroller::scroll()
+{
+ // -- good case. normal scroll
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+ QScroller::grabGesture(sw, QScroller::TouchGesture);
+ sw->setGeometry(100, 100, 400, 300);
+
+ QScroller *s1 = QScroller::scroller(sw);
+ kineticScroll(sw, QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
+ // now we should be scrolling
+ QCOMPARE( s1->state(), QScroller::Scrolling );
+
+ // wait until finished, check that no further first scroll is send
+ sw->receivedFirst = false;
+ sw->receivedScroll = false;
+ while (s1->state() == QScroller::Scrolling)
+ QTest::qWait(100);
+
+ QCOMPARE( sw->receivedFirst, false );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedLast, true );
+ QVERIFY(sw->currentPos.x() < 400);
+ QVERIFY(sw->currentPos.y() < 400);
+
+ // -- try to scroll when nothing to scroll
+
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QCOMPARE(sw->currentPos.x(), 0.0);
+ QCOMPARE(sw->currentPos.y(), 500.0);
+
+ delete sw;
+}
+#endif
+
+// Mac OS X < 10.6 does not support QTouchEvents.
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+void tst_QScroller::overshoot()
+{
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+ QScroller::grabGesture(sw, QScroller::TouchGesture);
+ sw->setGeometry(100, 100, 400, 300);
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QScrollerProperties sp1 = s1->scrollerProperties();
+
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.5);
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.2);
+ sp1.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.2);
+
+ // -- try to scroll with overshoot (when scrollable good case)
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, true );
+
+ // -- try to scroll with overshoot (when scrollable bad case)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // -- try to scroll with overshoot (always on)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, true );
+
+ // -- try to scroll with overshoot (always off)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // -- try to scroll with overshoot (always on but max overshoot = 0)
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.0);
+ sp1.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.0);
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ delete sw;
+}
+#endif
+
+QTEST_MAIN(tst_QScroller)
+
+#include "tst_qscroller.moc"
diff --git a/tests/auto/widgets/util/qsystemtrayicon/.gitignore b/tests/auto/widgets/util/qsystemtrayicon/.gitignore
new file mode 100644
index 0000000000..6da1f79209
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/.gitignore
@@ -0,0 +1 @@
+tst_qsystemtrayicon
diff --git a/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png b/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png
new file mode 100644
index 0000000000..7528931ed8
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png
Binary files differ
diff --git a/tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro b/tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro
new file mode 100644
index 0000000000..8a6ea3d0a9
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qsystemtrayicon.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qsystemtrayicon.cpp
+
+
diff --git a/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp b/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp
new file mode 100644
index 0000000000..a4a5ed7ad9
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qsystemtrayicon.h>
+#include <qmenu.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QSystemTrayIcon: public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QSystemTrayIcon();
+ virtual ~tst_QSystemTrayIcon();
+
+private slots:
+ void getSetCheck();
+ void showHide();
+ void showMessage();
+ void supportsMessages();
+ void lastWindowClosed();
+};
+
+tst_QSystemTrayIcon::tst_QSystemTrayIcon()
+{
+}
+
+tst_QSystemTrayIcon::~tst_QSystemTrayIcon()
+{
+}
+
+// Testing get/set functions
+void tst_QSystemTrayIcon::showHide()
+{
+ QSystemTrayIcon icon;
+ icon.setIcon(QIcon("icons/icon.png"));
+ icon.show();
+ icon.setIcon(QIcon("icons/icon.png"));
+ icon.hide();
+}
+
+// Testing get/set functions
+void tst_QSystemTrayIcon::showMessage()
+{
+ QSystemTrayIcon icon;
+ icon.setIcon(QIcon("icons/icon.png"));
+
+ icon.showMessage("Title", "Messagecontents");
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::NoIcon);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Warning);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Critical);
+
+ icon.show();
+ icon.showMessage("Title", "Messagecontents");
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::NoIcon);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Warning);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Critical);
+}
+
+// Testing get/set functions
+void tst_QSystemTrayIcon::getSetCheck()
+{
+ QSystemTrayIcon icon;
+ QCOMPARE(true, icon.toolTip().isEmpty());
+ icon.setToolTip("testToolTip");
+ QCOMPARE(true, "testToolTip" == icon.toolTip());
+
+ QCOMPARE(true, icon.icon().isNull());
+ icon.setIcon(QIcon("icons/icon.png"));
+ QCOMPARE(false, icon.icon().isNull());
+
+ QMenu menu;
+ QCOMPARE(true, icon.contextMenu() == 0);
+ icon.setContextMenu(&menu);
+ QCOMPARE(false, icon.contextMenu() == 0);
+}
+
+void tst_QSystemTrayIcon::supportsMessages()
+{
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20978 QSystemTrayIcon is unimplemented for qpa", Abort);
+#endif
+
+#if !defined(Q_WS_QWS)
+ QCOMPARE(QSystemTrayIcon::supportsMessages(), true );
+#else
+ QCOMPARE(QSystemTrayIcon::supportsMessages(), false );
+#endif
+
+}
+
+void tst_QSystemTrayIcon::lastWindowClosed()
+{
+ QSignalSpy spy(qApp, SIGNAL(lastWindowClosed()));
+ QWidget window;
+ QSystemTrayIcon icon;
+ icon.setIcon(QIcon("whatever.png"));
+ icon.show();
+ window.show();
+ QTimer::singleShot(2500, &window, SLOT(close()));
+ QTimer::singleShot(20000, qApp, SLOT(quit())); // in case the test fails
+ qApp->exec();
+ QVERIFY(spy.count() == 1);
+}
+
+QTEST_MAIN(tst_QSystemTrayIcon)
+#include "tst_qsystemtrayicon.moc"
diff --git a/tests/auto/widgets/util/qundogroup/.gitignore b/tests/auto/widgets/util/qundogroup/.gitignore
new file mode 100644
index 0000000000..bc3e8c4691
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/.gitignore
@@ -0,0 +1 @@
+tst_qundogroup
diff --git a/tests/auto/widgets/util/qundogroup/qundogroup.pro b/tests/auto/widgets/util/qundogroup/qundogroup.pro
new file mode 100644
index 0000000000..c2b6ceb038
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/qundogroup.pro
@@ -0,0 +1,4 @@
+CONFIG += qttest_p4
+QT += widgets
+SOURCES += tst_qundogroup.cpp
+TARGET = tst_qundogroup
diff --git a/tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts b/tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts
new file mode 100644
index 0000000000..a059bcb486
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en">
+<context>
+ <name>QUndoGroup</name>
+ <message>
+ <source>Undo %1</source>
+ <translation>undo-prefix %1 undo-suffix</translation>
+ </message>
+ <message>
+ <source>Undo</source>
+ <comment>Default text for undo action</comment>
+ <translation>Undo-default-text</translation>
+ </message>
+ <message>
+ <source>Redo %1</source>
+ <translation>redo-prefix %1 redo-suffix</translation>
+ </message>
+ <message>
+ <source>Redo</source>
+ <comment>Default text for redo action</comment>
+ <translation>Redo-default-text</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp b/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp
new file mode 100644
index 0000000000..6d51252e22
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp
@@ -0,0 +1,668 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QUndoGroup>
+#include <QUndoStack>
+#include <QAction>
+
+// Temporarily disabling IRIX due to build issuues with GCC
+#if !defined(__sgi) || defined(__sgi) && !defined(__GNUC__)
+
+/******************************************************************************
+** Commands
+*/
+
+class InsertCommand : public QUndoCommand
+{
+public:
+ InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class RemoveCommand : public QUndoCommand
+{
+public:
+ RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class AppendCommand : public QUndoCommand
+{
+public:
+ AppendCommand(QString *str, const QString &text, QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+ virtual int id() const;
+ virtual bool mergeWith(const QUndoCommand *other);
+
+ bool merged;
+
+private:
+ QString *m_str;
+ QString m_text;
+};
+
+InsertCommand::InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx);
+
+ setText("insert");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = text;
+}
+
+void InsertCommand::redo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+void InsertCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+RemoveCommand::RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx + len);
+
+ setText("remove");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = m_str->mid(m_idx, len);
+}
+
+void RemoveCommand::redo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+void RemoveCommand::undo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+AppendCommand::AppendCommand(QString *str, const QString &text, QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ setText("append");
+
+ m_str = str;
+ m_text = text;
+ merged = false;
+}
+
+void AppendCommand::redo()
+{
+ m_str->append(m_text);
+}
+
+void AppendCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_str->length() - m_text.length()), m_text);
+
+ m_str->truncate(m_str->length() - m_text.length());
+}
+
+int AppendCommand::id() const
+{
+ return 1;
+}
+
+bool AppendCommand::mergeWith(const QUndoCommand *other)
+{
+ if (other->id() != id())
+ return false;
+ m_text += static_cast<const AppendCommand*>(other)->m_text;
+ merged = true;
+ return true;
+}
+
+/******************************************************************************
+** tst_QUndoStack
+*/
+
+class tst_QUndoGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QUndoGroup();
+
+private slots:
+ void setActive();
+ void addRemoveStack();
+ void deleteStack();
+ void checkSignals();
+ void addStackAndDie();
+ void commandTextFormat();
+};
+
+tst_QUndoGroup::tst_QUndoGroup()
+{
+}
+
+void tst_QUndoGroup::setActive()
+{
+ QUndoGroup group;
+ QUndoStack stack1(&group), stack2(&group);
+
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), false);
+
+ QUndoStack stack3;
+ QCOMPARE(stack3.isActive(), true);
+
+ group.addStack(&stack3);
+ QCOMPARE(stack3.isActive(), false);
+
+ stack1.setActive();
+ QCOMPARE(group.activeStack(), &stack1);
+ QCOMPARE(stack1.isActive(), true);
+ QCOMPARE(stack2.isActive(), false);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.setActiveStack(&stack2);
+ QCOMPARE(group.activeStack(), &stack2);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+}
+
+void tst_QUndoGroup::addRemoveStack()
+{
+ QUndoGroup group;
+
+ QUndoStack stack1(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack1);
+
+ QUndoStack stack2;
+ group.addStack(&stack2);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack1 << &stack2);
+
+ group.addStack(&stack1);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack1 << &stack2);
+
+ group.removeStack(&stack1);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack2);
+
+ group.removeStack(&stack1);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack2);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>());
+}
+
+void tst_QUndoGroup::deleteStack()
+{
+ QUndoGroup group;
+
+ QUndoStack *stack1 = new QUndoStack(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+
+ stack1->setActive();
+ QCOMPARE(group.activeStack(), stack1);
+
+ QUndoStack *stack2 = new QUndoStack(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1 << stack2);
+ QCOMPARE(group.activeStack(), stack1);
+
+ QUndoStack *stack3 = new QUndoStack(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1 << stack2 << stack3);
+ QCOMPARE(group.activeStack(), stack1);
+
+ delete stack2;
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1 << stack3);
+ QCOMPARE(group.activeStack(), stack1);
+
+ delete stack1;
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack3);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+
+ stack3->setActive(false);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+
+ stack3->setActive(true);
+ QCOMPARE(group.activeStack(), stack3);
+
+ group.removeStack(stack3);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>());
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+
+ delete stack3;
+}
+
+static QString glue(const QString &s1, const QString &s2)
+{
+ QString result;
+
+ result.append(s1);
+ if (!s1.isEmpty() && !s2.isEmpty())
+ result.append(' ');
+ result.append(s2);
+
+ return result;
+}
+
+#define CHECK_STATE(_activeStack, _clean, _canUndo, _undoText, _canRedo, _redoText, \
+ _cleanChanged, _indexChanged, _undoChanged, _redoChanged) \
+ QCOMPARE(group.activeStack(), (QUndoStack*)_activeStack); \
+ QCOMPARE(group.isClean(), _clean); \
+ QCOMPARE(group.canUndo(), _canUndo); \
+ QCOMPARE(group.undoText(), QString(_undoText)); \
+ QCOMPARE(group.canRedo(), _canRedo); \
+ QCOMPARE(group.redoText(), QString(_redoText)); \
+ if (_indexChanged) { \
+ QCOMPARE(indexChangedSpy.count(), 1); \
+ indexChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(indexChangedSpy.count(), 0); \
+ } \
+ if (_cleanChanged) { \
+ QCOMPARE(cleanChangedSpy.count(), 1); \
+ QCOMPARE(cleanChangedSpy.at(0).at(0).toBool(), _clean); \
+ cleanChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(cleanChangedSpy.count(), 0); \
+ } \
+ if (_undoChanged) { \
+ QCOMPARE(canUndoChangedSpy.count(), 1); \
+ QCOMPARE(canUndoChangedSpy.at(0).at(0).toBool(), _canUndo); \
+ QCOMPARE(undo_action->isEnabled(), _canUndo); \
+ QCOMPARE(undoTextChangedSpy.count(), 1); \
+ QCOMPARE(undoTextChangedSpy.at(0).at(0).toString(), QString(_undoText)); \
+ QCOMPARE(undo_action->text(), glue("foo", _undoText)); \
+ canUndoChangedSpy.clear(); \
+ undoTextChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(canUndoChangedSpy.count(), 0); \
+ QCOMPARE(undoTextChangedSpy.count(), 0); \
+ } \
+ if (_redoChanged) { \
+ QCOMPARE(canRedoChangedSpy.count(), 1); \
+ QCOMPARE(canRedoChangedSpy.at(0).at(0).toBool(), _canRedo); \
+ QCOMPARE(redo_action->isEnabled(), _canRedo); \
+ QCOMPARE(redoTextChangedSpy.count(), 1); \
+ QCOMPARE(redoTextChangedSpy.at(0).at(0).toString(), QString(_redoText)); \
+ QCOMPARE(redo_action->text(), glue("bar", _redoText)); \
+ canRedoChangedSpy.clear(); \
+ redoTextChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(canRedoChangedSpy.count(), 0); \
+ QCOMPARE(redoTextChangedSpy.count(), 0); \
+ }
+
+void tst_QUndoGroup::checkSignals()
+{
+ QUndoGroup group;
+ QAction *undo_action = group.createUndoAction(0, QString("foo"));
+ QAction *redo_action = group.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&group, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&group, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&group, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&group, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&group, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&group, SIGNAL(redoTextChanged(QString)));
+
+ QString str;
+
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.undo();
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.redo();
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ QUndoStack *stack1 = new QUndoStack(&group);
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ stack1->push(new AppendCommand(&str, "foo"));
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ stack1->setActive();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->push(new InsertCommand(&str, 0, "bar"));
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->undo();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->undo();
+ CHECK_STATE(stack1, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->undo();
+ CHECK_STATE(stack1, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.undo();
+ CHECK_STATE(stack1, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.redo();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->setActive(false);
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ QUndoStack *stack2 = new QUndoStack(&group);
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ stack2->setActive();
+ CHECK_STATE(stack2, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->setActive();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ delete stack1;
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ delete undo_action;
+ delete redo_action;
+}
+
+void tst_QUndoGroup::addStackAndDie()
+{
+ // Test that QUndoStack doesn't keep a reference to QUndoGroup after the
+ // group is deleted.
+ QUndoStack *stack = new QUndoStack;
+ QUndoGroup *group = new QUndoGroup;
+ group->addStack(stack);
+ delete group;
+ stack->setActive(true);
+ delete stack;
+}
+
+void tst_QUndoGroup::commandTextFormat()
+{
+ QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+ if (QProcess::execute(binDir + "/lrelease -version") != 0) {
+ QSKIP("lrelease is missing or broken", SkipAll);
+ }
+
+ QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/qundogroup.ts"));
+
+ QTranslator translator;
+ QVERIFY(translator.load("testdata/qundogroup.qm"));
+ qApp->installTranslator(&translator);
+
+ QUndoGroup group;
+ QAction *undo_action = group.createUndoAction(0);
+ QAction *redo_action = group.createRedoAction(0);
+
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ QUndoStack stack(&group);
+ stack.setActive();
+ QString str;
+
+ stack.push(new AppendCommand(&str, "foo"));
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ stack.push(new InsertCommand(&str, 0, "bar"));
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix insert redo-suffix"));
+
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix append redo-suffix"));
+
+ qApp->removeTranslator(&translator);
+}
+
+#else
+class tst_QUndoGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QUndoGroup() {}
+
+private slots:
+ void setActive() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void addRemoveStack() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void deleteStack() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void checkSignals() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void addStackAndDie() { QSKIP( "Not tested on irix-g++", SkipAll); }
+};
+#endif
+
+QTEST_MAIN(tst_QUndoGroup)
+
+#include "tst_qundogroup.moc"
+
diff --git a/tests/auto/widgets/util/qundostack/.gitignore b/tests/auto/widgets/util/qundostack/.gitignore
new file mode 100644
index 0000000000..f8faf2771f
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/.gitignore
@@ -0,0 +1 @@
+tst_qundostack
diff --git a/tests/auto/widgets/util/qundostack/qundostack.pro b/tests/auto/widgets/util/qundostack/qundostack.pro
new file mode 100644
index 0000000000..c8cfb70059
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/qundostack.pro
@@ -0,0 +1,4 @@
+CONFIG += qttest_p4
+QT += widgets
+SOURCES += tst_qundostack.cpp
+TARGET = tst_qundostack
diff --git a/tests/auto/widgets/util/qundostack/testdata/qundostack.ts b/tests/auto/widgets/util/qundostack/testdata/qundostack.ts
new file mode 100644
index 0000000000..4584036af2
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/testdata/qundostack.ts
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en">
+<context>
+ <name>QUndoStack</name>
+ <message>
+ <source>Undo %1</source>
+ <translation>undo-prefix %1 undo-suffix</translation>
+ </message>
+ <message>
+ <source>Undo</source>
+ <comment>Default text for undo action</comment>
+ <translation>Undo-default-text</translation>
+ </message>
+ <message>
+ <source>Redo %1</source>
+ <translation>redo-prefix %1 redo-suffix</translation>
+ </message>
+ <message>
+ <source>Redo</source>
+ <comment>Default text for redo action</comment>
+ <translation>Redo-default-text</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/widgets/util/qundostack/tst_qundostack.cpp b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp
new file mode 100644
index 0000000000..834c2d5d50
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp
@@ -0,0 +1,3039 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QAction>
+#include <QUndoStack>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+/******************************************************************************
+** Commands
+*/
+
+class InsertCommand : public QUndoCommand
+{
+public:
+ InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class RemoveCommand : public QUndoCommand
+{
+public:
+ RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class AppendCommand : public QUndoCommand
+{
+public:
+ AppendCommand(QString *str, const QString &text, bool _fail_merge = false,
+ QUndoCommand *parent = 0);
+ ~AppendCommand();
+
+ virtual void undo();
+ virtual void redo();
+ virtual int id() const;
+ virtual bool mergeWith(const QUndoCommand *other);
+
+ bool merged;
+ bool fail_merge;
+ static int delete_cnt;
+
+private:
+ QString *m_str;
+ QString m_text;
+};
+
+class IdleCommand : public QUndoCommand
+{
+public:
+ IdleCommand(QUndoCommand *parent = 0);
+ ~IdleCommand();
+
+ virtual void undo();
+ virtual void redo();
+};
+
+InsertCommand::InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx);
+
+ setText("insert");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = text;
+}
+
+void InsertCommand::redo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+void InsertCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+RemoveCommand::RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx + len);
+
+ setText("remove");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = m_str->mid(m_idx, len);
+}
+
+void RemoveCommand::redo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+void RemoveCommand::undo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+int AppendCommand::delete_cnt = 0;
+
+AppendCommand::AppendCommand(QString *str, const QString &text, bool _fail_merge,
+ QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ setText("append");
+
+ m_str = str;
+ m_text = text;
+ merged = false;
+ fail_merge = _fail_merge;
+}
+
+AppendCommand::~AppendCommand()
+{
+ ++delete_cnt;
+}
+
+void AppendCommand::redo()
+{
+ m_str->append(m_text);
+}
+
+void AppendCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_str->length() - m_text.length()), m_text);
+
+ m_str->truncate(m_str->length() - m_text.length());
+}
+
+int AppendCommand::id() const
+{
+ return 1;
+}
+
+bool AppendCommand::mergeWith(const QUndoCommand *other)
+{
+ if (other->id() != id())
+ return false;
+ if (fail_merge)
+ return false;
+ m_text += static_cast<const AppendCommand*>(other)->m_text;
+ merged = true;
+ return true;
+}
+
+IdleCommand::IdleCommand(QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ // "idle-item" goes to QUndoStack::{redo,undo}Text
+ // "idle-action" goes to all other places (e.g. QUndoView)
+ setText("idle-item\nidle-action");
+}
+
+IdleCommand::~IdleCommand()
+{
+}
+
+void IdleCommand::redo()
+{
+}
+
+void IdleCommand::undo()
+{
+}
+
+/******************************************************************************
+** tst_QUndoStack
+*/
+
+class tst_QUndoStack : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QUndoStack();
+
+private slots:
+ void undoRedo();
+ void setIndex();
+ void setClean();
+ void clear();
+ void childCommand();
+ void macroBeginEnd();
+ void compression();
+ void undoLimit();
+ void commandTextFormat();
+ void separateUndoText();
+};
+
+tst_QUndoStack::tst_QUndoStack()
+{
+}
+
+static QString glue(const QString &s1, const QString &s2)
+{
+ QString result;
+
+ result.append(s1);
+ if (!s1.isEmpty() && !s2.isEmpty())
+ result.append(' ');
+ result.append(s2);
+
+ return result;
+}
+
+static void checkState(QSignalSpy &redoTextChangedSpy,
+ QSignalSpy &canRedoChangedSpy,
+ QSignalSpy &undoTextChangedSpy,
+ QAction *const redoAction,
+ QAction *const undoAction,
+ QSignalSpy &canUndoChangedSpy,
+ QSignalSpy &cleanChangedSpy,
+ QSignalSpy &indexChangedSpy,
+ QUndoStack &stack,
+ const bool _clean,
+ const int _count,
+ const int _index,
+ const bool _canUndo,
+ const QString &_undoText,
+ const bool _canRedo,
+ const QString &_redoText,
+ const bool _cleanChanged,
+ const bool _indexChanged,
+ const bool _undoChanged,
+ const bool _redoChanged)
+{
+ QCOMPARE(stack.count(), _count);
+ QCOMPARE(stack.isClean(), _clean);
+ QCOMPARE(stack.index(), _index);
+ QCOMPARE(stack.canUndo(), _canUndo);
+ QCOMPARE(stack.undoText(), QString(_undoText));
+ QCOMPARE(stack.canRedo(), _canRedo);
+ QCOMPARE(stack.redoText(), QString(_redoText));
+ if (_indexChanged) {
+ QCOMPARE(indexChangedSpy.count(), 1);
+ QCOMPARE(indexChangedSpy.at(0).at(0).toInt(), _index);
+ indexChangedSpy.clear();
+ } else {
+ QCOMPARE(indexChangedSpy.count(), 0);
+ }
+ if (_cleanChanged) {
+ QCOMPARE(cleanChangedSpy.count(), 1);
+ QCOMPARE(cleanChangedSpy.at(0).at(0).toBool(), _clean);
+ cleanChangedSpy.clear();
+ } else {
+ QCOMPARE(cleanChangedSpy.count(), 0);
+ }
+ if (_undoChanged) {
+ QCOMPARE(canUndoChangedSpy.count(), 1);
+ QCOMPARE(canUndoChangedSpy.at(0).at(0).toBool(), _canUndo);
+ QCOMPARE(undoAction->isEnabled(), _canUndo);
+ QCOMPARE(undoTextChangedSpy.count(), 1);
+ QCOMPARE(undoTextChangedSpy.at(0).at(0).toString(), QString(_undoText));
+ QCOMPARE(undoAction->text(), glue("foo", _undoText));
+ canUndoChangedSpy.clear();
+ undoTextChangedSpy.clear();
+ } else {
+ QCOMPARE(canUndoChangedSpy.count(), 0);
+ QCOMPARE(undoTextChangedSpy.count(), 0);
+ }
+ if (_redoChanged) {
+ QCOMPARE(canRedoChangedSpy.count(), 1);
+ QCOMPARE(canRedoChangedSpy.at(0).at(0).toBool(), _canRedo);
+ QCOMPARE(redoAction->isEnabled(), _canRedo);
+ QCOMPARE(redoTextChangedSpy.count(), 1);
+ QCOMPARE(redoTextChangedSpy.at(0).at(0).toString(), QString(_redoText));
+ QCOMPARE(redoAction->text(), glue("bar", _redoText));
+ canRedoChangedSpy.clear();
+ redoTextChangedSpy.clear();
+ } else {
+ QCOMPARE(canRedoChangedSpy.count(), 0);
+ QCOMPARE(redoTextChangedSpy.count(), 0);
+ }
+}
+
+void tst_QUndoStack::undoRedo()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ // push, undo, redo
+
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.undo(); // nothing to undo
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo();
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo(); // nothing to redo
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo(); // nothing to undo
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ // push after undo - check that undone commands get deleted
+
+ stack.redo();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new RemoveCommand(&str, 2, 2));
+ QCOMPARE(str, QString("heo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count - still 2, last command got deleted
+ 2, // index
+ true, // canUndo
+ "remove", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "remove", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "goodbye"));
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count - two commands got deleted
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::setIndex()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ stack.setIndex(10); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(0); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(-10); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(2);
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(0);
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(10); // should set index to 2
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(-10); // should set index to 0
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(1);
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(2);
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::setClean()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ QCOMPARE(stack.cleanIndex(), 0);
+ stack.setClean();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 0);
+
+ stack.push(new InsertCommand(&str, 0, "goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 0);
+
+ stack.setClean();
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.push(new AppendCommand(&str, " cowboy"));
+ QCOMPARE(str, QString("goodbye cowboy"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo(); // reaching clean state from above
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.redo(); // reaching clean state from below
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.push(new InsertCommand(&str, 0, "foo")); // the clean state gets deleted!
+ QCOMPARE(str, QString("foo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), -1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), -1);
+}
+
+void tst_QUndoStack::clear()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(this, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(this, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ stack.clear();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.clear();
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ str.clear();
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(0);
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.clear();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::childCommand()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ QUndoCommand *cmd = new QUndoCommand();
+ cmd->setText("ding");
+ new InsertCommand(&str, 5, "world", cmd);
+ new RemoveCommand(&str, 4, 1, cmd);
+ stack.push(cmd);
+ QCOMPARE(str, QString("hellworld"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "ding", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo();
+ QCOMPARE(str, QString("hellworld"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ delete undoAction;
+ delete redoAction;
+}
+
+void tst_QUndoStack::macroBeginEnd()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ stack.beginMacro("ding");
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setClean(); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.undo(); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.redo(); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(0); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index - endMacro() increments index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "h"));
+ QCOMPARE(str, QString("h"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 1, "owdy"));
+ QCOMPARE(str, QString("howdy"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(2);
+ QCOMPARE(str, QString("h"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.beginMacro("dong"); // the "owdy" command gets deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 1, "ello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new RemoveCommand(&str, 1, 2));
+ QCOMPARE(str, QString("hlo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.beginMacro("dong2");
+ QCOMPARE(str, QString("hlo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new RemoveCommand(&str, 1, 1));
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "dong", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("h"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "dong", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString(""));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 1, // index
+ true, // canUndo
+ "ding", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(3);
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "dong", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(1);
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 1, // index
+ true, // canUndo
+ "ding", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ delete undoAction;
+ delete redoAction;
+}
+
+void tst_QUndoStack::compression()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ QString str;
+
+ AppendCommand::delete_cnt = 0;
+
+ stack.push(new InsertCommand(&str, 0, "ene"));
+ QCOMPARE(str, QString("ene"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, " due")); // #1
+ QCOMPARE(str, QString("ene due"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, " rike")); // #2 should merge
+ QCOMPARE(str, QString("ene due rike"));
+ QCOMPARE(AppendCommand::delete_cnt, 1); // #2 should be deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setClean();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, " fake")); // #3 should NOT merge, since the stack was clean
+ QCOMPARE(str, QString("ene due rike fake")); // and we want to be able to return to this state
+ QCOMPARE(AppendCommand::delete_cnt, 1); // #3 should not be deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("ene due rike"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("ene"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "ma", true)); // #4 clean state gets deleted!
+ QCOMPARE(str, QString("enema"));
+ QCOMPARE(AppendCommand::delete_cnt, 3); // #1 got deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "trix")); // #5 should NOT merge
+ QCOMPARE(str, QString("enematrix"));
+ QCOMPARE(AppendCommand::delete_cnt, 3);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("enema"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ // and now for command compression inside macros
+
+ stack.setClean();
+ QCOMPARE(str, QString("enema"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.beginMacro("ding");
+ QCOMPARE(str, QString("enema"));
+ QCOMPARE(AppendCommand::delete_cnt, 4); // #5 gets deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ AppendCommand *merge_cmd = new AppendCommand(&str, "top");
+ stack.push(merge_cmd); // #6
+ QCOMPARE(merge_cmd->merged, false);
+ QCOMPARE(str, QString("enematop"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, "eja")); // #7 should merge
+ QCOMPARE(str, QString("enematopeja"));
+ QCOMPARE(merge_cmd->merged, true);
+ QCOMPARE(AppendCommand::delete_cnt, 5); // #7 gets deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ merge_cmd->merged = false;
+
+ stack.push(new InsertCommand(&str, 2, "123")); // should not merge
+ QCOMPARE(str, QString("en123ematopeja"));
+ QCOMPARE(merge_cmd->merged, false);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("en123ematopeja"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("enema"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "ding", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo();
+ QCOMPARE(str, QString("en123ematopeja"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ delete undoAction;
+ delete redoAction;
+}
+
+void tst_QUndoStack::undoLimit()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ AppendCommand::delete_cnt = 0;
+ QString str;
+
+ QCOMPARE(stack.undoLimit(), 0);
+ stack.setUndoLimit(2);
+ QCOMPARE(stack.undoLimit(), 2);
+
+ stack.push(new AppendCommand(&str, "1", true));
+ QCOMPARE(str, QString("1"));
+ QCOMPARE(AppendCommand::delete_cnt, 0);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "2", true));
+ QCOMPARE(str, QString("12"));
+ QCOMPARE(AppendCommand::delete_cnt, 0);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setClean();
+ QCOMPARE(str, QString("12"));
+ QCOMPARE(AppendCommand::delete_cnt, 0);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, "3", true));
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 1);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "4", true));
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 2);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 2);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("12"));
+ QCOMPARE(AppendCommand::delete_cnt, 2);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "3", true));
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 4);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "4", true));
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 4);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "5", true));
+ QCOMPARE(str, QString("12345"));
+ QCOMPARE(AppendCommand::delete_cnt, 5);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 5);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 5);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "4", true));
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 7);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "5"));
+ QCOMPARE(str, QString("12345"));
+ QCOMPARE(AppendCommand::delete_cnt, 7);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "6", true)); // should be merged
+ QCOMPARE(str, QString("123456"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.beginMacro("foo");
+ QCOMPARE(str, QString("123456"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "7", true));
+ QCOMPARE(str, QString("1234567"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, "8"));
+ QCOMPARE(str, QString("12345678"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("12345678"));
+ QCOMPARE(AppendCommand::delete_cnt, 9);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "foo", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("123456"));
+ QCOMPARE(AppendCommand::delete_cnt, 9);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "foo", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 9);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::commandTextFormat()
+{
+ QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+ if (QProcess::execute(binDir + "/lrelease -version") != 0) {
+ QSKIP("lrelease is missing or broken", SkipAll);
+ }
+
+ QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/qundostack.ts"));
+
+ QTranslator translator;
+ QVERIFY(translator.load("testdata/qundostack.qm"));
+ qApp->installTranslator(&translator);
+
+ QUndoStack stack;
+ QAction *undo_action = stack.createUndoAction(0);
+ QAction *redo_action = stack.createRedoAction(0);
+
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ QString str;
+
+ stack.push(new AppendCommand(&str, "foo"));
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ stack.push(new InsertCommand(&str, 0, "bar"));
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix insert redo-suffix"));
+
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix append redo-suffix"));
+
+ qApp->removeTranslator(&translator);
+}
+
+void tst_QUndoStack::separateUndoText()
+{
+ QUndoStack stack;
+ QAction *undo_action = stack.createUndoAction(0);
+ QAction *redo_action = stack.createRedoAction(0);
+
+ QUndoCommand *command1 = new IdleCommand();
+ QUndoCommand *command2 = new IdleCommand();
+ stack.push(command1);
+ stack.push(command2);
+ stack.undo();
+
+ QCOMPARE(undo_action->text(), QString("Undo idle-action"));
+ QCOMPARE(redo_action->text(), QString("Redo idle-action"));
+ QCOMPARE(command1->actionText(), QString("idle-action"));
+
+ QCOMPARE(command1->text(), QString("idle-item"));
+ QCOMPARE(stack.text(0), QString("idle-item"));
+
+ command1->setText("idle");
+ QCOMPARE(command1->actionText(), QString("idle"));
+ QCOMPARE(command1->text(), QString("idle"));
+
+ command1->setText("idle-item\nidle-action");
+ QCOMPARE(command1->actionText(), QString("idle-action"));
+ QCOMPARE(command1->text(), QString("idle-item"));
+}
+
+QTEST_MAIN(tst_QUndoStack)
+
+#include "tst_qundostack.moc"
diff --git a/tests/auto/widgets/util/util.pro b/tests/auto/widgets/util/util.pro
new file mode 100644
index 0000000000..b7fe35ce4c
--- /dev/null
+++ b/tests/auto/widgets/util/util.pro
@@ -0,0 +1,11 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qcompleter \
+ qscroller \
+ qsystemtrayicon \
+ qundogroup \
+ qundostack \
+
+symbian:SUBDIRS -= \
+ qsystemtrayicon \
+
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
new file mode 100644
index 0000000000..8b6c4722be
--- /dev/null
+++ b/tests/auto/widgets/widgets.pro
@@ -0,0 +1,10 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ dialogs \
+ effects \
+ graphicsview \
+ itemviews \
+ kernel \
+ styles \
+ util \
+ widgets \
diff --git a/tests/auto/widgets/widgets/qabstractbutton/.gitignore b/tests/auto/widgets/widgets/qabstractbutton/.gitignore
new file mode 100644
index 0000000000..82f669574c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractbutton/.gitignore
@@ -0,0 +1 @@
+tst_qabstractbutton
diff --git a/tests/auto/widgets/widgets/qabstractbutton/qabstractbutton.pro b/tests/auto/widgets/widgets/qabstractbutton/qabstractbutton.pro
new file mode 100644
index 0000000000..15d90ed4e1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractbutton/qabstractbutton.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstractbutton.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp b/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp
new file mode 100644
index 0000000000..f5f60c8fd3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp
@@ -0,0 +1,650 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qstyleoption.h>
+#include <qkeysequence.h>
+#include <qevent.h>
+#include <qgridlayout.h>
+
+
+
+#include <qabstractbutton.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAbstractButton : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAbstractButton();
+ virtual ~tst_QAbstractButton();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void setAutoRepeat_data();
+ void setAutoRepeat();
+
+ void pressed();
+ void released();
+ void setText();
+ void setIcon();
+
+ void setShortcut();
+
+ void animateClick();
+
+ void isCheckable();
+ void setDown();
+ void isChecked();
+ void toggled();
+ void setEnabled();
+ void shortcutEvents();
+ void stopRepeatTimer();
+
+ void keyNavigation();
+
+protected slots:
+ void onClicked();
+ void onToggled( bool on );
+ void onPressed();
+ void onReleased();
+ void resetValues();
+
+private:
+ uint click_count;
+ uint toggle_count;
+ uint press_count;
+ uint release_count;
+
+ QAbstractButton *testWidget;
+};
+
+// QAbstractButton is an abstract class in 4.0
+class MyButton : public QAbstractButton
+{
+public:
+ MyButton(QWidget *p = 0) : QAbstractButton(p) {}
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter p(this);
+ QRect r = rect();
+ p.fillRect(r, isDown() ? Qt::black : (isChecked() ? Qt::lightGray : Qt::white));
+ p.setPen(isDown() ? Qt::white : Qt::black);
+ p.drawRect(r);
+ p.drawText(r, Qt::AlignCenter | Qt::TextShowMnemonic, text());
+ if (hasFocus()) {
+ r.adjust(2, 2, -2, -2);
+ QStyleOptionFocusRect opt;
+ opt.rect = r;
+ opt.palette = palette();
+ opt.state = QStyle::State_None;
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, &p, this);
+#ifdef Q_WS_MAC
+ p.setPen(Qt::red);
+ p.drawRect(r);
+#endif
+ }
+ }
+ QSize sizeHint() const
+ {
+ QSize sh(8, 8);
+ if (!text().isEmpty())
+ sh += fontMetrics().boundingRect(text()).size();
+ return sh;
+ }
+
+ void resetTimerEvents() { timerEvents = 0; }
+ int timerEventCount() const { return timerEvents; }
+
+private:
+
+ int timerEvents;
+
+ void timerEvent(QTimerEvent *event)
+ {
+ ++timerEvents;
+ QAbstractButton::timerEvent(event);
+ }
+};
+
+tst_QAbstractButton::tst_QAbstractButton()
+{
+}
+
+tst_QAbstractButton::~tst_QAbstractButton()
+{
+}
+
+void tst_QAbstractButton::initTestCase()
+{
+ testWidget = new MyButton(0);
+ testWidget->setObjectName("testObject");
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+
+ connect( testWidget, SIGNAL(clicked()), this, SLOT(onClicked()) );
+ connect( testWidget, SIGNAL(pressed()), this, SLOT(onPressed()) );
+ connect( testWidget, SIGNAL(released()), this, SLOT(onReleased()) );
+ connect( testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)) );
+}
+
+void tst_QAbstractButton::cleanupTestCase()
+{
+ delete testWidget;
+}
+
+void tst_QAbstractButton::init()
+{
+ testWidget->setText("Test");
+ testWidget->setEnabled( TRUE );
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QKeySequence seq;
+ testWidget->setShortcut( seq );
+
+ toggle_count = 0;
+ press_count = 0;
+ release_count = 0;
+ click_count = 0;
+}
+
+void tst_QAbstractButton::cleanup()
+{
+}
+
+void tst_QAbstractButton::resetValues()
+{
+ toggle_count = 0;
+ press_count = 0;
+ release_count = 0;
+ click_count = 0;
+}
+
+void tst_QAbstractButton::onClicked()
+{
+ click_count++;
+}
+
+void tst_QAbstractButton::onToggled( bool /*on*/ )
+{
+ toggle_count++;
+}
+
+void tst_QAbstractButton::onPressed()
+{
+ press_count++;
+}
+
+void tst_QAbstractButton::onReleased()
+{
+ release_count++;
+}
+
+void tst_QAbstractButton::setAutoRepeat_data()
+{
+ QTest::addColumn<int>("mode");
+ QTest::newRow( "" ) << 0;
+ QTest::newRow( "" ) << 1;
+ QTest::newRow( "" ) << 2;
+ QTest::newRow( "" ) << 3;
+ QTest::newRow( "" ) << 4;
+ QTest::newRow( "" ) << 5;
+ QTest::newRow( "" ) << 6;
+}
+
+#define REPEAT_DELAY 1000
+
+int test_count = 0;
+int last_mode = 0;
+
+void tst_QAbstractButton::setAutoRepeat()
+{
+ QFETCH( int, mode );
+
+ //FIXME: temp code to check that the test fails consistenly
+ //retest( 3 );
+
+ switch (mode)
+ {
+ case 0:
+ QVERIFY( !testWidget->isCheckable() );
+ break;
+ case 1:
+ // check if we can toggle the mode
+ testWidget->setAutoRepeat( TRUE );
+ QVERIFY( testWidget->autoRepeat() );
+
+ testWidget->setAutoRepeat( FALSE );
+ QVERIFY( !testWidget->autoRepeat() );
+ break;
+ case 2:
+ // check that the button is down if we press space and not in autorepeat
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QTest::keyPress( testWidget, Qt::Key_Space );
+
+ QTest::qWait( REPEAT_DELAY );
+
+ QVERIFY( release_count == 0 );
+ QVERIFY( testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( click_count == 0 );
+
+ QTest::keyRelease( testWidget, Qt::Key_Space );
+ QVERIFY( click_count == 1 );
+ QVERIFY( release_count == 1 );
+ break;
+ case 3:
+ // check that the button is down if we press space while in autorepeat
+ testWidget->setDown(false);
+ testWidget->setAutoRepeat(true);
+ QTest::keyPress(testWidget, Qt::Key_Space);
+ QTest::qWait(REPEAT_DELAY);
+ QVERIFY(testWidget->isDown());
+ QTest::keyRelease(testWidget, Qt::Key_Space);
+ QVERIFY(release_count == press_count);
+ QVERIFY(toggle_count == 0);
+ QVERIFY(press_count == click_count);
+ QVERIFY(click_count > 1);
+ break;
+ case 4:
+ // check that pressing ENTER has no effect when autorepeat is FALSE
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QTest::keyPress( testWidget, Qt::Key_Enter );
+
+ QTest::qWait( REPEAT_DELAY );
+
+ QVERIFY( !testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 0 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+ QTest::keyRelease( testWidget, Qt::Key_Enter );
+
+ QVERIFY( click_count == 0 );
+ break;
+ case 5:
+ // check that pressing ENTER has no effect when autorepeat is TRUE
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( TRUE );
+ QTest::keyPress( testWidget, Qt::Key_Enter );
+
+ QTest::qWait( REPEAT_DELAY );
+
+ QVERIFY( !testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 0 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+
+ QTest::keyRelease( testWidget, Qt::Key_Enter );
+
+ QVERIFY( click_count == 0 );
+ break;
+ case 6:
+ // verify autorepeat is off by default.
+ MyButton tmp( 0);
+ tmp.setObjectName("tmp" );
+ QVERIFY( !tmp.autoRepeat() );
+ break;
+ }
+}
+
+void tst_QAbstractButton::pressed()
+{
+ // pressed/released signals expected for a QAbstractButton
+ QTest::keyPress( testWidget, ' ' );
+ QCOMPARE( press_count, (uint)1 );
+}
+
+void tst_QAbstractButton::released()
+{
+ // pressed/released signals expected for a QAbstractButton
+ QTest::keyPress( testWidget, ' ' );
+ QTest::keyRelease( testWidget, ' ' );
+ QCOMPARE( release_count, (uint)1 );
+}
+
+void tst_QAbstractButton::setText()
+{
+ testWidget->setText("");
+ QCOMPARE( testWidget->text(), QString("") );
+ testWidget->setText("simple");
+ QCOMPARE( testWidget->text(), QString("simple") );
+ testWidget->setText("&ampersand");
+ QCOMPARE( testWidget->text(), QString("&ampersand") );
+#ifndef Q_WS_MAC // no mneonics on Mac.
+ QCOMPARE( testWidget->shortcut(), QKeySequence("ALT+A"));
+#endif
+ testWidget->setText("te&st");
+ QCOMPARE( testWidget->text(), QString("te&st") );
+#ifndef Q_WS_MAC // no mneonics on Mac.
+ QCOMPARE( testWidget->shortcut(), QKeySequence("ALT+S"));
+#endif
+ testWidget->setText("foo");
+ QCOMPARE( testWidget->text(), QString("foo") );
+#ifndef Q_WS_MAC // no mneonics on Mac.
+ QCOMPARE( testWidget->shortcut(), QKeySequence());
+#endif
+}
+
+void tst_QAbstractButton::setIcon()
+{
+ const char *test1_xpm[] = {
+ "12 8 2 1",
+ ". c None",
+ "c c #ff0000",
+ ".........ccc",
+ "........ccc.",
+ ".......ccc..",
+ "ccc...ccc...",
+ ".ccc.ccc....",
+ "..ccccc.....",
+ "...ccc......",
+ "....c.......",
+ };
+
+ QPixmap p(test1_xpm);
+ testWidget->setIcon( p );
+ QCOMPARE( testWidget->icon().pixmap(12, 8), p );
+
+ // Test for #14793
+
+ const char *test2_xpm[] = {
+ "12 8 2 1",
+ ". c None",
+ "c c #ff0000",
+ "ccc......ccc",
+ ".ccc....ccc.",
+ "..ccc..ccc..",
+ "....cc.cc...",
+ ".....ccc....",
+ "....cc.cc...",
+ "...ccc.ccc..",
+ "..ccc...ccc.",
+ };
+
+ int currentHeight = testWidget->height();
+ int currentWidth = testWidget->width();
+
+ QPixmap p2( test2_xpm );
+ for ( int a = 0; a<5; a++ )
+ testWidget->setIcon( p2 );
+
+ QCOMPARE( testWidget->icon().pixmap(12, 8), p2 );
+
+ QCOMPARE( testWidget->height(), currentHeight );
+ QCOMPARE( testWidget->width(), currentWidth );
+}
+
+void tst_QAbstractButton::setEnabled()
+{
+ testWidget->setEnabled( FALSE );
+ QVERIFY( !testWidget->isEnabled() );
+// QTEST( testWidget, "disabled" );
+
+ testWidget->setEnabled( TRUE );
+ QVERIFY( testWidget->isEnabled() );
+// QTEST( testWidget, "enabled" );
+}
+
+void tst_QAbstractButton::isCheckable()
+{
+ QVERIFY( !testWidget->isCheckable() );
+}
+
+void tst_QAbstractButton::setDown()
+{
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isDown() );
+
+ testWidget->setDown( TRUE );
+ QTest::qWait(300);
+ QVERIFY( testWidget->isDown() );
+
+ testWidget->setDown( TRUE );
+
+ // add some debugging stuff
+ QWidget *grab = QWidget::keyboardGrabber();
+ if (grab != 0 && grab != testWidget)
+ qDebug( "testWidget != keyboardGrabber" );
+ grab = qApp->focusWidget();
+ if (grab != 0 && grab != testWidget)
+ qDebug( "testWidget != focusWidget" );
+
+ QTest::keyClick( testWidget, Qt::Key_Escape );
+ QVERIFY( !testWidget->isDown() );
+}
+
+void tst_QAbstractButton::isChecked()
+{
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isChecked() );
+
+ testWidget->setDown( TRUE );
+ QVERIFY( !testWidget->isChecked() );
+
+ testWidget->setDown( FALSE );
+ testWidget->toggle();
+ QVERIFY( testWidget->isChecked() == testWidget->isCheckable() );
+}
+
+void tst_QAbstractButton::toggled()
+{
+ testWidget->toggle();
+ QVERIFY( toggle_count == 0 );
+
+ QTest::mousePress( testWidget, Qt::LeftButton );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( click_count == 0 );
+
+ QTest::mouseRelease( testWidget, Qt::LeftButton );
+ QVERIFY( click_count == 1 );
+}
+
+void tst_QAbstractButton::setShortcut()
+{
+ QKeySequence seq( Qt::Key_A );
+ testWidget->setShortcut( seq );
+ QApplication::setActiveWindow(testWidget);
+
+ // must be active to get shortcuts
+ for (int i = 0; !testWidget->isActiveWindow() && i < 100; ++i) {
+ testWidget->activateWindow();
+ QApplication::instance()->processEvents();
+ QTest::qWait(100);
+ }
+ QVERIFY(testWidget->isActiveWindow());
+
+ QTest::keyClick( testWidget, 'A' );
+ QTest::qWait(300); // Animate click takes time
+ QCOMPARE(click_count, (uint)1);
+ QCOMPARE(press_count, (uint)1); // Press is part of a click
+ QCOMPARE(release_count,(uint)1); // Release is part of a click
+
+ QVERIFY( toggle_count == 0 );
+
+// resetValues();
+// QTest::keyPress( testWidget, 'A' );
+// QTest::qWait(10000);
+// QTest::keyRelease( testWidget, 'A' );
+// QCOMPARE(click_count, (uint)1);
+// QCOMPARE(press_count, (uint)1);
+// QCOMPARE(release_count,(uint)1);
+
+// qDebug() << click_count;
+
+}
+
+void tst_QAbstractButton::animateClick()
+{
+ testWidget->animateClick();
+ QVERIFY( testWidget->isDown() );
+ qApp->processEvents();
+ QVERIFY( testWidget->isDown() );
+ QTest::qWait(200);
+ qApp->processEvents();
+ QVERIFY( !testWidget->isDown() );
+}
+
+void tst_QAbstractButton::shortcutEvents()
+{
+ MyButton button;
+ QSignalSpy pressedSpy(&button, SIGNAL(pressed()));
+ QSignalSpy releasedSpy(&button, SIGNAL(released()));
+ QSignalSpy clickedSpy(&button, SIGNAL(clicked(bool)));
+
+ for (int i = 0; i < 4; ++i) {
+ QKeySequence sequence;
+ QShortcutEvent event(sequence, false);
+ QApplication::sendEvent(&button, &event);
+ if (i < 2)
+ QTest::qWait(500);
+ }
+
+ QTest::qWait(1000); // ensure animate timer is expired
+
+ QCOMPARE(pressedSpy.count(), 3);
+ QCOMPARE(releasedSpy.count(), 3);
+ QCOMPARE(clickedSpy.count(), 3);
+}
+
+void tst_QAbstractButton::stopRepeatTimer()
+{
+ MyButton button;
+ button.setAutoRepeat(true);
+
+ // Mouse trigger case:
+ button.resetTimerEvents();
+ QTest::mousePress(&button, Qt::LeftButton);
+ QTest::qWait(1000);
+ QVERIFY(button.timerEventCount() > 0);
+
+ QTest::mouseRelease(&button, Qt::LeftButton);
+ button.resetTimerEvents();
+ QTest::qWait(1000);
+ QCOMPARE(button.timerEventCount(), 0);
+
+ // Key trigger case:
+ button.resetTimerEvents();
+ QTest::keyPress(&button, Qt::Key_Space);
+ QTest::qWait(1000);
+ QVERIFY(button.timerEventCount() > 0);
+
+ QTest::keyRelease(&button, Qt::Key_Space);
+ button.resetTimerEvents();
+ QTest::qWait(1000);
+ QCOMPARE(button.timerEventCount(), 0);
+}
+
+void tst_QAbstractButton::keyNavigation()
+{
+ QSKIP("Key navigation in QAbstractButton will be fixed/improved as part of task 194373", SkipSingle);
+
+ QWidget widget;
+ QGridLayout *layout = new QGridLayout(&widget);
+ QAbstractButton *buttons[3][3];
+ for(int y = 0; y < 3; y++) {
+ for(int x = 0; x < 3; x++) {
+ buttons[y][x] = new MyButton(&widget);
+ buttons[y][x]->setFocusPolicy(Qt::StrongFocus);
+ layout->addWidget(buttons[y][x], y, x);
+ }
+ }
+
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWait(30);
+
+ buttons[1][1]->setFocus();
+ QTest::qWait(400);
+ QVERIFY(buttons[1][1]->hasFocus());
+ QTest::keyPress(buttons[1][1], Qt::Key_Up);
+ QTest::qWait(100);
+ QVERIFY(buttons[0][1]->hasFocus());
+ QTest::keyPress(buttons[0][1], Qt::Key_Down);
+ QTest::qWait(100);
+ QVERIFY(buttons[1][1]->hasFocus());
+ QTest::keyPress(buttons[1][1], Qt::Key_Left);
+ QTest::qWait(100);
+ QVERIFY(buttons[1][0]->hasFocus());
+ QTest::keyPress(buttons[1][0], Qt::Key_Down);
+ QTest::qWait(100);
+ QVERIFY(buttons[2][0]->hasFocus());
+ QTest::keyPress(buttons[2][0], Qt::Key_Right);
+ QTest::qWait(100);
+ QVERIFY(buttons[2][1]->hasFocus());
+ QTest::keyPress(buttons[2][1], Qt::Key_Right);
+ QTest::qWait(100);
+ QVERIFY(buttons[2][2]->hasFocus());
+ QTest::keyPress(buttons[2][2], Qt::Key_Up);
+ QTest::qWait(100);
+ QVERIFY(buttons[1][2]->hasFocus());
+ QTest::keyPress(buttons[1][2], Qt::Key_Up);
+ QTest::qWait(100);
+ QVERIFY(buttons[0][2]->hasFocus());
+ buttons[0][1]->hide();
+ QTest::keyPress(buttons[0][2], Qt::Key_Left);
+ QTest::qWait(100);
+ QVERIFY(buttons[0][0]->hasFocus());
+
+
+}
+
+QTEST_MAIN(tst_QAbstractButton)
+#include "tst_qabstractbutton.moc"
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/.gitignore b/tests/auto/widgets/widgets/qabstractscrollarea/.gitignore
new file mode 100644
index 0000000000..ab753b8a0a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/.gitignore
@@ -0,0 +1 @@
+tst_qabstractscrollarea
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/qabstractscrollarea.pro b/tests/auto/widgets/widgets/qabstractscrollarea/qabstractscrollarea.pro
new file mode 100644
index 0000000000..e4bc3f6495
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/qabstractscrollarea.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qabstractscrollarea.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstractscrollarea.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
new file mode 100644
index 0000000000..5c9a33cdc6
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qabstractscrollarea.h>
+#include <qscrollarea.h>
+#include <qscrollbar.h>
+#include <qlabel.h>
+#include <qwidget.h>
+#include <qdialog.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAbstractScrollArea : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QAbstractScrollArea();
+ virtual ~tst_QAbstractScrollArea();
+private slots:
+ void scrollBarWidgets();
+ void setScrollBars();
+ void setScrollBars2();
+ void objectNaming();
+ void patternBackground();
+
+ void viewportCrash();
+ void task214488_layoutDirection_data();
+ void task214488_layoutDirection();
+};
+
+tst_QAbstractScrollArea::tst_QAbstractScrollArea()
+{
+}
+
+tst_QAbstractScrollArea::~tst_QAbstractScrollArea()
+{
+}
+
+void tst_QAbstractScrollArea::scrollBarWidgets()
+{
+ QWidget *w1 = new QWidget(0);
+ QWidget *w2 = new QWidget(0);
+ QWidget *w3 = new QWidget(0);
+
+ Qt::Alignment all = Qt::AlignLeft | Qt::AlignRight | Qt::AlignTop | Qt::AlignBottom;
+
+ QWidgetList w1List = QWidgetList() << w1;
+ QWidgetList w2List = QWidgetList() << w2;
+ QWidgetList w3List = QWidgetList() << w3;
+
+ QWidgetList w1w2List = w1List + w2List;
+ QWidgetList allList = w1List + w2List + w3List;
+
+ QAbstractScrollArea area;
+ area.show();
+ QCOMPARE(area.scrollBarWidgets(all), QWidgetList());
+
+ area.addScrollBarWidget(w1, Qt::AlignLeft);
+ QCOMPARE(area.scrollBarWidgets(all), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), QWidgetList());
+
+ area.addScrollBarWidget(w2, Qt::AlignBottom);
+ QCOMPARE(area.scrollBarWidgets(all), w1w2List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
+
+ // duplicate add
+ area.addScrollBarWidget(w2, Qt::AlignBottom);
+ QCOMPARE(area.scrollBarWidgets(all), w1w2List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
+
+ //reparent
+ w2->setParent(w1);
+ QCOMPARE(area.scrollBarWidgets(all), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), QWidgetList());
+
+ // add after reparent
+ area.addScrollBarWidget(w2, Qt::AlignBottom);
+ QCOMPARE(area.scrollBarWidgets(all), w1w2List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
+
+ // two widgets at Bottom.
+ area.addScrollBarWidget(w3, Qt::AlignBottom);
+ QCOMPARE(area.scrollBarWidgets(all).toSet(), allList.toSet());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom).toSet(), (w2List + w3List).toSet());
+
+ //delete
+ delete w1;
+ delete w2;
+ delete w3;
+
+ QCOMPARE(area.scrollBarWidgets(all), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
+ QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), QWidgetList());
+}
+
+void tst_QAbstractScrollArea::setScrollBars()
+{
+ QScrollArea scrollArea;
+ scrollArea.resize(300, 300);
+ scrollArea.show();
+
+ QPointer<QScrollBar> vbar = scrollArea.verticalScrollBar();
+ QPointer<QScrollBar> hbar = scrollArea.horizontalScrollBar();
+
+ // Now set properties on the scroll bars
+ scrollArea.verticalScrollBar()->setInvertedAppearance(true);
+ scrollArea.verticalScrollBar()->setInvertedControls(true);
+ scrollArea.verticalScrollBar()->setTracking(true);
+ scrollArea.verticalScrollBar()->setRange(-100, 100);
+ scrollArea.verticalScrollBar()->setPageStep(42);
+ scrollArea.verticalScrollBar()->setSingleStep(3);
+ scrollArea.verticalScrollBar()->setValue(43);
+ scrollArea.horizontalScrollBar()->setInvertedAppearance(true);
+ scrollArea.horizontalScrollBar()->setInvertedControls(true);
+ scrollArea.horizontalScrollBar()->setTracking(true);
+ scrollArea.horizontalScrollBar()->setRange(-100, 100);
+ scrollArea.horizontalScrollBar()->setPageStep(42);
+ scrollArea.horizontalScrollBar()->setSingleStep(3);
+ scrollArea.horizontalScrollBar()->setValue(43);
+
+ qApp->processEvents();
+
+ // Then replace the scroll bars
+ scrollArea.setVerticalScrollBar(new QScrollBar);
+ scrollArea.setHorizontalScrollBar(new QScrollBar);
+
+ // Check that the old ones were deleted
+ QVERIFY(!vbar);
+ QVERIFY(!hbar);
+
+ qApp->processEvents();
+
+ // Check that all properties have been populated
+ QVERIFY(scrollArea.verticalScrollBar()->invertedAppearance());
+ QVERIFY(scrollArea.verticalScrollBar()->invertedControls());
+ QVERIFY(scrollArea.verticalScrollBar()->hasTracking());
+ QVERIFY(scrollArea.verticalScrollBar()->isVisible());
+ QCOMPARE(scrollArea.verticalScrollBar()->minimum(), -100);
+ QCOMPARE(scrollArea.verticalScrollBar()->maximum(), 100);
+ QCOMPARE(scrollArea.verticalScrollBar()->pageStep(), 42);
+ QCOMPARE(scrollArea.verticalScrollBar()->singleStep(), 3);
+ QCOMPARE(scrollArea.verticalScrollBar()->value(), 43);
+ QVERIFY(scrollArea.horizontalScrollBar()->invertedAppearance());
+ QVERIFY(scrollArea.horizontalScrollBar()->invertedControls());
+ QVERIFY(scrollArea.horizontalScrollBar()->hasTracking());
+ QVERIFY(scrollArea.horizontalScrollBar()->isVisible());
+ QCOMPARE(scrollArea.horizontalScrollBar()->minimum(), -100);
+ QCOMPARE(scrollArea.horizontalScrollBar()->maximum(), 100);
+ QCOMPARE(scrollArea.horizontalScrollBar()->pageStep(), 42);
+ QCOMPARE(scrollArea.horizontalScrollBar()->singleStep(), 3);
+ QCOMPARE(scrollArea.horizontalScrollBar()->value(), 43);
+}
+
+void tst_QAbstractScrollArea::setScrollBars2()
+{
+ QAbstractScrollArea scrollArea;
+ scrollArea.resize(300, 300);
+
+ QScrollBar *hbar = new QScrollBar;
+ scrollArea.setHorizontalScrollBar(hbar);
+ qApp->processEvents();
+ QCOMPARE(scrollArea.horizontalScrollBar(), hbar);
+
+ QScrollBar *vbar = new QScrollBar;
+ scrollArea.setVerticalScrollBar(vbar);
+ qApp->processEvents();
+ QCOMPARE(scrollArea.verticalScrollBar(), vbar);
+
+ scrollArea.horizontalScrollBar()->setRange(0, 100);
+ scrollArea.verticalScrollBar()->setRange(0, 100);
+ scrollArea.show();
+
+ // Make sure scroll bars are not explicitly hidden by QAbstractScrollArea itself.
+ QVERIFY(hbar->isVisible());
+ QVERIFY(vbar->isVisible());
+
+ // Hide the OLD scroll bar and ensure that the NEW one is hidden.
+ hbar->hide();
+ scrollArea.setHorizontalScrollBar(new QScrollBar);
+ qApp->processEvents();
+ QVERIFY(!scrollArea.horizontalScrollBar()->isVisible());
+
+ vbar->hide();
+ scrollArea.setVerticalScrollBar(new QScrollBar);
+ qApp->processEvents();
+ QVERIFY(!scrollArea.verticalScrollBar()->isVisible());
+
+ scrollArea.verticalScrollBar()->show();
+ scrollArea.horizontalScrollBar()->show();
+
+ // Hide the NEW scroll bar and ensure that it's visible
+ // (because the OLD one is visible).
+ hbar = new QScrollBar;
+ hbar->hide();
+ scrollArea.setHorizontalScrollBar(hbar);
+ qApp->processEvents();
+ QVERIFY(hbar->isVisible());
+
+ vbar = new QScrollBar;
+ vbar->hide();
+ scrollArea.setVerticalScrollBar(vbar);
+ qApp->processEvents();
+ QVERIFY(vbar->isVisible());
+
+ vbar->setRange(0, 0);
+ qApp->processEvents();
+ QVERIFY(!vbar->isVisible());
+
+ hbar->setRange(0, 0);
+ qApp->processEvents();
+ QVERIFY(!hbar->isVisible());
+}
+
+// we need to make sure the viewport internal widget is named
+// qt_scrollarea_viewport, otherwise we're going to confuse Squish
+// and friends.
+void tst_QAbstractScrollArea::objectNaming()
+{
+ QScrollArea area;
+ QCOMPARE(area.viewport()->objectName(), QString("qt_scrollarea_viewport"));
+}
+
+class ViewportCrashWidget : public QDialog
+{
+public:
+ ViewportCrashWidget()
+ {
+ // temprorary set PaintOnScreen to set the nativeChildrenForced flag.
+ setAttribute(Qt::WA_PaintOnScreen, true);
+ setAttribute(Qt::WA_PaintOnScreen, false);
+
+ setAttribute(Qt::WA_DropSiteRegistered, true);
+
+ startTimer(2000);
+ }
+
+ void timerEvent(QTimerEvent * /* event */)
+ {
+ // should not crash.
+ (void)new QScrollArea(this);
+ accept();
+ }
+};
+
+void tst_QAbstractScrollArea::viewportCrash()
+{
+ ViewportCrashWidget w;
+ // should not crash
+ w.exec();
+}
+
+Q_DECLARE_METATYPE(Qt::LayoutDirection);
+Q_DECLARE_METATYPE(Qt::Key);
+
+void tst_QAbstractScrollArea::task214488_layoutDirection_data()
+{
+ QTest::addColumn<Qt::LayoutDirection>("dir");
+ QTest::addColumn<Qt::Key>("key");
+ QTest::addColumn<bool>("lessThan");
+
+ QTest::newRow("LTR left") << Qt::LeftToRight << Qt::Key_Left << true;
+ QTest::newRow("LTR right") << Qt::LeftToRight << Qt::Key_Right << false;
+ QTest::newRow("RTL left") << Qt::RightToLeft << Qt::Key_Left << false;
+ QTest::newRow("RTL right") << Qt::RightToLeft << Qt::Key_Right << true;
+}
+
+void tst_QAbstractScrollArea::task214488_layoutDirection()
+{
+ QScrollArea scrollArea;
+ scrollArea.resize(200, 200);
+ QWidget widget;
+ widget.resize(600, 600);
+ scrollArea.setWidget(&widget);
+ scrollArea.show();
+ QScrollBar *hbar = scrollArea.horizontalScrollBar();
+ hbar->setValue((hbar->minimum() + hbar->maximum()) / 2);
+
+ QFETCH(Qt::LayoutDirection, dir);
+ QFETCH(Qt::Key, key);
+ QFETCH(bool, lessThan);
+
+ scrollArea.setLayoutDirection(dir);
+
+ int refValue = hbar->value();
+ qApp->sendEvent(&scrollArea, new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier));
+ QVERIFY(lessThan ? (hbar->value() < refValue) : (hbar->value() > refValue));
+}
+
+void tst_QAbstractScrollArea::patternBackground()
+{
+ QWidget topLevel;
+ QScrollArea scrollArea(&topLevel);
+ scrollArea.resize(200, 200);
+ QWidget widget;
+ widget.resize(600, 600);
+ scrollArea.setWidget(&widget);
+ topLevel.show();
+
+ QLinearGradient linearGrad(QPointF(250, 250), QPointF(300, 300));
+ linearGrad.setColorAt(0, Qt::yellow);
+ linearGrad.setColorAt(1, Qt::red);
+ QBrush bg(linearGrad);
+ scrollArea.viewport()->setPalette(QPalette(Qt::black, bg, bg, bg, bg, bg, bg, bg, bg));
+ widget.setPalette(Qt::transparent);
+
+ QTest::qWait(50);
+
+ QImage image(200, 200, QImage::Format_ARGB32);
+ scrollArea.render(&image);
+
+ QCOMPARE(image.pixel(QPoint(20,20)) , QColor(Qt::yellow).rgb());
+
+ QScrollBar *hbar = scrollArea.horizontalScrollBar();
+ hbar->setValue(hbar->maximum());
+ QScrollBar *vbar = scrollArea.verticalScrollBar();
+ vbar->setValue(vbar->maximum());
+
+ QTest::qWait(50);
+
+ scrollArea.render(&image);
+ QCOMPARE(image.pixel(QPoint(20,20)) , QColor(Qt::red).rgb());
+}
+
+QTEST_MAIN(tst_QAbstractScrollArea)
+#include "tst_qabstractscrollarea.moc"
diff --git a/tests/auto/widgets/widgets/qabstractslider/.gitignore b/tests/auto/widgets/widgets/qabstractslider/.gitignore
new file mode 100644
index 0000000000..cdbb891214
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractslider/.gitignore
@@ -0,0 +1 @@
+tst_qabstractslider
diff --git a/tests/auto/widgets/widgets/qabstractslider/qabstractslider.pro b/tests/auto/widgets/widgets/qabstractslider/qabstractslider.pro
new file mode 100644
index 0000000000..4507859ace
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractslider/qabstractslider.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstractslider.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
new file mode 100644
index 0000000000..e78844524e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
@@ -0,0 +1,1247 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QAbstractSlider>
+#include <QScrollBar>
+#include <QSlider>
+#include <QStyle>
+#include <QStyleOption>
+#include <QTime>
+#include <QDebug>
+
+// defined to be 120 by the wheel mouse vendors according to the docs
+#define WHEEL_DELTA 120
+
+class Slider : public QAbstractSlider
+{
+ public:
+ Slider(QWidget *parent)
+ : QAbstractSlider(parent) {}
+ using QAbstractSlider::setRepeatAction;
+ using QAbstractSlider::repeatAction;
+};
+
+class tst_QAbstractSlider: public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void actionTriggered(int action);
+ void rangeChanged(int min, int max);
+ void valueChanged(int value);
+ void sliderMoved(int value);
+
+private slots:
+ void triggerAction_data();
+ void triggerAction();
+ void minimum_maximum_data();
+ void minimum_maximum();
+ void keyPressed_data();
+ void keyPressed();
+ void wheelEvent_data();
+ void wheelEvent();
+ void sliderPressedReleased_data();
+ void sliderPressedReleased();
+ void setOrientation();
+ void sliderMoved_data();
+ void sliderMoved();
+ void rangeChanged_data();
+ void rangeChanged();
+ void setSliderPosition_data();
+ void setSliderPosition();
+ void setValue_data();
+ void setValue();
+ void setRepeatAction();
+
+private:
+ void waitUntilTimeElapsed(const QTime& t, int ms);
+
+ QWidget *topLevel;
+ Slider *slider;
+ int previousAction;
+ int reportedMinimum;
+ int reportedMaximum;
+ int reportedValue;
+ int reportedSliderPosition;
+ qint64 timeStamp;
+ qint64 actionTriggeredTimeStamp;
+ qint64 valueChangedTimeStamp;
+ qint64 rangeChangedTimeStamp;
+ qint64 sliderMovedTimeStamp;
+};
+
+Q_DECLARE_METATYPE(QList<Qt::Key>)
+Q_DECLARE_METATYPE(QPoint)
+
+void tst_QAbstractSlider::initTestCase()
+{
+ topLevel = new QWidget;
+ slider = new Slider(topLevel);
+ slider->setObjectName("testWidget");
+ slider->resize(100,100);
+ slider->show();
+
+ previousAction = QAbstractSlider::SliderNoAction;
+ timeStamp = 0;
+
+ connect(slider,SIGNAL(actionTriggered(int)),this,SLOT(actionTriggered(int)));
+ connect(slider,SIGNAL(rangeChanged(int,int)),this,SLOT(rangeChanged(int,int)));
+ connect(slider,SIGNAL(valueChanged(int)),this,SLOT(valueChanged(int)));
+ connect(slider,SIGNAL(sliderMoved(int)),this,SLOT(sliderMoved(int)));
+}
+
+void tst_QAbstractSlider::cleanupTestCase()
+{
+ delete topLevel;
+}
+
+void tst_QAbstractSlider::actionTriggered(int action)
+{
+ previousAction = action;
+ actionTriggeredTimeStamp = timeStamp++;
+}
+
+void tst_QAbstractSlider::rangeChanged(int min,int max)
+{
+ reportedMinimum = min;
+ reportedMaximum = max;
+ rangeChangedTimeStamp = timeStamp++;
+}
+
+void tst_QAbstractSlider::valueChanged(int value)
+{
+ reportedValue = value;
+ valueChangedTimeStamp = timeStamp++;
+}
+
+void tst_QAbstractSlider::sliderMoved(int value)
+{
+ reportedSliderPosition = value;
+ sliderMovedTimeStamp = timeStamp++;
+}
+
+void tst_QAbstractSlider::triggerAction_data()
+{
+ QTest::addColumn<int>("sliderAction");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("initialSliderPosition");
+ QTest::addColumn<int>("singleStep");
+ QTest::addColumn<int>("pageStep");
+ QTest::addColumn<int>("expectedSliderPosition");
+
+ QTest::newRow("No action") << int(QAbstractSlider::SliderNoAction) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 237 // single step size
+ << 234 // page step size
+ << 987; // expected position after
+
+ QTest::newRow("Move action") << int(QAbstractSlider::SliderMove) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 237 // single step size
+ << 234 // page step size
+ << 988; // expected position after
+
+ QTest::newRow("Empty step add") << int(QAbstractSlider::SliderSingleStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 0 // single step size
+ << 234 // page step size
+ << 988; // expected position after
+
+ QTest::newRow("Empty step sub") << int(QAbstractSlider::SliderSingleStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 0 // single step size
+ << 234 // page step size
+ << 987; // expected position after
+
+ QTest::newRow("Empty page add") << int(QAbstractSlider::SliderPageStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 234 // single step size
+ << 0 // page step size
+ << 988; // expected position after
+
+ QTest::newRow("Empty page sub") << int(QAbstractSlider::SliderPageStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 234 // single step size
+ << 0 // page step size
+ << 987; // expected position after
+
+ QTest::newRow("Legal step add") << int(QAbstractSlider::SliderSingleStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 5 // single step size
+ << 234 // page step size
+ << 993; // expected position after
+
+ QTest::newRow("Legal step sub") << int(QAbstractSlider::SliderSingleStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 5 // single step size
+ << 234 // page step size
+ << 982; // expected position after
+
+ QTest::newRow("Legal page add") << int(QAbstractSlider::SliderPageStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 234 // single step size
+ << 5 // page step size
+ << 993; // expected position after
+
+ QTest::newRow("Legal page sub") << int(QAbstractSlider::SliderPageStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 234 // single step size
+ << 5 // page step size
+ << 982; // expected position after
+
+ QTest::newRow("Illegal step add") << int(QAbstractSlider::SliderSingleStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 500 // single step size
+ << 234 // page step size
+ << 1000; // expected position after
+
+ QTest::newRow("Illegal step sub") << int(QAbstractSlider::SliderSingleStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 500 // single step size
+ << 234 // page step size
+ << 900; // expected position after
+
+ QTest::newRow("Illegal page add") << int(QAbstractSlider::SliderPageStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 234 // single step size
+ << 500 // page step size
+ << 1000; // expected position after
+
+ QTest::newRow("Illegal page sub") << int(QAbstractSlider::SliderPageStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 234 // single step size
+ << 500 // page step size
+ << 900; // expected position after
+
+ // Negative steps will also be abs()'d so, check that case.
+ QTest::newRow("Negative step add") << int(QAbstractSlider::SliderSingleStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << -1 // single step size
+ << 234 // page step size
+ << 989; // expected position after
+
+ QTest::newRow("Negative step sub") << int(QAbstractSlider::SliderSingleStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << -1 // single step size
+ << 234 // page step size
+ << 986; // expected position after
+
+ QTest::newRow("Negative page add") << int(QAbstractSlider::SliderPageStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 234 // single step size
+ << -1 // page step size
+ << 989; // expected position after
+
+ QTest::newRow("Negative page sub") << int(QAbstractSlider::SliderPageStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 987 // initial position
+ << 234 // single step size
+ << -1 // page step size
+ << 986; // expected position after
+
+ QTest::newRow("Illegal negative step add") << int(QAbstractSlider::SliderSingleStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << -500 // single step size
+ << 234 // page step size
+ << 1000; // expected position after
+
+
+ QTest::newRow("Illegal negative step sub") << int(QAbstractSlider::SliderSingleStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << -500 // single step size
+ << 234 // page step size
+ << 900; // expected position after
+
+ QTest::newRow("Illegal negative page add") << int(QAbstractSlider::SliderPageStepAdd) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 234 // single step size
+ << -500 // page step size
+ << 1000; // expected position after
+
+ QTest::newRow("Illegal negative page sub") << int(QAbstractSlider::SliderPageStepSub) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 245 // single step size
+ << -500 // page step size
+ << 900; // expected position after
+
+ QTest::newRow("Slider to minimum") << int(QAbstractSlider::SliderToMinimum) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 245 // single step size
+ << 1 // page step size
+ << 900; // expected position after
+
+ QTest::newRow("Slider to maximum") << int(QAbstractSlider::SliderToMaximum) // sliderAction
+ << 1000 // max
+ << 900 // min
+ << 988 // initial position
+ << 245 // single step size
+ << 1 // page step size
+ << 1000; // expected position after
+
+}
+
+void tst_QAbstractSlider::triggerAction()
+{
+ QFETCH(int,sliderAction);
+ QFETCH(int,maximum);
+ QFETCH(int,minimum);
+ QFETCH(int,initialSliderPosition);
+ QFETCH(int,singleStep);
+ QFETCH(int,pageStep);
+ QFETCH(int,expectedSliderPosition);
+
+ slider->setTracking(true);
+ slider->setRange(minimum,maximum);
+ slider->setSingleStep(singleStep);
+ slider->setPageStep(pageStep);
+ QCOMPARE(slider->singleStep(), qAbs(singleStep));
+ QCOMPARE(slider->pageStep(), qAbs(pageStep));
+
+ int oldPosition = slider->sliderPosition();
+ slider->setSliderPosition(initialSliderPosition);
+
+ QVERIFY( (oldPosition == initialSliderPosition && previousAction == int(QAbstractSlider::SliderNoAction)) ||
+ (oldPosition != initialSliderPosition && previousAction == int(QAbstractSlider::SliderMove)));
+ previousAction = int(QAbstractSlider::SliderNoAction);
+
+ QAbstractSlider::SliderAction *action = reinterpret_cast<QAbstractSlider::SliderAction*>(&sliderAction);
+ QVERIFY(action != 0);
+
+ slider->triggerAction(*action);
+ QCOMPARE(previousAction,sliderAction); // previousAction set in the actionTriggered() slot
+ QCOMPARE(slider->sliderPosition(),expectedSliderPosition);
+ QCOMPARE(slider->value(),expectedSliderPosition);
+ QCOMPARE(reportedValue,expectedSliderPosition);
+ previousAction = int(QAbstractSlider::SliderNoAction);
+ if (initialSliderPosition != expectedSliderPosition)
+ QVERIFY(actionTriggeredTimeStamp < valueChangedTimeStamp);
+}
+
+void tst_QAbstractSlider::minimum_maximum_data()
+{
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("expectedMinimum");
+ QTest::addColumn<int>("expectedMaximum");
+
+ QTest::newRow("Normal range") << 100 << 200 << 100 << 200;
+ QTest::newRow("Minimum higher") << 100 << 0 << 100 << 100;
+ QTest::newRow("Negative minimum") << -100 << 100 << -100 << 100;
+ QTest::newRow("Negative range") << -100 << -50 << -100 << -50;
+}
+
+void tst_QAbstractSlider::minimum_maximum()
+{
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, expectedMinimum);
+ QFETCH(int, expectedMaximum);
+
+ slider->setRange(minimum,maximum);
+ QCOMPARE(slider->minimum(),expectedMinimum);
+ QCOMPARE(slider->maximum(),expectedMaximum);
+ QCOMPARE(reportedMinimum,expectedMinimum);
+ QCOMPARE(reportedMaximum,expectedMaximum);
+
+ slider->setRange(minimum,maximum);
+ slider->setMaximum(slider->minimum() - 1);
+ QCOMPARE(slider->maximum(),slider->minimum());
+ QCOMPARE(reportedMinimum,slider->minimum());
+ QCOMPARE(reportedMaximum,slider->maximum());
+
+ slider->setRange(minimum,maximum);
+ slider->setMinimum(slider->maximum() + 1);
+ QCOMPARE(slider->minimum(),slider->maximum());
+ QCOMPARE(reportedMinimum,slider->minimum());
+ QCOMPARE(reportedMaximum,slider->maximum());
+
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(slider->maximum() + 1);
+ QCOMPARE(slider->sliderPosition(), slider->maximum());
+ QCOMPARE(slider->value(), slider->maximum());
+ QCOMPARE(reportedValue, slider->maximum());
+
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(slider->minimum() - 1);
+ QCOMPARE(slider->sliderPosition(), slider->minimum());
+ QCOMPARE(slider->value(), slider->minimum());
+ QCOMPARE(reportedValue, slider->minimum());
+
+ slider->setRange(minimum,maximum);
+ int oldPosition = slider->sliderPosition();
+ slider->setMaximum(oldPosition - 1);
+ QCOMPARE(slider->sliderPosition(),oldPosition - 1);
+
+ slider->setRange(minimum,maximum);
+ oldPosition = slider->sliderPosition();
+ slider->setMinimum(oldPosition + 1);
+ QCOMPARE(slider->sliderPosition(), oldPosition + 1);
+}
+
+void tst_QAbstractSlider::keyPressed_data()
+{
+ QTest::addColumn<int>("initialSliderPosition");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("stepSize");
+ QTest::addColumn<int>("pageSize");
+ QTest::addColumn<QList<Qt::Key> >("keySequence");
+ QTest::addColumn<int>("expectedSliderPositionHorizontal");
+ QTest::addColumn<int>("expectedSliderPositionVertical");
+ QTest::addColumn<int>("expectedSliderPositionHorizontalInverted"); // :)
+ QTest::addColumn<int>("expectedSliderPositionVerticalInverted");
+
+
+ QList<Qt::Key> list;
+
+ list << Qt::Key_Down;
+ QTest::newRow("Step down once") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 0 // page step size
+ << list // key sequence
+ << 7 // result in case of horizontal slider
+ << 7 // result in case of vertical slider
+ << 13 // result in case of inverted horiz. slider
+ << 13; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_Up;
+ QTest::newRow("Step down once") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 0 // page step size
+ << list // key sequence
+ << 13 // result in case of horizontal slider
+ << 13 // result in case of vertical slider
+ << 7 // result in case of inverted horiz. slider
+ << 7; // result in case of inverted vertical slider
+
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_Left;
+ QTest::newRow("Step left once") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 0 // page step size
+ << list // key sequence
+ << 7 // result in case of horizontal slider
+ << 7 // result in case of vertical slider
+ << 13 // result in case of inverted horiz. slider
+ << 13; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_Right;
+ QTest::newRow("Step right once") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 0 // page step size
+ << list // key sequence
+ << 13 // result in case of horizontal slider
+ << 13 // result in case of vertical slider
+ << 7 // result in case of inverted horiz. slider
+ << 7; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_PageDown;
+ QTest::newRow("Page down once") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 0 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 7 // result in case of horizontal slider
+ << 7 // result in case of vertical slider
+ << 13 // result in case of inverted horiz. slider
+ << 13; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_PageUp;
+ QTest::newRow("Page up once") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 0 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 13 // result in case of horizontal slider
+ << 13 // result in case of vertical slider
+ << 7 // result in case of inverted horiz. slider
+ << 7; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_Up << Qt::Key_Up << Qt::Key_PageDown << Qt::Key_PageDown << Qt::Key_Left << Qt::Key_Left
+ << Qt::Key_Right << Qt::Key_Down << Qt::Key_PageUp << Qt::Key_PageUp << Qt::Key_Down << Qt::Key_Right;
+ QTest::newRow("Symmetric seq") << 50 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 50 // result in case of horizontal slider
+ << 50 // result in case of vertical slider
+ << 50 // result in case of inverted horiz. slider
+ << 50; // result in case of inverted vertical slider
+
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_Home;
+ QTest::newRow("Home") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 0 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 0 // result in case of horizontal slider
+ << 0 // result in case of vertical slider
+ << 0 // result in case of inverted horiz. slider
+ << 0; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_End;
+ QTest::newRow("End") << 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 0 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 100 // result in case of horizontal slider
+ << 100 // result in case of vertical slider
+ << 100 // result in case of inverted horiz. slider
+ << 100; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_End << Qt::Key_Up;
+ QTest::newRow("Past end")<< 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 100 // result in case of horizontal slider
+ << 100 // result in case of vertical slider
+ << 97 // result in case of inverted horiz. slider
+ << 97; // result in case of inverted vertical slider
+
+ list = QList<Qt::Key>();
+ list << Qt::Key_Home << Qt::Key_Down;
+ QTest::newRow("Past home")<< 10 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 3 // single step size
+ << 3 // page step size
+ << list // key sequence
+ << 0 // result in case of horizontal slider
+ << 0 // result in case of vertical slider
+ << 3 // result in case of inverted horiz. slider
+ << 3; // result in case of inverted vertical slider
+
+}
+
+void tst_QAbstractSlider::keyPressed()
+{
+ QFETCH(int, initialSliderPosition);
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, stepSize);
+ QFETCH(int, pageSize);
+ QFETCH(QList<Qt::Key>, keySequence);
+ QFETCH(int, expectedSliderPositionHorizontal);
+ QFETCH(int, expectedSliderPositionVertical);
+ QFETCH(int, expectedSliderPositionHorizontalInverted);
+ QFETCH(int, expectedSliderPositionVerticalInverted);
+
+ // Horizontal non-inverted
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(initialSliderPosition);
+ slider->setSingleStep(stepSize);
+ slider->setPageStep(pageSize);
+ slider->setOrientation(Qt::Horizontal);
+ slider->setInvertedAppearance(false);
+ slider->setInvertedControls(false);
+ for (int i=0;i<keySequence.count();i++) {
+ QTest::keyClick(slider, keySequence.at(i));
+ }
+ QCOMPARE(slider->sliderPosition(), expectedSliderPositionHorizontal);
+
+ // Horizontal inverted
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(initialSliderPosition);
+ slider->setSingleStep(stepSize);
+ slider->setPageStep(pageSize);
+ slider->setOrientation(Qt::Horizontal);
+ slider->setInvertedAppearance(true);
+ slider->setInvertedControls(true);
+ for (int i=0;i<keySequence.count();i++)
+ QTest::keyPress(slider, keySequence.at(i));
+ QCOMPARE(slider->sliderPosition(), expectedSliderPositionHorizontalInverted);
+
+ // Vertical non-inverted
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(initialSliderPosition);
+ slider->setSingleStep(stepSize);
+ slider->setPageStep(pageSize);
+ slider->setOrientation(Qt::Vertical);
+ slider->setInvertedAppearance(false);
+ slider->setInvertedControls(false);
+ for (int i=0;i<keySequence.count();i++)
+ QTest::keyPress(slider, keySequence.at(i));
+ QCOMPARE(slider->sliderPosition(), expectedSliderPositionVertical);
+
+ // Vertical inverted
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(initialSliderPosition);
+ slider->setSingleStep(stepSize);
+ slider->setPageStep(pageSize);
+ slider->setOrientation(Qt::Vertical);
+ slider->setInvertedAppearance(true);
+ slider->setInvertedControls(true);
+ for (int i=0;i<keySequence.count();i++)
+ QTest::keyPress(slider, keySequence.at(i));
+ QCOMPARE(slider->sliderPosition(), expectedSliderPositionVerticalInverted);
+}
+
+void tst_QAbstractSlider::wheelEvent_data()
+{
+ QTest::addColumn<int>("initialSliderPosition");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("singleStep");
+ QTest::addColumn<int>("pageStep");
+ QTest::addColumn<bool>("invertedControls");
+ QTest::addColumn<int>("wheelScrollLines");
+ QTest::addColumn<bool>("withModifiers"); // use keyboard modifiers while scrolling? (CTRL and SHIFT)
+ QTest::addColumn<int>("deltaMultiple"); // multiples of WHEEL_DELTA
+ QTest::addColumn<int>("sliderOrientation");
+ QTest::addColumn<int>("wheelOrientation");
+ QTest::addColumn<int>("expectedSliderPosition");
+ QTest::addColumn<QPoint>("distanceFromBottomRight"); // mpointer's distance from bottom-right corner of widget
+
+ QTest::newRow("Normal data step") << 0 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 1 // single step
+ << 100 // page step
+ << false // inverted controls
+ << 20 // wheel scroll lines
+ << false // with modifiers
+ << 1 // delta
+ << int(Qt::Vertical) // orientation of slider
+ << int(Qt::Vertical) // orientation of wheel
+ << 20 // expected position after
+ << QPoint(0,0);
+
+ QTest::newRow("Normal data page") << 0 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 100 // single step
+ << 1 // page step
+ << false // inverted controls
+ << 20 // wheel scroll lines
+ << false // with modifiers
+ << 1 // delta
+ << int(Qt::Vertical) // orientation of slider
+ << int(Qt::Vertical) // orientation of wheel
+#ifndef Q_WS_MAC
+ << 1 // expected position after
+#else
+ // We don't restrict scrolling to pageStep on Mac
+ << 100 // expected position after
+#endif
+ << QPoint(1,1);
+ QTest::newRow("Different orientation") << 0 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 100 // single step
+ << 1 // page step
+ << false // inverted controls
+ << 20 // wheel scroll lines
+ << false // with modifiers
+ << 1 // delta
+ << int(Qt::Horizontal) // orientation of slider
+ << int(Qt::Vertical) // orientation of wheel
+#ifndef Q_WS_MAC
+ << 1 // expected position after
+#else
+ // We don't restrict scrolling to pageStep on Mac
+ << 100 // expected position after
+#endif
+ << QPoint(1,1);
+
+ QTest::newRow("Different orientation2")<< 0 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 100 // single step
+ << 1 // page step
+ << false // inverted controls
+ << 20 // wheel scroll lines
+ << false // with modifiers
+ << 1 // delta
+ << int(Qt::Horizontal) // orientation of slider
+ << int(Qt::Vertical) // orientation of wheel
+#ifndef Q_WS_MAC
+ << 1 // expected position after
+#else
+ // We don't restrict scrolling to pageStep on Mac
+ << 100 // expected position after
+#endif
+ << QPoint(0,0);
+
+ QTest::newRow("Inverted controls") << 50 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 1 // single step
+ << 100 // page step
+ << true // inverted controls
+ << 20 // wheel scroll lines
+ << false // with modifiers
+ << -1 // delta
+ << int(Qt::Horizontal) // orientation of slider
+ << int(Qt::Horizontal) // orientation of wheel
+ << 30 // expected position after
+ << QPoint(1,1);
+
+ QTest::newRow("Past end") << 50 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 26 // single step
+ << 100 // page step
+ << false // inverted controls
+ << 1 // wheel scroll lines
+ << false // with modifiers
+ << -2 // delta
+ << int(Qt::Horizontal) // orientation of slider
+ << int(Qt::Horizontal) // orientation of wheel
+ << 100 // expected position after
+ << QPoint(0,0);
+
+ QTest::newRow("Past start") << 50 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 26 // single step
+ << 100 // page step
+ << false // inverted controls
+ << 1 // wheel scroll lines
+ << false // with modifiers
+ << 2 // delta
+ << int(Qt::Horizontal) // orientation of slider
+ << int(Qt::Horizontal) // orientation of wheel
+ << 0 // expected position after
+ << QPoint(0,0);
+
+ QTest::newRow("With modifiers") << 50 // initial position
+ << 0 // minimum
+ << 100 // maximum
+ << 1 // single step
+ << 40 // page step
+ << false // inverted controls
+ << 20 // wheel scroll lines
+ << true // with modifiers
+ << -1 // delta
+ << int(Qt::Horizontal) // orientation of slider
+ << int(Qt::Horizontal) // orientation of wheel
+ << 90 // expected position after
+ << QPoint(0,0);
+
+}
+
+void tst_QAbstractSlider::wheelEvent()
+{
+ QFETCH(int,initialSliderPosition);
+ QFETCH(int,minimum);
+ QFETCH(int,maximum);
+ QFETCH(int,singleStep);
+ QFETCH(int,pageStep);
+ QFETCH(bool,invertedControls);
+ QFETCH(int,wheelScrollLines);
+ QFETCH(bool,withModifiers);
+ QFETCH(int,deltaMultiple);
+ QFETCH(int,sliderOrientation);
+ QFETCH(int,wheelOrientation);
+ QFETCH(int,expectedSliderPosition);
+ QFETCH(QPoint,distanceFromBottomRight);
+
+ QCoreApplication *applicationInstance = QCoreApplication::instance();
+ QVERIFY(applicationInstance != 0);
+ QApplication::setWheelScrollLines(wheelScrollLines);
+
+ Qt::Orientation orientation = *reinterpret_cast<Qt::Orientation*>(&sliderOrientation);
+ slider->setRange(minimum,maximum);
+ slider->setSliderPosition(initialSliderPosition);
+ slider->setSingleStep(singleStep);
+ slider->setPageStep(pageStep);
+ slider->setInvertedControls(invertedControls);
+ slider->setOrientation(orientation);
+
+ Qt::KeyboardModifier k = withModifiers ? Qt::ControlModifier : Qt::NoModifier;
+ orientation = *reinterpret_cast<Qt::Orientation*>(&wheelOrientation);
+ QWheelEvent event(slider->rect().bottomRight() + distanceFromBottomRight, WHEEL_DELTA * deltaMultiple,
+ Qt::NoButton, k, orientation);
+ QVERIFY(applicationInstance->sendEvent(slider,&event));
+ QCOMPARE(slider->sliderPosition(),expectedSliderPosition);
+
+ slider->setSliderPosition(initialSliderPosition);
+ k = withModifiers ? Qt::ShiftModifier : Qt::NoModifier;
+ event = QWheelEvent(slider->rect().bottomRight() + distanceFromBottomRight, WHEEL_DELTA * deltaMultiple,
+ Qt::NoButton, k, orientation);
+ QSignalSpy spy1(slider, SIGNAL(actionTriggered(int)));
+ QSignalSpy spy2(slider, SIGNAL(valueChanged(int)));
+ QVERIFY(applicationInstance->sendEvent(slider,&event));
+ QCOMPARE(slider->sliderPosition(),expectedSliderPosition);
+ int expectedSignalCount = (initialSliderPosition == expectedSliderPosition) ? 0 : 1;
+ QCOMPARE(spy1.count(), expectedSignalCount);
+ QCOMPARE(spy2.count(), expectedSignalCount);
+ if (expectedSignalCount)
+ QVERIFY(actionTriggeredTimeStamp < valueChangedTimeStamp);
+}
+
+void tst_QAbstractSlider::sliderPressedReleased_data()
+{
+ QTest::addColumn<int>("control");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<uint>("subControl");
+ QTest::addColumn<int>("expectedCount");
+
+ QTest::newRow("slider on the handle") << int(QStyle::CC_Slider)
+ << 0
+ << 20
+ << uint(QStyle::SC_SliderHandle)
+ << 1;
+
+ QTest::newRow("slider on the groove") << int(QStyle::CC_Slider)
+ << 0
+ << 20
+ << uint(QStyle::SC_SliderGroove)
+ << ((qApp->style()->styleHint(QStyle::SH_Slider_AbsoluteSetButtons) & Qt::LeftButton) ? 1 : 0);
+
+ QTest::newRow("scrollbar on the handle") << int(QStyle::CC_ScrollBar)
+ << 0
+ << 20
+ << uint(QStyle::SC_ScrollBarSlider)
+ << 1;
+
+ QTest::newRow("scrollbar on the groove") << int(QStyle::CC_ScrollBar)
+ << 0
+ << 20
+ << uint(QStyle::SC_ScrollBarGroove)
+ << 0;
+}
+
+void tst_QAbstractSlider::sliderPressedReleased()
+{
+ QFETCH(int, control);
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(uint, subControl);
+ QFETCH(int, expectedCount);
+
+ QWidget topLevel;
+ QAbstractSlider *slider;
+ switch (control) {
+ default:
+ qWarning("Bad input into test, leaving");
+ return;
+ break;
+ case QStyle::CC_Slider:
+ slider = new QSlider(&topLevel);
+ slider->setLayoutDirection(Qt::LeftToRight); // Makes "upside down" much easier to compute
+ break;
+ case QStyle::CC_ScrollBar:
+ slider = new QScrollBar(&topLevel);
+ break;
+ }
+
+
+ slider->setMinimum(minimum);
+ slider->setMaximum(maximum);
+ slider->setValue(0);
+ slider->setOrientation(Qt::Vertical);
+ slider->resize(slider->sizeHint().width(), slider->sizeHint().height() + 100);
+ QSignalSpy spy1(slider, SIGNAL(sliderPressed()));
+ QSignalSpy spy2(slider, SIGNAL(sliderReleased()));
+
+ // Mac Style requires the control to be active to get the correct values...
+ topLevel.show();
+ slider->activateWindow();
+
+ QStyleOptionSlider option;
+ option.init(slider);
+ option.upsideDown = control == QStyle::CC_Slider ? !slider->invertedAppearance()
+ : slider->invertedAppearance();
+ option.subControls = QStyle::SC_None;
+ option.activeSubControls = QStyle::SC_None;
+ option.orientation = slider->orientation();
+ option.maximum = maximum;
+ option.minimum = minimum;
+ option.sliderPosition = slider->value();
+ option.sliderValue = slider->value();
+ option.singleStep = slider->singleStep();
+ option.pageStep = slider->pageStep();
+ QRect rect = slider->style()->subControlRect(QStyle::ComplexControl(control), &option,
+ QStyle::SubControl(subControl), slider);
+
+ QTest::mousePress(slider, Qt::LeftButton, 0, QPoint(rect.center().x() + 2, rect.center().y() + 2));
+ QCOMPARE(spy1.count(), expectedCount);
+ QTest::mouseRelease(slider, Qt::LeftButton, 0, rect.center());
+ QCOMPARE(spy2.count(), expectedCount);
+
+ delete slider;
+}
+
+void tst_QAbstractSlider::sliderMoved_data()
+{
+ QTest::addColumn<int>("control");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("position");
+ QTest::addColumn<bool>("sliderDown");
+ QTest::addColumn<int>("expectedCount");
+
+ QTest::newRow("slider pressed") << int(QStyle::CC_Slider)
+ << 0
+ << 20
+ << 10
+ << true
+ << 1;
+
+ QTest::newRow("slider not pressed") << int(QStyle::CC_Slider)
+ << 0
+ << 20
+ << 10
+ << false
+ << 0;
+
+ QTest::newRow("scrollbar pressed") << int(QStyle::CC_ScrollBar)
+ << 0
+ << 20
+ << 10
+ << true
+ << 1;
+
+ QTest::newRow("scrollbar not pressed") << int(QStyle::CC_ScrollBar)
+ << 0
+ << 20
+ << 10
+ << false
+ << 0;
+}
+
+void tst_QAbstractSlider::sliderMoved()
+{
+ QFETCH(int, control);
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, position);
+ QFETCH(bool, sliderDown);
+ QFETCH(int, expectedCount);
+ QAbstractSlider *slider;
+ switch (control) {
+ default:
+ slider = 0;
+ break;
+ case QStyle::CC_Slider:
+ slider = new QSlider;
+ break;
+ case QStyle::CC_ScrollBar:
+ slider = new QScrollBar;
+ break;
+ }
+ QSignalSpy spy(slider, SIGNAL(sliderMoved(int)));
+
+ slider->setMinimum(minimum);
+ slider->setMaximum(maximum);
+ slider->setSliderDown(sliderDown);
+ slider->setSliderPosition(position);
+ QCOMPARE(spy.count(), expectedCount);
+
+ delete slider;
+}
+
+void tst_QAbstractSlider::setOrientation()
+{
+ QSlider slider(0);
+
+ QSizePolicy sp = slider.sizePolicy();
+ slider.setOrientation(slider.orientation());
+ QSizePolicy sp2 = slider.sizePolicy();
+ QCOMPARE(sp, sp2);
+
+ slider.setOrientation(Qt::Horizontal);
+ sp = slider.sizePolicy();
+ slider.setOrientation(Qt::Vertical);
+ sp2 = slider.sizePolicy();
+
+ QVERIFY(sp != sp2);
+ sp2.transpose();
+ QCOMPARE(sp, sp2);
+}
+
+
+void tst_QAbstractSlider::rangeChanged_data()
+{
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("newMin");
+ QTest::addColumn<int>("newMax");
+ QTest::addColumn<int>("expectedCount");
+
+ QTest::newRow("no change")
+ << 0
+ << 20
+ << 0
+ << 20
+ << 0;
+
+ QTest::newRow("min change")
+ << 0
+ << 20
+ << 10
+ << 20
+ << 1;
+ QTest::newRow("max change")
+ << 0
+ << 20
+ << 0
+ << 30
+ << 1;
+
+ QTest::newRow("both change")
+ << 0
+ << 20
+ << 10
+ << 30
+ << 1;
+}
+
+void tst_QAbstractSlider::rangeChanged()
+{
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, newMin);
+ QFETCH(int, newMax);
+ QFETCH(int, expectedCount);
+ QSlider slider;
+ slider.setRange(minimum, maximum);
+ QSignalSpy spy(&slider, SIGNAL(rangeChanged(int, int)));
+ slider.setRange(newMin, newMax);
+ QCOMPARE(spy.count(), expectedCount);
+}
+
+void tst_QAbstractSlider::setSliderPosition_data()
+{
+ QTest::addColumn<bool>("tracking");
+ QTest::addColumn<bool>("down");
+
+ QTest::newRow("tracking, slider down")
+ << true
+ << true;
+ QTest::newRow("tracking, slider not down")
+ << true
+ << false;
+ QTest::newRow("no tracking, slider down")
+ << false
+ << true;
+ QTest::newRow("no tracking, slider not down")
+ << false
+ << false;
+}
+
+void tst_QAbstractSlider::setSliderPosition()
+{
+ QFETCH(bool, tracking);
+ QFETCH(bool, down);
+ const int minimum = 0;
+ const int maximum = 100;
+ const int initialValue = 50;
+ const int targetPosition = 75;
+ slider->setRange(minimum, maximum);
+ slider->setTracking(tracking);
+ slider->setSliderDown(down);
+ slider->setValue(initialValue);
+ QCOMPARE(slider->sliderPosition(), initialValue);
+ QSignalSpy spy1(slider, SIGNAL(sliderMoved(int)));
+ QSignalSpy spy2(slider, SIGNAL(valueChanged(int)));
+ slider->setSliderPosition(targetPosition);
+ QCOMPARE(slider->sliderPosition(), targetPosition);
+ QCOMPARE(spy1.count(), down ? 1 : 0);
+ QCOMPARE(spy2.count(), tracking ? 1 : 0);
+ QCOMPARE(slider->value(), tracking ? targetPosition : initialValue);
+ if (tracking && down)
+ QVERIFY(sliderMovedTimeStamp < valueChangedTimeStamp);
+}
+
+void tst_QAbstractSlider::setValue_data()
+{
+ QTest::addColumn<bool>("down");
+
+ QTest::newRow("slider down")
+ << true;
+ QTest::newRow("slider not down")
+ << false;
+}
+
+void tst_QAbstractSlider::setValue()
+{
+ QFETCH(bool, down);
+ const int minimum = 0;
+ const int maximum = 100;
+ slider->setRange(minimum, maximum);
+ slider->setSliderDown(down);
+ slider->setValue(49); // to force a valueChanged() below
+ QSignalSpy spy1(slider, SIGNAL(sliderMoved(int)));
+ QSignalSpy spy2(slider, SIGNAL(valueChanged(int)));
+ QSignalSpy spy3(slider, SIGNAL(actionTriggered(int)));
+ slider->setValue(50);
+ QCOMPARE(spy1.count(), down ? 1 : 0);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 0);
+ QCOMPARE(slider->value(), reportedValue);
+ QCOMPARE(slider->sliderPosition(), reportedSliderPosition);
+ if (down)
+ QVERIFY(sliderMovedTimeStamp < valueChangedTimeStamp);
+}
+
+void tst_QAbstractSlider::waitUntilTimeElapsed(const QTime& t, int ms)
+{
+ const int eps = 80;
+ while (t.elapsed() < ms + eps)
+ QTest::qWait(qMax(ms - t.elapsed() + eps, 25));
+}
+
+void tst_QAbstractSlider::setRepeatAction()
+{
+ slider->setRange(0, 1000);
+ slider->setValue(55);
+ slider->setPageStep(10);
+ QSignalSpy spy(slider, SIGNAL(actionTriggered(int)));
+
+ // Start repeat action with initial delay of 500 ms, and then repeating
+ // every 250 ms.
+ slider->setRepeatAction(QAbstractSlider::SliderPageStepAdd, 500, 250);
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(slider->value(), 55);
+
+ QTime t;
+ t.start();
+ QTest::qWait(300);
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(slider->value(), 55);
+
+ waitUntilTimeElapsed(t, 550);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(slider->value(), 65);
+ QCOMPARE(spy.at(0).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd);
+
+ waitUntilTimeElapsed(t, 790);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(slider->value(), 75);
+ QCOMPARE(spy.at(1).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd);
+
+ waitUntilTimeElapsed(t, 1790);
+ QCOMPARE(spy.count(), 6);
+ QCOMPARE(slider->value(), 115);
+ QCOMPARE(spy.at(4).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd);
+ QCOMPARE(spy.at(5).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd);
+
+ slider->setRepeatAction(QAbstractSlider::SliderNoAction);
+ QCOMPARE(spy.count(), 6);
+ QCOMPARE(slider->value(), 115);
+
+ QTest::qWait(300);
+ QCOMPARE(spy.count(), 6);
+ QCOMPARE(slider->value(), 115);
+}
+
+QTEST_MAIN(tst_QAbstractSlider)
+#include "tst_qabstractslider.moc"
diff --git a/tests/auto/widgets/widgets/qabstractspinbox/.gitignore b/tests/auto/widgets/widgets/qabstractspinbox/.gitignore
new file mode 100644
index 0000000000..07d1d652ee
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractspinbox/.gitignore
@@ -0,0 +1 @@
+tst_qabstractspinbox
diff --git a/tests/auto/widgets/widgets/qabstractspinbox/qabstractspinbox.pro b/tests/auto/widgets/widgets/qabstractspinbox/qabstractspinbox.pro
new file mode 100644
index 0000000000..e156b2493d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractspinbox/qabstractspinbox.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qabstractspinbox.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qabstractspinbox.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp b/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp
new file mode 100644
index 0000000000..d14c75bbac
--- /dev/null
+++ b/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qabstractspinbox.h>
+#include <qlineedit.h>
+#include <qspinbox.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAbstractSpinBox : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QAbstractSpinBox();
+ virtual ~tst_QAbstractSpinBox();
+
+private slots:
+ void getSetCheck();
+
+ // task-specific tests below me:
+ void task183108_clear();
+ void task228728_cssselector();
+};
+
+tst_QAbstractSpinBox::tst_QAbstractSpinBox()
+{
+}
+
+tst_QAbstractSpinBox::~tst_QAbstractSpinBox()
+{
+}
+
+class MyAbstractSpinBox : public QAbstractSpinBox
+{
+public:
+ MyAbstractSpinBox() : QAbstractSpinBox() {}
+ QLineEdit *lineEdit() { return QAbstractSpinBox::lineEdit(); }
+ void setLineEdit(QLineEdit *le) { QAbstractSpinBox::setLineEdit(le); }
+};
+
+// Testing get/set functions
+void tst_QAbstractSpinBox::getSetCheck()
+{
+ MyAbstractSpinBox obj1;
+ // ButtonSymbols QAbstractSpinBox::buttonSymbols()
+ // void QAbstractSpinBox::setButtonSymbols(ButtonSymbols)
+ obj1.setButtonSymbols(QAbstractSpinBox::ButtonSymbols(QAbstractSpinBox::UpDownArrows));
+ QCOMPARE(QAbstractSpinBox::ButtonSymbols(QAbstractSpinBox::UpDownArrows), obj1.buttonSymbols());
+ obj1.setButtonSymbols(QAbstractSpinBox::ButtonSymbols(QAbstractSpinBox::PlusMinus));
+ QCOMPARE(QAbstractSpinBox::ButtonSymbols(QAbstractSpinBox::PlusMinus), obj1.buttonSymbols());
+
+ // bool QAbstractSpinBox::wrapping()
+ // void QAbstractSpinBox::setWrapping(bool)
+ obj1.setWrapping(false);
+ QCOMPARE(false, obj1.wrapping());
+ obj1.setWrapping(true);
+ QCOMPARE(true, obj1.wrapping());
+
+ // QLineEdit * QAbstractSpinBox::lineEdit()
+ // void QAbstractSpinBox::setLineEdit(QLineEdit *)
+ QLineEdit *var3 = new QLineEdit(0);
+ obj1.setLineEdit(var3);
+ QCOMPARE(var3, obj1.lineEdit());
+#ifndef QT_DEBUG
+ obj1.setLineEdit((QLineEdit *)0); // Will assert in debug, so only test in release
+ QCOMPARE(var3, obj1.lineEdit()); // Setting 0 should keep the current editor
+#endif
+ // delete var3; // No delete, since QAbstractSpinBox takes ownership
+}
+
+void tst_QAbstractSpinBox::task183108_clear()
+{
+ QAbstractSpinBox *sbox;
+
+ sbox = new QSpinBox;
+ sbox->clear();
+ sbox->show();
+ qApp->processEvents();
+ QVERIFY(sbox->text().isEmpty());
+
+ delete sbox;
+ sbox = new QSpinBox;
+ sbox->clear();
+ sbox->show();
+ sbox->hide();
+ qApp->processEvents();
+ QCOMPARE(sbox->text(), QString());
+
+ delete sbox;
+ sbox = new QSpinBox;
+ sbox->show();
+ sbox->clear();
+ qApp->processEvents();
+ QCOMPARE(sbox->text(), QString());
+
+ delete sbox;
+ sbox = new QSpinBox;
+ sbox->show();
+ sbox->clear();
+ sbox->hide();
+ qApp->processEvents();
+ QCOMPARE(sbox->text(), QString());
+
+ delete sbox;
+}
+
+void tst_QAbstractSpinBox::task228728_cssselector()
+{
+ //QAbstractSpinBox does some call to stylehint into his constructor.
+ //so while the stylesheet want to access property, it should not crash
+ qApp->setStyleSheet("[alignement=\"1\"], [text=\"foo\"] { color:black; }" );
+ QSpinBox box;
+}
+
+
+QTEST_MAIN(tst_QAbstractSpinBox)
+#include "tst_qabstractspinbox.moc"
diff --git a/tests/auto/widgets/widgets/qbuttongroup/.gitignore b/tests/auto/widgets/widgets/qbuttongroup/.gitignore
new file mode 100644
index 0000000000..898b2276b0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qbuttongroup/.gitignore
@@ -0,0 +1 @@
+tst_qbuttongroup
diff --git a/tests/auto/widgets/widgets/qbuttongroup/qbuttongroup.pro b/tests/auto/widgets/widgets/qbuttongroup/qbuttongroup.pro
new file mode 100644
index 0000000000..6f506e8f06
--- /dev/null
+++ b/tests/auto/widgets/widgets/qbuttongroup/qbuttongroup.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qbuttongroup.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp
new file mode 100644
index 0000000000..f9f6ec0a54
--- /dev/null
+++ b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include "qbuttongroup.h"
+#include <qaction.h>
+#include <qapplication.h>
+#include <qdialog.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qradiobutton.h>
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qtoolbutton.h>
+#ifdef Q_WS_MAC
+#include <qsettings.h>
+#endif
+
+class SpecialRadioButton: public QRadioButton
+{
+public:
+ SpecialRadioButton(QWidget *parent) : QRadioButton(parent)
+ { }
+
+protected:
+ void focusInEvent(QFocusEvent *)
+ {
+ QCoreApplication::postEvent(this, new QKeyEvent(QEvent::KeyPress,
+ Qt::Key_Down, Qt::NoModifier));
+ }
+};
+
+#include <qbuttongroup.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QButtonGroup : public QObject
+{
+Q_OBJECT
+public:
+ tst_QButtonGroup();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void arrowKeyNavigation();
+ void exclusive();
+ void exclusiveWithActions();
+ void testSignals();
+ void checkedButton();
+
+ void task106609();
+
+ void autoIncrementId();
+
+ void task209485_removeFromGroupInEventHandler_data();
+ void task209485_removeFromGroupInEventHandler();
+};
+
+tst_QButtonGroup::tst_QButtonGroup()
+{
+}
+
+
+void tst_QButtonGroup::initTestCase()
+{
+}
+
+void tst_QButtonGroup::cleanupTestCase()
+{
+}
+
+void tst_QButtonGroup::init()
+{
+}
+
+void tst_QButtonGroup::cleanup()
+{
+}
+
+QT_BEGIN_NAMESPACE
+extern bool Q_GUI_EXPORT qt_tab_all_widgets;
+QT_END_NAMESPACE
+
+
+void tst_QButtonGroup::arrowKeyNavigation()
+{
+ if (!qt_tab_all_widgets)
+ QSKIP("This test requires full keyboard control to be enabled.", SkipAll);
+
+ QDialog dlg(0);
+ QHBoxLayout layout(&dlg);
+ QGroupBox g1("1", &dlg);
+ QHBoxLayout g1layout(&g1);
+ QRadioButton bt1("Radio1", &g1);
+ QPushButton pb("PB", &g1);
+ QLineEdit le(&g1);
+ QRadioButton bt2("Radio2", &g1);
+ g1layout.addWidget(&bt1);
+ g1layout.addWidget(&pb);
+ g1layout.addWidget(&le);
+ g1layout.addWidget(&bt2);
+
+ // create a mixed button group with radion buttons and push
+ // buttons. Not very useful, but it tests borderline cases wrt
+ // focus handling.
+ QButtonGroup bgrp1(&g1);
+ bgrp1.addButton(&bt1);
+ bgrp1.addButton(&pb);
+ bgrp1.addButton(&bt2);
+
+ QGroupBox g2("2", &dlg);
+ QVBoxLayout g2layout(&g2);
+ // we don't need a button group here, because radio buttons are
+ // auto exclusive, i.e. they group themselves in he same parent
+ // widget.
+ QRadioButton bt3("Radio3", &g2);
+ QRadioButton bt4("Radio4", &g2);
+ g2layout.addWidget(&bt3);
+ g2layout.addWidget(&bt4);
+
+ layout.addWidget(&g1);
+ layout.addWidget(&g2);
+
+ dlg.show();
+ qApp->setActiveWindow(&dlg);
+ QTest::qWaitForWindowShown(&dlg);
+
+ bt1.setFocus();
+
+ QTRY_VERIFY(bt1.hasFocus());
+
+ QTest::keyClick(&bt1, Qt::Key_Right);
+ QVERIFY(pb.hasFocus());
+ QTest::keyClick(&pb, Qt::Key_Right);
+ QVERIFY(bt2.hasFocus());
+ QTest::keyClick(&bt2, Qt::Key_Right);
+ QVERIFY(bt2.hasFocus());
+ QTest::keyClick(&bt2, Qt::Key_Left);
+ QVERIFY(pb.hasFocus());
+ QTest::keyClick(&pb, Qt::Key_Left);
+ QVERIFY(bt1.hasFocus());
+
+ QTest::keyClick(&bt1, Qt::Key_Tab);
+ QVERIFY(pb.hasFocus());
+ QTest::keyClick(&pb, Qt::Key_Tab);
+
+ QVERIFY(le.hasFocus());
+ QCOMPARE(le.selectedText(), le.text());
+ QTest::keyClick(&le, Qt::Key_Tab);
+
+ QVERIFY(bt2.hasFocus());
+ QTest::keyClick(&bt2, Qt::Key_Tab);
+ QVERIFY(bt3.hasFocus());
+
+ QTest::keyClick(&bt3, Qt::Key_Down);
+ QVERIFY(bt4.hasFocus());
+ QTest::keyClick(&bt4, Qt::Key_Down);
+ QVERIFY(bt4.hasFocus());
+
+ QTest::keyClick(&bt4, Qt::Key_Up);
+ QVERIFY(bt3.hasFocus());
+ QTest::keyClick(&bt3, Qt::Key_Up);
+ QVERIFY(bt3.hasFocus());
+}
+
+void tst_QButtonGroup::exclusiveWithActions()
+{
+ QDialog dlg(0);
+ QHBoxLayout layout(&dlg);
+ QAction *action1 = new QAction("Action 1", &dlg);
+ action1->setCheckable(true);
+ QAction *action2 = new QAction("Action 2", &dlg);
+ action2->setCheckable(true);
+ QAction *action3 = new QAction("Action 3", &dlg);
+ action3->setCheckable(true);
+ QToolButton *toolButton1 = new QToolButton(&dlg);
+ QToolButton *toolButton2 = new QToolButton(&dlg);
+ QToolButton *toolButton3 = new QToolButton(&dlg);
+ toolButton1->setDefaultAction(action1);
+ toolButton2->setDefaultAction(action2);
+ toolButton3->setDefaultAction(action3);
+ layout.addWidget(toolButton1);
+ layout.addWidget(toolButton2);
+ layout.addWidget(toolButton3);
+ QButtonGroup *buttonGroup = new QButtonGroup( &dlg );
+ buttonGroup->setExclusive(true);
+ buttonGroup->addButton(toolButton1, 1);
+ buttonGroup->addButton(toolButton2, 2);
+ buttonGroup->addButton(toolButton3, 3);
+ dlg.show();
+
+ QTest::mouseClick(toolButton1, Qt::LeftButton);
+ QVERIFY(toolButton1->isChecked());
+ QVERIFY(action1->isChecked());
+ QVERIFY(!toolButton2->isChecked());
+ QVERIFY(!toolButton3->isChecked());
+ QVERIFY(!action2->isChecked());
+ QVERIFY(!action3->isChecked());
+
+ QTest::mouseClick(toolButton2, Qt::LeftButton);
+ QVERIFY(toolButton2->isChecked());
+ QVERIFY(action2->isChecked());
+ QVERIFY(!toolButton1->isChecked());
+ QVERIFY(!toolButton3->isChecked());
+ QVERIFY(!action1->isChecked());
+ QVERIFY(!action3->isChecked());
+
+ QTest::mouseClick(toolButton3, Qt::LeftButton);
+ QVERIFY(toolButton3->isChecked());
+ QVERIFY(action3->isChecked());
+ QVERIFY(!toolButton1->isChecked());
+ QVERIFY(!toolButton2->isChecked());
+ QVERIFY(!action1->isChecked());
+ QVERIFY(!action2->isChecked());
+
+ QTest::mouseClick(toolButton2, Qt::LeftButton);
+ QVERIFY(toolButton2->isChecked());
+ QVERIFY(action2->isChecked());
+ QVERIFY(!toolButton1->isChecked());
+ QVERIFY(!toolButton3->isChecked());
+ QVERIFY(!action1->isChecked());
+ QVERIFY(!action3->isChecked());
+}
+
+void tst_QButtonGroup::exclusive()
+{
+ QDialog dlg(0);
+ QHBoxLayout layout(&dlg);
+ QPushButton *pushButton1 = new QPushButton(&dlg);
+ QPushButton *pushButton2 = new QPushButton(&dlg);
+ QPushButton *pushButton3 = new QPushButton(&dlg);
+ pushButton1->setCheckable(true);
+ pushButton2->setCheckable(true);
+ pushButton3->setCheckable(true);
+ layout.addWidget(pushButton1);
+ layout.addWidget(pushButton2);
+ layout.addWidget(pushButton3);
+ QButtonGroup *buttonGroup = new QButtonGroup( &dlg );
+ buttonGroup->setExclusive(true);
+ buttonGroup->addButton(pushButton1, 1);
+ buttonGroup->addButton(pushButton2, 2);
+ buttonGroup->addButton(pushButton3, 3);
+ dlg.show();
+
+ QTest::mouseClick(pushButton1, Qt::LeftButton);
+ QVERIFY(pushButton1->isChecked());
+ QVERIFY(!pushButton2->isChecked());
+ QVERIFY(!pushButton3->isChecked());
+
+ QTest::mouseClick(pushButton2, Qt::LeftButton);
+ QVERIFY(pushButton2->isChecked());
+ QVERIFY(!pushButton1->isChecked());
+ QVERIFY(!pushButton3->isChecked());
+
+ QTest::mouseClick(pushButton3, Qt::LeftButton);
+ QVERIFY(pushButton3->isChecked());
+ QVERIFY(!pushButton1->isChecked());
+ QVERIFY(!pushButton2->isChecked());
+
+ QTest::mouseClick(pushButton2, Qt::LeftButton);
+ QVERIFY(pushButton2->isChecked());
+ QVERIFY(!pushButton1->isChecked());
+ QVERIFY(!pushButton3->isChecked());
+}
+
+void tst_QButtonGroup::testSignals()
+{
+ QButtonGroup buttons;
+ QPushButton pb1;
+ QPushButton pb2;
+ QPushButton pb3;
+ buttons.addButton(&pb1);
+ buttons.addButton(&pb2, 23);
+ buttons.addButton(&pb3);
+
+ qRegisterMetaType<QAbstractButton *>("QAbstractButton *");
+ QSignalSpy clickedSpy(&buttons, SIGNAL(buttonClicked(QAbstractButton *)));
+ QSignalSpy clickedIdSpy(&buttons, SIGNAL(buttonClicked(int)));
+ QSignalSpy pressedSpy(&buttons, SIGNAL(buttonPressed(QAbstractButton *)));
+ QSignalSpy pressedIdSpy(&buttons, SIGNAL(buttonPressed(int)));
+ QSignalSpy releasedSpy(&buttons, SIGNAL(buttonReleased(QAbstractButton *)));
+ QSignalSpy releasedIdSpy(&buttons, SIGNAL(buttonReleased(int)));
+
+ pb1.animateClick();
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(clickedSpy.count(), 1);
+ QCOMPARE(clickedIdSpy.count(), 1);
+
+ int expectedId = -2;
+
+ QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == expectedId);
+ QCOMPARE(pressedSpy.count(), 1);
+ QCOMPARE(pressedIdSpy.count(), 1);
+ QVERIFY(pressedIdSpy.takeFirst().at(0).toInt() == expectedId);
+ QCOMPARE(releasedSpy.count(), 1);
+ QCOMPARE(releasedIdSpy.count(), 1);
+ QVERIFY(releasedIdSpy.takeFirst().at(0).toInt() == expectedId);
+
+ clickedSpy.clear();
+ clickedIdSpy.clear();
+ pressedSpy.clear();
+ pressedIdSpy.clear();
+ releasedSpy.clear();
+ releasedIdSpy.clear();
+
+ pb2.animateClick();
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(clickedSpy.count(), 1);
+ QCOMPARE(clickedIdSpy.count(), 1);
+ QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == 23);
+ QCOMPARE(pressedSpy.count(), 1);
+ QCOMPARE(pressedIdSpy.count(), 1);
+ QVERIFY(pressedIdSpy.takeFirst().at(0).toInt() == 23);
+ QCOMPARE(releasedSpy.count(), 1);
+ QCOMPARE(releasedIdSpy.count(), 1);
+ QVERIFY(releasedIdSpy.takeFirst().at(0).toInt() == 23);
+}
+
+void tst_QButtonGroup::task106609()
+{
+ // task is:
+ // sometimes, only one of the two signals in QButtonGroup get emitted
+ // they get emitted when using the mouse, but when using the keyboard, only one is
+ //
+
+ QDialog dlg(0);
+ QButtonGroup *buttons = new QButtonGroup(&dlg);
+ QVBoxLayout *vbox = new QVBoxLayout(&dlg);
+
+ SpecialRadioButton *radio1 = new SpecialRadioButton(&dlg);
+ radio1->setText("radio1");
+ SpecialRadioButton *radio2 = new SpecialRadioButton(&dlg);
+ radio2->setText("radio2");
+ QRadioButton *radio3 = new QRadioButton(&dlg);
+ radio3->setText("radio3");
+
+ buttons->addButton(radio1, 1);
+ vbox->addWidget(radio1);
+ buttons->addButton(radio2, 2);
+ vbox->addWidget(radio2);
+ buttons->addButton(radio3, 3);
+ vbox->addWidget(radio3);
+ dlg.show();
+ QTest::qWaitForWindowShown(&dlg);
+
+ qRegisterMetaType<QAbstractButton*>("QAbstractButton*");
+ QSignalSpy spy1(buttons, SIGNAL(buttonClicked(QAbstractButton*)));
+ QSignalSpy spy2(buttons, SIGNAL(buttonClicked(int)));
+
+ QApplication::setActiveWindow(&dlg);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&dlg));
+
+ radio1->setFocus();
+ radio1->setChecked(true);
+ QTestEventLoop::instance().enterLoop(1);
+
+ //qDebug() << "int:" << spy2.count() << "QAbstractButton*:" << spy1.count();
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy1.count(), 2);
+}
+
+void tst_QButtonGroup::checkedButton()
+{
+ QButtonGroup buttons;
+ buttons.setExclusive(false);
+ QPushButton pb1;
+ pb1.setCheckable(true);
+ QPushButton pb2;
+ pb2.setCheckable(true);
+ buttons.addButton(&pb1);
+ buttons.addButton(&pb2, 23);
+
+ QVERIFY(buttons.checkedButton() == 0);
+ pb1.setChecked(true);
+ QVERIFY(buttons.checkedButton() == &pb1);
+ pb2.setChecked(true);
+ QVERIFY(buttons.checkedButton() == &pb2);
+ pb2.setChecked(false);
+ QVERIFY(buttons.checkedButton() == &pb1);
+ pb1.setChecked(false);
+ QVERIFY(buttons.checkedButton() == 0);
+
+ buttons.setExclusive(true);
+ QVERIFY(buttons.checkedButton() == 0);
+ pb1.setChecked(true);
+ QVERIFY(buttons.checkedButton() == &pb1);
+ pb2.setChecked(true);
+ QVERIFY(buttons.checkedButton() == &pb2);
+ // checked button cannot be unchecked
+ pb2.setChecked(false);
+ QVERIFY(buttons.checkedButton() == &pb2);
+}
+
+class task209485_ButtonDeleter : public QObject
+{
+ Q_OBJECT
+
+public:
+ task209485_ButtonDeleter(QButtonGroup *group, bool deleteButton)
+ : group(group)
+ , deleteButton(deleteButton)
+ {
+ connect(group, SIGNAL(buttonClicked(int)), SLOT(buttonClicked(int)));
+ }
+
+private slots:
+ void buttonClicked(int)
+ {
+ if (deleteButton)
+ group->removeButton(group->buttons().first());
+ }
+
+private:
+ QButtonGroup *group;
+ bool deleteButton;
+};
+
+void tst_QButtonGroup::task209485_removeFromGroupInEventHandler_data()
+{
+ QTest::addColumn<bool>("deleteButton");
+ QTest::addColumn<int>("signalCount");
+ QTest::newRow("buttonPress 1") << true << 1;
+ QTest::newRow("buttonPress 2") << false << 2;
+}
+
+void tst_QButtonGroup::task209485_removeFromGroupInEventHandler()
+{
+ QFETCH(bool, deleteButton);
+ QFETCH(int, signalCount);
+ qRegisterMetaType<QAbstractButton *>("QAbstractButton *");
+
+ QPushButton *button = new QPushButton;
+ QButtonGroup group;
+ group.addButton(button);
+
+ task209485_ButtonDeleter buttonDeleter(&group, deleteButton);
+
+ QSignalSpy spy1(&group, SIGNAL(buttonClicked(QAbstractButton *)));
+ QSignalSpy spy2(&group, SIGNAL(buttonClicked(int)));
+
+ // NOTE: Reintroducing the bug of this task will cause the following line to crash:
+ QTest::mouseClick(button, Qt::LeftButton);
+
+ QCOMPARE(spy1.count() + spy2.count(), signalCount);
+}
+
+void tst_QButtonGroup::autoIncrementId()
+{
+ QDialog dlg(0);
+ QButtonGroup *buttons = new QButtonGroup(&dlg);
+ QVBoxLayout *vbox = new QVBoxLayout(&dlg);
+
+ QRadioButton *radio1 = new QRadioButton(&dlg);
+ radio1->setText("radio1");
+ QRadioButton *radio2 = new QRadioButton(&dlg);
+ radio2->setText("radio2");
+ QRadioButton *radio3 = new QRadioButton(&dlg);
+ radio3->setText("radio3");
+
+ buttons->addButton(radio1);
+ vbox->addWidget(radio1);
+ buttons->addButton(radio2);
+ vbox->addWidget(radio2);
+ buttons->addButton(radio3);
+ vbox->addWidget(radio3);
+
+ radio1->setChecked(true);
+
+ QVERIFY(buttons->id(radio1) == -2);
+ QVERIFY(buttons->id(radio2) == -3);
+ QVERIFY(buttons->id(radio3) == -4);
+
+ dlg.show();
+}
+
+QTEST_MAIN(tst_QButtonGroup)
+#include "tst_qbuttongroup.moc"
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/.gitignore b/tests/auto/widgets/widgets/qcalendarwidget/.gitignore
new file mode 100644
index 0000000000..db8a381e0d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcalendarwidget/.gitignore
@@ -0,0 +1 @@
+tst_qcalendarwidget
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro b/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro
new file mode 100644
index 0000000000..d250b83537
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qcalendarwidget.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
new file mode 100644
index 0000000000..50dc6a1d1c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcalendarwidget.h>
+#include <qtoolbutton.h>
+#include <qspinbox.h>
+#include <qmenu.h>
+#include <qdebug.h>
+#include <qdatetime.h>
+#include <qtextformat.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QCalendarWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QCalendarWidget();
+ virtual ~tst_QCalendarWidget();
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void buttonClickCheck();
+
+ void setTextFormat();
+ void resetTextFormat();
+
+ void setWeekdayFormat();
+ void showPrevNext_data();
+ void showPrevNext();
+};
+
+// Testing get/set functions
+void tst_QCalendarWidget::getSetCheck()
+{
+ QWidget topLevel;
+ QCalendarWidget object(&topLevel);
+
+ //horizontal header formats
+ object.setHorizontalHeaderFormat(QCalendarWidget::NoHorizontalHeader);
+ QCOMPARE(QCalendarWidget::NoHorizontalHeader, object.horizontalHeaderFormat());
+ object.setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
+ QCOMPARE(QCalendarWidget::SingleLetterDayNames, object.horizontalHeaderFormat());
+ object.setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);
+ QCOMPARE(QCalendarWidget::ShortDayNames, object.horizontalHeaderFormat());
+ object.setHorizontalHeaderFormat(QCalendarWidget::LongDayNames);
+ QCOMPARE(QCalendarWidget::LongDayNames, object.horizontalHeaderFormat());
+ //vertical header formats
+ object.setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);
+ QCOMPARE(QCalendarWidget::ISOWeekNumbers, object.verticalHeaderFormat());
+ object.setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
+ QCOMPARE(QCalendarWidget::NoVerticalHeader, object.verticalHeaderFormat());
+ //maximum Date
+ QDate maxDate(2006, 7, 3);
+ object.setMaximumDate(maxDate);
+ QCOMPARE(maxDate, object.maximumDate());
+ //minimum date
+ QDate minDate(2004, 7, 3);
+ object.setMinimumDate(minDate);
+ QCOMPARE(minDate, object.minimumDate());
+ //day of week
+ object.setFirstDayOfWeek(Qt::Thursday);
+ QCOMPARE(Qt::Thursday, object.firstDayOfWeek());
+ //grid visible
+ object.setGridVisible(true);
+ QVERIFY(object.isGridVisible());
+ object.setGridVisible(false);
+ QVERIFY(!object.isGridVisible());
+ //header visible
+ object.setNavigationBarVisible(true);
+ QVERIFY(object.isNavigationBarVisible());
+ object.setNavigationBarVisible(false);
+ QVERIFY(!object.isNavigationBarVisible());
+ //selection mode
+ QCOMPARE(QCalendarWidget::SingleSelection, object.selectionMode());
+ object.setSelectionMode(QCalendarWidget::NoSelection);
+ QCOMPARE(QCalendarWidget::NoSelection, object.selectionMode());
+ object.setSelectionMode(QCalendarWidget::SingleSelection);
+ QCOMPARE(QCalendarWidget::SingleSelection, object.selectionMode());
+ //selected date
+ QDate selectedDate(2005, 7, 3);
+ QSignalSpy spy(&object, SIGNAL(selectionChanged()));
+ object.setSelectedDate(selectedDate);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(selectedDate, object.selectedDate());
+ //month and year
+ object.setCurrentPage(2004, 1);
+ QCOMPARE(1, object.monthShown());
+ QCOMPARE(2004, object.yearShown());
+ object.showNextMonth();
+ QCOMPARE(2, object.monthShown());
+ object.showPreviousMonth();
+ QCOMPARE(1, object.monthShown());
+ object.showNextYear();
+ QCOMPARE(2005, object.yearShown());
+ object.showPreviousYear();
+ QCOMPARE(2004, object.yearShown());
+ //date range
+ minDate = QDate(2006,1,1);
+ maxDate = QDate(2010,12,31);
+ object.setDateRange(minDate, maxDate);
+ QCOMPARE(maxDate, object.maximumDate());
+ QCOMPARE(minDate, object.minimumDate());
+
+ //date should not go beyond the minimum.
+ selectedDate = minDate.addDays(-10);
+ object.setSelectedDate(selectedDate);
+ QCOMPARE(minDate, object.selectedDate());
+ QVERIFY(selectedDate != object.selectedDate());
+ //date should not go beyond the maximum.
+ selectedDate = maxDate.addDays(10);
+ object.setSelectedDate(selectedDate);
+ QCOMPARE(maxDate, object.selectedDate());
+ QVERIFY(selectedDate != object.selectedDate());
+ //show today
+ QDate today = QDate::currentDate();
+ object.showToday();
+ QCOMPARE(today.month(), object.monthShown());
+ QCOMPARE(today.year(), object.yearShown());
+ //slect a different date and move.
+ object.setSelectedDate(minDate);
+ object.showSelectedDate();
+ QCOMPARE(minDate.month(), object.monthShown());
+ QCOMPARE(minDate.year(), object.yearShown());
+}
+
+void tst_QCalendarWidget::buttonClickCheck()
+{
+ QCalendarWidget object;
+ QSize size = object.sizeHint();
+ object.setGeometry(0,0,size.width(), size.height());
+ object.show();
+
+ QRect rect = object.geometry();
+ QDate selectedDate(2005, 1, 1);
+ //click on the month buttons
+ int month = object.monthShown();
+ QToolButton *button = qFindChild<QToolButton *>(&object, "qt_calendar_prevmonth");
+ QTest::mouseClick(button, Qt::LeftButton);
+ QCOMPARE(month > 1 ? month-1 : 12, object.monthShown());
+ button = qFindChild<QToolButton *>(&object, "qt_calendar_nextmonth");
+ QTest::mouseClick(button, Qt::LeftButton);
+ QCOMPARE(month, object.monthShown());
+
+ button = qFindChild<QToolButton *>(&object, "qt_calendar_yearbutton");
+ QTest::mouseClick(button, Qt::LeftButton, Qt::NoModifier, button->rect().center(), 2);
+ QVERIFY(!button->isVisible());
+ QSpinBox *spinbox = qFindChild<QSpinBox *>(&object, "qt_calendar_yearedit");
+ QTest::qWait(500);
+ QTest::keyClick(spinbox, '2');
+ QTest::keyClick(spinbox, '0');
+ QTest::keyClick(spinbox, '0');
+ QTest::keyClick(spinbox, '6');
+ QTest::qWait(500);
+ QWidget *widget = qFindChild<QWidget *>(&object, "qt_calendar_calendarview");
+ QTest::mouseMove(widget);
+ QTest::mouseClick(widget, Qt::LeftButton);
+ QCOMPARE(2006, object.yearShown());
+ object.setSelectedDate(selectedDate);
+ object.showSelectedDate();
+ QTest::keyClick(widget, Qt::Key_Down);
+ QVERIFY(selectedDate != object.selectedDate());
+
+ object.setDateRange(QDate(2006,1,1), QDate(2006,2,28));
+ object.setSelectedDate(QDate(2006,1,1));
+ object.showSelectedDate();
+ button = qFindChild<QToolButton *>(&object, "qt_calendar_prevmonth");
+ QTest::mouseClick(button, Qt::LeftButton);
+ QCOMPARE(1, object.monthShown());
+
+ button = qFindChild<QToolButton *>(&object, "qt_calendar_nextmonth");
+ QTest::mouseClick(button, Qt::LeftButton);
+ QCOMPARE(2, object.monthShown());
+ QTest::mouseClick(button, Qt::LeftButton);
+ QCOMPARE(2, object.monthShown());
+
+}
+
+void tst_QCalendarWidget::setTextFormat()
+{
+ QCalendarWidget calendar;
+ QTextCharFormat format;
+ format.setFontItalic(true);
+ format.setForeground(Qt::green);
+
+ const QDate date(1984, 10, 20);
+ calendar.setDateTextFormat(date, format);
+ QCOMPARE(calendar.dateTextFormat(date), format);
+}
+
+void tst_QCalendarWidget::resetTextFormat()
+{
+ QCalendarWidget calendar;
+ QTextCharFormat format;
+ format.setFontItalic(true);
+ format.setForeground(Qt::green);
+
+ const QDate date(1984, 10, 20);
+ calendar.setDateTextFormat(date, format);
+
+ calendar.setDateTextFormat(QDate(), QTextCharFormat());
+ QCOMPARE(calendar.dateTextFormat(date), QTextCharFormat());
+}
+
+void tst_QCalendarWidget::setWeekdayFormat()
+{
+ QCalendarWidget calendar;
+
+ QTextCharFormat format;
+ format.setFontItalic(true);
+ format.setForeground(Qt::green);
+
+ calendar.setWeekdayTextFormat(Qt::Wednesday, format);
+
+ // check the format of the a given month
+ for (int i = 1; i <= 31; ++i) {
+ const QDate date(1984, 10, i);
+ const Qt::DayOfWeek dayOfWeek = static_cast<Qt::DayOfWeek>(date.dayOfWeek());
+ if (dayOfWeek == Qt::Wednesday)
+ QCOMPARE(calendar.weekdayTextFormat(dayOfWeek), format);
+ else
+ QVERIFY(calendar.weekdayTextFormat(dayOfWeek) != format);
+ }
+}
+
+tst_QCalendarWidget::tst_QCalendarWidget()
+{
+}
+
+tst_QCalendarWidget::~tst_QCalendarWidget()
+{
+}
+
+void tst_QCalendarWidget::initTestCase()
+{
+}
+
+void tst_QCalendarWidget::cleanupTestCase()
+{
+}
+
+void tst_QCalendarWidget::init()
+{
+}
+
+void tst_QCalendarWidget::cleanup()
+{
+}
+
+
+typedef void (QCalendarWidget::*ShowFunc)();
+Q_DECLARE_METATYPE(ShowFunc)
+
+void tst_QCalendarWidget::showPrevNext_data()
+{
+ QTest::addColumn<ShowFunc>("function");
+ QTest::addColumn<QDate>("dateOrigin");
+ QTest::addColumn<QDate>("expectedDate");
+
+ QTest::newRow("showNextMonth") << &QCalendarWidget::showNextMonth << QDate(1984,7,30) << QDate(1984,8,30);
+ QTest::newRow("showPrevMonth") << &QCalendarWidget::showPreviousMonth << QDate(1984,7,30) << QDate(1984,6,30);
+ QTest::newRow("showNextYear") << &QCalendarWidget::showNextYear << QDate(1984,7,30) << QDate(1985,7,30);
+ QTest::newRow("showPrevYear") << &QCalendarWidget::showPreviousYear << QDate(1984,7,30) << QDate(1983,7,30);
+
+ QTest::newRow("showNextMonth limit") << &QCalendarWidget::showNextMonth << QDate(2007,12,4) << QDate(2008,1,4);
+ QTest::newRow("showPreviousMonth limit") << &QCalendarWidget::showPreviousMonth << QDate(2006,1,23) << QDate(2005,12,23);
+
+ QTest::newRow("showNextMonth now") << &QCalendarWidget::showNextMonth << QDate() << QDate::currentDate().addMonths(1);
+ QTest::newRow("showNextYear now") << &QCalendarWidget::showNextYear << QDate() << QDate::currentDate().addYears(1);
+ QTest::newRow("showPrevieousMonth now") << &QCalendarWidget::showPreviousMonth << QDate() << QDate::currentDate().addMonths(-1);
+ QTest::newRow("showPreviousYear now") << &QCalendarWidget::showPreviousYear << QDate() << QDate::currentDate().addYears(-1);
+
+ QTest::newRow("showToday now") << &QCalendarWidget::showToday << QDate(2000,1,31) << QDate::currentDate();
+ QTest::newRow("showNextMonth 31") << &QCalendarWidget::showNextMonth << QDate(2000,1,31) << QDate(2000,2,28);
+ QTest::newRow("selectedDate") << &QCalendarWidget::showSelectedDate << QDate(2008,2,29) << QDate(2008,2,29);
+
+}
+
+void tst_QCalendarWidget::showPrevNext()
+{
+ QFETCH(ShowFunc, function);
+ QFETCH(QDate, dateOrigin);
+ QFETCH(QDate, expectedDate);
+
+ QCalendarWidget calWidget;
+ calWidget.show();
+ QTest::qWaitForWindowShown(&calWidget);
+ if(!dateOrigin.isNull()) {
+ calWidget.setSelectedDate(dateOrigin);
+ calWidget.setCurrentPage(dateOrigin.year(), dateOrigin.month());
+
+ QCOMPARE(calWidget.yearShown(), dateOrigin.year());
+ QCOMPARE(calWidget.monthShown(), dateOrigin.month());
+ } else {
+ QCOMPARE(calWidget.yearShown(), QDate::currentDate().year());
+ QCOMPARE(calWidget.monthShown(), QDate::currentDate().month());
+ }
+
+ (calWidget.*function)();
+
+ QCOMPARE(calWidget.yearShown(), expectedDate.year());
+ QCOMPARE(calWidget.monthShown(), expectedDate.month());
+
+ // QTBUG-4058
+ QTest::qWait(20);
+ QToolButton *button = qFindChild<QToolButton *>(&calWidget, "qt_calendar_prevmonth");
+ QTest::mouseClick(button, Qt::LeftButton);
+ expectedDate = expectedDate.addMonths(-1);
+ QCOMPARE(calWidget.yearShown(), expectedDate.year());
+ QCOMPARE(calWidget.monthShown(), expectedDate.month());
+
+ if(!dateOrigin.isNull()) {
+ //the selectedDate should not have changed
+ QCOMPARE(calWidget.selectedDate(), dateOrigin);
+ }
+}
+
+QTEST_MAIN(tst_QCalendarWidget)
+#include "tst_qcalendarwidget.moc"
diff --git a/tests/auto/widgets/widgets/qcheckbox/.gitignore b/tests/auto/widgets/widgets/qcheckbox/.gitignore
new file mode 100644
index 0000000000..b838802077
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcheckbox/.gitignore
@@ -0,0 +1 @@
+tst_qcheckbox
diff --git a/tests/auto/widgets/widgets/qcheckbox/qcheckbox.pro b/tests/auto/widgets/widgets/qcheckbox/qcheckbox.pro
new file mode 100644
index 0000000000..aa1f35b3c9
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcheckbox/qcheckbox.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qcheckbox.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp b/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp
new file mode 100644
index 0000000000..33f5af4d0b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include "qcheckbox.h"
+#include <qapplication.h>
+#include <qpixmap.h>
+#include <qdatetime.h>
+#include <qcheckbox.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QCheckBox : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QCheckBox();
+ virtual ~tst_QCheckBox();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void setChecked();
+ void setTriState();
+ void setText_data();
+ void setText();
+ void isToggleButton();
+ void setDown();
+ void setAutoRepeat();
+ void toggle();
+ void pressed();
+ void toggled();
+ void stateChanged();
+ void foregroundRole();
+ void minimumSizeHint();
+
+protected slots:
+ void onClicked();
+ void onToggled( bool on );
+ void onPressed();
+ void onReleased();
+ void onStateChanged( int state );
+
+private:
+ uint click_count;
+ uint toggle_count;
+ uint press_count;
+ uint release_count;
+ int cur_state;
+ uint tmp;
+ QCheckBox *testWidget;
+ uint tmp2;
+};
+
+tst_QCheckBox::tst_QCheckBox()
+{
+}
+
+tst_QCheckBox::~tst_QCheckBox()
+{
+}
+
+void tst_QCheckBox::initTestCase()
+{
+ // Create the test class
+ testWidget = new QCheckBox(0);
+ testWidget->setObjectName("testObject");
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+}
+
+void tst_QCheckBox::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QCheckBox::init()
+{
+ testWidget->setTristate( FALSE );
+ testWidget->setChecked( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+}
+
+void tst_QCheckBox::cleanup()
+{
+ disconnect(testWidget, SIGNAL(pressed()), this, SLOT(onPressed()));
+ disconnect(testWidget, SIGNAL(released()), this, SLOT(onReleased()));
+ disconnect(testWidget, SIGNAL(clicked()), this, SLOT(onClicked()));
+ disconnect(testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)));
+}
+
+void tst_QCheckBox::onClicked()
+{
+ click_count++;
+}
+
+void tst_QCheckBox::onPressed()
+{
+ press_count++;
+}
+
+void tst_QCheckBox::onReleased()
+{
+ release_count++;
+}
+
+void tst_QCheckBox::onToggled( bool /*on*/ )
+{
+ toggle_count++;
+}
+
+// ***************************************************
+
+void tst_QCheckBox::setChecked()
+{
+ testWidget->setChecked( TRUE );
+ QVERIFY( testWidget->isChecked() );
+ QVERIFY( testWidget->isChecked() );
+ QVERIFY( testWidget->checkState() == Qt::Checked );
+
+ testWidget->setChecked( FALSE );
+ QVERIFY( !testWidget->isChecked() );
+ QVERIFY( !testWidget->isChecked() );
+ QVERIFY( testWidget->checkState() == Qt::Unchecked );
+
+ testWidget->setChecked( FALSE );
+ QTest::keyClick( testWidget, ' ' );
+ QVERIFY( testWidget->isChecked() );
+
+ QTest::keyClick( testWidget, ' ' );
+ QVERIFY( !testWidget->isChecked() );
+}
+
+void tst_QCheckBox::setTriState()
+{
+ testWidget->setTristate( TRUE );
+ QVERIFY( testWidget->isTristate() );
+ QVERIFY( testWidget->checkState() == Qt::Unchecked );
+
+ testWidget->setCheckState(Qt::PartiallyChecked);
+ QVERIFY( testWidget->checkState() == Qt::PartiallyChecked );
+
+ testWidget->setChecked( TRUE );
+ QVERIFY( testWidget->isChecked() );
+ QVERIFY( testWidget->checkState() == Qt::Checked );
+
+ testWidget->setChecked( FALSE );
+ QVERIFY( !testWidget->isChecked() );
+ QVERIFY( testWidget->checkState() == Qt::Unchecked );
+
+ testWidget->setCheckState(Qt::PartiallyChecked);
+ QVERIFY( testWidget->checkState() == Qt::PartiallyChecked );
+
+ testWidget->setTristate( FALSE );
+ QVERIFY( !testWidget->isTristate() );
+
+ testWidget->setCheckState(Qt::PartiallyChecked);
+ QVERIFY( testWidget->checkState() == Qt::PartiallyChecked );
+
+ testWidget->setChecked( TRUE );
+ QVERIFY( testWidget->checkState() == Qt::Checked );
+
+ testWidget->setChecked( FALSE );
+ QVERIFY( testWidget->checkState() == Qt::Unchecked );
+}
+
+void tst_QCheckBox::setText_data()
+{
+ QTest::addColumn<QString>("s1");
+
+#ifdef Q_OS_WIN32
+ QTest::newRow( "win32_data0" ) << QString("This is a text");
+ QTest::newRow( "win32_data1" ) << QString("A");
+ QTest::newRow( "win32_data2" ) << QString("ABCDEFG ");
+ QTest::newRow( "win32_data3" ) << QString("Text\nwith a cr-lf");
+ QTest::newRow( "win32_data4" ) << QString("");
+#else
+ QTest::newRow( "data0" ) << QString("This is a text");
+ QTest::newRow( "data1" ) << QString("A");
+ QTest::newRow( "data2" ) << QString("ABCDEFG ");
+ QTest::newRow( "data3" ) << QString("Text\nwith a cr-lf");
+ QTest::newRow( "data4" ) << QString("");
+#endif
+}
+
+void tst_QCheckBox::setText()
+{
+ QFETCH( QString, s1 );
+ testWidget->setText( s1 );
+ QCOMPARE( testWidget->text(), s1 );
+}
+
+void tst_QCheckBox::setDown()
+{
+ testWidget->setDown( TRUE );
+ QVERIFY( testWidget->isDown() );
+
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isDown() );
+}
+
+void tst_QCheckBox::setAutoRepeat()
+{
+ // setAutoRepeat has no effect on toggle buttons
+ QVERIFY( testWidget->isCheckable() );
+}
+
+void tst_QCheckBox::toggle()
+{
+ bool cur_state;
+ cur_state = testWidget->isChecked();
+ testWidget->toggle();
+ QVERIFY( cur_state != testWidget->isChecked() );
+
+ cur_state = testWidget->isChecked();
+ testWidget->toggle();
+ QVERIFY( cur_state != testWidget->isChecked() );
+
+ cur_state = testWidget->isChecked();
+ testWidget->toggle();
+ QVERIFY( cur_state != testWidget->isChecked() );
+}
+
+void tst_QCheckBox::pressed()
+{
+ connect(testWidget, SIGNAL(pressed()), this, SLOT(onPressed()));
+ connect(testWidget, SIGNAL(released()), this, SLOT(onReleased()));
+ press_count = 0;
+ release_count = 0;
+ testWidget->setDown(FALSE);
+ QVERIFY( !testWidget->isChecked() );
+
+ QTest::keyPress( testWidget, Qt::Key_Space );
+ QTest::qWait(100);
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( !testWidget->isChecked() );
+
+ QTest::keyRelease( testWidget, Qt::Key_Space );
+ QTest::qWait(100);
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 1 );
+ QVERIFY( testWidget->isChecked() );
+}
+
+void tst_QCheckBox::toggled()
+{
+ connect(testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)));
+ click_count = 0;
+ toggle_count = 0;
+ testWidget->toggle();
+ QCOMPARE( toggle_count, (uint)1 );
+
+ testWidget->toggle();
+ QCOMPARE( toggle_count, (uint)2 );
+
+ testWidget->toggle();
+ QCOMPARE( toggle_count, (uint)3 );
+
+ QCOMPARE( click_count, (uint)0 );
+}
+
+void tst_QCheckBox::onStateChanged( int state )
+{
+ cur_state = state;
+}
+
+void tst_QCheckBox::stateChanged()
+{
+ QSignalSpy stateChangedSpy(testWidget, SIGNAL(stateChanged(int)));
+ connect(testWidget, SIGNAL(stateChanged(int)), this, SLOT(onStateChanged(int)));
+ cur_state = -1;
+ testWidget->setChecked( TRUE );
+ qApp->processEvents();
+ QCOMPARE( cur_state, (int)2 );
+
+ cur_state = -1;
+ testWidget->setChecked( FALSE );
+ qApp->processEvents();
+ QCOMPARE( cur_state, (int)0 );
+
+ cur_state = -1;
+ testWidget->setCheckState(Qt::PartiallyChecked);
+ qApp->processEvents();
+ QCOMPARE( cur_state, (int)1 );
+
+ QCOMPARE(stateChangedSpy.count(), 3);
+ testWidget->setCheckState(Qt::PartiallyChecked);
+ qApp->processEvents();
+ QCOMPARE(stateChangedSpy.count(), 3);
+}
+
+void tst_QCheckBox::isToggleButton()
+{
+ QVERIFY( testWidget->isCheckable() );
+}
+
+void tst_QCheckBox::foregroundRole()
+{
+ QVERIFY(testWidget->foregroundRole() == QPalette::WindowText);
+}
+
+void tst_QCheckBox::minimumSizeHint()
+{
+ QCheckBox box(tr("CheckBox's sizeHint is the same as it's minimumSizeHint"));
+ QCOMPARE(box.sizeHint(), box.minimumSizeHint());
+}
+
+QTEST_MAIN(tst_QCheckBox)
+#include "tst_qcheckbox.moc"
diff --git a/tests/auto/widgets/widgets/qcombobox/.gitignore b/tests/auto/widgets/widgets/qcombobox/.gitignore
new file mode 100644
index 0000000000..0db112206b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcombobox/.gitignore
@@ -0,0 +1 @@
+tst_qcombobox
diff --git a/tests/auto/widgets/widgets/qcombobox/qcombobox.pro b/tests/auto/widgets/widgets/qcombobox/qcombobox.pro
new file mode 100644
index 0000000000..7f5b57c237
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcombobox/qcombobox.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets widgets-private gui-private core-private
+SOURCES += tst_qcombobox.cpp
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
new file mode 100644
index 0000000000..cb4468f6f4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -0,0 +1,2579 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include "qcombobox.h"
+#include <private/qcombobox_p.h>
+
+#include <qfontcombobox.h>
+#include <qdesktopwidget.h>
+#include <qapplication.h>
+#include <qpushbutton.h>
+#include <qdialog.h>
+#include <qevent.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qheaderview.h>
+#include <qlistwidget.h>
+#include <qtreewidget.h>
+#include <qtablewidget.h>
+#include <qscrollbar.h>
+#include <qboxlayout.h>
+#ifdef Q_WS_MAC
+#include <qmacstyle_mac.h>
+#elif defined Q_WS_X11
+#include <private/qt_x11_p.h>
+#endif
+
+#include <qstandarditemmodel.h>
+#include <qstringlistmodel.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include <qdialog.h>
+#include <qstringlist.h>
+#include <qvalidator.h>
+#include <qcompleter.h>
+#ifndef QT_NO_STYLE_CLEANLOOKS
+#include <qcleanlooksstyle.h>
+#endif
+#include <qabstractitemview.h>
+#include <qstyleditemdelegate.h>
+#ifndef QT_NO_STYLE_WINDOWS
+#include <qwindowsstyle.h>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QComboBox : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QComboBox();
+ ~tst_QComboBox();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void ensureReturnIsIgnored();
+ void setEditable();
+ void setPalette();
+ void sizeAdjustPolicy();
+ void clear();
+ void insertPolicy_data();
+ void insertPolicy();
+ void virtualAutocompletion();
+ void autoCompletionCaseSensitivity();
+ void hide();
+ void currentIndex_data();
+ void currentIndex();
+ void insertItems_data();
+ void insertItems();
+ void insertItem_data();
+ void insertItem();
+ void insertOnCurrentIndex();
+ void textpixmapdata_data();
+ void textpixmapdata();
+ void editTextChanged();
+ void setModel();
+ void modelDeleted();
+ void setMaxCount();
+ void setCurrentIndex();
+ void convenienceViews();
+ void findText_data();
+ void findText();
+ void flaggedItems_data();
+ void flaggedItems();
+ void pixmapIcon();
+ void mouseWheel_data();
+ void mouseWheel();
+ void layoutDirection();
+ void itemListPosition();
+ void separatorItem_data();
+ void separatorItem();
+#ifndef QT_NO_STYLE_CLEANLOOKS
+ void task190351_layout();
+ void task191329_size();
+#endif
+ void task166349_setEditableOnReturn();
+ void task190205_setModelAdjustToContents();
+ void task248169_popupWithMinimalSize();
+ void task247863_keyBoardSelection();
+ void task220195_keyBoardSelection2();
+ void setModelColumn();
+ void noScrollbar_data();
+ void noScrollbar();
+ void setItemDelegate();
+ void task253944_itemDelegateIsReset();
+ void subControlRectsWithOffset_data();
+ void subControlRectsWithOffset();
+#ifndef QT_NO_STYLE_WINDOWS
+ void task260974_menuItemRectangleForComboBoxPopup();
+#endif
+ void removeItem();
+ void resetModel();
+ void keyBoardNavigationWithMouse();
+ void task_QTBUG_1071_changingFocusEmitsActivated();
+ void maxVisibleItems();
+ void task_QTBUG_10491_currentIndexAndModelColumn();
+
+protected slots:
+ void onEditTextChanged( const QString &newString );
+
+private:
+ QComboBox *testWidget;
+ QWidget *parent;
+ QPushButton* ok;
+ int editTextCount;
+ QString editText;
+};
+
+class MyAbstractItemDelegate : public QAbstractItemDelegate
+{
+public:
+ MyAbstractItemDelegate() : QAbstractItemDelegate() {};
+ void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
+ QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
+};
+
+class MyAbstractItemModel: public QAbstractItemModel
+{
+public:
+ MyAbstractItemModel() : QAbstractItemModel() {};
+ QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); }
+ QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
+ int rowCount(const QModelIndex &) const { return 0; }
+ int columnCount(const QModelIndex &) const { return 0; }
+ bool hasChildren(const QModelIndex &) const { return false; }
+ QVariant data(const QModelIndex &, int) const { return QVariant(); }
+ bool setData(const QModelIndex &, const QVariant &, int) { return false; }
+ bool insertRows(int, int, const QModelIndex &) { return false; }
+ bool insertColumns(int, int, const QModelIndex &) { return false; }
+ void setPersistent(const QModelIndex &, const QModelIndex &) {}
+ bool removeRows (int, int, const QModelIndex &) { return false; }
+ bool removeColumns(int, int, const QModelIndex &) { return false; }
+ void reset() {}
+};
+
+class MyAbstractItemView : public QAbstractItemView
+{
+public:
+ MyAbstractItemView() : QAbstractItemView() {}
+ QRect visualRect(const QModelIndex &) const { return QRect(); }
+ void scrollTo(const QModelIndex &, ScrollHint) {}
+ QModelIndex indexAt(const QPoint &) const { return QModelIndex(); }
+protected:
+ QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers) { return QModelIndex(); }
+ int horizontalOffset() const { return 0; }
+ int verticalOffset() const { return 0; }
+ bool isIndexHidden(const QModelIndex &) const { return false; }
+ void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) {}
+ QRegion visualRegionForSelection(const QItemSelection &) const { return QRegion(); }
+};
+
+// Testing get/set functions
+void tst_QComboBox::getSetCheck()
+{
+ QComboBox obj1;
+ // int QComboBox::maxVisibleItems()
+ // void QComboBox::setMaxVisibleItems(int)
+ obj1.setMaxVisibleItems(100);
+ QCOMPARE(100, obj1.maxVisibleItems());
+ obj1.setMaxVisibleItems(0);
+ QCOMPARE(obj1.maxVisibleItems(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxVisibleItems: "
+ "Invalid max visible items (-2147483648) must be >= 0");
+ obj1.setMaxVisibleItems(INT_MIN);
+ QCOMPARE(obj1.maxVisibleItems(), 0); // Cannot be set to something negative => old value
+ obj1.setMaxVisibleItems(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.maxVisibleItems());
+
+ // int QComboBox::maxCount()
+ // void QComboBox::setMaxCount(int)
+ obj1.setMaxCount(0);
+ QCOMPARE(0, obj1.maxCount());
+#ifndef QT_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QComboBox::setMaxCount: Invalid count (-2147483648) must be >= 0");
+ obj1.setMaxCount(INT_MIN);
+ QCOMPARE(0, obj1.maxCount()); // Setting a value below 0 makes no sense, and shouldn't be allowed
+#endif
+ obj1.setMaxCount(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.maxCount());
+
+ // bool QComboBox::autoCompletion()
+ // void QComboBox::setAutoCompletion(bool)
+ obj1.setAutoCompletion(false);
+ QCOMPARE(false, obj1.autoCompletion());
+ obj1.setAutoCompletion(true);
+ QCOMPARE(true, obj1.autoCompletion());
+
+ // bool QComboBox::duplicatesEnabled()
+ // void QComboBox::setDuplicatesEnabled(bool)
+ obj1.setDuplicatesEnabled(false);
+ QCOMPARE(false, obj1.duplicatesEnabled());
+ obj1.setDuplicatesEnabled(true);
+ QCOMPARE(true, obj1.duplicatesEnabled());
+
+ // InsertPolicy QComboBox::insertPolicy()
+ // void QComboBox::setInsertPolicy(InsertPolicy)
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::NoInsert));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::NoInsert), obj1.insertPolicy());
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtTop));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtTop), obj1.insertPolicy());
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtCurrent));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtCurrent), obj1.insertPolicy());
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAtBottom));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAtBottom), obj1.insertPolicy());
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAfterCurrent));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAfterCurrent), obj1.insertPolicy());
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertBeforeCurrent));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertBeforeCurrent), obj1.insertPolicy());
+ obj1.setInsertPolicy(QComboBox::InsertPolicy(QComboBox::InsertAlphabetically));
+ QCOMPARE(QComboBox::InsertPolicy(QComboBox::InsertAlphabetically), obj1.insertPolicy());
+
+ // SizeAdjustPolicy QComboBox::sizeAdjustPolicy()
+ // void QComboBox::setSizeAdjustPolicy(SizeAdjustPolicy)
+ obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents));
+ QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContents), obj1.sizeAdjustPolicy());
+ obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow));
+ QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow), obj1.sizeAdjustPolicy());
+ obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength));
+ QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength), obj1.sizeAdjustPolicy());
+ obj1.setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon));
+ QCOMPARE(QComboBox::SizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon), obj1.sizeAdjustPolicy());
+
+ // int QComboBox::minimumContentsLength()
+ // void QComboBox::setMinimumContentsLength(int)
+ obj1.setMinimumContentsLength(0);
+ QCOMPARE(0, obj1.minimumContentsLength());
+ obj1.setMinimumContentsLength(100);
+ QCOMPARE(100, obj1.minimumContentsLength());
+ obj1.setMinimumContentsLength(INT_MIN);
+ QCOMPARE(100, obj1.minimumContentsLength()); // Cannot be set to something negative => old value
+ obj1.setMinimumContentsLength(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.minimumContentsLength());
+
+ // QLineEdit * QComboBox::lineEdit()
+ // void QComboBox::setLineEdit(QLineEdit *)
+ QLineEdit *var8 = new QLineEdit(0);
+ obj1.setLineEdit(var8);
+ QCOMPARE(var8, obj1.lineEdit());
+ QTest::ignoreMessage(QtWarningMsg, "QComboBox::setLineEdit: cannot set a 0 line edit");
+ obj1.setLineEdit((QLineEdit *)0);
+ QCOMPARE(var8, obj1.lineEdit());
+ // delete var8; // No delete, since QComboBox takes ownership
+
+ // const QValidator * QComboBox::validator()
+ // void QComboBox::setValidator(const QValidator *)
+ QIntValidator *var9 = new QIntValidator(0);
+ obj1.setValidator(var9);
+ QCOMPARE(obj1.validator(), (const QValidator *)var9);
+ obj1.setValidator((QValidator *)0);
+ QCOMPARE(obj1.validator(), (const QValidator *)0);
+ delete var9;
+
+ // QAbstractItemDelegate * QComboBox::itemDelegate()
+ // void QComboBox::setItemDelegate(QAbstractItemDelegate *)
+ MyAbstractItemDelegate *var10 = new MyAbstractItemDelegate;
+ obj1.setItemDelegate(var10);
+ QCOMPARE(obj1.itemDelegate(), (QAbstractItemDelegate *)var10);
+ QTest::ignoreMessage(QtWarningMsg, "QComboBox::setItemDelegate: cannot set a 0 delegate");
+ obj1.setItemDelegate((QAbstractItemDelegate *)0);
+ QCOMPARE(obj1.itemDelegate(), (QAbstractItemDelegate *)var10);
+ // delete var10; // No delete, since QComboBox takes ownership
+
+ // QAbstractItemModel * QComboBox::model()
+ // void QComboBox::setModel(QAbstractItemModel *)
+ MyAbstractItemModel *var11 = new MyAbstractItemModel;
+ obj1.setModel(var11);
+ QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
+ QTest::ignoreMessage(QtWarningMsg, "QComboBox::setModel: cannot set a 0 model");
+ obj1.setModel((QAbstractItemModel *)0);
+ QCOMPARE(obj1.model(), (QAbstractItemModel *)var11);
+ delete var11;
+ obj1.model();
+
+ // int QComboBox::modelColumn()
+ // void QComboBox::setModelColumn(int)
+ obj1.setModelColumn(0);
+ QCOMPARE(0, obj1.modelColumn());
+ obj1.setModelColumn(INT_MIN);
+// QCOMPARE(0, obj1.modelColumn()); // Cannot be set to something negative => column 0
+ obj1.setModelColumn(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.modelColumn());
+ obj1.setModelColumn(0); // back to normal
+
+ // QAbstractItemView * QComboBox::view()
+ // void QComboBox::setView(QAbstractItemView *)
+ MyAbstractItemView *var13 = new MyAbstractItemView;
+ obj1.setView(var13);
+ QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
+ QTest::ignoreMessage(QtWarningMsg, "QComboBox::setView: cannot set a 0 view");
+ obj1.setView((QAbstractItemView *)0);
+ QCOMPARE(obj1.view(), (QAbstractItemView *)var13);
+ delete var13;
+
+ // int QComboBox::currentIndex()
+ // void QComboBox::setCurrentIndex(int)
+ obj1.setEditable(false);
+ obj1.setCurrentIndex(0);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.addItems(QStringList() << "1" << "2" << "3" << "4" << "5");
+ obj1.setCurrentIndex(0);
+ QCOMPARE(0, obj1.currentIndex()); // Valid
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
+ obj1.setCurrentIndex(4);
+ QCOMPARE(4, obj1.currentIndex()); // Valid
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(-1, obj1.currentIndex()); // Invalid => -1
+}
+
+typedef QList<QVariant> VariantList;
+typedef QList<QIcon> IconList;
+
+Q_DECLARE_METATYPE(VariantList)
+Q_DECLARE_METATYPE(IconList)
+Q_DECLARE_METATYPE(QComboBox::InsertPolicy)
+
+tst_QComboBox::tst_QComboBox()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ parent = 0;
+}
+
+tst_QComboBox::~tst_QComboBox()
+{
+}
+
+
+void tst_QComboBox::initTestCase()
+{
+ // Create the test class
+ parent = new QWidget(0, Qt::Window);
+ parent->setObjectName("parent");
+ parent->resize(400, 400);
+ testWidget = new QComboBox(parent);
+ testWidget->setObjectName("testObject");
+ testWidget->setGeometry(0, 0, 100, 100);
+ editTextCount = 0;
+ editText.clear();
+ connect(testWidget, SIGNAL(editTextChanged(const QString&)),
+ this, SLOT(onEditTextChanged(const QString&)));
+ parent->show();
+}
+
+void tst_QComboBox::cleanupTestCase()
+{
+ delete parent;
+ parent = 0;
+}
+
+
+void tst_QComboBox::init()
+{
+ // all tests starts with a clean non-editable combobox
+ testWidget->setEditable(false);
+ testWidget->clear();
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QComboBox::cleanup()
+{
+ //nothing
+}
+
+
+void tst_QComboBox::setEditable()
+{
+ // make sure we have no lineedit
+ QVERIFY(!testWidget->lineEdit());
+ // test setEditable(true)
+ testWidget->setEditable(true);
+ QVERIFY(testWidget->lineEdit());
+ testWidget->addItem("foo");
+ QCOMPARE(testWidget->lineEdit()->text(), QString("foo"));
+ // test setEditable(false)
+
+ QLineEdit *lineEdit = testWidget->lineEdit();
+ // line edit is visible when combobox is editable
+ QVERIFY(lineEdit->isVisible());
+ testWidget->setEditable(false);
+ QVERIFY(!testWidget->lineEdit());
+ // line edit should have been explicitly hidden when editable was turned off
+ QVERIFY(!lineEdit->isVisible());
+}
+
+
+void tst_QComboBox::setPalette()
+{
+#ifdef Q_WS_MAC
+ if (qobject_cast<QMacStyle *>(testWidget->style())) {
+ QSKIP("This test doesn't make sense for pixmap-based styles", SkipAll);
+ }
+#endif
+ QPalette pal = testWidget->palette();
+ pal.setColor(QPalette::Base, Qt::red);
+ testWidget->setPalette(pal);
+ testWidget->setEditable(!testWidget->isEditable());
+
+ pal.setColor(QPalette::Base, Qt::blue);
+ testWidget->setPalette(pal);
+
+ const QObjectList comboChildren = testWidget->children();
+ for (int i = 0; i < comboChildren.size(); ++i) {
+ QObject *o = comboChildren.at(i);
+ if (o->isWidgetType()) {
+ QVERIFY(((QWidget*)o)->palette() == pal);
+ }
+ }
+
+ testWidget->setEditable(true);
+ pal.setColor(QPalette::Base, Qt::red);
+ //Setting it on the lineedit should be separate form the combo
+ testWidget->lineEdit()->setPalette(pal);
+ QVERIFY(testWidget->palette() != pal);
+ QVERIFY(testWidget->lineEdit()->palette() == pal);
+ pal.setColor(QPalette::Base, Qt::green);
+ //Setting it on the combo directly should override lineedit
+ testWidget->setPalette(pal);
+ QVERIFY(testWidget->palette() == pal);
+ QVERIFY(testWidget->lineEdit()->palette() == pal);
+}
+
+void tst_QComboBox::sizeAdjustPolicy()
+{
+ // test that adding new items will not change the sizehint for AdjustToContentsOnFirstShow
+ QVERIFY(!testWidget->count());
+ QVERIFY(testWidget->sizeAdjustPolicy() == QComboBox::AdjustToContentsOnFirstShow);
+ QVERIFY(testWidget->isVisible());
+ QSize firstShow = testWidget->sizeHint();
+ testWidget->addItem("normal item");
+ QCOMPARE(testWidget->sizeHint(), firstShow);
+
+ // check that with minimumContentsLength/AdjustToMinimumContentsLength sizehint changes
+ testWidget->setMinimumContentsLength(30);
+ QCOMPARE(testWidget->sizeHint(), firstShow);
+ testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
+ QSize minimumContentsLength = testWidget->sizeHint();
+ QVERIFY(minimumContentsLength.width() > firstShow.width());
+ testWidget->setMinimumContentsLength(60);
+ QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
+
+ // check that with minimumContentsLength/AdjustToMinimumContentsLengthWithIcon sizehint changes
+ testWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
+ testWidget->setMinimumContentsLength(30);
+ minimumContentsLength = testWidget->sizeHint();
+ QVERIFY(minimumContentsLength.width() > firstShow.width());
+ testWidget->setMinimumContentsLength(60);
+ QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
+ minimumContentsLength = testWidget->sizeHint();
+ testWidget->setIconSize(QSize(128,128));
+ QVERIFY(minimumContentsLength.width() < testWidget->sizeHint().width());
+
+ // check AdjustToContents changes with content
+ testWidget->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ QSize content = testWidget->sizeHint();
+ testWidget->addItem("small");
+ QCOMPARE(testWidget->sizeHint(), content);
+ testWidget->addItem("looooooooooooooooooooooong item");
+ // minimumContentsLength() > sizeof("looooooooooooooooooooooong item"), so the sizeHint()
+ // stays the same
+ QCOMPARE(testWidget->sizeHint(), content);
+ // over 60 characters (cf. setMinimumContentsLength() call above)
+ testWidget->addItem("loooooooooooooooooooooooooooooooooooooooooooooo"
+ "ooooooooooooooooooooooooooooooooooooooooooooooo"
+ "ooooooooooooooooooooooooooooong item");
+ QVERIFY(testWidget->sizeHint().width() > content.width());
+
+ // check AdjustToContents also shrinks when item changes
+ content = testWidget->sizeHint();
+ for (int i=0; i<testWidget->count(); ++i)
+ testWidget->setItemText(i, "XXXXXXXXXX");
+ QVERIFY(testWidget->sizeHint().width() < content.width());
+
+ // check AdjustToContents shrinks when items are removed
+ content = testWidget->sizeHint();
+ while (testWidget->count())
+ testWidget->removeItem(0);
+ QCOMPARE(testWidget->sizeHint(), content);
+ testWidget->setMinimumContentsLength(0);
+ QVERIFY(testWidget->sizeHint().width() < content.width());
+}
+
+void tst_QComboBox::clear()
+{
+ // first non editable combobox
+ testWidget->addItem("foo");
+ testWidget->addItem("bar");
+ QVERIFY(testWidget->count() > 0);
+ QCOMPARE(testWidget->currentIndex(), 0);
+
+ testWidget->clear();
+ QCOMPARE(testWidget->count(), 0);
+ QCOMPARE(testWidget->currentIndex(), -1);
+ QVERIFY(testWidget->currentText().isEmpty());
+
+ // then editable combobox
+ testWidget->clear();
+ testWidget->setEditable(true);
+ testWidget->addItem("foo");
+ testWidget->addItem("bar");
+ QVERIFY(testWidget->count() > 0);
+ QCOMPARE(testWidget->currentIndex(), 0);
+ QVERIFY(testWidget->lineEdit());
+ QVERIFY(!testWidget->lineEdit()->text().isEmpty());
+ testWidget->clear();
+ QCOMPARE(testWidget->count(), 0);
+ QCOMPARE(testWidget->currentIndex(), -1);
+ QVERIFY(testWidget->currentText().isEmpty());
+ QVERIFY(testWidget->lineEdit()->text().isEmpty());
+}
+
+void tst_QComboBox::insertPolicy_data()
+{
+ QTest::addColumn<QStringList>("initialEntries");
+ QTest::addColumn<QComboBox::InsertPolicy>("insertPolicy");
+ QTest::addColumn<int>("currentIndex");
+ QTest::addColumn<QString>("userInput");
+ QTest::addColumn<QStringList>("result");
+
+ /* Each insertPolicy should test at least:
+ no initial entries
+ one initial entry
+ five initial entries, current is first item
+ five initial entries, current is third item
+ five initial entries, current is last item
+ */
+
+ /* QComboBox::NoInsert - the string will not be inserted into the combobox.
+ QComboBox::InsertAtTop - insert the string as the first item in the combobox.
+ QComboBox::InsertAtCurrent - replace the previously selected item with the string the user has entered.
+ QComboBox::InsertAtBottom - insert the string as the last item in the combobox.
+ QComboBox::InsertAfterCurrent - insert the string after the previously selected item.
+ QComboBox::InsertBeforeCurrent - insert the string before the previously selected item.
+ QComboBox::InsertAlphabetically - insert the string at the alphabetic position.
+ */
+ QStringList initial;
+ QStringList oneEntry("One");
+ QStringList fiveEntries;
+ fiveEntries << "One" << "Two" << "Three" << "Four" << "Five";
+ QString input("insert");
+
+ {
+ QTest::newRow("NoInsert-NoInitial") << initial << QComboBox::NoInsert << 0 << input << initial;
+ QTest::newRow("NoInsert-OneInitial") << oneEntry << QComboBox::NoInsert << 0 << input << oneEntry;
+ QTest::newRow("NoInsert-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::NoInsert << 0 << input << fiveEntries;
+ QTest::newRow("NoInsert-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::NoInsert << 2 << input << fiveEntries;
+ QTest::newRow("NoInsert-FiveInitial-LastCurrent") << fiveEntries << QComboBox::NoInsert << 4 << input << fiveEntries;
+ }
+
+ {
+ QStringList initialAtTop("insert");
+ QStringList oneAtTop;
+ oneAtTop << "insert" << "One";
+ QStringList fiveAtTop;
+ fiveAtTop << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
+
+ QTest::newRow("AtTop-NoInitial") << initial << QComboBox::InsertAtTop << 0 << input << initialAtTop;
+ QTest::newRow("AtTop-OneInitial") << oneEntry << QComboBox::InsertAtTop << 0 << input << oneAtTop;
+ QTest::newRow("AtTop-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtTop << 0 << input << fiveAtTop;
+ QTest::newRow("AtTop-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtTop << 2 << input << fiveAtTop;
+ QTest::newRow("AtTop-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtTop << 4 << input << fiveAtTop;
+ }
+
+ {
+ QStringList initialAtCurrent("insert");
+ QStringList oneAtCurrent("insert");
+ QStringList fiveAtCurrentFirst;
+ fiveAtCurrentFirst << "insert" << "Two" << "Three" << "Four" << "Five";
+ QStringList fiveAtCurrentThird;
+ fiveAtCurrentThird << "One" << "Two" << "insert" << "Four" << "Five";
+ QStringList fiveAtCurrentLast;
+ fiveAtCurrentLast << "One" << "Two" << "Three" << "Four" << "insert";
+
+ QTest::newRow("AtCurrent-NoInitial") << initial << QComboBox::InsertAtCurrent << 0 << input << initialAtCurrent;
+ QTest::newRow("AtCurrent-OneInitial") << oneEntry << QComboBox::InsertAtCurrent << 0 << input << oneAtCurrent;
+ QTest::newRow("AtCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 0 << input << fiveAtCurrentFirst;
+ QTest::newRow("AtCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 2 << input << fiveAtCurrentThird;
+ QTest::newRow("AtCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtCurrent << 4 << input << fiveAtCurrentLast;
+ }
+
+ {
+ QStringList initialAtBottom("insert");
+ QStringList oneAtBottom;
+ oneAtBottom << "One" << "insert";
+ QStringList fiveAtBottom;
+ fiveAtBottom << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
+
+ QTest::newRow("AtBottom-NoInitial") << initial << QComboBox::InsertAtBottom << 0 << input << initialAtBottom;
+ QTest::newRow("AtBottom-OneInitial") << oneEntry << QComboBox::InsertAtBottom << 0 << input << oneAtBottom;
+ QTest::newRow("AtBottom-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAtBottom << 0 << input << fiveAtBottom;
+ QTest::newRow("AtBottom-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAtBottom << 2 << input << fiveAtBottom;
+ QTest::newRow("AtBottom-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAtBottom << 4 << input << fiveAtBottom;
+ }
+
+ {
+ QStringList initialAfterCurrent("insert");
+ QStringList oneAfterCurrent;
+ oneAfterCurrent << "One" << "insert";
+ QStringList fiveAfterCurrentFirst;
+ fiveAfterCurrentFirst << "One" << "insert" << "Two" << "Three" << "Four" << "Five";
+ QStringList fiveAfterCurrentThird;
+ fiveAfterCurrentThird << "One" << "Two" << "Three" << "insert" << "Four" << "Five";
+ QStringList fiveAfterCurrentLast;
+ fiveAfterCurrentLast << "One" << "Two" << "Three" << "Four" << "Five" << "insert";
+
+ QTest::newRow("AfterCurrent-NoInitial") << initial << QComboBox::InsertAfterCurrent << 0 << input << initialAfterCurrent;
+ QTest::newRow("AfterCurrent-OneInitial") << oneEntry << QComboBox::InsertAfterCurrent << 0 << input << oneAfterCurrent;
+ QTest::newRow("AfterCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 0 << input << fiveAfterCurrentFirst;
+ QTest::newRow("AfterCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 2 << input << fiveAfterCurrentThird;
+ QTest::newRow("AfterCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAfterCurrent << 4 << input << fiveAfterCurrentLast;
+ }
+
+ {
+ QStringList initialBeforeCurrent("insert");
+ QStringList oneBeforeCurrent;
+ oneBeforeCurrent << "insert" << "One";
+ QStringList fiveBeforeCurrentFirst;
+ fiveBeforeCurrentFirst << "insert" << "One" << "Two" << "Three" << "Four" << "Five";
+ QStringList fiveBeforeCurrentThird;
+ fiveBeforeCurrentThird << "One" << "Two" << "insert" << "Three" << "Four" << "Five";
+ QStringList fiveBeforeCurrentLast;
+ fiveBeforeCurrentLast << "One" << "Two" << "Three" << "Four" << "insert" << "Five";
+
+ QTest::newRow("BeforeCurrent-NoInitial") << initial << QComboBox::InsertBeforeCurrent << 0 << input << initialBeforeCurrent;
+ QTest::newRow("BeforeCurrent-OneInitial") << oneEntry << QComboBox::InsertBeforeCurrent << 0 << input << oneBeforeCurrent;
+ QTest::newRow("BeforeCurrent-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 0 << input << fiveBeforeCurrentFirst;
+ QTest::newRow("BeforeCurrent-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 2 << input << fiveBeforeCurrentThird;
+ QTest::newRow("BeforeCurrent-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertBeforeCurrent << 4 << input << fiveBeforeCurrentLast;
+ }
+
+ {
+ oneEntry.clear();
+ oneEntry << "foobar";
+ fiveEntries.clear();
+ fiveEntries << "bar" << "foo" << "initial" << "Item" << "stamp";
+
+ QStringList initialAlphabetically("insert");
+ QStringList oneAlphabetically;
+ oneAlphabetically << "foobar" << "insert";
+ QStringList fiveAlphabetically;
+ fiveAlphabetically << "bar" << "foo" << "initial" << "insert" << "Item" << "stamp";
+
+ QTest::newRow("Alphabetically-NoInitial") << initial << QComboBox::InsertAlphabetically << 0 << input << initialAlphabetically;
+ QTest::newRow("Alphabetically-OneInitial") << oneEntry << QComboBox::InsertAlphabetically << 0 << input << oneAlphabetically;
+ QTest::newRow("Alphabetically-FiveInitial-FirstCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 0 << input << fiveAlphabetically;
+ QTest::newRow("Alphabetically-FiveInitial-ThirdCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 2 << input << fiveAlphabetically;
+ QTest::newRow("Alphabetically-FiveInitial-LastCurrent") << fiveEntries << QComboBox::InsertAlphabetically << 4 << input << fiveAlphabetically;
+ }
+}
+
+void tst_QComboBox::insertPolicy()
+{
+ QFETCH(QStringList, initialEntries);
+ QFETCH(QComboBox::InsertPolicy, insertPolicy);
+ QFETCH(int, currentIndex);
+ QFETCH(QString, userInput);
+ QFETCH(QStringList, result);
+
+ testWidget->clear();
+ testWidget->setInsertPolicy(insertPolicy);
+ testWidget->addItems(initialEntries);
+ testWidget->setEditable(true);
+ if (initialEntries.count() > 0)
+ testWidget->setCurrentIndex(currentIndex);
+
+ // clear
+ QTest::mouseDClick(testWidget->lineEdit(), Qt::LeftButton);
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Delete);
+
+ QTest::keyClicks(testWidget->lineEdit(), userInput);
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Return);
+
+ // First check that there is the right number of entries, or
+ // we may unwittingly pass
+ QVERIFY((int)result.count() == testWidget->count());
+
+ // No need to compare if there are no strings to compare
+ if (result.count() > 0) {
+ for (int i=0; i<testWidget->count(); ++i) {
+ QCOMPARE(testWidget->itemText(i), result.at(i));
+ }
+ }
+}
+
+// Apps running with valgrind are not fast enough.
+void tst_QComboBox::virtualAutocompletion()
+{
+ testWidget->clear();
+ testWidget->setAutoCompletion(true);
+ testWidget->addItem("Foo");
+ testWidget->addItem("Bar");
+ testWidget->addItem("Boat");
+ testWidget->addItem("Boost");
+ testWidget->clearEditText();
+
+ // We need to set the keyboard input interval to a higher value
+ // as the processEvent() call takes too much time, so it restarts
+ // the keyboard search then
+#if defined(QT_ARCH_ARM) || defined(QT_ARCH_MIPS)
+ int oldInterval = QApplication::keyboardInputInterval();
+ QApplication::setKeyboardInputInterval(1500);
+#endif
+
+ // NOTE:
+ // Cannot use keyClick for this test, as it simulates keyclicks too well
+ // The virtual keyboards we're trying to catch here, do not perform that
+ // well, and send a keypress & keyrelease right after each other.
+ // This provokes the actual error, as there's no events in between to do
+ // the text completion.
+ QKeyEvent kp1(QEvent::KeyPress, Qt::Key_B, 0, "b");
+ QKeyEvent kr1(QEvent::KeyRelease, Qt::Key_B, 0, "b");
+ QApplication::sendEvent(testWidget, &kp1);
+ QApplication::sendEvent(testWidget, &kr1);
+
+ qApp->processEvents(); // Process events to trigger autocompletion
+ QTRY_VERIFY(testWidget->currentIndex() == 1);
+
+ QKeyEvent kp2(QEvent::KeyPress, Qt::Key_O, 0, "o");
+ QKeyEvent kr2(QEvent::KeyRelease, Qt::Key_O, 0, "o");
+
+ QApplication::sendEvent(testWidget, &kp2);
+ QApplication::sendEvent(testWidget, &kr2);
+
+ qApp->processEvents(); // Process events to trigger autocompletion
+ QTRY_COMPARE(testWidget->currentIndex(), 2);
+
+ QApplication::sendEvent(testWidget, &kp2);
+ QApplication::sendEvent(testWidget, &kr2);
+ qApp->processEvents(); // Process events to trigger autocompletion
+ QTRY_COMPARE(testWidget->currentIndex(), 3);
+#if defined(QT_ARCH_ARM) || defined(QT_ARCH_MIPS)
+ QApplication::setKeyboardInputInterval(oldInterval);
+#endif
+}
+
+void tst_QComboBox::autoCompletionCaseSensitivity()
+{
+ //we have put the focus because the completer
+ //is only used when the widget actually has the focus
+ testWidget->setFocus();
+ qApp->setActiveWindow(testWidget);
+ QTRY_COMPARE(qApp->focusWidget(), (QWidget *)testWidget);
+
+ testWidget->clear();
+ testWidget->setAutoCompletion(true);
+ testWidget->addItem("Cow");
+ testWidget->addItem("irrelevant1");
+ testWidget->addItem("aww");
+ testWidget->addItem("A*");
+ testWidget->addItem("irrelevant2");
+ testWidget->addItem("aBCDEF");
+ testWidget->addItem("irrelevant3");
+ testWidget->addItem("abcdef");
+ testWidget->addItem("abCdef");
+ testWidget->setEditable(true);
+
+ // case insensitive
+ testWidget->clearEditText();
+ QSignalSpy spyReturn(testWidget, SIGNAL(activated(int)));
+ testWidget->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
+ QVERIFY(testWidget->autoCompletionCaseSensitivity() == Qt::CaseInsensitive);
+
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
+ qApp->processEvents();
+ QCOMPARE(testWidget->currentText(), QString("aww"));
+ QCOMPARE(spyReturn.count(), 0);
+
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
+ qApp->processEvents();
+ // autocompletions preserve userkey-case from 4.2
+ QCOMPARE(testWidget->currentText(), QString("abCDEF"));
+ QCOMPARE(spyReturn.count(), 0);
+
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
+ qApp->processEvents();
+ QCOMPARE(testWidget->currentText(), QString("aBCDEF")); // case restored to item's case
+ QCOMPARE(spyReturn.count(), 1);
+
+ testWidget->clearEditText();
+ QTest::keyClick(testWidget->lineEdit(), 'c');
+ QCOMPARE(testWidget->currentText(), QString("cow"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
+ QCOMPARE(testWidget->currentText(), QString("Cow")); // case restored to item's case
+
+ testWidget->clearEditText();
+ QTest::keyClick(testWidget->lineEdit(), 'a');
+ QTest::keyClick(testWidget->lineEdit(), '*');
+ QCOMPARE(testWidget->currentText(), QString("a*"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
+ QCOMPARE(testWidget->currentText(), QString("A*"));
+
+ // case sensitive
+ testWidget->clearEditText();
+ testWidget->setAutoCompletionCaseSensitivity(Qt::CaseSensitive);
+ QVERIFY(testWidget->autoCompletionCaseSensitivity() == Qt::CaseSensitive);
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
+ qApp->processEvents();
+ QCOMPARE(testWidget->currentText(), QString("aww"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_B);
+ qApp->processEvents();
+ QCOMPARE(testWidget->currentText(), QString("abcdef"));
+
+ testWidget->setCurrentIndex(0); // to reset the completion's "start"
+ testWidget->clearEditText();
+ QTest::keyClick(testWidget->lineEdit(), 'a');
+ QTest::keyClick(testWidget->lineEdit(), 'b');
+ QCOMPARE(testWidget->currentText(), QString("abcdef"));
+ QTest::keyClick(testWidget->lineEdit(), 'C');
+ qApp->processEvents();
+ QCOMPARE(testWidget->currentText(), QString("abCdef"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
+ qApp->processEvents();
+ QCOMPARE(testWidget->currentText(), QString("abCdef")); // case restored to item's case
+
+ testWidget->clearEditText();
+ QTest::keyClick(testWidget->lineEdit(), 'c');
+ QCOMPARE(testWidget->currentText(), QString("c"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Backspace);
+ QTest::keyClick(testWidget->lineEdit(), 'C');
+ QCOMPARE(testWidget->currentText(), QString("Cow"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
+ QCOMPARE(testWidget->currentText(), QString("Cow"));
+
+ testWidget->clearEditText();
+ QTest::keyClick(testWidget->lineEdit(), 'a');
+ QTest::keyClick(testWidget->lineEdit(), '*');
+ QCOMPARE(testWidget->currentText(), QString("a*"));
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter);
+ QCOMPARE(testWidget->currentText(), QString("a*")); // A* not matched
+}
+
+void tst_QComboBox::hide()
+{
+ testWidget->addItem("foo");
+ testWidget->showPopup();
+ //allow combobox effect to complete
+ QTRY_VERIFY(testWidget->view());
+ QTRY_VERIFY(testWidget->view()->isVisible());
+ testWidget->hidePopup();
+ //allow combobox effect to complete
+ QTRY_VERIFY(!testWidget->view()->isVisible());
+ testWidget->hide();
+ QVERIFY(!testWidget->isVisible());
+}
+
+
+
+void tst_QComboBox::currentIndex_data()
+{
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("setCurrentIndex");
+ QTest::addColumn<int>("removeIndex");
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<QString>("insertText");
+ QTest::addColumn<int>("expectedCurrentIndex");
+ QTest::addColumn<QString>("expectedCurrentText");
+ QTest::addColumn<int>("expectedSignalCount");
+
+ QStringList initialItems;
+ int setCurrentIndex;
+ int removeIndex;
+ int insertIndex;
+ QString insertText;
+ int expectedCurrentIndex;
+ QString expectedCurrentText;
+ int expectedSignalCount;
+
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar";
+ setCurrentIndex = -2;
+ removeIndex = -1;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = 0;
+ expectedCurrentText = "foo";
+ expectedSignalCount = 1;
+ QTest::newRow("first added item is set to current if there is no current")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar";
+ setCurrentIndex = 1;
+ removeIndex = -1;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = 1;
+ expectedCurrentText = "bar";
+ expectedSignalCount = 2;
+ QTest::newRow("check that setting the index works")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar";
+ setCurrentIndex = -1; // will invalidate the currentIndex
+ removeIndex = -1;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = -1;
+ expectedCurrentText = "";
+ expectedSignalCount = 2;
+ QTest::newRow("check that isetting the index to -1 works")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo";
+ setCurrentIndex = 0;
+ removeIndex = 0;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = -1;
+ expectedCurrentText = "";
+ expectedSignalCount = 2;
+ QTest::newRow("check that current index is invalid when removing the only item")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar";
+ setCurrentIndex = 1;
+ removeIndex = 0;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = 0;
+ expectedCurrentText = "bar";
+ expectedSignalCount = 3;
+ QTest::newRow("check that the current index follows the item when removing an item above")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar" << "baz";
+ setCurrentIndex = 1;
+ removeIndex = 1;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = 1;
+ expectedCurrentText = "baz";
+ expectedSignalCount = 3;
+ QTest::newRow("check that the current index uses the next item if current is removed")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar" << "baz";
+ setCurrentIndex = 2;
+ removeIndex = 2;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = 1;
+ expectedCurrentText = "bar";
+ expectedSignalCount = 3;
+ QTest::newRow("check that the current index is moved to the one before if current is removed")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar" << "baz";
+ setCurrentIndex = 1;
+ removeIndex = 2;
+ insertIndex = -1;
+ insertText = "";
+ expectedCurrentIndex = 1;
+ expectedCurrentText = "bar";
+ expectedSignalCount = 2;
+ QTest::newRow("check that the current index is unchanged if you remove an item after")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo" << "bar";
+ setCurrentIndex = 1;
+ removeIndex = -1;
+ insertIndex = 0;
+ insertText = "baz";
+ expectedCurrentIndex = 2;
+ expectedCurrentText = "bar";
+ expectedSignalCount = 3;
+ QTest::newRow("check that the current index follows the item if you insert before current")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo";
+ setCurrentIndex = 0;
+ removeIndex = -1;
+ insertIndex = 0;
+ insertText = "bar";
+ expectedCurrentIndex = 1;
+ expectedCurrentText = "foo";
+ expectedSignalCount = 2;
+ QTest::newRow("check that the current index follows the item if you insert on the current")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+ {
+ initialItems.clear();
+ initialItems << "foo";
+ setCurrentIndex = 0;
+ removeIndex = -1;
+ insertIndex = 1;
+ insertText = "bar";
+ expectedCurrentIndex = 0;
+ expectedCurrentText = "foo";
+ expectedSignalCount = 1;
+ QTest::newRow("check that the current index stays the same if you insert after the current")
+ << initialItems << setCurrentIndex << removeIndex
+ << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText
+ << expectedSignalCount;
+ }
+}
+
+void tst_QComboBox::currentIndex()
+{
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, setCurrentIndex);
+ QFETCH(int, removeIndex);
+ QFETCH(int, insertIndex);
+ QFETCH(QString, insertText);
+ QFETCH(int, expectedCurrentIndex);
+ QFETCH(QString, expectedCurrentText);
+ QFETCH(int, expectedSignalCount);
+
+ // test both editable/non-editable combobox
+ for (int edit = 0; edit < 2; ++edit) {
+ testWidget->clear();
+ testWidget->setEditable(edit ? true : false);
+ if (edit)
+ QVERIFY(testWidget->lineEdit());
+
+ // verify it is empty, has no current index and no current text
+ QCOMPARE(testWidget->count(), 0);
+ QCOMPARE(testWidget->currentIndex(), -1);
+ QVERIFY(testWidget->currentText().isEmpty());
+
+ // spy on currentIndexChanged
+ QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int)));
+ QSignalSpy indexChangedString(testWidget, SIGNAL(currentIndexChanged(const QString&)));
+
+ // stuff items into it
+ foreach(QString text, initialItems) {
+ testWidget->addItem(text);
+ }
+ QCOMPARE(testWidget->count(), initialItems.count());
+
+ // set current index, remove and/or insert
+ if (setCurrentIndex >= -1) {
+ testWidget->setCurrentIndex(setCurrentIndex);
+ QCOMPARE(testWidget->currentIndex(), setCurrentIndex);
+ }
+
+ if (removeIndex >= 0)
+ testWidget->removeItem(removeIndex);
+ if (insertIndex >= 0)
+ testWidget->insertItem(insertIndex, insertText);
+
+ // compare with expected index and text
+ QCOMPARE(testWidget->currentIndex(), expectedCurrentIndex);
+ QCOMPARE(testWidget->currentText(), expectedCurrentText);
+
+ // check that signal count is correct
+ QCOMPARE(indexChangedInt.count(), expectedSignalCount);
+ QCOMPARE(indexChangedString.count(), expectedSignalCount);
+
+ // compare with last sent signal values
+ if (indexChangedInt.count())
+ QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(),
+ testWidget->currentIndex());
+ if (indexChangedString.count())
+ QCOMPARE(indexChangedString.at(indexChangedString.count() - 1).at(0).toString(),
+ testWidget->currentText());
+
+ if (edit) {
+ testWidget->setCurrentIndex(-1);
+ testWidget->setInsertPolicy(QComboBox::InsertAtBottom);
+ QTest::keyPress(testWidget, 'a');
+ QTest::keyPress(testWidget, 'b');
+ QCOMPARE(testWidget->currentText(), QString("ab"));
+ QCOMPARE(testWidget->currentIndex(), -1);
+ int numItems = testWidget->count();
+ QTest::keyPress(testWidget, Qt::Key_Return);
+ QCOMPARE(testWidget->count(), numItems + 1);
+ QCOMPARE(testWidget->currentIndex(), numItems);
+ testWidget->setCurrentIndex(-1);
+ QTest::keyPress(testWidget, 'a');
+ QTest::keyPress(testWidget, 'b');
+ QCOMPARE(testWidget->currentIndex(), -1);
+ }
+ }
+}
+
+void tst_QComboBox::insertItems_data()
+{
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<QStringList>("insertedItems");
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<int>("expectedIndex");
+
+ QStringList initialItems;
+ QStringList insertedItems;
+
+ initialItems << "foo" << "bar";
+ insertedItems << "mongo";
+
+ QTest::newRow("prepend") << initialItems << insertedItems << 0 << 0;
+ QTest::newRow("prepend with negative value") << initialItems << insertedItems << -1 << 0;
+ QTest::newRow("append") << initialItems << insertedItems << initialItems.count() << initialItems.count();
+ QTest::newRow("append with too high value") << initialItems << insertedItems << 999 << initialItems.count();
+ QTest::newRow("insert") << initialItems << insertedItems << 1 << 1;
+}
+
+void tst_QComboBox::insertItems()
+{
+ QFETCH(QStringList, initialItems);
+ QFETCH(QStringList, insertedItems);
+ QFETCH(int, insertIndex);
+ QFETCH(int, expectedIndex);
+
+ testWidget->insertItems(0, initialItems);
+ QCOMPARE(testWidget->count(), initialItems.count());
+
+ testWidget->insertItems(insertIndex, insertedItems);
+
+ QCOMPARE(testWidget->count(), initialItems.count() + insertedItems.count());
+ for (int i=0; i<insertedItems.count(); ++i)
+ QCOMPARE(testWidget->itemText(expectedIndex + i), insertedItems.at(i));
+}
+
+void tst_QComboBox::insertItem_data()
+{
+ QTest::addColumn<QStringList>("initialItems");
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<QString>("itemLabel");
+ QTest::addColumn<int>("expectedIndex");
+ QTest::addColumn<bool>("editable");
+
+ QStringList initialItems;
+ initialItems << "foo" << "bar";
+ for(int e = 0 ; e<2 ; e++) {
+ bool editable = (e==0);
+ QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0 << editable;
+ QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0 << editable;
+ QTest::newRow("Insert beyond count") << initialItems << 3 << "inserted" << 2 << editable;
+ QTest::newRow("Insert at count") << initialItems << 2 << "inserted" << 2 << editable;
+ QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1 << editable;
+ }
+}
+
+void tst_QComboBox::insertItem()
+{
+ QFETCH(QStringList, initialItems);
+ QFETCH(int, insertIndex);
+ QFETCH(QString, itemLabel);
+ QFETCH(int, expectedIndex);
+ QFETCH(bool, editable);
+
+ testWidget->insertItems(0, initialItems);
+ QCOMPARE(testWidget->count(), initialItems.count());
+
+ testWidget->setEditable(true);
+ if (editable)
+ testWidget->setEditText("FOO");
+ testWidget->insertItem(insertIndex, itemLabel);
+
+ QCOMPARE(testWidget->count(), initialItems.count() + 1);
+ QCOMPARE(testWidget->itemText(expectedIndex), itemLabel);
+
+ if (editable)
+ QCOMPARE(testWidget->currentText(), QString("FOO"));
+}
+
+void tst_QComboBox::insertOnCurrentIndex()
+{
+ testWidget->setEditable(true);
+ testWidget->addItem("first item");
+ testWidget->setCurrentIndex(0);
+ testWidget->insertItem(0, "second item");
+ QCOMPARE(testWidget->lineEdit()->text(), QString::fromAscii("first item"));
+}
+
+void tst_QComboBox::textpixmapdata_data()
+{
+ QTest::addColumn<QStringList>("text");
+ QTest::addColumn<IconList>("icons");
+ QTest::addColumn<VariantList>("variant");
+
+ QStringList text;
+ IconList icon;
+ VariantList variant;
+
+ {
+ text.clear(); icon.clear(); variant.clear();
+ text << "foo" << "bar";
+ icon << QIcon() << QIcon();
+ variant << QVariant() << QVariant();
+ QTest::newRow("just text") << text << icon << variant;
+ }
+ {
+ text.clear(); icon.clear(); variant.clear();
+ text << QString() << QString();
+ icon << QIcon(QPixmap("qtlogo.png")) << QIcon(QPixmap("qtlogoinverted.png"));
+ variant << QVariant() << QVariant();
+ QTest::newRow("just icons") << text << icon << variant;
+ }
+ {
+ text.clear(); icon.clear(); variant.clear();
+ text << QString() << QString();
+ icon << QIcon() << QIcon();
+ variant << 12 << "bingo";
+ QTest::newRow("just user data") << text << icon << variant;
+ }
+ {
+ text.clear(); icon.clear(); variant.clear();
+ text << "foo" << "bar";
+ icon << QIcon(QPixmap("qtlogo.png")) << QIcon(QPixmap("qtlogoinverted.png"));
+ variant << 12 << "bingo";
+ QTest::newRow("text, icons and user data") << text << icon << variant;
+ }
+}
+
+void tst_QComboBox::textpixmapdata()
+{
+ QFETCH(QStringList, text);
+ QFETCH(IconList, icons);
+ QFETCH(VariantList, variant);
+
+ QVERIFY(text.count() == icons.count() && text.count() == variant.count());
+
+ for (int i = 0; i<text.count(); ++i) {
+ testWidget->insertItem(i, text.at(i));
+ testWidget->setItemIcon(i, icons.at(i));
+ testWidget->setItemData(i, variant.at(i), Qt::UserRole);
+ }
+
+ QCOMPARE(testWidget->count(), text.count());
+
+ for (int i = 0; i<text.count(); ++i) {
+ QIcon icon = testWidget->itemIcon(i);
+ QVERIFY(icon.serialNumber() == icons.at(i).serialNumber());
+ QPixmap original = icons.at(i).pixmap(1024);
+ QPixmap pixmap = icon.pixmap(1024);
+ QVERIFY(pixmap.toImage() == original.toImage());
+ }
+
+ for (int i = 0; i<text.count(); ++i) {
+ QCOMPARE(testWidget->itemText(i), text.at(i));
+ // ### we should test icons/pixmap as well, but I need to fix the api mismatch first
+ QCOMPARE(testWidget->itemData(i, Qt::UserRole), variant.at(i));
+ }
+}
+
+void tst_QComboBox::setCurrentIndex()
+{
+ QCOMPARE(testWidget->count(), 0);
+ testWidget->addItem("foo");
+ testWidget->addItem("bar");
+ QCOMPARE(testWidget->count(), 2);
+
+ QCOMPARE(testWidget->currentIndex(), 0);
+ testWidget->setCurrentIndex(0);
+ QCOMPARE(testWidget->currentText(), QString("foo"));
+
+ testWidget->setCurrentIndex(1);
+ QCOMPARE(testWidget->currentText(), QString("bar"));
+
+ testWidget->setCurrentIndex(0);
+ QCOMPARE(testWidget->currentText(), QString("foo"));
+}
+
+void tst_QComboBox::editTextChanged()
+{
+ QCOMPARE(testWidget->count(), 0);
+ testWidget->addItem("foo");
+ testWidget->addItem("bar");
+ QCOMPARE(testWidget->count(), 2);
+
+ // first we test non editable
+ testWidget->setEditable(false);
+ QCOMPARE(testWidget->isEditable(), false);
+
+ // no signal should be sent when current is set to the same
+ QCOMPARE(testWidget->currentIndex(), 0);
+ editTextCount = 0;
+ editText.clear();
+ testWidget->setCurrentIndex(0);
+ QCOMPARE(testWidget->currentIndex(), 0);
+ QCOMPARE(editTextCount, 0);
+ QCOMPARE(editText.isEmpty(), true);
+
+ // no signal should be sent when changing to other index because we are not editable
+ QCOMPARE(testWidget->currentIndex(), 0);
+ editTextCount = 0;
+ editText.clear();
+ testWidget->setCurrentIndex(1);
+ QCOMPARE(testWidget->currentIndex(), 1);
+ QCOMPARE(editTextCount, 0);
+ QCOMPARE(editText.isEmpty(), true);
+
+ // now set to editable and reset current index
+ testWidget->setEditable(true);
+ QCOMPARE(testWidget->isEditable(), true);
+ testWidget->setCurrentIndex(0);
+
+ // no signal should be sent when current is set to the same
+ QCOMPARE(testWidget->currentIndex(), 0);
+ editTextCount = 0;
+ editText.clear();
+ testWidget->setCurrentIndex(0);
+ QCOMPARE(testWidget->currentIndex(), 0);
+ QCOMPARE(editTextCount, 0);
+ QCOMPARE(editText.isEmpty(), true);
+
+ // signal should be sent when changing to other index
+ QCOMPARE(testWidget->currentIndex(), 0);
+ editTextCount = 0;
+ editText.clear();
+ testWidget->setCurrentIndex(1);
+ QCOMPARE(testWidget->currentIndex(), 1);
+ QCOMPARE(editTextCount, 1);
+ QCOMPARE(editText, QString("bar"));
+
+ // insert some keys and notice they are all signaled
+ editTextCount = 0;
+ editText.clear();
+ QTest::keyClicks(testWidget, "bingo");
+ QCOMPARE(editTextCount, 5);
+ QCOMPARE(editText, QString("barbingo"));
+}
+
+void tst_QComboBox::onEditTextChanged(const QString &text)
+{
+ editTextCount++;
+ editText = text;
+}
+
+void tst_QComboBox::setModel()
+{
+ QComboBox box;
+ QCOMPARE(box.currentIndex(), -1);
+ box.addItems((QStringList() << "foo" << "bar"));
+ QCOMPARE(box.currentIndex(), 0);
+ box.setCurrentIndex(1);
+ QCOMPARE(box.currentIndex(), 1);
+
+ // check that currentIndex is set to invalid
+ QAbstractItemModel *oldModel = box.model();
+ box.setModel(new QStandardItemModel(&box));
+ QCOMPARE(box.currentIndex(), -1);
+ QVERIFY(box.model() != oldModel);
+
+ // check that currentIndex is set to first item
+ oldModel = box.model();
+ box.setModel(new QStandardItemModel(2,1, &box));
+ QCOMPARE(box.currentIndex(), 0);
+ QVERIFY(box.model() != oldModel);
+}
+
+void tst_QComboBox::modelDeleted()
+{
+ QComboBox box;
+ QStandardItemModel *model = new QStandardItemModel;
+ box.setModel(model);
+ QCOMPARE(box.model(), static_cast<QAbstractItemModel *>(model));
+ delete model;
+ QVERIFY(box.model());
+ QCOMPARE(box.findText("bubu"), -1);
+
+ delete box.model();
+ QVERIFY(box.model());
+ delete box.model();
+ QVERIFY(box.model());
+}
+
+void tst_QComboBox::setMaxCount()
+{
+ QStringList items;
+ items << "1" << "2" << "3" << "4" << "5";
+
+ QComboBox box;
+ box.addItems(items);
+ QCOMPARE(box.count(), 5);
+
+ box.setMaxCount(4);
+ QCOMPARE(box.count(), 4);
+ QCOMPARE(box.itemText(0), QString("1"));
+ QCOMPARE(box.itemText(1), QString("2"));
+ QCOMPARE(box.itemText(2), QString("3"));
+ QCOMPARE(box.itemText(3), QString("4"));
+
+ // appending should do nothing
+ box.addItem("foo");
+ QCOMPARE(box.count(), 4);
+ QCOMPARE(box.findText("foo"), -1);
+
+ // inserting one item at top should remove the last
+ box.insertItem(0, "0");
+ QCOMPARE(box.count(), 4);
+ QCOMPARE(box.itemText(0), QString("0"));
+ QCOMPARE(box.itemText(1), QString("1"));
+ QCOMPARE(box.itemText(2), QString("2"));
+ QCOMPARE(box.itemText(3), QString("3"));
+
+ // insert 5 items in a box with maxCount 4
+ box.insertItems(0, items);
+ QCOMPARE(box.count(), 4);
+ QCOMPARE(box.itemText(0), QString("1"));
+ QCOMPARE(box.itemText(1), QString("2"));
+ QCOMPARE(box.itemText(2), QString("3"));
+ QCOMPARE(box.itemText(3), QString("4"));
+
+ // insert 5 items at pos 2. Make sure only two get inserted
+ QSignalSpy spy(box.model(), SIGNAL(rowsInserted(QModelIndex,int,int)));
+ box.insertItems(2, items);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(1).toInt(), 2);
+ QCOMPARE(spy.at(0).at(2).toInt(), 3);
+
+ QCOMPARE(box.count(), 4);
+ QCOMPARE(box.itemText(0), QString("1"));
+ QCOMPARE(box.itemText(1), QString("2"));
+ QCOMPARE(box.itemText(2), QString("1"));
+ QCOMPARE(box.itemText(3), QString("2"));
+
+ box.insertItems(0, QStringList());
+ QCOMPARE(box.count(), 4);
+
+ box.setMaxCount(0);
+ QCOMPARE(box.count(), 0);
+ box.addItem("foo");
+ QCOMPARE(box.count(), 0);
+ box.addItems(items);
+ QCOMPARE(box.count(), 0);
+}
+
+void tst_QComboBox::convenienceViews()
+{
+ // QListWidget
+ QComboBox listCombo;
+ QListWidget *list = new QListWidget();
+ listCombo.setModel(list->model());
+ listCombo.setView(list);
+ // add items
+ list->addItem("list0");
+ listCombo.addItem("list1");
+ QCOMPARE(listCombo.count(), 2);
+ QCOMPARE(listCombo.itemText(0), QString("list0"));
+ QCOMPARE(listCombo.itemText(1), QString("list1"));
+
+ // QTreeWidget
+ QComboBox treeCombo;
+ QTreeWidget *tree = new QTreeWidget();
+ tree->setColumnCount(1);
+ tree->header()->hide();
+ treeCombo.setModel(tree->model());
+ treeCombo.setView(tree);
+ // add items
+ tree->addTopLevelItem(new QTreeWidgetItem(QStringList("tree0")));
+ treeCombo.addItem("tree1");
+ QCOMPARE(treeCombo.count(), 2);
+ QCOMPARE(treeCombo.itemText(0), QString("tree0"));
+ QCOMPARE(treeCombo.itemText(1), QString("tree1"));
+
+ // QTableWidget
+ QComboBox tableCombo;
+ QTableWidget *table = new QTableWidget(0,1);
+ table->verticalHeader()->hide();
+ table->horizontalHeader()->hide();
+ tableCombo.setModel(table->model());
+ tableCombo.setView(table);
+ // add items
+ table->setRowCount(table->rowCount() + 1);
+ table->setItem(0, table->rowCount() - 1, new QTableWidgetItem("table0"));
+ tableCombo.addItem("table1");
+ QCOMPARE(tableCombo.count(), 2);
+ QCOMPARE(tableCombo.itemText(0), QString("table0"));
+ QCOMPARE(tableCombo.itemText(1), QString("table1"));
+}
+
+class ReturnClass : public QWidget
+{
+ Q_OBJECT
+public:
+ ReturnClass(QWidget *parent = 0)
+ : QWidget(parent), received(false)
+ {
+ QComboBox *box = new QComboBox(this);
+ box->setEditable(true);
+ edit = box->lineEdit();
+ box->setGeometry(rect());
+ }
+
+ void keyPressEvent(QKeyEvent *e)
+ {
+ received = (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter);
+ }
+
+ QLineEdit *edit;
+
+ bool received;
+
+};
+
+
+
+void tst_QComboBox::ensureReturnIsIgnored()
+{
+ ReturnClass r;
+ r.show();
+
+ QTest::keyClick(r.edit, Qt::Key_Return);
+ QVERIFY(r.received);
+ r.received = false;
+ QTest::keyClick(r.edit, Qt::Key_Enter);
+ QVERIFY(r.received);
+}
+
+
+void tst_QComboBox::findText_data()
+{
+ QTest::addColumn<QStringList>("items");
+ QTest::addColumn<int>("matchflags");
+ QTest::addColumn<QString>("search");
+ QTest::addColumn<int>("result");
+
+ QStringList list;
+ list << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "one";
+ QTest::newRow("CaseSensitive_1") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
+ << QString("Two") << 1;
+ QTest::newRow("CaseSensitive_2") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
+ << QString("two") << -1;
+ QTest::newRow("CaseSensitive_3") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
+ << QString("One") << 0;
+ QTest::newRow("CaseSensitive_4") << list << (int)(Qt::MatchExactly|Qt::MatchCaseSensitive)
+ << QString("one") << 6;
+ QTest::newRow("CaseInsensitive_1") << list << (int)(Qt::MatchExactly) << QString("Two") << 1;
+ QTest::newRow("CaseInsensitive_2") << list << (int)(Qt::MatchExactly) << QString("two") << -1;
+ QTest::newRow("CaseInsensitive_3") << list << (int)(Qt::MatchExactly) << QString("One") << 0;
+ QTest::newRow("CaseInsensitive_4") << list << (int)(Qt::MatchExactly) << QString("one") << 6;
+}
+void tst_QComboBox::findText()
+{
+ QFETCH(QStringList, items);
+ QFETCH(int, matchflags);
+ QFETCH(QString, search);
+ QFETCH(int, result);
+
+ testWidget->clear();
+ testWidget->addItems(items);
+
+ QCOMPARE(testWidget->findText(search, (Qt::MatchFlags)matchflags), result);
+}
+
+typedef QList<int> IntList;
+typedef QList<Qt::Key> KeyList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(KeyList)
+
+void tst_QComboBox::flaggedItems_data()
+{
+ QTest::addColumn<QStringList>("itemList");
+ QTest::addColumn<IntList>("deselectFlagList");
+ QTest::addColumn<IntList>("disableFlagList");
+ QTest::addColumn<KeyList>("keyMovementList");
+ QTest::addColumn<bool>("editable");
+ QTest::addColumn<int>("expectedIndex");
+
+ for (int editable=0;editable<2;editable++) {
+ QString testCase = editable ? "editable:" : "non-editable:";
+ QStringList itemList;
+ itemList << "One" << "Two" << "Three" << "Four" << "Five" << "Six" << "Seven" << "Eight";
+ IntList deselectFlagList;
+ IntList disableFlagList;
+ KeyList keyMovementList;
+
+ keyMovementList << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down;
+ QTest::newRow(testCase.toAscii() + "normal") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
+
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ deselectFlagList << 1 << 3;
+ QTest::newRow(testCase.toAscii() + "non-selectable") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
+
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ disableFlagList << 2;
+ QTest::newRow(testCase.toAscii() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 5;
+
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ deselectFlagList << 1 << 3;
+ disableFlagList << 2 << 3;
+ QTest::newRow(testCase.toAscii() + "mixed") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 6;
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ disableFlagList << 0 << 1 << 2 << 3 << 4 << 5 << 6;
+ QTest::newRow(testCase.toAscii() + "nearly-empty") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
+
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ disableFlagList << 0 << 1 << 2 << 3 << 5 << 6 << 7;
+ keyMovementList.clear();
+ QTest::newRow(testCase.toAscii() + "only one enabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
+
+ if (!editable) {
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ keyMovementList.clear();
+ disableFlagList << 0 << 2 << 3;
+ keyMovementList << Qt::Key_Down << Qt::Key_Home;
+ QTest::newRow(testCase.toAscii() + "home-disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 1;
+
+ keyMovementList.clear();
+ keyMovementList << Qt::Key_End;
+ QTest::newRow(testCase.toAscii() + "end-key") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 7;
+
+ disableFlagList.clear();
+ disableFlagList << 1 ;
+ keyMovementList << Qt::Key_T;
+ QTest::newRow(testCase.toAscii() + "keyboard-search") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
+
+ itemList << "nine" << "ten";
+ keyMovementList << Qt::Key_T;
+ QTest::newRow(testCase.toAscii() + "search same start letter") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 9;
+
+ keyMovementList.clear();
+ keyMovementList << Qt::Key_T << Qt::Key_H;
+ QTest::newRow(testCase.toAscii() + "keyboard search item") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
+
+ disableFlagList.clear();
+ disableFlagList << 1 << 3 << 5 << 7 << 9;
+ keyMovementList.clear();
+ keyMovementList << Qt::Key_End << Qt::Key_Up << Qt::Key_Up << Qt::Key_PageDown << Qt::Key_PageUp << Qt::Key_PageUp << Qt::Key_Down;
+ QTest::newRow(testCase.toAscii() + "all key combinations") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 4;
+ } else {
+ deselectFlagList.clear();
+ disableFlagList.clear();
+ disableFlagList << 1;
+ keyMovementList.clear();
+ keyMovementList << Qt::Key_T << Qt::Key_Enter;
+ QTest::newRow(testCase.toAscii() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
+ QTest::newRow(testCase.toAscii() + "broken autocompletion") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2;
+ }
+ }
+}
+
+void tst_QComboBox::flaggedItems()
+{
+ QFETCH(QStringList, itemList);
+ QFETCH(IntList, deselectFlagList);
+ QFETCH(IntList, disableFlagList);
+ QFETCH(KeyList, keyMovementList);
+ QFETCH(bool, editable);
+ QFETCH(int, expectedIndex);
+
+ QComboBox comboBox;
+ QListWidget listWidget;
+ listWidget.addItems(itemList);
+
+ comboBox.setEditable(editable);
+ foreach (int index, deselectFlagList)
+ listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsSelectable);
+
+ foreach (int index, disableFlagList)
+ listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
+
+ comboBox.setModel(listWidget.model());
+ comboBox.setView(&listWidget);
+ comboBox.show();
+ QApplication::setActiveWindow(&comboBox);
+ comboBox.activateWindow();
+ comboBox.setFocus();
+ QTRY_VERIFY(comboBox.isVisible());
+ QTRY_VERIFY(comboBox.hasFocus());
+
+ if (editable)
+ comboBox.lineEdit()->selectAll();
+
+ QSignalSpy indexChangedInt(&comboBox, SIGNAL(currentIndexChanged(int)));
+ for (int i = 0; i < keyMovementList.count(); ++i) {
+ Qt::Key key = keyMovementList[i];
+ QTest::keyClick(&comboBox, key);
+ if (indexChangedInt.count() != i + 1) {
+ QTest::qWait(400);
+ }
+ }
+
+ QCOMPARE(comboBox.currentIndex() , expectedIndex);
+}
+
+void tst_QComboBox::pixmapIcon()
+{
+ QComboBox box;
+ QStandardItemModel *model = new QStandardItemModel(2, 1, &box);
+
+ QPixmap pix(10, 10);
+ pix.fill(Qt::red);
+ model->setData(model->index(0, 0), "Element 1");
+ model->setData(model->index(0, 0), pix, Qt::DecorationRole);
+
+ QIcon icon(pix);
+ model->setData(model->index(1, 0), "Element 2");
+ model->setData(model->index(1, 0), icon, Qt::DecorationRole);
+
+ box.setModel(model);
+
+ QCOMPARE( box.itemIcon(0).isNull(), false );
+ QCOMPARE( box.itemIcon(1).isNull(), false );
+}
+
+// defined to be 120 by the wheel mouse vendors according to the docs
+#define WHEEL_DELTA 120
+
+void tst_QComboBox::mouseWheel_data()
+{
+ QTest::addColumn<IntList>("disabledItems");
+ QTest::addColumn<int>("startIndex");
+ QTest::addColumn<int>("wheelDirection");
+ QTest::addColumn<int>("expectedIndex");
+
+ IntList disabled;
+ disabled << 0 << 1 << 2 << 4;
+ int start = 3;
+ int wheel = 1;
+ int expected = 3;
+ QTest::newRow("upper locked") << disabled << start << wheel << expected;
+
+ wheel = -1;
+ expected = 5;
+ QTest::newRow("jump over") << disabled << start << wheel << expected;
+
+ disabled.clear();
+ disabled << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9;
+ start = 0;
+ wheel = -1;
+ expected = 0;
+ QTest::newRow("single Item enabled") << disabled << start << wheel << expected;
+}
+
+void tst_QComboBox::mouseWheel()
+{
+ QFETCH(IntList, disabledItems);
+ QFETCH(int, startIndex);
+ QFETCH(int, wheelDirection);
+ QFETCH(int, expectedIndex);
+
+ QCoreApplication *applicationInstance = QCoreApplication::instance();
+ QVERIFY(applicationInstance != 0);
+
+ QComboBox box;
+ QStringList list;
+ list << "one" << "two" << "three" << "four" << "five" << "six" << "seven" << "eight" << "nine" << "ten";
+
+ QListWidget listWidget;
+ listWidget.addItems(list);
+
+ foreach (int index, disabledItems)
+ listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled);
+
+ box.setModel(listWidget.model());
+ box.setView(&listWidget);
+ for (int i=0; i < 2; ++i) {
+ box.setEditable(i==0?false:true);
+ box.setCurrentIndex(startIndex);
+
+ QWheelEvent event = QWheelEvent(box.rect().bottomRight() , WHEEL_DELTA * wheelDirection, Qt::NoButton, Qt::NoModifier);
+ QVERIFY(applicationInstance->sendEvent(&box,&event));
+
+ QCOMPARE(box.currentIndex(), expectedIndex);
+ }
+}
+
+void tst_QComboBox::layoutDirection()
+{
+ QComboBox box;
+ Qt::LayoutDirection dir;
+ QLineEdit *lineEdit;
+
+ // RTL
+ box.setLayoutDirection(Qt::RightToLeft);
+ QStyleOptionComboBox opt;
+ opt.direction = Qt::RightToLeft;
+ dir = (Qt::LayoutDirection)box.style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, &box);
+
+ QCOMPARE(box.view()->layoutDirection(), dir);
+ box.setEditable(true);
+ QCOMPARE(box.lineEdit()->layoutDirection(), dir);
+ lineEdit = new QLineEdit;
+ QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
+ box.setLineEdit(lineEdit);
+ QCOMPARE(lineEdit->layoutDirection(), dir);
+
+ // LTR
+ box.setLayoutDirection(Qt::LeftToRight);
+ qApp->setLayoutDirection(Qt::RightToLeft);
+
+ opt.direction = Qt::LeftToRight;
+ dir = (Qt::LayoutDirection)box.style()->styleHint(QStyle::SH_ComboBox_LayoutDirection, &opt, &box);
+
+ QCOMPARE(box.view()->layoutDirection(), dir);
+ box.setEditable(true);
+ QCOMPARE(box.lineEdit()->layoutDirection(), dir);
+ lineEdit = new QLineEdit;
+ QCOMPARE(lineEdit->layoutDirection(), qApp->layoutDirection());
+ box.setLineEdit(lineEdit);
+ QCOMPARE(lineEdit->layoutDirection(), dir);
+
+}
+
+void tst_QComboBox::itemListPosition()
+{
+ //tests that the list is not out of the screen boundaries
+
+ //put the QApplication layout back
+ QApplication::setLayoutDirection(Qt::LeftToRight);
+
+ //we test QFontComboBox because it has the specific behaviour to set a fixed size
+ //to the list view
+ QWidget topLevel;
+ QFontComboBox combo(&topLevel);
+
+ //the code to get the avaialbe screen space is copied from QComboBox code
+ const int scrNumber = QApplication::desktop()->screenNumber(&combo);
+ QRect screen;
+#ifdef Q_WS_WIN
+ screen = QApplication::desktop()->screenGeometry(scrNumber);
+#elif defined Q_WS_X11
+ if (X11->desktopEnvironment == DE_KDE)
+ screen = QApplication::desktop()->screenGeometry(scrNumber);
+ else
+ screen = QApplication::desktop()->availableGeometry(scrNumber);
+#else
+ screen = QApplication::desktop()->availableGeometry(scrNumber);
+#endif
+
+ combo.move(screen.width()-combo.sizeHint().width(), 0); //puts the combo to the top-right corner
+
+ topLevel.show();
+ //wait because the window manager can move the window if there is a right panel
+ QTRY_VERIFY(combo.isVisible());
+ combo.showPopup();
+ QTRY_VERIFY(combo.view());
+ QTRY_VERIFY(combo.view()->isVisible());
+ QVERIFY( combo.view()->window()->x() + combo.view()->window()->width() <= screen.x() + screen.width() );
+}
+
+void tst_QComboBox::separatorItem_data()
+{
+ QTest::addColumn<QStringList>("items");
+ QTest::addColumn<IntList>("separators");
+
+ QTest::newRow("test") << (QStringList() << "one" << "two" << "three" << "other...")
+ << (IntList() << 4);
+}
+
+void tst_QComboBox::separatorItem()
+{
+ QFETCH(QStringList, items);
+ QFETCH(IntList, separators);
+
+ QComboBox box;
+ box.addItems(items);
+ foreach(int index, separators)
+ box.insertSeparator(index);
+ QCOMPARE(box.count(), (items.count() + separators.count()));
+ for (int i = 0, s = 0; i < box.count(); ++i) {
+ if (i == separators.at(s)) {
+ QCOMPARE(box.itemText(i), QString());
+ ++s;
+ } else {
+ QCOMPARE(box.itemText(i), items.at(i - s));
+ }
+ }
+}
+
+// This test requires the Cleanlooks style
+#ifndef QT_NO_STYLE_CLEANLOOKS
+void tst_QComboBox::task190351_layout()
+{
+ const QString oldStyle = QApplication::style()->objectName();
+ QApplication::setStyle(new QCleanlooksStyle);
+
+ QComboBox listCombo;
+ QListWidget *list = new QListWidget();
+ listCombo.setModel(list->model());
+ listCombo.setView(list);
+ for(int i = 1; i < 150; i++)
+ list->addItem(QLatin1String("list") + QString::number(i));
+
+ listCombo.show();
+ QTest::qWaitForWindowShown(&listCombo);
+ QTRY_VERIFY(listCombo.isVisible());
+ listCombo.setCurrentIndex(70);
+ listCombo.showPopup();
+ QTRY_VERIFY(listCombo.view());
+ QTest::qWaitForWindowShown(listCombo.view());
+ QTRY_VERIFY(listCombo.view()->isVisible());
+ QApplication::processEvents();
+
+#ifdef QT_BUILD_INTERNAL
+ QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&listCombo);
+ QVERIFY(container);
+ QCOMPARE(static_cast<QAbstractItemView *>(list), qFindChild<QAbstractItemView *>(container));
+ QWidget *top = qFindChild<QComboBoxPrivateScroller *>(container);
+ QVERIFY(top);
+ QVERIFY(top->isVisible());
+ QCOMPARE(top->mapToGlobal(QPoint(0, top->height())).y(), list->mapToGlobal(QPoint()).y());
+#endif
+
+ QApplication::setStyle(oldStyle);
+}
+#endif
+
+class task166349_ComboBox : public QComboBox
+{
+ Q_OBJECT
+public:
+ task166349_ComboBox(QWidget *parent = 0) : QComboBox(parent)
+ {
+ QStringList list;
+ list << "one" << "two";
+ connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
+ addItems(list);
+ }
+public slots:
+ void onCurrentIndexChanged(int index)
+ {
+ setEditable(index % 2 == 1);
+ }
+};
+
+void tst_QComboBox::task166349_setEditableOnReturn()
+{
+ task166349_ComboBox comboBox;
+ QTest::keyClick(&comboBox, Qt::Key_Down);
+ QTest::keyClick(&comboBox, Qt::Key_1);
+ QTest::keyClick(&comboBox, Qt::Key_Enter);
+ QCOMPARE(QLatin1String("two1"), comboBox.itemText(comboBox.count() - 1));
+}
+
+// This test requires the Cleanlooks style.
+#ifndef QT_NO_STYLE_CLEANLOOKS
+void tst_QComboBox::task191329_size()
+{
+ const QString oldStyle = QApplication::style()->objectName();
+ QApplication::setStyle(new QCleanlooksStyle);
+
+ QComboBox tableCombo;
+ int rows;
+ if (QApplication::desktop()->screenGeometry().height() < 480)
+ rows = 8;
+ else
+ rows = 15;
+
+ QStandardItemModel model(rows, 2);
+ for (int row = 0; row < model.rowCount(); ++row) {
+ for (int column = 0; column < model.columnCount(); ++column) {
+ QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
+ model.setItem(row, column, item);
+ }
+ }
+ QTableView *table = new QTableView();
+ table->verticalHeader()->hide();
+ table->horizontalHeader()->hide();
+ tableCombo.setView(table);
+ tableCombo.setModel(&model);
+
+ tableCombo.show();
+ QTRY_VERIFY(tableCombo.isVisible());
+ tableCombo.showPopup();
+ QTRY_VERIFY(tableCombo.view());
+ QTRY_VERIFY(tableCombo.view()->isVisible());
+
+#ifdef QT_BUILD_INTERNAL
+ QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&tableCombo);
+ QVERIFY(container);
+ QCOMPARE(static_cast<QAbstractItemView *>(table), qFindChild<QAbstractItemView *>(container));
+ foreach (QWidget *button, qFindChildren<QComboBoxPrivateScroller *>(container)) {
+ //the popup should be large enough to contains everithing so the top and left button are hidden
+ QVERIFY(!button->isVisible());
+ }
+#endif
+
+ QApplication::setStyle(oldStyle);
+}
+#endif
+
+void tst_QComboBox::task190205_setModelAdjustToContents()
+{
+ QStringList initialContent;
+ QStringList finalContent;
+ initialContent << "foo" << "bar";
+ finalContent << "bar" << "foooooooobar";
+
+ QComboBox box;
+ box.setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ box.addItems(initialContent);
+ box.show();
+
+ //wait needed in order to get the combo initial size
+ QTRY_VERIFY(box.isVisible());
+
+ box.setModel(new QStringListModel(finalContent));
+
+ QComboBox correctBox;
+ correctBox.addItems(finalContent);
+ correctBox.show();
+
+ QCoreApplication::processEvents();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&box);
+ qt_x11_wait_for_window_manager(&correctBox);
+#endif
+
+ // box should be resized to the same size as correctBox
+ QTRY_COMPARE(box.size(), correctBox.size());
+}
+
+void tst_QComboBox::task248169_popupWithMinimalSize()
+{
+ QStringList initialContent;
+ initialContent << "foo" << "bar" << "foobar";
+
+ QComboBox comboBox;
+ comboBox.addItems(initialContent);
+ QDesktopWidget desktop;
+ QRect desktopSize = desktop.availableGeometry();
+ comboBox.view()->setMinimumWidth(desktopSize.width() / 2);
+
+ comboBox.setGeometry(desktopSize.width() - (desktopSize.width() / 4), (desktopSize.width() / 4), (desktopSize.width() / 2), (desktopSize.width() / 4));
+
+ comboBox.show();
+ QTest::qWaitForWindowShown(&comboBox);
+ QTRY_VERIFY(comboBox.isVisible());
+ comboBox.showPopup();
+ QTRY_VERIFY(comboBox.view());
+ QTest::qWaitForWindowShown(comboBox.view());
+ QTRY_VERIFY(comboBox.view()->isVisible());
+
+#ifdef QT_BUILD_INTERNAL
+ QFrame *container = qFindChild<QComboBoxPrivateContainer *>(&comboBox);
+ QVERIFY(container);
+ QTRY_VERIFY(desktop.screenGeometry(container).contains(container->geometry()));
+#endif
+}
+
+void tst_QComboBox::task247863_keyBoardSelection()
+{
+ QComboBox combo;
+ combo.setEditable(false);
+ combo.addItem( QLatin1String("111"));
+ combo.addItem( QLatin1String("222"));
+ combo.show();
+ QApplication::setActiveWindow(&combo);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
+
+ QSignalSpy spy(&combo, SIGNAL(activated(const QString &)));
+ qApp->setEffectEnabled(Qt::UI_AnimateCombo, false);
+ QTest::keyClick(&combo, Qt::Key_Space);
+ qApp->setEffectEnabled(Qt::UI_AnimateCombo, true);
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down);
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter);
+ QCOMPARE(combo.currentText(), QLatin1String("222"));
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QComboBox::task220195_keyBoardSelection2()
+{
+ QComboBox combo;
+ combo.setEditable(false);
+ combo.addItem( QLatin1String("foo1"));
+ combo.addItem( QLatin1String("foo2"));
+ combo.addItem( QLatin1String("foo3"));
+ combo.show();
+ QApplication::setActiveWindow(&combo);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
+
+ combo.setCurrentIndex(-1);
+ QVERIFY(combo.currentText().isNull());
+
+ QTest::keyClick(&combo, 'f');
+ QCOMPARE(combo.currentText(), QLatin1String("foo1"));
+ QTest::qWait(QApplication::keyboardInputInterval() + 30);
+ QTest::keyClick(&combo, 'f');
+ QCOMPARE(combo.currentText(), QLatin1String("foo2"));
+ QTest::qWait(QApplication::keyboardInputInterval() + 30);
+ QTest::keyClick(&combo, 'f');
+ QCOMPARE(combo.currentText(), QLatin1String("foo3"));
+ QTest::qWait(QApplication::keyboardInputInterval() + 30);
+ QTest::keyClick(&combo, 'f');
+ QCOMPARE(combo.currentText(), QLatin1String("foo1"));
+ QTest::qWait(QApplication::keyboardInputInterval() + 30);
+
+ combo.setCurrentIndex(1);
+ QCOMPARE(combo.currentText(), QLatin1String("foo2"));
+ QTest::keyClick(&combo, 'f');
+ QCOMPARE(combo.currentText(), QLatin1String("foo3"));
+}
+
+
+void tst_QComboBox::setModelColumn()
+{
+ QStandardItemModel model(5,3);
+ model.setItem(0,0, new QStandardItem("0"));
+ model.setItem(1,0, new QStandardItem("1"));
+ model.setItem(2,0, new QStandardItem("2"));
+ model.setItem(3,0, new QStandardItem("3"));
+ model.setItem(4,0, new QStandardItem("4"));
+ model.setItem(0,1, new QStandardItem("zero"));
+ model.setItem(1,1, new QStandardItem("un"));
+ model.setItem(2,1, new QStandardItem("deux"));
+ model.setItem(3,1, new QStandardItem("trois"));
+ model.setItem(4,1, new QStandardItem("quatre"));
+ model.setItem(0,2, new QStandardItem("a"));
+ model.setItem(1,2, new QStandardItem("b"));
+ model.setItem(2,2, new QStandardItem("c"));
+ model.setItem(3,2, new QStandardItem("d"));
+ model.setItem(4,2, new QStandardItem("e"));
+
+ QComboBox box;
+ box.setModel(&model);
+ QCOMPARE(box.currentText(), QString("0"));
+ box.setModelColumn(1);
+ QCOMPARE(box.currentText(), QString("zero"));
+}
+
+void tst_QComboBox::noScrollbar_data()
+{
+ QTest::addColumn<QString>("stylesheet");
+
+ QTest::newRow("normal") << QString();
+ QTest::newRow("border") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue;}");
+ QTest::newRow("margin") << QString::fromLatin1("QAbstractItemView { margin: 12px 15px 13px 10px; }");
+ QTest::newRow("padding") << QString::fromLatin1("QAbstractItemView { padding: 12px 15px 13px 10px;}");
+ QTest::newRow("everything") << QString::fromLatin1("QAbstractItemView { border: 12px solid blue; "
+ " padding: 12px 15px 13px 10px; margin: 12px 15px 13px 10px; }");
+ QTest::newRow("everything and more") << QString::fromLatin1("QAbstractItemView { border: 1px 3px 5px 1px solid blue; "
+ " padding: 2px 5px 3px 1px; margin: 2px 5px 3px 1px; } "
+ " QAbstractItemView::item { border: 2px solid green; "
+ " padding: 1px 1px 2px 2px; margin: 1px; } " );
+}
+
+void tst_QComboBox::noScrollbar()
+{
+ QStringList initialContent;
+ initialContent << "foo" << "bar" << "foobar" << "moo";
+ QFETCH(QString, stylesheet);
+ QString oldCss = qApp->styleSheet();
+ qApp->setStyleSheet(stylesheet);
+
+ {
+ QWidget topLevel;
+ QComboBox comboBox(&topLevel);
+ comboBox.addItems(initialContent);
+ topLevel.show();
+ comboBox.resize(200, comboBox.height());
+ QTRY_VERIFY(comboBox.isVisible());
+ comboBox.showPopup();
+ QTRY_VERIFY(comboBox.view());
+ QTRY_VERIFY(comboBox.view()->isVisible());
+
+ QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
+ QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
+ }
+
+ {
+ QTableWidget *table = new QTableWidget(2,2);
+ QComboBox comboBox;
+ comboBox.setModel(table->model());
+ comboBox.setView(table);
+ comboBox.show();
+ QTRY_VERIFY(comboBox.isVisible());
+ comboBox.resize(200, comboBox.height());
+ comboBox.showPopup();
+ QTRY_VERIFY(comboBox.view());
+ QTRY_VERIFY(comboBox.view()->isVisible());
+
+ QVERIFY(!comboBox.view()->horizontalScrollBar()->isVisible());
+ QVERIFY(!comboBox.view()->verticalScrollBar()->isVisible());
+ }
+
+ qApp->setStyleSheet(oldCss);
+}
+
+void tst_QComboBox::setItemDelegate()
+{
+ QComboBox comboBox;
+ QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
+ comboBox.setItemDelegate(itemDelegate);
+ // the cast is a workaround for the XLC and Metrowerks compilers
+ QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
+}
+
+void tst_QComboBox::task253944_itemDelegateIsReset()
+{
+ QComboBox comboBox;
+ QStyledItemDelegate *itemDelegate = new QStyledItemDelegate;
+ comboBox.setItemDelegate(itemDelegate);
+
+ // the casts are workarounds for the XLC and Metrowerks compilers
+
+ comboBox.setEditable(true);
+ QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
+
+ comboBox.setStyleSheet("QComboBox { border: 1px solid gray; }");
+ QCOMPARE(static_cast<QStyledItemDelegate *>(comboBox.itemDelegate()), itemDelegate);
+}
+
+
+void tst_QComboBox::subControlRectsWithOffset_data()
+{
+ QTest::addColumn<bool>("editable");
+
+ QTest::newRow("editable = true") << true;
+ QTest::newRow("editable = false") << false;
+}
+
+void tst_QComboBox::subControlRectsWithOffset()
+{
+ // The sub control rect relative position should not depends
+ // on the position of the combobox
+
+ class FriendlyCombo : public QComboBox {
+ public:
+ void styleOption(QStyleOptionComboBox *optCombo) {
+ initStyleOption(optCombo);
+ }
+ } combo;
+ QStyleOptionComboBox optCombo;
+ combo.styleOption(&optCombo);
+
+
+ const QRect rectAtOrigin(0, 0, 80, 30);
+ const QPoint offset(25, 50);
+ const QRect rectWithOffset = rectAtOrigin.translated(offset);
+
+ QStyle *style = combo.style();
+
+ QFETCH(bool, editable);
+ optCombo.editable = editable;
+
+ optCombo.rect = rectAtOrigin;
+ QRect editFieldRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
+ QRect arrowRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
+ QRect listboxRect = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
+
+ optCombo.rect = rectWithOffset;
+ QRect editFieldRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxEditField, 0);
+ QRect arrowRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxArrow, 0);
+ QRect listboxRectWithOffset = style->subControlRect(QStyle::CC_ComboBox, &optCombo, QStyle::SC_ComboBoxListBoxPopup, 0);
+
+ QCOMPARE(editFieldRect, editFieldRectWithOffset.translated(-offset));
+ QCOMPARE(arrowRect, arrowRectWithOffset.translated(-offset));
+ QCOMPARE(listboxRect, listboxRectWithOffset.translated(-offset));
+
+}
+
+// This test depends on Windows style.
+#ifndef QT_NO_STYLE_WINDOWS
+void tst_QComboBox::task260974_menuItemRectangleForComboBoxPopup()
+{
+ class TestStyle: public QWindowsStyle
+ {
+ public:
+ int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *ret) const
+ {
+ if (hint == SH_ComboBox_Popup) return 1;
+ else return QCommonStyle::styleHint(hint, option, widget, ret);
+ }
+
+ void drawControl(ControlElement element, const QStyleOption *option, QPainter *, const QWidget *) const
+ {
+ if (element == CE_MenuItem)
+ discoveredRect = option->rect;
+ }
+
+ mutable QRect discoveredRect;
+ } style;
+
+
+ {
+ QComboBox comboBox;
+ comboBox.setStyle(&style);
+ comboBox.addItem("Item 1");
+
+ comboBox.show();
+ QTRY_VERIFY(comboBox.isVisible());
+ comboBox.showPopup();
+ QTRY_VERIFY(comboBox.view());
+ QTRY_VERIFY(comboBox.view()->isVisible());
+
+ QTRY_VERIFY(style.discoveredRect.width() <= comboBox.width());
+ }
+}
+#endif
+
+void tst_QComboBox::removeItem()
+{
+ QComboBox cb;
+ cb.removeItem(-1);
+ cb.removeItem(1);
+ cb.removeItem(0);
+ QCOMPARE(cb.count(), 0);
+
+ cb.addItem("foo");
+ cb.removeItem(-1);
+ QCOMPARE(cb.count(), 1);
+ cb.removeItem(1);
+ QCOMPARE(cb.count(), 1);
+ cb.removeItem(0);
+ QCOMPARE(cb.count(), 0);
+}
+
+void tst_QComboBox::resetModel()
+{
+ class StringListModel : public QStringListModel
+ {
+ public:
+ StringListModel(const QStringList &list) : QStringListModel(list)
+ {
+ }
+
+ void reset()
+ {
+ QStringListModel::reset();
+ }
+ };
+ QComboBox cb;
+ StringListModel model( QStringList() << "1" << "2");
+ QSignalSpy spy(&cb, SIGNAL(currentIndexChanged(int)));
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(cb.currentIndex(), -1); //no selection
+
+ cb.setModel(&model);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(cb.currentIndex(), 0); //first item selected
+
+ model.reset();
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(cb.currentIndex(), -1); //no selection
+
+}
+
+void tst_QComboBox::keyBoardNavigationWithMouse()
+{
+ QComboBox combo;
+ combo.setEditable(false);
+ for (int i = 0; i < 80; i++)
+ combo.addItem( QString::number(i));
+ combo.show();
+ QApplication::setActiveWindow(&combo);
+ QTest::qWaitForWindowShown(&combo);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
+
+ QCOMPARE(combo.currentText(), QLatin1String("0"));
+
+ combo.setFocus();
+ QTRY_VERIFY(combo.hasFocus());
+
+ QTest::keyClick(testWidget->lineEdit(), Qt::Key_Space);
+ QTest::qWait(30);
+ QTRY_VERIFY(combo.view());
+ QTRY_VERIFY(combo.view()->isVisible());
+ QTest::qWait(130);
+
+ QCOMPARE(combo.currentText(), QLatin1String("0"));
+
+ // When calling cursor function, Windows CE responds with: This function is not supported on this system.
+#ifndef Q_OS_WINCE
+ // Force cursor movement to prevent QCursor::setPos() from returning prematurely on QPA:
+ const QPoint target(combo.view()->mapToGlobal(combo.view()->rect().center()));
+ QCursor::setPos(QPoint(target.x() + 1, target.y()));
+ QCursor::setPos(target);
+
+ QTest::qWait(200);
+
+#define GET_SELECTION(SEL) \
+ QCOMPARE(combo.view()->selectionModel()->selection().count(), 1); \
+ QCOMPARE(combo.view()->selectionModel()->selection().indexes().count(), 1); \
+ SEL = combo.view()->selectionModel()->selection().indexes().first().row()
+
+ int selection;
+ GET_SELECTION(selection);
+
+ //since we moved the mouse is in the middle it should even be around 5;
+ QVERIFY(selection > 3);
+
+ static const int final = 40;
+ for (int i = selection + 1; i <= final; i++)
+ {
+ QTest::keyClick(combo.view(), Qt::Key_Down);
+ QTest::qWait(20);
+ GET_SELECTION(selection);
+ QCOMPARE(selection, i);
+ }
+
+ QTest::keyClick(combo.view(), Qt::Key_Enter);
+ QTRY_COMPARE(combo.currentText(), QString::number(final));
+#endif
+}
+
+void tst_QComboBox::task_QTBUG_1071_changingFocusEmitsActivated()
+{
+ QWidget w;
+ QVBoxLayout layout(&w);
+ QComboBox cb;
+ cb.setEditable(true);
+ QSignalSpy spy(&cb, SIGNAL(activated(int)));
+ cb.addItem("0");
+ cb.addItem("1");
+ cb.addItem("2");
+ QLineEdit edit;
+ layout.addWidget(&cb);
+ layout.addWidget(&edit);
+
+ w.show();
+ QApplication::setActiveWindow(&w);
+ QTest::qWaitForWindowShown(&w);
+ cb.clearEditText();
+ cb.setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(cb.hasFocus());
+ QTest::keyClick(static_cast<QWidget *>(0), '1');
+ QCOMPARE(spy.count(), 0);
+ edit.setFocus();
+ QTRY_VERIFY(edit.hasFocus());
+ QTRY_COMPARE(spy.count(), 1);
+}
+
+void tst_QComboBox::maxVisibleItems()
+{
+ QComboBox comboBox;
+ QCOMPARE(comboBox.maxVisibleItems(), 10); //default value.
+
+ QStringList content;
+ for(int i = 1; i < 50; i++)
+ content += QString::number(i);
+
+ comboBox.addItems(content);
+ comboBox.show();
+ comboBox.resize(200, comboBox.height());
+ QTRY_VERIFY(comboBox.isVisible());
+
+ comboBox.setMaxVisibleItems(5);
+ QCOMPARE(comboBox.maxVisibleItems(), 5);
+
+ comboBox.showPopup();
+ QTRY_VERIFY(comboBox.view());
+ QTRY_VERIFY(comboBox.view()->isVisible());
+
+ QAbstractItemView *v = comboBox.view();
+ int itemHeight = v->visualRect(v->model()->index(0,0)).height();
+ QListView *lv = qobject_cast<QListView*>(v);
+ if (lv)
+ itemHeight += lv->spacing();
+ QStyleOptionComboBox opt;
+ opt.initFrom(&comboBox);
+ if (!comboBox.style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
+ QCOMPARE(v->viewport()->height(), itemHeight * comboBox.maxVisibleItems());
+}
+
+void tst_QComboBox::task_QTBUG_10491_currentIndexAndModelColumn()
+{
+ QComboBox comboBox;
+
+ QStandardItemModel model(4, 4, &comboBox);
+ for (int i = 0; i < 4; i++){
+ model.setItem(i, 0, new QStandardItem(QString("Employee Nr %1").arg(i)));
+ model.setItem(i, 1, new QStandardItem(QString("Street Nr %1").arg(i)));
+ model.setItem(i, 2, new QStandardItem(QString("Town Nr %1").arg(i)));
+ model.setItem(i, 3, new QStandardItem(QString("Phone Nr %1").arg(i)));
+ }
+ comboBox.setModel(&model);
+ comboBox.setModelColumn(0);
+
+ QComboBoxPrivate *d = static_cast<QComboBoxPrivate *>(QComboBoxPrivate::get(&comboBox));
+ d->setCurrentIndex(model.index(2, 2));
+ QCOMPARE(QModelIndex(d->currentIndex), model.index(2, comboBox.modelColumn()));
+}
+
+QTEST_MAIN(tst_QComboBox)
+#include "tst_qcombobox.moc"
diff --git a/tests/auto/widgets/widgets/qcommandlinkbutton/.gitignore b/tests/auto/widgets/widgets/qcommandlinkbutton/.gitignore
new file mode 100644
index 0000000000..878121e2e6
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcommandlinkbutton/.gitignore
@@ -0,0 +1 @@
+tst_qcommandlinkbutton
diff --git a/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro b/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro
new file mode 100644
index 0000000000..497b8298a2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qcommandlinkbutton.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp b/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp
new file mode 100644
index 0000000000..6a51bf4bba
--- /dev/null
+++ b/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp
@@ -0,0 +1,590 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include "qcommandlinkbutton.h"
+#include <qapplication.h>
+
+#include <qcommandlinkbutton.h>
+#include <qmenu.h>
+#include <qtimer.h>
+#include <QDialog>
+#include <QGridLayout>
+#include <QPainter>
+
+Q_DECLARE_METATYPE(QCommandLinkButton*)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QCommandLinkButton : public QObject
+{
+Q_OBJECT
+public:
+ tst_QCommandLinkButton();
+ virtual ~tst_QCommandLinkButton();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void pressed();
+ void setAccel();
+ void isCheckable();
+ void setDown();
+ void popupCrash();
+ void isChecked();
+ void animateClick();
+ void toggle();
+ void clicked();
+ void toggled();
+ void defaultAndAutoDefault();
+ void setAutoRepeat();
+ void heightForWithWithIcon();
+
+protected slots:
+ void resetCounters();
+ void onClicked();
+ void onToggled( bool on );
+ void onPressed();
+ void onReleased();
+ void helperSlotDelete();
+
+private:
+ uint click_count;
+ uint toggle_count;
+ uint press_count;
+ uint release_count;
+
+ QCommandLinkButton *testWidget;
+};
+
+// Testing get/set functions
+void tst_QCommandLinkButton::getSetCheck()
+{
+ QCommandLinkButton obj1;
+
+ QString text("mytext");
+ QVERIFY(obj1.description().isEmpty());
+ obj1.setDescription(text);
+ QVERIFY(obj1.description() == text);
+
+ QVERIFY(obj1.text().isEmpty());
+ obj1.setText(text);
+ QVERIFY(obj1.text() == text);
+
+
+ QMenu *var1 = new QMenu;
+ obj1.setMenu(var1);
+ QCOMPARE(var1, obj1.menu());
+ obj1.setMenu((QMenu *)0);
+ QCOMPARE((QMenu *)0, obj1.menu());
+ delete var1;
+}
+
+tst_QCommandLinkButton::tst_QCommandLinkButton()
+{
+}
+
+tst_QCommandLinkButton::~tst_QCommandLinkButton()
+{
+}
+
+void tst_QCommandLinkButton::initTestCase()
+{
+ // Create the test class
+ testWidget = new QCommandLinkButton( "&Start", 0 );
+ testWidget->setObjectName("testWidget");
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+
+ connect( testWidget, SIGNAL(clicked()), this, SLOT(onClicked()) );
+ connect( testWidget, SIGNAL(pressed()), this, SLOT(onPressed()) );
+ connect( testWidget, SIGNAL(released()), this, SLOT(onReleased()) );
+ connect( testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)) );
+}
+
+void tst_QCommandLinkButton::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QCommandLinkButton::init()
+{
+ testWidget->setAutoRepeat( FALSE );
+ testWidget->setDown( FALSE );
+ testWidget->setText("Test");
+ testWidget->setDescription("Description text.");
+ testWidget->setEnabled( TRUE );
+ QKeySequence seq;
+ testWidget->setShortcut( seq );
+
+ resetCounters();
+}
+
+void tst_QCommandLinkButton::cleanup()
+{
+}
+
+
+void tst_QCommandLinkButton::resetCounters()
+{
+ toggle_count = 0;
+ press_count = 0;
+ release_count = 0;
+ click_count = 0;
+}
+
+void tst_QCommandLinkButton::onClicked()
+{
+ click_count++;
+}
+
+void tst_QCommandLinkButton::onToggled( bool /*on*/ )
+{
+ toggle_count++;
+}
+
+void tst_QCommandLinkButton::onPressed()
+{
+ press_count++;
+}
+
+void tst_QCommandLinkButton::onReleased()
+{
+ release_count++;
+}
+
+void tst_QCommandLinkButton::setAutoRepeat()
+{
+ // Give the last tests time to finish - i.e., wait for the window close
+ // and deactivate to avoid a race condition here. We can't add this to the
+ // end of the defaultAndAutoDefault test, since any failure in that test
+ // will return out of that function.
+ QTest::qWait( 1000 );
+
+ // If this changes, this test must be completely revised.
+ QVERIFY( !testWidget->isCheckable() );
+
+ // verify autorepeat is off by default.
+ QCommandLinkButton tmp( 0 );
+ tmp.setObjectName("tmp");
+ QVERIFY( !tmp.autoRepeat() );
+
+ // check if we can toggle the mode
+ testWidget->setAutoRepeat( TRUE );
+ QVERIFY( testWidget->autoRepeat() );
+
+ testWidget->setAutoRepeat( FALSE );
+ QVERIFY( !testWidget->autoRepeat() );
+
+ resetCounters();
+
+ // check that the button is down if we press space and not in autorepeat
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QTest::keyPress( testWidget, Qt::Key_Space );
+
+ QTest::qWait( 300 );
+
+ QVERIFY( testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+
+ QTest::keyRelease( testWidget, Qt::Key_Space );
+ resetCounters();
+
+ // check that the button is down if we press space while in autorepeat
+ // we can't actually confirm how many times it is fired, more than 1 is enough.
+
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( TRUE );
+ QTest::keyPress( testWidget, Qt::Key_Space );
+ QTest::qWait(900);
+ QVERIFY( testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QTest::keyRelease( testWidget, Qt::Key_Space );
+ QVERIFY(press_count == release_count);
+ QVERIFY(release_count == click_count);
+ QVERIFY(press_count > 1);
+
+ // #### shouldn't I check here to see if multiple signals have been fired???
+
+ // check that pressing ENTER has no effect
+ resetCounters();
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QTest::keyPress( testWidget, Qt::Key_Enter );
+
+ QTest::qWait( 300 );
+
+ QVERIFY( !testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 0 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+ QTest::keyRelease( testWidget, Qt::Key_Enter );
+
+ // check that pressing ENTER has no effect
+ resetCounters();
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( TRUE );
+ QTest::keyClick( testWidget, Qt::Key_Enter );
+ QTest::qWait( 300 );
+ QVERIFY( !testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 0 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+}
+
+void tst_QCommandLinkButton::pressed()
+{
+ QTest::keyPress( testWidget, ' ' );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)0 );
+
+ QTest::keyRelease( testWidget, ' ' );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)1 );
+
+ QTest::keyPress( testWidget,Qt::Key_Enter );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)1 );
+
+ testWidget->setAutoDefault(true);
+ QTest::keyPress( testWidget,Qt::Key_Enter );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)2 );
+ QCOMPARE( release_count, (uint)2 );
+ testWidget->setAutoDefault(false);
+
+}
+
+
+
+void tst_QCommandLinkButton::isCheckable()
+{
+ QVERIFY( !testWidget->isCheckable() );
+}
+
+void tst_QCommandLinkButton::setDown()
+{
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isDown() );
+
+ testWidget->setDown( TRUE );
+ QVERIFY( testWidget->isDown() );
+
+ testWidget->setDown( TRUE );
+ QTest::keyClick( testWidget, Qt::Key_Escape );
+ QVERIFY( !testWidget->isDown() );
+}
+
+void tst_QCommandLinkButton::isChecked()
+{
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isChecked() );
+
+ testWidget->setDown( TRUE );
+ QVERIFY( !testWidget->isChecked() );
+
+ testWidget->setDown( FALSE );
+ testWidget->toggle();
+ QVERIFY( testWidget->isChecked() == testWidget->isCheckable() );
+}
+
+void tst_QCommandLinkButton::toggle()
+{
+ // the pushbutton shouldn't toggle the button.
+ testWidget->toggle();
+ QVERIFY( testWidget->isChecked() == FALSE );
+}
+
+void tst_QCommandLinkButton::toggled()
+{
+ // the pushbutton shouldn't send a toggled signal when we call the toggle slot.
+ QVERIFY( !testWidget->isCheckable() );
+
+ testWidget->toggle();
+ QVERIFY( toggle_count == 0 );
+
+ // do it again, just to be sure
+ resetCounters();
+ testWidget->toggle();
+ QVERIFY( toggle_count == 0 );
+
+ // finally check that we can toggle using the mouse
+ resetCounters();
+ QTest::mousePress( testWidget, Qt::LeftButton );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( click_count == 0 );
+
+ QTest::mouseRelease( testWidget, Qt::LeftButton );
+ QVERIFY( click_count == 1 );
+}
+
+/*
+ If we press an accelerator key we ONLY get a pressed signal and
+ NOT a released or clicked signal.
+*/
+
+void tst_QCommandLinkButton::setAccel()
+{
+ testWidget->setText("&AccelTest");
+ QKeySequence seq( Qt::ALT + Qt::Key_A );
+ testWidget->setShortcut( seq );
+
+ // The shortcut will not be activated unless the button is in a active
+ // window and has focus
+ testWidget->setFocus();
+ for (int i = 0; !testWidget->isActiveWindow() && i < 1000; ++i) {
+ testWidget->activateWindow();
+ QApplication::instance()->processEvents();
+ QTest::qWait(100);
+ }
+
+ QVERIFY(testWidget->isActiveWindow());
+
+ QTest::keyClick( testWidget, 'A', Qt::AltModifier );
+ QTest::qWait( 500 );
+ QVERIFY( click_count == 1 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 1 );
+ QVERIFY( toggle_count == 0 );
+
+ // wait 200 ms because setAccel uses animateClick.
+ // if we don't wait this may screw up a next test.
+ QTest::qWait(200);
+}
+
+void tst_QCommandLinkButton::animateClick()
+{
+ QVERIFY( !testWidget->isDown() );
+ testWidget->animateClick();
+ QVERIFY( testWidget->isDown() );
+ QTest::qWait( 200 );
+ QVERIFY( !testWidget->isDown() );
+
+ QVERIFY( click_count == 1 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 1 );
+ QVERIFY( toggle_count == 0 );
+}
+
+void tst_QCommandLinkButton::clicked()
+{
+ QTest::mousePress( testWidget, Qt::LeftButton );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 0 );
+
+ QTest::mouseRelease( testWidget, Qt::LeftButton );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)1 );
+
+ press_count = 0;
+ release_count = 0;
+ testWidget->setDown(FALSE);
+ for (uint i=0; i<10; i++)
+ QTest::mouseClick( testWidget, Qt::LeftButton );
+ QCOMPARE( press_count, (uint)10 );
+ QCOMPARE( release_count, (uint)10 );
+}
+
+QCommandLinkButton *pb = 0;
+void tst_QCommandLinkButton::helperSlotDelete()
+{
+ delete pb;
+ pb = 0;
+}
+
+void tst_QCommandLinkButton::popupCrash()
+{
+ pb = new QCommandLinkButton("foo", "description");
+ QMenu *menu = new QMenu("bar", pb);
+ pb->setMenu(menu);
+ QTimer::singleShot(1000, this, SLOT(helperSlotDelete()));
+ pb->show();
+ pb->click();
+}
+
+void tst_QCommandLinkButton::defaultAndAutoDefault()
+{
+ {
+ // Adding buttons directly to QDialog
+ QDialog dialog;
+
+ QCommandLinkButton button1(&dialog);
+ QVERIFY(button1.autoDefault());
+ QVERIFY(!button1.isDefault());
+
+ QCommandLinkButton button2(&dialog);
+ QVERIFY(button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ button1.setDefault(true);
+ QVERIFY(button1.autoDefault());
+ QVERIFY(button1.isDefault());
+ QVERIFY(button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ dialog.show();
+ QVERIFY(dialog.isVisible());
+
+ QObject::connect(&button1, SIGNAL(clicked()), &dialog, SLOT(hide()));
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QApplication::sendEvent(&dialog, &event);
+ QVERIFY(!dialog.isVisible());
+ }
+
+ {
+ // Adding buttons to QDialog through a layout
+ QDialog dialog;
+
+ QCommandLinkButton button3;
+ button3.setAutoDefault(false);
+
+ QCommandLinkButton button1;
+ QVERIFY(!button1.autoDefault());
+ QVERIFY(!button1.isDefault());
+
+ QCommandLinkButton button2;
+ QVERIFY(!button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ button1.setDefault(true);
+ QVERIFY(!button1.autoDefault());
+ QVERIFY(button1.isDefault());
+ QVERIFY(!button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ QGridLayout layout;
+ layout.addWidget(&button3, 0, 3);
+ layout.addWidget(&button2, 0, 2);
+ layout.addWidget(&button1, 0, 1);
+ dialog.setLayout(&layout);
+ button3.setFocus();
+ QVERIFY(button1.autoDefault());
+ QVERIFY(button1.isDefault());
+ QVERIFY(button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ dialog.show();
+ QVERIFY(dialog.isVisible());
+
+ QObject::connect(&button1, SIGNAL(clicked()), &dialog, SLOT(hide()));
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QApplication::sendEvent(&dialog, &event);
+ QVERIFY(!dialog.isVisible());
+ }
+
+ {
+ // autoDefault behavior.
+ QDialog dialog;
+ QCommandLinkButton button2(&dialog);
+ QCommandLinkButton button1(&dialog);
+ dialog.show();
+ QVERIFY(dialog.isVisible());
+
+ // No default button is set, and button2 is the first autoDefault button
+ // that is next in the tab order
+ QObject::connect(&button2, SIGNAL(clicked()), &dialog, SLOT(hide()));
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QApplication::sendEvent(&dialog, &event);
+ QVERIFY(!dialog.isVisible());
+
+ // Reparenting
+ QVERIFY(button2.autoDefault());
+ button2.setParent(0);
+ QVERIFY(!button2.autoDefault());
+ button2.setAutoDefault(false);
+ button2.setParent(&dialog);
+ QVERIFY(!button2.autoDefault());
+
+ button1.setAutoDefault(true);
+ button1.setParent(0);
+ QVERIFY(button1.autoDefault());
+ }
+}
+
+void tst_QCommandLinkButton::heightForWithWithIcon()
+{
+ QWidget mainWin;
+
+ QPixmap pixmap(64, 64);
+ {
+ pixmap.fill(Qt::white);
+ QPainter painter(&pixmap);
+ painter.setBrush(Qt::black);
+ painter.drawEllipse(0, 0, 63, 63);
+ }
+
+ QCommandLinkButton *largeIconButton = new QCommandLinkButton(QString("Large Icon"),
+ QString("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris nibh lectus, adipiscing eu."),
+ &mainWin);
+ largeIconButton->setIconSize(QSize(64, 64));
+ largeIconButton->setIcon(pixmap);
+
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->addWidget(largeIconButton);
+ layout->addStretch();
+ mainWin.setLayout(layout);
+ mainWin.showMaximized();
+ QTest::qWaitForWindowShown(&mainWin);
+ QVERIFY(largeIconButton->height() > 68); //enough room for the icon
+
+}
+
+QTEST_MAIN(tst_QCommandLinkButton)
+#include "tst_qcommandlinkbutton.moc"
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/.gitignore b/tests/auto/widgets/widgets/qdatetimeedit/.gitignore
new file mode 100644
index 0000000000..a68e3269d2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdatetimeedit/.gitignore
@@ -0,0 +1 @@
+tst_qdatetimeedit
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/qdatetimeedit.pro b/tests/auto/widgets/widgets/qdatetimeedit/qdatetimeedit.pro
new file mode 100644
index 0000000000..47356d448c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdatetimeedit/qdatetimeedit.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdatetimeedit.cpp
+
+wincewm50smart-msvc2005: DEFINES += WINCE_NO_MODIFIER_KEYS
+
+
+
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
new file mode 100644
index 0000000000..c64c9e7019
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -0,0 +1,3458 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qgroupbox.h>
+#include <qlineedit.h>
+#include <qwindowsstyle.h>
+
+
+
+#include <qdatetimeedit.h>
+#include <qlocale.h>
+#include <qlayout.h>
+#include <qeventloop.h>
+#include <qstyle.h>
+#include <qstyle.h>
+#include <QStyleOptionSpinBox>
+#include <QDate>
+#include <QDateTime>
+#include <QTime>
+#include <QList>
+#include <QDateTimeEdit>
+#include <QCalendarWidget>
+#include <QWidget>
+#include <QLineEdit>
+#include <QObject>
+#include <QLocale>
+#include <QString>
+#include <QVariantList>
+#include <QVariant>
+#include <QApplication>
+#include <QPoint>
+#include <QVBoxLayout>
+#include <QRect>
+#include <QCursor>
+#include <QEventLoop>
+#include <QStyle>
+#include <QStyleOptionComboBox>
+#include <QTimeEdit>
+#include <QMetaType>
+#include <QDebug>
+#include <QWheelEvent>
+#include <QTest>
+#include <QSignalSpy>
+#include <QTestEventList>
+#include <QDateEdit>
+
+#ifdef Q_OS_WIN
+# include <windows.h>
+# undef min
+# undef max
+#endif
+
+
+Q_DECLARE_METATYPE(QDate);
+Q_DECLARE_METATYPE(Qt::Key);
+Q_DECLARE_METATYPE(Qt::KeyboardModifiers);
+Q_DECLARE_METATYPE(Qt::KeyboardModifier);
+Q_DECLARE_METATYPE(QDateTime);
+Q_DECLARE_METATYPE(QTime);
+Q_DECLARE_METATYPE(QList<int>);
+
+#if defined(Q_OS_WINCE)
+bool qt_wince_is_platform(const QString &platformString) {
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
+ sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
+ return true;
+ return false;
+}
+bool qt_wince_is_pocket_pc() {
+ return qt_wince_is_platform(QString::fromLatin1("PocketPC"));
+}
+bool qt_wince_is_smartphone() {
+ return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
+}
+bool qt_wince_is_mobile() {
+ return (qt_wince_is_smartphone() || qt_wince_is_pocket_pc());
+}
+#endif
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class EditorDateEdit : public QDateTimeEdit
+{
+ Q_OBJECT
+public:
+ EditorDateEdit(QWidget *parent = 0) : QDateTimeEdit(parent) {}
+ QLineEdit *lineEdit() { return QDateTimeEdit::lineEdit(); }
+ friend class tst_QDateTimeEdit;
+};
+
+class tst_QDateTimeEdit : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDateTimeEdit();
+ virtual ~tst_QDateTimeEdit();
+public slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+ void cleanupTestCase();
+private slots:
+ void cachedDayTest();
+ void getSetCheck();
+ void constructor_qwidget();
+ void constructor_qdatetime_data();
+ void constructor_qdatetime();
+ void constructor_qdate_data();
+ void constructor_qdate();
+ void constructor_qtime_data();
+ void constructor_qtime();
+
+ void sectionText_data();
+ void sectionText();
+ void dateTimeSignalChecking_data();
+ void dateTimeSignalChecking();
+ void mousePress();
+ void stepHourAMPM_data();
+
+ void stepHourAMPM();
+ void displayedSections_data();
+ void displayedSections();
+ void currentSection_data();
+ void currentSection();
+
+ void setCurrentSection();
+ void setCurrentSection_data();
+
+ void minimumDate_data();
+ void minimumDate();
+ void maximumDate_data();
+ void maximumDate();
+ void clearMinimumDate_data();
+ void clearMinimumDate();
+ void clearMaximumDate_data();
+ void clearMaximumDate();
+
+ void minimumDateTime_data();
+ void minimumDateTime();
+ void maximumDateTime_data();
+ void maximumDateTime();
+
+ void clearMinimumDateTime_data();
+ void clearMinimumDateTime();
+ void clearMaximumDateTime_data();
+ void clearMaximumDateTime();
+
+ void displayFormat_data();
+ void displayFormat();
+
+ void specialValueText();
+ void setRange_data();
+ void setRange();
+
+ void selectAndScrollWithKeys();
+ void backspaceKey();
+ void deleteKey();
+ void tabKeyNavigation();
+ void tabKeyNavigationWithPrefix();
+ void tabKeyNavigationWithSuffix();
+ void enterKey();
+
+ void readOnly();
+
+ void wrappingDate_data();
+ void wrappingDate();
+
+ void dateSignalChecking_data();
+ void dateSignalChecking();
+
+ void wrappingTime_data();
+ void wrappingTime();
+
+ void userKeyPress_Time_data();
+ void userKeyPress_Time();
+
+ void timeSignalChecking_data();
+ void timeSignalChecking();
+
+ void weirdCase();
+ void newCase();
+ void newCase2();
+ void newCase3();
+ void newCase4();
+ void newCase5();
+ void newCase6();
+
+ void task98554();
+ void task149097();
+
+ void cursorPos();
+ void calendarPopup();
+
+ void hour12Test();
+ void yyTest();
+ void task108572();
+
+ void task148725();
+ void task148522();
+
+ void setSelectedSection();
+ void reverseTest();
+
+ void ddMMMMyyyy();
+ void wheelEvent();
+
+ void specialValueCornerCase();
+ void cursorPositionOnInit();
+
+ void task118867();
+
+ void nextPrevSection_data();
+ void nextPrevSection();
+
+ void dateEditTimeEditFormats();
+ void timeSpec_data();
+ void timeSpec();
+ void timeSpecBug();
+
+ void monthEdgeCase();
+ void setLocale();
+
+ void potentialYYValueBug();
+ void textSectionAtEnd();
+
+ void keypadAutoAdvance_data();
+ void keypadAutoAdvance();
+
+ void task196924();
+ void focusNextPrevChild();
+
+ void taskQTBUG_12384_timeSpecShowTimeOnly();
+
+ void deleteCalendarWidget();
+
+private:
+ EditorDateEdit* testWidget;
+ QWidget *testFocusWidget;
+};
+
+typedef QList<QTime> TimeList;
+typedef QList<Qt::Key> KeyList;
+
+Q_DECLARE_METATYPE(TimeList)
+Q_DECLARE_METATYPE(KeyList)
+
+// Testing get/set functions
+void tst_QDateTimeEdit::getSetCheck()
+{
+ QDateTimeEdit obj1;
+ obj1.setDisplayFormat("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z AP");
+ // Section QDateTimeEdit::currentSection()
+ // void QDateTimeEdit::setCurrentSection(Section)
+ obj1.setCurrentSection(QDateTimeEdit::NoSection);
+ QVERIFY(obj1.currentSection() != QDateTimeEdit::NoSection);
+ obj1.setCurrentSection(QDateTimeEdit::AmPmSection);
+ QCOMPARE(QDateTimeEdit::AmPmSection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::MSecSection);
+ QCOMPARE(QDateTimeEdit::MSecSection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::SecondSection);
+ QCOMPARE(QDateTimeEdit::SecondSection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::MinuteSection);
+ QCOMPARE(QDateTimeEdit::MinuteSection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::HourSection);
+ QCOMPARE(QDateTimeEdit::HourSection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::DaySection);
+ QCOMPARE(QDateTimeEdit::DaySection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::MonthSection);
+ QCOMPARE(QDateTimeEdit::MonthSection, obj1.currentSection());
+ obj1.setCurrentSection(QDateTimeEdit::YearSection);
+ QCOMPARE(QDateTimeEdit::YearSection, obj1.currentSection());
+}
+
+tst_QDateTimeEdit::tst_QDateTimeEdit()
+{
+ qRegisterMetaType<QDate>("QDate");
+ qRegisterMetaType<QTime>("QTime");
+ qRegisterMetaType<QDateTime>("QDateTime");
+ qRegisterMetaType<QList<int> >("QList<int>");
+}
+
+tst_QDateTimeEdit::~tst_QDateTimeEdit()
+{
+
+}
+
+void tst_QDateTimeEdit::initTestCase()
+{
+ QLocale system = QLocale::system();
+ if (system.language() != QLocale::C && system.language() != QLocale::English)
+ qWarning("Running under locale %s/%s -- this test may generate failures due to language differences",
+ qPrintable(QLocale::languageToString(system.language())),
+ qPrintable(QLocale::countryToString(system.country())));
+ testWidget = new EditorDateEdit(0);
+ testFocusWidget = new QWidget(0);
+ testFocusWidget->resize(200, 100);
+ testFocusWidget->show();
+}
+
+void tst_QDateTimeEdit::cleanupTestCase()
+{
+ delete testFocusWidget;
+ testFocusWidget = 0;
+ delete testWidget;
+ testWidget = 0;
+}
+
+
+void tst_QDateTimeEdit::init()
+{
+ QLocale::setDefault(QLocale(QLocale::C));
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
+#endif
+ testWidget->setDisplayFormat("dd/MM/yyyy"); // Nice default to have
+ testWidget->setDateTime(QDateTime(QDate(2000, 1, 1), QTime(0, 0)));
+ testWidget->show();
+ testFocusWidget->move(-1000, -1000);
+}
+
+void tst_QDateTimeEdit::cleanup()
+{
+ testWidget->clearMinimumDateTime();
+ testWidget->clearMaximumDateTime();
+ testWidget->setTimeSpec(Qt::LocalTime);
+ testWidget->setSpecialValueText(QString());
+ testWidget->setWrapping(false);
+}
+
+void tst_QDateTimeEdit::constructor_qwidget()
+{
+ testWidget->hide();
+ QDateTimeEdit dte(0);
+ dte.show();
+ QCOMPARE(dte.dateTime(), QDateTime(QDate(2000, 1, 1), QTime(0, 0, 0, 0)));
+ QCOMPARE(dte.minimumDate(), QDate(1752, 9, 14));
+ QCOMPARE(dte.minimumTime(), QTime(0, 0, 0, 0));
+ QCOMPARE(dte.maximumDate(), QDate(7999, 12, 31));
+ QCOMPARE(dte.maximumTime(), QTime(23, 59, 59, 999));
+}
+
+void tst_QDateTimeEdit::constructor_qdatetime_data()
+{
+ QTest::addColumn<QDateTime>("parameter");
+ QTest::addColumn<QDateTime>("displayDateTime");
+ QTest::addColumn<QDate>("minimumDate");
+ QTest::addColumn<QTime>("minimumTime");
+ QTest::addColumn<QDate>("maximumDate");
+ QTest::addColumn<QTime>("maximumTime");
+
+ QTest::newRow("normal") << QDateTime(QDate(2004, 6, 16), QTime(13, 46, 32, 764))
+ << QDateTime(QDate(2004, 6, 16), QTime(13, 46, 32, 764))
+ << QDate(1752, 9, 14) << QTime(0, 0, 0, 0)
+ << QDate(7999, 12, 31) << QTime(23, 59, 59, 999);
+
+ QTest::newRow("invalid") << QDateTime(QDate(9999, 99, 99), QTime(13, 46, 32, 764))
+ << QDateTime(QDate(2000, 1, 1), QTime(0, 0, 0, 0))
+ << QDate(1752, 9, 14) << QTime(0, 0, 0, 0)
+ << QDate(7999, 12, 31) << QTime(23, 59, 59, 999);
+}
+
+
+
+void tst_QDateTimeEdit::constructor_qdatetime()
+{
+ QFETCH(QDateTime, parameter);
+ QFETCH(QDateTime, displayDateTime);
+ QFETCH(QDate, minimumDate);
+ QFETCH(QTime, minimumTime);
+ QFETCH(QDate, maximumDate);
+ QFETCH(QTime, maximumTime);
+
+ testWidget->hide();
+
+ QDateTimeEdit dte(parameter);
+ dte.show();
+ QCOMPARE(dte.dateTime(), displayDateTime);
+ QCOMPARE(dte.minimumDate(), minimumDate);
+ QCOMPARE(dte.minimumTime(), minimumTime);
+ QCOMPARE(dte.maximumDate(), maximumDate);
+ QCOMPARE(dte.maximumTime(), maximumTime);
+}
+
+void tst_QDateTimeEdit::constructor_qdate_data()
+{
+ QTest::addColumn<QDate>("parameter");
+ QTest::addColumn<QDateTime>("displayDateTime");
+ QTest::addColumn<QDate>("minimumDate");
+ QTest::addColumn<QTime>("minimumTime");
+ QTest::addColumn<QDate>("maximumDate");
+ QTest::addColumn<QTime>("maximumTime");
+
+ QTest::newRow("normal") << QDate(2004, 6, 16)
+ << QDateTime(QDate(2004, 6, 16), QTime(0, 0, 0, 0))
+ << QDate(1752, 9, 14) << QTime(0, 0, 0, 0)
+ << QDate(7999, 12, 31) << QTime(23, 59, 59, 999);
+
+ QTest::newRow("invalid") << QDate(9999, 99, 99)
+ << QDateTime(QDate(2000, 1, 1), QTime(0, 0, 0, 0))
+ << QDate(1752, 9, 14) << QTime(0, 0, 0, 0)
+ << QDate(7999, 12, 31) << QTime(23, 59, 59, 999);
+}
+
+
+
+void tst_QDateTimeEdit::constructor_qdate()
+{
+ QFETCH(QDate, parameter);
+ QFETCH(QDateTime, displayDateTime);
+ QFETCH(QDate, minimumDate);
+ QFETCH(QTime, minimumTime);
+ QFETCH(QDate, maximumDate);
+ QFETCH(QTime, maximumTime);
+
+ testWidget->hide();
+
+ QDateTimeEdit dte(parameter);
+ dte.show();
+ QCOMPARE(dte.dateTime(), displayDateTime);
+ QCOMPARE(dte.minimumDate(), minimumDate);
+ QCOMPARE(dte.minimumTime(), minimumTime);
+ QCOMPARE(dte.maximumDate(), maximumDate);
+ QCOMPARE(dte.maximumTime(), maximumTime);
+}
+
+void tst_QDateTimeEdit::constructor_qtime_data()
+{
+ QTest::addColumn<QTime>("parameter");
+ QTest::addColumn<QDateTime>("displayDateTime");
+ QTest::addColumn<QDate>("minimumDate");
+ QTest::addColumn<QTime>("minimumTime");
+ QTest::addColumn<QDate>("maximumDate");
+ QTest::addColumn<QTime>("maximumTime");
+
+ QTest::newRow("normal") << QTime(13, 46, 32, 764)
+ << QDateTime(QDate(2000, 1, 1), QTime(13, 46, 32, 764))
+ << QDate(2000, 1, 1) << QTime(0, 0, 0, 0)
+ << QDate(2000, 1, 1) << QTime(23, 59, 59, 999);
+
+ QTest::newRow("invalid") << QTime(99, 99, 99, 5000)
+ << QDateTime(QDate(2000, 1, 1), QTime(0, 0, 0, 0))
+ << QDate(2000, 1, 1) << QTime(0, 0, 0, 0)
+ << QDate(2000, 1, 1) << QTime(23, 59, 59, 999);
+}
+
+
+
+void tst_QDateTimeEdit::constructor_qtime()
+{
+ QFETCH(QTime, parameter);
+ QFETCH(QDateTime, displayDateTime);
+ QFETCH(QDate, minimumDate);
+ QFETCH(QTime, minimumTime);
+ QFETCH(QDate, maximumDate);
+ QFETCH(QTime, maximumTime);
+
+ testWidget->hide();
+
+ QDateTimeEdit dte(parameter);
+ dte.show();
+ QCOMPARE(dte.dateTime(), displayDateTime);
+ QCOMPARE(dte.minimumDate(), minimumDate);
+ QCOMPARE(dte.minimumTime(), minimumTime);
+ QCOMPARE(dte.maximumDate(), maximumDate);
+ QCOMPARE(dte.maximumTime(), maximumTime);
+}
+
+void tst_QDateTimeEdit::minimumDate_data()
+{
+ QTest::addColumn<QDate>("minimumDate");
+ QTest::addColumn<QDate>("expectedMinDate");
+
+ QTest::newRow("normal-0") << QDate(2004, 5, 10) << QDate(2004, 5, 10);
+ QTest::newRow("normal-1") << QDate(2002, 3, 15) << QDate(2002, 3, 15);
+ QTest::newRow("normal-2") << QDate(7999, 12, 31) << QDate(7999, 12, 31);
+ QTest::newRow("normal-3") << QDate(1753, 1, 1) << QDate(1753, 1, 1);
+ QTest::newRow("invalid-0") << QDate(0, 0, 0) << QDate(1752, 9, 14);
+ QTest::newRow("old") << QDate(1492, 8, 3) << QDate(1492, 8, 3);
+}
+
+void tst_QDateTimeEdit::minimumDate()
+{
+ QFETCH(QDate, minimumDate);
+ QFETCH(QDate, expectedMinDate);
+
+ testWidget->setMinimumDate(minimumDate);
+ QCOMPARE(testWidget->minimumDate(), expectedMinDate);
+}
+
+void tst_QDateTimeEdit::minimumDateTime_data()
+{
+ QTest::addColumn<QDateTime>("minimumDateTime");
+ QTest::addColumn<QDateTime>("expectedMinDateTime");
+
+ QTest::newRow("normal-0") << QDateTime(QDate(2004, 5, 10), QTime(2, 3, 14))
+ << QDateTime(QDate(2004, 5, 10), QTime(2, 3, 14));
+
+ QTest::newRow("normal-1") << QDateTime(QDate(2005, 5, 10), QTime(22, 33, 1))
+ << QDateTime(QDate(2005, 5, 10), QTime(22, 33, 1));
+ QTest::newRow("normal-2") << QDateTime(QDate(2006, 5, 10), QTime(13, 31, 23))
+ << QDateTime(QDate(2006, 5, 10), QTime(13, 31, 23));
+ QTest::newRow("normal-3") << QDateTime(QDate(2007, 5, 10), QTime(22, 23, 23))
+ << QDateTime(QDate(2007, 5, 10), QTime(22, 23, 23));
+ QTest::newRow("normal-4") << QDateTime(QDate(2008, 5, 10), QTime(2, 3, 1))
+ << QDateTime(QDate(2008, 5, 10), QTime(2, 3, 1));
+ QTest::newRow("invalid-0") << QDateTime() << QDateTime(QDate(1752, 9, 14), QTime(0, 0, 0));
+ QTest::newRow("old") << QDateTime(QDate(1492, 8, 3), QTime(2, 3, 1))
+ << QDateTime(QDate(1492, 8, 3), QTime(2, 3, 1));
+}
+
+void tst_QDateTimeEdit::minimumDateTime()
+{
+ QFETCH(QDateTime, minimumDateTime);
+ QFETCH(QDateTime, expectedMinDateTime);
+
+ testWidget->setMinimumDateTime(minimumDateTime);
+ QCOMPARE(testWidget->minimumDateTime(), expectedMinDateTime);
+}
+
+
+void tst_QDateTimeEdit::maximumDateTime_data()
+{
+ QTest::addColumn<QDateTime>("maximumDateTime");
+ QTest::addColumn<QDateTime>("expectedMinDateTime");
+
+ QTest::newRow("normal-0") << QDateTime(QDate(2004, 5, 10), QTime(2, 3, 14))
+ << QDateTime(QDate(2004, 5, 10), QTime(2, 3, 14));
+
+ QTest::newRow("normal-1") << QDateTime(QDate(2005, 5, 10), QTime(22, 33, 1))
+ << QDateTime(QDate(2005, 5, 10), QTime(22, 33, 1));
+ QTest::newRow("normal-2") << QDateTime(QDate(2006, 5, 10), QTime(13, 31, 23))
+ << QDateTime(QDate(2006, 5, 10), QTime(13, 31, 23));
+ QTest::newRow("normal-3") << QDateTime(QDate(2007, 5, 10), QTime(22, 23, 23))
+ << QDateTime(QDate(2007, 5, 10), QTime(22, 23, 23));
+ QTest::newRow("normal-4") << QDateTime(QDate(2008, 5, 10), QTime(2, 3, 1))
+ << QDateTime(QDate(2008, 5, 10), QTime(2, 3, 1));
+ QTest::newRow("invalid-0") << QDateTime() << QDateTime(QDate(7999, 12, 31), QTime(23, 59, 59, 999));
+}
+
+void tst_QDateTimeEdit::maximumDateTime()
+{
+ QFETCH(QDateTime, maximumDateTime);
+ QFETCH(QDateTime, expectedMinDateTime);
+
+ testWidget->setMaximumDateTime(maximumDateTime);
+ QCOMPARE(testWidget->maximumDateTime(), expectedMinDateTime);
+}
+
+void tst_QDateTimeEdit::maximumDate_data()
+{
+ QTest::addColumn<QDate>("maximumDate");
+ QTest::addColumn<QDate>("expectedMaxDate");
+
+ QTest::newRow("normal-0") << QDate(2004, 05, 10) << QDate(2004, 5, 10);
+ QTest::newRow("normal-1") << QDate(2002, 03, 15) << QDate(2002, 3, 15);
+ QTest::newRow("normal-2") << QDate(7999, 12, 31) << QDate(7999, 12, 31);
+ QTest::newRow("normal-3") << QDate(1753, 1, 1) << QDate(1753, 1, 1);
+ QTest::newRow("invalid-0") << QDate(0, 0, 0) << QDate(7999, 12, 31);
+}
+
+void tst_QDateTimeEdit::maximumDate()
+{
+ QFETCH(QDate, maximumDate);
+ QFETCH(QDate, expectedMaxDate);
+
+ testWidget->setMaximumDate(maximumDate);
+ QCOMPARE(testWidget->maximumDate(), expectedMaxDate);
+}
+
+void tst_QDateTimeEdit::clearMinimumDate_data()
+{
+ QTest::addColumn<QDate>("minimumDate");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QDate>("expectedMinDateAfterClear");
+
+ QTest::newRow("normal-0") << QDate(2004, 05, 10) << true << QDate(1752, 9, 14);
+ QTest::newRow("normal-1") << QDate(2002, 3, 15) << true << QDate(1752, 9, 14);
+ QTest::newRow("normal-2") << QDate(7999, 12, 31) << true << QDate(1752, 9, 14);
+ QTest::newRow("normal-3") << QDate(1753, 1, 1) << true << QDate(1752, 9, 14);
+ QTest::newRow("invalid-0") << QDate(0, 0, 0) << false << QDate(1752, 9, 14);
+}
+
+void tst_QDateTimeEdit::clearMinimumDate()
+{
+ QFETCH(QDate, minimumDate);
+ QFETCH(bool, valid);
+ QFETCH(QDate, expectedMinDateAfterClear);
+
+ testWidget->setMinimumDate(minimumDate);
+ if (valid) {
+ QCOMPARE(testWidget->minimumDate(), minimumDate);
+ }
+ testWidget->clearMinimumDate();
+ QCOMPARE(testWidget->minimumDate(), expectedMinDateAfterClear);
+}
+
+void tst_QDateTimeEdit::clearMinimumDateTime_data()
+{
+ QTest::addColumn<QDateTime>("minimumDateTime");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QDateTime>("expectedMinDateTimeAfterClear");
+
+ QTest::newRow("normal-0") << QDateTime(QDate(2004, 05, 10), QTime(12, 12, 12))
+ << true << QDateTime(QDate(1752, 9, 14), QTime(0, 0));
+ QTest::newRow("normal-1") << QDateTime(QDate(2002, 3, 15), QTime(13, 13, 13))
+ << true << QDateTime(QDate(1752, 9, 14), QTime(0, 0));
+ QTest::newRow("normal-2") << QDateTime(QDate(7999, 12, 31), QTime(14, 14, 14))
+ << true << QDateTime(QDate(1752, 9, 14), QTime(0, 0));
+ QTest::newRow("normal-3") << QDateTime(QDate(1753, 1, 1), QTime(15, 15, 15))
+ << true << QDateTime(QDate(1752, 9, 14), QTime(0, 0));
+ QTest::newRow("invalid-0") << QDateTime() << false << QDateTime(QDate(1752, 9, 14), QTime(0, 0));
+ QTest::newRow("old") << QDateTime(QDate(1492, 8, 3), QTime(2, 3, 1)) << true
+ << QDateTime(QDate(1752, 9, 14), QTime(0, 0));
+
+}
+
+void tst_QDateTimeEdit::clearMinimumDateTime()
+{
+ QFETCH(QDateTime, minimumDateTime);
+ QFETCH(bool, valid);
+ QFETCH(QDateTime, expectedMinDateTimeAfterClear);
+
+ testWidget->setMinimumDateTime(minimumDateTime);
+ if (valid) {
+ QCOMPARE(testWidget->minimumDateTime(), minimumDateTime);
+ }
+ testWidget->clearMinimumDateTime();
+ QCOMPARE(testWidget->minimumDateTime(), expectedMinDateTimeAfterClear);
+}
+
+
+void tst_QDateTimeEdit::clearMaximumDateTime_data()
+{
+ QTest::addColumn<QDateTime>("maximumDateTime");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QDateTime>("expectedMinDateTimeAfterClear");
+
+ QTest::newRow("normal-0") << QDateTime(QDate(2004, 05, 10), QTime(12, 12, 12))
+ << true << QDateTime(QDate(7999, 12, 31), QTime(23, 59, 59, 999));
+ QTest::newRow("normal-1") << QDateTime(QDate(2002, 3, 15), QTime(13, 13, 13))
+ << true << QDateTime(QDate(7999, 12, 31), QTime(23, 59, 59, 999));
+ QTest::newRow("normal-2") << QDateTime(QDate(7999, 12, 31), QTime(14, 14, 14))
+ << true << QDateTime(QDate(7999, 12, 31), QTime(23, 59, 59, 999));
+ QTest::newRow("normal-3") << QDateTime(QDate(1753, 1, 1), QTime(15, 15, 15))
+ << true << QDateTime(QDate(7999, 12, 31), QTime(23, 59, 59, 999));
+ QTest::newRow("invalid-0") << QDateTime()
+ << false << QDateTime(QDate(7999, 12, 31), QTime(23, 59, 59, 999));
+}
+
+void tst_QDateTimeEdit::clearMaximumDateTime()
+{
+ QFETCH(QDateTime, maximumDateTime);
+ QFETCH(bool, valid);
+ QFETCH(QDateTime, expectedMinDateTimeAfterClear);
+
+ testWidget->setMaximumDateTime(maximumDateTime);
+ if (valid) {
+ QCOMPARE(testWidget->maximumDateTime(), maximumDateTime);
+ }
+ testWidget->clearMaximumDateTime();
+ QCOMPARE(testWidget->maximumDateTime(), expectedMinDateTimeAfterClear);
+}
+
+
+void tst_QDateTimeEdit::clearMaximumDate_data()
+{
+ QTest::addColumn<QDate>("maximumDate");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QDate>("expectedMaxDateAfterClear");
+
+ QTest::newRow("normal-0") << QDate(2004, 05, 10) << true << QDate(7999, 12, 31);
+ QTest::newRow("normal-1") << QDate(2002, 03, 15) << true << QDate(7999, 12, 31);
+ QTest::newRow("normal-2") << QDate(7999, 12, 31) << true << QDate(7999, 12, 31);
+ QTest::newRow("normal-3") << QDate(2000, 1, 1) << true << QDate(7999, 12, 31);
+ QTest::newRow("invalid-0") << QDate(0, 0, 0) << false << QDate(7999, 12, 31);
+}
+
+void tst_QDateTimeEdit::clearMaximumDate()
+{
+ QFETCH(QDate, maximumDate);
+ QFETCH(bool, valid);
+ QFETCH(QDate, expectedMaxDateAfterClear);
+
+ testWidget->setMaximumDate(maximumDate);
+ if (valid) {
+ QCOMPARE(testWidget->maximumDate(), maximumDate);
+ }
+ testWidget->clearMaximumDate();
+ QCOMPARE(testWidget->maximumDate(), expectedMaxDateAfterClear);
+}
+
+void tst_QDateTimeEdit::displayFormat_data()
+{
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QDateTime>("date");
+
+ const QDateTime dt(QDate(2999, 12, 31), QTime(3, 59, 59, 999));
+
+ QTest::newRow("valid-0") << QString("yyyy MM dd") << true << QString("2999 12 31") << dt;
+ QTest::newRow("valid-1") << QString("dd MM yyyy::ss:mm:hh") << true
+ << QString("31 12 2999::59:59:03") << dt;
+ QTest::newRow("valid-2") << QString("hh-dd-mm-MM-yy") << true << QString("03-31-59-12-99") << dt;
+ QTest::newRow("valid-3") << QString("ddd MM d yyyy::ss:mm:hh") << true
+ << QDate::shortDayName(2) + " 12 31 2999::59:59:03" << dt;
+ QTest::newRow("valid-4") << QString("hh-dd-mm-MM-yyyy") << true << QString("03-31-59-12-2999") << dt;
+ QTest::newRow("invalid-0") << QString("yyyy.MM.yy") << true << QString("2999.12.99") << dt;
+ QTest::newRow("invalid-1") << QString("y") << false << QString() << dt;
+ QTest::newRow("invalid-2") << QString("") << false << QString() << dt;
+ QTest::newRow("quoted-1") << QString("'Midday is at:' dd") << true << QString("Midday is at: 31") << dt;
+ QTest::newRow("leading1") << QString("h:hh:hhh") << true << QString("3:03:033") << dt;
+ QTest::newRow("H1") << QString("HH:hh:ap") << true << QString("03:03:am") << dt;
+ QTest::newRow("H2") << QString("HH:hh:ap") << true << QString("23:11:pm")
+ << QDateTime(dt.date(), QTime(23, 0, 0));
+}
+
+void tst_QDateTimeEdit::displayFormat()
+{
+ QFETCH(QString, format);
+ QFETCH(bool, valid);
+ QFETCH(QString, text);
+ QFETCH(QDateTime, date);
+
+ testWidget->setDateTime(date);
+
+ QString compareFormat = format;
+ if (!valid)
+ compareFormat = testWidget->displayFormat();
+ testWidget->setDisplayFormat(format);
+ QCOMPARE(testWidget->displayFormat(), compareFormat);
+ if (valid)
+ QCOMPARE(testWidget->text(), text);
+}
+
+void tst_QDateTimeEdit::selectAndScrollWithKeys()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 05, 11));
+ testWidget->setDisplayFormat("dd/MM/yyyy");
+ testWidget->show();
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("1"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/0"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/2"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/20"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/200"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/2004"));
+
+ // Now the year part should be selected
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2005, 5, 11));
+ QCOMPARE(testWidget->currentSection(), QDateTimeEdit::YearSection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2005"));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2004, 5, 11));
+ QCOMPARE(testWidget->currentSection(), QDateTimeEdit::YearSection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2004"));
+
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("4"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("04"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("5/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("1/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11/05/2004"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+
+ // Now the day part should be selected
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2004, 5, 12));
+ QCOMPARE(testWidget->currentSection(), QDateTimeEdit::DaySection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("12"));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2004, 5, 11));
+ QCOMPARE(testWidget->currentSection(), QDateTimeEdit::DaySection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+ // Now the day part should be selected
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2004, 05, 12));
+}
+
+void tst_QDateTimeEdit::backspaceKey()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 05, 11));
+ testWidget->setDisplayFormat("d/MM/yyyy");
+ testWidget->show();
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QCOMPARE(testWidget->text(), QString("11/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/200"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/20"));
+ // Check that moving into another field reverts it
+ for (int i=0;i<3;i++)
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QCOMPARE(testWidget->text(), QString("11/05/2004"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ for (int i=0;i<4;i++) {
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ }
+
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/"));
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/0/2004"));
+ testWidget->interpretText();
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/200"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/20"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/2"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/05/"));
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11/0/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("11//2004"));
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("1/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->text(), QString("1/05/2004"));
+}
+
+void tst_QDateTimeEdit::deleteKey()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 05, 11));
+ testWidget->setDisplayFormat("d/MM/yyyy");
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QCOMPARE(testWidget->text(), QString("1/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QCOMPARE(testWidget->text(), QString("/05/2004"));
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QCOMPARE(testWidget->text(), QString("1/05/2004"));
+}
+
+void tst_QDateTimeEdit::tabKeyNavigation()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 05, 11));
+ testWidget->setDisplayFormat("dd/MM/yyyy");
+ testWidget->show();
+ testWidget->setCurrentSection(QDateTimeEdit::DaySection);
+
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05"));
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2004"));
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05"));
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+}
+
+void tst_QDateTimeEdit::tabKeyNavigationWithPrefix()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 05, 11));
+ testWidget->setDisplayFormat("prefix dd/MM/yyyy");
+
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05"));
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2004"));
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05"));
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+}
+
+void tst_QDateTimeEdit::tabKeyNavigationWithSuffix()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 05, 11));
+ testWidget->setDisplayFormat("dd/MM/yyyy 'suffix'");
+
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05"));
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2004"));
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("05"));
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+}
+
+
+void tst_QDateTimeEdit::enterKey()
+{
+ qApp->setActiveWindow(testWidget);
+ testWidget->setDate(QDate(2004, 5, 11));
+ testWidget->setDisplayFormat("prefix d/MM/yyyy 'suffix'");
+ testWidget->lineEdit()->setFocus();
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QVERIFY(!testWidget->lineEdit()->hasSelectedText());
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QVERIFY(!testWidget->lineEdit()->hasSelectedText());
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+ QTest::keyClick(testWidget, Qt::Key_1);
+ QTest::keyClick(testWidget, Qt::Key_5);
+
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("15"));
+ QCOMPARE(testWidget->date(), QDate(2004, 5, 15));
+
+ QTest::keyClick(testWidget, Qt::Key_9);
+ QTest::keyClick(testWidget, Qt::Key_Tab, Qt::ShiftModifier);
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("9"));
+ QCOMPARE(testWidget->date(), QDate(2004, 5, 9));
+
+ QTest::keyClick(testWidget, Qt::Key_0);
+ QTest::keyClick(testWidget, Qt::Key_0);
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("9"));
+ QCOMPARE(testWidget->date(), QDate(2004, 5, 9));
+
+ QSignalSpy enterSpy(testWidget, SIGNAL(dateChanged(const QDate &)));
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(enterSpy.count(), 1);
+
+#if 0
+ QVariantList list = enterSpy.takeFirst();
+ QCOMPARE(list.at(0).toDate(), QDate(2004, 9, 15));
+#endif
+
+}
+
+void tst_QDateTimeEdit::specialValueText()
+{
+ testWidget->setDisplayFormat("dd/MM/yyyy");
+ testWidget->setDateRange(QDate(2000, 1, 1), QDate(2001, 1, 1));
+ testWidget->setDate(QDate(2000, 1, 2));
+ testWidget->setSpecialValueText("fOo");
+ testWidget->setCurrentSection(QDateTimeEdit::DaySection);
+ QCOMPARE(testWidget->date(), QDate(2000, 1, 2));
+ QCOMPARE(testWidget->text(), QString("02/01/2000"));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2000, 1, 1));
+ QCOMPARE(testWidget->text(), QString("fOo"));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2000, 1, 1));
+ QCOMPARE(testWidget->text(), QString("fOo"));
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2000, 1, 2));
+ QCOMPARE(testWidget->text(), QString("02/01/2000"));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2000, 1, 1));
+ QCOMPARE(testWidget->text(), QString("fOo"));
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2000, 1, 2));
+ QCOMPARE(testWidget->text(), QString("02/01/2000"));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->text(), QString("fOo"));
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("fO"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString("f"));
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString());
+ QTest::keyClick(testWidget, Qt::Key_F);
+ QCOMPARE(testWidget->text(), QString("f"));
+ QTest::keyClick(testWidget, Qt::Key_O); // will automatically uppercase
+ QCOMPARE(testWidget->text(), QString("fO"));
+ QTest::keyClick(testWidget, Qt::Key_O);
+ QCOMPARE(testWidget->text(), QString("fOo"));
+}
+
+
+void tst_QDateTimeEdit::setRange_data()
+{
+ QTest::addColumn<QTime>("minTime");
+ QTest::addColumn<QTime>("maxTime");
+ QTest::addColumn<QDate>("minDate");
+ QTest::addColumn<QDate>("maxDate");
+ QTest::addColumn<QDateTime>("expectedMin");
+ QTest::addColumn<QDateTime>("expectedMax");
+
+ const QDate cdt = QDate::currentDate();
+
+ QTest::newRow("data0") << QTime(0, 0) << QTime(14, 12, 0)
+ << cdt << cdt
+ << QDateTime(cdt, QTime(0, 0))
+ << QDateTime(cdt, QTime(14, 12, 0));
+
+ QTest::newRow("data1") << QTime(10, 0) << QTime(1, 12, 0) << cdt.addDays(-1)
+ << cdt
+ << QDateTime(cdt.addDays(-1), QTime(10, 0))
+ << QDateTime(cdt, QTime(1, 12, 0));
+}
+
+void tst_QDateTimeEdit::setRange()
+{
+ QFETCH(QTime, minTime);
+ QFETCH(QTime, maxTime);
+ QFETCH(QDate, minDate);
+ QFETCH(QDate, maxDate);
+ QFETCH(QDateTime, expectedMin);
+ QFETCH(QDateTime, expectedMax);
+ testWidget->hide();
+
+ {
+ QDateTimeEdit dte(0);
+ dte.setTimeRange(minTime, maxTime);
+ QCOMPARE(dte.minimumTime(), expectedMin.time());
+ QCOMPARE(dte.maximumTime(), expectedMax.time());
+ dte.setDateRange(minDate, maxDate);
+ QCOMPARE(dte.minimumDate(), expectedMin.date());
+ QCOMPARE(dte.minimumDateTime(), expectedMin);
+ QCOMPARE(dte.maximumDate(), expectedMax.date());
+ QCOMPARE(dte.maximumDateTime(), expectedMax);
+ QCOMPARE(dte.minimumTime(), expectedMin.time());
+ QCOMPARE(dte.maximumTime(), expectedMax.time());
+ dte.setDateTimeRange(QDateTime(minDate, minTime), QDateTime(maxDate, maxTime));
+ QCOMPARE(dte.minimumDate(), expectedMin.date());
+ QCOMPARE(dte.minimumDateTime(), expectedMin);
+ QCOMPARE(dte.maximumDate(), expectedMax.date());
+ QCOMPARE(dte.maximumDateTime(), expectedMax);
+ QCOMPARE(dte.minimumTime(), expectedMin.time());
+ QCOMPARE(dte.maximumTime(), expectedMax.time());
+ }
+ {
+
+ QDateTimeEdit dte2(0);
+ dte2.setDateRange(minDate, maxDate);
+ dte2.setTimeRange(minTime, maxTime);
+
+ QCOMPARE(dte2.minimumDate(), expectedMin.date());
+ QCOMPARE(dte2.maximumDate(), expectedMax.date());
+ QCOMPARE(dte2.minimumTime(), expectedMin.time());
+ QCOMPARE(dte2.maximumTime(), expectedMax.time());
+ }
+
+ {
+ QDateTimeEdit dte3(0);
+ dte3.setMinimumTime(minTime);
+ dte3.setMaximumTime(maxTime);
+ dte3.setMinimumDate(minDate);
+ dte3.setMaximumDate(maxDate);
+
+ QCOMPARE(dte3.minimumDate(), expectedMin.date());
+ QCOMPARE(dte3.maximumDate(), expectedMax.date());
+ QCOMPARE(dte3.minimumTime(), expectedMin.time());
+ QCOMPARE(dte3.maximumTime(), expectedMax.time());
+ }
+
+ {
+ QDateTimeEdit dte4(0);
+ dte4.setMinimumDate(minDate);
+ dte4.setMaximumDate(maxDate);
+ dte4.setMinimumTime(minTime);
+ dte4.setMaximumTime(maxTime);
+
+ QCOMPARE(dte4.minimumDate(), expectedMin.date());
+ QCOMPARE(dte4.maximumDate(), expectedMax.date());
+ QCOMPARE(dte4.minimumTime(), expectedMin.time());
+ QCOMPARE(dte4.maximumTime(), expectedMax.time());
+ }
+}
+
+void tst_QDateTimeEdit::wrappingTime_data()
+{
+ QTest::addColumn<bool>("startWithMin");
+ QTest::addColumn<QTime>("minimumTime");
+ QTest::addColumn<QTime>("maximumTime");
+ QTest::addColumn<uint>("section");
+ QTest::addColumn<QTime>("newTime");
+
+ QTest::newRow("data0") << false << QTime(0,0,0) << QTime(2,2,2) << (uint)QDateTimeEdit::HourSection
+ << QTime(0,2,2);
+ QTest::newRow("data1") << true << QTime(0,0,0) << QTime(2,2,2) << (uint)QDateTimeEdit::HourSection
+ << QTime(2,0,0);
+ QTest::newRow("data2") << false << QTime(0,0,0) << QTime(2,2,2) << (uint)QDateTimeEdit::MinuteSection
+ << QTime(2,0,2);
+ QTest::newRow("data3") << true << QTime(0,0,0) << QTime(2,2,2) << (uint)QDateTimeEdit::MinuteSection
+ << QTime(0,59,0);
+ QTest::newRow("data4") << false << QTime(0,0,0) << QTime(2,2,2) << (uint)QDateTimeEdit::SecondSection
+ << QTime(2,2,0);
+ QTest::newRow("data5") << true << QTime(0,0,0) << QTime(2,2,2) << (uint)QDateTimeEdit::SecondSection
+ << QTime(0,0,59);
+ QTest::newRow("data6") << false << QTime(1,1,1) << QTime(22,22,22) << (uint)QDateTimeEdit::HourSection
+ << QTime(1,22,22);
+ QTest::newRow("data7") << true << QTime(1,1,1) << QTime(22,22,22) << (uint)QDateTimeEdit::HourSection
+ << QTime(22,1,1);
+ QTest::newRow("data8") << false << QTime(1,1,1) << QTime(22,22,22) << (uint)QDateTimeEdit::MinuteSection
+ << QTime(22,0,22);
+ QTest::newRow("data9") << true << QTime(1,1,1) << QTime(22,22,22) << (uint)QDateTimeEdit::MinuteSection
+ << QTime(1,59,1);
+ QTest::newRow("data10") << false << QTime(1,1,1) << QTime(22,22,22) << (uint)QDateTimeEdit::SecondSection
+ << QTime(22,22,0);
+ QTest::newRow("data11") << true << QTime(1,1,1) << QTime(22,22,22) << (uint)QDateTimeEdit::SecondSection
+ << QTime(1,1,59);
+ QTest::newRow("data12") << false << QTime(1,1,1) << QTime(1,2,1) << (uint)QDateTimeEdit::HourSection
+ << QTime(1,2,1);
+ QTest::newRow("data13") << true << QTime(1,1,1) << QTime(1,2,1) << (uint)QDateTimeEdit::HourSection
+ << QTime(1,1,1);
+ QTest::newRow("data14") << false << QTime(1,1,1) << QTime(1,2,1) << (uint)QDateTimeEdit::MinuteSection
+ << QTime(1,1,1);
+ QTest::newRow("data15") << true << QTime(1,1,1) << QTime(1,2,1) << (uint)QDateTimeEdit::MinuteSection
+ << QTime(1,2,1);
+ QTest::newRow("data16") << false << QTime(1,1,1) << QTime(1,2,1) << (uint)QDateTimeEdit::SecondSection
+ << QTime(1,2,0);
+ QTest::newRow("data17") << true << QTime(1,1,1) << QTime(1,2,1) << (uint)QDateTimeEdit::SecondSection
+ << QTime(1,1,59);
+}
+
+
+void tst_QDateTimeEdit::wrappingTime()
+{
+ QFETCH(bool, startWithMin);
+ QFETCH(QTime, minimumTime);
+ QFETCH(QTime, maximumTime);
+ QFETCH(uint, section);
+ QFETCH(QTime, newTime);
+
+ testWidget->setDisplayFormat("hh:mm:ss");
+ testWidget->setMinimumTime(minimumTime);
+ testWidget->setMaximumTime(maximumTime);
+ testWidget->setWrapping(true);
+ testWidget->setCurrentSection((QDateTimeEdit::Section)section);
+ if (startWithMin) {
+ testWidget->setTime(minimumTime);
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ } else {
+ testWidget->setTime(maximumTime);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ }
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->time(), newTime);
+}
+
+void tst_QDateTimeEdit::userKeyPress_Time_data()
+{
+ QTest::addColumn<bool>("ampm");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QTime>("expected_time");
+
+ // ***************** test the hours ***************
+
+ // use up/down keys to change hour in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 10, 0, 0 );
+ QTest::newRow( "data0" ) << bool(true) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<5; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 6, 0, 0 );
+ QTest::newRow( "data1" ) << bool(true) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<10; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 1, 0, 0 );
+ QTest::newRow( "data2" ) << bool(true) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<12; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 23, 0, 0 );
+ QTest::newRow( "data3" ) << bool(true) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 12, 0, 0 );
+ QTest::newRow( "data4" ) << bool(true) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 13, 0, 0 );
+ QTest::newRow( "data5" ) << bool(true) << keys << expected;
+ }
+
+ // use up/down keys to change hour in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 10, 0, 0 );
+ QTest::newRow( "data6" ) << bool(false) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<5; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 6, 0, 0 );
+ QTest::newRow( "data7" ) << bool(false) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<10; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 1, 0, 0 );
+ QTest::newRow( "data8" ) << bool(false) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<12; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 23, 0, 0 );
+ QTest::newRow( "data9" ) << bool(false) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 12, 0, 0 );
+ QTest::newRow( "data10" ) << bool(false) << keys << expected;
+ }
+ {
+ QTestEventList keys;
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 13, 0, 0 );
+ QTest::newRow( "data11" ) << bool(false) << keys << expected;
+ }
+
+ // enter a one digit valid hour
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '5' );
+ QTime expected( 5, 0, 0 );
+ QTest::newRow( "data12" ) << bool(true) << keys << expected;
+ }
+
+ // entering a two digit valid hour
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '1' );
+ keys.addKeyClick( '1' );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data13" ) << bool(true) << keys << expected;
+ }
+
+ // entering an invalid hour
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '2' );
+ // the '5' creates an invalid hour (25) so it must be ignored
+ keys.addKeyClick( '5' );
+ QTime expected( 2, 0, 0 );
+ QTest::newRow( "data14" ) << bool(true) << keys << expected;
+ }
+
+ // enter a value, in hour which causes a field change
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '0' );
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '1' );
+ QTime expected( 2, 1, 0 );
+ QTest::newRow( "data15" ) << bool(true) << keys << expected;
+ }
+
+ // enter a one digit valid hour in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '5' );
+ QTime expected( 5, 0, 0 );
+ QTest::newRow( "data16" ) << bool(false) << keys << expected;
+ }
+
+ // enter a two digit valid hour in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '1' );
+ keys.addKeyClick( '1' );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data17" ) << bool(false) << keys << expected;
+ }
+
+ // enter a two digit valid hour (>12) in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '1' );
+ keys.addKeyClick( '5' );
+ QTime expected( 15, 0, 0 );
+ QTest::newRow( "data18" ) << bool(false) << keys << expected;
+ }
+
+ // enter a two digit valid hour (>20) in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '1' );
+ QTime expected( 21, 0, 0 );
+ QTest::newRow( "data19" ) << bool(false) << keys << expected;
+ }
+
+ // enter a two digit invalid hour (>23) in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '4' );
+ QTime expected( 2, 0, 0 );
+ QTest::newRow( "data20" ) << bool(false) << keys << expected;
+ }
+
+ // ***************** test the minutes ***************
+
+ // use up/down keys to change the minutes in 12 hour mode
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 2, 0 );
+ QTest::newRow( "data21" ) << bool(true) << keys << expected;
+ }
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<16; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 16, 0 );
+ QTest::newRow( "data22" ) << bool(true) << keys << expected;
+ }
+ { // test maximum value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<59; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 59, 0 );
+ QTest::newRow( "data23" ) << bool(true) << keys << expected;
+ }
+ { // test 'overflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<60; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data24" ) << bool(true) << keys << expected;
+ }
+ { // test 'underflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 59, 0 );
+ QTest::newRow( "data25" ) << bool(true) << keys << expected;
+ }
+ { // test valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 58, 0 );
+ QTest::newRow( "data26" ) << bool(true) << keys << expected;
+ }
+
+ // use up/down keys to change the minutes in 24 hour mode
+
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 2, 0 );
+ QTest::newRow( "data27" ) << bool(false) << keys << expected;
+ }
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<16; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 16, 0 );
+ QTest::newRow( "data28" ) << bool(false) << keys << expected;
+ }
+ { // test maximum value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<59; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 59, 0 );
+ QTest::newRow( "data29" ) << bool(false) << keys << expected;
+ }
+ { // test 'overflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<60; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data30" ) << bool(false) << keys << expected;
+ }
+ { // test 'underflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 59, 0 );
+ QTest::newRow( "data31" ) << bool(false) << keys << expected;
+ }
+ { // test valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 58, 0 );
+ QTest::newRow( "data32" ) << bool(false) << keys << expected;
+ }
+
+ // enter a valid one digit minute in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Tab);
+ keys.addKeyClick( '2' );
+ QTime expected( 11, 2, 0 );
+ QTest::newRow( "data33" ) << bool(true) << keys << expected;
+ }
+
+ // enter a valid two digit minutes in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Tab);
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '4' );
+ QTime expected( 11, 24, 0 );
+ QTest::newRow( "data34" ) << bool(true) << keys << expected;
+ }
+
+ // check the lower limit of the minutes in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Tab);
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data35" ) << bool(true) << keys << expected;
+ }
+
+ // check the upper limit of the minutes in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Tab);
+ keys.addKeyClick( '5' );
+ keys.addKeyClick( '9' );
+ QTime expected( 11, 59, 0 );
+ QTest::newRow( "data36" ) << bool(true) << keys << expected;
+ }
+
+ // enter an invalid two digit minutes in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '6' );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 6, 0 );
+ QTest::newRow( "data37" ) << bool(true) << keys << expected;
+ }
+
+ // test minutes in 24 hour motestWidget-> Behaviour should be exactly the same
+
+ // enter a valid one digit minute in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '2' );
+ QTime expected( 11, 2, 0 );
+ QTest::newRow( "data38" ) << bool(false) << keys << expected;
+ }
+
+ // enter a valid two digit minutes in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '4' );
+ QTime expected( 11, 24, 0 );
+ QTest::newRow( "data39" ) << bool(false) << keys << expected;
+ }
+
+ // check the lower limit of the minutes in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data40" ) << bool(false) << keys << expected;
+ }
+
+ // check the upper limit of the minutes in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '5' );
+ keys.addKeyClick( '9' );
+ QTime expected( 11, 59, 0 );
+ QTest::newRow( "data41" ) << bool(false) << keys << expected;
+ }
+
+ // enter an invalid two digit minutes in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '6' );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 6, 0 );
+ QTest::newRow( "data42" ) << bool(false) << keys << expected;
+ }
+
+ // ***************** test the seconds ***************
+
+ // use up/down to edit the seconds...
+
+ // use up/down keys to change the seconds in 12 hour mode
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 2 );
+ QTest::newRow( "data43" ) << bool(true) << keys << expected;
+ }
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<16; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 16 );
+ QTest::newRow( "data44" ) << bool(true) << keys << expected;
+ }
+ { // test maximum value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<59; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 59 );
+ QTest::newRow( "data45" ) << bool(true) << keys << expected;
+ }
+ { // test 'overflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<60; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data46" ) << bool(true) << keys << expected;
+ }
+ { // test 'underflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 0, 59 );
+ QTest::newRow( "data47" ) << bool(true) << keys << expected;
+ }
+ { // test valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 0, 58 );
+ QTest::newRow( "data48" ) << bool(true) << keys << expected;
+ }
+
+ // use up/down keys to change the seconds in 24 hour mode
+
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 2 );
+ QTest::newRow( "data49" ) << bool(false) << keys << expected;
+ }
+ { // test a valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<16; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 16 );
+ QTest::newRow( "data50" ) << bool(false) << keys << expected;
+ }
+ { // test maximum value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<59; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 59 );
+ QTest::newRow( "data51" ) << bool(false) << keys << expected;
+ }
+ { // test 'overflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<60; i++)
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data52" ) << bool(false) << keys << expected;
+ }
+ { // test 'underflow'
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 0, 59 );
+ QTest::newRow( "data53" ) << bool(false) << keys << expected;
+ }
+ { // test valid value
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ for (uint i=0; i<2; i++)
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 0, 58 );
+ QTest::newRow( "data54" ) << bool(false) << keys << expected;
+ }
+
+ // enter a valid one digit second in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '2' );
+ QTime expected( 11, 0, 2 );
+ QTest::newRow( "data55" ) << bool(true) << keys << expected;
+ }
+
+ // enter a valid two digit seconds in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '4' );
+ QTime expected( 11, 0, 24 );
+ QTest::newRow( "data56" ) << bool(true) << keys << expected;
+ }
+
+ // check the lower limit of the seconds in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data57" ) << bool(true) << keys << expected;
+ }
+
+ // check the upper limit of the seconds in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '5' );
+ keys.addKeyClick( '9' );
+ QTime expected( 11, 0, 59 );
+ QTest::newRow( "data58" ) << bool(true) << keys << expected;
+ }
+
+ // enter an invalid two digit seconds in 12 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '6' );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 0, 6 );
+ QTest::newRow( "data59" ) << bool(true) << keys << expected;
+ }
+
+ // test seconds in 24 hour mode. Behaviour should be exactly the same
+
+ // enter a valid one digit minute in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '2' );
+ QTime expected( 11, 0, 2 );
+ QTest::newRow( "data60" ) << bool(false) << keys << expected;
+ }
+
+ // enter a valid two digit seconds in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '2' );
+ keys.addKeyClick( '4' );
+ QTime expected( 11, 0, 24 );
+ QTest::newRow( "data61" ) << bool(false) << keys << expected;
+ }
+
+ // check the lower limit of the seconds in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data62" ) << bool(false) << keys << expected;
+ }
+
+ // check the upper limit of the seconds in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '5' );
+ keys.addKeyClick( '9' );
+ QTime expected( 11, 0, 59 );
+ QTest::newRow( "data63" ) << bool(false) << keys << expected;
+ }
+
+ // enter an invalid two digit seconds in 24 h mode
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( '6' );
+ keys.addKeyClick( '0' );
+ QTime expected( 11, 0, 6 );
+ QTest::newRow( "data64" ) << bool(false) << keys << expected;
+ }
+
+ // Test the AMPM indicator
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Up );
+ QTime expected( 23, 0, 0 );
+ QTest::newRow( "data65" ) << bool(true) << keys << expected;
+ }
+ // Test the AMPM indicator
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 23, 0, 0 );
+ QTest::newRow( "data66" ) << bool(true) << keys << expected;
+ }
+ // Test the AMPM indicator
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Down );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data67" ) << bool(true) << keys << expected;
+ }
+ // Test the AMPM indicator
+ {
+ QTestEventList keys;
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Tab );
+ keys.addKeyClick( Qt::Key_Up );
+ keys.addKeyClick( Qt::Key_Down );
+ QTime expected( 11, 0, 0 );
+ QTest::newRow( "data68" ) << bool(true) << keys << expected;
+ }
+}
+
+void tst_QDateTimeEdit::userKeyPress_Time()
+{
+ QFETCH(bool, ampm);
+ QFETCH(QTestEventList, keys);
+ QFETCH(QTime, expected_time);
+
+ if (ampm)
+ testWidget->setDisplayFormat("hh:mm:ss ap");
+ else
+ testWidget->setDisplayFormat("hh:mm:ss");
+
+ testWidget->setTime(QTime(11, 0, 0));
+ testWidget->setFocus();
+
+ testWidget->setWrapping(true);
+
+ QTest::keyClick(testWidget, Qt::Key_Enter); // Make sure the first section is now focused
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11"));
+ keys.simulate(testWidget);
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+
+ QCOMPARE(testWidget->time(), expected_time);
+}
+
+void tst_QDateTimeEdit::wrappingDate_data()
+{
+ QTest::addColumn<bool>("startWithMin");
+ QTest::addColumn<QDate>("minimumDate");
+ QTest::addColumn<QDate>("maximumDate");
+ QTest::addColumn<uint>("section");
+ QTest::addColumn<QDate>("newDate");
+
+ QTest::newRow("data0") << false << QDate(1999, 1, 1) << QDate(1999, 1, 31) << (uint)QDateTimeEdit::DaySection
+ << QDate(1999, 1, 1);
+ QTest::newRow("data1") << true << QDate(1999, 1, 1) << QDate(1999, 1, 31) << (uint)QDateTimeEdit::DaySection
+ << QDate(1999, 1, 31);
+ QTest::newRow("data2") << false << QDate(1999, 1, 1) << QDate(1999, 1, 31) << (uint)QDateTimeEdit::MonthSection
+ << QDate(1999, 1, 31);
+ QTest::newRow("data3") << true << QDate(1999, 1, 1) << QDate(1999, 1, 31) << (uint)QDateTimeEdit::MonthSection
+ << QDate(1999, 1, 1);
+ QTest::newRow("data4") << false << QDate(1999, 1, 1) << QDate(1999, 1, 31) << (uint)QDateTimeEdit::YearSection
+ << QDate(1999, 1, 31);
+ QTest::newRow("data5") << true << QDate(1999, 1, 1) << QDate(1999, 1, 31) << (uint)QDateTimeEdit::YearSection
+ << QDate(1999, 1, 1);
+ QTest::newRow("data6") << false << QDate(1999, 1, 1) << QDate(2000, 1, 31) << (uint)QDateTimeEdit::DaySection
+ << QDate(2000, 1, 1);
+ QTest::newRow("data7") << true << QDate(1999, 1, 1) << QDate(2000, 1, 31) << (uint)QDateTimeEdit::DaySection
+ << QDate(1999, 1, 31);
+ QTest::newRow("data8") << false << QDate(1999, 1, 1) << QDate(2000, 1, 31) << (uint)QDateTimeEdit::MonthSection
+ << QDate(2000, 1, 31);
+ QTest::newRow("data9") << true << QDate(1999, 1, 1) << QDate(2000, 1, 31) << (uint)QDateTimeEdit::MonthSection
+ << QDate(1999, 12, 1);
+ QTest::newRow("data10") << false << QDate(1999, 1, 1) << QDate(2000, 1, 31) << (uint)QDateTimeEdit::YearSection
+ << QDate(1999, 1, 31);
+ QTest::newRow("data11") << true << QDate(1999, 1, 1) << QDate(2000, 1, 31) << (uint)QDateTimeEdit::YearSection
+ << QDate(2000, 1, 1);
+}
+
+
+void tst_QDateTimeEdit::wrappingDate()
+{
+ QFETCH(bool, startWithMin);
+ QFETCH(QDate, minimumDate);
+ QFETCH(QDate, maximumDate);
+ QFETCH(uint, section);
+ QFETCH(QDate, newDate);
+
+ testWidget->setDisplayFormat("dd/MM/yyyy");
+ testWidget->setMinimumDate(minimumDate);
+ testWidget->setMaximumDate(maximumDate);
+ testWidget->setWrapping(true);
+ testWidget->setCurrentSection((QDateTimeEdit::Section)section);
+
+ if (startWithMin) {
+ testWidget->setDate(minimumDate);
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ } else {
+ testWidget->setDate(maximumDate);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ }
+ if (testWidget->currentSection() == QDateTimeEdit::MonthSection)
+ QCOMPARE(testWidget->date(), newDate);
+}
+
+void tst_QDateTimeEdit::dateSignalChecking_data()
+{
+ QTest::addColumn<QDate>("originalDate");
+ QTest::addColumn<QDate>("newDate");
+ QTest::addColumn<int>("timesEmitted");
+
+ QTest::newRow("data0") << QDate(2004, 06, 22) << QDate(2004, 07, 23) << 1;
+ QTest::newRow("data1") << QDate(2004, 06, 22) << QDate(2004, 06, 22) << 0;
+}
+
+void tst_QDateTimeEdit::dateSignalChecking()
+{
+ QFETCH(QDate, originalDate);
+ QFETCH(QDate, newDate);
+ QFETCH(int, timesEmitted);
+
+ testWidget->setDate(originalDate);
+
+ QSignalSpy dateSpy(testWidget, SIGNAL(dateChanged(const QDate &)));
+ QSignalSpy dateTimeSpy(testWidget, SIGNAL(dateTimeChanged(const QDateTime &)));
+ QSignalSpy timeSpy(testWidget, SIGNAL(timeChanged(const QTime &)));
+
+ testWidget->setDate(newDate);
+ QCOMPARE(dateSpy.count(), timesEmitted);
+
+ if (timesEmitted > 0) {
+ QList<QVariant> list = dateSpy.takeFirst();
+ QDate d;
+ d = qVariantValue<QDate>(list.at(0));
+ QCOMPARE(d, newDate);
+ }
+ QCOMPARE(dateTimeSpy.count(), timesEmitted);
+ QCOMPARE(timeSpy.count(), 0);
+}
+
+void tst_QDateTimeEdit::timeSignalChecking_data()
+{
+ QTest::addColumn<QTime>("originalTime");
+ QTest::addColumn<QTime>("newTime");
+ QTest::addColumn<int>("timesEmitted");
+
+ QTest::newRow("data0") << QTime(15, 55, 00) << QTime(15, 17, 12) << 1;
+ QTest::newRow("data1") << QTime(15, 55, 00) << QTime(15, 55, 00) << 0;
+}
+
+void tst_QDateTimeEdit::timeSignalChecking()
+{
+ QFETCH(QTime, originalTime);
+ QFETCH(QTime, newTime);
+ QFETCH(int, timesEmitted);
+
+ testWidget->setTime(originalTime);
+
+ testWidget->setDisplayFormat("hh:mm:ss");
+ QSignalSpy dateSpy(testWidget, SIGNAL(dateChanged(const QDate &)));
+ QSignalSpy dateTimeSpy(testWidget, SIGNAL(dateTimeChanged(const QDateTime &)));
+ QSignalSpy timeSpy(testWidget, SIGNAL(timeChanged(const QTime &)));
+
+ testWidget->setTime(newTime);
+ QCOMPARE(timeSpy.count(), timesEmitted);
+
+ if (timesEmitted > 0) {
+ QList<QVariant> list = timeSpy.takeFirst();
+ QTime t;
+ t = qVariantValue<QTime>(list.at(0));
+ QCOMPARE(t, newTime);
+ }
+ QCOMPARE(dateTimeSpy.count(), timesEmitted);
+ QCOMPARE(dateSpy.count(), 0);
+}
+
+void tst_QDateTimeEdit::dateTimeSignalChecking_data()
+{
+ QTest::addColumn<QDateTime>("originalDateTime");
+ QTest::addColumn<QDateTime>("newDateTime");
+ QTest::addColumn<int>("timesDateEmitted");
+ QTest::addColumn<int>("timesTimeEmitted");
+ QTest::addColumn<int>("timesDateTimeEmitted");
+
+ QTest::newRow("data0") << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 0))
+ << QDateTime(QDate(2004, 7, 23), QTime(15, 17, 12))
+ << 1 << 1 << 1;
+ QTest::newRow("data1") << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 0))
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 17, 12))
+ << 0 << 1 << 1;
+ QTest::newRow("data2") << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 0))
+ << QDateTime(QDate(2004, 7, 23), QTime(15, 55, 0))
+ << 1 << 0 << 1;
+ QTest::newRow("data3") << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 0))
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 0))
+ << 0 << 0 << 0;
+}
+
+void tst_QDateTimeEdit::dateTimeSignalChecking()
+{
+ QFETCH(QDateTime, originalDateTime);
+ QFETCH(QDateTime, newDateTime);
+ QFETCH(int, timesDateEmitted);
+ QFETCH(int, timesTimeEmitted);
+ QFETCH(int, timesDateTimeEmitted);
+
+ testWidget->setDisplayFormat("dd/MM/yyyy hh:mm:ss");
+ testWidget->setDateTime(originalDateTime);
+
+ QSignalSpy dateSpy(testWidget, SIGNAL(dateChanged(const QDate &)));
+ QSignalSpy timeSpy(testWidget, SIGNAL(timeChanged(const QTime &)));
+ QSignalSpy dateTimeSpy(testWidget, SIGNAL(dateTimeChanged(const QDateTime &)));
+
+ testWidget->setDateTime(newDateTime);
+ QCOMPARE(dateSpy.count(), timesDateEmitted);
+ if (timesDateEmitted > 0) {
+ QCOMPARE(timesDateEmitted, 1);
+ QList<QVariant> list = dateSpy.takeFirst();
+ QDate d;
+ d = qVariantValue<QDate>(list.at(0));
+ QCOMPARE(d, newDateTime.date());
+ }
+ QCOMPARE(timeSpy.count(), timesTimeEmitted);
+ if (timesTimeEmitted > 0) {
+ QList<QVariant> list = timeSpy.takeFirst();
+ QTime t;
+ t = qVariantValue<QTime>(list.at(0));
+ QCOMPARE(t, newDateTime.time());
+ }
+ QCOMPARE(dateTimeSpy.count(), timesDateTimeEmitted);
+ if (timesDateTimeEmitted > 0) {
+ QList<QVariant> list = dateTimeSpy.takeFirst();
+ QDateTime dt;
+ dt = qVariantValue<QDateTime>(list.at(0));
+ QCOMPARE(dt, newDateTime);
+ }
+}
+
+
+void tst_QDateTimeEdit::sectionText_data()
+{
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<QDateTime>("dateTime");
+ QTest::addColumn<uint>("section");
+ QTest::addColumn<QString>("sectionText");
+
+ QTest::newRow("data0") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::NoSection << QString();
+ QTest::newRow("data1") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::AmPmSection << QString("pm");
+ QTest::newRow("data2") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::MSecSection << QString("789");
+ QTest::newRow("data3") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::SecondSection << QString("03");
+ QTest::newRow("data4") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::MinuteSection << QString("55");
+ QTest::newRow("data5") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::HourSection << QString("03");
+ QTest::newRow("data6") << QString("dd/MM/yyyy hh:mm:ss zzz")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::HourSection << QString("15");
+ QTest::newRow("data7") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::DaySection << QString("22");
+ QTest::newRow("data8") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::MonthSection << QString("06");
+ QTest::newRow("data9") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::YearSection << QString("2004");
+ QTest::newRow("data10") << QString("dd/MM/yyyy hh:mm:ss zzz AP")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::AmPmSection << QString("PM");
+ QTest::newRow("data11") << QString("dd/MM/yyyy hh:mm:ss ap")
+ << QDateTime(QDate(2004, 6, 22), QTime(15, 55, 3, 789))
+ << (uint)QDateTimeEdit::MSecSection << QString();
+}
+
+void tst_QDateTimeEdit::sectionText()
+{
+ QFETCH(QString, format);
+ QFETCH(QDateTime, dateTime);
+ QFETCH(uint, section);
+ QFETCH(QString, sectionText);
+
+ testWidget->setDisplayFormat(format);
+ testWidget->setDateTime(dateTime);
+ QCOMPARE(testWidget->sectionText((QDateTimeEdit::Section)section), sectionText);
+// QApplication::setLayoutDirection(Qt::RightToLeft);
+// testWidget->setDisplayFormat(format);
+// QCOMPARE(format, testWidget->displayFormat());
+// testWidget->setDateTime(dateTime);
+// QCOMPARE(testWidget->sectionText((QDateTimeEdit::Section)section), sectionText);
+// QApplication::setLayoutDirection(Qt::LeftToRight);
+}
+
+void tst_QDateTimeEdit::mousePress()
+{
+ testWidget->setDate(QDate(2004, 6, 23));
+ testWidget->setCurrentSection(QDateTimeEdit::YearSection);
+ QCOMPARE(testWidget->currentSection(), QDateTimeEdit::YearSection);
+
+ // Ask the SC_SpinBoxUp button location from style
+ QStyleOptionSpinBox so;
+ so.rect = testWidget->rect();
+ QRect rectUp = testWidget->style()->subControlRect(QStyle::CC_SpinBox, &so, QStyle::SC_SpinBoxUp, testWidget);
+
+ // Send mouseClick to center of SC_SpinBoxUp
+ QTest::mouseClick(testWidget, Qt::LeftButton, 0, rectUp.center());
+ QCOMPARE(testWidget->date().year(), 2005);
+
+}
+
+void tst_QDateTimeEdit::stepHourAMPM_data()
+{
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<KeyList>("keys");
+ QTest::addColumn<TimeList>("expected");
+ QTest::addColumn<QTime>("start");
+ QTest::addColumn<QTime>("min");
+ QTest::addColumn<QTime>("max");
+
+ {
+ KeyList keys;
+ TimeList expected;
+ keys << Qt::Key_Up;
+ expected << QTime(1, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(2, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(3, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(4, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(5, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(6, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(7, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(8, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(9, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(10, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(11, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(12, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(13, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(14, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(15, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(16, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(17, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(18, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(19, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(20, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(21, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(22, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(23, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(22, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(21, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(20, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(19, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(18, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(17, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(16, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(15, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(14, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(13, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(12, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(11, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(10, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(9, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(8, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(7, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(6, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(5, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(4, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(3, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(2, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(1, 0, 0);
+ keys << Qt::Key_Down;
+ expected << QTime(0, 0, 0);
+
+ QTest::newRow("hh 1") << QString("hh") << keys << expected << QTime(0, 0)
+ << QTime(0, 0) << QTime(23, 59, 59);
+ QTest::newRow("hh:ap 1") << QString("hh:ap") << keys << expected
+ << QTime(0, 0) << QTime(0, 0)
+ << QTime(23, 59, 59);
+
+ QTest::newRow("HH:ap 2") << QString("HH:ap") << keys << expected
+ << QTime(0, 0) << QTime(0, 0)
+ << QTime(23, 59, 59);
+
+ }
+ {
+ KeyList keys;
+ TimeList expected;
+ keys << Qt::Key_Down;
+ expected << QTime(2, 0, 0);
+ QTest::newRow("hh 2") << QString("hh") << keys << expected << QTime(0, 0) << QTime(2, 0, 0) << QTime(23, 59, 59);
+ QTest::newRow("hh:ap 2") << QString("hh:ap") << keys << expected << QTime(0, 0) << QTime(2, 0, 0) << QTime(23, 59, 59);
+ }
+ {
+ KeyList keys;
+ TimeList expected;
+ keys << Qt::Key_Up;
+ expected << QTime(23, 0, 0);
+ keys << Qt::Key_Up;
+ expected << QTime(23, 0, 0);
+ QTest::newRow("hh 3") << QString("hh") << keys << expected << QTime(0, 0) << QTime(22, 0, 0)
+ << QTime(23, 59, 59);
+ QTest::newRow("hh:ap 3") << QString("hh:ap") << keys << expected << QTime(0, 0)
+ << QTime(22, 0, 0) << QTime(23, 59, 59);
+ }
+ {
+ KeyList keys;
+ TimeList expected;
+ keys << Qt::Key_Up;
+ expected << QTime(15, 31, 0);
+ QTest::newRow("hh:mm:ap 3") << QString("hh:mm:ap") << keys << expected << QTime(15, 31, 0)
+ << QTime(9, 0, 0) << QTime(16, 0, 0);
+ QTest::newRow("hh:mm 3") << QString("hh:mm") << keys << expected << QTime(15, 31, 0)
+ << QTime(9, 0, 0) << QTime(16, 0, 0);
+ }
+}
+
+void tst_QDateTimeEdit::stepHourAMPM()
+{
+ QFETCH(QString, format);
+ QFETCH(KeyList, keys);
+ QFETCH(TimeList, expected);
+ QFETCH(QTime, start);
+ QFETCH(QTime, min);
+ QFETCH(QTime, max);
+
+
+ testWidget->setDisplayFormat(format);
+ testWidget->setTime(start);
+ testWidget->setMinimumTime(min);
+ testWidget->setMaximumTime(max);
+ if (keys.size() != expected.size()) {
+ qWarning("%s:%d Test broken", __FILE__, __LINE__);
+ QCOMPARE(keys.size(), expected.size());
+ }
+
+ for (int i=0; i<keys.size(); ++i) {
+ QTest::keyClick(testWidget, keys.at(i));
+ QCOMPARE(testWidget->time(), expected.at(i));
+ }
+}
+
+
+void tst_QDateTimeEdit::displayedSections_data()
+{
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<uint>("section");
+
+ QTest::newRow("data0") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)(QDateTimeEdit::DaySection | QDateTimeEdit::MonthSection
+ | QDateTimeEdit::YearSection | QDateTimeEdit::HourSection
+ | QDateTimeEdit::MinuteSection | QDateTimeEdit::SecondSection
+ | QDateTimeEdit::MSecSection | QDateTimeEdit::AmPmSection);
+ QTest::newRow("data1") << QString("dd/yyyy hh:mm:ss zzz ap")
+ << (uint)(QDateTimeEdit::DaySection
+ | QDateTimeEdit::YearSection | QDateTimeEdit::HourSection
+ | QDateTimeEdit::MinuteSection | QDateTimeEdit::SecondSection
+ | QDateTimeEdit::MSecSection | QDateTimeEdit::AmPmSection);
+ QTest::newRow("data2") << QString("dd/MM/yyyy mm zzz ap")
+ << (uint)(QDateTimeEdit::DaySection | QDateTimeEdit::MonthSection
+ | QDateTimeEdit::YearSection
+ | QDateTimeEdit::MinuteSection
+ | QDateTimeEdit::MSecSection | QDateTimeEdit::AmPmSection);
+ QTest::newRow("data3") << QString("dd/MM/yyyy")
+ << (uint)(QDateTimeEdit::DaySection | QDateTimeEdit::MonthSection
+ | QDateTimeEdit::YearSection);
+ QTest::newRow("data4") << QString("hh:mm:ss zzz ap")
+ << (uint)(QDateTimeEdit::HourSection
+ | QDateTimeEdit::MinuteSection | QDateTimeEdit::SecondSection
+ | QDateTimeEdit::MSecSection | QDateTimeEdit::AmPmSection);
+ QTest::newRow("data5") << QString("dd ap")
+ << (uint)(QDateTimeEdit::DaySection | QDateTimeEdit::AmPmSection);
+ QTest::newRow("data6") << QString("zzz")
+ << (uint)QDateTimeEdit::MSecSection;
+}
+
+void tst_QDateTimeEdit::displayedSections()
+{
+ QFETCH(QString, format);
+ QFETCH(uint, section);
+
+ testWidget->setDisplayFormat(format);
+ QVERIFY((QDateTimeEdit::Section)section == testWidget->displayedSections());
+}
+
+void tst_QDateTimeEdit::currentSection_data()
+{
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<uint>("section");
+ QTest::addColumn<uint>("currentSection");
+
+ // First is deliberate, this way we can make sure that it is not reset by specifying no section.
+ QTest::newRow("data0") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::NoSection << (uint)QDateTimeEdit::YearSection;
+ QTest::newRow("data1") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::AmPmSection << (uint)QDateTimeEdit::AmPmSection;
+ QTest::newRow("data2") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::MSecSection << (uint)QDateTimeEdit::MSecSection;
+ QTest::newRow("data3") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::SecondSection << (uint)QDateTimeEdit::SecondSection;
+ QTest::newRow("data4") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::MinuteSection << (uint)QDateTimeEdit::MinuteSection;
+ QTest::newRow("data5") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::HourSection << (uint)QDateTimeEdit::HourSection;
+ QTest::newRow("data6") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::DaySection << (uint)QDateTimeEdit::DaySection;
+ QTest::newRow("data7") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::MonthSection << (uint)QDateTimeEdit::MonthSection;
+ QTest::newRow("data8") << QString("dd/MM/yyyy hh:mm:ss zzz ap")
+ << (uint)QDateTimeEdit::YearSection << (uint)QDateTimeEdit::YearSection;
+ QTest::newRow("data9") << QString("dd/MM/yyyy hh:mm:ss zzz AP")
+ << (uint)QDateTimeEdit::AmPmSection << (uint)QDateTimeEdit::AmPmSection;
+ QTest::newRow("data10") << QString("dd/MM/yyyy hh:mm:ss ap")
+ << (uint)QDateTimeEdit::MSecSection << (uint)QDateTimeEdit::DaySection;
+}
+
+void tst_QDateTimeEdit::currentSection()
+{
+ QFETCH(QString, format);
+ QFETCH(uint, section);
+ QFETCH(uint, currentSection);
+
+ testWidget->setDisplayFormat(format);
+ if ((QDateTimeEdit::Section)section == QDateTimeEdit::NoSection)
+ testWidget->setCurrentSection(QDateTimeEdit::YearSection); // Ensure it's not reset (see above)
+ testWidget->setCurrentSection((QDateTimeEdit::Section)section);
+ QVERIFY((QDateTimeEdit::Section)currentSection == testWidget->currentSection());
+}
+
+void tst_QDateTimeEdit::readOnly()
+{
+ testWidget->hide();
+ QDateTimeEdit dt(QDate(2000, 2, 1));
+ dt.setDisplayFormat("yyyy.MM.dd");
+ dt.show();
+ dt.setCurrentSection(QDateTimeEdit::DaySection);
+ QTest::keyClick(&dt, Qt::Key_Up);
+ QCOMPARE(dt.date(), QDate(2000, 2, 2));
+ dt.setReadOnly(true);
+ QTest::keyClick(&dt, Qt::Key_Up);
+ QCOMPARE(dt.date(), QDate(2000, 2, 2));
+ dt.stepBy(1); // stepBy should still work
+ QCOMPARE(dt.date(), QDate(2000, 2, 3));
+ dt.setReadOnly(false);
+ QTest::keyClick(&dt, Qt::Key_Up);
+ QCOMPARE(dt.date(), QDate(2000, 2, 4));
+}
+
+void tst_QDateTimeEdit::weirdCase()
+{
+ testWidget->lineEdit()->setCursorPosition(0);
+ testWidget->setDateRange(QDate(2005, 1, 1), QDate(2010, 12, 31));
+ testWidget->setDisplayFormat("dd//MM//yyyy");
+ testWidget->setDate(testWidget->minimumDate());
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QVERIFY(!testWidget->lineEdit()->hasSelectedText());
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), 0);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->lineEdit()->hasSelectedText());
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), 8);
+
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QCOMPARE(testWidget->text(), QString("01//01//005"));
+ QTest::keyClick(testWidget, Qt::Key_4);
+ QCOMPARE(testWidget->text(), QString("01//01//005"));
+}
+
+void tst_QDateTimeEdit::newCase()
+{
+ if (QDate::shortMonthName(6) != "Jun" || QDate::shortMonthName(7) != "Jul" ||
+ QDate::longMonthName(6) != "June" || QDate::longMonthName(7) != "July")
+ QSKIP("This test only works in English", SkipAll);
+
+ testWidget->setDisplayFormat("MMMM'a'MbMMMcMM");
+ testWidget->setDate(QDate(2005, 6, 1));
+ QCOMPARE(testWidget->text(), QString("Junea6bJunc06"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->text(), QString("Julya7bJulc07"));
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("July"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+
+
+ QCOMPARE(testWidget->text(), QString("Jula7bJulc07"));
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QCOMPARE(testWidget->text(), QString("Jua7bJulc07"));
+ QTest::keyClick(testWidget, Qt::Key_N);
+ QCOMPARE(testWidget->text(), QString("Juna7bJulc07"));
+ QTest::keyClick(testWidget, Qt::Key_E);
+ QCOMPARE(testWidget->text(), QString("Junea6bJunc06"));
+}
+
+void tst_QDateTimeEdit::newCase2()
+{
+ testWidget->setDisplayFormat("MMMM yyyy-MM-dd MMMM");
+ testWidget->setDate(QDate(2005, 8, 8));
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->text(), QString(" 2005-08-08 ") + QDate::longMonthName(8));
+}
+
+void tst_QDateTimeEdit::newCase3()
+{
+ if (!QDate::longMonthName(1).startsWith("Januar"))
+ QSKIP("This test does not work in this locale", SkipAll);
+
+ testWidget->setDisplayFormat("dd MMMM yyyy");
+ testWidget->setDate(QDate(2000, 1, 1));
+ testWidget->setGeometry(QRect(QPoint(0, 0), testWidget->sizeHint()));
+ testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QTest::keyClick(testWidget, Qt::Key_J);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("01 J 2000"));
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), 4);
+ QTest::keyClick(testWidget, Qt::Key_A);
+ QTest::keyClick(testWidget, Qt::Key_N);
+ QTest::keyClick(testWidget, Qt::Key_U);
+ QTest::keyClick(testWidget, Qt::Key_A);
+ QTest::keyClick(testWidget, Qt::Key_R);
+}
+
+
+void tst_QDateTimeEdit::cursorPos()
+{
+ if (QDate::longMonthName(1) != "January")
+ QSKIP("This test only works in English", SkipAll);
+
+ testWidget->setDisplayFormat("dd MMMM yyyy");
+ //testWidget->setGeometry(0, 0, 200, 200);
+ testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), 10);
+ QTest::keyClick(testWidget, Qt::Key_J);
+ QTest::keyClick(testWidget, Qt::Key_A);
+ QTest::keyClick(testWidget, Qt::Key_N);
+ QTest::keyClick(testWidget, Qt::Key_U);
+ QTest::keyClick(testWidget, Qt::Key_A);
+ QTest::keyClick(testWidget, Qt::Key_R);
+ //QCursor::setPos(20, 20);
+ //QEventLoop l;
+ //l.exec();
+ QTest::keyClick(testWidget, Qt::Key_Y);
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), 11);
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QTest::keyClick(testWidget, Qt::Key_3);
+ QTest::keyClick(testWidget, Qt::Key_1);
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), 3);
+}
+
+void tst_QDateTimeEdit::newCase4()
+{
+ testWidget->setDisplayFormat("hh:mm");
+ testWidget->setMinimumTime(QTime(3, 3, 0));
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QTest::keyClick(testWidget, Qt::Key_0);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("0:03"));
+ QTest::keyClick(testWidget, Qt::Key_2);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("0:03"));
+ QTest::keyClick(testWidget, Qt::Key_4);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("04:03"));
+}
+
+void tst_QDateTimeEdit::newCase5()
+{
+ testWidget->setDisplayFormat("yyyy-MM-dd hh:mm:ss zzz 'ms'");
+ testWidget->setDateTime(QDateTime(QDate(2005, 10, 7), QTime(17, 44, 13, 100)));
+ testWidget->show();
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("2005-10-07 17:44:13 100 ms"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Backtab, Qt::ShiftModifier);
+
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QTest::keyClick(testWidget, Qt::Key_1);
+ QTest::keyClick(testWidget, Qt::Key_2);
+ QTest::keyClick(testWidget, Qt::Key_4);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("2005-10-07 17:44:13 124 ms"));
+
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("2005-10-07 17:44:13 12 ms"));
+}
+
+void tst_QDateTimeEdit::newCase6()
+{
+ testWidget->setDisplayFormat("d-yyyy-MM-dd");
+ testWidget->setDate(QDate(2005, 10, 7));
+ testWidget->show();
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("7-2005-10-07"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QTest::keyClick(testWidget, Qt::Key_1);
+ QTest::keyClick(testWidget, Qt::Key_2);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("12-2005-10-12"));
+}
+
+
+void tst_QDateTimeEdit::task98554()
+{
+ testWidget->setDisplayFormat("mm.ss.zzz(ms)");
+ testWidget->setTime(QTime(0, 0, 9));
+ testWidget->setCurrentSection(QDateTimeEdit::SecondSection);
+ testWidget->show();
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("00.09.000(09)"));
+ QCOMPARE(testWidget->time(), QTime(0, 0, 9, 0));
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("00.10.000(010)"));
+ QCOMPARE(testWidget->time(), QTime(0, 0, 10, 0));
+}
+
+static QList<int> makeList(int val1, int val2, int val3)
+{
+ QList<int> ret;
+ ret << val1 << val2 << val3;
+ return ret;
+}
+
+
+void tst_QDateTimeEdit::setCurrentSection_data()
+{
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<QDateTime>("dateTime");
+ QTest::addColumn<QList<int> >("setCurrentSections");
+ QTest::addColumn<QList<int> >("expectedCursorPositions");
+
+ QTest::newRow("Day") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::DaySection, QDateTimeEdit::DaySection, QDateTimeEdit::DaySection)
+ << makeList(24, 0, 24);
+ QTest::newRow("Month") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::MonthSection, QDateTimeEdit::MonthSection, QDateTimeEdit::MonthSection)
+ << makeList(3, 26, 3);
+ QTest::newRow("Year") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::YearSection, QDateTimeEdit::YearSection, QDateTimeEdit::YearSection)
+ << makeList(6, 28, 6);
+ QTest::newRow("Hour") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::HourSection, QDateTimeEdit::HourSection, QDateTimeEdit::HourSection)
+ << makeList(11, 31, 11);
+ QTest::newRow("Minute") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::MinuteSection, QDateTimeEdit::MinuteSection, QDateTimeEdit::MinuteSection)
+ << makeList(14, 33, 14);
+ QTest::newRow("Second") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::SecondSection, QDateTimeEdit::SecondSection, QDateTimeEdit::SecondSection)
+ << makeList(17, 35, 17);
+ QTest::newRow("MSec") << QString("dd/MM/yyyy hh:mm:ss.zzz d/M/yy h:m:s.z") << QDateTime(QDate(2001, 1, 1), QTime(1, 2, 3, 4))
+ << makeList(QDateTimeEdit::MSecSection, QDateTimeEdit::MSecSection, QDateTimeEdit::MSecSection)
+ << makeList(20, 37, 20);
+}
+
+void tst_QDateTimeEdit::setCurrentSection()
+{
+ QFETCH(QString, format);
+ QFETCH(QDateTime, dateTime);
+ QFETCH(QList<int>, setCurrentSections);
+ QFETCH(QList<int>, expectedCursorPositions);
+
+ QCOMPARE(setCurrentSections.size(), expectedCursorPositions.size());
+ testWidget->setDisplayFormat(format);
+ testWidget->setDateTime(dateTime);
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+
+ testWidget->resize(400, 100);
+ for (int i=0; i<setCurrentSections.size(); ++i) {
+ testWidget->setCurrentSection((QDateTimeEdit::Section)setCurrentSections.at(i));
+ QCOMPARE(testWidget->currentSection(), (QDateTimeEdit::Section)setCurrentSections.at(i));
+ QCOMPARE(testWidget->lineEdit()->cursorPosition(), expectedCursorPositions.at(i));
+ }
+}
+
+
+void tst_QDateTimeEdit::setSelectedSection()
+{
+ testWidget->setDisplayFormat("mm.ss.zzz('ms') m");
+ testWidget->setTime(QTime(0, 0, 9));
+ testWidget->show();
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_Home);
+#endif
+ QVERIFY(!testWidget->lineEdit()->hasSelectedText());
+ testWidget->setSelectedSection(QDateTimeEdit::MinuteSection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("00"));
+ testWidget->setCurrentSection(QDateTimeEdit::MinuteSection);
+ testWidget->setSelectedSection(QDateTimeEdit::MinuteSection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("0"));
+ testWidget->setSelectedSection(QDateTimeEdit::SecondSection);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("09"));
+ testWidget->setSelectedSection(QDateTimeEdit::NoSection);
+ QVERIFY(!testWidget->lineEdit()->hasSelectedText());
+}
+
+void tst_QDateTimeEdit::calendarPopup()
+{
+ {
+ QDateEdit edit;
+ QVERIFY(!edit.calendarWidget());
+ edit.setCalendarPopup(true);
+ QVERIFY(edit.calendarWidget());
+ }
+
+ {
+ QTimeEdit edit;
+ QVERIFY(!edit.calendarWidget());
+ edit.setCalendarPopup(true);
+ QVERIFY(!edit.calendarWidget());
+ }
+
+ {
+ QDateEdit edit;
+ QVERIFY(!edit.calendarWidget());
+ QCalendarWidget *cw = new QCalendarWidget;
+ edit.setCalendarWidget(cw);
+ QVERIFY(!edit.calendarWidget());
+ edit.setCalendarPopup(true);
+ edit.setCalendarWidget(cw);
+ QCOMPARE(edit.calendarWidget(), cw);
+ edit.setDateRange(QDate(1980, 1, 5), QDate(1980, 2, 11));
+ QCOMPARE(cw->minimumDate(), edit.minimumDate());
+ QCOMPARE(cw->maximumDate(), edit.maximumDate());
+ edit.setDate(QDate(1980, 1, 31));
+ QCOMPARE(edit.date(), cw->selectedDate());
+ cw->setSelectedDate(QDate(1980, 1, 30));
+ QCOMPARE(edit.date(), cw->selectedDate());
+ }
+
+ testWidget->setDisplayFormat("dd/MM/yyyy");
+ testWidget->setDateTime(QDateTime(QDate(2000, 1, 1), QTime(0, 0)));
+ testWidget->show();
+ testWidget->setCalendarPopup(true);
+ QCOMPARE(testWidget->calendarPopup(), true);
+ QStyle *style = testWidget->style();
+ QStyleOptionComboBox opt;
+ opt.initFrom(testWidget);
+ opt.editable = true;
+ opt.subControls = QStyle::SC_ComboBoxArrow;
+ QRect rect = style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, testWidget);
+ QTest::mouseClick(testWidget, Qt::LeftButton, 0, QPoint(rect.left()+rect.width()/2, rect.top()+rect.height()/2));
+ QWidget *wid = qFindChild<QWidget *>(testWidget, "qt_datetimedit_calendar");
+ QVERIFY(wid != 0);
+ testWidget->hide();
+
+ QTimeEdit timeEdit;
+ timeEdit.setCalendarPopup(true);
+ timeEdit.show();
+
+ opt.initFrom(&timeEdit);
+ opt.subControls = QStyle::SC_ComboBoxArrow;
+ rect = style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, &timeEdit);
+ QTest::mouseClick(&timeEdit, Qt::LeftButton, 0, QPoint(rect.left()+rect.width()/2, rect.top()+rect.height()/2));
+ QWidget *wid2 = qFindChild<QWidget *>(&timeEdit, "qt_datetimedit_calendar");
+ QVERIFY(wid2 == 0);
+ timeEdit.hide();
+
+
+ QDateEdit dateEdit;
+ dateEdit.setCalendarPopup(true);
+ dateEdit.setReadOnly(true);
+ dateEdit.show();
+
+ opt.initFrom(&dateEdit);
+ opt.subControls = QStyle::SC_ComboBoxArrow;
+ rect = style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, &dateEdit);
+ QTest::mouseClick(&dateEdit, Qt::LeftButton, 0, QPoint(rect.left()+rect.width()/2, rect.top()+rect.height()/2));
+ QWidget *wid3 = qFindChild<QWidget *>(&dateEdit, "qt_datetimedit_calendar");
+ QVERIFY(wid3 == 0);
+ dateEdit.hide();
+
+}
+
+class RestoreLayoutDirectioner
+{
+public:
+ RestoreLayoutDirectioner(Qt::LayoutDirection was)
+ : old(was)
+ {}
+
+ ~RestoreLayoutDirectioner()
+ {
+ QApplication::setLayoutDirection(old);
+ }
+private:
+ const Qt::LayoutDirection old;
+};
+
+void tst_QDateTimeEdit::reverseTest()
+{
+ const RestoreLayoutDirectioner restorer(QApplication::layoutDirection());
+ QApplication::setLayoutDirection(Qt::RightToLeft);
+ testWidget->setDisplayFormat("dd/MM/yyyy");
+ testWidget->setDate(QDate(2001, 3, 30));
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("2001/03/30"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QCOMPARE(testWidget->currentSection(), QDateTimeEdit::DaySection);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2001, 3, 31));
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("2001/03/31"));
+}
+
+
+void tst_QDateTimeEdit::hour12Test()
+{
+ testWidget->setDisplayFormat("hh a");
+ testWidget->setTime(QTime(0, 0, 0));
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("12 am"));
+ for (int i=0; i<11; ++i) {
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ }
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("11 am"));
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("12 pm"));
+ for (int i=0; i<11; ++i) {
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ }
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("11 pm"));
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("11 pm"));
+ for (int i=0; i<12; ++i) {
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ }
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("11 am"));
+ QTest::keyClick(testWidget, Qt::Key_1);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("1 am"));
+ QTest::keyClick(testWidget, Qt::Key_3);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("1 am"));
+}
+
+void tst_QDateTimeEdit::yyTest()
+{
+ testWidget->setDisplayFormat("dd-MMM-yy");
+ testWidget->setTime(QTime(0, 0, 0));
+ testWidget->setDateRange(QDate(2005, 1, 1), QDate(2010, 12, 31));
+ testWidget->setDate(testWidget->minimumDate());
+ testWidget->setCurrentSection(QDateTimeEdit::YearSection);
+
+ QString jan = QDate::shortMonthName(1);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-05");
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-06");
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-07");
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-08");
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-09");
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-10");
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-10");
+ testWidget->setWrapping(true);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-05");
+
+ testWidget->setDateRange(QDate(100, 1, 1), QDate(8000, 12, 31));
+ testWidget->setDate(QDate(2000, 1, 1));
+ testWidget->setCurrentSection(QDateTimeEdit::YearSection);
+ testWidget->setWrapping(false);
+ for (int i=0; i<10; ++i) {
+ for (int j=0; j<50; ++j) {
+ testWidget->stepBy(-1);
+ }
+ testWidget->stepBy(-50);
+ QCOMPARE(testWidget->sectionText(QDateTimeEdit::YearSection), QString("00"));
+ QCOMPARE(testWidget->date(), QDate(2000 - ((i + 1) * 100), 1, 1));
+ }
+}
+
+void tst_QDateTimeEdit::task108572()
+{
+ testWidget->setDisplayFormat("hh:mm:ss.zzz");
+ testWidget->setTime(QTime(0, 1, 2, 0));
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("00:01:02.000"));
+
+ testWidget->setCurrentSection(QDateTimeEdit::MSecSection);
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("000"));
+ QTest::keyClick(testWidget, Qt::Key_2);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("00:01:02.2"));
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QCOMPARE(testWidget->lineEdit()->displayText(), QString("00:01:02.200"));
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("200"));
+ QCOMPARE(testWidget->time(), QTime(0, 1, 2, 200));
+}
+
+void tst_QDateTimeEdit::task149097()
+{
+ QSignalSpy dtSpy(testWidget, SIGNAL(dateTimeChanged(const QDateTime &)));
+ QSignalSpy dSpy(testWidget, SIGNAL(dateChanged(const QDate &)));
+ QSignalSpy tSpy(testWidget, SIGNAL(timeChanged(const QTime &)));
+
+ testWidget->setDisplayFormat("yyyy/MM/dd hh:mm:ss");
+ testWidget->setDateTime(QDateTime(QDate(2001, 02, 03), QTime(5, 1, 2)));
+// QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(dtSpy.count(), 1);
+ QCOMPARE(dSpy.count(), 1);
+ QCOMPARE(tSpy.count(), 1);
+ testWidget->setCurrentSection(QDateTimeEdit::YearSection);
+ testWidget->stepBy(1);
+
+ QCOMPARE(dtSpy.count(), 2);
+ QCOMPARE(dSpy.count(), 2);
+ QCOMPARE(tSpy.count(), 1);
+
+ testWidget->setCurrentSection(QDateTimeEdit::MinuteSection);
+ testWidget->stepBy(1);
+
+ QCOMPARE(dtSpy.count(), 3);
+ QCOMPARE(dSpy.count(), 2);
+ QCOMPARE(tSpy.count(), 2);
+}
+
+void tst_QDateTimeEdit::task148725()
+{
+ testWidget->setDisplayFormat("dd/MM");
+ testWidget->setDate(QDate(2001, 2, 27));
+ testWidget->stepBy(1);
+ QCOMPARE(testWidget->date(), QDate(2001, 2, 28));
+ testWidget->stepBy(1);
+ QCOMPARE(testWidget->date(), QDate(2001, 2, 28));
+ testWidget->setWrapping(true);
+ testWidget->stepBy(1);
+ QCOMPARE(testWidget->date(), QDate(2001, 2, 1));
+}
+
+void tst_QDateTimeEdit::task148522()
+{
+ QTimeEdit edit;
+ const QDateTime dt(QDate(2000, 12, 12), QTime(12, 13, 14, 15));
+ edit.setDateTime(dt);
+ QCOMPARE(edit.dateTime(), dt);
+}
+
+void tst_QDateTimeEdit::ddMMMMyyyy()
+{
+ testWidget->setDisplayFormat("dd.MMMM.yyyy");
+ testWidget->setDate(QDate(2000, 1, 1));
+ testWidget->setCurrentSection(QDateTimeEdit::YearSection);
+ QTest::keyClick(testWidget, Qt::Key_Enter);
+ QCOMPARE(testWidget->lineEdit()->selectedText(), QString("2000"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(testWidget, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(testWidget, Qt::Key_End);
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->lineEdit()->text(), "01." + QDate::longMonthName(1) + ".200");
+}
+
+void tst_QDateTimeEdit::wheelEvent()
+{
+ testWidget->setDisplayFormat("dddd/MM");
+ testWidget->setDate(QDate(2000, 2, 21));
+ testWidget->setCurrentSection(QDateTimeEdit::DaySection);
+ QWheelEvent w(testWidget->lineEdit()->geometry().center(), 120, 0, 0);
+ qApp->sendEvent(testWidget, &w);
+ QCOMPARE(testWidget->date(), QDate(2000, 2, 22));
+ testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
+ qApp->sendEvent(testWidget, &w);
+ QCOMPARE(testWidget->date(), QDate(2000, 3, 22));
+}
+
+void tst_QDateTimeEdit::specialValueCornerCase()
+{
+ // if you set minimum to value it won't update since value won't
+ // be bounded to anything. If you have a specialValueText it needs
+ // to call updateEdit to make sure the text is changed
+
+ QDateTimeEdit edit;
+ edit.setSpecialValueText("foobar");
+ edit.setMinimumDate(edit.date());
+ QCOMPARE(edit.minimumDate(), edit.date());
+ QCOMPARE(edit.text(), QString("foobar"));
+}
+
+void tst_QDateTimeEdit::cursorPositionOnInit()
+{
+ {
+ EditorDateEdit edit;
+ edit.setDisplayFormat("dd/MM");
+ edit.show();
+ QCOMPARE(edit.lineEdit()->cursorPosition(), 0);
+ }
+
+ {
+ EditorDateEdit edit;
+ edit.setDisplayFormat("dd/MM");
+ edit.setSpecialValueText("special");
+ edit.setMinimumDate(edit.date());
+ edit.show();
+ QCOMPARE(edit.lineEdit()->cursorPosition(), 7);
+ // ### legacy behavior. Keep it like this rather than changing
+ // ### but add a test none-the-less
+ }
+}
+
+void tst_QDateTimeEdit::task118867()
+{
+ EditorDateEdit edit;
+ edit.setDisplayFormat("hh:mm");
+ edit.setMinimumTime(QTime(5, 30));
+ edit.setMaximumTime(QTime(6, 30));
+ QCOMPARE(edit.text(), QString("05:30"));
+ edit.lineEdit()->setCursorPosition(5);
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QCOMPARE(edit.text(), QString("05:3"));
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QCOMPARE(edit.text(), QString("05:"));
+ QTest::keyClick(&edit, Qt::Key_1);
+ QCOMPARE(edit.text(), QString("05:"));
+ QTest::keyClick(&edit, Qt::Key_2);
+ QCOMPARE(edit.text(), QString("05:"));
+ QTest::keyClick(&edit, Qt::Key_3);
+ QCOMPARE(edit.text(), QString("05:3"));
+ QTest::keyClick(&edit, Qt::Key_3);
+ QCOMPARE(edit.text(), QString("05:33"));
+}
+
+void tst_QDateTimeEdit::nextPrevSection_data()
+{
+ QTest::addColumn<Qt::Key>("key");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<QString>("selectedText");
+
+ QTest::newRow("tab") << Qt::Key_Tab << (Qt::KeyboardModifiers)Qt::NoModifier << QString("56");
+ QTest::newRow("backtab") << Qt::Key_Backtab << (Qt::KeyboardModifiers)Qt::NoModifier << QString("12");
+ QTest::newRow("shift-tab") << Qt::Key_Tab << (Qt::KeyboardModifiers)Qt::ShiftModifier << QString("12");
+ QTest::newRow("/") << Qt::Key_Slash << (Qt::KeyboardModifiers)Qt::NoModifier << QString("56");
+ QTest::newRow("b") << Qt::Key_B << (Qt::KeyboardModifiers)Qt::NoModifier << QString("56");
+ QTest::newRow("c") << Qt::Key_C << (Qt::KeyboardModifiers)Qt::NoModifier << QString("56");
+
+ // 1. mac doesn't do these,
+ // 2. some WinCE devices do not have modifiers
+#if !defined(Q_OS_MAC) && !defined(WINCE_NO_MODIFIER_KEYS)
+ QTest::newRow("ctrl-right") << Qt::Key_Right << (Qt::KeyboardModifiers)Qt::ControlModifier << QString("56");
+ QTest::newRow("ctrl-left") << Qt::Key_Left << (Qt::KeyboardModifiers)Qt::ControlModifier << QString("12");
+#endif
+}
+
+
+void tst_QDateTimeEdit::nextPrevSection()
+{
+ QFETCH(Qt::Key, key);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(QString, selectedText);
+
+ EditorDateEdit edit;
+ edit.setDisplayFormat("hh/mm/bc9ss");
+ edit.setTime(QTime(12, 34, 56));
+ edit.show();
+ edit.setSelectedSection(QDateTimeEdit::MinuteSection);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("34")); // selftest
+ QTest::keyClick(&edit, key, modifiers);
+ QCOMPARE(edit.lineEdit()->selectedText(), selectedText);
+}
+
+void tst_QDateTimeEdit::dateEditTimeEditFormats()
+{
+ QTimeEdit t;
+ t.setDisplayFormat("hh yyyy");
+ QCOMPARE(t.displayedSections(), QDateTimeEdit::HourSection);
+
+ QDateEdit d;
+ d.setDisplayFormat("hh yyyy");
+ QCOMPARE(d.displayedSections(), QDateTimeEdit::YearSection);
+}
+
+
+void tst_QDateTimeEdit::timeSpec_data()
+{
+ QTest::addColumn<bool>("useSetProperty");
+ QTest::newRow("setProperty") << true;
+ QTest::newRow("setTimeSpec") << false;
+}
+
+
+void tst_QDateTimeEdit::timeSpec()
+{
+ QFETCH(bool, useSetProperty);
+
+ QDateTimeEdit edit;
+ QCOMPARE(edit.dateTime().timeSpec(), edit.timeSpec());
+ QCOMPARE(edit.minimumDateTime().timeSpec(), edit.timeSpec());
+ QCOMPARE(edit.maximumDateTime().timeSpec(), edit.timeSpec());
+ if (useSetProperty) {
+ edit.setProperty("timeSpec", Qt::UTC);
+ } else {
+ edit.setTimeSpec(Qt::UTC);
+ }
+ QCOMPARE(edit.minimumDateTime().timeSpec(), edit.timeSpec());
+ QCOMPARE(edit.maximumDateTime().timeSpec(), edit.timeSpec());
+ QCOMPARE(edit.dateTime().timeSpec(), edit.timeSpec());
+ if (useSetProperty) {
+ edit.setProperty("timeSpec", Qt::LocalTime);
+ } else {
+ edit.setTimeSpec(Qt::LocalTime);
+ }
+ const QDateTime dt = edit.dateTime();
+ QCOMPARE(edit.timeSpec(), Qt::LocalTime);
+ const QDateTime utc = dt.toUTC();
+ if (dt.time() != utc.time()) {
+ const QDateTime min(QDate(1999, 1, 1), QTime(1, 0, 0), Qt::LocalTime);
+ edit.setMinimumDateTime(min);
+ QCOMPARE(edit.minimumTime(), min.time());
+ if (useSetProperty) {
+ edit.setProperty("timeSpec", Qt::UTC);
+ } else {
+ edit.setTimeSpec(Qt::UTC);
+ }
+ QVERIFY(edit.minimumTime() != min.time());
+ QVERIFY(edit.minimumDateTime().timeSpec() != min.timeSpec());
+ QCOMPARE(edit.minimumDateTime().toTime_t(), min.toTime_t());
+ } else {
+ QSKIP("Not tested in the GMT timezone", SkipAll);
+ }
+}
+
+void tst_QDateTimeEdit::timeSpecBug()
+{
+ testWidget->setTimeSpec(Qt::UTC);
+ testWidget->setDisplayFormat("hh:mm");
+ testWidget->setTime(QTime(2, 2));
+ const QString oldText = testWidget->text();
+ const QDateTime oldDateTime = testWidget->dateTime();
+ QTest::keyClick(testWidget, Qt::Key_Tab);
+ QCOMPARE(oldDateTime, testWidget->dateTime());
+ QCOMPARE(oldText, testWidget->text());
+}
+
+
+void tst_QDateTimeEdit::cachedDayTest()
+{
+ testWidget->setDisplayFormat("MM/dd");
+ testWidget->setDate(QDate(2007, 1, 30));
+ testWidget->setCurrentSection(QDateTimeEdit::DaySection);
+ //QTest::keyClick(testWidget->lineEdit(), Qt::Key_Up); // this doesn't work
+ //on Mac. QTestLib bug? ###
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2007, 2, 28));
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2007, 3, 31));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2007, 2, 28));
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2007, 1, 31));
+
+ testWidget->setCurrentSection(QDateTimeEdit::DaySection);
+ QTest::keyClick(testWidget, Qt::Key_Down);
+ QCOMPARE(testWidget->date(), QDate(2007, 1, 30));
+ testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2007, 2, 28));
+ testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
+ QTest::keyClick(testWidget, Qt::Key_Up);
+ QCOMPARE(testWidget->date(), QDate(2007, 3, 30));
+
+}
+
+void tst_QDateTimeEdit::monthEdgeCase()
+{
+ EditorDateEdit edit;
+ edit.setLocale(QLocale("fr_FR"));
+ edit.setDisplayFormat("MMM d");
+ edit.setDate(QDate(2000, 1, 1));
+ QCOMPARE(edit.text(), QString("janv. 1"));
+ edit.lineEdit()->setCursorPosition(5);
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QCOMPARE(edit.text(), QString("janv 1"));
+}
+
+class RestoreLocaler
+{
+public:
+ RestoreLocaler()
+ : old(QLocale())
+ {}
+
+ ~RestoreLocaler()
+ {
+ QLocale::setDefault(old);
+ }
+private:
+ const QLocale old;
+};
+
+
+
+
+void tst_QDateTimeEdit::setLocale()
+{
+ RestoreLocaler r;
+ QLocale::setDefault(QLocale("en_US"));
+ {
+ EditorDateEdit edit;
+ edit.setDisplayFormat("MMMM d");
+ edit.setDate(QDate(2000, 1, 1));
+ QCOMPARE(edit.text(), QString("January 1"));
+ }
+ QLocale::setDefault(QLocale("no_NO"));
+ {
+ EditorDateEdit edit;
+ edit.setDisplayFormat("MMMM d");
+ edit.setDate(QDate(2000, 1, 1));
+ QCOMPARE(edit.text().toLower(), QString("januar 1"));
+ // I get Januar on Mac and januar on linux
+ }
+ QLocale::setDefault(QLocale("en_US"));
+ {
+ EditorDateEdit edit;
+ edit.setDisplayFormat("MMMM d");
+ edit.setDate(QDate(2000, 1, 1));
+ QCOMPARE(edit.text(), QString("January 1"));
+ edit.setLocale(QLocale("no_NO"));
+ QCOMPARE(edit.text().toLower(), QString("januar 1"));
+ edit.setLocale(QLocale("no_NO"));
+ }
+}
+
+
+void tst_QDateTimeEdit::potentialYYValueBug()
+{
+ EditorDateEdit edit;
+ edit.setDisplayFormat("dd/MM/yy");
+ QCOMPARE(edit.minimumDate(), QDate(1752, 9, 14));
+ edit.setDate(edit.minimumDate());
+ edit.lineEdit()->setFocus();
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(&edit, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(&edit, Qt::Key_End);
+#endif
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QCOMPARE(edit.text(), QString("14/09/5"));
+}
+
+void tst_QDateTimeEdit::textSectionAtEnd()
+{
+ EditorDateEdit edit;
+ edit.setDisplayFormat("MMMM");
+ edit.setDate(QDate(2000, 1, 1));
+ edit.lineEdit()->setFocus();
+#ifdef Q_WS_MAC
+ QTest::keyClick(&edit, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(&edit, Qt::Key_End);
+#endif
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QCOMPARE(edit.text(), QString("Januar"));
+}
+
+void tst_QDateTimeEdit::keypadAutoAdvance_data()
+{
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::newRow("None") << (Qt::KeyboardModifiers)Qt::NoModifier;
+ QTest::newRow("Keypad") << (Qt::KeyboardModifiers)Qt::KeypadModifier;
+ // QTBUG-7842: Using KeyPad with shift (numlock off)
+ QTest::newRow("Keypad+Shift") << (Qt::KeyboardModifiers)(Qt::KeypadModifier|Qt::ShiftModifier);
+}
+
+
+void tst_QDateTimeEdit::keypadAutoAdvance()
+{
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+
+ EditorDateEdit edit;
+ edit.setDate(QDate(2000, 2, 1));
+ edit.setDisplayFormat("dd/MM");
+#ifdef Q_WS_MAC
+ QTest::keyClick(&edit, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(&edit, Qt::Key_Home);
+#endif
+ QTest::keyClick(&edit, Qt::Key_Return);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("01"));
+ QTest::keyClick(&edit, Qt::Key_1, modifiers);
+ QTest::keyClick(&edit, Qt::Key_2, modifiers);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("02"));
+}
+
+
+void tst_QDateTimeEdit::task196924()
+{
+ EditorDateEdit edit;
+ edit.setDisplayFormat("dd/M/yyyy");
+ edit.setDate(QDate(2345, 6, 17));
+ QCOMPARE(edit.text(), QString("17/6/2345"));
+ QTest::keyClick(&edit, Qt::Key_Tab);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("6"));
+ QTest::keyClick(&edit, Qt::Key_3);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("2345"));
+ QCOMPARE(edit.text(), QString("17/3/2345"));
+
+ edit.setDisplayFormat("dd/MM/yyyy");
+ edit.setDate(QDate(2345, 6, 17));
+ edit.lineEdit()->setCursorPosition(0);
+ QCOMPARE(edit.text(), QString("17/06/2345"));
+ QTest::keyClick(&edit, Qt::Key_Tab);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("06"));
+ QTest::keyClick(&edit, Qt::Key_3);
+ QCOMPARE(edit.lineEdit()->selectedText(), QString("2345"));
+ QCOMPARE(edit.text(), QString("17/03/2345"));
+
+}
+
+void tst_QDateTimeEdit::focusNextPrevChild()
+{
+ EditorDateEdit edit;
+ edit.setDisplayFormat("dd/MM/yyyy");
+
+ edit.show();
+ edit.setFocus();
+ edit.setCurrentSection(QDateTimeEdit::DaySection);
+
+ QCOMPARE(edit.currentSection(), QDateTimeEdit::DaySection);
+ edit.focusNextPrevChild(true);
+ QCOMPARE(edit.currentSection(), QDateTimeEdit::MonthSection);
+}
+
+void tst_QDateTimeEdit::taskQTBUG_12384_timeSpecShowTimeOnly()
+{
+ QDateTime time = QDateTime::fromString("20100723 04:02:40", "yyyyMMdd hh:mm:ss");
+ time.setTimeSpec(Qt::UTC);
+
+ EditorDateEdit edit;
+ edit.setDisplayFormat("hh:mm:ss");
+ edit.setTimeSpec(Qt::UTC);
+ edit.setDateTime(time);
+
+ QCOMPARE(edit.minimumTime(), QTime(0, 0, 0, 0));
+ QCOMPARE(edit.maximumTime(), QTime(23, 59, 59, 999));
+ QCOMPARE(edit.time(), time.time());
+}
+
+void tst_QDateTimeEdit::deleteCalendarWidget()
+{
+ {
+ // setup
+ QCalendarWidget *cw = 0;
+ QDateEdit edit;
+ QVERIFY(!edit.calendarWidget());
+ edit.setCalendarPopup(true);
+ QVERIFY(edit.calendarWidget());
+ edit.calendarWidget()->setObjectName("cw1");;
+
+ // delete
+ cw = edit.calendarWidget();
+ delete cw;
+
+ // it should create a new widget
+ QVERIFY(edit.calendarWidget());
+ QVERIFY(edit.calendarWidget()->objectName() != "cw1");
+ }
+}
+
+QTEST_MAIN(tst_QDateTimeEdit)
+#include "tst_qdatetimeedit.moc"
diff --git a/tests/auto/widgets/widgets/qdial/.gitignore b/tests/auto/widgets/widgets/qdial/.gitignore
new file mode 100644
index 0000000000..3a640cf1a1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdial/.gitignore
@@ -0,0 +1 @@
+tst_qdial
diff --git a/tests/auto/widgets/widgets/qdial/qdial.pro b/tests/auto/widgets/widgets/qdial/qdial.pro
new file mode 100644
index 0000000000..acf66de430
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdial/qdial.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdial.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qdial/tst_qdial.cpp b/tests/auto/widgets/widgets/qdial/tst_qdial.cpp
new file mode 100644
index 0000000000..568b82d28b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdial/tst_qdial.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QDial>
+
+class tst_QDial : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDial();
+
+private slots:
+ void getSetCheck();
+ void valueChanged();
+ void sliderMoved();
+ void wrappingCheck();
+};
+
+// Testing get/set functions
+void tst_QDial::getSetCheck()
+{
+ QDial obj1;
+ // bool QDial::notchesVisible()
+ // void QDial::setNotchesVisible(bool)
+ obj1.setNotchesVisible(false);
+ QCOMPARE(false, obj1.notchesVisible());
+ obj1.setNotchesVisible(true);
+ QCOMPARE(true, obj1.notchesVisible());
+
+ // bool QDial::wrapping()
+ // void QDial::setWrapping(bool)
+ obj1.setWrapping(false);
+ QCOMPARE(false, obj1.wrapping());
+ obj1.setWrapping(true);
+ QCOMPARE(true, obj1.wrapping());
+}
+
+tst_QDial::tst_QDial()
+{
+}
+
+void tst_QDial::valueChanged()
+{
+ QDial dial;
+ dial.setMinimum(0);
+ dial.setMaximum(100);
+ QSignalSpy spy(&dial, SIGNAL(valueChanged(int)));
+ dial.setValue(50);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ dial.setValue(25);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ // repeat!
+ dial.setValue(25);
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QDial::sliderMoved()
+{
+ //this tests that when dragging the arrow that the sliderMoved signal is emitted
+ //even if tracking is set to false
+ QDial dial;
+ dial.setTracking(false);
+ dial.setMinimum(0);
+ dial.setMaximum(100);
+
+ dial.show();
+
+ QPoint init(dial.width()/4, dial.height()/2);
+
+ QMouseEvent pressevent(QEvent::MouseButtonPress, init,
+ Qt::LeftButton, Qt::LeftButton, 0);
+ qApp->sendEvent(&dial, &pressevent);
+
+ QSignalSpy sliderspy(&dial, SIGNAL(sliderMoved(int)));
+ QSignalSpy valuespy(&dial, SIGNAL(valueChanged(int)));
+
+
+ { //move on top of the slider
+ init = QPoint(dial.width()/2, dial.height()/4);
+ QMouseEvent moveevent(QEvent::MouseMove, init,
+ Qt::LeftButton, Qt::LeftButton, 0);
+ qApp->sendEvent(&dial, &moveevent);
+ QCOMPARE( sliderspy.count(), 1);
+ QCOMPARE( valuespy.count(), 0);
+ }
+
+
+ { //move on the right of the slider
+ init = QPoint(dial.width()*3/4, dial.height()/2);
+ QMouseEvent moveevent(QEvent::MouseMove, init,
+ Qt::LeftButton, Qt::LeftButton, 0);
+ qApp->sendEvent(&dial, &moveevent);
+ QCOMPARE( sliderspy.count(), 2);
+ QCOMPARE( valuespy.count(), 0);
+ }
+
+ QMouseEvent releaseevent(QEvent::MouseButtonRelease, init,
+ Qt::LeftButton, Qt::LeftButton, 0);
+ qApp->sendEvent(&dial, &releaseevent);
+ QCOMPARE( valuespy.count(), 1); // valuechanged signal should be called at this point
+
+}
+
+void tst_QDial::wrappingCheck()
+{
+ //This tests if dial will wrap past the maximum value back to the minimum
+ //and vice versa when changing the value with a keypress
+ QDial dial;
+ dial.setMinimum(0);
+ dial.setMaximum(100);
+ dial.setSingleStep(1);
+ dial.setWrapping(true);
+ dial.setValue(99);
+ dial.show();
+
+ { //set value to maximum but do not wrap
+ QTest::keyPress(&dial, Qt::Key_Up);
+ QCOMPARE( dial.value(), 100);
+ }
+
+ { //step up once more and wrap clockwise to minimum + 1
+ QTest::keyPress(&dial, Qt::Key_Up);
+ QCOMPARE( dial.value(), 1);
+ }
+
+ { //step down once, and wrap anti-clockwise to minimum, then again to maximum - 1
+ QTest::keyPress(&dial, Qt::Key_Down);
+ QCOMPARE( dial.value(), 0);
+
+ QTest::keyPress(&dial, Qt::Key_Down);
+ QCOMPARE( dial.value(), 99);
+ }
+
+ { //when wrapping property is false no wrapping will occur
+ dial.setWrapping(false);
+ dial.setValue(100);
+
+ QTest::keyPress(&dial, Qt::Key_Up);
+ QCOMPARE( dial.value(), 100);
+
+ dial.setValue(0);
+ QTest::keyPress(&dial, Qt::Key_Down);
+ QCOMPARE( dial.value(), 0);
+ }
+
+ { //When the step is really big or small, wrapping should still behave
+ dial.setWrapping(true);
+ dial.setValue(dial.minimum());
+ dial.setSingleStep(305);
+
+ QTest::keyPress(&dial, Qt::Key_Up);
+ QCOMPARE( dial.value(), 5);
+
+ dial.setValue(dial.minimum());
+ QTest::keyPress(&dial, Qt::Key_Down);
+ QCOMPARE( dial.value(), 95);
+
+ dial.setMinimum(-30);
+ dial.setMaximum(-4);
+ dial.setSingleStep(200);
+ dial.setValue(dial.minimum());
+ QTest::keyPress(&dial, Qt::Key_Down);
+ QCOMPARE( dial.value(), -22);
+ }
+}
+
+QTEST_MAIN(tst_QDial)
+#include "tst_qdial.moc"
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/.gitignore b/tests/auto/widgets/widgets/qdialogbuttonbox/.gitignore
new file mode 100644
index 0000000000..edf08554d4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/.gitignore
@@ -0,0 +1 @@
+tst_qdialogbuttonbox
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/qdialogbuttonbox.pro b/tests/auto/widgets/widgets/qdialogbuttonbox/qdialogbuttonbox.pro
new file mode 100644
index 0000000000..efbeca0c1b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/qdialogbuttonbox.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdialogbuttonbox.cpp
+
+TARGET = tst_qdialogbuttonbox
+
+
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
new file mode 100644
index 0000000000..449cc5e44d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
@@ -0,0 +1,810 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QLayout>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QAction>
+#include <qdialogbuttonbox.h>
+#include <limits.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QDialogButtonBox::ButtonRole)
+Q_DECLARE_METATYPE(QDialogButtonBox::StandardButton)
+Q_DECLARE_METATYPE(QDialogButtonBox::StandardButtons)
+Q_DECLARE_METATYPE(QAbstractButton*)
+
+class tst_QDialogButtonBox : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDialogButtonBox();
+ ~tst_QDialogButtonBox();
+
+
+public slots:
+ void buttonClicked1(QAbstractButton *);
+ void acceptClicked();
+ void rejectClicked();
+ void helpRequestedClicked();
+
+private slots:
+ void standardButtons();
+ void testConstructor1();
+ void testConstrurtor2();
+ void testConstrurtor2_data();
+ void testConstructor3();
+ void testConstructor3_data();
+ void setOrientation_data();
+ void setOrientation();
+ void addButton1_data();
+ void addButton1();
+ void addButton2_data();
+ void addButton2();
+ void addButton3_data();
+ void addButton3();
+ void clear_data();
+ void clear();
+ void removeButton_data();
+ void removeButton();
+ void buttonRole_data();
+ void buttonRole();
+ void setStandardButtons_data();
+ void setStandardButtons();
+ void layoutReuse();
+
+
+ // Skip these tests, buttons is used in every test thus far.
+// void buttons_data();
+// void buttons();
+
+ void testDelete();
+ void testRemove();
+ void testMultipleAdd();
+ void testStandardButtonMapping_data();
+ void testStandardButtonMapping();
+ void testSignals_data();
+ void testSignals();
+ void testSignalOrder();
+ void testDefaultButton_data();
+ void testDefaultButton();
+#ifdef QT_SOFTKEYS_ENABLED
+ void testSoftKeyReparenting();
+#endif
+
+ void task191642_default();
+private:
+ qint64 timeStamp;
+ qint64 buttonClicked1TimeStamp;
+ qint64 acceptTimeStamp;
+ qint64 rejectTimeStamp;
+ qint64 helpRequestedTimeStamp;
+};
+
+tst_QDialogButtonBox::tst_QDialogButtonBox()
+{
+}
+
+tst_QDialogButtonBox::~tst_QDialogButtonBox()
+{
+}
+
+void tst_QDialogButtonBox::testConstructor1()
+{
+ QDialogButtonBox buttonbox;
+ QCOMPARE(buttonbox.orientation(), Qt::Horizontal);
+
+ QCOMPARE(buttonbox.buttons().count(), 0);
+}
+
+void tst_QDialogButtonBox::layoutReuse()
+{
+ QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok);
+ QPointer<QLayout> layout = box->layout();
+ box->setCenterButtons(!box->centerButtons());
+ QVERIFY(layout == box->layout());
+ QEvent event(QEvent::StyleChange);
+ QApplication::sendEvent(box, &event);
+ QVERIFY(layout == box->layout());
+ box->setOrientation(box->orientation() == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal);
+ QVERIFY(layout == 0);
+ QVERIFY(layout != box->layout());
+ delete box;
+}
+
+void tst_QDialogButtonBox::testConstrurtor2_data()
+{
+ QTest::addColumn<int>("orientation");
+
+ QTest::newRow("horizontal") << int(Qt::Horizontal);
+ QTest::newRow("vertical") << int(Qt::Vertical);
+}
+
+void tst_QDialogButtonBox::testConstrurtor2()
+{
+ QFETCH(int, orientation);
+ Qt::Orientation orient = Qt::Orientation(orientation);
+ QDialogButtonBox buttonBox(orient);
+
+ QCOMPARE(buttonBox.orientation(), orient);
+ QCOMPARE(buttonBox.buttons().count(), 0);
+}
+
+void tst_QDialogButtonBox::testConstructor3_data()
+{
+ QTest::addColumn<int>("orientation");
+ QTest::addColumn<QDialogButtonBox::StandardButtons>("buttons");
+ QTest::addColumn<int>("buttonCount");
+
+ QTest::newRow("nothing") << int(Qt::Horizontal) << (QDialogButtonBox::StandardButtons)0 << 0;
+ QTest::newRow("only 1") << int(Qt::Horizontal) << QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok) << 1;
+ QTest::newRow("only 1.. twice") << int(Qt::Horizontal)
+ << (QDialogButtonBox::Ok | QDialogButtonBox::Ok)
+ << 1;
+ QTest::newRow("only 2") << int(Qt::Horizontal)
+ << (QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
+ << 2;
+ QTest::newRow("two different things") << int(Qt::Horizontal)
+ << (QDialogButtonBox::Save | QDialogButtonBox::Close)
+ << 2;
+ QTest::newRow("three") << int(Qt::Horizontal)
+ << (QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Help)
+ << 3;
+ QTest::newRow("everything") << int(Qt::Vertical)
+ << (QDialogButtonBox::StandardButtons)UINT_MAX
+ << 18;
+}
+
+void tst_QDialogButtonBox::testConstructor3()
+{
+ QFETCH(int, orientation);
+ QFETCH(QDialogButtonBox::StandardButtons, buttons);
+
+ QDialogButtonBox buttonBox(buttons, (Qt::Orientation)orientation);
+ QCOMPARE(int(buttonBox.orientation()), orientation);
+ QTEST(buttonBox.buttons().count(), "buttonCount");
+}
+
+void tst_QDialogButtonBox::setOrientation_data()
+{
+ QTest::addColumn<int>("orientation");
+
+ QTest::newRow("Horizontal") << int(Qt::Horizontal);
+ QTest::newRow("Vertical") << int(Qt::Vertical);
+}
+
+void tst_QDialogButtonBox::setOrientation()
+{
+ QFETCH(int, orientation);
+ QDialogButtonBox buttonBox;
+ QCOMPARE(int(buttonBox.orientation()), int(Qt::Horizontal));
+
+ buttonBox.setOrientation(Qt::Orientation(orientation));
+ QCOMPARE(int(buttonBox.orientation()), orientation);
+}
+
+/*
+void tst_QDialogButtonBox::setLayoutPolicy_data()
+{
+ QTest::addColumn<int>("layoutPolicy");
+
+ QTest::newRow("win") << int(QDialogButtonBox::WinLayout);
+ QTest::newRow("mac") << int(QDialogButtonBox::MacLayout);
+ QTest::newRow("kde") << int(QDialogButtonBox::KdeLayout);
+ QTest::newRow("gnome") << int(QDialogButtonBox::GnomeLayout);
+
+}
+
+void tst_QDialogButtonBox::setLayoutPolicy()
+{
+ QFETCH(int, layoutPolicy);
+
+ QDialogButtonBox buttonBox;
+ QCOMPARE(int(buttonBox.layoutPolicy()),
+ int(buttonBox.style()->styleHint(QStyle::SH_DialogButtonLayout)));
+ buttonBox.setLayoutPolicy(QDialogButtonBox::ButtonLayout(layoutPolicy));
+ QCOMPARE(int(buttonBox.layoutPolicy()), layoutPolicy);
+}
+*/
+
+void tst_QDialogButtonBox::addButton1_data()
+{
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("role");
+ QTest::addColumn<int>("totalCount");
+
+ QTest::newRow("InvalidRole") << QDialogButtonBox::InvalidRole << 0;
+ QTest::newRow("AcceptRole") << QDialogButtonBox::AcceptRole << 1;
+ QTest::newRow("RejectRole") << QDialogButtonBox::RejectRole << 1;
+ QTest::newRow("DestructiveRole") << QDialogButtonBox::DestructiveRole << 1;
+ QTest::newRow("ActionRole") << QDialogButtonBox::ActionRole << 1;
+ QTest::newRow("HelpRole") << QDialogButtonBox::HelpRole << 1;
+ QTest::newRow("WackyValue") << (QDialogButtonBox::ButtonRole)-1 << 0;
+}
+
+void tst_QDialogButtonBox::addButton1()
+{
+ QFETCH(QDialogButtonBox::ButtonRole, role);
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ QPushButton *button = new QPushButton();
+ buttonBox.addButton(button, role);
+ QTEST(buttonBox.buttons().count(), "totalCount");
+ QList<QAbstractButton *> children = qFindChildren<QAbstractButton *>(&buttonBox);
+ QTEST(children.count(), "totalCount");
+ delete button;
+}
+
+void tst_QDialogButtonBox::addButton2_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("role");
+ QTest::addColumn<int>("totalCount");
+ QTest::newRow("InvalidRole") << QString("foo") << QDialogButtonBox::InvalidRole << 0;
+ QTest::newRow("AcceptRole") << QString("foo") << QDialogButtonBox::AcceptRole << 1;
+ QTest::newRow("RejectRole") << QString("foo") << QDialogButtonBox::RejectRole << 1;
+ QTest::newRow("DestructiveRole") << QString("foo") << QDialogButtonBox::DestructiveRole << 1;
+ QTest::newRow("ActionRole") << QString("foo") << QDialogButtonBox::ActionRole << 1;
+ QTest::newRow("HelpRole") << QString("foo") << QDialogButtonBox::HelpRole << 1;
+ QTest::newRow("WackyValue") << QString("foo") << (QDialogButtonBox::ButtonRole)-1 << 0;
+}
+
+void tst_QDialogButtonBox::addButton2()
+{
+ QFETCH(QString, text);
+ QFETCH(QDialogButtonBox::ButtonRole, role);
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ buttonBox.addButton(text, role);
+ QTEST(buttonBox.buttons().count(), "totalCount");
+ QList<QAbstractButton *> children = qFindChildren<QAbstractButton *>(&buttonBox);
+ QTEST(children.count(), "totalCount");
+}
+
+void tst_QDialogButtonBox::addButton3_data()
+{
+ QTest::addColumn<QDialogButtonBox::StandardButton>("button");
+ QTest::addColumn<int>("totalCount");
+ QTest::newRow("Ok") << QDialogButtonBox::Ok << 1;
+ QTest::newRow("Open") << QDialogButtonBox::Open << 1;
+ QTest::newRow("Save") << QDialogButtonBox::Save << 1;
+ QTest::newRow("Cancel") << QDialogButtonBox::Cancel << 1;
+ QTest::newRow("Close") << QDialogButtonBox::Close << 1;
+ QTest::newRow("Discard") << QDialogButtonBox::Discard << 1;
+ QTest::newRow("Apply") << QDialogButtonBox::Apply << 1;
+ QTest::newRow("Reset") << QDialogButtonBox::Reset << 1;
+ QTest::newRow("Help") << QDialogButtonBox::Help << 1;
+ QTest::newRow("noButton") << (QDialogButtonBox::StandardButton)0 << 0;
+}
+
+void tst_QDialogButtonBox::addButton3()
+{
+ QFETCH(QDialogButtonBox::StandardButton, button);
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ buttonBox.addButton(button);
+ QTEST(buttonBox.buttons().count(), "totalCount");
+ QList<QAbstractButton *> children = qFindChildren<QAbstractButton *>(&buttonBox);
+ QTEST(children.count(), "totalCount");
+}
+
+void tst_QDialogButtonBox::clear_data()
+{
+ QTest::addColumn<int>("rolesToAdd");
+
+ QTest::newRow("nothing") << 0;
+ QTest::newRow("one") << 1;
+ QTest::newRow("all") << int(QDialogButtonBox::NRoles);
+}
+
+void tst_QDialogButtonBox::clear()
+{
+ QFETCH(int, rolesToAdd);
+
+ QDialogButtonBox buttonBox;
+ for (int i = 1; i < rolesToAdd; ++i)
+ buttonBox.addButton("Happy", QDialogButtonBox::ButtonRole(i));
+ buttonBox.clear();
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ QList<QAbstractButton *> children = qFindChildren<QAbstractButton *>(&buttonBox);
+ QCOMPARE(children.count(), 0);
+}
+
+void tst_QDialogButtonBox::removeButton_data()
+{
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("roleToAdd");
+ QTest::addColumn<int>("expectedCount");
+ QTest::newRow("no button added") << QDialogButtonBox::InvalidRole << 0;
+ QTest::newRow("a button") << QDialogButtonBox::AcceptRole << 1;
+}
+
+void tst_QDialogButtonBox::removeButton()
+{
+ QFETCH(QDialogButtonBox::ButtonRole, roleToAdd);
+
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ QPushButton *button = new QPushButton("RemoveButton test");
+ buttonBox.addButton(button, roleToAdd);
+ QTEST(buttonBox.buttons().count(), "expectedCount");
+
+ buttonBox.removeButton(button);
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ delete button;
+}
+
+void tst_QDialogButtonBox::testDelete()
+{
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+
+ QPushButton *deleteMe = new QPushButton("Happy");
+ buttonBox.addButton(deleteMe, QDialogButtonBox::HelpRole);
+ QCOMPARE(buttonBox.buttons().count(), 1);
+ QList<QAbstractButton *> children = qFindChildren<QAbstractButton *>(&buttonBox);
+ QCOMPARE(children.count(), 1);
+
+ delete deleteMe;
+ children = qFindChildren<QAbstractButton *>(&buttonBox);
+ QCOMPARE(children.count(), 0);
+ QCOMPARE(buttonBox.buttons().count(), 0);
+}
+
+void tst_QDialogButtonBox::testMultipleAdd()
+{
+ // Add a button into the thing multiple times.
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+
+ QPushButton *button = new QPushButton("Foo away");
+ buttonBox.addButton(button, QDialogButtonBox::AcceptRole);
+ QCOMPARE(buttonBox.buttons().count(), 1);
+ QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::AcceptRole);
+ buttonBox.addButton(button, QDialogButtonBox::AcceptRole);
+ QCOMPARE(buttonBox.buttons().count(), 1);
+ QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::AcceptRole);
+
+ // Add it again with a different role
+ buttonBox.addButton(button, QDialogButtonBox::RejectRole);
+ QCOMPARE(buttonBox.buttons().count(), 1);
+ QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::RejectRole);
+
+ // Add it as an "invalid" role
+ buttonBox.addButton(button, QDialogButtonBox::InvalidRole);
+ QCOMPARE(buttonBox.buttons().count(), 1);
+ QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::RejectRole);
+}
+
+void tst_QDialogButtonBox::buttonRole_data()
+{
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("roleToAdd");
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("expectedRole");
+
+ QTest::newRow("AcceptRole stuff") << QDialogButtonBox::AcceptRole
+ << QDialogButtonBox::AcceptRole;
+ QTest::newRow("Nothing") << QDialogButtonBox::InvalidRole << QDialogButtonBox::InvalidRole;
+ QTest::newRow("bad stuff") << (QDialogButtonBox::ButtonRole)-1 << QDialogButtonBox::InvalidRole;
+}
+
+void tst_QDialogButtonBox::buttonRole()
+{
+ QFETCH(QDialogButtonBox::ButtonRole, roleToAdd);
+ QDialogButtonBox buttonBox;
+ QAbstractButton *button = buttonBox.addButton("Here's a button", roleToAdd);
+ QTEST(buttonBox.buttonRole(button), "expectedRole");
+}
+
+void tst_QDialogButtonBox::testStandardButtonMapping_data()
+{
+ QTest::addColumn<QDialogButtonBox::StandardButton>("button");
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("expectedRole");
+ QTest::addColumn<QString>("expectedText");
+
+ int layoutPolicy = qApp->style()->styleHint(QStyle::SH_DialogButtonLayout);
+
+ QTest::newRow("QDialogButtonBox::Ok") << QDialogButtonBox::Ok
+ << QDialogButtonBox::AcceptRole
+ << QDialogButtonBox::tr("OK");
+ QTest::newRow("QDialogButtonBox::Open") << QDialogButtonBox::Open
+ << QDialogButtonBox::AcceptRole
+ << QDialogButtonBox::tr("Open");
+ QTest::newRow("QDialogButtonBox::Save") << QDialogButtonBox::Save
+ << QDialogButtonBox::AcceptRole
+ << QDialogButtonBox::tr("Save");
+ QTest::newRow("QDialogButtonBox::Cancel") << QDialogButtonBox::Cancel
+ << QDialogButtonBox::RejectRole
+ << QDialogButtonBox::tr("Cancel");
+ QTest::newRow("QDialogButtonBox::Close") << QDialogButtonBox::Close
+ << QDialogButtonBox::RejectRole
+ << QDialogButtonBox::tr("Close");
+ if (layoutPolicy == QDialogButtonBox::MacLayout) {
+ QTest::newRow("QDialogButtonBox::Discard") << QDialogButtonBox::Discard
+ << QDialogButtonBox::DestructiveRole
+ << QDialogButtonBox::tr("Don't Save");
+ } else if (layoutPolicy == QDialogButtonBox::GnomeLayout) {
+ QTest::newRow("QDialogButtonBox::Discard")
+ << QDialogButtonBox::Discard
+ << QDialogButtonBox::DestructiveRole
+ << QDialogButtonBox::tr("Close without Saving");
+ } else {
+ QTest::newRow("QDialogButtonBox::Discard") << QDialogButtonBox::Discard
+ << QDialogButtonBox::DestructiveRole
+ << QDialogButtonBox::tr("Discard");
+ }
+ QTest::newRow("QDialogButtonBox::Apply") << QDialogButtonBox::Apply
+ << QDialogButtonBox::ApplyRole
+ << QDialogButtonBox::tr("Apply");
+ QTest::newRow("QDialogButtonBox::Reset") << QDialogButtonBox::Reset
+ << QDialogButtonBox::ResetRole
+ << QDialogButtonBox::tr("Reset");
+ QTest::newRow("QDialogButtonBox::Help") << QDialogButtonBox::Help
+ << QDialogButtonBox::HelpRole
+ << QDialogButtonBox::tr("Help");
+}
+
+void tst_QDialogButtonBox::testStandardButtonMapping()
+{
+ QFETCH(QDialogButtonBox::StandardButton, button);
+ QDialogButtonBox buttonBox;
+
+ QAbstractButton *theButton = buttonBox.addButton(button);
+ QTEST(buttonBox.buttonRole(theButton), "expectedRole");
+ QString textWithoutMnemonic = theButton->text().remove("&");
+ QTEST(textWithoutMnemonic, "expectedText");
+}
+
+void tst_QDialogButtonBox::testSignals_data()
+{
+ QTest::addColumn<QDialogButtonBox::ButtonRole>("buttonToClick");
+ QTest::addColumn<int>("clicked2Count");
+ QTest::addColumn<int>("acceptCount");
+ QTest::addColumn<int>("rejectCount");
+ QTest::addColumn<int>("helpRequestedCount");
+
+ QTest::newRow("nothing") << QDialogButtonBox::InvalidRole << 0 << 0 << 0 << 0;
+ QTest::newRow("accept") << QDialogButtonBox::AcceptRole << 1 << 1 << 0 << 0;
+ QTest::newRow("reject") << QDialogButtonBox::RejectRole << 1 << 0 << 1 << 0;
+ QTest::newRow("destructive") << QDialogButtonBox::DestructiveRole << 1 << 0 << 0 << 0;
+ QTest::newRow("Action") << QDialogButtonBox::ActionRole << 1 << 0 << 0 << 0;
+ QTest::newRow("Help") << QDialogButtonBox::HelpRole << 1 << 0 << 0 << 1;
+}
+
+void tst_QDialogButtonBox::testSignals()
+{
+ QFETCH(QDialogButtonBox::ButtonRole, buttonToClick);
+ QDialogButtonBox buttonBox;
+ qRegisterMetaType<QAbstractButton *>("QAbstractButton*");
+ QSignalSpy clicked2(&buttonBox, SIGNAL(clicked(QAbstractButton*)));
+ QSignalSpy accept(&buttonBox, SIGNAL(accepted()));
+ QSignalSpy reject(&buttonBox, SIGNAL(rejected()));
+ QSignalSpy helpRequested(&buttonBox, SIGNAL(helpRequested()));
+
+ QPushButton *clickMe = 0;
+ for (int i = QDialogButtonBox::AcceptRole; i < QDialogButtonBox::NRoles; ++i) {
+ QPushButton *button = buttonBox.addButton(QString::number(i),
+ QDialogButtonBox::ButtonRole(i));
+
+ if (i == buttonToClick)
+ clickMe = button;
+ }
+ if (clickMe) {
+ clickMe->animateClick(0);
+ QTest::qWait(100);
+ }
+
+ QTEST(clicked2.count(), "clicked2Count");
+ if (clicked2.count() > 0)
+ QCOMPARE(qvariant_cast<QAbstractButton *>(clicked2.at(0).at(0)), (QAbstractButton *)clickMe);
+
+ QTEST(accept.count(), "acceptCount");
+ QTEST(reject.count(), "rejectCount");
+ QTEST(helpRequested.count(), "helpRequestedCount");
+}
+
+void tst_QDialogButtonBox::testSignalOrder()
+{
+ const qint64 longLongZero = 0;
+ buttonClicked1TimeStamp = acceptTimeStamp
+ = rejectTimeStamp = helpRequestedTimeStamp = timeStamp = 0;
+ QDialogButtonBox buttonBox;
+ connect(&buttonBox, SIGNAL(clicked(QAbstractButton *)),
+ this, SLOT(buttonClicked1(QAbstractButton *)));
+ connect(&buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
+ connect(&buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
+ connect(&buttonBox, SIGNAL(helpRequested()), this, SLOT(helpRequestedClicked()));
+
+ QPushButton *acceptButton = buttonBox.addButton("OK", QDialogButtonBox::AcceptRole);
+ QPushButton *rejectButton = buttonBox.addButton("Cancel", QDialogButtonBox::RejectRole);
+ QPushButton *actionButton = buttonBox.addButton("Action This", QDialogButtonBox::ActionRole);
+ QPushButton *helpButton = buttonBox.addButton("Help Me!", QDialogButtonBox::HelpRole);
+
+ // Try accept
+ acceptButton->animateClick(0);
+ QTest::qWait(100);
+ QCOMPARE(rejectTimeStamp, longLongZero);
+ QCOMPARE(helpRequestedTimeStamp, longLongZero);
+
+ QVERIFY(buttonClicked1TimeStamp < acceptTimeStamp);
+ acceptTimeStamp = 0;
+
+ rejectButton->animateClick(0);
+ QTest::qWait(100);
+ QCOMPARE(acceptTimeStamp, longLongZero);
+ QCOMPARE(helpRequestedTimeStamp, longLongZero);
+ QVERIFY(buttonClicked1TimeStamp < rejectTimeStamp);
+
+ rejectTimeStamp = 0;
+ actionButton->animateClick(0);
+ QTest::qWait(100);
+ QCOMPARE(acceptTimeStamp, longLongZero);
+ QCOMPARE(rejectTimeStamp, longLongZero);
+ QCOMPARE(helpRequestedTimeStamp, longLongZero);
+
+ helpButton->animateClick(0);
+ QTest::qWait(100);
+ QCOMPARE(acceptTimeStamp, longLongZero);
+ QCOMPARE(rejectTimeStamp, longLongZero);
+ QVERIFY(buttonClicked1TimeStamp < helpRequestedTimeStamp);
+}
+
+void tst_QDialogButtonBox::buttonClicked1(QAbstractButton *)
+{
+ buttonClicked1TimeStamp = ++timeStamp;
+}
+
+void tst_QDialogButtonBox::acceptClicked()
+{
+ acceptTimeStamp = ++timeStamp;
+}
+
+void tst_QDialogButtonBox::rejectClicked()
+{
+ rejectTimeStamp = ++timeStamp;
+}
+
+void tst_QDialogButtonBox::helpRequestedClicked()
+{
+ helpRequestedTimeStamp = ++timeStamp;
+}
+
+void tst_QDialogButtonBox::setStandardButtons_data()
+{
+ QTest::addColumn<QDialogButtonBox::StandardButtons>("buttonsToAdd");
+ QTest::addColumn<QDialogButtonBox::StandardButtons>("expectedResult");
+
+ QTest::newRow("Nothing") << QDialogButtonBox::StandardButtons(QDialogButtonBox::NoButton)
+ << QDialogButtonBox::StandardButtons(QDialogButtonBox::NoButton);
+ QTest::newRow("Everything") << (QDialogButtonBox::StandardButtons)0xffffffff
+ << (QDialogButtonBox::Ok
+ | QDialogButtonBox::Open
+ | QDialogButtonBox::Save
+ | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Close
+ | QDialogButtonBox::Discard
+ | QDialogButtonBox::Apply
+ | QDialogButtonBox::Reset
+ | QDialogButtonBox::Help
+ | QDialogButtonBox::Yes
+ | QDialogButtonBox::YesToAll
+ | QDialogButtonBox::No
+ | QDialogButtonBox::NoToAll
+ | QDialogButtonBox::SaveAll
+ | QDialogButtonBox::Abort
+ | QDialogButtonBox::Retry
+ | QDialogButtonBox::Ignore
+ | QDialogButtonBox::RestoreDefaults
+ );
+ QTest::newRow("Simple thing") << QDialogButtonBox::StandardButtons(QDialogButtonBox::Help)
+ << QDialogButtonBox::StandardButtons(QDialogButtonBox::Help);
+ QTest::newRow("Standard thing") << (QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
+ << (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+}
+
+void tst_QDialogButtonBox::setStandardButtons()
+{
+ QFETCH(QDialogButtonBox::StandardButtons, buttonsToAdd);
+ QDialogButtonBox buttonBox;
+ buttonBox.setStandardButtons(buttonsToAdd);
+ QTEST(buttonBox.standardButtons(), "expectedResult");
+}
+
+void tst_QDialogButtonBox::standardButtons()
+{
+ // Test various cases of setting StandardButtons
+ QDialogButtonBox buttonBox;
+
+ QCOMPARE(buttonBox.standardButtons(),
+ QDialogButtonBox::StandardButtons(QDialogButtonBox::NoButton));
+
+ // Set some buttons
+ buttonBox.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ QCOMPARE(buttonBox.standardButtons(), QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+ // Now add a button
+ buttonBox.addButton(QDialogButtonBox::Apply);
+ QCOMPARE(buttonBox.standardButtons(),
+ QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply);
+
+ // Set the standard buttons to other things
+ buttonBox.setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Discard);
+ QCOMPARE(buttonBox.standardButtons(), QDialogButtonBox::Save | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Discard);
+ QCOMPARE(buttonBox.buttons().size(), 3);
+
+ // Add another button (not a standard one)
+ buttonBox.addButton(QLatin1String("Help"), QDialogButtonBox::HelpRole);
+ QCOMPARE(buttonBox.standardButtons(), QDialogButtonBox::Save | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Discard);
+ QCOMPARE(buttonBox.buttons().size(), 4);
+
+ // Finally, check if we construct with standard buttons that they show up.
+ QDialogButtonBox buttonBox2(QDialogButtonBox::Open | QDialogButtonBox::Reset);
+ QCOMPARE(buttonBox2.standardButtons(), QDialogButtonBox::Open | QDialogButtonBox::Reset);
+}
+
+void tst_QDialogButtonBox::testRemove()
+{
+ // Make sure that removing a button and clicking it, doesn't trigger any latent signals
+ QDialogButtonBox buttonBox;
+ QSignalSpy clicked(&buttonBox, SIGNAL(clicked(QAbstractButton*)));
+
+ QAbstractButton *button = buttonBox.addButton(QDialogButtonBox::Ok);
+
+ buttonBox.removeButton(button);
+
+ button->animateClick(0);
+ QTest::qWait(100);
+ QCOMPARE(clicked.count(), 0);
+ delete button;
+}
+
+void tst_QDialogButtonBox::testDefaultButton_data()
+{
+ QTest::addColumn<int>("whenToSetDefault"); // -1 Do nothing, 0 after accept, 1 before accept
+ QTest::addColumn<int>("buttonToBeDefault");
+ QTest::addColumn<int>("indexThatIsDefault");
+
+ QTest::newRow("do nothing First Accept implicit") << -1 << -1 << 0;
+ QTest::newRow("First accept explicit before add") << 1 << 0 << 0;
+ QTest::newRow("First accept explicit after add") << 0 << 0 << 0;
+ QTest::newRow("second accept explicit before add") << 1 << 1 << 1;
+ QTest::newRow("second accept explicit after add") << 0 << 1 << 1;
+ QTest::newRow("third accept explicit befare add") << 1 << 2 << 2;
+ QTest::newRow("third accept explicit after add") << 0 << 2 << 2;
+}
+
+static int softKeyCount(QWidget *widget)
+{
+ int softkeyCount = 0;
+#ifndef QT_NO_ACTION
+ QList<QAction *> actions = widget->actions();
+ foreach (QAction *action, actions) {
+ if (action->softKeyRole() != QAction::NoSoftKey)
+ softkeyCount++;
+ }
+#endif
+ return softkeyCount;
+}
+
+#ifdef QT_SOFTKEYS_ENABLED
+void tst_QDialogButtonBox::testSoftKeyReparenting()
+{
+ QDialog dialog;
+ QDialogButtonBox *buttonBox = new QDialogButtonBox;
+ buttonBox->addButton(QDialogButtonBox::Ok);
+ buttonBox->addButton(QDialogButtonBox::Cancel);
+
+#ifndef QT_NO_ACTION
+ QCOMPARE(softKeyCount(&dialog), 0);
+ QCOMPARE(softKeyCount(buttonBox), 2);
+#endif
+
+ // Were the softkeys re-parented correctly?
+ dialog.setLayout(new QVBoxLayout);
+ dialog.layout()->addWidget(buttonBox);
+#ifndef QT_NO_ACTION
+ QCOMPARE(softKeyCount(&dialog), 2);
+ QCOMPARE(softKeyCount(buttonBox), 0);
+#endif
+
+ // Softkeys are only added to QDialog, not QWidget
+ QWidget *nested = new QWidget;
+ nested->setLayout(new QVBoxLayout);
+ nested->layout()->addWidget(buttonBox);
+#ifndef QT_NO_ACTION
+ QCOMPARE(softKeyCount(nested), 0);
+ QCOMPARE(softKeyCount(buttonBox), 2);
+#endif
+}
+#endif
+
+void tst_QDialogButtonBox::testDefaultButton()
+{
+ QFETCH(int, whenToSetDefault);
+ QFETCH(int, buttonToBeDefault);
+ QFETCH(int, indexThatIsDefault);
+ QDialogButtonBox buttonBox;
+ QPushButton *buttonArray[] = { new QPushButton("Foo"), new QPushButton("Bar"), new QPushButton("Baz") };
+
+ for (int i = 0; i < 3; ++i) {
+ if (whenToSetDefault == 1 && i == buttonToBeDefault)
+ buttonArray[i]->setDefault(true);
+ buttonBox.addButton(buttonArray[i], QDialogButtonBox::AcceptRole);
+ if (whenToSetDefault == 0 && i == buttonToBeDefault)
+ buttonArray[i]->setDefault(true);
+ }
+ buttonBox.show();
+
+ for (int i = 0; i < 3; ++i) {
+ if (i == indexThatIsDefault)
+ QVERIFY(buttonArray[i]->isDefault());
+ else
+ QVERIFY(!buttonArray[i]->isDefault());
+ }
+}
+
+void tst_QDialogButtonBox::task191642_default()
+{
+ QDialog dlg;
+ QPushButton *def = new QPushButton(&dlg);
+ QSignalSpy clicked(def, SIGNAL(clicked(bool)));
+ def->setDefault(true);
+ QDialogButtonBox *bb = new QDialogButtonBox(&dlg);
+ bb->addButton(QDialogButtonBox::Ok);
+ bb->addButton(QDialogButtonBox::Cancel);
+ bb->addButton(QDialogButtonBox::Help);
+
+ dlg.show();
+ QTest::qWait(10);
+ QVERIFY(def->isDefault());
+ QTest::keyPress( &dlg, Qt::Key_Enter );
+ QTest::qWait(100);
+ QCOMPARE(clicked.count(), 1);
+}
+
+QTEST_MAIN(tst_QDialogButtonBox)
+#include "tst_qdialogbuttonbox.moc"
diff --git a/tests/auto/widgets/widgets/qdockwidget/.gitignore b/tests/auto/widgets/widgets/qdockwidget/.gitignore
new file mode 100644
index 0000000000..7c79145a67
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdockwidget/.gitignore
@@ -0,0 +1 @@
+tst_qdockwidget
diff --git a/tests/auto/widgets/widgets/qdockwidget/qdockwidget.pro b/tests/auto/widgets/widgets/qdockwidget/qdockwidget.pro
new file mode 100644
index 0000000000..e59728207f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdockwidget/qdockwidget.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qdockwidget.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
new file mode 100644
index 0000000000..2c1f7c0954
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -0,0 +1,877 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#include <QtTest/QtTest>
+
+
+#include <qaction.h>
+#include <qdockwidget.h>
+#include <qmainwindow.h>
+#include <qlineedit.h>
+#include <QDesktopWidget>
+#include <QtGui/QPainter>
+#include "private/qdockwidget_p.h"
+
+bool hasFeature(QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature)
+{ return (dockwidget->features() & feature) == feature; }
+
+void setFeature(QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature, bool on = true)
+{
+ const QDockWidget::DockWidgetFeatures features = dockwidget->features();
+ dockwidget->setFeatures(on ? features | feature : features & ~feature);
+}
+
+//TESTED_FILES=
+
+class tst_QDockWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QDockWidget();
+
+private slots:
+ void getSetCheck();
+ void widget();
+ void features();
+ void setFloating();
+ void allowedAreas();
+ void toggleViewAction();
+ void visibilityChanged();
+ void dockLocationChanged();
+ void setTitleBarWidget();
+ void titleBarDoubleClick();
+ void restoreStateOfFloating();
+ // task specific tests:
+ void task165177_deleteFocusWidget();
+ void task169808_setFloating();
+ void task237438_setFloatingCrash();
+ void task248604_infiniteResize();
+ void task258459_visibilityChanged();
+ void taskQTBUG_1665_closableChanged();
+ void taskQTBUG_9758_undockedGeometry();
+};
+
+// Testing get/set functions
+void tst_QDockWidget::getSetCheck()
+{
+ QDockWidget obj1;
+ // QWidget * QDockWidget::widget()
+ // void QDockWidget::setWidget(QWidget *)
+ QWidget *var1 = new QWidget();
+ obj1.setWidget(var1);
+ QCOMPARE(var1, obj1.widget());
+ obj1.setWidget((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.widget());
+ delete var1;
+
+ // DockWidgetFeatures QDockWidget::features()
+ // void QDockWidget::setFeatures(DockWidgetFeatures)
+ obj1.setFeatures(QDockWidget::DockWidgetFeatures(QDockWidget::DockWidgetClosable));
+ QCOMPARE(QDockWidget::DockWidgetFeatures(QDockWidget::DockWidgetClosable), obj1.features());
+ obj1.setFeatures(QDockWidget::DockWidgetFeatures(QDockWidget::DockWidgetMovable));
+ QCOMPARE(QDockWidget::DockWidgetFeatures(QDockWidget::DockWidgetMovable), obj1.features());
+ obj1.setFeatures(QDockWidget::DockWidgetFeatures(QDockWidget::DockWidgetFloatable));
+ QCOMPARE(QDockWidget::DockWidgetFeatures(QDockWidget::DockWidgetFloatable), obj1.features());
+ obj1.setFeatures(QDockWidget::DockWidgetFeatures(QDockWidget::AllDockWidgetFeatures));
+ QCOMPARE(QDockWidget::DockWidgetFeatures(QDockWidget::AllDockWidgetFeatures), obj1.features());
+ obj1.setFeatures(QDockWidget::DockWidgetFeatures(QDockWidget::NoDockWidgetFeatures));
+ QCOMPARE(QDockWidget::DockWidgetFeatures(QDockWidget::NoDockWidgetFeatures), obj1.features());
+}
+
+tst_QDockWidget::tst_QDockWidget()
+{
+ qRegisterMetaType<QDockWidget::DockWidgetFeatures>("QDockWidget::DockWidgetFeatures");
+ qRegisterMetaType<Qt::DockWidgetAreas>("Qt::DockWidgetAreas");
+}
+
+void tst_QDockWidget::widget()
+{
+ {
+ QDockWidget dw;
+ QVERIFY(dw.widget() == 0);
+ }
+
+ {
+ QDockWidget dw;
+ QWidget *w1 = new QWidget;
+ QWidget *w2 = new QWidget;
+
+ dw.setWidget(w1);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w1);
+ QCOMPARE(w1->parentWidget(), (QWidget*)&dw);
+
+ dw.setWidget(0);
+ QVERIFY(dw.widget() == 0);
+
+ dw.setWidget(w2);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w2);
+ QCOMPARE(w2->parentWidget(), (QWidget*)&dw);
+
+ dw.setWidget(0);
+ QVERIFY(dw.widget() == 0);
+
+ dw.setWidget(w1);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w1);
+ QCOMPARE(w1->parentWidget(), (QWidget*)&dw);
+
+ dw.setWidget(w2);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w2);
+ QCOMPARE(w2->parentWidget(), (QWidget*)&dw);
+
+ dw.setWidget(0);
+ QVERIFY(dw.widget() == 0);
+ }
+
+ {
+ QDockWidget dw;
+ QWidget *w1 = new QWidget;
+ QWidget *w2 = new QWidget;
+
+ dw.setWidget(w1);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w1);
+ QCOMPARE(w1->parentWidget(), (QWidget*)&dw);
+
+ w1->setParent(0);
+ QVERIFY(dw.widget() == 0);
+
+ dw.setWidget(w2);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w2);
+ QCOMPARE(w2->parentWidget(), (QWidget*)&dw);
+
+ w2->setParent(0);
+ QVERIFY(dw.widget() == 0);
+
+ dw.setWidget(w1);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w1);
+ QCOMPARE(w1->parentWidget(), (QWidget*)&dw);
+
+ dw.setWidget(w2);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w2);
+ QCOMPARE(w2->parentWidget(), (QWidget*)&dw);
+
+ w1->setParent(0);
+ QVERIFY(dw.widget() != 0);
+ QVERIFY(dw.widget() == w2);
+ QCOMPARE(w2->parentWidget(), (QWidget*)&dw);
+
+ w2->setParent(0);
+ QVERIFY(dw.widget() == 0);
+ delete w1;
+ delete w2;
+ }
+}
+
+void tst_QDockWidget::features()
+{
+ QDockWidget dw;
+
+ QSignalSpy spy(&dw, SIGNAL(featuresChanged(QDockWidget::DockWidgetFeatures)));
+
+ // default features for dock widgets
+ int allDockWidgetFeatures = QDockWidget::DockWidgetClosable |
+ QDockWidget::DockWidgetMovable |
+ QDockWidget::DockWidgetFloatable;
+
+ // defaults
+ QCOMPARE(dw.features(), allDockWidgetFeatures);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+
+ // test individual setting
+ setFeature(&dw, QDockWidget::DockWidgetClosable, false);
+ QCOMPARE(dw.features(), QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
+ QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*(static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData())),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ setFeature(&dw, QDockWidget::DockWidgetClosable);
+ QCOMPARE(dw.features(), allDockWidgetFeatures);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ setFeature(&dw, QDockWidget::DockWidgetMovable, false);
+ QCOMPARE(dw.features(), QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ setFeature(&dw, QDockWidget::DockWidgetMovable);
+ QCOMPARE(dw.features(), allDockWidgetFeatures);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ setFeature(&dw, QDockWidget::DockWidgetFloatable, false);
+ QCOMPARE(dw.features(), QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ setFeature(&dw, QDockWidget::DockWidgetFloatable);
+ QCOMPARE(dw.features(), allDockWidgetFeatures);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ // set all at once
+ dw.setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
+ QCOMPARE(dw.features(), QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ dw.setFeatures(QDockWidget::DockWidgetClosable);
+ QCOMPARE(dw.features(), QDockWidget::DockWidgetClosable);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ dw.setFeatures(QDockWidget::AllDockWidgetFeatures);
+ QCOMPARE(dw.features(), QDockWidget::AllDockWidgetFeatures);
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable));
+ QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()),
+ (int)dw.features());
+ spy.clear();
+ dw.setFeatures(dw.features());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+}
+
+void tst_QDockWidget::setFloating()
+{
+ QMainWindow mw;
+ QDockWidget dw;
+ mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+
+ mw.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mw);
+#endif
+
+ QVERIFY(!dw.isFloating());
+
+ QSignalSpy spy(&dw, SIGNAL(topLevelChanged(bool)));
+
+ dw.setFloating(true);
+ QVERIFY(dw.isFloating());
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).value(0).toBool(), dw.isFloating());
+ spy.clear();
+ dw.setFloating(dw.isFloating());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+
+ dw.setFloating(false);
+ QVERIFY(!dw.isFloating());
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).value(0).toBool(), dw.isFloating());
+ spy.clear();
+ dw.setFloating(dw.isFloating());
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+}
+
+void tst_QDockWidget::allowedAreas()
+{
+ QDockWidget dw;
+
+ QSignalSpy spy(&dw, SIGNAL(allowedAreasChanged(Qt::DockWidgetAreas)));
+
+ // default
+ QCOMPARE(dw.allowedAreas(), Qt::AllDockWidgetAreas);
+ QVERIFY(dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+
+ // a single dock window area
+ dw.setAllowedAreas(Qt::LeftDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::LeftDockWidgetArea);
+ QVERIFY(dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ dw.setAllowedAreas(Qt::RightDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::RightDockWidgetArea);
+ QVERIFY(!dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ dw.setAllowedAreas(Qt::TopDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::TopDockWidgetArea);
+ QVERIFY(!dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ dw.setAllowedAreas(Qt::BottomDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::BottomDockWidgetArea);
+ QVERIFY(!dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ // multiple dock window areas
+ dw.setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+ QVERIFY(!dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ dw.setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ QVERIFY(dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ dw.setAllowedAreas(Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea);
+ QVERIFY(dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ dw.setAllowedAreas(Qt::BottomDockWidgetArea | Qt::RightDockWidgetArea);
+ QCOMPARE(dw.allowedAreas(), Qt::BottomDockWidgetArea | Qt::RightDockWidgetArea);
+ QVERIFY(!dw.isAreaAllowed(Qt::LeftDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::RightDockWidgetArea));
+ QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea));
+ QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()),
+ dw.allowedAreas());
+ spy.clear();
+ dw.setAllowedAreas(dw.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QDockWidget::toggleViewAction()
+{
+ QMainWindow mw;
+ QDockWidget dw(&mw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+ mw.show();
+ QAction *toggleViewAction = dw.toggleViewAction();
+ QVERIFY(!dw.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(dw.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(!dw.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(dw.isHidden());
+}
+
+void tst_QDockWidget::visibilityChanged()
+{
+ QMainWindow mw;
+ QDockWidget dw;
+ QSignalSpy spy(&dw, SIGNAL(visibilityChanged(bool)));
+
+ mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+ mw.show();
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+ spy.clear();
+
+ dw.hide();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), false);
+ spy.clear();
+
+ dw.hide();
+ QCOMPARE(spy.count(), 0);
+
+ dw.show();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+ spy.clear();
+
+ dw.show();
+ QCOMPARE(spy.count(), 0);
+
+ QDockWidget dw2;
+ mw.tabifyDockWidget(&dw, &dw2);
+ dw2.show();
+ dw2.raise();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), false);
+ spy.clear();
+
+ dw2.hide();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+ spy.clear();
+
+ dw2.show();
+ dw2.raise();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), false);
+ spy.clear();
+
+ dw.raise();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+ spy.clear();
+
+ dw.raise();
+ QCOMPARE(spy.count(), 0);
+
+ dw2.raise();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), false);
+ spy.clear();
+
+ dw2.raise();
+ QCOMPARE(spy.count(), 0);
+
+ mw.addDockWidget(Qt::RightDockWidgetArea, &dw2);
+ QTest::qWait(200);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+}
+
+Q_DECLARE_METATYPE(Qt::DockWidgetArea)
+
+void tst_QDockWidget::dockLocationChanged()
+{
+ qRegisterMetaType<Qt::DockWidgetArea>("Qt::DockWidgetArea");
+
+ QMainWindow mw;
+ QDockWidget dw;
+ dw.setObjectName("dock1");
+ QSignalSpy spy(&dw, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)));
+
+ mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::LeftDockWidgetArea);
+ spy.clear();
+
+ mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::LeftDockWidgetArea);
+ spy.clear();
+
+ mw.addDockWidget(Qt::RightDockWidgetArea, &dw);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::RightDockWidgetArea);
+ spy.clear();
+
+ mw.removeDockWidget(&dw);
+ QCOMPARE(spy.count(), 0);
+
+ QDockWidget dw2;
+ dw2.setObjectName("dock2");
+ mw.addDockWidget(Qt::TopDockWidgetArea, &dw2);
+ mw.tabifyDockWidget(&dw2, &dw);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::TopDockWidgetArea);
+ spy.clear();
+
+ mw.splitDockWidget(&dw2, &dw, Qt::Horizontal);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::TopDockWidgetArea);
+ spy.clear();
+
+ dw.setFloating(true);
+ QTest::qWait(100);
+ dw.setFloating(false);
+ QTest::qWait(100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::TopDockWidgetArea);
+ spy.clear();
+
+ QByteArray ba = mw.saveState();
+ mw.restoreState(ba);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::TopDockWidgetArea);
+}
+
+void tst_QDockWidget::setTitleBarWidget()
+{
+ //test the successive usage of setTitleBarWidget
+
+ QDockWidget dock;
+ QWidget w, w2;
+
+ dock.show();
+ qApp->processEvents();
+
+ dock.setTitleBarWidget(&w);
+ qApp->processEvents();
+ QCOMPARE(w.isVisible(), true);
+
+ //set another widget as the titlebar widget
+ dock.setTitleBarWidget(&w2); // this used to crash (task 184668)
+ qApp->processEvents();
+ QCOMPARE(w.isVisible(), false);
+ QCOMPARE(w2.isVisible(), true);
+
+ //tries to reset the titlebarwidget to none
+ dock.setTitleBarWidget(0);
+ qApp->processEvents();
+ QCOMPARE(w.isVisible(), false);
+ QCOMPARE(w2.isVisible(), false);
+}
+
+void tst_QDockWidget::titleBarDoubleClick()
+{
+ QMainWindow win;
+ QDockWidget dock(&win);
+ win.show();
+ dock.setFloating(true);
+
+ QEvent e(QEvent::NonClientAreaMouseButtonDblClick);
+ QApplication::sendEvent(&dock, &e);
+ QVERIFY(dock.isFloating());
+ QCOMPARE(win.dockWidgetArea(&dock), Qt::NoDockWidgetArea);
+
+ win.addDockWidget(Qt::TopDockWidgetArea, &dock);
+ dock.setFloating(true);
+ QApplication::sendEvent(&dock, &e);
+ QVERIFY(!dock.isFloating());
+ QCOMPARE(win.dockWidgetArea(&dock), Qt::TopDockWidgetArea);
+}
+
+void tst_QDockWidget::restoreStateOfFloating()
+{
+ QMainWindow mw;
+ QDockWidget dock;
+ dock.setObjectName("dock1");
+ mw.addDockWidget(Qt::TopDockWidgetArea, &dock);
+ QVERIFY(!dock.isFloating());
+ QByteArray ba = mw.saveState();
+ dock.setFloating(true);
+ QVERIFY(dock.isFloating());
+ QVERIFY(mw.restoreState(ba));
+ QVERIFY(!dock.isFloating());
+}
+
+
+void tst_QDockWidget::task165177_deleteFocusWidget()
+{
+ QMainWindow mw;
+ QDockWidget *dw = new QDockWidget(&mw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, dw);
+ QLineEdit *ledit = new QLineEdit;
+ dw->setWidget(ledit);
+ mw.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mw);
+#endif
+ qApp->processEvents();
+ dw->setFloating(true);
+ delete ledit;
+ QCOMPARE(mw.focusWidget(), (QWidget *)0);
+ QCOMPARE(dw->focusWidget(), (QWidget *)0);
+}
+
+void tst_QDockWidget::task169808_setFloating()
+{
+ //we try to test if the sizeHint of the dock widget widget is taken into account
+
+ class MyWidget : public QWidget
+ {
+ public:
+ QSize sizeHint() const
+ {
+ const QRect& deskRect = qApp->desktop()->availableGeometry();
+ return QSize(qMin(300, deskRect.width()), 300);
+ }
+
+ QSize minimumSizeHint() const
+ {
+ return QSize(20,20);
+ }
+
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter p(this);
+ p.fillRect(rect(), Qt::red);
+ }
+ };
+ QMainWindow mw;
+ mw.setCentralWidget(new MyWidget);
+ QDockWidget *dw = new QDockWidget("my dock");
+ dw->setWidget(new MyWidget);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, dw);
+ dw->setFloating(true);
+ mw.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mw);
+#endif
+
+ QCOMPARE(dw->widget()->size(), dw->widget()->sizeHint());
+
+ //and now we try to test if the contents margin is taken into account
+ dw->widget()->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ dw->setFloating(false);
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mw);
+#endif
+ QTest::qWait(100); //leave time processing events
+
+
+ const QSize oldSize = dw->size();
+ const int margin = 20;
+
+ dw->setContentsMargins(margin, margin, margin, margin);
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mw);
+#endif
+ QTest::qWait(100); //leave time processing events
+
+ //widget size shouldn't have changed
+ QCOMPARE(dw->widget()->size(), dw->widget()->sizeHint());
+ //dockwidget should be bigger
+ QCOMPARE(dw->size(), oldSize + QSize(margin * 2, margin * 2));
+
+
+}
+
+void tst_QDockWidget::task237438_setFloatingCrash()
+{
+ //should not crash
+ QDockWidget pqdwDock;
+ pqdwDock.setFloating(false);
+ pqdwDock.show();
+}
+
+void tst_QDockWidget::task248604_infiniteResize()
+{
+ QDockWidget d;
+ QTabWidget *t = new QTabWidget;
+ t->addTab(new QWidget, "Foo");
+ d.setWidget(t);
+ d.setContentsMargins(2, 2, 2, 2);
+ d.setMinimumSize(320, 240);
+ d.show();
+ QTest::qWait(400);
+ QCOMPARE(d.size(), QSize(320, 240));
+}
+
+
+void tst_QDockWidget::task258459_visibilityChanged()
+{
+ QMainWindow win;
+ QDockWidget dock1, dock2;
+ win.addDockWidget(Qt::RightDockWidgetArea, &dock1);
+ win.tabifyDockWidget(&dock1, &dock2);
+ QSignalSpy spy1(&dock1, SIGNAL(visibilityChanged(bool)));
+ QSignalSpy spy2(&dock2, SIGNAL(visibilityChanged(bool)));
+ win.show();
+ QTest::qWait(200);
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy1.first().first().toBool(), false); //dock1 is invisible
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy2.first().first().toBool(), true); //dock1 is visible
+}
+
+void tst_QDockWidget::taskQTBUG_1665_closableChanged()
+{
+ QDockWidget dock;
+ dock.show();
+ QTest::qWaitForWindowShown(&dock);
+
+ QDockWidgetLayout *l = qobject_cast<QDockWidgetLayout*>(dock.layout());
+
+ if (l && !l->nativeWindowDeco())
+ QSKIP("this machine doesn't support native dock widget", SkipAll);
+
+ QVERIFY(dock.windowFlags() & Qt::WindowCloseButtonHint);
+
+ //now let's remove the closable attribute
+ dock.setFeatures(dock.features() ^ QDockWidget::DockWidgetClosable);
+ QVERIFY(!(dock.windowFlags() & Qt::WindowCloseButtonHint));
+}
+
+void tst_QDockWidget::taskQTBUG_9758_undockedGeometry()
+{
+ QMainWindow window;
+ QDockWidget dock1(&window);
+ QDockWidget dock2(&window);
+ window.addDockWidget(Qt::RightDockWidgetArea, &dock1);
+ window.addDockWidget(Qt::RightDockWidgetArea, &dock2);
+ window.tabifyDockWidget(&dock1, &dock2);
+ dock1.hide();
+ dock2.hide();
+ window.show();
+ QTest::qWaitForWindowShown(&window);
+ dock1.setFloating(true);
+ dock1.show();
+ QTest::qWaitForWindowShown(&dock1);
+
+ QVERIFY(dock1.x() >= 0);
+ QVERIFY(dock1.y() >= 0);
+}
+
+
+
+QTEST_MAIN(tst_QDockWidget)
+#include "tst_qdockwidget.moc"
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/.gitignore b/tests/auto/widgets/widgets/qdoublespinbox/.gitignore
new file mode 100644
index 0000000000..7704132e98
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublespinbox/.gitignore
@@ -0,0 +1 @@
+tst_qdoublespinbox
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/qdoublespinbox.pro b/tests/auto/widgets/widgets/qdoublespinbox/qdoublespinbox.pro
new file mode 100644
index 0000000000..ff0eb2edae
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublespinbox/qdoublespinbox.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdoublespinbox.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
new file mode 100644
index 0000000000..15f38e3334
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
@@ -0,0 +1,1111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <limits.h>
+
+#include <float.h>
+
+#include <qspinbox.h>
+#include <qlocale.h>
+#include <qlayout.h>
+
+#include <qlineedit.h>
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/widgets/qspinbox.h gui/widgets/qspinbox.cpp gui/widgets/qabstractspinbox.cpp gui/widgets/qabstractspinbox_p.h gui/widgets/qabstractspinbox.h
+
+
+class DoubleSpinBox : public QDoubleSpinBox
+{
+ Q_OBJECT
+public:
+ DoubleSpinBox(QWidget *parent = 0)
+ : QDoubleSpinBox(parent)
+ { /*connect(this, SIGNAL(valueChanged(double)), this, SLOT(foo(double)));*/ }
+ QString textFromValue(double v) const
+ {
+ return QDoubleSpinBox::textFromValue(v);
+ }
+ QValidator::State validate(QString &text, int &pos) const
+ {
+ return QDoubleSpinBox::validate(text, pos);
+ }
+ double valueFromText(const QString &text) const
+ {
+ return QDoubleSpinBox::valueFromText(text);
+ }
+
+ QLineEdit* lineEdit() const { return QDoubleSpinBox::lineEdit(); }
+public slots:
+ void foo(double vla)
+ {
+ qDebug() << vla;
+ }
+};
+
+
+class tst_QDoubleSpinBox : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDoubleSpinBox();
+ virtual ~tst_QDoubleSpinBox();
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+
+private slots:
+ void germanTest();
+
+ void task54433();
+
+ void setValue_data();
+ void setValue();
+
+ void setPrefixSuffix_data();
+ void setPrefixSuffix();
+
+ void setTracking_data();
+ void setTracking();
+
+ void setWrapping_data();
+ void setWrapping();
+
+ void setSpecialValueText_data();
+ void setSpecialValueText();
+
+ void setSingleStep_data();
+ void setSingleStep();
+
+ void setMinMax_data();
+ void setMinMax();
+
+ void setDecimals_data();
+ void setDecimals();
+
+ void doubleDot();
+
+ void undoRedo();
+
+ void valueFromTextAndValidate_data();
+ void valueFromTextAndValidate();
+
+ void setReadOnly();
+
+ void editingFinished();
+
+ void removeAll();
+
+ void task199226_stateAfterEnter();
+ void task224497_fltMax();
+
+ void task221221();
+ void task255471_decimalsValidation();
+
+ void taskQTBUG_5008_textFromValueAndValidate();
+ void taskQTBUG_6670_selectAllWithPrefix();
+ void taskQTBUG_6496_fiddlingWithPrecision();
+
+public slots:
+ void valueChangedHelper(const QString &);
+ void valueChangedHelper(double);
+private:
+ QStringList actualTexts;
+ QList<double> actualValues;
+ QWidget *testFocusWidget;
+};
+
+typedef QList<double> DoubleList;
+Q_DECLARE_METATYPE(DoubleList)
+
+tst_QDoubleSpinBox::tst_QDoubleSpinBox()
+
+{
+}
+
+tst_QDoubleSpinBox::~tst_QDoubleSpinBox()
+{
+
+}
+
+void tst_QDoubleSpinBox::initTestCase()
+{
+ testFocusWidget = new QWidget(0);
+ testFocusWidget->resize(200, 100);
+ testFocusWidget->show();
+}
+
+void tst_QDoubleSpinBox::cleanupTestCase()
+{
+ delete testFocusWidget;
+ testFocusWidget = 0;
+}
+
+void tst_QDoubleSpinBox::init()
+{
+ QLocale::setDefault(QLocale(QLocale::C));
+}
+
+void tst_QDoubleSpinBox::setValue_data()
+{
+ QTest::addColumn<double>("val");
+
+ QTest::newRow("data0") << 0.0;
+ QTest::newRow("data1") << 100.5;
+ QTest::newRow("data2") << -100.5;
+ QTest::newRow("data3") << -DBL_MAX;
+ QTest::newRow("data4") << DBL_MAX;
+}
+
+void tst_QDoubleSpinBox::setValue()
+{
+ QFETCH(double, val);
+ QDoubleSpinBox spin(0);
+ spin.setRange(-DBL_MAX, DBL_MAX);
+ spin.setValue(val);
+ QCOMPARE(spin.value(), val);
+}
+
+void tst_QDoubleSpinBox::setPrefixSuffix_data()
+{
+ QTest::addColumn<QString>("prefix");
+ QTest::addColumn<QString>("suffix");
+ QTest::addColumn<double>("value");
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedCleanText");
+ QTest::addColumn<bool>("show");
+
+ QTest::newRow("data0") << QString() << QString() << 10.5 << 1 << "10.5" << "10.5" << false;
+ QTest::newRow("data1") << QString() << "cm" << 10.5 << 2 << "10.50cm" << "10.50" << false;
+ QTest::newRow("data2") << "cm: " << QString() << 10.5 << 0 << "cm: 10" << "10" << false;
+ QTest::newRow("data3") << "length: " << "cm" << 10.5 << 3 << "length: 10.500cm" << "10.500" << false;
+
+ QTest::newRow("data4") << QString() << QString() << 10.5 << 1 << "10.5" << "10.5" << true;
+ QTest::newRow("data5") << QString() << "cm" << 10.5 << 2 << "10.50cm" << "10.50" << true;
+ QTest::newRow("data6") << "cm: " << QString() << 10.5 << 0 << "cm: 10" << "10" << true;
+ QTest::newRow("data7") << "length: " << "cm" << 10.5 << 3 << "length: 10.500cm" << "10.500" << true;
+}
+
+void tst_QDoubleSpinBox::setPrefixSuffix()
+{
+ QFETCH(QString, prefix);
+ QFETCH(QString, suffix);
+ QFETCH(double, value);
+ QFETCH(int, decimals);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedCleanText);
+ QFETCH(bool, show);
+
+ QDoubleSpinBox spin(0);
+ spin.setDecimals(decimals);
+ spin.setPrefix(prefix);
+ spin.setSuffix(suffix);
+ spin.setValue(value);
+ if (show)
+ spin.show();
+
+ QCOMPARE(spin.text(), expectedText);
+ QCOMPARE(spin.cleanText(), expectedCleanText);
+}
+
+void tst_QDoubleSpinBox::valueChangedHelper(const QString &text)
+{
+ actualTexts << text;
+}
+
+void tst_QDoubleSpinBox::valueChangedHelper(double value)
+{
+ actualValues << value;
+}
+
+void tst_QDoubleSpinBox::setTracking_data()
+{
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QStringList>("texts");
+ QTest::addColumn<bool>("tracking");
+
+ QTestEventList keys;
+ QStringList texts1;
+ QStringList texts2;
+#ifdef Q_WS_MAC
+ keys.addKeyClick(Qt::Key_Right, Qt::ControlModifier);
+#else
+ keys.addKeyClick(Qt::Key_End);
+#endif
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick('7');
+ keys.addKeyClick('.');
+ keys.addKeyClick('9');
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick('2');
+ keys.addKeyClick(Qt::Key_Enter);
+ keys.addKeyClick(Qt::Key_Enter);
+ keys.addKeyClick(Qt::Key_Enter);
+ texts1 << "7" << "7.9" << "7." << "7.2" << "7.200" << "7.200" << "7.200";
+ texts2 << "7.200";
+ QTest::newRow("data1") << 3 << keys << texts1 << true;
+ QTest::newRow("data2") << 3 << keys << texts2 << false;
+
+}
+
+void tst_QDoubleSpinBox::setTracking()
+{
+ QLocale::setDefault(QLocale(QLocale::C));
+
+ actualTexts.clear();
+ QFETCH(int, decimals);
+ QFETCH(QTestEventList, keys);
+ QFETCH(QStringList, texts);
+ QFETCH(bool, tracking);
+
+ QDoubleSpinBox spin(0);
+ spin.setKeyboardTracking(tracking);
+ spin.setDecimals(decimals);
+ spin.show();
+
+ connect(&spin, SIGNAL(valueChanged(QString)), this, SLOT(valueChangedHelper(const QString &)));
+
+ keys.simulate(&spin);
+ QCOMPARE(actualTexts, texts);
+}
+
+void tst_QDoubleSpinBox::setWrapping_data()
+{
+ QTest::addColumn<bool>("wrapping");
+ QTest::addColumn<double>("minimum");
+ QTest::addColumn<double>("maximum");
+ QTest::addColumn<double>("startValue");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<DoubleList>("expected");
+
+ QTestEventList keys;
+ DoubleList values;
+ keys.addKeyClick(Qt::Key_Up);
+ values << 10;
+ keys.addKeyClick(Qt::Key_Up);
+ QTest::newRow("data0") << false << 0.0 << 10.0 << 9.0 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_Up);
+ values << 10;
+ keys.addKeyClick(Qt::Key_Up);
+ values << 0;
+ QTest::newRow("data1") << true << 0.0 << 10.0 << 9.0 << keys << values;
+
+ keys.clear();
+ values.clear();
+#ifdef Q_WS_MAC
+ keys.addKeyClick(Qt::Key_Right, Qt::ControlModifier);
+#else
+ keys.addKeyClick(Qt::Key_End);
+#endif
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick('1');
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_PageDown);
+ values << 9.01 << 8.01 << 7.01 << 0.0;
+ QTest::newRow("data2") << false << 0.0 << 10.0 << 9.0 << keys << values;
+
+ keys.clear();
+ values.clear();
+#ifdef Q_WS_MAC
+ keys.addKeyClick(Qt::Key_Left, Qt::ControlModifier);
+#else
+ keys.addKeyClick(Qt::Key_Home);
+#endif
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick('1');
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 0 << 1 << 0 << 10;
+ QTest::newRow("data3") << true << 0.0 << 10.0 << 9.0 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 0;
+ QTest::newRow("data4") << false << 0.0 << 10.0 << 6.0 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 0 << 10;
+ QTest::newRow("data5") << true << 0.0 << 10.0 << 6.0 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_PageUp);
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_PageDown);
+ values << 10 << 0 << 10 << 0 << 10 << 0;
+ QTest::newRow("data6") << true << 0.0 << 10.0 << 6.0 << keys << values;
+
+}
+
+
+void tst_QDoubleSpinBox::setWrapping()
+{
+ QLocale::setDefault(QLocale(QLocale::C));
+ QFETCH(bool, wrapping);
+ QFETCH(double, minimum);
+ QFETCH(double, maximum);
+ QFETCH(double, startValue);
+ QFETCH(QTestEventList, keys);
+ QFETCH(DoubleList, expected);
+
+ QDoubleSpinBox spin(0);
+ spin.setMinimum(minimum);
+ spin.setMaximum(maximum);
+ spin.setValue(startValue);
+ spin.setWrapping(wrapping);
+ spin.show();
+ actualValues.clear();
+ connect(&spin, SIGNAL(valueChanged(double)), this, SLOT(valueChangedHelper(double)));
+
+ keys.simulate(&spin);
+
+ QCOMPARE(actualValues.size(), expected.size());
+ for (int i=0; i<qMin(actualValues.size(), expected.size()); ++i) {
+ QCOMPARE(actualValues.at(i), expected.at(i));
+ }
+}
+
+void tst_QDoubleSpinBox::setSpecialValueText_data()
+{
+ QTest::addColumn<QString>("specialValueText");
+ QTest::addColumn<double>("minimum");
+ QTest::addColumn<double>("maximum");
+ QTest::addColumn<double>("value");
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<bool>("show");
+
+ QTest::newRow("data0") << QString() << 0.0 << 10.0 << 1.0 << 4 << "1.0000" << false;
+ QTest::newRow("data1") << QString() << 0.0 << 10.0 << 1.0 << 4 << "1.0000" << true;
+ QTest::newRow("data2") << "foo" << 0.0 << 10.0 << 0.0 << 2 << "foo" << false;
+ QTest::newRow("data3") << "foo" << 0.0 << 10.0 << 0.0 << 2 << "foo" << true;
+}
+
+void tst_QDoubleSpinBox::setSpecialValueText()
+{
+ QFETCH(QString, specialValueText);
+ QFETCH(double, minimum);
+ QFETCH(double, maximum);
+ QFETCH(double, value);
+ QFETCH(int, decimals);
+ QFETCH(QString, expected);
+ QFETCH(bool, show);
+
+ QDoubleSpinBox spin(0);
+ spin.setSpecialValueText(specialValueText);
+ spin.setMinimum(minimum);
+ spin.setMaximum(maximum);
+ spin.setValue(value);
+ spin.setDecimals(decimals);
+ if (show)
+ spin.show();
+
+ QCOMPARE(spin.text(), expected);
+}
+
+void tst_QDoubleSpinBox::setSingleStep_data()
+{
+ QTest::addColumn<double>("singleStep");
+ QTest::addColumn<double>("startValue");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<DoubleList>("expected");
+ QTest::addColumn<bool>("show");
+
+ QTestEventList keys;
+ DoubleList values;
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Up);
+ values << 11 << 10 << 11;
+ QTest::newRow("data0") << 1.0 << 10.0 << keys << values << false;
+ QTest::newRow("data1") << 1.0 << 10.0 << keys << values << true;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Up);
+ values << 12.5 << 10.0 << 12.5;
+ QTest::newRow("data2") << 2.5 << 10.0 << keys << values << false;
+ QTest::newRow("data3") << 2.5 << 10.0 << keys << values << true;
+}
+
+void tst_QDoubleSpinBox::setSingleStep()
+{
+ QFETCH(double, singleStep);
+ QFETCH(double, startValue);
+ QFETCH(QTestEventList, keys);
+ QFETCH(DoubleList, expected);
+ QFETCH(bool, show);
+
+ QDoubleSpinBox spin(0);
+ actualValues.clear();
+ spin.setSingleStep(singleStep);
+ spin.setValue(startValue);
+ if (show)
+ spin.show();
+ connect(&spin, SIGNAL(valueChanged(double)), this, SLOT(valueChangedHelper(double)));
+
+ QCOMPARE(actualValues.size(), 0);
+ keys.simulate(&spin);
+ QCOMPARE(actualValues.size(), expected.size());
+ for (int i=0; i<qMin(actualValues.size(), expected.size()); ++i) {
+ QCOMPARE(actualValues.at(i), expected.at(i));
+ }
+}
+
+void tst_QDoubleSpinBox::setMinMax_data()
+{
+ QTest::addColumn<double>("startValue");
+ QTest::addColumn<double>("minimum");
+ QTest::addColumn<double>("maximum");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<double>("expected");
+ QTest::addColumn<bool>("show");
+
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ QTest::newRow("data0") << 1.0 << -DBL_MAX << 2.0 << keys << 2.0 << false;
+ QTest::newRow("data1") << 1.0 << -DBL_MAX << 2.0 << keys << 2.0 << true;
+ QTest::newRow("data2") << -20000.0 << -15000.0 << -13000.0 << keys << -14995.0 << false;
+ QTest::newRow("data3") << -20000.0 << -15000.0 << -13000.0 << keys << -14995.0 << true;
+ QTest::newRow("data4") << 20.0 << -101.2 << -102.0 << QTestEventList() << -102.0 << false;
+ QTest::newRow("data5") << 20.0 << -101.2 << -102.0 << QTestEventList() << -102.0 << true;
+}
+
+void tst_QDoubleSpinBox::setMinMax()
+{
+ QFETCH(double, startValue);
+ QFETCH(double, minimum);
+ QFETCH(double, maximum);
+ QFETCH(QTestEventList, keys);
+ QFETCH(double, expected);
+ QFETCH(bool, show);
+
+ {
+ QDoubleSpinBox spin(0);
+ spin.setMinimum(minimum);
+ spin.setMaximum(maximum);
+ spin.setValue(startValue);
+
+ if (show)
+ spin.show();
+ keys.simulate(&spin);
+ QCOMPARE(spin.value(), expected);
+ }
+
+ {
+ QDoubleSpinBox spin(0);
+ spin.setMaximum(maximum);
+ spin.setMinimum(minimum);
+ spin.setValue(startValue);
+
+ if (show)
+ spin.show();
+ keys.simulate(&spin);
+ }
+
+ {
+ QDoubleSpinBox spin(0);
+ spin.setRange(minimum, maximum);
+ spin.setValue(startValue);
+
+ if (show)
+ spin.show();
+ keys.simulate(&spin);
+ }
+
+
+}
+
+void tst_QDoubleSpinBox::setDecimals_data()
+{
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<int>("expectedDecimals");
+ QTest::addColumn<double>("startValue");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("data0") << 4 << 4 << 1.0 << "1.0000";
+ QTest::newRow("data1") << 1 << 1 << 1.243443 << "1.2";
+ QTest::newRow("data2") << 6 << 6 << 1.29 << "1.290000";
+ QTest::newRow("data3") << 8 << 8 << 9.1234567809 << "9.12345678";
+ QTest::newRow("data4") << 13 << 13 << 0.12345678901237 << "0.1234567890124";
+ QTest::newRow("data5") << 13 << 13 << -0.12345678901237 << "-0.1234567890124";
+ QTest::newRow("data6") << 13 << 13 << -0.12345678901237 << "-0.1234567890124";
+ QTest::newRow("data7") << -1 << 0 << 0.1 << "0";
+ QTest::newRow("data8") << 120 << 120 << -0.12345678901237 << "-0.123456789012370005131913330842508003115653991699218750000000000000000000000000000000000000000000000000000000000000000000";
+
+}
+
+void tst_QDoubleSpinBox::setDecimals()
+{
+ QFETCH(int, decimals);
+ QFETCH(int, expectedDecimals);
+ QFETCH(double, startValue);
+ QFETCH(QString, expected);
+
+ QDoubleSpinBox spin(0);
+ spin.setRange(-DBL_MAX, DBL_MAX);
+ spin.setDecimals(decimals);
+ spin.setValue(startValue);
+ QCOMPARE(spin.decimals(), expectedDecimals);
+ if (sizeof(qreal) == sizeof(float))
+ QCOMPARE(spin.text().left(17), expected.left(17));
+ else
+ QCOMPARE(spin.text(), expected);
+
+ if (spin.decimals() > 0) {
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_End);
+#endif
+ QTest::keyClick(&spin, Qt::Key_1); // just make sure we can't input more decimals than what is specified
+ QTest::keyClick(&spin, Qt::Key_1);
+ QTest::keyClick(&spin, Qt::Key_1);
+ QTest::keyClick(&spin, Qt::Key_1);
+ QTest::keyClick(&spin, Qt::Key_1);
+ if (sizeof(qreal) == sizeof(float))
+ QCOMPARE(spin.text().left(17), expected.left(17));
+ else
+ QCOMPARE(spin.text(), expected);
+ }
+}
+
+static QString stateName(int state)
+{
+ switch (state) {
+ case QValidator::Acceptable: return QString("Acceptable");
+ case QValidator::Intermediate: return QString("Intermediate");
+ case QValidator::Invalid: return QString("Invalid");
+ default: break;
+ }
+ qWarning("%s %d: this should never happen", __FILE__, __LINE__);
+ return QString();
+}
+
+void tst_QDoubleSpinBox::valueFromTextAndValidate_data()
+{
+ const int Intermediate = QValidator::Intermediate;
+ const int Invalid = QValidator::Invalid;
+ const int Acceptable = QValidator::Acceptable;
+
+ QTest::addColumn<QString>("txt");
+ QTest::addColumn<int>("state");
+ QTest::addColumn<double>("mini");
+ QTest::addColumn<double>("maxi");
+ QTest::addColumn<int>("language");
+ QTest::addColumn<QString>("expectedText"); // if empty we don't check
+
+ QTest::newRow("data0") << QString("2.2") << Intermediate << 3.0 << 5.0 << (int)QLocale::C << QString();
+ QTest::newRow("data1") << QString() << Intermediate << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data2") << QString("asd") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data3") << QString("2.2") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data4") << QString(" ") << Intermediate << 0.0 << 100.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data5") << QString(" ") << Intermediate << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data6") << QString(",") << Intermediate << 0.0 << 100.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data7") << QString(",") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data8") << QString("1 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::Norwegian << QString("1");
+ QTest::newRow("data9") << QString("1 ") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString("1");
+ QTest::newRow("data10") << QString(" 1") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString("1");
+ QTest::newRow("data11") << QString(" 1") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString("1");
+ QTest::newRow("data12") << QString("1,") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data13") << QString("1,") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
+ QTest::newRow("data14") << QString("1, ") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString("1,");
+ QTest::newRow("data15") << QString("1, ") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data16") << QString("2") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString();
+ QTest::newRow("data17") << QString("22.0") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString();
+ QTest::newRow("data18") << QString("12.0") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString();
+ QTest::newRow("data19") << QString("12.2") << Intermediate << 100. << 102.0 << (int)QLocale::C << QString();
+ QTest::newRow("data20") << QString("21.") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString();
+ QTest::newRow("data21") << QString("-21.") << Intermediate << -102.0 << -100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data22") << QString("-12.") << Intermediate << -102.0 << -100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data23") << QString("-11.11") << Intermediate << -102.0 << -101.2 << (int)QLocale::C << QString();
+ QTest::newRow("data24") << QString("-11.4") << Intermediate << -102.0 << -101.3 << (int)QLocale::C << QString();
+ QTest::newRow("data25") << QString("11.400") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
+ QTest::newRow("data26") << QString(".4") << Intermediate << 0.45 << 0.5 << (int)QLocale::C << QString();
+ QTest::newRow("data27") << QString("+.4") << Intermediate << 0.45 << 0.5 << (int)QLocale::C << QString();
+ QTest::newRow("data28") << QString("-.4") << Intermediate << -0.5 << -0.45 << (int)QLocale::C << QString();
+ QTest::newRow("data29") << QString(".4") << Intermediate << 1.0 << 2.4 << (int)QLocale::C << QString();
+ QTest::newRow("data30") << QString("-.4") << Intermediate << -2.3 << -1.9 << (int)QLocale::C << QString();
+ QTest::newRow("data31") << QString("-42") << Invalid << -2.43 << -1.0 << (int)QLocale::C << QString();
+ QTest::newRow("data32") << QString("-4") << Invalid << -1.4 << -1.0 << (int)QLocale::C << QString();
+ QTest::newRow("data33") << QString("-42") << Invalid << -1.4 << -1.0 << (int)QLocale::C << QString();
+ QTest::newRow("data34") << QString("1000000000000") << Invalid << -140.0 << -120.2 << (int)QLocale::C << QString();
+ QTest::newRow("data35") << QString("+.12") << Invalid << -5.0 << -3.2 << (int)QLocale::C << QString();
+ QTest::newRow("data36") << QString("-.12") << Invalid << 5.0 << 33.2 << (int)QLocale::C << QString();
+ QTest::newRow("data37") << QString("12.2") << Intermediate << 100. << 103.0 << (int)QLocale::C << QString();
+ QTest::newRow("data38") << QString("12.2") << Intermediate << 100. << 102.3 << (int)QLocale::C << QString();
+ QTest::newRow("data39") << QString("-12.") << Acceptable << -102.0 << 102.0 << (int)QLocale::C << QString();
+ QTest::newRow("data40") << QString("12.") << Invalid << -102.0 << 11.0 << (int)QLocale::C << QString();
+ QTest::newRow("data41") << QString("103.") << Invalid << -102.0 << 11.0 << (int)QLocale::C << QString();
+ QTest::newRow("data42") << QString("122") << Invalid << 10.0 << 12.2 << (int)QLocale::C << QString();
+ QTest::newRow("data43") << QString("-2.2") << Intermediate << -12.2 << -3.2 << (int)QLocale::C << QString();
+ QTest::newRow("data44") << QString("-2.20") << Intermediate << -12.1 << -3.2 << (int)QLocale::C << QString();
+ QTest::newRow("data45") << QString("200,2") << Invalid << 0.0 << 1000.0 << (int)QLocale::C << QString();
+ QTest::newRow("data46") << QString("200,2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::German << QString();
+ QTest::newRow("data47") << QString("2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
+ QTest::newRow("data48") << QString("2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::German << QString();
+ QTest::newRow("data49") << QString("2.2,00") << Acceptable << 0.0 << 1000.0 << (int)QLocale::German << QString();
+ QTest::newRow("data50") << QString("2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
+ QTest::newRow("data51") << QString("2.2,00") << Invalid << 0.0 << 1000.0 << (int)QLocale::C << QString();
+ QTest::newRow("data52") << QString("2..2,00") << Invalid << 0.0 << 1000.0 << (int)QLocale::German << QString();
+ QTest::newRow("data53") << QString("2.2") << Invalid << 0.0 << 1000.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data54") << QString(" 2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
+ QTest::newRow("data55") << QString("2.2 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString("2.2");
+ QTest::newRow("data56") << QString(" 2.2 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString("2.2");
+ QTest::newRow("data57") << QString("2 2") << Invalid << 0.0 << 1000.0 << (int)QLocale::C << QString();
+}
+
+void tst_QDoubleSpinBox::valueFromTextAndValidate()
+{
+ QFETCH(QString, txt);
+ QFETCH(int, state);
+ QFETCH(double, mini);
+ QFETCH(double, maxi);
+ QFETCH(int, language);
+ QFETCH(QString, expectedText);
+ QLocale::setDefault(QLocale((QLocale::Language)language));
+
+ DoubleSpinBox sb(0);
+ sb.show();
+ sb.setRange(mini, maxi);
+
+ int unused = 0;
+ QCOMPARE(stateName(sb.validate(txt, unused)), stateName(state));
+ if (!expectedText.isEmpty())
+ QCOMPARE(txt, expectedText);
+}
+
+void tst_QDoubleSpinBox::setReadOnly()
+{
+ QDoubleSpinBox spin(0);
+ spin.setValue(0.2);
+ spin.show();
+ QCOMPARE(spin.value(), 0.2);
+ QTest::keyClick(&spin, Qt::Key_Up);
+ QCOMPARE(spin.value(), 1.2);
+ spin.setReadOnly(true);
+ QTest::keyClick(&spin, Qt::Key_Up);
+ QCOMPARE(spin.value(), 1.2);
+ spin.stepBy(1);
+ QCOMPARE(spin.value(), 2.2);
+ spin.setReadOnly(false);
+ QTest::keyClick(&spin, Qt::Key_Up);
+ QCOMPARE(spin.value(), 3.2);
+}
+
+void tst_QDoubleSpinBox::editingFinished()
+{
+ QVBoxLayout *layout = new QVBoxLayout(testFocusWidget);
+ QDoubleSpinBox *box = new QDoubleSpinBox(testFocusWidget);
+ layout->addWidget(box);
+ QDoubleSpinBox *box2 = new QDoubleSpinBox(testFocusWidget);
+ layout->addWidget(box2);
+
+ testFocusWidget->show();
+ QApplication::setActiveWindow(testFocusWidget);
+ QTest::qWait(10);
+ QTRY_VERIFY(testFocusWidget->isActiveWindow());
+ box->setFocus();
+ QTRY_VERIFY(box->hasFocus());
+
+ QSignalSpy editingFinishedSpy1(box, SIGNAL(editingFinished()));
+ QSignalSpy editingFinishedSpy2(box2, SIGNAL(editingFinished()));
+
+ box->setFocus();
+ QTest::keyClick(box, Qt::Key_Up);
+ QTest::keyClick(box, Qt::Key_Up);
+
+
+ QCOMPARE(editingFinishedSpy1.count(), 0);
+ QCOMPARE(editingFinishedSpy2.count(), 0);
+
+ QTest::keyClick(box2, Qt::Key_Up);
+ QTest::keyClick(box2, Qt::Key_Up);
+ box2->setFocus();
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+ box->setFocus();
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box, Qt::Key_Up);
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box, Qt::Key_Enter);
+ QCOMPARE(editingFinishedSpy1.count(), 2);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box, Qt::Key_Return);
+ QCOMPARE(editingFinishedSpy1.count(), 3);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ box2->setFocus();
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box2, Qt::Key_Enter);
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 2);
+ QTest::keyClick(box2, Qt::Key_Return);
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 3);
+ testFocusWidget->hide();
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 4);
+
+}
+
+void tst_QDoubleSpinBox::removeAll()
+{
+ DoubleSpinBox spin(0);
+ spin.setPrefix("foo");
+ spin.setSuffix("bar");
+ spin.setValue(0.2);
+ spin.setDecimals(1);
+ spin.show();
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_Home);
+#endif
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Right, Qt::ControlModifier|Qt::ShiftModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_End, Qt::ShiftModifier);
+#endif
+
+ QCOMPARE(spin.lineEdit()->selectedText(), QString("foo0.2bar"));
+ QTest::keyClick(&spin, Qt::Key_1);
+ QCOMPARE(spin.text(), QString("foo1bar"));
+}
+
+void tst_QDoubleSpinBox::task54433()
+{
+ DoubleSpinBox priceSpinBox;
+ priceSpinBox.show();
+ priceSpinBox.setRange(0.0, 999.99);
+ priceSpinBox.setDecimals(2);
+ priceSpinBox.setValue(999.99);
+ QCOMPARE(priceSpinBox.text(), QString("999.99"));
+ QCOMPARE(priceSpinBox.value(), 999.99);
+ QCOMPARE(priceSpinBox.maximum(), 999.99);
+ priceSpinBox.setDecimals(1);
+ QCOMPARE(priceSpinBox.value(), 1000.0);
+ QCOMPARE(priceSpinBox.maximum(), 1000.0);
+ QCOMPARE(priceSpinBox.text(), QString("1000.0"));
+
+ priceSpinBox.setDecimals(2);
+ priceSpinBox.setRange(-999.99, 0.0);
+ priceSpinBox.setValue(-999.99);
+ QCOMPARE(priceSpinBox.text(), QString("-999.99"));
+ QCOMPARE(priceSpinBox.value(), -999.99);
+ QCOMPARE(priceSpinBox.minimum(), -999.99);
+ priceSpinBox.setDecimals(1);
+ QCOMPARE(priceSpinBox.value(), -1000.0);
+ QCOMPARE(priceSpinBox.minimum(), -1000.0);
+ QCOMPARE(priceSpinBox.text(), QString("-1000.0"));
+}
+
+
+
+void tst_QDoubleSpinBox::germanTest()
+{
+ QLocale::setDefault(QLocale(QLocale::German));
+ DoubleSpinBox spin;
+ spin.show();
+ spin.setValue(2.12);
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Right, Qt::ControlModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_End);
+#endif
+ QTest::keyClick(&spin, Qt::Key_Backspace);
+ QCOMPARE(spin.text(), QString("2,1"));
+ QTest::keyClick(&spin, Qt::Key_Enter);
+ QCOMPARE(spin.text(), QString("2,10"));
+}
+
+void tst_QDoubleSpinBox::doubleDot()
+{
+ DoubleSpinBox spin;
+ spin.show();
+ spin.setValue(2.12);
+ QTest::keyClick(&spin, Qt::Key_Backspace);
+ QCOMPARE(spin.text(), QString("2.12"));
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_Home);
+#endif
+ QTest::keyClick(&spin, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(spin.lineEdit()->selectedText(), QString("2"));
+ QTest::keyClick(&spin, Qt::Key_1);
+ QCOMPARE(spin.text(), QString("1.12"));
+ QCOMPARE(spin.lineEdit()->cursorPosition(), 1);
+ QTest::keyClick(&spin, Qt::Key_Period);
+ QCOMPARE(spin.text(), QString("1.12"));
+ QCOMPARE(spin.lineEdit()->cursorPosition(), 2);
+}
+
+void tst_QDoubleSpinBox::undoRedo()
+{
+ //test undo/redo feature (in conjunction with the "undoRedoEnabled" property)
+ DoubleSpinBox spin(0);
+ spin.show();
+
+ //the undo/redo is disabled by default
+
+ QCOMPARE(spin.value(), 0.0); //this is the default value
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+
+ spin.lineEdit()->selectAll(); //ensures everything is selected and will be cleared by typing a key
+ QTest::keyClick(&spin, Qt::Key_1); //we put 1 into the spinbox
+ QCOMPARE(spin.value(), 1.0);
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+
+ //testing CTRL+Z (undo)
+ int val = QKeySequence(QKeySequence::Undo)[0];
+ if (val != 0) {
+ Qt::KeyboardModifiers mods = (Qt::KeyboardModifiers)(val & Qt::KeyboardModifierMask);
+ QTest::keyClick(&spin, val & ~mods, mods);
+ QCOMPARE(spin.value(), 0.0);
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(spin.lineEdit()->isRedoAvailable());
+ } else {
+ QWARN("Undo not tested because no key sequence associated to QKeySequence::Redo");
+ }
+
+
+ //testing CTRL+Y (redo)
+ val = QKeySequence(QKeySequence::Redo)[0];
+ if (val != 0) {
+ Qt::KeyboardModifiers mods = (Qt::KeyboardModifiers)(val & Qt::KeyboardModifierMask);
+ QTest::keyClick(&spin, val & ~mods, mods);
+ QCOMPARE(spin.value(), 1.0);
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+ } else {
+ QWARN("Redo not tested because no key sequence associated to QKeySequence::Redo");
+ }
+
+
+ spin.setValue(55.0);
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+}
+
+struct task199226_DoubleSpinBox : public QDoubleSpinBox
+{
+ task199226_DoubleSpinBox(QWidget *parent = 0) : QDoubleSpinBox(parent) {}
+ QLineEdit *lineEdit() { return QAbstractSpinBox::lineEdit(); }
+};
+
+void tst_QDoubleSpinBox::task199226_stateAfterEnter()
+{
+ task199226_DoubleSpinBox spin;
+ spin.setMinimum(0);
+ spin.setMaximum(10);
+ spin.setDecimals(0);
+ spin.show();
+ QTest::mouseDClick(spin.lineEdit(), Qt::LeftButton);
+ QTest::keyClick(spin.lineEdit(), Qt::Key_3);
+ QVERIFY(spin.lineEdit()->isModified());
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+ QTest::keyClick(spin.lineEdit(), Qt::Key_Enter);
+ QVERIFY(!spin.lineEdit()->isModified());
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+}
+
+class task224497_fltMax_DoubleSpinBox : public QDoubleSpinBox
+{
+public:
+ QLineEdit * lineEdit () const { return QDoubleSpinBox::lineEdit(); }
+};
+
+void tst_QDoubleSpinBox::task224497_fltMax()
+{
+ task224497_fltMax_DoubleSpinBox *dspin = new task224497_fltMax_DoubleSpinBox;
+ dspin->setMinimum(3);
+ dspin->setMaximum(FLT_MAX);
+ dspin->show();
+ QTest::qWait(1000);
+ dspin->lineEdit()->selectAll();
+ QTest::keyClick(dspin->lineEdit(), Qt::Key_Delete);
+ QTest::keyClick(dspin->lineEdit(), Qt::Key_1);
+ QCOMPARE(dspin->cleanText(), QLatin1String("1"));
+}
+
+void tst_QDoubleSpinBox::task221221()
+{
+ QDoubleSpinBox spin;
+ QTest::keyClick(&spin, Qt::Key_1);
+ QCOMPARE(spin.text(), QLatin1String("1"));
+ spin.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&spin);
+#endif
+ QVERIFY(spin.isVisible());
+ QCOMPARE(spin.text(), QLatin1String("1"));
+}
+
+void tst_QDoubleSpinBox::task255471_decimalsValidation()
+{
+ // QDoubleSpinBox shouldn't crash with large numbers of decimals. Even if
+ // the results are useless ;-)
+ for (int i = 0; i < 32; ++i)
+ {
+ QDoubleSpinBox spinBox;
+ spinBox.setDecimals(i);
+ spinBox.setMinimum(0.3);
+ spinBox.setMaximum(12);
+
+ spinBox.show();
+ QTRY_VERIFY(spinBox.isVisible());
+ spinBox.setFocus();
+ QTRY_VERIFY(spinBox.hasFocus());
+
+ QTest::keyPress(&spinBox, Qt::Key_Right);
+ QTest::keyPress(&spinBox, Qt::Key_Right);
+ QTest::keyPress(&spinBox, Qt::Key_Delete);
+
+ // Don't crash!
+ QTest::keyPress(&spinBox, Qt::Key_2);
+ }
+}
+
+void tst_QDoubleSpinBox::taskQTBUG_5008_textFromValueAndValidate()
+{
+ class DecoratedSpinBox : public QDoubleSpinBox
+ {
+ public:
+ DecoratedSpinBox()
+ {
+ setLocale(QLocale::French);
+ setMaximum(100000000);
+ setValue(1000);
+ }
+
+ QLineEdit *lineEdit() const
+ {
+ return QDoubleSpinBox::lineEdit();
+ }
+
+ //we use the French delimiters here
+ QString textFromValue (double value) const
+ {
+ return locale().toString(value);
+ }
+ } spinbox;
+ spinbox.show();
+ spinbox.activateWindow();
+ spinbox.setFocus();
+ QApplication::setActiveWindow(&spinbox);
+ QTest::qWaitForWindowShown(&spinbox);
+ QTRY_VERIFY(spinbox.hasFocus());
+ QTRY_COMPARE(static_cast<QWidget *>(&spinbox), QApplication::activeWindow());
+ QCOMPARE(spinbox.text(), spinbox.locale().toString(spinbox.value()));
+ spinbox.lineEdit()->setCursorPosition(2); //just after the first thousand separator
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_0); // let's insert a 0
+ QCOMPARE(spinbox.value(), 10000.);
+ spinbox.clearFocus(); //make sure the value is correctly formatted
+ QCOMPARE(spinbox.text(), spinbox.locale().toString(spinbox.value()));
+}
+
+void tst_QDoubleSpinBox::taskQTBUG_6670_selectAllWithPrefix()
+{
+ DoubleSpinBox spin;
+ spin.setPrefix("$ ");
+ spin.lineEdit()->selectAll();
+ QTest::keyClick(spin.lineEdit(), Qt::Key_1);
+ QCOMPARE(spin.value(), 1.);
+ QTest::keyClick(spin.lineEdit(), Qt::Key_2);
+ QCOMPARE(spin.value(), 12.);
+}
+
+void tst_QDoubleSpinBox::taskQTBUG_6496_fiddlingWithPrecision()
+{
+ QDoubleSpinBox dsb;
+ dsb.setRange(0, 0.991);
+ dsb.setDecimals(1);
+ QCOMPARE(dsb.maximum(), 1.0);
+ dsb.setDecimals(2);
+ QCOMPARE(dsb.maximum(), 0.99);
+ dsb.setDecimals(3);
+ QCOMPARE(dsb.maximum(), 0.991);
+}
+
+QTEST_MAIN(tst_QDoubleSpinBox)
+#include "tst_qdoublespinbox.moc"
diff --git a/tests/auto/widgets/widgets/qdoublevalidator/.gitignore b/tests/auto/widgets/widgets/qdoublevalidator/.gitignore
new file mode 100644
index 0000000000..95c97bbc30
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublevalidator/.gitignore
@@ -0,0 +1 @@
+tst_qdoublevalidator
diff --git a/tests/auto/widgets/widgets/qdoublevalidator/qdoublevalidator.pro b/tests/auto/widgets/widgets/qdoublevalidator/qdoublevalidator.pro
new file mode 100644
index 0000000000..7fbb72bb7f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublevalidator/qdoublevalidator.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdoublevalidator.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/widgets/widgets/qdoublevalidator/tst_qdoublevalidator.cpp
new file mode 100644
index 0000000000..6014ce5165
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublevalidator/tst_qdoublevalidator.cpp
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qvalidator.h>
+
+class tst_QDoubleValidator : public QObject
+{
+ Q_OBJECT
+private slots:
+ void validate_data();
+ void validate();
+ void validateThouSep_data();
+ void validateThouSep();
+ void validateIntEquiv_data();
+ void validateIntEquiv();
+ void notifySignals();
+};
+
+Q_DECLARE_METATYPE(QValidator::State);
+#define INV QValidator::Invalid
+#define ITM QValidator::Intermediate
+#define ACC QValidator::Acceptable
+
+void tst_QDoubleValidator::validateThouSep_data()
+{
+ QTest::addColumn<QString>("localeName");
+ QTest::addColumn<QString>("value");
+ QTest::addColumn<QValidator::State>("result");
+
+ QTest::newRow("1,000C") << "C" << QString("1,000") << ACC;
+ QTest::newRow("1.000C") << "C" << QString("1.000") << ACC;
+
+ QTest::newRow("1,000de") << "de" << QString("1,000") << ACC;
+ QTest::newRow("1.000de") << "de" << QString("1.000") << ACC;
+
+ QTest::newRow(".C") << "C" << QString(".") << ITM;
+ QTest::newRow(".de") << "de" << QString(".") << ITM;
+ QTest::newRow(",C") << "C" << QString(",") << INV;
+ QTest::newRow(",de") << "de" << QString(",") << ITM;
+}
+
+void tst_QDoubleValidator::validateThouSep()
+{
+ QFETCH(QString, localeName);
+ QFETCH(QString, value);
+ QFETCH(QValidator::State, result);
+ int dummy = 0;
+
+ QDoubleValidator iv(-10000, 10000, 3, 0);
+ iv.setNotation(QDoubleValidator::ScientificNotation);
+ iv.setLocale(QLocale(localeName));
+
+ QCOMPARE(iv.validate(value, dummy), result);
+}
+
+void tst_QDoubleValidator::validate_data()
+{
+ QTest::addColumn<QString>("localeName");
+ QTest::addColumn<double>("minimum");
+ QTest::addColumn<double>("maximum");
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<QString>("value");
+ QTest::addColumn<QValidator::State>("scientific_state");
+ QTest::addColumn<QValidator::State>("standard_state");
+
+ QTest::newRow("data0") << "C" << 0.0 << 100.0 << 1 << QString("50.0") << ACC << ACC;
+ QTest::newRow("data1") << "C" << 00.0 << 100.0 << 1 << QString("500.0") << ITM << ITM;
+ QTest::newRow("data1a") << "C" << 00.0 << 100.0 << 1 << QString("5001.0") << ITM << INV;
+ QTest::newRow("data2") << "C" << 00.0 << 100.0 << 1 << QString("-35.0") << INV << INV;
+ QTest::newRow("data3") << "C" << 00.0 << 100.0 << 1 << QString("a") << INV << INV;
+ QTest::newRow("data4") << "C" << 0.0 << 100.0 << 1 << QString("-") << INV << INV;
+ QTest::newRow("data5") << "C" << 0.0 << 100.0 << 1 << QString("100.0") << ACC << ACC;
+ QTest::newRow("data6") << "C" << -100.0 << 100.0 << 1 << QString("-") << ITM << ITM;
+ QTest::newRow("data7") << "C" << -100.0 << 100.0 << 1 << QString("-500.0") << ITM << ITM;
+ QTest::newRow("data8") << "C" << -100.0 << 100.0 << 1 << QString("-100") << ACC << ACC;
+ QTest::newRow("data9") << "C" << -100.0 << -10.0 << 1 << QString("10") << ITM << ITM;
+ QTest::newRow("data10") << "C" << 0.3 << 0.5 << 5 << QString("0.34567") << ACC << ACC;
+ QTest::newRow("data11") << "C" << -0.3 << -0.5 << 5 << QString("-0.345678") << INV << INV;
+ QTest::newRow("data12") << "C" << -0.32 << 0.32 << 1 << QString("0") << ACC << ACC;
+ QTest::newRow("data13") << "C" << 0.0 << 100.0 << 1 << QString("3456a") << INV << INV;
+ QTest::newRow("data14") << "C" << -100.0 << 100.0 << 1 << QString("-3456a") << INV << INV;
+ QTest::newRow("data15") << "C" << -100.0 << 100.0 << 1 << QString("a-3456") << INV << INV;
+ QTest::newRow("data16") << "C" << -100.0 << 100.0 << 1 << QString("a-3456a") << INV << INV;
+ QTest::newRow("data17") << "C" << 1229.0 << 1231.0 << 0 << QString("123e") << ITM << INV;
+ QTest::newRow("data18") << "C" << 1229.0 << 1231.0 << 0 << QString("123e+") << ITM << INV;
+ QTest::newRow("data19") << "C" << 1229.0 << 1231.0 << 0 << QString("123e+1") << ACC << INV;
+ QTest::newRow("data20") << "C" << 12290.0 << 12310.0 << 0 << QString("123e+2") << ACC << INV;
+ QTest::newRow("data21") << "C" << 12.290 << 12.310 << 2 << QString("123e-") << ITM << INV;
+ QTest::newRow("data22") << "C" << 12.290 << 12.310 << 2 << QString("123e-1") << ACC << INV;
+ QTest::newRow("data23") << "C" << 1.2290 << 1.2310 << 3 << QString("123e-2") << ACC << INV;
+ QTest::newRow("data24") << "C" << 1229.0 << 1231.0 << 0 << QString("123E") << ITM << INV;
+ QTest::newRow("data25") << "C" << 1229.0 << 1231.0 << 0 << QString("123E+") << ITM << INV;
+ QTest::newRow("data26") << "C" << 1229.0 << 1231.0 << 0 << QString("123E+1") << ACC << INV;
+ QTest::newRow("data27") << "C" << 12290.0 << 12310.0 << 0 << QString("123E+2") << ACC << INV;
+ QTest::newRow("data28") << "C" << 12.290 << 12.310 << 2 << QString("123E-") << ITM << INV;
+ QTest::newRow("data29") << "C" << 12.290 << 12.310 << 2 << QString("123E-1") << ACC << INV;
+ QTest::newRow("data30") << "C" << 1.2290 << 1.2310 << 3 << QString("123E-2") << ACC << INV;
+ QTest::newRow("data31") << "C" << 1.2290 << 1.2310 << 3 << QString("e") << ITM << INV;
+ QTest::newRow("data32") << "C" << 1.2290 << 1.2310 << 3 << QString("e+") << ITM << INV;
+ QTest::newRow("data33") << "C" << 1.2290 << 1.2310 << 3 << QString("e+1") << ITM << INV;
+ QTest::newRow("data34") << "C" << 1.2290 << 1.2310 << 3 << QString("e-") << ITM << INV;
+ QTest::newRow("data35") << "C" << 1.2290 << 1.2310 << 3 << QString("e-1") << ITM << INV;
+ QTest::newRow("data36") << "C" << 1.2290 << 1.2310 << 3 << QString("E") << ITM << INV;
+ QTest::newRow("data37") << "C" << 1.2290 << 1.2310 << 3 << QString("E+") << ITM << INV;
+ QTest::newRow("data38") << "C" << 1.2290 << 1.2310 << 3 << QString("E+1") << ITM << INV;
+ QTest::newRow("data39") << "C" << 1.2290 << 1.2310 << 3 << QString("E-") << ITM << INV;
+ QTest::newRow("data40") << "C" << 1.2290 << 1.2310 << 3 << QString("E-1") << ITM << INV;
+ QTest::newRow("data41") << "C" << -100.0 << 100.0 << 0 << QString("10e") << ITM << INV;
+ QTest::newRow("data42") << "C" << -100.0 << 100.0 << 0 << QString("10e+") << ITM << INV;
+ QTest::newRow("data43") << "C" << 0.01 << 0.09 << 2 << QString("0") << ITM << ITM;
+ QTest::newRow("data44") << "C" << 0.0 << 10.0 << 1 << QString("11") << ITM << ITM;
+ QTest::newRow("data45") << "C" << 0.0 << 10.0 << 2 << QString("11") << ITM << ITM;
+ QTest::newRow("data46") << "C" << 0.0 << 100.0 << 0 << QString("0.") << ACC << ACC;
+ QTest::newRow("data47") << "C" << 0.0 << 100.0 << 0 << QString("0.0") << INV << INV;
+ QTest::newRow("data48") << "C" << 0.0 << 100.0 << 1 << QString("0.0") << ACC << ACC;
+ QTest::newRow("data49") << "C" << 0.0 << 100.0 << 0 << QString(".") << ITM << ITM;
+ QTest::newRow("data50") << "C" << 0.0 << 100.0 << 1 << QString(".") << ITM << ITM;
+
+ QTest::newRow("data_de0") << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC;
+ QTest::newRow("data_de1") << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM;
+ QTest::newRow("data_de1a") << "de" << 00.0 << 100.0 << 1 << QString("5001,0") << ITM << INV;
+ QTest::newRow("data_de0C") << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC;
+ QTest::newRow("data_de1C") << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM;
+ QTest::newRow("data_de1aC") << "de" << 00.0 << 100.0 << 1 << QString("5001,0") << ITM << INV;
+ QTest::newRow("data_de2") << "de" << 00.0 << 100.0 << 1 << QString("-35,0") << INV << INV;
+ QTest::newRow("data_de3") << "de" << 00.0 << 100.0 << 1 << QString("a") << INV << INV;
+ QTest::newRow("data_de4") << "de" << 0.0 << 100.0 << 1 << QString("-") << INV << INV;
+ QTest::newRow("data_de5") << "de" << 0.0 << 100.0 << 1 << QString("100,0") << ACC << ACC;
+ QTest::newRow("data_de6") << "de" << -100.0 << 100.0 << 1 << QString("-") << ITM << ITM;
+ QTest::newRow("data_de7") << "de" << -100.0 << 100.0 << 1 << QString("-500,0") << ITM << ITM;
+ QTest::newRow("data_de8") << "de" << -100.0 << 100.0 << 1 << QString("-100") << ACC << ACC;
+ QTest::newRow("data_de9") << "de" << -100.0 << -10.0 << 1 << QString("10") << ITM << ITM;
+ QTest::newRow("data_de10") << "de" << 0.3 << 0.5 << 5 << QString("0,34567") << ACC << ACC;
+ QTest::newRow("data_de11") << "de" << -0.3 << -0.5 << 5 << QString("-0,345678") << ITM << INV;
+ QTest::newRow("data_de12") << "de" << -0.32 << 0.32 << 1 << QString("0") << ACC << ACC;
+ QTest::newRow("data_de13") << "de" << 0.0 << 100.0 << 1 << QString("3456a") << INV << INV;
+ QTest::newRow("data_de14") << "de" << -100.0 << 100.0 << 1 << QString("-3456a") << INV << INV;
+ QTest::newRow("data_de15") << "de" << -100.0 << 100.0 << 1 << QString("a-3456") << INV << INV;
+ QTest::newRow("data_de16") << "de" << -100.0 << 100.0 << 1 << QString("a-3456a") << INV << INV;
+ QTest::newRow("data_de17") << "de" << 1229.0 << 1231.0 << 0 << QString("123e") << ITM << INV;
+ QTest::newRow("data_de18") << "de" << 1229.0 << 1231.0 << 0 << QString("123e+") << ITM << INV;
+ QTest::newRow("data_de19") << "de" << 1229.0 << 1231.0 << 0 << QString("123e+1") << ACC << INV;
+ QTest::newRow("data_de20") << "de" << 12290.0 << 12310.0 << 0 << QString("123e+2") << ACC << INV;
+ QTest::newRow("data_de21") << "de" << 12.290 << 12.310 << 2 << QString("123e-") << ITM << INV;
+ QTest::newRow("data_de22") << "de" << 12.290 << 12.310 << 2 << QString("123e-1") << ACC << INV;
+ QTest::newRow("data_de23") << "de" << 1.2290 << 1.2310 << 3 << QString("123e-2") << ACC << INV;
+ QTest::newRow("data_de24") << "de" << 1229.0 << 1231.0 << 0 << QString("123E") << ITM << INV;
+ QTest::newRow("data_de25") << "de" << 1229.0 << 1231.0 << 0 << QString("123E+") << ITM << INV;
+ QTest::newRow("data_de26") << "de" << 1229.0 << 1231.0 << 0 << QString("123E+1") << ACC << INV;
+ QTest::newRow("data_de27") << "de" << 12290.0 << 12310.0 << 0 << QString("123E+2") << ACC << INV;
+ QTest::newRow("data_de28") << "de" << 12.290 << 12.310 << 2 << QString("123E-") << ITM << INV;
+ QTest::newRow("data_de29") << "de" << 12.290 << 12.310 << 2 << QString("123E-1") << ACC << INV;
+ QTest::newRow("data_de30") << "de" << 1.2290 << 1.2310 << 3 << QString("123E-2") << ACC << INV;
+ QTest::newRow("data_de31") << "de" << 1.2290 << 1.2310 << 3 << QString("e") << ITM << INV;
+ QTest::newRow("data_de32") << "de" << 1.2290 << 1.2310 << 3 << QString("e+") << ITM << INV;
+ QTest::newRow("data_de33") << "de" << 1.2290 << 1.2310 << 3 << QString("e+1") << ITM << INV;
+ QTest::newRow("data_de34") << "de" << 1.2290 << 1.2310 << 3 << QString("e-") << ITM << INV;
+ QTest::newRow("data_de35") << "de" << 1.2290 << 1.2310 << 3 << QString("e-1") << ITM << INV;
+ QTest::newRow("data_de36") << "de" << 1.2290 << 1.2310 << 3 << QString("E") << ITM << INV;
+ QTest::newRow("data_de37") << "de" << 1.2290 << 1.2310 << 3 << QString("E+") << ITM << INV;
+ QTest::newRow("data_de38") << "de" << 1.2290 << 1.2310 << 3 << QString("E+1") << ITM << INV;
+ QTest::newRow("data_de39") << "de" << 1.2290 << 1.2310 << 3 << QString("E-") << ITM << INV;
+ QTest::newRow("data_de40") << "de" << 1.2290 << 1.2310 << 3 << QString("E-1") << ITM << INV;
+ QTest::newRow("data_de41") << "de" << -100.0 << 100.0 << 0 << QString("10e") << ITM << INV;
+ QTest::newRow("data_de42") << "de" << -100.0 << 100.0 << 0 << QString("10e+") << ITM << INV;
+ QTest::newRow("data_de43") << "de" << 0.01 << 0.09 << 2 << QString("0") << ITM << ITM;
+ QTest::newRow("data_de44") << "de" << 0.0 << 10.0 << 1 << QString("11") << ITM << ITM;
+ QTest::newRow("data_de45") << "de" << 0.0 << 10.0 << 2 << QString("11") << ITM << ITM;
+
+ QString arabicNum;
+ arabicNum += QChar(1633); // "18.4" in arabic
+ arabicNum += QChar(1640);
+ arabicNum += QChar(1643);
+ arabicNum += QChar(1636);
+ QTest::newRow("arabic") << "ar" << 0.0 << 20.0 << 2 << arabicNum << ACC << ACC;
+
+ QTest::newRow("data_QTBUG_14935-1") << "de" << 0.0 << 1.0 << 5 << QString("0.31") << ACC << ACC;
+ QTest::newRow("data_QTBUG_14935-2") << "de" << 0.0 << 1000000.0 << 5 << QString("3.123") << ACC << ACC;
+ QTest::newRow("data_QTBUG_14935-3") << "de" << 0.0 << 1000000.0 << 5 << QString("123,345.678") << ACC << ACC;
+
+ QTest::newRow("data_de_problem-1") << "de" << 0.0 << 10.0 << 0 << QString("1.0") << ITM << ITM;
+ QTest::newRow("data_de_problem-2") << "de" << 0.0 << 10.0 << 0 << QString("0.1") << INV << INV;
+}
+
+void tst_QDoubleValidator::validate()
+{
+ QFETCH(QString, localeName);
+ QFETCH(double, minimum);
+ QFETCH(double, maximum);
+ QFETCH(int, decimals);
+ QFETCH(QString, value);
+ QFETCH(QValidator::State, scientific_state);
+ QFETCH(QValidator::State, standard_state);
+
+ QEXPECT_FAIL("data_de_problem-1", "To be fixed. See QTBUG-15210.", Abort);
+ QEXPECT_FAIL("data_de_problem-2", "To be fixed. See QTBUG-15210.", Abort);
+
+ QLocale::setDefault(QLocale(localeName));
+
+ QDoubleValidator dv(minimum, maximum, decimals, 0);
+ int dummy;
+ QCOMPARE((int)dv.validate(value, dummy), (int)scientific_state);
+ dv.setNotation(QDoubleValidator::StandardNotation);
+ QCOMPARE((int)dv.validate(value, dummy), (int)standard_state);
+}
+void tst_QDoubleValidator::notifySignals()
+{
+ QDoubleValidator dv(0.1, 0.9, 10, 0);
+ QSignalSpy topSpy(&dv, SIGNAL(topChanged(double)));
+ QSignalSpy bottomSpy(&dv, SIGNAL(bottomChanged(double)));
+ QSignalSpy decSpy(&dv, SIGNAL(decimalsChanged(int)));
+
+ qRegisterMetaType<QDoubleValidator::Notation>("QDoubleValidator::Notation");
+ QSignalSpy notSpy(&dv, SIGNAL(notationChanged(QDoubleValidator::Notation)));
+
+ dv.setTop(0.8);
+ QCOMPARE(topSpy.count(), 1);
+ QVERIFY(dv.top() == 0.8);
+ dv.setBottom(0.2);
+ QCOMPARE(bottomSpy.count(), 1);
+ QVERIFY(dv.bottom() == 0.2);
+
+ dv.setRange(0.2, 0.7);
+ QCOMPARE(topSpy.count(), 2);
+ QCOMPARE(bottomSpy.count(), 1);
+ QCOMPARE(decSpy.count(), 1);
+ QVERIFY(dv.bottom() == 0.2);
+ QVERIFY(dv.top() == 0.7);
+ QVERIFY(dv.decimals() == 0.);
+
+ dv.setRange(0.3, 0.7);
+ QCOMPARE(topSpy.count(), 2);
+ QCOMPARE(bottomSpy.count(), 2);
+ QVERIFY(dv.bottom() == 0.3);
+ QVERIFY(dv.top() == 0.7);
+ QVERIFY(dv.decimals() == 0.);
+
+ dv.setRange(0.4, 0.6);
+ QCOMPARE(topSpy.count(), 3);
+ QCOMPARE(bottomSpy.count(), 3);
+ QVERIFY(dv.bottom() == 0.4);
+ QVERIFY(dv.top() == 0.6);
+ QVERIFY(dv.decimals() == 0.);
+
+ dv.setDecimals(10);
+ QCOMPARE(decSpy.count(), 2);
+ QVERIFY(dv.decimals() == 10.);
+
+
+ dv.setRange(0.4, 0.6, 100);
+ QCOMPARE(topSpy.count(), 3);
+ QCOMPARE(bottomSpy.count(), 3);
+ QCOMPARE(decSpy.count(), 3);
+ QVERIFY(dv.bottom() == 0.4);
+ QVERIFY(dv.top() == 0.6);
+ QVERIFY(dv.decimals() == 100.);
+
+ dv.setNotation(QDoubleValidator::StandardNotation);
+ QCOMPARE(notSpy.count(), 1);
+ QVERIFY(dv.notation() == QDoubleValidator::StandardNotation);
+}
+
+void tst_QDoubleValidator::validateIntEquiv_data()
+{
+ QTest::addColumn<double>("minimum");
+ QTest::addColumn<double>("maximum");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QValidator::State>("state");
+
+ QTest::newRow("1.1") << 0.0 << 10.0 << QString("") << ITM;
+ QTest::newRow("1.2") << 10.0 << 0.0 << QString("") << ITM;
+
+ QTest::newRow("2.1") << 0.0 << 10.0 << QString("-") << INV;
+ QTest::newRow("2.2") << 0.0 << 10.0 << QString("-0") << INV;
+ QTest::newRow("2.3") << -10.0 << -1.0 << QString("+") << INV;
+ QTest::newRow("2.4") << -10.0 << 10.0 << QString("-") << ITM;
+ QTest::newRow("2.5") << -10.0 << 10.0 << QString("+") << ITM;
+ QTest::newRow("2.5a") << -10.0 << -9.0 << QString("+") << INV;
+ QTest::newRow("2.6") << -10.0 << 10.0 << QString("+0") << ACC;
+ QTest::newRow("2.7") << -10.0 << 10.0 << QString("+1") << ACC;
+ QTest::newRow("2.8") << -10.0 << 10.0 << QString("+-") << INV;
+ QTest::newRow("2.9") << -10.0 << 10.0 << QString("-+") << INV;
+
+ QTest::newRow("3.1") << 0.0 << 10.0 << QString("12345678901234567890") << INV;
+ QTest::newRow("3.2") << 0.0 << 10.0 << QString("-12345678901234567890") << INV;
+ QTest::newRow("3.3") << 0.0 << 10.0 << QString("000000000000000000000") << ACC;
+ QTest::newRow("3.4") << 1.0 << 10.0 << QString("000000000000000000000") << ITM;
+ QTest::newRow("3.5") << 0.0 << 10.0 << QString("-000000000000000000000") << INV;
+ QTest::newRow("3.6") << -10.0 << -1.0 << QString("-000000000000000000000") << ITM;
+ QTest::newRow("3.7") << -10.0 << -1.0 << QString("-0000000000000000000001") << ACC;
+
+ QTest::newRow("4.1") << 0.0 << 10.0 << QString(" ") << INV;
+ QTest::newRow("4.2") << 0.0 << 10.0 << QString(" 1") << INV;
+ QTest::newRow("4.3") << 0.0 << 10.0 << QString("1 ") << INV;
+ QTest::newRow("4.4") << 0.0 << 10.0 << QString("1.0") << INV;
+ QTest::newRow("4.5") << 0.0 << 10.0 << QString("0.1") << INV;
+ QTest::newRow("4.6") << 0.0 << 10.0 << QString(".1") << INV;
+ QTest::newRow("4.7") << 0.0 << 10.0 << QString("-1.0") << INV;
+
+ QTest::newRow("5.1") << 6.0 << 8.0 << QString("5") << ITM;
+ QTest::newRow("5.1") << 6.0 << 8.0 << QString("56") << INV;
+ QTest::newRow("5.2") << 6.0 << 8.0 << QString("7") << ACC;
+ QTest::newRow("5.3") << 6.0 << 8.0 << QString("9") << ITM;
+ QTest::newRow("5.3") << 6.0 << 8.0 << QString("-") << INV;
+ QTest::newRow("5.4a") << -8.0 << -6.0 << QString("+") << INV;
+ QTest::newRow("5.4b") << -8.0 << -6.0 << QString("+5") << INV;
+ QTest::newRow("5.4c") << -8.0 << -6.0 << QString("-5") << ITM;
+ QTest::newRow("5.5") << -8.0 << -6.0 << QString("-7") << ACC;
+ QTest::newRow("5.6") << -8.0 << -6.0 << QString("-9") << ITM;
+ QTest::newRow("5.7") << -8.0 << -6.0 << QString("5") << ITM;
+ QTest::newRow("5.8") << -8.0 << -6.0 << QString("7") << ITM;
+ QTest::newRow("5.9") << -8.0 << -6.0 << QString("9") << ITM;
+ QTest::newRow("5.10") << -6.0 << 8.0 << QString("-5") << ACC;
+ QTest::newRow("5.11") << -6.0 << 8.0 << QString("5") << ACC;
+ QTest::newRow("5.12") << -6.0 << 8.0 << QString("-7") << ITM;
+ QTest::newRow("5.13") << -6.0 << 8.0 << QString("7") << ACC;
+ QTest::newRow("5.14") << -6.0 << 8.0 << QString("-9") << ITM;
+ QTest::newRow("5.15") << -6.0 << 8.0 << QString("9") << ITM;
+
+ QTest::newRow("6.1") << 100.0 << 102.0 << QString("11") << ITM;
+ QTest::newRow("6.2") << 100.0 << 102.0 << QString("-11") << INV;
+
+ QTest::newRow("7.1") << 0.0 << 10.0 << QString("100") << INV;
+ QTest::newRow("7.2") << 0.0 << -10.0 << QString("100") << INV;
+ QTest::newRow("7.3") << 0.0 << -10.0 << QString("-100") << INV;
+ QTest::newRow("7.4") << -100.0 << 10.0 << QString("100") << ITM;
+}
+
+void tst_QDoubleValidator::validateIntEquiv()
+{
+ QFETCH(double, minimum);
+ QFETCH(double, maximum);
+ QFETCH(QString, input);
+ QFETCH(QValidator::State, state);
+
+ QLocale::setDefault(QLocale("C"));
+
+ QDoubleValidator dv(minimum, maximum, 0, 0);
+ dv.setNotation(QDoubleValidator::StandardNotation);
+ int dummy;
+ QCOMPARE(dv.validate(input, dummy), state);
+}
+
+QTEST_APPLESS_MAIN(tst_QDoubleValidator)
+#include "tst_qdoublevalidator.moc"
diff --git a/tests/auto/widgets/widgets/qfocusframe/.gitignore b/tests/auto/widgets/widgets/qfocusframe/.gitignore
new file mode 100644
index 0000000000..7a6e000227
--- /dev/null
+++ b/tests/auto/widgets/widgets/qfocusframe/.gitignore
@@ -0,0 +1 @@
+tst_qfocusframe
diff --git a/tests/auto/widgets/widgets/qfocusframe/qfocusframe.pro b/tests/auto/widgets/widgets/qfocusframe/qfocusframe.pro
new file mode 100644
index 0000000000..0fcc9bf23d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qfocusframe/qfocusframe.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qfocusframe.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qfocusframe.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp b/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp
new file mode 100644
index 0000000000..1658cf3fe5
--- /dev/null
+++ b/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qfocusframe.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFocusFrame : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QFocusFrame();
+ virtual ~tst_QFocusFrame();
+
+private slots:
+ void getSetCheck();
+};
+
+tst_QFocusFrame::tst_QFocusFrame()
+{
+}
+
+tst_QFocusFrame::~tst_QFocusFrame()
+{
+}
+
+// Testing get/set functions
+void tst_QFocusFrame::getSetCheck()
+{
+ QFocusFrame *obj1 = new QFocusFrame();
+ // QWidget * QFocusFrame::widget()
+ // void QFocusFrame::setWidget(QWidget *)
+ QWidget var1;
+ QWidget *var2 = new QWidget(&var1);
+ obj1->setWidget(var2);
+ QCOMPARE(var2, obj1->widget());
+ obj1->setWidget((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1->widget());
+ delete obj1;
+}
+
+QTEST_MAIN(tst_QFocusFrame)
+#include "tst_qfocusframe.moc"
diff --git a/tests/auto/widgets/widgets/qfontcombobox/.gitignore b/tests/auto/widgets/widgets/qfontcombobox/.gitignore
new file mode 100644
index 0000000000..acc19de07e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qfontcombobox/.gitignore
@@ -0,0 +1 @@
+tst_qfontcombobox
diff --git a/tests/auto/widgets/widgets/qfontcombobox/qfontcombobox.pro b/tests/auto/widgets/widgets/qfontcombobox/qfontcombobox.pro
new file mode 100644
index 0000000000..7faa0e36bd
--- /dev/null
+++ b/tests/auto/widgets/widgets/qfontcombobox/qfontcombobox.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qfontcombobox.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
new file mode 100644
index 0000000000..72b3dfe8ca
--- /dev/null
+++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qfontcombobox.h>
+
+class tst_QFontComboBox : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qfontcombobox_data();
+ void qfontcombobox();
+ void currentFont_data();
+ void currentFont();
+ void fontFilters_data();
+ void fontFilters();
+ void sizeHint();
+ void writingSystem_data();
+ void writingSystem();
+ void currentFontChanged();
+};
+
+// Subclass that exposes the protected functions.
+class SubQFontComboBox : public QFontComboBox
+{
+public:
+ void call_currentFontChanged(QFont const& f)
+ { return SubQFontComboBox::currentFontChanged(f); }
+
+ bool call_event(QEvent* e)
+ { return SubQFontComboBox::event(e); }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QFontComboBox::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QFontComboBox::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QFontComboBox::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QFontComboBox::cleanup()
+{
+}
+
+void tst_QFontComboBox::qfontcombobox_data()
+{
+}
+
+void tst_QFontComboBox::qfontcombobox()
+{
+ SubQFontComboBox box;
+ QCOMPARE(box.currentFont(), QFont());
+ QCOMPARE(box.fontFilters(), QFontComboBox::AllFonts);
+ box.setCurrentFont(QFont());
+ box.setFontFilters(QFontComboBox::AllFonts);
+ box.setWritingSystem(QFontDatabase::Any);
+ QVERIFY(box.sizeHint() != QSize());
+ QCOMPARE(box.writingSystem(), QFontDatabase::Any);
+ box.call_currentFontChanged(QFont());
+ QEvent event(QEvent::None);
+ QCOMPARE(box.call_event(&event), false);
+}
+
+void tst_QFontComboBox::currentFont_data()
+{
+ QTest::addColumn<QFont>("currentFont");
+ // Normalize the names
+ QFont defaultFont;
+ QFontInfo fi(defaultFont);
+ defaultFont = QFont(fi.family()); // make sure we have a real font name and not something like 'Sans Serif'.
+ QTest::newRow("default") << defaultFont;
+ defaultFont.setPointSize(defaultFont.pointSize() + 10);
+ QTest::newRow("default2") << defaultFont;
+ QFontDatabase db;
+ QStringList list = db.families();
+ for (int i = 0; i < list.count(); ++i) {
+ QFont f = QFont(QFontInfo(QFont(list.at(i))).family());
+ QTest::newRow(qPrintable(list.at(i))) << f;
+ }
+}
+
+// public QFont currentFont() const
+void tst_QFontComboBox::currentFont()
+{
+ QFETCH(QFont, currentFont);
+
+ SubQFontComboBox box;
+ QSignalSpy spy0(&box, SIGNAL(currentFontChanged(QFont const&)));
+ QFont oldCurrentFont = box.currentFont();
+
+ box.setCurrentFont(currentFont);
+ QRegExp foundry(" \\[.*\\]");
+ if (!box.currentFont().family().contains(foundry)) {
+ QCOMPARE(box.currentFont(), currentFont);
+ }
+ QString boxFontFamily = QFontInfo(box.currentFont()).family();
+ if (!currentFont.family().contains(foundry))
+ boxFontFamily.remove(foundry);
+ QCOMPARE(boxFontFamily, currentFont.family());
+
+ if (oldCurrentFont != box.currentFont()) {
+ //the signal may be emit twice if there is a foundry into brackets
+ QCOMPARE(spy0.count(),1);
+ }
+}
+
+Q_DECLARE_METATYPE(QFontComboBox::FontFilters)
+void tst_QFontComboBox::fontFilters_data()
+{
+ QTest::addColumn<QFontComboBox::FontFilters>("fontFilters");
+ QTest::newRow("AllFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::AllFonts);
+ QTest::newRow("ScalableFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::ScalableFonts);
+ QTest::newRow("NonScalableFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::NonScalableFonts);
+ QTest::newRow("MonospacedFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::MonospacedFonts);
+ QTest::newRow("ProportionalFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::ProportionalFonts);
+
+ // combine two
+ QTest::newRow("ProportionalFonts | NonScalableFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::ProportionalFonts | QFontComboBox::NonScalableFonts);
+
+ // i.e. all
+ QTest::newRow("ScalableFonts | NonScalableFonts")
+ << QFontComboBox::FontFilters(QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
+
+}
+
+// public QFontComboBox::FontFilters fontFilters() const
+void tst_QFontComboBox::fontFilters()
+{
+ QFETCH(QFontComboBox::FontFilters, fontFilters);
+
+ SubQFontComboBox box;
+ QSignalSpy spy0(&box, SIGNAL(currentFontChanged(QFont const&)));
+ QFont currentFont = box.currentFont();
+
+ box.setFontFilters(fontFilters);
+ QCOMPARE(box.fontFilters(), fontFilters);
+
+ QFontDatabase db;
+ QStringList list = db.families();
+ int c = 0;
+ const int scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
+ const int spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);
+ if((fontFilters & scalableMask) == scalableMask)
+ fontFilters &= ~scalableMask;
+ if((fontFilters & spacingMask) == spacingMask)
+ fontFilters &= ~spacingMask;
+
+ for (int i = 0; i < list.count(); ++i) {
+ if (fontFilters & QFontComboBox::ScalableFonts) {
+ if (!db.isSmoothlyScalable(list[i]))
+ continue;
+ } else if (fontFilters & QFontComboBox::NonScalableFonts) {
+ if (db.isSmoothlyScalable(list[i]))
+ continue;
+ }
+ if (fontFilters & QFontComboBox::MonospacedFonts) {
+ if (!db.isFixedPitch(list[i]))
+ continue;
+ } else if (fontFilters & QFontComboBox::ProportionalFonts) {
+ if (db.isFixedPitch(list[i]))
+ continue;
+ }
+ c++;
+ }
+
+ QCOMPARE(box.model()->rowCount(), c);
+
+ if (c == 0)
+ QCOMPARE(box.currentFont(), QFont());
+
+ QCOMPARE(spy0.count(), (currentFont != box.currentFont()) ? 1 : 0);
+}
+
+// public QSize sizeHint() const
+void tst_QFontComboBox::sizeHint()
+{
+ SubQFontComboBox box;
+ QSize sizeHint = box.QComboBox::sizeHint();
+ QFontMetrics fm(box.font());
+ sizeHint.setWidth(qMax(sizeHint.width(), fm.width(QLatin1Char('m'))*14));
+ QCOMPARE(box.sizeHint(), sizeHint);
+}
+
+Q_DECLARE_METATYPE(QFontDatabase::WritingSystem)
+void tst_QFontComboBox::writingSystem_data()
+{
+ QTest::addColumn<QFontDatabase::WritingSystem>("writingSystem");
+ QTest::newRow("Any") << QFontDatabase::Any;
+ QTest::newRow("Latin") << QFontDatabase::Latin;
+ QTest::newRow("Lao") << QFontDatabase::Lao;
+ QTest::newRow("TraditionalChinese") << QFontDatabase::TraditionalChinese;
+ QTest::newRow("Ogham") << QFontDatabase::Ogham;
+ QTest::newRow("Runic") << QFontDatabase::Runic;
+
+ for (int i = 0; i < 31; ++i)
+ QTest::newRow("enum") << (QFontDatabase::WritingSystem)i;
+}
+
+// public QFontDatabase::WritingSystem writingSystem() const
+void tst_QFontComboBox::writingSystem()
+{
+ QFETCH(QFontDatabase::WritingSystem, writingSystem);
+
+ SubQFontComboBox box;
+ QSignalSpy spy0(&box, SIGNAL(currentFontChanged(QFont const&)));
+ QFont currentFont = box.currentFont();
+
+ box.setWritingSystem(writingSystem);
+ QCOMPARE(box.writingSystem(), writingSystem);
+
+ QFontDatabase db;
+ QStringList list = db.families(writingSystem);
+ QCOMPARE(box.model()->rowCount(), list.count());
+
+ if (list.count() == 0)
+ QCOMPARE(box.currentFont(), QFont());
+
+ QCOMPARE(spy0.count(), (currentFont != box.currentFont()) ? 1 : 0);
+}
+
+// protected void currentFontChanged(QFont const& f)
+void tst_QFontComboBox::currentFontChanged()
+{
+ SubQFontComboBox box;
+ QSignalSpy spy0(&box, SIGNAL(currentFontChanged(QFont const&)));
+
+ if (box.model()->rowCount() > 2) {
+ QTest::keyPress(&box, Qt::Key_Down);
+ QCOMPARE(spy0.count(), 1);
+
+ QFont f( "Sans Serif" );
+ box.setCurrentFont(f);
+ QCOMPARE(spy0.count(), 2);
+ } else
+ qWarning("Not enough fonts installed on test system. Consider adding some");
+}
+
+QTEST_MAIN(tst_QFontComboBox)
+#include "tst_qfontcombobox.moc"
+
diff --git a/tests/auto/widgets/widgets/qgroupbox/.gitignore b/tests/auto/widgets/widgets/qgroupbox/.gitignore
new file mode 100644
index 0000000000..16dc39494e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qgroupbox/.gitignore
@@ -0,0 +1 @@
+tst_qgroupbox
diff --git a/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro b/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro
new file mode 100644
index 0000000000..f4181a33ed
--- /dev/null
+++ b/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgroupbox.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
new file mode 100644
index 0000000000..8568ef01d1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
@@ -0,0 +1,475 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QLineEdit>
+#include <QStyle>
+#include <QStyleOptionGroupBox>
+#include <QVBoxLayout>
+#include <QRadioButton>
+
+#include "qgroupbox.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QGroupBox : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QGroupBox();
+ virtual ~tst_QGroupBox();
+
+public slots:
+ void toggledHelperSlot(bool on);
+ void init();
+ void clickTimestampSlot();
+ void toggleTimestampSlot();
+
+private slots:
+ void setTitle_data();
+ void setTitle();
+ void setCheckable_data();
+ void setCheckable();
+ void setChecked_data();
+ void setChecked();
+ void enabledPropagation();
+ void sizeHint();
+ void toggled();
+ void clicked_data();
+ void clicked();
+ void toggledVsClicked();
+ void childrenAreDisabled();
+ void propagateFocus();
+
+private:
+ bool checked;
+ qint64 timeStamp;
+ qint64 clickTimeStamp;
+ qint64 toggleTimeStamp;
+
+};
+
+tst_QGroupBox::tst_QGroupBox()
+{
+ checked = true;
+}
+
+tst_QGroupBox::~tst_QGroupBox()
+{
+
+}
+
+void tst_QGroupBox::init()
+{
+ checked = true;
+}
+
+void tst_QGroupBox::setTitle_data()
+{
+ QTest::addColumn<QString>("title");
+ QTest::addColumn<QString>("expectedTitle");
+ QTest::newRow( "empty_title" ) << QString("") << QString("");
+ QTest::newRow( "normal_title" ) << QString("Whatisthematrix") << QString("Whatisthematrix");
+ QTest::newRow( "special_chars_title" ) << QString("<>%&#/()=") << QString("<>%&#/()=");
+ QTest::newRow( "spaces_title" ) << QString(" Hello ") << QString(" Hello ");
+}
+
+void tst_QGroupBox::setCheckable_data()
+{
+ QTest::addColumn<bool>("checkable");
+ QTest::addColumn<bool>("expectedCheckable");
+ QTest::newRow( "checkable_true" ) << true << true;
+ QTest::newRow( "checkable_false" ) << false << false;
+}
+
+void tst_QGroupBox::setChecked_data()
+{
+ QTest::addColumn<bool>("checkable");
+ QTest::addColumn<bool>("checked");
+ QTest::addColumn<bool>("expectedChecked");
+ QTest::newRow( "checkable_false_checked_true" ) << false << true << false;
+ QTest::newRow( "checkable_true_checked_true" ) << true << true << true;
+ QTest::newRow( "checkable_true_checked_false" ) << true << false << false;
+}
+
+void tst_QGroupBox::setTitle()
+{
+ QFETCH( QString, title );
+ QFETCH( QString, expectedTitle );
+
+ QGroupBox groupBox;
+
+ groupBox.setTitle( title );
+
+ QCOMPARE( groupBox.title() , expectedTitle );
+}
+
+void tst_QGroupBox::setCheckable()
+{
+ QFETCH( bool, checkable );
+ QFETCH( bool, expectedCheckable );
+
+ QGroupBox groupBox;
+
+ groupBox.setCheckable( checkable );
+ QCOMPARE( groupBox.isCheckable() , expectedCheckable );
+}
+
+
+void tst_QGroupBox::setChecked()
+{
+ QFETCH( bool, checkable );
+ QFETCH( bool, checked );
+ QFETCH( bool, expectedChecked );
+
+ QGroupBox groupBox;
+
+ groupBox.setCheckable( checkable );
+ groupBox.setChecked( checked );
+ QCOMPARE( groupBox.isChecked(), expectedChecked );
+}
+
+void tst_QGroupBox::enabledPropagation()
+{
+ QGroupBox *testWidget = new QGroupBox(0);
+ testWidget->setCheckable(true);
+ testWidget->setChecked(true);
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ testWidget->setEnabled( false );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ testWidget->setDisabled( false );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( grandChildWidget->isEnabled() );
+
+ testWidget->setDisabled( true );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( false );
+ testWidget->setEnabled( true );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( true );
+ testWidget->setEnabled( false );
+ childWidget->setDisabled( true );
+ testWidget->setEnabled( true );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ // Reset state
+ testWidget->setEnabled( true );
+ childWidget->setEnabled( true );
+ grandChildWidget->setEnabled( true );
+
+ // Now check when it's disabled
+ testWidget->setChecked(false);
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ testWidget->setEnabled( false );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ testWidget->setDisabled( false );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ testWidget->setDisabled( true );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( false );
+ testWidget->setEnabled( true );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( true );
+ testWidget->setEnabled( false );
+ childWidget->setDisabled( true );
+ testWidget->setEnabled( true );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ // Reset state
+ testWidget->setEnabled( true );
+ childWidget->setEnabled( true );
+ grandChildWidget->setEnabled( true );
+
+ // Finally enable it again
+ testWidget->setChecked(true);
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ testWidget->setEnabled( false );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ testWidget->setDisabled( false );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+ QVERIFY( grandChildWidget->isEnabled() );
+
+ testWidget->setDisabled( true );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( false );
+ testWidget->setEnabled( true );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( true );
+ testWidget->setEnabled( false );
+ childWidget->setDisabled( true );
+ testWidget->setEnabled( true );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ delete testWidget;
+}
+
+
+void tst_QGroupBox::sizeHint()
+{
+ QGroupBox testWidget1(0);
+ testWidget1.setTitle("&0&0&0&0&0&0&0&0&0&0");
+
+ QGroupBox testWidget2(0);
+ testWidget2.setTitle("0000000000");
+
+ QCOMPARE(testWidget1.sizeHint().width(), testWidget2.sizeHint().width());
+
+ // if the above fails one should maybe test to see like underneath.
+ // QVERIFY((QABS(testWidget1->sizeHint().width() - testWidget2->sizeHint().width()) < 10));
+}
+
+void tst_QGroupBox::toggledHelperSlot(bool on)
+{
+ checked = on;
+}
+
+
+void tst_QGroupBox::toggled()
+{
+ QGroupBox testWidget1(0);
+ testWidget1.setCheckable(true);
+ connect(&testWidget1, SIGNAL(toggled(bool)), this, SLOT(toggledHelperSlot(bool)));
+ QLineEdit *edit = new QLineEdit(&testWidget1);
+ QVERIFY(checked);
+ testWidget1.setChecked(true);
+ QVERIFY(checked);
+ QVERIFY(edit->isEnabled());
+ testWidget1.setChecked(false);
+ QVERIFY(!checked);
+ QVERIFY(!edit->isEnabled());
+}
+
+void tst_QGroupBox::clicked_data()
+{
+ QTest::addColumn<bool>("checkable");
+ QTest::addColumn<bool>("initialCheck");
+ QTest::addColumn<int>("areaToHit");
+ QTest::addColumn<int>("clickedCount");
+ QTest::addColumn<bool>("finalCheck");
+
+ QTest::newRow("hit nothing, not checkable") << false << false << int(QStyle::SC_None) << 0 << false;
+ QTest::newRow("hit frame, not checkable") << false << false << int(QStyle::SC_GroupBoxFrame) << 0 << false;
+ QTest::newRow("hit content, not checkable") << false << false << int(QStyle::SC_GroupBoxContents) << 0 << false;
+ QTest::newRow("hit label, not checkable") << false << false << int(QStyle::SC_GroupBoxLabel) << 0 << false;
+ QTest::newRow("hit checkbox, not checkable") << false << false << int(QStyle::SC_GroupBoxCheckBox) << 0 << false;
+
+ QTest::newRow("hit nothing, checkable") << true << true << int(QStyle::SC_None) << 0 << true;
+ QTest::newRow("hit frame, checkable") << true << true << int(QStyle::SC_GroupBoxFrame) << 0 << true;
+ QTest::newRow("hit content, checkable") << true << true << int(QStyle::SC_GroupBoxContents) << 0 << true;
+ QTest::newRow("hit label, checkable") << true << true << int(QStyle::SC_GroupBoxLabel) << 1 << false;
+ QTest::newRow("hit checkbox, checkable") << true << true << int(QStyle::SC_GroupBoxCheckBox) << 1 << false;
+
+ QTest::newRow("hit nothing, checkable, but unchecked") << true << false << int(QStyle::SC_None) << 0 << false;
+ QTest::newRow("hit frame, checkable, but unchecked") << true << false << int(QStyle::SC_GroupBoxFrame) << 0 << false;
+ QTest::newRow("hit content, checkable, but unchecked") << true << false << int(QStyle::SC_GroupBoxContents) << 0 << false;
+ QTest::newRow("hit label, checkable, but unchecked") << true << false << int(QStyle::SC_GroupBoxLabel) << 1 << true;
+ QTest::newRow("hit checkbox, checkable, but unchecked") << true << false << int(QStyle::SC_GroupBoxCheckBox) << 1 << true;
+}
+
+void tst_QGroupBox::clicked()
+{
+ QFETCH(bool, checkable);
+ QFETCH(bool, initialCheck);
+ QFETCH(int, areaToHit);
+ QGroupBox testWidget(QLatin1String("Testing Clicked"));
+ testWidget.setCheckable(checkable);
+ testWidget.setChecked(initialCheck);
+ QCOMPARE(testWidget.isChecked(), initialCheck);
+ testWidget.resize(200, 200);
+ QSignalSpy spy(&testWidget, SIGNAL(clicked(bool)));
+
+ QStyleOptionGroupBox option;
+ option.initFrom(&testWidget);
+ option.subControls = checkable ? QStyle::SubControls(QStyle::SC_All) : QStyle::SubControls(QStyle::SC_All & ~QStyle::SC_GroupBoxCheckBox);
+ option.text = testWidget.title();
+ option.textAlignment = testWidget.alignment();
+
+ QRect rect = testWidget.style()->subControlRect(QStyle::CC_GroupBox, &option,
+ QStyle::SubControl(areaToHit), &testWidget);
+
+ if (rect.isValid())
+ QTest::mouseClick(&testWidget, Qt::LeftButton, 0, rect.center());
+ else
+ QTest::mouseClick(&testWidget, Qt::LeftButton);
+
+ QTEST(spy.count(), "clickedCount");
+ if (spy.count() > 0)
+ QTEST(spy.at(0).at(0).toBool(), "finalCheck");
+ QTEST(testWidget.isChecked(), "finalCheck");
+}
+
+void tst_QGroupBox::toggledVsClicked()
+{
+ timeStamp = clickTimeStamp = toggleTimeStamp = 0;
+ QGroupBox groupBox;
+ groupBox.setCheckable(true);
+ QSignalSpy toggleSpy(&groupBox, SIGNAL(toggled(bool)));
+ QSignalSpy clickSpy(&groupBox, SIGNAL(clicked(bool)));
+
+ groupBox.setChecked(!groupBox.isChecked());
+ QCOMPARE(clickSpy.count(), 0);
+ QCOMPARE(toggleSpy.count(), 1);
+ if (toggleSpy.count() > 0)
+ QCOMPARE(toggleSpy.at(0).at(0).toBool(), groupBox.isChecked());
+
+ connect(&groupBox, SIGNAL(clicked(bool)), this, SLOT(clickTimestampSlot()));
+ connect(&groupBox, SIGNAL(toggled(bool)), this, SLOT(toggleTimestampSlot()));
+
+ QStyleOptionGroupBox option;
+ option.initFrom(&groupBox);
+ option.subControls = QStyle::SubControls(QStyle::SC_All);
+ QRect rect = groupBox.style()->subControlRect(QStyle::CC_GroupBox, &option,
+ QStyle::SC_GroupBoxCheckBox, &groupBox);
+
+ QTest::mouseClick(&groupBox, Qt::LeftButton, 0, rect.center());
+ QCOMPARE(clickSpy.count(), 1);
+ QCOMPARE(toggleSpy.count(), 2);
+ QVERIFY(toggleTimeStamp < clickTimeStamp);
+}
+
+void tst_QGroupBox::clickTimestampSlot()
+{
+ clickTimeStamp = ++timeStamp;
+}
+
+void tst_QGroupBox::toggleTimestampSlot()
+{
+ toggleTimeStamp = ++timeStamp;
+}
+
+void tst_QGroupBox::childrenAreDisabled()
+{
+ QGroupBox box;
+ box.setCheckable(true);
+ box.setChecked(false);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QRadioButton);
+ layout->addWidget(new QRadioButton);
+ layout->addWidget(new QRadioButton);
+ box.setLayout(layout);
+
+ foreach (QObject *object, box.children()) {
+ if (QWidget *widget = qobject_cast<QWidget *>(object)) {
+ QVERIFY(!widget->isEnabled());
+ QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled));
+ }
+ }
+
+ box.setChecked(true);
+ foreach (QObject *object, box.children()) {
+ if (QWidget *widget = qobject_cast<QWidget *>(object)) {
+ QVERIFY(widget->isEnabled());
+ QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled));
+ }
+ }
+
+ box.setChecked(false);
+ foreach (QObject *object, box.children()) {
+ if (QWidget *widget = qobject_cast<QWidget *>(object)) {
+ QVERIFY(!widget->isEnabled());
+ QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled));
+ }
+ }
+}
+
+void tst_QGroupBox::propagateFocus()
+{
+ QGroupBox box;
+ QLineEdit lineEdit(&box);
+ box.show();
+ QApplication::setActiveWindow(&box);
+ box.setFocus();
+ QTest::qWait(250);
+ QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(&lineEdit));
+}
+
+QTEST_MAIN(tst_QGroupBox)
+#include "tst_qgroupbox.moc"
diff --git a/tests/auto/widgets/widgets/qintvalidator/.gitignore b/tests/auto/widgets/widgets/qintvalidator/.gitignore
new file mode 100644
index 0000000000..c6d5c989f0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qintvalidator/.gitignore
@@ -0,0 +1 @@
+tst_qintvalidator
diff --git a/tests/auto/widgets/widgets/qintvalidator/qintvalidator.pro b/tests/auto/widgets/widgets/qintvalidator/qintvalidator.pro
new file mode 100644
index 0000000000..576621a08b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qintvalidator/qintvalidator.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qintvalidator.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qintvalidator/tst_qintvalidator.cpp b/tests/auto/widgets/widgets/qintvalidator/tst_qintvalidator.cpp
new file mode 100644
index 0000000000..369e3254e8
--- /dev/null
+++ b/tests/auto/widgets/widgets/qintvalidator/tst_qintvalidator.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qvalidator.h>
+
+class tst_QIntValidator : public QObject
+{
+ Q_OBJECT
+private slots:
+ void validate_data();
+ void validate();
+ void validateArabic();
+ void validateFrench();
+ void notifySignals();
+};
+
+Q_DECLARE_METATYPE(QValidator::State);
+#define INV QValidator::Invalid
+#define INT QValidator::Intermediate
+#define ACC QValidator::Acceptable
+
+void tst_QIntValidator::validate_data()
+{
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<QString>("value");
+ QTest::addColumn<QValidator::State>("state");
+
+ QTest::newRow("data0") << 0 << 100 << QString("50") << ACC;
+ QTest::newRow("data1") << 0 << 100 << QString("500") << INV;
+ QTest::newRow("data1a") << 0 << 100 << QString("5000") << INV;
+ QTest::newRow("data1b") << -100 << 0 << QString("50") << INT;
+ QTest::newRow("data1b") << -100 << 0 << QString("500") << INV;
+ QTest::newRow("data1c") << -100 << 0 << QString("5000") << INV;
+ QTest::newRow("data2") << 0 << 100 << QString("-35") << INV;
+ QTest::newRow("data3") << 0 << 100 << QString("a") << INV;
+ QTest::newRow("data4") << 0 << 100 << QString("-") << INV;
+ QTest::newRow("data5") << 0 << 100 << QString("100") << ACC;
+ QTest::newRow("data6") << -100 << 100 << QString("-") << INT;
+ QTest::newRow("data7") << -100 << 100 << QString("-500") << INV;
+ QTest::newRow("data8") << -100 << 100 << QString("-100") << ACC;
+ QTest::newRow("data9") << -100 << -10 << QString("10") << INT;
+
+ QTest::newRow("data10") << 100 << 999 << QString("") << INT;
+ QTest::newRow("data11") << 100 << 999 << QString("5") << INT;
+ QTest::newRow("data12") << 100 << 999 << QString("50") << INT;
+ QTest::newRow("data13") << 100 << 999 << QString("99") << INT;
+ QTest::newRow("data14") << 100 << 999 << QString("100") << ACC;
+ QTest::newRow("data15") << 100 << 999 << QString("101") << ACC;
+ QTest::newRow("data16") << 100 << 999 << QString("998") << ACC;
+ QTest::newRow("data17") << 100 << 999 << QString("999") << ACC;
+ QTest::newRow("data18") << 100 << 999 << QString("1000") << INV;
+ QTest::newRow("data19") << 100 << 999 << QString("-10") << INV;
+
+ QTest::newRow("data20") << -999 << -100 << QString("50") << INT;
+ QTest::newRow("data21") << -999 << -100 << QString("-") << INT;
+ QTest::newRow("data22") << -999 << -100 << QString("-1") << INT;
+ QTest::newRow("data23") << -999 << -100 << QString("-10") << INT;
+ QTest::newRow("data24") << -999 << -100 << QString("-100") << ACC;
+ QTest::newRow("data25") << -999 << -100 << QString("-500") << ACC;
+ QTest::newRow("data26") << -999 << -100 << QString("-998") << ACC;
+ QTest::newRow("data27") << -999 << -100 << QString("-999") << ACC;
+ QTest::newRow("data28") << -999 << -100 << QString("-1000") << INV;
+ QTest::newRow("data29") << -999 << -100 << QString("-2000") << INV;
+
+ QTest::newRow("1.1") << 0 << 10 << QString("") << INT;
+ QTest::newRow("1.2") << 10 << 0 << QString("") << INT;
+
+ QTest::newRow("2.1") << 0 << 10 << QString("-") << INV;
+ QTest::newRow("2.2") << 0 << 10 << QString("-0") << INV;
+ QTest::newRow("2.3") << -10 << -1 << QString("+") << INV;
+ QTest::newRow("2.4") << -10 << 10 << QString("-") << INT;
+ QTest::newRow("2.5") << -10 << 10 << QString("+") << INT;
+ QTest::newRow("2.6") << -10 << 10 << QString("+0") << ACC;
+ QTest::newRow("2.7") << -10 << 10 << QString("+1") << ACC;
+ QTest::newRow("2.8") << -10 << 10 << QString("+-") << INV;
+ QTest::newRow("2.9") << -10 << 10 << QString("-+") << INV;
+
+ QTest::newRow("3.1") << 0 << 10 << QString("12345678901234567890") << INV;
+ QTest::newRow("3.2") << 0 << 10 << QString("-12345678901234567890") << INV;
+ QTest::newRow("3.3") << 0 << 10 << QString("000000000000000000000") << ACC;
+ QTest::newRow("3.4") << 1 << 10 << QString("000000000000000000000") << INT;
+ QTest::newRow("3.5") << 0 << 10 << QString("-000000000000000000000") << INV;
+ QTest::newRow("3.6") << -10 << -1 << QString("-000000000000000000000") << INT;
+ QTest::newRow("3.7") << -10 << -1 << QString("-0000000000000000000001") << ACC;
+
+ QTest::newRow("4.1") << 0 << 10 << QString(" ") << INV;
+ QTest::newRow("4.2") << 0 << 10 << QString(" 1") << INV;
+ QTest::newRow("4.3") << 0 << 10 << QString("1 ") << INV;
+ QTest::newRow("4.4") << 0 << 10 << QString("1.0") << INV;
+ QTest::newRow("4.5") << 0 << 10 << QString("0.1") << INV;
+ QTest::newRow("4.6") << 0 << 10 << QString(".1") << INV;
+ QTest::newRow("4.7") << 0 << 10 << QString("-1.0") << INV;
+
+ QTest::newRow("5.1") << 6 << 8 << QString("5") << INT;
+ QTest::newRow("5.2") << 6 << 8 << QString("7") << ACC;
+ QTest::newRow("5.3") << 6 << 8 << QString("9") << INV;
+ QTest::newRow("5.3a") << 6 << 8 << QString("19") << INV;
+ QTest::newRow("5.4") << -8 << -6 << QString("-5") << INT;
+ QTest::newRow("5.5") << -8 << -6 << QString("-7") << ACC;
+ QTest::newRow("5.6") << -8 << -6 << QString("-9") << INV;
+ QTest::newRow("5.6a") << -8 << -6 << QString("-19") << INV;
+ QTest::newRow("5.7") << -8 << -6 << QString("5") << INT;
+ QTest::newRow("5.8") << -8 << -6 << QString("7") << INT;
+ QTest::newRow("5.9") << -8 << -6 << QString("9") << INV;
+ QTest::newRow("5.10") << -6 << 8 << QString("-5") << ACC;
+ QTest::newRow("5.11") << -6 << 8 << QString("5") << ACC;
+ QTest::newRow("5.12") << -6 << 8 << QString("-7") << INV;
+ QTest::newRow("5.13") << -6 << 8 << QString("7") << ACC;
+ QTest::newRow("5.14") << -6 << 8 << QString("-9") << INV;
+ QTest::newRow("5.15") << -6 << 8 << QString("9") << INV;
+
+ QTest::newRow("6.1") << 100 << 102 << QString("11") << INT;
+ QTest::newRow("6.2") << 100 << 102 << QString("-11") << INV;
+
+ QTest::newRow("7.1") << 0 << 10 << QString("100") << INV;
+ QTest::newRow("7.2") << 0 << -10 << QString("100") << INV;
+ QTest::newRow("7.3") << 0 << -10 << QString("-100") << INV;
+ QTest::newRow("7.4") << -100 << 10 << QString("100") << INT;
+
+ QTest::newRow("8.1") << -100 << -10 << QString("+") << INV;
+ QTest::newRow("8.2") << -100 << -10 << QString("+50") << INV;
+ QTest::newRow("8.3") << -100 << -10 << QString("50") << INT;
+ QTest::newRow("8.4") << 10 << 100 << QString("-") << INV;
+ QTest::newRow("8.5") << 10 << 100 << QString("-50") << INV;
+ QTest::newRow("8.6") << 10 << 100 << QString("5") << INT;
+ QTest::newRow("8.7") << -1 << 100 << QString("-") << INT;
+ QTest::newRow("8.8") << -1 << 100 << QString("-50") << INV;
+ QTest::newRow("8.9") << -1 << 100 << QString("5") << ACC;
+ QTest::newRow("8.10") << -1 << 100 << QString("+") << INT;
+ QTest::newRow("8.11") << -1 << 100 << QString("+50") << ACC;
+}
+
+void tst_QIntValidator::validateArabic()
+{
+ QString arabicNum;
+ arabicNum += QChar(1633); // "18" in arabic
+ arabicNum += QChar(1640);
+
+ QIntValidator validator(-20, 20, 0);
+ validator.setLocale(QLocale(QLocale::Arabic, QLocale::SaudiArabia));
+ int i;
+ QCOMPARE(validator.validate(arabicNum, i), QValidator::Acceptable);
+
+}
+
+
+void tst_QIntValidator::validateFrench()
+{
+ QIntValidator validator(-2000, 2000, 0);
+ validator.setLocale(QLocale::French);
+ int i;
+ QString s = QLatin1String("1 ");
+ QCOMPARE(validator.validate(s, i), QValidator::Acceptable);
+ validator.fixup(s);
+ QCOMPARE(s, s);
+
+ s = QLatin1String("1 000");
+ QCOMPARE(validator.validate(s, i), QValidator::Acceptable);
+ validator.fixup(s);
+ QCOMPARE(s, s);
+
+
+ s = QLatin1String("1 0 00");
+ QCOMPARE(validator.validate(s, i), QValidator::Intermediate);
+ validator.fixup(s);
+ QCOMPARE(s, validator.locale().toString(1000));
+}
+
+void tst_QIntValidator::validate()
+{
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(QString, value);
+ QFETCH(QValidator::State, state);
+
+ QIntValidator iv(minimum, maximum, 0);
+ iv.setLocale(QLocale::C);
+ int dummy;
+ QCOMPARE((int)iv.validate(value, dummy), (int)state);
+}
+
+void tst_QIntValidator::notifySignals()
+{
+ QIntValidator iv(0, 10, 0);
+ QSignalSpy topSpy(&iv, SIGNAL(topChanged(int)));
+ QSignalSpy bottomSpy(&iv, SIGNAL(bottomChanged(int)));
+ iv.setTop(9);
+ QCOMPARE(topSpy.count(), 1);
+ QVERIFY(iv.top() == 9);
+ iv.setBottom(1);
+ QCOMPARE(bottomSpy.count(), 1);
+ QVERIFY(iv.bottom() == 1);
+
+ iv.setRange(1, 8);
+ QCOMPARE(topSpy.count(), 2);
+ QCOMPARE(bottomSpy.count(), 1);
+ QVERIFY(iv.top() == 8);
+ QVERIFY(iv.bottom() == 1);
+
+ iv.setRange(2, 8);
+ QCOMPARE(topSpy.count(), 2);
+ QCOMPARE(bottomSpy.count(), 2);
+ QVERIFY(iv.top() == 8);
+ QVERIFY(iv.bottom() == 2);
+
+ iv.setRange(3, 7);
+ QCOMPARE(topSpy.count(), 3);
+ QCOMPARE(bottomSpy.count(), 3);
+ QVERIFY(iv.top() == 7);
+ QVERIFY(iv.bottom() == 3);
+}
+
+QTEST_MAIN(tst_QIntValidator)
+#include "tst_qintvalidator.moc"
diff --git a/tests/auto/widgets/widgets/qlabel/.gitignore b/tests/auto/widgets/widgets/qlabel/.gitignore
new file mode 100644
index 0000000000..e050d7ab5e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/.gitignore
@@ -0,0 +1 @@
+tst_qlabel
diff --git a/tests/auto/widgets/widgets/qlabel/green.png b/tests/auto/widgets/widgets/qlabel/green.png
new file mode 100644
index 0000000000..dfc95d4f37
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/green.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/qlabel.pro b/tests/auto/widgets/widgets/qlabel/qlabel.pro
new file mode 100644
index 0000000000..0e0c3a43c4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/qlabel.pro
@@ -0,0 +1,15 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qlabel.cpp
+wince*::DEFINES += SRCDIR=\\\"\\\"
+else:DEFINES += SRCDIR=\\\"$$PWD/\\\"
+wince* {
+ addFiles.files = *.png \
+ testdata
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+}
+
diff --git a/tests/auto/widgets/widgets/qlabel/red.png b/tests/auto/widgets/widgets/qlabel/red.png
new file mode 100644
index 0000000000..4a843e744f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/red.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_data0.qsnap
new file mode 100644
index 0000000000..522c173ac4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..acd881d29a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap
new file mode 100644
index 0000000000..9e2c1764d3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap
new file mode 100644
index 0000000000..dcd708fdbf
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap
new file mode 100644
index 0000000000..2131f59fe9
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap
new file mode 100644
index 0000000000..2edd976830
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap
new file mode 100644
index 0000000000..2ce28d9816
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap
new file mode 100644
index 0000000000..6476f6c26b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap
new file mode 100644
index 0000000000..6039742962
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap
new file mode 100644
index 0000000000..477d203960
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap
new file mode 100644
index 0000000000..c673f4099e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap
new file mode 100644
index 0000000000..a490f77118
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap
new file mode 100644
index 0000000000..33342d3616
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap
new file mode 100644
index 0000000000..3fe9a82c2f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap
new file mode 100644
index 0000000000..175235dc38
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap
new file mode 100644
index 0000000000..b1ac74b531
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap
new file mode 100644
index 0000000000..fdd3c7c701
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap
new file mode 100644
index 0000000000..caa47f7292
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap
new file mode 100644
index 0000000000..a0d2498e76
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap
new file mode 100644
index 0000000000..756d9fe827
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap
new file mode 100644
index 0000000000..f973d14c38
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap
new file mode 100644
index 0000000000..720d807db2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap
new file mode 100644
index 0000000000..20fd48e7cc
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap
new file mode 100644
index 0000000000..7db7c97a14
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..d9912d8c92
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap
new file mode 100644
index 0000000000..bfc3a6488e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap
new file mode 100644
index 0000000000..09a35ef761
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap
new file mode 100644
index 0000000000..14e11232f0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap
new file mode 100644
index 0000000000..6ef864e635
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap
new file mode 100644
index 0000000000..eb029008e3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap
new file mode 100644
index 0000000000..439e196b57
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap
new file mode 100644
index 0000000000..9637d1741a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap
new file mode 100644
index 0000000000..9a553465c3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap
new file mode 100644
index 0000000000..0d9184c316
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap
new file mode 100644
index 0000000000..f2873b1c78
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap
new file mode 100644
index 0000000000..1385a50d38
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap
new file mode 100644
index 0000000000..38223cfba2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap
new file mode 100644
index 0000000000..0b946a4968
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap
new file mode 100644
index 0000000000..e1d2c41d88
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap
new file mode 100644
index 0000000000..b7bdee551b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap
new file mode 100644
index 0000000000..a20492ee70
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..85e3306d0c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap
new file mode 100644
index 0000000000..3bf991f674
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap
new file mode 100644
index 0000000000..f05a9dcebd
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap
new file mode 100644
index 0000000000..d7428df5ef
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap
new file mode 100644
index 0000000000..905acd1283
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..e1dea4b76b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap
new file mode 100644
index 0000000000..055ccda47e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap
new file mode 100644
index 0000000000..64b70763d4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..fb0ea227ad
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap
new file mode 100644
index 0000000000..ae9cda541f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap
new file mode 100644
index 0000000000..e21af3223a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..32cc40652b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data0.qsnap
new file mode 100644
index 0000000000..7191b517d2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data1.qsnap
new file mode 100644
index 0000000000..d943ce960a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data2.qsnap
new file mode 100644
index 0000000000..946432e66d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data3.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data3.qsnap
new file mode 100644
index 0000000000..dc5ac0c56d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data0.qsnap
new file mode 100644
index 0000000000..2ab392e50e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data1.qsnap
new file mode 100644
index 0000000000..5769459ab6
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data2.qsnap
new file mode 100644
index 0000000000..b4206c2a57
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data3.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data3.qsnap
new file mode 100644
index 0000000000..f120ac2e76
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..7644f53726
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data1.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data1.qsnap
new file mode 100644
index 0000000000..7902b1b087
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data2.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data2.qsnap
new file mode 100644
index 0000000000..60bd075c78
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data3.qsnap b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data3.qsnap
new file mode 100644
index 0000000000..c1dcb272b3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
new file mode 100644
index 0000000000..9cab8b328d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
@@ -0,0 +1,581 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include "qlabel.h"
+#include <qapplication.h>
+#include <qboxlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qmovie.h>
+#include <qpicture.h>
+#include <qmessagebox.h>
+#include <private/qlabel_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class Widget : public QWidget
+{
+public:
+ Widget() { }
+
+ QList<QEvent::Type> events;
+
+protected:
+ bool event(QEvent *ev) {
+ events.append(ev->type());
+ return QWidget::event(ev);
+ }
+
+};
+
+class tst_QLabel : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QLabel();
+ virtual ~tst_QLabel();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void setText_data();
+ void setText();
+ void setTextFormat();
+#ifndef Q_WS_MAC
+ void setBuddy();
+#endif
+ void setNum();
+ void clear();
+ void wordWrap();
+ void eventPropagation_data();
+ void eventPropagation();
+ void focusPolicy();
+
+ void task190318_sizes();
+
+ void sizeHint();
+
+ void task226479_movieResize();
+ void emptyPixmap();
+
+ void unicodeText_data();
+ void unicodeText();
+
+ void mnemonic_data();
+ void mnemonic();
+ void selection();
+
+#ifndef QT_NO_CONTEXTMENU
+ void taskQTBUG_7902_contextMenuCrash();
+#endif
+
+private:
+ QLabel *testWidget;
+ QPointer<Widget> test_box;
+ QPointer<QLabel> test_label;
+ QLineEdit *test_edit;
+};
+
+// Testing get/set functions
+void tst_QLabel::getSetCheck()
+{
+ QLabel obj1;
+ // bool QLabel::wordWrap()
+ // void QLabel::setWordWrap(bool)
+ obj1.setWordWrap(false);
+ QCOMPARE(false, obj1.wordWrap());
+ obj1.setWordWrap(true);
+ QCOMPARE(true, obj1.wordWrap());
+
+ // QWidget * QLabel::buddy()
+ // void QLabel::setBuddy(QWidget *)
+ QWidget *var2 = new QWidget();
+ obj1.setBuddy(var2);
+ QCOMPARE(var2, obj1.buddy());
+ obj1.setBuddy((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.buddy());
+ delete var2;
+
+ // QMovie * QLabel::movie()
+ // void QLabel::setMovie(QMovie *)
+ QMovie *var3 = new QMovie;
+ obj1.setMovie(var3);
+ QCOMPARE(var3, obj1.movie());
+ obj1.setMovie((QMovie *)0);
+ QCOMPARE((QMovie *)0, obj1.movie());
+ delete var3;
+}
+
+
+tst_QLabel::tst_QLabel(): test_box(0)
+{
+}
+
+tst_QLabel::~tst_QLabel()
+{
+}
+
+void tst_QLabel::initTestCase()
+{
+ // Create the test class
+ testWidget = new QLabel(0);
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+}
+
+void tst_QLabel::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+ if (test_box)
+ delete test_box;
+}
+
+void tst_QLabel::init()
+{
+ testWidget->setTextFormat( Qt::AutoText );
+ testWidget->setBuddy( 0 );
+ testWidget->setIndent( 0 );
+ testWidget->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
+ testWidget->setScaledContents( FALSE );
+}
+
+void tst_QLabel::cleanup()
+{
+ if (QTest::currentTestFunction() == QLatin1String("setBuddy")) {
+ testWidget->show();
+
+ delete test_box; // this should delete tst_labl and test_edit as well.
+ }
+}
+
+// Set buddy doesn't make much sense on Mac OS X.
+#ifndef Q_WS_MAC
+void tst_QLabel::setBuddy()
+{
+ testWidget->hide();
+
+ test_box = new Widget;
+ test_label= new QLabel( test_box );
+ test_label->setText( "&Test with a buddy" );
+ test_edit = new QLineEdit( test_box );
+ QVBoxLayout *layout = new QVBoxLayout(test_box);
+ layout->addWidget(test_label);
+ layout->addWidget(test_edit);
+ test_box->show();
+ qApp->setActiveWindow(test_box);
+ QVERIFY(test_box->isActiveWindow());
+
+ test_label->setBuddy( test_edit );
+ test_label->setFocus();
+ QVERIFY( !test_edit->hasFocus() );
+ QTest::keyClick( test_box, 't', Qt::AltModifier );
+ QVERIFY( test_edit->hasFocus() );
+ delete test_box;
+}
+#endif
+
+void tst_QLabel::setText_data()
+{
+ QTest::addColumn<QString>("txt");
+ QTest::addColumn<QString>("font");
+
+ QString prefix = "";
+#ifdef Q_OS_WIN32
+ prefix = "win32_";
+#endif
+
+ QTest::newRow( QString(prefix + "data0").toLatin1() ) << QString("This is a single line") << QString("Helvetica");
+ QTest::newRow( QString(prefix + "data1").toLatin1() ) << QString("This is the first line\nThis is the second line") << QString("Courier");
+ QTest::newRow( QString(prefix + "data2").toLatin1() ) << QString("This is the first line\nThis is the second line\nThis is the third line") << QString("Helvetica");
+ QTest::newRow( QString(prefix + "data3").toLatin1() ) << QString("This is <b>bold</b> richtext") << QString("Courier");
+ QTest::newRow( QString(prefix + "data4").toLatin1() ) << QString("I Have a &shortcut") << QString("Helvetica");
+}
+
+void tst_QLabel::setText()
+{
+ QFETCH( QString, txt );
+ QFETCH( QString, font );
+ QFont f( font, 8 );
+ testWidget->setFont( f );
+ testWidget->setText( txt );
+ QCOMPARE( testWidget->text(), txt );
+}
+
+void tst_QLabel::setTextFormat()
+{
+ // lets' start with the simple stuff...
+ testWidget->setTextFormat( Qt::PlainText );
+ QVERIFY( testWidget->textFormat() == Qt::PlainText );
+
+ testWidget->setTextFormat( Qt::RichText );
+ QVERIFY( testWidget->textFormat() == Qt::RichText );
+
+ testWidget->setTextFormat( Qt::LogText );
+ QVERIFY( testWidget->textFormat() == Qt::LogText );
+
+ testWidget->setTextFormat( Qt::AutoText );
+ QVERIFY( testWidget->textFormat() == Qt::AutoText );
+}
+
+void tst_QLabel::setNum()
+{
+ testWidget->setText( "This is a text" );
+ testWidget->setNum( 12 );
+ QCOMPARE( testWidget->text(), QString("12") );
+ testWidget->setNum( 12.345 );
+ QCOMPARE( testWidget->text(), QString("12.345") );
+}
+
+void tst_QLabel::clear()
+{
+ const QString TEXT = "blah blah";
+ testWidget->setText(TEXT);
+ QCOMPARE(testWidget->text(), TEXT);
+ testWidget->clear();
+ QVERIFY(testWidget->text().isEmpty());
+}
+
+void tst_QLabel::wordWrap()
+{
+ QLabel label;
+
+ QVERIFY(!label.wordWrap());
+
+ label.setText("Plain Text");
+ QVERIFY(!label.wordWrap());
+
+ label.setText("<b>rich text</b>");
+ QVERIFY(!label.wordWrap());
+
+ label.setWordWrap(false);
+ label.setText("<b>rich text</b>");
+ QVERIFY(!label.wordWrap());
+}
+
+void tst_QLabel::eventPropagation_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("textInteractionFlags");
+ QTest::addColumn<int>("focusPolicy");
+ QTest::addColumn<bool>("propagation");
+
+ QTest::newRow("plain text1") << QString("plain text") << int(Qt::LinksAccessibleByMouse) << int(Qt::NoFocus) << true;
+ QTest::newRow("plain text2") << QString("plain text") << (int)Qt::TextSelectableByKeyboard << (int)Qt::ClickFocus << true;
+ QTest::newRow("plain text3") << QString("plain text") << (int)Qt::TextSelectableByMouse << (int)Qt::ClickFocus << false;
+ QTest::newRow("plain text4") << QString("plain text") << (int)Qt::NoTextInteraction << (int)Qt::NoFocus << true;
+ QTest::newRow("rich text1") << QString("<b>rich text</b>") << (int)Qt::LinksAccessibleByMouse << (int)Qt::NoFocus << true;
+ QTest::newRow("rich text2") << QString("<b>rich text</b>") << (int)Qt::TextSelectableByKeyboard << (int)Qt::ClickFocus << true;
+ QTest::newRow("rich text3") << QString("<b>rich text</b>") << (int)Qt::TextSelectableByMouse << (int)Qt::ClickFocus << false;
+ QTest::newRow("rich text4") << QString("<b>rich text</b>") << (int)Qt::NoTextInteraction << (int)Qt::NoFocus << true;
+ QTest::newRow("rich text4") << QString("<b>rich text</b>") << (int)Qt::LinksAccessibleByKeyboard << (int)Qt::StrongFocus << true;
+
+ if (!test_box)
+ test_box = new Widget;
+ if (!test_label)
+ test_label = new QLabel(test_box);
+}
+
+void tst_QLabel::eventPropagation()
+{
+ QFETCH(QString, text);
+ QFETCH(int, textInteractionFlags);
+ QFETCH(int, focusPolicy);
+ QFETCH(bool, propagation);
+
+ // plain text (accepts mouse event _only_ when label selectable by mouse)
+ test_label->setText(text);
+ test_box->events.clear();
+ test_label->setTextInteractionFlags(Qt::TextInteractionFlags(textInteractionFlags));
+ QVERIFY(int(test_label->focusPolicy()) == focusPolicy);
+ QTest::mousePress(test_label, Qt::LeftButton);
+ QVERIFY(test_box->events.contains(QEvent::MouseButtonPress) == propagation); // should have propagated!
+}
+
+void tst_QLabel::focusPolicy()
+{
+ delete test_label;
+ test_label = new QLabel;
+ QCOMPARE(test_label->focusPolicy(), Qt::NoFocus); // default
+ test_label->setFocusPolicy(Qt::StrongFocus);
+ test_label->setText("Whatever"); // setting text should not change the focus policy
+ QCOMPARE(test_label->focusPolicy(), Qt::StrongFocus);
+ test_label->setTextInteractionFlags(Qt::TextSelectableByKeyboard); // this should
+ QCOMPARE(test_label->focusPolicy(), Qt::ClickFocus);
+ test_label->setFocusPolicy(Qt::StrongFocus);
+ test_label->setText("Whatever"); // setting text should not change the focus policy
+ QCOMPARE(test_label->focusPolicy(), Qt::StrongFocus);
+ test_label->setTextInteractionFlags(Qt::NoTextInteraction);
+ QCOMPARE(test_label->focusPolicy(), Qt::NoFocus);
+ test_label->setFocusPolicy(Qt::StrongFocus);
+ test_label->setTextInteractionFlags(Qt::NoTextInteraction);
+ QCOMPARE(test_label->focusPolicy(), Qt::StrongFocus); // is not touched since value didn't change
+ delete test_label;
+}
+
+void tst_QLabel::task190318_sizes()
+{
+ QLabel label(" ");
+ QSize ms(500,600);
+ label.setMinimumSize(ms);
+ QCOMPARE(label.minimumSize(), ms);
+ QCOMPARE(label.sizeHint(), ms);
+ QCOMPARE(label.minimumSizeHint(), ms);
+}
+
+void tst_QLabel::sizeHint()
+{
+ QLabel label(QLatin1String("Test"));
+ label.setIndent(0);
+ label.setMargin(0);
+ label.setContentsMargins(0, 0, 0, 0);
+ label.setAlignment(Qt::AlignVCenter);
+ int h = label.sizeHint().height();
+
+ QLabel l1(QLatin1String("Test"));
+ l1.setIndent(0);
+ l1.setMargin(0);
+ l1.setContentsMargins(0, 0, 0, 0);
+ l1.setAlignment(Qt::AlignVCenter);
+ l1.setTextInteractionFlags(Qt::TextSelectableByMouse); // will now use qtextcontrol
+ int h1 = l1.sizeHint().height();
+ QCOMPARE(h1, h);
+
+}
+
+void tst_QLabel::task226479_movieResize()
+{
+ class Label : public QLabel {
+ protected:
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ QLabel::paintEvent(e);
+ }
+
+ public:
+ QRegion paintedRegion;
+ };
+
+ Label label;
+ label.resize(350,350);
+ label.show();
+ QMovie *movie = new QMovie( &label );
+ label.setMovie(movie);
+ QTest::qWaitForWindowShown(&label);
+ movie->setFileName(SRCDIR "red.png");
+ movie->start();
+ QTest::qWait(50);
+ movie->stop();
+ label.paintedRegion = QRegion();
+ movie->setFileName(SRCDIR "green.png");
+ movie->start();
+ QTest::qWait(50);
+
+ QTRY_COMPARE(label.paintedRegion , QRegion(label.rect()) );
+}
+
+void tst_QLabel::emptyPixmap()
+{
+ //task 197919
+ QLabel label1, label2, label3, label4;
+ label2.setPixmap(QPixmap("/tmp/idonotexist"));
+ QMovie movie;
+ label3.setMovie(&movie);
+ label4.setPicture(QPicture());
+ QCOMPARE(label1.sizeHint(), label2.sizeHint());
+ QCOMPARE(label1.sizeHint(), label3.sizeHint());
+ QCOMPARE(label1.sizeHint(), label4.sizeHint());
+}
+
+/**
+ Test for QTBUG-4848 - unicode data corrupting QLabel display
+*/
+void tst_QLabel::unicodeText_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("languageName");
+
+ /*
+ The "glass" phrase in Thai was the initial report for bug QTBUG-4848, was
+ originally found on http://www.columbia.edu/kermit/utf8.html.
+
+ The phrase is from an internet tradition regarding a striking phrase
+ that is translated into many different languages. The utf8 strings
+ below were generated by using http://translate.google.com.
+
+ The glass phrase in Thai contains the ้ว character which manifests bug
+ QTBUG-4848
+
+ The last long phrase is an excerpt from Churchills "on the beaches"
+ speech, also translated using http://translate.google.com.
+ */
+
+ QTest::newRow("english") << QString::fromUtf8("I can eat glass and it doesn't hurt me.") << QString("english");
+ QTest::newRow("thai") << QString::fromUtf8("ฉันจะกินแก้วและไม่เจ็บฉัน") << QString("thai");
+ QTest::newRow("chinese") << QString::fromUtf8("我可以吃玻璃,并没有伤害我。") << QString("chinese");
+ QTest::newRow("arabic") << QString::fromUtf8("أستطيع أكل الزجاج ، وأنه لا يؤذيني.") << QString("arabic");
+ QTest::newRow("russian") << QString::fromUtf8("Я могу есть стекло, и не больно.") << QString("russian");
+ QTest::newRow("korean") << QString::fromUtf8("유리를 먹을 수있는, 그리고 그게 날 다치게하지 않습니다.") << QString("korean");
+ QTest::newRow("greek") << QString::fromUtf8("Μπορώ να φάτε γυαλί και δεν μου κάνει κακό.") << QString("greek");
+ QTest::newRow("german") << QString::fromUtf8("Ich kann Glas essen und es macht mich nicht heiß.") << QString("german");
+
+ QTest::newRow("thai_long") << QString::fromUtf8("เราจะต่อสู้ในทะเลและมหาสมุทร. เราจะต่อสู้ด้วยความมั่นใจเติบโตและความเจริญเติบโตในอากาศเราจะปกป้องเกาะของเราค่าใช้จ่ายใดๆอาจ."
+ "เราจะต่อสู้บนชายหาดเราจะต่อสู้ในบริเวณเชื่อมโยงไปถึงเราจะต่อสู้ในช่องและในถนนที่เราจะต่อสู้ในภูเขานั้นเราจะไม่ยอม.")
+ << QString("thai_long");
+}
+
+void tst_QLabel::unicodeText()
+{
+ const QString testDataPath("testdata/unicodeText");
+ QFETCH(QString, text);
+ QFETCH(QString, languageName);
+ QFrame frame;
+ QVBoxLayout *layout = new QVBoxLayout();
+ QLabel *label = new QLabel(text, &frame);
+ layout->addWidget(label);
+ layout->setMargin(8);
+ frame.setLayout(layout);
+ frame.show();
+ QTest::qWaitForWindowShown(&frame);
+ QVERIFY(frame.isVisible()); // was successfully sized and shown
+ testWidget->show();
+}
+
+void tst_QLabel::mnemonic_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("expectedDocText");
+ QTest::addColumn<QString>("expectedShortcutCursor");
+
+ QTest::newRow("1") << QString("Normal") << QString("Normal") << QString();
+ QTest::newRow("2") << QString("&Simple") << QString("Simple") << QString("S");
+ QTest::newRow("3") << QString("Also &simple") << QString("Also simple") << QString("s");
+ QTest::newRow("4") << QString("&&With &Double &&amp;") << QString("&With Double &amp;") << QString("D");
+ QTest::newRow("5") << QString("Hep&&Hop") << QString("Hep&Hop") << QString("");
+ QTest::newRow("6") << QString("Hep&&&Hop") << QString("Hep&Hop") << QString("H");
+}
+
+
+void tst_QLabel::mnemonic()
+{
+ // this test that the mnemonics appears correctly when the label has a text control.
+
+ QFETCH(QString, text);
+ QFETCH(QString, expectedDocText);
+ QFETCH(QString, expectedShortcutCursor);
+
+ QWidget w;
+ QHBoxLayout *hbox = new QHBoxLayout;
+ QLabel *lab = new QLabel(text);
+ //lab->setText("plop &plop");
+ QLineEdit *lineedit = new QLineEdit;
+ lab->setBuddy(lineedit);
+ lab->setTextInteractionFlags(Qt::TextSelectableByMouse);
+
+ hbox->addWidget(lab);
+ hbox->addWidget(lineedit);
+ hbox->addWidget(new QLineEdit);
+ w.setLayout(hbox);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+
+ QLabelPrivate *d = static_cast<QLabelPrivate *>(QObjectPrivate::get(lab));
+ QVERIFY(d->control);
+ QCOMPARE(d->control->document()->toPlainText(), expectedDocText);
+ QCOMPARE(d->shortcutCursor.selectedText(), expectedShortcutCursor);
+}
+
+void tst_QLabel::selection()
+{
+ QLabel label;
+ label.setText("Hello world");
+
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse);
+
+ QVERIFY(!label.hasSelectedText());
+ QCOMPARE(label.selectedText(), QString());
+ QCOMPARE(label.selectionStart(), -1);
+
+ label.setSelection(0, 4);
+ QVERIFY(label.hasSelectedText());
+ QCOMPARE(label.selectedText(), QString::fromLatin1("Hell"));
+ QCOMPARE(label.selectionStart(), 0);
+
+ label.setSelection(6, 5);
+ QVERIFY(label.hasSelectedText());
+ QCOMPARE(label.selectedText(), QString::fromLatin1("world"));
+ QCOMPARE(label.selectionStart(), 6);
+}
+
+#ifndef QT_NO_CONTEXTMENU
+void tst_QLabel::taskQTBUG_7902_contextMenuCrash()
+{
+ QLabel *w = new QLabel("Test or crash?");
+ w->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ w->show();
+ QTest::qWaitForWindowShown(w);
+
+ QTimer ti;
+ w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
+ ti.start(300);
+
+ QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
+ qApp->postEvent(w, cme);
+
+ QTest::qWait(350);
+ // No crash, it's allright.
+}
+#endif
+
+QTEST_MAIN(tst_QLabel)
+#include "tst_qlabel.moc"
diff --git a/tests/auto/widgets/widgets/qlcdnumber/.gitignore b/tests/auto/widgets/widgets/qlcdnumber/.gitignore
new file mode 100644
index 0000000000..cbf08a078d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlcdnumber/.gitignore
@@ -0,0 +1 @@
+tst_qlcdnumber
diff --git a/tests/auto/widgets/widgets/qlcdnumber/qlcdnumber.pro b/tests/auto/widgets/widgets/qlcdnumber/qlcdnumber.pro
new file mode 100644
index 0000000000..cd909de5be
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlcdnumber/qlcdnumber.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qlcdnumber.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qlcdnumber.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp b/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp
new file mode 100644
index 0000000000..0976f3f619
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qlcdnumber.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QLCDNumber : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QLCDNumber();
+ virtual ~tst_QLCDNumber();
+
+private slots:
+ void getSetCheck();
+};
+
+tst_QLCDNumber::tst_QLCDNumber()
+{
+}
+
+tst_QLCDNumber::~tst_QLCDNumber()
+{
+}
+
+// Testing get/set functions
+void tst_QLCDNumber::getSetCheck()
+{
+ QLCDNumber obj1;
+ // int QLCDNumber::digitCount()
+ // void QLCDNumber::setDigitCount(int)
+ obj1.setDigitCount(0);
+ QCOMPARE(0, obj1.digitCount());
+ obj1.setDigitCount(INT_MIN);
+ QCOMPARE(0, obj1.digitCount()); // Range<0, 99>
+ obj1.setDigitCount(INT_MAX);
+ QCOMPARE(99, obj1.digitCount()); // Range<0, 99>
+}
+
+QTEST_MAIN(tst_QLCDNumber)
+#include "tst_qlcdnumber.moc"
diff --git a/tests/auto/widgets/widgets/qlineedit/.gitignore b/tests/auto/widgets/widgets/qlineedit/.gitignore
new file mode 100644
index 0000000000..7fcade47c9
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/.gitignore
@@ -0,0 +1 @@
+tst_qlineedit
diff --git a/tests/auto/widgets/widgets/qlineedit/qlineedit.pro b/tests/auto/widgets/widgets/qlineedit/qlineedit.pro
new file mode 100644
index 0000000000..077b7c919e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/qlineedit.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qlineedit.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png
new file mode 100644
index 0000000000..81a3e3de4d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png
new file mode 100644
index 0000000000..81a3e3de4d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png
new file mode 100644
index 0000000000..ed3810c2e7
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png
new file mode 100644
index 0000000000..fe4456ffbf
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png
new file mode 100644
index 0000000000..7ab7ffd4da
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png
new file mode 100644
index 0000000000..5918bb93f1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png
new file mode 100644
index 0000000000..66119386a3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png
new file mode 100644
index 0000000000..89e81db837
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png
new file mode 100644
index 0000000000..2cf5c7a9cf
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png
new file mode 100644
index 0000000000..70ec6530b8
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png
new file mode 100644
index 0000000000..d6708bcd12
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png
new file mode 100644
index 0000000000..9000dfc4cf
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
new file mode 100644
index 0000000000..6e4726e5b5
--- /dev/null
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -0,0 +1,3835 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "qlineedit.h"
+#include "qapplication.h"
+#include "qstringlist.h"
+#include "qstyle.h"
+#include "qvalidator.h"
+#include "qcompleter.h"
+#include "qstandarditemmodel.h"
+
+#ifndef QT_NO_CLIPBOARD
+#include "qclipboard.h"
+#endif
+
+#ifdef Q_WS_MAC
+#include <Carbon/Carbon.h> // For the random function.
+#include <cstdlib> // For the random function.
+#endif
+
+#include <qlineedit.h>
+#include <qmenu.h>
+#include <qlayout.h>
+#include <qspinbox.h>
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#include "qcommonstyle.h"
+#include "qstyleoption.h"
+
+#include "qplatformdefs.h"
+
+QT_BEGIN_NAMESPACE
+class QPainter;
+QT_END_NAMESPACE
+
+class StyleOptionTestStyle : public QCommonStyle
+{
+private:
+ bool readOnly;
+
+public:
+ inline StyleOptionTestStyle() : QCommonStyle(), readOnly(false)
+ {
+ }
+
+ inline void setReadOnly(bool readOnly)
+ {
+ this->readOnly = readOnly;
+ }
+
+ inline void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *,
+ const QWidget *) const
+ {
+ switch (pe) {
+ case PE_PanelLineEdit:
+ if (readOnly)
+ QVERIFY(opt->state & QStyle::State_ReadOnly);
+ else
+ QVERIFY(!(opt->state & QStyle::State_ReadOnly));
+ break;
+
+ default:
+ break;
+ }
+ }
+};
+
+class tst_QLineEdit : public QObject
+{
+Q_OBJECT
+
+public:
+ enum EventStates { Press, Release, Click };
+
+ tst_QLineEdit();
+ virtual ~tst_QLineEdit();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void experimental();
+
+ void upperAndLowercase();
+
+ void setInputMask_data();
+ void setInputMask();
+
+ void inputMask_data();
+ void inputMask();
+
+ void clearInputMask();
+
+ void keypress_inputMask_data();
+ void keypress_inputMask();
+
+ void inputMaskAndValidator_data();
+ void inputMaskAndValidator();
+
+ void hasAcceptableInputMask_data();
+ void hasAcceptableInputMask();
+
+ void hasAcceptableInputValidator();
+
+
+ void redo_data();
+ void redo();
+
+ void undo_data();
+ void undo();
+
+ void undo_keypressevents_data();
+ void undo_keypressevents();
+
+#ifndef QT_NO_CLIPBOARD
+ void QTBUG5786_undoPaste();
+#endif
+
+ void clear();
+
+ void text_data();
+ void text();
+ void textMask_data();
+ void textMask();
+ void maskCharacter();
+ void maskCharacter_data();
+ void setText();
+
+ void displayText_data();
+ void displayText();
+ void passwordEchoOnEdit();
+
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+ void passwordEchoDelay();
+#endif
+
+ void maxLength_mask_data();
+ void maxLength_mask();
+
+ void maxLength_data();
+ void maxLength();
+
+ void isReadOnly();
+
+ void cursorPosition();
+
+ void cursorPositionChanged_data();
+ void cursorPositionChanged();
+
+ void selectedText();
+ void deleteSelectedText();
+
+ void textChangedAndTextEdited();
+ void returnPressed();
+ void returnPressed_maskvalidator_data();
+ void returnPressed_maskvalidator();
+
+ void setValidator();
+ void setValidator_QIntValidator_data();
+ void setValidator_QIntValidator();
+
+ void frame_data();
+ void frame();
+
+ void leftKeyOnSelectedText();
+
+ void setAlignment_data();
+ void setAlignment();
+
+ void isModified();
+ void edited();
+
+ void insert();
+ void setSelection_data();
+ void setSelection();
+
+#ifndef QT_NO_CLIPBOARD
+ void cut();
+#endif
+ void maxLengthAndInputMask();
+ void returnPressedKeyEvent();
+
+ void keepSelectionOnTabFocusIn();
+
+ void readOnlyStyleOption();
+
+ void validateOnFocusOut();
+
+ void editInvalidText();
+
+ void charWithAltOrCtrlModifier();
+
+ void inlineCompletion();
+
+ void noTextEditedOnClear();
+
+#ifndef QT_NO_CURSOR
+ void cursor();
+#endif
+
+ void textMargin_data();
+ void textMargin();
+
+ // task-specific tests:
+ void task180999_focus();
+ void task174640_editingFinished();
+#ifndef QT_NO_COMPLETER
+ void task198789_currentCompletion();
+ void task210502_caseInsensitiveInlineCompletion();
+#endif
+ void task229938_dontEmitChangedWhenTextIsNotChanged();
+ void task233101_cursorPosAfterInputMethod_data();
+ void task233101_cursorPosAfterInputMethod();
+ void task241436_passwordEchoOnEditRestoreEchoMode();
+ void task248948_redoRemovedSelection();
+ void taskQTBUG_4401_enterKeyClearsPassword();
+ void taskQTBUG_4679_moveToStartEndOfBlock();
+ void taskQTBUG_4679_selectToStartEndOfBlock();
+#ifndef QT_NO_CONTEXTMENU
+ void taskQTBUG_7902_contextMenuCrash();
+#endif
+ void taskQTBUG_7395_readOnlyShortcut();
+#ifdef Q_WS_X11
+ void QTBUG697_paletteCurrentColorGroup();
+#endif
+ void QTBUG13520_textNotVisible();
+
+ void bidiVisualMovement_data();
+ void bidiVisualMovement();
+
+ void bidiLogicalMovement_data();
+ void bidiLogicalMovement();
+
+ void selectAndCursorPosition();
+ void inputMethodSelection();
+
+protected slots:
+ void editingFinished();
+
+ void onTextChanged( const QString &newString );
+ void onTextEdited( const QString &newString );
+ void onReturnPressed();
+ void onSelectionChanged();
+ void onCursorPositionChanged(int oldpos, int newpos);
+
+private:
+ // keyClicks(..) is moved to QtTestCase
+ void psKeyClick(QWidget *target, Qt::Key key, Qt::KeyboardModifiers pressState = 0);
+ void psKeyClick(QTestEventList &keys, Qt::Key key, Qt::KeyboardModifiers pressState = 0);
+
+ bool validInput;
+ QString changed_string;
+ int changed_count;
+ int edited_count;
+ int return_count;
+ int selection_count;
+ int lastCursorPos;
+ int newCursorPos;
+ QLineEdit *testWidget;
+};
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(QLineEdit::EchoMode)
+
+// Testing get/set functions
+void tst_QLineEdit::getSetCheck()
+{
+ QLineEdit obj1;
+ // const QValidator * QLineEdit::validator()
+ // void QLineEdit::setValidator(const QValidator *)
+ QIntValidator *var1 = new QIntValidator(0);
+ obj1.setValidator(var1);
+ QCOMPARE((const QValidator *)var1, obj1.validator());
+ obj1.setValidator((QValidator *)0);
+ QCOMPARE((const QValidator *)0, obj1.validator());
+ delete var1;
+
+ // bool QLineEdit::dragEnabled()
+ // void QLineEdit::setDragEnabled(bool)
+ obj1.setDragEnabled(false);
+ QCOMPARE(false, obj1.dragEnabled());
+ obj1.setDragEnabled(true);
+ QCOMPARE(true, obj1.dragEnabled());
+}
+
+tst_QLineEdit::tst_QLineEdit()
+{
+ validInput = false;
+}
+
+tst_QLineEdit::~tst_QLineEdit()
+{
+}
+
+void tst_QLineEdit::initTestCase()
+{
+ testWidget = new QLineEdit(0);
+ testWidget->setObjectName("testWidget");
+ connect(testWidget, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorPositionChanged(int, int)));
+ connect(testWidget, SIGNAL(textChanged(const QString&)), this, SLOT(onTextChanged(const QString&)));
+ connect(testWidget, SIGNAL(textEdited(const QString&)), this, SLOT(onTextEdited(const QString&)));
+ connect(testWidget, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
+ connect(testWidget, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
+ connect(testWidget, SIGNAL(editingFinished()), this, SLOT(editingFinished()));
+
+ testWidget->resize(200,50);
+ testWidget->show();
+ QApplication::setActiveWindow(testWidget);
+#ifdef Q_WS_X11
+ // to be safe and avoid failing setFocus with window managers
+ qt_x11_wait_for_window_manager(testWidget);
+#endif
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ changed_count = 0;
+ edited_count = 0;
+ selection_count = 0;
+}
+
+void tst_QLineEdit::cleanupTestCase()
+{
+ delete testWidget;
+}
+
+void tst_QLineEdit::init()
+{
+ return_count = 0;
+ testWidget->clear();
+ testWidget->setEchoMode(QLineEdit::Normal);
+ testWidget->setMaxLength(32767);
+ testWidget->setReadOnly(false);
+ testWidget->setText("");
+ testWidget->setInputMask("");
+ testWidget->setFrame(true);
+ testWidget->setValidator(0);
+ testWidget->setDragEnabled(true);
+}
+
+void tst_QLineEdit::cleanup()
+{
+}
+
+void tst_QLineEdit::experimental()
+{
+ QIntValidator intValidator(3, 7, 0);
+ testWidget->setValidator(&intValidator);
+ testWidget->setText("");
+
+
+ // test the order of setting these
+ testWidget->setInputMask("");
+ testWidget->setText("abc123");
+ testWidget->setInputMask("000.000.000.000");
+ QCOMPARE(testWidget->text(), QString("123..."));
+ testWidget->setText("");
+
+
+}
+
+void tst_QLineEdit::upperAndLowercase()
+{
+ testWidget->setInputMask("");
+ testWidget->setText("");
+
+ QTest::keyClicks(testWidget, "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?");
+ qApp->processEvents();
+ QCOMPARE(testWidget->text(), QString("aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"));
+}
+
+void tst_QLineEdit::setInputMask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedDisplay");
+ QTest::addColumn<bool>("insert_text");
+
+ // both keyboard and insert()
+ for (int i=0; i<2; i++) {
+ bool insert_text = i==0 ? false : true;
+ QString insert_mode = "keys ";
+ if (insert_text)
+ insert_mode = "insert ";
+
+ QTest::newRow(QString(insert_mode + "ip_localhost").toLatin1())
+ << QString("000.000.000.000")
+ << QString("127.0.0.1")
+ << QString("127.0.0.1")
+ << QString("127.0 .0 .1 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "mac").toLatin1())
+ << QString("HH:HH:HH:HH:HH:HH;#")
+ << QString("00:E0:81:21:9E:8E")
+ << QString("00:E0:81:21:9E:8E")
+ << QString("00:E0:81:21:9E:8E")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "mac2").toLatin1())
+ << QString("<HH:>HH:!HH:HH:HH:HH;#")
+ << QString("AAe081219E8E")
+ << QString("aa:E0:81:21:9E:8E")
+ << QString("aa:E0:81:21:9E:8E")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "byte").toLatin1())
+ << QString("BBBBBBBB;0")
+ << QString("11011001")
+ << QString("11111")
+ << QString("11011001")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "halfbytes").toLatin1())
+ << QString("bbbb.bbbb;-")
+ << QString("110. 0001")
+ << QString("110.0001")
+ << QString("110-.0001")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "blank char same type as content").toLatin1())
+ << QString("000.000.000.000;0")
+ << QString("127.0.0.1")
+ << QString("127...1")
+ << QString("127.000.000.100")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "parts of ip_localhost").toLatin1())
+ << QString("000.000.000.000")
+ << QString(".0.0.1")
+ << QString(".0.0.1")
+ << QString(" .0 .0 .1 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "ip_null").toLatin1())
+ << QString("000.000.000.000")
+ << QString()
+ << QString("...")
+ << QString(" . . . ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "ip_null_hash").toLatin1())
+ << QString("000.000.000.000;#")
+ << QString()
+ << QString("...")
+ << QString("###.###.###.###")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "ip_overflow").toLatin1())
+ << QString("000.000.000.000")
+ << QString("1234123412341234")
+ << QString("123.412.341.234")
+ << QString("123.412.341.234")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "uppercase").toLatin1())
+ << QString(">AAAA")
+ << QString("AbCd")
+ << QString("ABCD")
+ << QString("ABCD")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "lowercase").toLatin1())
+ << QString("<AAAA")
+ << QString("AbCd")
+ << QString("abcd")
+ << QString("abcd")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "nocase").toLatin1())
+ << QString("!AAAA")
+ << QString("AbCd")
+ << QString("AbCd")
+ << QString("AbCd")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "nocase1").toLatin1())
+ << QString("!A!A!A!A")
+ << QString("AbCd")
+ << QString("AbCd")
+ << QString("AbCd")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "nocase2").toLatin1())
+ << QString("AAAA")
+ << QString("AbCd")
+ << QString("AbCd")
+ << QString("AbCd")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "reserved").toLatin1())
+ << QString("{n}[0]")
+ << QString("A9")
+ << QString("A9")
+ << QString("A9")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "escape01").toLatin1())
+ << QString("\\N\\n00")
+ << QString("9")
+ << QString("Nn9")
+ << QString("Nn9 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "escape02").toLatin1())
+ << QString("\\\\00")
+ << QString("0")
+ << QString("\\0")
+ << QString("\\0 ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "escape03").toLatin1())
+ << QString("\\(00\\)")
+ << QString("0")
+ << QString("(0)")
+ << QString("(0 )")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "upper_lower_nocase1").toLatin1())
+ << QString(">AAAA<AAAA!AAAA")
+ << QString("AbCdEfGhIjKl")
+ << QString("ABCDefghIjKl")
+ << QString("ABCDefghIjKl")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "upper_lower_nocase2").toLatin1())
+ << QString(">aaaa<aaaa!aaaa")
+ << QString("AbCdEfGhIjKl")
+ << QString("ABCDefghIjKl")
+ << QString("ABCDefghIjKl")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "exact_case1").toLatin1())
+ << QString(">A<A<A>A>A<A!A!A")
+ << QString("AbCdEFGH")
+ << QString("AbcDEfGH")
+ << QString("AbcDEfGH")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case2").toLatin1())
+ << QString(">A<A<A>A>A<A!A!A")
+ << QString("aBcDefgh")
+ << QString("AbcDEfgh")
+ << QString("AbcDEfgh")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case3").toLatin1())
+ << QString(">a<a<a>a>a<a!a!a")
+ << QString("AbCdEFGH")
+ << QString("AbcDEfGH")
+ << QString("AbcDEfGH")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case4").toLatin1())
+ << QString(">a<a<a>a>a<a!a!a")
+ << QString("aBcDefgh")
+ << QString("AbcDEfgh")
+ << QString("AbcDEfgh")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case5").toLatin1())
+ << QString(">H<H<H>H>H<H!H!H")
+ << QString("aBcDef01")
+ << QString("AbcDEf01")
+ << QString("AbcDEf01")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "exact_case6").toLatin1())
+ << QString(">h<h<h>h>h<h!h!h")
+ << QString("aBcDef92")
+ << QString("AbcDEf92")
+ << QString("AbcDEf92")
+ << bool(insert_text);
+
+ QTest::newRow(QString(insert_mode + "illegal_keys1").toLatin1())
+ << QString("AAAAAAAA")
+ << QString("A2#a;.0!")
+ << QString("Aa")
+ << QString("Aa ")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "illegal_keys2").toLatin1())
+ << QString("AAAA")
+ << QString("f4f4f4f4")
+ << QString("ffff")
+ << QString("ffff")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "blank=input").toLatin1())
+ << QString("9999;0")
+ << QString("2004")
+ << QString("2004")
+ << QString("2004")
+ << bool(insert_text);
+ }
+}
+
+void tst_QLineEdit::setInputMask()
+{
+ QFETCH(QString, mask);
+ QFETCH(QString, input);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedDisplay);
+ QFETCH(bool, insert_text);
+
+ QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
+ QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
+
+ // First set the input mask
+ testWidget->setInputMask(mask);
+
+ // then either insert using insert() or keyboard
+ if (insert_text) {
+ testWidget->insert(input);
+ } else {
+ psKeyClick(testWidget, Qt::Key_Home);
+ for (int i=0; i<input.length(); i++)
+ QTest::keyClick(testWidget, input.at(i).toLatin1());
+ }
+
+ QCOMPARE(testWidget->text(), expectedText);
+ QCOMPARE(testWidget->displayText(), expectedDisplay);
+}
+
+void tst_QLineEdit::inputMask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QString>("expectedMask");
+
+ // if no mask is set a nul string should be returned
+ QTest::newRow("") << QString("") << QString();
+ QTest::newRow("") << QString() << QString();
+
+ // try different masks
+ QTest::newRow("") << QString("000.000.000.000") << QString("000.000.000.000; ");
+ QTest::newRow("") << QString("000.000.000.000;#") << QString("000.000.000.000;#");
+ QTest::newRow("") << QString("AAA.aa.999.###;") << QString("AAA.aa.999.###; ");
+ QTest::newRow("") << QString(">abcdef<GHIJK") << QString(">abcdef<GHIJK; ");
+// QTest::newRow("") << QString() << QString();
+
+ // set an invalid input mask...
+ // the current behaviour is that this exact (faulty) string is returned.
+ QTest::newRow("") << QString("ABCDEFGHIKLMNOP;") << QString("ABCDEFGHIKLMNOP; ");
+
+ // verify that we can unset the mask again
+ QTest::newRow("") << QString("") << QString();
+}
+
+void tst_QLineEdit::inputMask()
+{
+ QFETCH(QString, mask);
+ QFETCH(QString, expectedMask);
+
+ testWidget->setInputMask(mask);
+ QCOMPARE(testWidget->inputMask(), expectedMask);
+}
+
+void tst_QLineEdit::clearInputMask()
+{
+ testWidget->setInputMask("000.000.000.000");
+ QVERIFY(testWidget->inputMask() != QString::null);
+ testWidget->setInputMask(QString::null);
+ QCOMPARE(testWidget->inputMask(), QString());
+}
+
+void tst_QLineEdit::keypress_inputMask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedDisplayText");
+
+ {
+ QTestEventList keys;
+ // inserting 'A1.2B'
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_Period);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_B);
+ QTest::newRow("jumping on period(separator)") << QString("000.000;_") << keys << QString("1.2") << QString("1__.2__");
+ }
+ {
+ QTestEventList keys;
+ // inserting 'A1.2B'
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_0);
+ keys.addKeyClick(Qt::Key_Exclam);
+ keys.addKeyClick('P');
+ keys.addKeyClick(Qt::Key_3);
+ QTest::newRow("jumping on input") << QString("D0.AA.XX.AA.00;_") << keys << QString("0..!P..3") << QString("_0.__.!P.__.3_");
+ }
+ {
+ QTestEventList keys;
+ // pressing delete
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_Delete);
+ QTest::newRow("delete") << QString("000.000;_") << keys << QString(".") << QString("___.___");
+ }
+ {
+ QTestEventList keys;
+ // selecting all and delete
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_End, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Delete);
+ QTest::newRow("deleting all") << QString("000.000;_") << keys << QString(".") << QString("___.___");
+ }
+ {
+ QTestEventList keys;
+ // inserting '12.12' then two backspaces
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_Period);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_Backspace);
+ keys.addKeyClick(Qt::Key_Backspace);
+ QTest::newRow("backspace") << QString("000.000;_") << keys << QString("12.") << QString("12_.___");
+ }
+ {
+ QTestEventList keys;
+ // inserting '12ab'
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ QTest::newRow("uppercase") << QString("9999 >AA;_") << keys << QString("12 AB") << QString("12__ AB");
+ }
+}
+
+void tst_QLineEdit::keypress_inputMask()
+{
+ QFETCH(QString, mask);
+ QFETCH(QTestEventList, keys);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedDisplayText);
+
+ testWidget->setInputMask(mask);
+ keys.simulate(testWidget);
+
+ QCOMPARE(testWidget->text(), expectedText);
+ QCOMPARE(testWidget->displayText(), expectedDisplayText);
+}
+
+
+void tst_QLineEdit::hasAcceptableInputMask_data()
+{
+ QTest::addColumn<QString>("optionalMask");
+ QTest::addColumn<QString>("requiredMask");
+ QTest::addColumn<QString>("invalid");
+ QTest::addColumn<QString>("valid");
+
+ QTest::newRow("Alphabetic optional and required")
+ << QString("aaaa") << QString("AAAA") << QString("ab") << QString("abcd");
+ QTest::newRow("Alphanumeric optional and require")
+ << QString("nnnn") << QString("NNNN") << QString("R2") << QString("R2D2");
+ QTest::newRow("Any optional and required")
+ << QString("xxxx") << QString("XXXX") << QString("+-") << QString("+-*/");
+ QTest::newRow("Numeric (0-9) required")
+ << QString("0000") << QString("9999") << QString("11") << QString("1138");
+ QTest::newRow("Numeric (1-9) optional and required")
+ << QString("dddd") << QString("DDDD") << QString("12") << QString("1234");
+}
+
+void tst_QLineEdit::hasAcceptableInputMask()
+{
+ QFocusEvent lostFocus(QEvent::FocusOut);
+ QFETCH(QString, optionalMask);
+ QFETCH(QString, requiredMask);
+ QFETCH(QString, invalid);
+ QFETCH(QString, valid);
+
+ // test that invalid input (for required) work for optionalMask
+ testWidget->setInputMask(optionalMask);
+ validInput = false;
+ testWidget->setText(invalid);
+ qApp->sendEvent(testWidget, &lostFocus);
+ QVERIFY(validInput);
+
+ // at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless
+ QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort);
+
+ // test requiredMask
+ testWidget->setInputMask(requiredMask);
+ validInput = true;
+ testWidget->setText(invalid);
+ validInput = testWidget->hasAcceptableInput();
+ QVERIFY(!validInput);
+
+ validInput = false;
+ testWidget->setText(valid);
+ qApp->sendEvent(testWidget, &lostFocus);
+ QVERIFY(validInput);
+}
+
+static const int chars = 8;
+class ValidatorWithFixup : public QValidator
+{
+public:
+ ValidatorWithFixup(QWidget *parent = 0)
+ : QValidator(parent)
+ {}
+
+ QValidator::State validate(QString &str, int &) const
+ {
+ const int s = str.size();
+ if (s < chars) {
+ return Intermediate;
+ } else if (s > chars) {
+ return Invalid;
+ }
+ return Acceptable;
+ }
+
+ void fixup(QString &str) const
+ {
+ str = str.leftJustified(chars, 'X', true);
+ }
+};
+
+
+
+void tst_QLineEdit::hasAcceptableInputValidator()
+{
+ QFocusEvent lostFocus(QEvent::FocusOut);
+ ValidatorWithFixup val;
+ testWidget->setValidator(&val);
+ testWidget->setText("foobar");
+ qApp->sendEvent(testWidget, &lostFocus);
+ QVERIFY(testWidget->hasAcceptableInput());
+}
+
+
+
+void tst_QLineEdit::maskCharacter_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<bool>("expectedValid");
+
+ QTest::newRow("Hex") << QString("H")
+ << QString("0123456789abcdefABCDEF") << true;
+ QTest::newRow("hex") << QString("h")
+ << QString("0123456789abcdefABCDEF") << true;
+ QTest::newRow("HexInvalid") << QString("H")
+ << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ")
+ << false;
+ QTest::newRow("hexInvalid") << QString("h")
+ << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ")
+ << false;
+ QTest::newRow("Bin") << QString("B")
+ << QString("01") << true;
+ QTest::newRow("bin") << QString("b")
+ << QString("01") << true;
+ QTest::newRow("BinInvalid") << QString("B")
+ << QString("23456789qwertyuiopasdfghjklzxcvbnm")
+ << false;
+ QTest::newRow("binInvalid") << QString("b")
+ << QString("23456789qwertyuiopasdfghjklzxcvbnm")
+ << false;
+}
+
+void tst_QLineEdit::maskCharacter()
+{
+ QFETCH(QString, mask);
+ QFETCH(QString, input);
+ QFETCH(bool, expectedValid);
+
+ QFocusEvent lostFocus(QEvent::FocusOut);
+
+ testWidget->setInputMask(mask);
+ for (int i = 0; i < input.size(); ++i) {
+ QString in = QString(input.at(i));
+ QString expected = expectedValid ? in : QString();
+ testWidget->setText(QString(input.at(i)));
+ qApp->sendEvent(testWidget, &lostFocus);
+ QCOMPARE(testWidget->text(), expected);
+ }
+}
+
+#define NORMAL 0
+#define REPLACE_UNTIL_END 1
+
+void tst_QLineEdit::undo_data()
+{
+ QTest::addColumn<QStringList>("insertString");
+ QTest::addColumn<IntList>("insertIndex");
+ QTest::addColumn<IntList>("insertMode");
+ QTest::addColumn<QStringList>("expectedString");
+ QTest::addColumn<bool>("use_keys");
+
+ for (int i=0; i<2; i++) {
+ QString keys_str = "keyboard";
+ bool use_keys = true;
+ if (i==0) {
+ keys_str = "insert";
+ use_keys = false;
+ }
+
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "1";
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "5";
+
+ insertIndex << 1;
+ insertMode << NORMAL;
+ insertString << "3";
+
+ insertIndex << 1;
+ insertMode << NORMAL;
+ insertString << "2";
+
+ insertIndex << 3;
+ insertMode << NORMAL;
+ insertString << "4";
+
+ expectedString << "12345";
+ expectedString << "1235";
+ expectedString << "135";
+ expectedString << "15";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "World"; // World
+
+ insertIndex << 0;
+ insertMode << NORMAL;
+ insertString << "Hello"; // HelloWorld
+
+ insertIndex << 0;
+ insertMode << NORMAL;
+ insertString << "Well"; // WellHelloWorld
+
+ insertIndex << 9;
+ insertMode << NORMAL;
+ insertString << "There"; // WellHelloThereWorld;
+
+ expectedString << "WellHelloThereWorld";
+ expectedString << "WellHelloWorld";
+ expectedString << "HelloWorld";
+ expectedString << "World";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "Ensuring";
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << " instan";
+
+ insertIndex << 9;
+ insertMode << NORMAL;
+ insertString << "an ";
+
+ insertIndex << 10;
+ insertMode << REPLACE_UNTIL_END;
+ insertString << " unique instance.";
+
+ expectedString << "Ensuring a unique instance.";
+ expectedString << "Ensuring an instan";
+ expectedString << "Ensuring instan";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ }
+}
+
+void tst_QLineEdit::undo()
+{
+ QFETCH(QStringList, insertString);
+ QFETCH(IntList, insertIndex);
+ QFETCH(IntList, insertMode);
+ QFETCH(QStringList, expectedString);
+ QFETCH(bool, use_keys);
+
+ QVERIFY(!testWidget->isUndoAvailable());
+
+ int i;
+
+// STEP 1: First build up an undo history by inserting or typing some strings...
+ for (i=0; i<insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ testWidget->setCursorPosition(insertIndex[i]);
+
+ // experimental stuff
+ if (insertMode[i] == REPLACE_UNTIL_END) {
+ testWidget->setSelection(insertIndex[i], 8);
+
+ // This is what I actually want...
+ // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
+ }
+
+ if (use_keys)
+ QTest::keyClicks(testWidget, insertString[i]);
+ else
+ testWidget->insert(insertString[i]);
+ }
+
+// STEP 2: Next call undo several times and see if we can restore to the previous state
+ for (i=0; i<expectedString.size()-1; ++i) {
+ QCOMPARE(testWidget->text(), expectedString[i]);
+ QVERIFY(testWidget->isUndoAvailable());
+ testWidget->undo();
+ }
+
+// STEP 3: Verify that we have undone everything
+ QVERIFY(!testWidget->isUndoAvailable());
+ QVERIFY(testWidget->text().isEmpty());
+
+#ifdef Q_WS_WIN
+ // Repeat the test using shortcut instead of undo()
+ for (i=0; i<insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ testWidget->setCursorPosition(insertIndex[i]);
+ if (insertMode[i] == REPLACE_UNTIL_END) {
+ testWidget->setSelection(insertIndex[i], 8);
+ }
+ if (use_keys)
+ QTest::keyClicks(testWidget, insertString[i]);
+ else
+ testWidget->insert(insertString[i]);
+ }
+ for (i=0; i<expectedString.size()-1; ++i) {
+ QCOMPARE(testWidget->text(), expectedString[i]);
+ QVERIFY(testWidget->isUndoAvailable());
+ QTest::keyClick(testWidget, Qt::Key_Backspace, Qt::AltModifier);
+ }
+#endif
+}
+
+void tst_QLineEdit::redo_data()
+{
+ QTest::addColumn<QStringList>("insertString");
+ QTest::addColumn<IntList>("insertIndex");
+ QTest::addColumn<QStringList>("expectedString");
+
+ {
+ IntList insertIndex;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertString << "World"; // World
+ insertIndex << 0;
+ insertString << "Hello"; // HelloWorld
+ insertIndex << 0;
+ insertString << "Well"; // WellHelloWorld
+ insertIndex << 9;
+ insertString << "There"; // WellHelloThereWorld;
+
+ expectedString << "World";
+ expectedString << "HelloWorld";
+ expectedString << "WellHelloWorld";
+ expectedString << "WellHelloThereWorld";
+
+ QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
+ }
+}
+
+void tst_QLineEdit::redo()
+{
+ QFETCH(QStringList, insertString);
+ QFETCH(IntList, insertIndex);
+ QFETCH(QStringList, expectedString);
+
+ QVERIFY(!testWidget->isUndoAvailable());
+ QVERIFY(!testWidget->isRedoAvailable());
+
+ int i;
+ // inserts the diff strings at diff positions
+ for (i=0; i<insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ testWidget->setCursorPosition(insertIndex[i]);
+ testWidget->insert(insertString[i]);
+ }
+
+ QVERIFY(!testWidget->isRedoAvailable());
+
+ // undo everything
+ while (!testWidget->text().isEmpty())
+ testWidget->undo();
+
+ for (i=0; i<expectedString.size(); ++i) {
+ QVERIFY(testWidget->isRedoAvailable());
+ testWidget->redo();
+ QCOMPARE(testWidget->text() , expectedString[i]);
+ }
+
+ QVERIFY(!testWidget->isRedoAvailable());
+
+#ifdef Q_WS_WIN
+ // repeat test, this time using shortcuts instead of undo()/redo()
+
+ while (!testWidget->text().isEmpty())
+ QTest::keyClick(testWidget, Qt::Key_Backspace, Qt::AltModifier);
+
+ for (i = 0; i < expectedString.size(); ++i) {
+ QVERIFY(testWidget->isRedoAvailable());
+ QTest::keyClick(testWidget, Qt::Key_Backspace,
+ Qt::ShiftModifier | Qt::AltModifier);
+ QCOMPARE(testWidget->text() , expectedString[i]);
+ }
+
+ QVERIFY(!testWidget->isRedoAvailable());
+#endif
+}
+
+void tst_QLineEdit::undo_keypressevents_data()
+{
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QStringList>("expectedString");
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ keys.addKeyClick('A');
+ keys.addKeyClick('F');
+ keys.addKeyClick('R');
+ keys.addKeyClick('A');
+ keys.addKeyClick('I');
+ keys.addKeyClick('D');
+ psKeyClick(keys, Qt::Key_Home);
+
+ keys.addKeyClick('V');
+ keys.addKeyClick('E');
+ keys.addKeyClick('R');
+ keys.addKeyClick('Y');
+
+ keys.addKeyClick(Qt::Key_Left);
+ keys.addKeyClick(Qt::Key_Left);
+ keys.addKeyClick(Qt::Key_Left);
+ keys.addKeyClick(Qt::Key_Left);
+
+ keys.addKeyClick('B');
+ keys.addKeyClick('E');
+ psKeyClick(keys, Qt::Key_End);
+
+ keys.addKeyClick(Qt::Key_Exclam);
+
+ expectedString << "BEVERYAFRAID!";
+ expectedString << "BEVERYAFRAID";
+ expectedString << "VERYAFRAID";
+ expectedString << "AFRAID";
+
+ QTest::newRow("Inserts and moving cursor") << keys << expectedString;
+ }
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ // inserting '1234'
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_3);
+ keys.addKeyClick(Qt::Key_4);
+ psKeyClick(keys, Qt::Key_Home);
+
+ // skipping '12'
+ keys.addKeyClick(Qt::Key_Right);
+ keys.addKeyClick(Qt::Key_Right);
+
+ // selecting '34'
+ keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
+
+ // deleting '34'
+ keys.addKeyClick(Qt::Key_Delete);
+
+ expectedString << "12";
+ expectedString << "1234";
+
+ QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
+ }
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ // inserting 'AB12'
+ keys.addKeyClick('A');
+ keys.addKeyClick('B');
+
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+
+ psKeyClick(keys, Qt::Key_Home);
+
+ // selecting 'AB'
+ keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
+
+ // deleting 'AB'
+ keys.addKeyClick(Qt::Key_Delete);
+
+ // undoing deletion of 'AB'
+ keys.addKeyClick(Qt::Key_Z, Qt::ControlModifier);
+
+ // unselect any current selection
+ keys.addKeyClick(Qt::Key_Right);
+#ifdef Q_WS_WIN //Mac has a specialcase to handle jumping to the end of a selection
+ keys.addKeyClick(Qt::Key_Left);
+#endif
+
+ // selecting '12'
+ keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
+
+ // deleting '12'
+ keys.addKeyClick(Qt::Key_Delete);
+
+ expectedString << "AB";
+ expectedString << "AB12";
+
+ QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
+ }
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ // inserting 'ABCD'
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_D);
+
+ //move left two
+ keys.addKeyClick(Qt::Key_Left);
+ keys.addKeyClick(Qt::Key_Left);
+
+ // inserting '1234'
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_3);
+ keys.addKeyClick(Qt::Key_4);
+
+ // selecting '1234'
+ keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
+ keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
+
+ // overwriting '1234' with '5'
+ keys.addKeyClick(Qt::Key_5);
+
+ // undoing deletion of 'AB'
+ keys.addKeyClick(Qt::Key_Z, Qt::ControlModifier);
+
+ // overwriting '1234' with '6'
+ keys.addKeyClick(Qt::Key_6);
+
+ expectedString << "ab6cd";
+ // for versions previous to 3.2 we overwrite needed two undo operations
+ expectedString << "ab1234cd";
+ expectedString << "abcd";
+
+ QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
+ }
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ // inserting 'ABC'
+ keys.addKeyClick('A');
+ keys.addKeyClick('B');
+ keys.addKeyClick('C');
+
+ // removes 'C'
+ keys.addKeyClick(Qt::Key_Backspace);
+
+ expectedString << "AB";
+ expectedString << "ABC";
+
+ QTest::newRow("Inserts,backspace") << keys << expectedString;
+ }
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ // inserting 'ABC'
+ keys.addKeyClick('A');
+ keys.addKeyClick('B');
+ keys.addKeyClick('C');
+
+ // removes 'C'
+ keys.addKeyClick(Qt::Key_Backspace);
+
+ // inserting 'Z'
+ keys.addKeyClick('Z');
+
+ expectedString << "ABZ";
+ expectedString << "AB";
+ expectedString << "ABC";
+
+ QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
+ }
+
+
+ {
+ QTestEventList keys;
+ QStringList expectedString;
+
+ // inserting '123'
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_3);
+ psKeyClick(keys, Qt::Key_Home);
+
+ // selecting '123'
+ psKeyClick(keys, Qt::Key_End, Qt::ShiftModifier);
+
+ // overwriting '123' with 'ABC'
+ keys.addKeyClick('A');
+ keys.addKeyClick('B');
+ keys.addKeyClick('C');
+
+ expectedString << "ABC";
+ // for versions previous to 3.2 we overwrite needed two undo operations
+ expectedString << "123";
+
+ QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
+ }
+}
+
+void tst_QLineEdit::undo_keypressevents()
+{
+ QFETCH(QTestEventList, keys);
+ QFETCH(QStringList, expectedString);
+
+ keys.simulate(testWidget);
+
+ for (int i=0; i<expectedString.size(); ++i) {
+ QCOMPARE(testWidget->text() , expectedString[i]);
+ testWidget->undo();
+ }
+ QVERIFY(testWidget->text().isEmpty());
+}
+
+#ifndef QT_NO_CLIPBOARD
+static bool nativeClipboardWorking()
+{
+#ifdef Q_WS_MAC
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ return status == noErr;
+#endif
+ return true;
+}
+
+void tst_QLineEdit::QTBUG5786_undoPaste()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("this machine doesn't support the clipboard", SkipAll);
+ QString initial("initial");
+ QString string("test");
+ QString additional("add");
+ QApplication::clipboard()->setText(string);
+ QLineEdit edit(initial);
+ QCOMPARE(edit.text(), initial);
+ edit.paste();
+ QCOMPARE(edit.text(), initial + string);
+ edit.paste();
+ QCOMPARE(edit.text(), initial + string + string);
+ edit.insert(additional);
+ QCOMPARE(edit.text(), initial + string + string + additional);
+ edit.undo();
+ QCOMPARE(edit.text(), initial + string + string);
+ edit.undo();
+ QCOMPARE(edit.text(), initial + string);
+ edit.undo();
+ QCOMPARE(edit.text(), initial);
+ edit.selectAll();
+ QApplication::clipboard()->setText(QString());
+ edit.paste();
+ QVERIFY(edit.text().isEmpty());
+
+}
+#endif
+
+
+void tst_QLineEdit::clear()
+{
+ // checking that clear of empty/nullstring doesn't add to undo history
+ int max = 5000;
+ while (max > 0 && testWidget->isUndoAvailable()) {
+ max--;
+ testWidget->undo();
+ }
+
+ testWidget->clear();
+// QVERIFY(!testWidget->isUndoAvailable());
+
+ // checks that clear actually clears
+ testWidget->insert("I am Legend");
+ testWidget->clear();
+ QVERIFY(testWidget->text().isEmpty());
+
+ // checks that clears can be undone
+ testWidget->undo();
+ QCOMPARE(testWidget->text(), QString("I am Legend"));
+}
+
+void tst_QLineEdit::editingFinished()
+{
+ if (testWidget->hasAcceptableInput())
+ validInput = true;
+ else
+ validInput = false;
+}
+
+void tst_QLineEdit::text_data()
+{
+ QTest::addColumn<QString>("insertString");
+
+ QTest::newRow("Plain text0") << QString("Hello World");
+ QTest::newRow("Plain text1") << QString("");
+ QTest::newRow("Plain text2") << QString("A");
+ QTest::newRow("Plain text3") << QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry");
+ QTest::newRow("Plain text4") << QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"");
+ QTest::newRow("Newlines") << QString("A\nB\nC\n");
+ QTest::newRow("Text with nbsp") << QString("Hello") + QChar(0xa0) + "World";
+}
+
+void tst_QLineEdit::text()
+{
+ QFETCH(QString, insertString);
+ testWidget->setText(insertString);
+ QCOMPARE(testWidget->text(), insertString);
+}
+
+void tst_QLineEdit::textMask_data()
+{
+ QTest::addColumn<QString>("insertString");
+
+ QTest::newRow( "Plain text1" ) << QString( "" );
+}
+
+void tst_QLineEdit::textMask()
+{
+ QFETCH( QString, insertString );
+ testWidget->setInputMask( "#" );
+ testWidget->setText( insertString );
+ QCOMPARE( testWidget->text(), insertString );
+}
+
+void tst_QLineEdit::setText()
+{
+ QSignalSpy editedSpy(testWidget, SIGNAL(textEdited(QString)));
+ QSignalSpy changedSpy(testWidget, SIGNAL(textChanged(QString)));
+ testWidget->setText("hello");
+ QCOMPARE(editedSpy.count(), 0);
+ QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello"));
+}
+
+void tst_QLineEdit::displayText_data()
+{
+ QTest::addColumn<QString>("insertString");
+ QTest::addColumn<QString>("expectedString");
+ QTest::addColumn<QLineEdit::EchoMode>("mode");
+ QTest::addColumn<bool>("use_setText");
+
+ QString s;
+ QLineEdit::EchoMode m;
+
+ for (int i=0; i<2; i++) {
+ QString key_mode_str;
+ bool use_setText;
+ if (i==0) {
+ key_mode_str = "setText_";
+ use_setText = true;
+ } else {
+ key_mode_str = "useKeys_";
+ use_setText = false;
+ }
+ s = key_mode_str + "Normal";
+ m = QLineEdit::Normal;
+ QTest::newRow(QString(s + " text0").toLatin1()) << QString("Hello World") <<
+ QString("Hello World") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text1").toLatin1()) << QString("") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") <<
+ QString("A") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text3").toLatin1()) << QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry") <<
+ QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text4").toLatin1()) << QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"") <<
+ QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text with nbsp").toLatin1()) << QString("Hello") + QChar(0xa0) + "World" <<
+ QString("Hello") + QChar(0xa0) + "World" <<
+ m << bool(use_setText);
+ s = key_mode_str + "NoEcho";
+ m = QLineEdit::NoEcho;
+ QTest::newRow(QString(s + " text0").toLatin1()) << QString("Hello World") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text1").toLatin1()) << QString("") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text3").toLatin1()) << QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text4").toLatin1()) << QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text with nbsp").toLatin1()) << QString("Hello") + QChar(0xa0) + "World" <<
+ QString("") <<
+ m << bool(use_setText);
+ s = key_mode_str + "Password";
+ m = QLineEdit::Password;
+ QChar passChar = qApp->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, 0, testWidget);
+ QString input;
+ QString pass;
+ input = "Hello World";
+ pass.resize(input.length());
+ pass.fill(passChar);
+ QTest::newRow(QString(s + " text0").toLatin1()) << input << pass << m << bool(use_setText);
+ QTest::newRow(QString(s + " text1").toLatin1()) << QString("") <<
+ QString("") <<
+ m << bool(use_setText);
+ QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") << QString(passChar) << m << bool(use_setText);
+ input = QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry");
+ pass.resize(input.length());
+ pass.fill(passChar);
+ QTest::newRow(QString(s + " text3").toLatin1()) << input << pass << m << bool(use_setText);
+ input = QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"");
+ pass.fill(passChar, input.length());
+ QTest::newRow(QString(s + " text4").toLatin1()) << input << pass << m << bool(use_setText);
+ input = QString("Hello") + QChar(0xa0) + "World";
+ pass.resize(input.length());
+ pass.fill(passChar);
+ QTest::newRow(QString(s + " text with nbsp").toLatin1()) << input << pass << m << bool(use_setText);
+ }
+}
+
+void tst_QLineEdit::displayText()
+{
+ QFETCH(QString, insertString);
+ QFETCH(QString, expectedString);
+ QFETCH(QLineEdit::EchoMode, mode);
+ //QFETCH(bool, use_setText); Currently unused.
+
+ testWidget->setEchoMode(mode);
+ testWidget->setText(insertString);
+ QCOMPARE(testWidget->displayText(), expectedString);
+ QVERIFY(testWidget->echoMode() == mode);
+}
+
+void tst_QLineEdit::passwordEchoOnEdit()
+{
+ QStyleOptionFrameV2 opt;
+ QChar fillChar = testWidget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, testWidget);
+
+ testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
+ testWidget->setFocus();
+ testWidget->raise();
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ QTest::keyPress(testWidget, '0');
+ QTest::keyPress(testWidget, '1');
+ QTest::keyPress(testWidget, '2');
+ QTest::keyPress(testWidget, '3');
+ QTest::keyPress(testWidget, '4');
+ QCOMPARE(testWidget->displayText(), QString("01234"));
+ testWidget->clearFocus();
+ QVERIFY(!testWidget->hasFocus());
+ QCOMPARE(testWidget->displayText(), QString(5, fillChar));
+ testWidget->setFocus();
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ QCOMPARE(testWidget->displayText(), QString(5, fillChar));
+ QTest::keyPress(testWidget, '0');
+ QCOMPARE(testWidget->displayText(), QString("0"));
+
+ // restore clean state
+ testWidget->setEchoMode(QLineEdit::Normal);
+}
+
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+void tst_QLineEdit::passwordEchoDelay()
+{
+ QStyleOptionFrameV2 opt;
+ QChar fillChar = testWidget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, testWidget);
+
+ testWidget->setEchoMode(QLineEdit::Password);
+ testWidget->setFocus();
+ testWidget->raise();
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ QTest::keyPress(testWidget, '0');
+ QTest::keyPress(testWidget, '1');
+ QTest::keyPress(testWidget, '2');
+ QCOMPARE(testWidget->displayText(), QString(2, fillChar) + QLatin1Char('2'));
+ QTest::keyPress(testWidget, '3');
+ QTest::keyPress(testWidget, '4');
+ QCOMPARE(testWidget->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::keyPress(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->displayText(), QString(4, fillChar));
+ QTest::keyPress(testWidget, '4');
+ QCOMPARE(testWidget->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
+ QTRY_COMPARE(testWidget->displayText(), QString(5, fillChar));
+ QTest::keyPress(testWidget, '5');
+ QCOMPARE(testWidget->displayText(), QString(5, fillChar) + QLatin1Char('5'));
+ testWidget->clearFocus();
+ QVERIFY(!testWidget->hasFocus());
+ QCOMPARE(testWidget->displayText(), QString(6, fillChar));
+ testWidget->setFocus();
+ QTRY_VERIFY(testWidget->hasFocus());
+ QCOMPARE(testWidget->displayText(), QString(6, fillChar));
+ QTest::keyPress(testWidget, '6');
+ QCOMPARE(testWidget->displayText(), QString(6, fillChar) + QLatin1Char('6'));
+
+ QInputMethodEvent ev;
+ ev.setCommitString(QLatin1String("7"));
+ QApplication::sendEvent(testWidget, &ev);
+ QCOMPARE(testWidget->displayText(), QString(7, fillChar) + QLatin1Char('7'));
+
+ testWidget->setCursorPosition(3);
+ QCOMPARE(testWidget->displayText(), QString(7, fillChar) + QLatin1Char('7'));
+ QTest::keyPress(testWidget, 'a');
+ QCOMPARE(testWidget->displayText(), QString(3, fillChar) + QLatin1Char('a') + QString(5, fillChar));
+ QTest::keyPress(testWidget, Qt::Key_Backspace);
+ QCOMPARE(testWidget->displayText(), QString(8, fillChar));
+
+ // restore clean state
+ testWidget->setEchoMode(QLineEdit::Normal);
+}
+#endif
+
+void tst_QLineEdit::maxLength_mask_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<int>("expectedLength");
+
+ QTest::newRow("mask_case") << QString(">000<>00<000") << 8;
+ QTest::newRow("mask_nocase") << QString("00000000") << 8;
+ QTest::newRow("mask_null") << QString() << 32767;
+ QTest::newRow("mask_escape") << QString("\\A\\aAA") << 4;
+}
+
+void tst_QLineEdit::maxLength_mask()
+{
+ QFETCH(QString, mask);
+ QFETCH(int, expectedLength);
+
+ testWidget->setInputMask(mask);
+
+ QCOMPARE(testWidget->maxLength(), expectedLength);
+}
+
+void tst_QLineEdit::maxLength_data()
+{
+ QTest::addColumn<QString>("insertString");
+ QTest::addColumn<QString>("expectedString");
+ QTest::addColumn<int>("length");
+ QTest::addColumn<bool>("insertBeforeSettingMaxLength");
+ QTest::addColumn<bool>("use_setText");
+
+ QTest::newRow("keyclick before0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(true) << bool(false);
+ QTest::newRow("keyclick before1") << QString("this is a test.") << QString("this is a ") << 10 << bool(true) << bool(false);
+ QTest::newRow("keyclick after0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(false) << bool(false);
+ QTest::newRow("keyclick after1") << QString("this is a test.") << QString("this is a ") << 10 << bool(false) << bool(false);
+ QTest::newRow("settext before0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(true) << bool(true);
+ QTest::newRow("settext before1") << QString("this is a test.") << QString("this is a ") << 10 << bool(true) << bool(true);
+ QTest::newRow("settext after0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(false) << bool(true);
+ QTest::newRow("settext after1") << QString("this is a test.") << QString("this is a ") << 10 << bool(false) << bool(true);
+}
+
+void tst_QLineEdit::maxLength()
+{
+ QFETCH(QString, insertString);
+ QFETCH(QString, expectedString);
+ QFETCH(int, length);
+ QFETCH(bool, insertBeforeSettingMaxLength);
+ QFETCH(bool, use_setText);
+
+ // in some cases we set the maxLength _before_ entering the text.
+ if (!insertBeforeSettingMaxLength)
+ testWidget->setMaxLength(length);
+
+ // I expect MaxLength to work BOTH with entering live characters AND with setting the text.
+ if (use_setText) {
+ // Enter insertString using setText.
+ testWidget->setText(insertString);
+ } else {
+ // Enter insertString as a sequence of keyClicks
+ QTest::keyClicks(testWidget, insertString);
+ }
+
+ // in all other cases we set the maxLength _after_ entering the text.
+ if (insertBeforeSettingMaxLength) {
+ changed_count = 0;
+ testWidget->setMaxLength(length);
+
+ // Make sure that the textChanged is not emitted unless the text is actually changed
+ if (insertString == expectedString) {
+ QVERIFY(changed_count == 0);
+ } else {
+ QVERIFY(changed_count == 1);
+ }
+ }
+
+ // and check if we get the expected string back
+ QCOMPARE(testWidget->text(), expectedString);
+}
+
+void tst_QLineEdit::isReadOnly()
+{
+ QVERIFY(!testWidget->isReadOnly());
+
+ // start with a basic text
+ QTest::keyClicks(testWidget, "the quick brown fox");
+ QCOMPARE(testWidget->text(), QString("the quick brown fox"));
+
+ // do a quick check to verify that we can indeed edit the text
+ testWidget->home(false);
+ testWidget->cursorForward(false, 10);
+ QTest::keyClicks(testWidget, "dark ");
+ QCOMPARE(testWidget->text(), QString("the quick dark brown fox"));
+
+ testWidget->setReadOnly(true);
+ QVERIFY(testWidget->isReadOnly());
+
+ // verify that we cannot edit the text anymore
+ testWidget->home(false);
+ testWidget->cursorForward(false, 10);
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QCOMPARE(testWidget->text(), QString("the quick dark brown fox"));
+ testWidget->cursorForward(false, 10);
+ QTest::keyClicks(testWidget, "this should not have any effect!! ");
+ QCOMPARE(testWidget->text(), QString("the quick dark brown fox"));
+}
+
+static void figureOutProperKey(Qt::Key &key, Qt::KeyboardModifiers &pressState)
+{
+#ifdef Q_WS_MAC
+ static bool tst_lineedit_randomized = false;
+ // Mac has 3 different ways of accomplishing this (same for moving to the back)
+ // So I guess we should just randomly do this for now. Which may get people mad, but if
+ // we fail at one point, it's just a matter of setting roll to the correct value
+ // instead of random.
+
+ if (!tst_lineedit_randomized) {
+ tst_lineedit_randomized = true;
+ ::srandom(ulong(time(0)));
+ }
+ long roll = ::random() % 3;
+ switch (roll) {
+ case 0:
+ key = key == Qt::Key_Home ? Qt::Key_Up : Qt::Key_Down;
+ break;
+ case 1:
+ case 2:
+ key = key == Qt::Key_Home ? Qt::Key_Left : Qt::Key_Right;
+ pressState |= (roll == 1) ? Qt::ControlModifier : Qt::MetaModifier;
+ break;
+ }
+#else
+ // Naively kill the warning.
+ key = key;
+ pressState = pressState;
+#endif
+}
+
+// Platform specific move. Home and End do nothing on the Mac,
+// so do something a bit smarter than tons of #ifdefs
+void tst_QLineEdit::psKeyClick(QWidget *target, Qt::Key key, Qt::KeyboardModifiers pressState)
+{
+ figureOutProperKey(key, pressState);
+ QTest::keyClick(target, key, pressState);
+}
+
+void tst_QLineEdit::psKeyClick(QTestEventList &keys, Qt::Key key, Qt::KeyboardModifiers pressState)
+{
+ figureOutProperKey(key, pressState);
+ keys.addKeyClick(key, pressState);
+}
+
+void tst_QLineEdit::cursorPosition()
+{
+ QVERIFY(testWidget->cursorPosition() == 0);
+
+ // start with a basic text
+ QTest::keyClicks(testWidget, "The");
+ QCOMPARE(testWidget->cursorPosition(), 3);
+ QTest::keyClicks(testWidget, " quick");
+ QCOMPARE(testWidget->cursorPosition(), 9);
+ QTest::keyClicks(testWidget, " brown fox jumps over the lazy dog");
+ QCOMPARE(testWidget->cursorPosition(), 43);
+
+ // The text we have now is:
+ // 1 2 3 4 5
+ // 012345678901234567890123456789012345678901234567890
+ // The quick brown fox jumps over the lazy dog
+
+ // next we will check some of the cursor movement functions
+ testWidget->end(false);
+ QCOMPARE(testWidget->cursorPosition() , 43);
+ testWidget->cursorForward(false, -1);
+ QCOMPARE(testWidget->cursorPosition() , 42);
+ testWidget->cursorBackward(false, 1);
+ QCOMPARE(testWidget->cursorPosition() , 41);
+ testWidget->home(false);
+ QCOMPARE(testWidget->cursorPosition() , 0);
+ testWidget->cursorForward(false, 1);
+ QCOMPARE(testWidget->cursorPosition() , 1);
+ testWidget->cursorForward(false, 9);
+ QCOMPARE(testWidget->cursorPosition() , 10);
+ testWidget->cursorWordForward(false); // 'fox'
+ QCOMPARE(testWidget->cursorPosition(), 16);
+ testWidget->cursorWordForward(false); // 'jumps'
+ QCOMPARE(testWidget->cursorPosition(), 20);
+ testWidget->cursorWordBackward(false); // 'fox'
+ QCOMPARE(testWidget->cursorPosition(), 16);
+ testWidget->cursorWordBackward(false); // 'brown'
+ testWidget->cursorWordBackward(false); // 'quick'
+ testWidget->cursorWordBackward(false); // 'The'
+ QCOMPARE(testWidget->cursorPosition(), 0);
+ testWidget->cursorWordBackward(false); // 'The'
+ QCOMPARE(testWidget->cursorPosition(), 0);
+
+ // Cursor position should be 0 here!
+ int i;
+ for (i=0; i<5; i++)
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QCOMPARE(testWidget->cursorPosition(), 5);
+ psKeyClick(testWidget, Qt::Key_End);
+ QCOMPARE(testWidget->cursorPosition(), 43);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QCOMPARE(testWidget->cursorPosition(), 42);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QCOMPARE(testWidget->cursorPosition(), 41);
+ psKeyClick(testWidget, Qt::Key_Home);
+ QCOMPARE(testWidget->cursorPosition(), 0);
+
+ // cursorposition when maxlength is set
+ int maxLength = 9;
+ testWidget->clear();
+ testWidget->setMaxLength(maxLength);
+ QCOMPARE(testWidget->cursorPosition() , 0);
+ QTest::keyClicks(testWidget, "123ABC123");
+ QCOMPARE(testWidget->cursorPosition() , maxLength);
+ psKeyClick(testWidget, Qt::Key_Home);
+ QCOMPARE(testWidget->cursorPosition() , 0);
+ psKeyClick(testWidget, Qt::Key_End);
+ QCOMPARE(testWidget->cursorPosition() , maxLength);
+}
+
+/* // tested in cursorPosition
+void tst_QLineEdit::cursorLeft()
+void tst_QLineEdit::cursorRight()
+void tst_QLineEdit::cursorForward()
+void tst_QLineEdit::cursorBackward()
+void tst_QLineEdit::cursorWordForward()
+void tst_QLineEdit::cursorWordBackward()
+void tst_QLineEdit::home()
+void tst_QLineEdit::end()
+*/
+
+void tst_QLineEdit::cursorPositionChanged_data()
+{
+ QTest::addColumn<QTestEventList>("input");
+ QTest::addColumn<int>("lastPos");
+ QTest::addColumn<int>("newPos");
+
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_A);
+ QTest::newRow("a") << keys << 0 << 1;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ psKeyClick(keys, Qt::Key_Home);
+ QTest::newRow("abc<home>") << keys << 3 << 0;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Left);
+ QTest::newRow("abc<left>") << keys << 3 << 2;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Right);
+ QTest::newRow("abc<right>") << keys << 2 << 3;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ psKeyClick(keys, Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_Right);
+ QTest::newRow("abc<home><right>") << keys << 0 << 1;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Backspace);
+ QTest::newRow("abc<backspace>") << keys << 3 << 2;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Delete);
+ QTest::newRow("abc<delete>") << keys << 2 << 3;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Left);
+ keys.addKeyClick(Qt::Key_Delete);
+ QTest::newRow("abc<left><delete>") << keys << 3 << 2;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ psKeyClick(keys, Qt::Key_Home);
+ psKeyClick(keys, Qt::Key_End);
+ QTest::newRow("abc<home><end>") << keys << 0 << 3;
+ keys.clear();
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Space);
+ keys.addKeyClick(Qt::Key_D);
+ keys.addKeyClick(Qt::Key_E);
+ keys.addKeyClick(Qt::Key_F);
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_Right, Qt::ControlModifier);
+ QTest::newRow("abc efg<home><ctrl-right>") << keys
+#ifndef Q_WS_MAC
+ << 0 << 4;
+#else
+ << 6 << 7;
+#endif
+ keys.clear();
+
+#ifdef Q_WS_MAC
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Space);
+ keys.addKeyClick(Qt::Key_D);
+ keys.addKeyClick(Qt::Key_E);
+ keys.addKeyClick(Qt::Key_F);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Right, Qt::AltModifier);
+ QTest::newRow("mac equivalent abc efg<up><option-right>") << keys << 0 << 4;
+ keys.clear();
+#endif
+
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Space);
+ keys.addKeyClick(Qt::Key_D);
+ keys.addKeyClick(Qt::Key_E);
+ keys.addKeyClick(Qt::Key_F);
+ keys.addKeyClick(Qt::Key_Left, Qt::ControlModifier);
+ QTest::newRow("abc efg<ctrl-left>") << keys << 7
+#ifndef Q_WS_MAC
+ << 4;
+#else
+ << 0;
+#endif
+ keys.clear();
+#ifdef Q_WS_MAC
+ keys.addKeyClick(Qt::Key_A);
+ keys.addKeyClick(Qt::Key_B);
+ keys.addKeyClick(Qt::Key_C);
+ keys.addKeyClick(Qt::Key_Space);
+ keys.addKeyClick(Qt::Key_D);
+ keys.addKeyClick(Qt::Key_E);
+ keys.addKeyClick(Qt::Key_F);
+ keys.addKeyClick(Qt::Key_Left, Qt::AltModifier);
+ QTest::newRow("mac equivalent abc efg<option-left>") << keys << 7 << 4;
+ keys.clear();
+#endif
+}
+
+
+void tst_QLineEdit::cursorPositionChanged()
+{
+ QFETCH(QTestEventList, input);
+ QFETCH(int, lastPos);
+ QFETCH(int, newPos);
+
+ lastCursorPos = 0;
+ newCursorPos = 0;
+ input.simulate(testWidget);
+ QCOMPARE(lastCursorPos, lastPos);
+ QCOMPARE(newCursorPos, newPos);
+}
+
+void tst_QLineEdit::selectedText()
+{
+ QString testString = "Abc defg hijklmno, p 'qrst' uvw xyz";
+
+ // start with a basic text
+ testWidget->setText(testString);
+ selection_count = 0;
+
+ // The text we have now is:
+ // 1 2 3 4 5
+ // 012345678901234567890123456789012345678901234567890
+ // Abc defg hijklmno, p 'qrst' uvw xyz
+
+ testWidget->home(false);
+ QVERIFY(!testWidget->hasSelectedText());
+ QCOMPARE(testWidget->selectedText(), QString());
+
+ // play a bit with the cursorForward, cursorBackward(), etc
+ testWidget->cursorForward(true, 9);
+ QVERIFY(testWidget->hasSelectedText());
+ QCOMPARE(testWidget->selectedText(), QString("Abc defg "));
+ QVERIFY(selection_count == 1);
+
+ // reset selection
+ testWidget->home(false);
+ QVERIFY(!testWidget->hasSelectedText());
+ QCOMPARE(testWidget->selectedText(), QString());
+ selection_count = 0;
+}
+
+/* // tested in selectedText
+void tst_QLineEdit::backspace()
+void tst_QLineEdit::del()
+void tst_QLineEdit::selectionChanged()
+void tst_QLineEdit::selectAll()
+void tst_QLineEdit::deselect()
+*/
+
+void tst_QLineEdit::onSelectionChanged()
+{
+ selection_count++;
+}
+
+void tst_QLineEdit::deleteSelectedText()
+{
+ const QString text = QString::fromLatin1("bar");
+ QLineEdit edit( text );
+ QCOMPARE(edit.text(), text);
+
+ edit.selectAll();
+
+ QTest::keyClick(&edit, Qt::Key_Delete, 0);
+ QVERIFY(edit.text().isEmpty());
+
+ edit.setText(text);
+ edit.selectAll();
+
+ QMenu *menu = edit.createStandardContextMenu();
+ for (int i = 0; i < menu->actions().count(); ++i) {
+ QAction *current = menu->actions().at(i);
+ if (current->text() == QLineEdit::tr("Delete")) {
+ current->trigger(); //this will delete the whole text selected
+ QVERIFY(edit.text().isEmpty());
+ }
+ }
+
+}
+
+
+void tst_QLineEdit::textChangedAndTextEdited()
+{
+ changed_count = 0;
+ edited_count = 0;
+
+ QTest::keyClick(testWidget, Qt::Key_A);
+ QCOMPARE(changed_count, 1);
+ QVERIFY(edited_count == changed_count);
+ QTest::keyClick(testWidget, 'b');
+ QCOMPARE(changed_count, 2);
+ QVERIFY(edited_count == changed_count);
+ QTest::keyClick(testWidget, 'c');
+ QCOMPARE(changed_count, 3);
+ QVERIFY(edited_count == changed_count);
+ QTest::keyClick(testWidget, ' ');
+ QCOMPARE(changed_count, 4);
+ QVERIFY(edited_count == changed_count);
+ QTest::keyClick(testWidget, 'd');
+ QCOMPARE(changed_count, 5);
+ QVERIFY(edited_count == changed_count);
+
+ changed_count = 0;
+ edited_count = 0;
+ changed_string = QString::null;
+
+ testWidget->setText("foo");
+ QCOMPARE(changed_count, 1);
+ QCOMPARE(edited_count, 0);
+ QCOMPARE(changed_string, QString("foo"));
+
+ changed_count = 0;
+ edited_count = 0;
+ changed_string = QString::null;
+
+ testWidget->setText("");
+ QCOMPARE(changed_count, 1);
+ QCOMPARE(edited_count, 0);
+ QVERIFY(changed_string.isEmpty());
+ QVERIFY(!changed_string.isNull());
+}
+
+void tst_QLineEdit::onTextChanged(const QString &text)
+{
+ changed_count++;
+ changed_string = text;
+}
+
+void tst_QLineEdit::onTextEdited(const QString &/*text*/)
+{
+ edited_count++;
+}
+
+
+void tst_QLineEdit::onCursorPositionChanged(int oldPos, int newPos)
+{
+ lastCursorPos = oldPos;
+ newCursorPos = newPos;
+}
+
+void tst_QLineEdit::returnPressed()
+{
+ return_count = 0;
+
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QVERIFY(return_count == 1);
+ return_count = 0;
+
+ QTest::keyClick(testWidget, 'A');
+ QVERIFY(return_count == 0);
+ QTest::keyClick(testWidget, 'b');
+ QVERIFY(return_count == 0);
+ QTest::keyClick(testWidget, 'c');
+ QVERIFY(return_count == 0);
+ QTest::keyClick(testWidget, ' ');
+ QVERIFY(return_count == 0);
+ QTest::keyClick(testWidget, 'd');
+ QVERIFY(return_count == 0);
+ psKeyClick(testWidget, Qt::Key_Home);
+ QVERIFY(return_count == 0);
+ psKeyClick(testWidget, Qt::Key_End);
+ QVERIFY(return_count == 0);
+ QTest::keyClick(testWidget, Qt::Key_Escape);
+ QVERIFY(return_count == 0);
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QVERIFY(return_count == 1);
+}
+
+// int validator that fixes all !isNumber to '0'
+class QIntFixValidator : public QIntValidator {
+public:
+ QIntFixValidator(int min, int max, QObject *parent) : QIntValidator(min, max, parent) {}
+ void fixup (QString &input) const {
+ for (int i=0; i<input.length(); ++i)
+ if (!input.at(i).isNumber()) {
+ input[(int)i] = QChar('0');
+ }
+ }
+};
+
+void tst_QLineEdit::returnPressed_maskvalidator_data() {
+ QTest::addColumn<QString>("inputMask");
+ QTest::addColumn<bool>("hasValidator");
+ QTest::addColumn<QTestEventList>("input");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<bool>("returnPressed");
+
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_3);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("no mask, no validator, input '123<cr>'")
+ << QString()
+ << false
+ << keys
+ << QString("123")
+ << true;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("mask '999', no validator, input '12<cr>'")
+ << QString("999")
+ << false
+ << keys
+ << QString("12")
+ << false;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_3);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("mask '999', no validator, input '123<cr>'")
+ << QString("999")
+ << false
+ << keys
+ << QString("123")
+ << true;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_3);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("no mask, intfix validator(0,999), input '123<cr>'")
+ << QString()
+ << true
+ << keys
+ << QString("123")
+ << true;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_7);
+ keys.addKeyClick(Qt::Key_7);
+ keys.addKeyClick(Qt::Key_7);
+ keys.addKeyClick(Qt::Key_7);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("no mask, intfix validator(0,999), input '7777<cr>'")
+ << QString()
+ << true
+ << keys
+ << QString("777")
+ << true;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_1);
+ keys.addKeyClick(Qt::Key_2);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("mask '999', intfix validator(0,999), input '12<cr>'")
+ << QString("999")
+ << true
+ << keys
+ << QString("12")
+ << false;
+ }
+ {
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Home);
+ keys.addKeyClick(Qt::Key_Return);
+ QTest::newRow("mask '999', intfix validator(0,999), input '<cr>'")
+ << QString("999")
+ << true
+ << keys
+ << QString("000")
+ << true;
+ }
+}
+
+void tst_QLineEdit::returnPressed_maskvalidator()
+{
+ QFETCH(QString, inputMask);
+ QFETCH(bool, hasValidator);
+ QFETCH(QTestEventList, input);
+ QFETCH(QString, expectedText);
+ QFETCH(bool, returnPressed);
+
+ QEXPECT_FAIL("mask '999', intfix validator(0,999), input '12<cr>'", "QIntValidator has changed behaviour. Does not accept spaces. Task 43082.", Abort);
+
+ testWidget->setInputMask(inputMask);
+ if (hasValidator)
+ testWidget->setValidator(new QIntFixValidator(0, 999, testWidget));
+
+ return_count = 0;
+ input.simulate(testWidget);
+
+ QCOMPARE(testWidget->text(), expectedText);
+ QCOMPARE(return_count , returnPressed ? 1 : 0);
+}
+
+void tst_QLineEdit::onReturnPressed()
+{
+ return_count++;
+}
+
+void tst_QLineEdit::setValidator()
+{
+ // Verify that we can set and re-set a validator.
+ QVERIFY(!testWidget->validator());
+
+ QIntValidator iv1(0);
+ testWidget->setValidator(&iv1);
+ QCOMPARE(testWidget->validator(), static_cast<const QValidator*>(&iv1));
+
+ testWidget->setValidator(0);
+ QVERIFY(testWidget->validator() == 0);
+
+ QIntValidator iv2(0, 99, 0);
+ testWidget->setValidator(&iv2);
+ QCOMPARE(testWidget->validator(), static_cast<const QValidator *>(&iv2));
+
+ testWidget->setValidator(0);
+ QVERIFY(testWidget->validator() == 0);
+}
+
+void tst_QLineEdit::setValidator_QIntValidator_data()
+{
+ QTest::addColumn<int>("mini");
+ QTest::addColumn<int>("maxi");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<bool>("useKeys");
+ QTest::addColumn<bool>("is_valid");
+
+ for (int i=0; i<2; i++) {
+ bool useKeys = false;
+ QString inputMode = "insert ";
+ if (i!=0) {
+ inputMode = "useKeys ";
+ useKeys = true;
+ }
+
+ // valid data
+ QTest::newRow(QString(inputMode + "range [0,9] valid '1'").toLatin1())
+ << 0
+ << 9
+ << QString("1")
+ << QString("1")
+ << bool(useKeys)
+ << bool(true);
+
+ QTest::newRow(QString(inputMode + "range [3,7] valid '3'").toLatin1())
+ << 3
+ << 7
+ << QString("3")
+ << QString("3")
+ << bool(useKeys)
+ << bool(true);
+
+ QTest::newRow(QString(inputMode + "range [3,7] valid '7'").toLatin1())
+ << 3
+ << 7
+ << QString("7")
+ << QString("7")
+ << bool(useKeys)
+ << bool(true);
+
+ QTest::newRow(QString(inputMode + "range [0,100] valid '9'").toLatin1())
+ << 0
+ << 100
+ << QString("9")
+ << QString("9")
+ << bool(useKeys)
+ << bool(true);
+
+ QTest::newRow(QString(inputMode + "range [0,100] valid '12'").toLatin1())
+ << 0
+ << 100
+ << QString("12")
+ << QString("12")
+ << bool(useKeys)
+ << bool(true);
+
+ QTest::newRow(QString(inputMode + "range [-100,100] valid '-12'").toLatin1())
+ << -100
+ << 100
+ << QString("-12")
+ << QString("-12")
+ << bool(useKeys)
+ << bool(true);
+
+ // invalid data
+ // characters not allowed in QIntValidator
+ QTest::newRow(QString(inputMode + "range [0,9] inv 'a-a'").toLatin1())
+ << 0
+ << 9
+ << QString("a")
+ << QString("")
+ << bool(useKeys)
+ << bool(false);
+
+ QTest::newRow(QString(inputMode + "range [0,9] inv 'A'").toLatin1())
+ << 0
+ << 9
+ << QString("A")
+ << QString("")
+ << bool(useKeys)
+ << bool(false);
+ // minus sign only allowed with a range on the negative side
+ QTest::newRow(QString(inputMode + "range [0,100] inv '-'").toLatin1())
+ << 0
+ << 100
+ << QString("-")
+ << QString("")
+ << bool(useKeys)
+ << bool(false);
+ QTest::newRow(QString(inputMode + "range [0,100] int '153'").toLatin1())
+ << 0
+ << 100
+ << QString("153")
+ << QString(useKeys ? "15" : "")
+ << bool(useKeys)
+ << bool(useKeys ? true : false);
+ QTest::newRow(QString(inputMode + "range [-100,100] int '-153'").toLatin1())
+ << -100
+ << 100
+ << QString("-153")
+ << QString(useKeys ? "-15" : "")
+ << bool(useKeys)
+ << bool(useKeys ? true : false);
+ QTest::newRow(QString(inputMode + "range [3,7] int '2'").toLatin1())
+ << 3
+ << 7
+ << QString("2")
+ << QString("2")
+ << bool(useKeys)
+ << bool(false);
+
+ QTest::newRow(QString(inputMode + "range [3,7] int '8'").toLatin1())
+ << 3
+ << 7
+ << QString("8")
+ << QString("")
+ << bool(useKeys)
+ << bool(false);
+ }
+}
+
+void tst_QLineEdit::setValidator_QIntValidator()
+{
+ QFETCH(int, mini);
+ QFETCH(int, maxi);
+ QFETCH(QString, input);
+ QFETCH(QString, expectedText);
+ QFETCH(bool, useKeys);
+ QFETCH(bool, is_valid);
+
+ QIntValidator intValidator(mini, maxi, 0);
+ testWidget->setValidator(&intValidator);
+ QVERIFY(testWidget->text().isEmpty());
+//qDebug("1 input: '" + input + "' Exp: '" + expectedText + "'");
+
+ // tests valid input
+ if (!useKeys) {
+ testWidget->insert(input);
+ } else {
+ QTest::keyClicks(testWidget, input);
+ return_count = 0;
+ QTest::keyClick(testWidget, Qt::Key_Return);
+ QCOMPARE(return_count, int(is_valid)); // assuming that is_valid = true equals 1
+ }
+//qDebug("2 input: '" + input + "' Exp: '" + expectedText + "'");
+// QCOMPARE(testWidget->displayText(), expectedText);
+ QCOMPARE(testWidget->text(), expectedText);
+}
+
+#define NO_PIXMAP_TESTS
+
+void tst_QLineEdit::frame_data()
+{
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTest::addColumn<QPixmap>("noFrame");
+ QTest::addColumn<QPixmap>("useFrame");
+
+ QTest::newRow("win");
+//#else
+// QTest::newRow("x11");
+#endif
+#endif
+}
+
+void tst_QLineEdit::frame()
+{
+ testWidget->setFrame(false);
+ // verify that the editor is shown without a frame
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTEST(testWidget, "noFrame");
+#endif
+#endif
+ QVERIFY(!testWidget->hasFrame());
+
+ testWidget->setFrame(true);
+ // verify that the editor is shown with a frame
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTEST(testWidget, "useFrame");
+#endif
+#endif
+ QVERIFY(testWidget->hasFrame());
+}
+
+void tst_QLineEdit::setAlignment_data()
+{
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTest::addColumn<QPixmap>("left");
+ QTest::addColumn<QPixmap>("right");
+ QTest::addColumn<QPixmap>("hcenter");
+ QTest::addColumn<QPixmap>("auto");
+
+ QTest::newRow("win");
+//#else
+// QTest::newRow("x11");
+#endif
+#endif
+}
+
+void tst_QLineEdit::setAlignment()
+{
+ testWidget->setText("left");
+ testWidget->setAlignment(Qt::AlignLeft);
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTEST(testWidget, "left");
+#endif
+#endif
+ QVERIFY(testWidget->alignment() == Qt::AlignLeft);
+
+ testWidget->setText("hcenter");
+ testWidget->setAlignment(Qt::AlignHCenter);
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTEST(testWidget, "hcenter");
+#endif
+#endif
+ QVERIFY(testWidget->alignment() == Qt::AlignHCenter);
+
+ testWidget->setText("right");
+ testWidget->setAlignment(Qt::AlignRight);
+#ifndef NO_PIXMAP_TESTS
+#if defined Q_WS_WIN
+ QTEST(testWidget, "right");
+#endif
+#endif
+ QVERIFY(testWidget->alignment() == Qt::AlignRight);
+
+ testWidget->setAlignment(Qt::AlignTop);
+ QVERIFY(testWidget->alignment() == Qt::AlignTop);
+
+ testWidget->setAlignment(Qt::AlignBottom);
+ QVERIFY(testWidget->alignment() == Qt::AlignBottom);
+
+ testWidget->setAlignment(Qt::AlignCenter);
+ QVERIFY(testWidget->alignment() == Qt::AlignCenter);
+}
+
+void tst_QLineEdit::isModified()
+{
+ QVERIFY(!testWidget->isModified());
+ testWidget->setText("bla");
+ QVERIFY(!testWidget->isModified());
+
+ psKeyClick(testWidget, Qt::Key_Home);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QVERIFY(!testWidget->isModified());
+ psKeyClick(testWidget, Qt::Key_End);
+ QVERIFY(!testWidget->isModified());
+
+ QTest::keyClicks(testWidget, "T");
+ QVERIFY(testWidget->isModified());
+ QTest::keyClicks(testWidget, "his is a string");
+ QVERIFY(testWidget->isModified());
+
+ testWidget->setText("");
+ QVERIFY(!testWidget->isModified());
+ testWidget->setText("foo");
+ QVERIFY(!testWidget->isModified());
+}
+
+/*
+ Obsolete function but as long as we provide it, it needs to work.
+*/
+
+void tst_QLineEdit::edited()
+{
+ QVERIFY(!testWidget->isModified());
+ testWidget->setText("bla");
+ QVERIFY(!testWidget->isModified());
+
+ psKeyClick(testWidget, Qt::Key_Home);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Right);
+ QVERIFY(!testWidget->isModified());
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QVERIFY(!testWidget->isModified());
+ psKeyClick(testWidget, Qt::Key_End);
+ QVERIFY(!testWidget->isModified());
+
+ QTest::keyClicks(testWidget, "T");
+ QVERIFY(testWidget->isModified());
+ QTest::keyClicks(testWidget, "his is a string");
+ QVERIFY(testWidget->isModified());
+
+ testWidget->setModified(false);
+ QVERIFY(!testWidget->isModified());
+
+ testWidget->setModified(true);
+ QVERIFY(testWidget->isModified());
+}
+
+void tst_QLineEdit::insert()
+{
+ testWidget->insert("This");
+ testWidget->insert(" is");
+ testWidget->insert(" a");
+ testWidget->insert(" test");
+
+ QCOMPARE(testWidget->text(), QString("This is a test"));
+
+ testWidget->cursorWordBackward(false);
+ testWidget->cursorBackward(false, 1);
+ testWidget->insert(" nice");
+ QCOMPARE(testWidget->text(), QString("This is a nice test"));
+
+ testWidget->setCursorPosition(-1);
+ testWidget->insert("No Crash! ");
+ QCOMPARE(testWidget->text(), QString("No Crash! This is a nice test"));
+}
+
+void tst_QLineEdit::setSelection_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("length");
+ QTest::addColumn<int>("expectedCursor");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<bool>("expectedHasSelectedText");
+
+ QString text = "Abc defg hijklmno, p 'qrst' uvw xyz";
+ int start, length, pos;
+
+ start = 0; length = 1; pos = 1;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("A") << true;
+
+ start = 0; length = 2; pos = 2;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("Ab") << true;
+
+ start = 0; length = 4; pos = 4;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("Abc ") << true;
+
+ start = -1; length = 0; pos = text.length();
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString() << false;
+
+ start = 34; length = 1; pos = 35;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("z") << true;
+
+ start = 34; length = 2; pos = 35;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("z") << true;
+
+ start = 34; length = -1; pos = 33;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("y") << true;
+
+ start = 1; length = -2; pos = 0;
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString("A") << true;
+
+ start = -1; length = -1; pos = text.length();
+ QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
+ << text << start << length << pos << QString() << false;
+}
+
+
+void tst_QLineEdit::setSelection()
+{
+ QFETCH(QString, text);
+ QFETCH(int, start);
+ QFETCH(int, length);
+ QFETCH(int, expectedCursor);
+ QFETCH(QString, expectedText);
+ QFETCH(bool, expectedHasSelectedText);
+
+ testWidget->setText(text);
+ testWidget->setSelection(start, length);
+ QCOMPARE(testWidget->hasSelectedText(), expectedHasSelectedText);
+ QCOMPARE(testWidget->selectedText(), expectedText);
+ if (expectedCursor >= 0)
+ QCOMPARE(testWidget->cursorPosition(), expectedCursor);
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QLineEdit::cut()
+{
+#ifdef Q_WS_MAC
+ {
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ else
+ QSKIP("Autotests run from cron and pasteboard don't get along quite ATM", SkipAll);
+ }
+#endif
+ // test newlines in cut'n'paste
+ testWidget->setText("A\nB\nC\n");
+ testWidget->setSelection(0, 6);
+ testWidget->cut();
+ psKeyClick(testWidget, Qt::Key_Home);
+ testWidget->paste();
+ QCOMPARE(testWidget->text(), QString("A\nB\nC\n"));
+ // 1 2 3 4
+ // 01234567890123456789012345678901234567890
+ testWidget->setText("Abc defg hijklmno");
+
+ testWidget->setSelection(0, 3);
+ testWidget->cut();
+ QCOMPARE(testWidget->text(), QString(" defg hijklmno"));
+
+ psKeyClick(testWidget, Qt::Key_End);
+ testWidget->paste();
+ QCOMPARE(testWidget->text(), QString(" defg hijklmnoAbc"));
+
+ psKeyClick(testWidget, Qt::Key_Home);
+ testWidget->del();
+ QCOMPARE(testWidget->text(), QString("defg hijklmnoAbc"));
+
+ testWidget->setSelection(0, 4);
+ testWidget->copy();
+ psKeyClick(testWidget, Qt::Key_End);
+ testWidget->paste();
+ QCOMPARE(testWidget->text(), QString("defg hijklmnoAbcdefg"));
+
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, Qt::Key_Left);
+ QTest::keyClick(testWidget, ' ');
+ QCOMPARE(testWidget->text(), QString("defg hijklmno Abcdefg"));
+
+ testWidget->setSelection(0, 5);
+ testWidget->del();
+ QCOMPARE(testWidget->text(), QString("hijklmno Abcdefg"));
+
+ testWidget->end(false);
+ QTest::keyClick(testWidget, ' ');
+ testWidget->paste();
+ QCOMPARE(testWidget->text(), QString("hijklmno Abcdefg defg"));
+
+ testWidget->home(false);
+ testWidget->cursorWordForward(true);
+ testWidget->cut();
+ testWidget->end(false);
+ QTest::keyClick(testWidget, ' ');
+ testWidget->paste();
+ testWidget->cursorBackward(true, 1);
+ testWidget->cut();
+ QCOMPARE(testWidget->text(), QString("Abcdefg defg hijklmno"));
+}
+#endif
+
+class InputMaskValidator : public QValidator
+{
+public:
+ InputMaskValidator(QObject *parent, const char *name = 0) : QValidator(parent) { setObjectName(name); }
+ State validate(QString &text, int &pos) const
+ {
+ InputMaskValidator *that = (InputMaskValidator *)this;
+ that->validateText = text;
+ that->validatePos = pos;
+ return Acceptable;
+ }
+ QString validateText;
+ int validatePos;
+};
+
+void tst_QLineEdit::inputMaskAndValidator_data()
+{
+ QTest::addColumn<QString>("inputMask");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QString>("validateText");
+ QTest::addColumn<int>("validatePos");
+
+ QTestEventList inputKeys;
+ inputKeys.addKeyClick(Qt::Key_1);
+ inputKeys.addKeyClick(Qt::Key_2);
+
+ QTest::newRow("task28291") << "000;_" << inputKeys << "12_" << 2;
+}
+
+void tst_QLineEdit::inputMaskAndValidator()
+{
+ QFETCH(QString, inputMask);
+ QFETCH(QTestEventList, keys);
+ QFETCH(QString, validateText);
+ QFETCH(int, validatePos);
+
+ InputMaskValidator imv(testWidget);
+ testWidget->setValidator(&imv);
+
+ testWidget->setInputMask(inputMask);
+ keys.simulate(testWidget);
+
+ QCOMPARE(imv.validateText, validateText);
+ QCOMPARE(imv.validatePos, validatePos);
+}
+
+void tst_QLineEdit::maxLengthAndInputMask()
+{
+ // Really a test for #30447
+ QVERIFY(testWidget->inputMask().isNull());
+ testWidget->setMaxLength(10);
+ QVERIFY(testWidget->maxLength() == 10);
+ testWidget->setInputMask(QString::null);
+ QVERIFY(testWidget->inputMask().isNull());
+ QVERIFY(testWidget->maxLength() == 10);
+}
+
+
+class LineEdit : public QLineEdit
+{
+public:
+ LineEdit() { state = Other; }
+
+ void keyPressEvent(QKeyEvent *e)
+ {
+ QLineEdit::keyPressEvent(e);
+ if (e->key() == Qt::Key_Enter) {
+ state = e->isAccepted() ? Accepted : Ignored;
+ } else {
+ state = Other;
+ }
+
+ }
+ enum State {
+ Accepted,
+ Ignored,
+ Other
+ };
+
+ State state;
+
+ friend class tst_QLineEdit;
+};
+
+Q_DECLARE_METATYPE(LineEdit::State);
+void tst_QLineEdit::returnPressedKeyEvent()
+{
+ LineEdit lineedit;
+ lineedit.show();
+ QCOMPARE((int)lineedit.state, (int)LineEdit::Other);
+ QTest::keyClick(&lineedit, Qt::Key_Enter);
+ QCOMPARE((int)lineedit.state, (int)LineEdit::Ignored);
+ connect(&lineedit, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
+ QTest::keyClick(&lineedit, Qt::Key_Enter);
+ QCOMPARE((int)lineedit.state, (int)LineEdit::Ignored);
+ disconnect(&lineedit, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
+ QTest::keyClick(&lineedit, Qt::Key_Enter);
+ QCOMPARE((int)lineedit.state, (int)LineEdit::Ignored);
+ QTest::keyClick(&lineedit, Qt::Key_1);
+ QCOMPARE((int)lineedit.state, (int)LineEdit::Other);
+}
+
+void tst_QLineEdit::keepSelectionOnTabFocusIn()
+{
+ testWidget->setText("hello world");
+ {
+ QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
+ QApplication::sendEvent(testWidget, &e);
+ }
+ QCOMPARE(testWidget->selectedText(), QString("hello world"));
+ testWidget->setSelection(0, 5);
+ QCOMPARE(testWidget->selectedText(), QString("hello"));
+ {
+ QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
+ QApplication::sendEvent(testWidget, &e);
+ }
+ QCOMPARE(testWidget->selectedText(), QString("hello"));
+}
+
+void tst_QLineEdit::readOnlyStyleOption()
+{
+ bool wasReadOnly = testWidget->isReadOnly();
+ QStyle *oldStyle = testWidget->style();
+
+ StyleOptionTestStyle myStyle;
+ testWidget->setStyle(&myStyle);
+
+ myStyle.setReadOnly(true);
+ testWidget->setReadOnly(true);
+ testWidget->repaint();
+ qApp->processEvents();
+
+ testWidget->setReadOnly(false);
+ myStyle.setReadOnly(false);
+ testWidget->repaint();
+ qApp->processEvents();
+
+ testWidget->setReadOnly(wasReadOnly);
+ testWidget->setStyle(oldStyle);
+}
+
+void tst_QLineEdit::validateOnFocusOut()
+{
+ QSignalSpy editingFinishedSpy(testWidget, SIGNAL(editingFinished()));
+ testWidget->setValidator(new QIntValidator(100, 999, 0));
+ QTest::keyPress(testWidget, '1');
+ QTest::keyPress(testWidget, '0');
+ QCOMPARE(testWidget->text(), QString("10"));
+ testWidget->clearFocus();
+ QCOMPARE(editingFinishedSpy.count(), 0);
+
+ testWidget->setFocus();
+ testWidget->activateWindow();
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ QTest::keyPress(testWidget, '0');
+ QTRY_COMPARE(testWidget->text(), QString("100"));
+
+ testWidget->clearFocus();
+ QCOMPARE(editingFinishedSpy.count(), 1);
+}
+
+void tst_QLineEdit::editInvalidText()
+{
+ testWidget->clear();
+ testWidget->setValidator(new QIntValidator(0, 120, 0));
+ testWidget->setText("1234");
+
+ QVERIFY(!testWidget->hasAcceptableInput());
+ QTest::keyPress(testWidget, Qt::Key_Backspace);
+ QTest::keyPress(testWidget, Qt::Key_Backspace);
+ QTest::keyPress(testWidget, Qt::Key_A);
+ QTest::keyPress(testWidget, Qt::Key_B);
+ QTest::keyPress(testWidget, Qt::Key_C);
+ QTest::keyPress(testWidget, Qt::Key_1);
+ QVERIFY(testWidget->hasAcceptableInput());
+ QCOMPARE(testWidget->text(), QString("12"));
+ testWidget->cursorBackward(false);
+ testWidget->cursorBackward(true, 2);
+ QTest::keyPress(testWidget, Qt::Key_Delete);
+ QVERIFY(testWidget->hasAcceptableInput());
+ QCOMPARE(testWidget->text(), QString("2"));
+ QTest::keyPress(testWidget, Qt::Key_1);
+ QVERIFY(testWidget->hasAcceptableInput());
+ QCOMPARE(testWidget->text(), QString("12"));
+
+ testWidget->setValidator(0);
+}
+
+void tst_QLineEdit::charWithAltOrCtrlModifier()
+{
+ testWidget->clear();
+ QCOMPARE(testWidget->text(), QString(""));
+ QTest::keyPress(testWidget, Qt::Key_Plus);
+ QCOMPARE(testWidget->text(), QString("+"));
+ QTest::keyPress(testWidget, Qt::Key_Plus, Qt::ControlModifier);
+ QCOMPARE(testWidget->text(), QString("++"));
+ QTest::keyPress(testWidget, Qt::Key_Plus, Qt::AltModifier);
+ QCOMPARE(testWidget->text(), QString("+++"));
+ QTest::keyPress(testWidget, Qt::Key_Plus, Qt::AltModifier | Qt::ControlModifier);
+ QCOMPARE(testWidget->text(), QString("++++"));
+}
+
+void tst_QLineEdit::leftKeyOnSelectedText()
+{
+ testWidget->clear();
+ testWidget->setText("0123");
+ testWidget->setCursorPosition(4);
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->cursorPosition(), 3);
+ QCOMPARE(testWidget->selectedText(), QString("3"));
+ QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
+ QCOMPARE(testWidget->cursorPosition(), 2);
+ QCOMPARE(testWidget->selectedText(), QString("23"));
+ QTest::keyClick(testWidget, Qt::Key_Left);
+#ifdef Q_OS_WIN
+ QCOMPARE(testWidget->cursorPosition(), 1);
+#else
+ // X11 used to behave like window prior to 4.2. Changes caused by QKeySequence
+ // resulted in an inadvertant change in behavior
+ QCOMPARE(testWidget->cursorPosition(), 2);
+#endif
+}
+
+void tst_QLineEdit::inlineCompletion()
+{
+ testWidget->clear();
+ QStandardItemModel *model = new QStandardItemModel;
+ QStandardItem *root = model->invisibleRootItem();
+ QStandardItem *items[5];
+ for (int i = 0; i < 5; i++) {
+ items[i] = new QStandardItem(QString("item%1").arg(i));
+ if ((i+2)%2 == 0) { // disable 0,2,4
+ items[i]->setFlags(items[i]->flags() & ~Qt::ItemIsEnabled);
+ }
+ root->appendRow(items[i]);
+ }
+ QCompleter *completer = new QCompleter(model);
+ completer->setCompletionMode(QCompleter::InlineCompletion);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ testWidget->setFocus();
+ QTRY_COMPARE(qApp->activeWindow(), (QWidget*)testWidget);
+ testWidget->setCompleter(completer);
+
+ // sanity
+ QTest::keyClick(testWidget, Qt::Key_X);
+ QCOMPARE(testWidget->selectedText(), QString());
+ QCOMPARE(testWidget->text(), QString("x"));
+ QTest::keyClick(testWidget, Qt::Key_Down, Qt::ControlModifier);
+ QCOMPARE(testWidget->selectedText(), QString());
+ QCOMPARE(testWidget->text(), QString("x"));
+ QTest::keyClick(testWidget, Qt::Key_Up, Qt::ControlModifier);
+ QCOMPARE(testWidget->selectedText(), QString());
+ QCOMPARE(testWidget->text(), QString("x"));
+
+ testWidget->clear();
+ QTest::keyClick(testWidget, Qt::Key_I);
+ QCOMPARE(testWidget->selectedText(), QString("tem1"));
+
+ Qt::KeyboardModifiers keyboardModifiers = Qt::ControlModifier;
+#ifdef Q_WS_MAC
+ keyboardModifiers |= Qt::AltModifier;
+#endif
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
+ QCOMPARE(testWidget->selectedText(), QString("tem3"));
+
+ // wraps around (Default)
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
+ QCOMPARE(testWidget->selectedText(), QString("tem1"));
+
+ QTest::keyClick(testWidget, Qt::Key_Up, keyboardModifiers);
+ QCOMPARE(testWidget->selectedText(), QString("tem3"));
+
+ // should not wrap
+ completer->setWrapAround(false);
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
+ QCOMPARE(testWidget->selectedText(), QString("tem3"));
+ QTest::keyClick(testWidget, Qt::Key_Up, keyboardModifiers); // item1
+ QTest::keyClick(testWidget, Qt::Key_Up, keyboardModifiers); // item1
+ QCOMPARE(testWidget->selectedText(), QString("tem1"));
+
+ // trivia :)
+ root->appendRow(new QStandardItem("item11"));
+ root->appendRow(new QStandardItem("item12"));
+ testWidget->clear();
+ QTest::keyClick(testWidget, Qt::Key_I);
+ QCOMPARE(testWidget->selectedText(), QString("tem1"));
+ QTest::keyClick(testWidget, Qt::Key_Delete);
+ QCOMPARE(testWidget->selectedText(), QString());
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
+ QCOMPARE(testWidget->selectedText(), QString("tem1")); // neato
+ testWidget->setText("item1");
+ testWidget->setSelection(1, 2);
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
+ testWidget->end(false);
+ QCOMPARE(testWidget->text(), QString("item1")); // no effect for selection in "middle"
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers); // item1
+ QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers); // item11
+ QCOMPARE(testWidget->text(), QString("item11"));
+
+ delete model;
+ delete completer;
+}
+
+void tst_QLineEdit::noTextEditedOnClear()
+{
+ testWidget->setText("Test");
+ QSignalSpy textEditedSpy(testWidget, SIGNAL(textEdited(const QString &)));
+ testWidget->clear();
+ QCOMPARE(textEditedSpy.count(), 0);
+}
+
+void tst_QLineEdit::textMargin_data()
+{
+ QTest::addColumn<int>("left");
+ QTest::addColumn<int>("top");
+ QTest::addColumn<int>("right");
+ QTest::addColumn<int>("bottom");
+
+ QTest::addColumn<QPoint>("mousePressPos");
+ QTest::addColumn<int>("cursorPosition");
+
+ QLineEdit testWidget;
+ QFontMetrics metrics(testWidget.font());
+ const QString s = QLatin1String("MMM MMM MMM");
+
+ // Different styles generate different offsets, so
+ // calculate the width rather than hardcode it.
+ const int pixelWidthOfM = metrics.width(s, 1);
+ const int pixelWidthOfMMM_MM = metrics.width(s, 6);
+
+ QTest::newRow("default-0") << 0 << 0 << 0 << 0 << QPoint(pixelWidthOfMMM_MM, 0) << 6;
+ QTest::newRow("default-1") << 0 << 0 << 0 << 0 << QPoint(1, 1) << 0;
+ QTest::newRow("default-2") << -1 << 0 << -1 << 0 << QPoint(pixelWidthOfMMM_MM, 0) << 6;
+ QTest::newRow("default-3") << 0 << 0 << 0 << 0 << QPoint(pixelWidthOfM, 1) << 1;
+
+ QTest::newRow("hor-0") << 10 << 0 << 10 << 0 << QPoint(1, 1) << 0;
+ QTest::newRow("hor-1") << 10 << 0 << 10 << 0 << QPoint(10, 1) << 0;
+ QTest::newRow("hor-2") << 20 << 0 << 10 << 0 << QPoint(20, 1) << 0;
+
+ if (!qApp->style()->inherits("QMacStyle")) { //MacStyle doesn't support verticals margins.
+ QTest::newRow("default-2-ver") << -1 << -1 << -1 << -1 << QPoint(pixelWidthOfMMM_MM, 0) << 6;
+ QTest::newRow("ver") << 0 << 10 << 0 << 10 << QPoint(1, 1) << 0;
+ }
+}
+
+void tst_QLineEdit::textMargin()
+{
+ QFETCH(int, left);
+ QFETCH(int, top);
+ QFETCH(int, right);
+ QFETCH(int, bottom);
+ QFETCH(QPoint, mousePressPos);
+ QFETCH(int, cursorPosition);
+
+ // Put the line edit into a toplevel window to avoid
+ // resizing by the window system.
+ QWidget tlw;
+ QLineEdit testWidget(&tlw);
+ testWidget.setGeometry(100, 100, 100, 30);
+ testWidget.setText("MMM MMM MMM");
+ testWidget.setCursorPosition(6);
+
+ QSize sizeHint = testWidget.sizeHint();
+ testWidget.setTextMargins(left, top, right, bottom);
+ sizeHint.setWidth(sizeHint.width() + left + right);
+ sizeHint.setHeight(sizeHint.height() + top +bottom);
+ QCOMPARE(testWidget.sizeHint(), sizeHint);
+ testWidget.setFrame(false);
+ tlw.show();
+
+ int l;
+ int t;
+ int r;
+ int b;
+ testWidget.getTextMargins(&l, &t, &r, &b);
+ QCOMPARE(left, l);
+ QCOMPARE(top, t);
+ QCOMPARE(right, r);
+ QCOMPARE(bottom, b);
+
+ QTest::mouseClick(&testWidget, Qt::LeftButton, 0, mousePressPos);
+ QTRY_COMPARE(testWidget.cursorPosition(), cursorPosition);
+}
+
+#ifndef QT_NO_CURSOR
+void tst_QLineEdit::cursor()
+{
+ testWidget->setReadOnly(false);
+ QCOMPARE(testWidget->cursor().shape(), Qt::IBeamCursor);
+ testWidget->setReadOnly(true);
+ QCOMPARE(testWidget->cursor().shape(), Qt::ArrowCursor);
+ testWidget->setReadOnly(false);
+ QCOMPARE(testWidget->cursor().shape(), Qt::IBeamCursor);
+}
+#endif
+
+class task180999_Widget : public QWidget
+{
+public:
+ task180999_Widget(QWidget *parent = 0) : QWidget(parent)
+ {
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ lineEdit1.setText("some text 1 ...");
+ lineEdit2.setText("some text 2 ...");
+ layout->addWidget(&lineEdit1);
+ layout->addWidget(&lineEdit2);
+ }
+
+ QLineEdit lineEdit1;
+ QLineEdit lineEdit2;
+};
+
+void tst_QLineEdit::task180999_focus()
+{
+ task180999_Widget widget;
+
+ widget.lineEdit1.setFocus();
+ widget.show();
+
+ widget.lineEdit2.setFocus();
+ widget.lineEdit2.selectAll();
+ widget.hide();
+
+ widget.lineEdit1.setFocus();
+ widget.show();
+ QTest::qWait(200);
+ widget.activateWindow();
+
+ QTRY_VERIFY(!widget.lineEdit2.hasSelectedText());
+}
+
+void tst_QLineEdit::task174640_editingFinished()
+{
+ QWidget mw;
+ QVBoxLayout *layout = new QVBoxLayout(&mw);
+ QLineEdit *le1 = new QLineEdit(&mw);
+ QLineEdit *le2 = new QLineEdit(&mw);
+ layout->addWidget(le1);
+ layout->addWidget(le2);
+
+ mw.show();
+ QApplication::setActiveWindow(&mw);
+ mw.activateWindow();
+ QTest::qWaitForWindowShown(&mw);
+ QTRY_COMPARE(&mw, QApplication::activeWindow());
+
+ QSignalSpy editingFinishedSpy(le1, SIGNAL(editingFinished()));
+
+ le1->setFocus();
+ QTest::qWait(20);
+ QTRY_VERIFY(le1->hasFocus());
+ QCOMPARE(editingFinishedSpy.count(), 0);
+
+ le2->setFocus();
+ QTest::qWait(20);
+ QTRY_VERIFY(le2->hasFocus());
+ QCOMPARE(editingFinishedSpy.count(), 1);
+ editingFinishedSpy.clear();
+
+ le1->setFocus();
+ QTest::qWait(20);
+ QTRY_VERIFY(le1->hasFocus());
+
+ QMenu *testMenu1 = new QMenu(le1);
+ testMenu1->addAction("foo");
+ testMenu1->addAction("bar");
+ testMenu1->show();
+ QTest::qWaitForWindowShown(testMenu1);
+ QTest::qWait(20);
+ mw.activateWindow();
+
+ delete testMenu1;
+ QCOMPARE(editingFinishedSpy.count(), 0);
+ QTRY_VERIFY(le1->hasFocus());
+
+ QMenu *testMenu2 = new QMenu(le2);
+ testMenu2->addAction("foo2");
+ testMenu2->addAction("bar2");
+ testMenu2->show();
+ QTest::qWaitForWindowShown(testMenu2);
+ QTest::qWait(20);
+ mw.activateWindow();
+ delete testMenu2;
+ QCOMPARE(editingFinishedSpy.count(), 1);
+}
+
+#ifndef QT_NO_COMPLETER
+class task198789_Widget : public QWidget
+{
+ Q_OBJECT
+public:
+ task198789_Widget(QWidget *parent = 0) : QWidget(parent)
+ {
+ QStringList wordList;
+ wordList << "alpha" << "omega" << "omicron" << "zeta";
+
+ lineEdit = new QLineEdit(this);
+ completer = new QCompleter(wordList, this);
+ lineEdit->setCompleter(completer);
+
+ connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
+ }
+
+ QLineEdit *lineEdit;
+ QCompleter *completer;
+ QString currentCompletion;
+
+private slots:
+ void textChanged(const QString &)
+ {
+ currentCompletion = completer->currentCompletion();
+ }
+};
+
+void tst_QLineEdit::task198789_currentCompletion()
+{
+ task198789_Widget widget;
+ widget.show();
+ qApp->processEvents();
+ QTest::keyPress(widget.lineEdit, 'o');
+ QTest::keyPress(widget.lineEdit, 'm');
+ QTest::keyPress(widget.lineEdit, 'i');
+ QCOMPARE(widget.currentCompletion, QLatin1String("omicron"));
+}
+
+void tst_QLineEdit::task210502_caseInsensitiveInlineCompletion()
+{
+ QString completion("ABCD");
+ QStringList completions;
+ completions << completion;
+ QLineEdit lineEdit;
+ QCompleter completer(completions);
+ completer.setCaseSensitivity(Qt::CaseInsensitive);
+ completer.setCompletionMode(QCompleter::InlineCompletion);
+ lineEdit.setCompleter(&completer);
+ lineEdit.show();
+ QTest::qWaitForWindowShown(&lineEdit);
+ QApplication::setActiveWindow(&lineEdit);
+ lineEdit.setFocus();
+ QTRY_VERIFY(lineEdit.hasFocus());
+ QTest::keyPress(&lineEdit, 'a');
+ QTest::keyPress(&lineEdit, Qt::Key_Return);
+ QCOMPARE(lineEdit.text(), completion);
+}
+
+#endif // QT_NO_COMPLETER
+
+
+void tst_QLineEdit::task229938_dontEmitChangedWhenTextIsNotChanged()
+{
+ QLineEdit lineEdit;
+ lineEdit.setMaxLength(5);
+ lineEdit.show();
+#ifdef Q_WS_X11
+ // to be safe and avoid failing setFocus with window managers
+ qt_x11_wait_for_window_manager(&lineEdit);
+#endif
+ lineEdit.setFocus();
+ QSignalSpy changedSpy(&lineEdit, SIGNAL(textChanged(QString)));
+ QTest::qWait(200);
+ QTest::keyPress(&lineEdit, 'a');
+ QTest::keyPress(&lineEdit, 'b');
+ QTest::keyPress(&lineEdit, 'c');
+ QTest::keyPress(&lineEdit, 'd');
+ QTest::keyPress(&lineEdit, 'e');
+ QTest::keyPress(&lineEdit, 'f');
+ QCOMPARE(changedSpy.count(), 5);
+}
+
+void tst_QLineEdit::task233101_cursorPosAfterInputMethod_data()
+{
+ QTest::addColumn<int>("maxLength");
+ QTest::addColumn<int>("cursorPos");
+ QTest::addColumn<int>("replacementStart");
+ QTest::addColumn<int>("replacementLength");
+ QTest::addColumn<QString>("commitString");
+
+ QTest::newRow("") << 4 << 4 << 0 << 0 << QString("");
+ QTest::newRow("") << 4 << 4 << 0 << 0 << QString("x");
+ QTest::newRow("") << 4 << 4 << 0 << 0 << QString("xxxxxxxxxxxxxxxx");
+ QTest::newRow("") << 4 << 3 << 0 << 0 << QString("");
+ QTest::newRow("") << 4 << 3 << 0 << 0 << QString("x");
+ QTest::newRow("") << 4 << 3 << 0 << 0 << QString("xxxxxxxxxxxxxxxx");
+ QTest::newRow("") << 4 << 0 << 0 << 0 << QString("");
+ QTest::newRow("") << 4 << 0 << 0 << 0 << QString("x");
+ QTest::newRow("") << 4 << 0 << 0 << 0 << QString("xxxxxxxxxxxxxxxx");
+
+ QTest::newRow("") << 4 << 4 << -4 << 4 << QString("");
+ QTest::newRow("") << 4 << 4 << -4 << 4 << QString("x");
+ QTest::newRow("") << 4 << 4 << -4 << 4 << QString("xxxxxxxxxxxxxxxx");
+ QTest::newRow("") << 4 << 3 << -3 << 4 << QString("");
+ QTest::newRow("") << 4 << 3 << -3 << 4 << QString("x");
+ QTest::newRow("") << 4 << 3 << -3 << 4 << QString("xxxxxxxxxxxxxxxx");
+ QTest::newRow("") << 4 << 0 << 0 << 4 << QString("");
+ QTest::newRow("") << 4 << 0 << 0 << 4 << QString("x");
+ QTest::newRow("") << 4 << 0 << 0 << 4 << QString("xxxxxxxxxxxxxxxx");
+
+ QTest::newRow("") << 4 << 4 << -4 << 0 << QString("");
+ QTest::newRow("") << 4 << 4 << -4 << 0 << QString("x");
+ QTest::newRow("") << 4 << 4 << -4 << 0 << QString("xxxxxxxxxxxxxxxx");
+ QTest::newRow("") << 4 << 3 << -3 << 0 << QString("");
+ QTest::newRow("") << 4 << 3 << -3 << 0 << QString("x");
+ QTest::newRow("") << 4 << 3 << -3 << 0 << QString("xxxxxxxxxxxxxxxx");
+}
+
+void tst_QLineEdit::task233101_cursorPosAfterInputMethod()
+{
+ QFETCH(int, maxLength);
+ QFETCH(int, cursorPos);
+ QFETCH(int, replacementStart);
+ QFETCH(int, replacementLength);
+ QFETCH(QString, commitString);
+
+ QLineEdit lineEdit;
+ lineEdit.setMaxLength(maxLength);
+ lineEdit.insert(QString().fill(QLatin1Char('a'), cursorPos));
+ QCOMPARE(lineEdit.cursorPosition(), cursorPos);
+
+ QInputMethodEvent event;
+ event.setCommitString(QLatin1String("x"), replacementStart, replacementLength);
+ qApp->sendEvent(&lineEdit, &event);
+ QVERIFY(lineEdit.cursorPosition() >= 0);
+ QVERIFY(lineEdit.cursorPosition() <= lineEdit.text().size());
+ QVERIFY(lineEdit.text().size() <= lineEdit.maxLength());
+}
+
+void tst_QLineEdit::task241436_passwordEchoOnEditRestoreEchoMode()
+{
+ QStyleOptionFrameV2 opt;
+ QChar fillChar = testWidget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, testWidget);
+
+ testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
+ testWidget->setFocus();
+ QApplication::setActiveWindow(testWidget);
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ QTest::keyPress(testWidget, '0');
+ QCOMPARE(testWidget->displayText(), QString("0"));
+ testWidget->setEchoMode(QLineEdit::Normal);
+ testWidget->clearFocus();
+ QCOMPARE(testWidget->displayText(), QString("0"));
+
+ testWidget->activateWindow();
+ testWidget->setFocus();
+ testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
+ QTest::keyPress(testWidget, '0');
+ QCOMPARE(testWidget->displayText(), QString("0"));
+ testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
+ QCOMPARE(testWidget->displayText(), QString("0"));
+ testWidget->clearFocus();
+ QCOMPARE(testWidget->displayText(), QString(fillChar));
+
+ // restore clean state
+ testWidget->setEchoMode(QLineEdit::Normal);
+}
+
+void tst_QLineEdit::task248948_redoRemovedSelection()
+{
+ testWidget->setText("a");
+ testWidget->selectAll();
+ QTest::keyPress(testWidget, Qt::Key_Delete);
+ testWidget->undo();
+ testWidget->redo();
+ QTest::keyPress(testWidget, 'a');
+ QTest::keyPress(testWidget, 'b');
+ QCOMPARE(testWidget->text(), QLatin1String("ab"));
+}
+
+void tst_QLineEdit::taskQTBUG_4401_enterKeyClearsPassword()
+{
+ QString password("Wanna guess?");
+
+ testWidget->setText(password);
+ testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
+ testWidget->setFocus();
+ testWidget->selectAll();
+ QApplication::setActiveWindow(testWidget);
+ QTRY_VERIFY(testWidget->hasFocus());
+
+ QTest::keyPress(testWidget, Qt::Key_Enter);
+ QTRY_COMPARE(testWidget->text(), password);
+}
+
+void tst_QLineEdit::taskQTBUG_4679_moveToStartEndOfBlock()
+{
+#ifdef Q_OS_MAC
+ const QString text("there are no blocks for lineEdit");
+ testWidget->setText(text);
+ testWidget->setCursorPosition(5);
+ QCOMPARE(testWidget->cursorPosition(), 5);
+ testWidget->setFocus();
+ QTest::keyPress(testWidget, Qt::Key_A, Qt::MetaModifier);
+ QCOMPARE(testWidget->cursorPosition(), 0);
+ QTest::keyPress(testWidget, Qt::Key_E, Qt::MetaModifier);
+ QCOMPARE(testWidget->cursorPosition(), text.size());
+#endif // Q_OS_MAC
+}
+
+void tst_QLineEdit::taskQTBUG_4679_selectToStartEndOfBlock()
+{
+#ifdef Q_OS_MAC
+ const QString text("there are no blocks for lineEdit, select all");
+ testWidget->setText(text);
+ testWidget->setCursorPosition(5);
+ QCOMPARE(testWidget->cursorPosition(), 5);
+ testWidget->setFocus();
+ QTest::keyPress(testWidget, Qt::Key_A, Qt::MetaModifier | Qt::ShiftModifier);
+ QCOMPARE(testWidget->cursorPosition(), 0);
+ QVERIFY(testWidget->hasSelectedText());
+ QCOMPARE(testWidget->selectedText(), text.mid(0, 5));
+
+ QTest::keyPress(testWidget, Qt::Key_E, Qt::MetaModifier | Qt::ShiftModifier);
+ QCOMPARE(testWidget->cursorPosition(), text.size());
+ QVERIFY(testWidget->hasSelectedText());
+ QCOMPARE(testWidget->selectedText(), text.mid(5));
+#endif // Q_OS_MAC
+}
+
+#ifndef QT_NO_CONTEXTMENU
+void tst_QLineEdit::taskQTBUG_7902_contextMenuCrash()
+{
+ // Would pass before the associated commit, but left as a guard.
+ QLineEdit *w = new QLineEdit;
+ w->show();
+ QTest::qWaitForWindowShown(w);
+
+ QTimer ti;
+ w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
+ ti.start(200);
+
+ QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
+ qApp->postEvent(w, cme);
+
+ QTest::qWait(300);
+ // No crash, it's allright.
+}
+#endif
+
+void tst_QLineEdit::taskQTBUG_7395_readOnlyShortcut()
+{
+ //ReadOnly QLineEdit should not intercept shortcut.
+ QLineEdit le;
+ le.setReadOnly(true);
+
+ QAction action(QString::fromLatin1("hello"), &le);
+ action.setShortcut(QString::fromLatin1("p"));
+ QSignalSpy spy(&action, SIGNAL(triggered()));
+ le.addAction(&action);
+
+ le.show();
+ QTest::qWaitForWindowShown(&le);
+ QApplication::setActiveWindow(&le);
+ le.setFocus();
+ QTRY_VERIFY(le.hasFocus());
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_P);
+ QCOMPARE(spy.count(), 1);
+}
+
+#ifdef Q_WS_X11
+void tst_QLineEdit::QTBUG697_paletteCurrentColorGroup()
+{
+ QLineEdit le;
+ le.setText(" ");
+ QPalette p = le.palette();
+ p.setBrush(QPalette::Active, QPalette::Highlight, Qt::green);
+ p.setBrush(QPalette::Inactive, QPalette::Highlight, Qt::red);
+ le.setPalette(p);
+
+ le.show();
+ QApplication::setActiveWindow(&le);
+ QTest::qWaitForWindowShown(&le);
+ le.setFocus();
+ QTRY_VERIFY(le.hasFocus());
+ le.selectAll();
+
+ QImage img(le.size(),QImage::Format_ARGB32 );
+ le.render(&img);
+ QCOMPARE(img.pixel(10, le.height()/2), QColor(Qt::green).rgb());
+ QApplication::setActiveWindow(0);
+ le.render(&img);
+ QCOMPARE(img.pixel(10, le.height()/2), QColor(Qt::red).rgb());
+}
+#endif
+
+void tst_QLineEdit::QTBUG13520_textNotVisible()
+{
+ LineEdit le;
+ le.setAlignment( Qt::AlignRight | Qt::AlignVCenter);
+ le.show();
+ QTest::qWaitForWindowShown(&le);
+ le.setText("01-ST16-01SIL-MPL001wfgsdfgsdgsdfgsdfgsdfgsdfgsdfg");
+ le.setCursorPosition(0);
+ QTest::qWait(100); //just make sure we get he lineedit correcly painted
+
+ QVERIFY(le.cursorRect().center().x() < le.width() / 2);
+
+
+}
+
+
+void tst_QLineEdit::bidiVisualMovement_data()
+{
+ QTest::addColumn<QString>("logical");
+ QTest::addColumn<int>("basicDir");
+ QTest::addColumn<IntList>("positionList");
+
+ QTest::newRow("Latin text")
+ << QString::fromUtf8("abc")
+ << (int) QChar::DirL
+ << (IntList() << 0 << 1 << 2 << 3);
+ QTest::newRow("Hebrew text, one item")
+ << QString::fromUtf8("\327\220\327\221\327\222")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 3);
+ QTest::newRow("Hebrew text after Latin text")
+ << QString::fromUtf8("abc\327\220\327\221\327\222")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 6 << 5 << 4 << 3);
+ QTest::newRow("Latin text after Hebrew text")
+ << QString::fromUtf8("\327\220\327\221\327\222abc")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 6 << 5 << 4 << 3);
+ QTest::newRow("LTR, 3 items")
+ << QString::fromUtf8("abc\327\220\327\221\327\222abc")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 9);
+ QTest::newRow("RTL, 3 items")
+ << QString::fromUtf8("\327\220\327\221\327\222abc\327\220\327\221\327\222")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 9);
+ QTest::newRow("LTR, 4 items")
+ << QString::fromUtf8("abc\327\220\327\221\327\222abc\327\220\327\221\327\222")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 12 << 11 << 10 << 9);
+ QTest::newRow("RTL, 4 items")
+ << QString::fromUtf8("\327\220\327\221\327\222abc\327\220\327\221\327\222abc")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 12 << 11 << 10 << 9);
+}
+
+void tst_QLineEdit::bidiVisualMovement()
+{
+ QFETCH(QString, logical);
+ QFETCH(int, basicDir);
+ QFETCH(IntList, positionList);
+
+ QLineEdit le;
+ le.setText(logical);
+
+ le.setCursorMoveStyle(Qt::VisualMoveStyle);
+ le.setCursorPosition(0);
+
+ bool moved;
+ int i = 0, oldPos, newPos = 0;
+
+ do {
+ oldPos = newPos;
+ QVERIFY(oldPos == positionList[i]);
+ if (basicDir == QChar::DirL) {
+ QTest::keyClick(&le, Qt::Key_Right);
+ } else
+ QTest::keyClick(&le, Qt::Key_Left);
+ newPos = le.cursorPosition();
+ moved = (oldPos != newPos);
+ i++;
+ } while (moved);
+
+ QVERIFY(i == positionList.size());
+
+ do {
+ i--;
+ oldPos = newPos;
+ QVERIFY(oldPos == positionList[i]);
+ if (basicDir == QChar::DirL) {
+ QTest::keyClick(&le, Qt::Key_Left);
+ } else
+ {
+ QTest::keyClick(&le, Qt::Key_Right);
+ }
+ newPos = le.cursorPosition();
+ moved = (oldPos != newPos);
+ } while (moved && i >= 0);
+}
+
+void tst_QLineEdit::bidiLogicalMovement_data()
+{
+ bidiVisualMovement_data();
+}
+
+void tst_QLineEdit::bidiLogicalMovement()
+{
+ QFETCH(QString, logical);
+ QFETCH(int, basicDir);
+
+ QLineEdit le;
+ le.setText(logical);
+
+ le.setCursorMoveStyle(Qt::LogicalMoveStyle);
+ le.setCursorPosition(0);
+
+ bool moved;
+ int i = 0, oldPos, newPos = 0;
+
+ do {
+ oldPos = newPos;
+ QVERIFY(oldPos == i);
+ if (basicDir == QChar::DirL) {
+ QTest::keyClick(&le, Qt::Key_Right);
+ } else
+ QTest::keyClick(&le, Qt::Key_Left);
+ newPos = le.cursorPosition();
+ moved = (oldPos != newPos);
+ i++;
+ } while (moved);
+
+ do {
+ i--;
+ oldPos = newPos;
+ QVERIFY(oldPos == i);
+ if (basicDir == QChar::DirL) {
+ QTest::keyClick(&le, Qt::Key_Left);
+ } else
+ {
+ QTest::keyClick(&le, Qt::Key_Right);
+ }
+ newPos = le.cursorPosition();
+ moved = (oldPos != newPos);
+ } while (moved && i >= 0);
+}
+
+void tst_QLineEdit::selectAndCursorPosition()
+{
+ testWidget->setText("This is a long piece of text");
+
+ testWidget->setSelection(0, 5);
+ QCOMPARE(testWidget->cursorPosition(), 5);
+ testWidget->setSelection(5, -5);
+ QCOMPARE(testWidget->cursorPosition(), 0);
+}
+
+void tst_QLineEdit::inputMethodSelection()
+{
+ testWidget->setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ testWidget->setSelection(0,0);
+ QSignalSpy selectionSpy(testWidget, SIGNAL(selectionChanged()));
+
+ QCOMPARE(selectionSpy.count(), 0);
+ QCOMPARE(testWidget->selectionStart(), -1);
+
+ testWidget->setSelection(0,5);
+
+ QCOMPARE(selectionSpy.count(), 1);
+ QCOMPARE(testWidget->selectionStart(), 0);
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 12, 5, QVariant());
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(testWidget, &event);
+
+ QCOMPARE(selectionSpy.count(), 2);
+ QCOMPARE(testWidget->selectionStart(), 12);
+}
+
+QTEST_MAIN(tst_QLineEdit)
+#include "tst_qlineedit.moc"
diff --git a/tests/auto/widgets/widgets/qmainwindow/.gitignore b/tests/auto/widgets/widgets/qmainwindow/.gitignore
new file mode 100644
index 0000000000..7550c7063f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmainwindow/.gitignore
@@ -0,0 +1 @@
+tst_qmainwindow
diff --git a/tests/auto/widgets/widgets/qmainwindow/qmainwindow.pro b/tests/auto/widgets/widgets/qmainwindow/qmainwindow.pro
new file mode 100644
index 0000000000..c140f76c89
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmainwindow/qmainwindow.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets widgets-private
+SOURCES += tst_qmainwindow.cpp
diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
new file mode 100644
index 0000000000..9722a3194b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
@@ -0,0 +1,1742 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qdockwidget.h>
+#include <qlayout.h>
+#include <qmainwindow.h>
+#include <qmenubar.h>
+#include <qstatusbar.h>
+#include <qstyle.h>
+#include <qtoolbar.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qtextedit.h>
+#include <private/qmainwindowlayout_p.h>
+#include <private/qdockarealayout_p.h>
+#include "../../../platformquirks.h"
+
+//TESTED_FILES=
+
+static uchar restoreData41[] = { 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x1, 0x19, 0xfc, 0x2, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x30, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x34, 0x1, 0x0, 0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x38, 0x1, 0x0, 0x0, 0x0, 0x8d, 0x0, 0x0, 0x0, 0x43, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x32, 0x1, 0x0, 0x0, 0x0, 0xd4, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x1, 0x19, 0xfc, 0x2, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x35, 0x1, 0x0, 0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x39, 0x1, 0x0, 0x0, 0x0, 0x8d, 0x0, 0x0, 0x0, 0x43, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x33, 0x1, 0x0, 0x0, 0x0, 0xd4, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x1, 0x89, 0x0, 0x0, 0x0, 0xe, 0xfc, 0x1, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x32, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x36, 0x1, 0x0, 0x0, 0x0, 0x63, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x30, 0x1, 0x0, 0x0, 0x0, 0xc8, 0x0, 0x0, 0x0, 0x5e, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x34, 0x1, 0x0, 0x0, 0x1, 0x2a, 0x0, 0x0, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x89, 0x0, 0x0, 0x0, 0xe, 0xfc, 0x1, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x33, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x37, 0x1, 0x0, 0x0, 0x0, 0x63, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x31, 0x1, 0x0, 0x0, 0x0, 0xc8, 0x0, 0x0, 0x0, 0x5e, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x35, 0x1, 0x0, 0x0, 0x1, 0x2a, 0x0, 0x0, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x0, 0x1, 0x19};
+static uchar restoreData42[] = { 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x0, 0x0, 0x2, 0x2b, 0xfc, 0x2, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x30, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x34, 0x1, 0x0, 0x0, 0x0, 0xb6, 0x0, 0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x38, 0x1, 0x0, 0x0, 0x1, 0x42, 0x0, 0x0, 0x0, 0x87, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x32, 0x1, 0x0, 0x0, 0x1, 0xcd, 0x0, 0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x2, 0x2b, 0xfc, 0x2, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x35, 0x1, 0x0, 0x0, 0x0, 0xb6, 0x0, 0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x39, 0x1, 0x0, 0x0, 0x1, 0x42, 0x0, 0x0, 0x0, 0x87, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x33, 0x1, 0x0, 0x0, 0x1, 0xcd, 0x0, 0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x21, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x4, 0x4e, 0x0, 0x0, 0x0, 0x26, 0xfc, 0x1, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x32, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x12, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x36, 0x1, 0x0, 0x0, 0x1, 0x16, 0x0, 0x0, 0x1, 0xe, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x30, 0x1, 0x0, 0x0, 0x2, 0x28, 0x0, 0x0, 0x1, 0x14, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x34, 0x1, 0x0, 0x0, 0x3, 0x40, 0x0, 0x0, 0x1, 0xe, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x4, 0x4e, 0x0, 0x0, 0x0, 0x26, 0xfc, 0x1, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x33, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x12, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x37, 0x1, 0x0, 0x0, 0x1, 0x16, 0x0, 0x0, 0x1, 0xe, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x31, 0x1, 0x0, 0x0, 0x2, 0x28, 0x0, 0x0, 0x1, 0x14, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x35, 0x1, 0x0, 0x0, 0x3, 0x40, 0x0, 0x0, 0x1, 0xe, 0x0, 0x0, 0x0, 0xa, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x3, 0x8a, 0x0, 0x0, 0x2, 0x2b, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8};
+static uchar restoreData43[] = { 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0xa0, 0xfc, 0x2, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x30, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x34, 0x1, 0x0, 0x0, 0x0, 0x53, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x38, 0x1, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x32, 0x1, 0x0, 0x0, 0x0, 0xa5, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0xa0, 0xfc, 0x2, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x35, 0x1, 0x0, 0x0, 0x0, 0x53, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x39, 0x1, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x33, 0x1, 0x0, 0x0, 0x0, 0xa5, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x1, 0xa8, 0x0, 0x0, 0x0, 0x26, 0xfc, 0x1, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x32, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x36, 0x1, 0x0, 0x0, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x66, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x30, 0x1, 0x0, 0x0, 0x0, 0xd6, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x34, 0x1, 0x0, 0x0, 0x1, 0x42, 0x0, 0x0, 0x0, 0x66, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0xa8, 0x0, 0x0, 0x0, 0x26, 0xfc, 0x1, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x33, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xc, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x37, 0x1, 0x0, 0x0, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x66, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x31, 0x1, 0x0, 0x0, 0x0, 0xd6, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0xe, 0x0, 0x64, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0, 0x20, 0x0, 0x31, 0x0, 0x35, 0x1, 0x0, 0x0, 0x1, 0x42, 0x0, 0x0, 0x0, 0x66, 0x0, 0x0, 0x0, 0x50, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xb8, 0x0, 0x0, 0x0, 0xa0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0xfc, 0x0, 0x0, 0x0, 0x0};
+
+class tst_QMainWindow : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QMainWindow();
+
+private slots:
+ void getSetCheck();
+ void constructor();
+ void iconSize();
+ void toolButtonStyle();
+#ifndef Q_WS_WINCE_WM
+ void menuBar();
+#endif
+ void statusBar();
+ void centralWidget();
+ void corner();
+ void addToolBarBreak();
+ void insertToolBarBreak();
+ void addToolBar();
+ void insertToolBar();
+ void removeToolBar();
+ void toolBarArea();
+ void addDockWidget();
+ void splitDockWidget();
+ void removeDockWidget();
+ void dockWidgetArea();
+ void restoreState();
+ void restoreStateFromPreviousVersion();
+ void createPopupMenu();
+ void hideBeforeLayout();
+ void saveRestore();
+ void saveRestore_data();
+ void isSeparator();
+#ifndef QT_NO_CURSOR
+ void setCursor();
+#endif
+ void addToolbarAfterShow();
+ void centralWidgetSize();
+ void dockWidgetSize();
+ void QTBUG2774_stylechange();
+#ifdef Q_OS_MAC
+ void toggleUnifiedTitleAndToolBarOnMac();
+#endif
+};
+
+// Testing get/set functions
+void tst_QMainWindow::getSetCheck()
+{
+ QMainWindow obj1;
+ // QMenuBar * QMainWindow::menuBar()
+ // void QMainWindow::setMenuBar(QMenuBar *)
+ QPointer<QMenuBar> var1 = new QMenuBar;
+ obj1.setMenuBar(var1);
+ QCOMPARE(static_cast<QMenuBar *>(var1), obj1.menuBar());
+ obj1.setMenuBar((QMenuBar *)0);
+ QVERIFY(obj1.menuBar());
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!var1);
+ // delete var1; // No delete, since QMainWindow takes ownership
+
+ // QStatusBar * QMainWindow::statusBar()
+ // void QMainWindow::setStatusBar(QStatusBar *)
+ QPointer<QStatusBar> var2 = new QStatusBar;
+ obj1.setStatusBar(var2);
+ QCOMPARE(static_cast<QStatusBar *>(var2), obj1.statusBar());
+ obj1.setStatusBar((QStatusBar *)0);
+ QVERIFY(obj1.statusBar());
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!var2);
+ // delete var2; // No delete, since QMainWindow takes ownership
+
+ // QWidget * QMainWindow::centralWidget()
+ // void QMainWindow::setCentralWidget(QWidget *)
+ QWidget *var3 = new QWidget;
+ obj1.setCentralWidget(var3);
+ QCOMPARE(var3, obj1.centralWidget());
+ obj1.setCentralWidget((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.centralWidget());
+ // delete var3; // No delete, since QMainWindow takes ownership
+}
+
+tst_QMainWindow::tst_QMainWindow()
+{
+ qRegisterMetaType<QSize>("QSize");
+ qRegisterMetaType<Qt::ToolButtonStyle>("Qt::ToolButtonStyle");
+}
+
+void tst_QMainWindow::constructor()
+{
+ QMainWindow mw;
+ QVERIFY(mw.parentWidget() == 0);
+ QVERIFY(mw.isWindow());
+
+ QMainWindow mw2(&mw);
+ QVERIFY(mw2.parentWidget() == &mw);
+ QVERIFY(mw2.isWindow());
+
+ QMainWindow mw3(&mw, Qt::FramelessWindowHint);
+ QVERIFY(mw3.parentWidget() == &mw);
+ QVERIFY(mw3.isWindow());
+}
+
+void tst_QMainWindow::iconSize()
+{
+ {
+ QMainWindow mw;
+ QSignalSpy spy(&mw, SIGNAL(iconSizeChanged(QSize)));
+
+ // the default is determined by the style
+ const int metric = mw.style()->pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QSize defaultIconSize = QSize(metric, metric);
+ const QSize smallIconSize = QSize(metric / 2, metric / 2);
+ const QSize largeIconSize = QSize(metric * 2, metric * 2);
+
+ // no-op
+ QCOMPARE(mw.iconSize(), defaultIconSize);
+ mw.setIconSize(defaultIconSize);
+ QCOMPARE(mw.iconSize(), defaultIconSize);
+ QCOMPARE(spy.size(), 0);
+
+ mw.setIconSize(largeIconSize);
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(spy.first().first().toSize(), largeIconSize);
+ spy.clear();
+
+ // no-op
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ mw.setIconSize(largeIconSize);
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ QCOMPARE(spy.size(), 0);
+
+ mw.setIconSize(smallIconSize);
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(spy.first().first().toSize(), smallIconSize);
+ spy.clear();
+
+ // no-op
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ mw.setIconSize(smallIconSize);
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ QCOMPARE(spy.size(), 0);
+
+ // setting the icon size to an invalid QSize will reset the
+ // iconSize property to the default
+ mw.setIconSize(QSize());
+ QCOMPARE(mw.iconSize(), defaultIconSize);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(spy.first().first().toSize(), defaultIconSize);
+ spy.clear();
+ }
+
+ {
+ // toolbars should follow the mainwindow's icon size
+ QMainWindow mw;
+ QToolBar tb;
+ mw.addToolBar(&tb);
+
+ QSignalSpy mwSpy(&mw, SIGNAL(iconSizeChanged(QSize)));
+ QSignalSpy tbSpy(&tb, SIGNAL(iconSizeChanged(QSize)));
+
+ // the default is determined by the style
+ const int metric = mw.style()->pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QSize defaultIconSize = QSize(metric, metric);
+ const QSize smallIconSize = QSize(metric / 2, metric / 2);
+ const QSize largeIconSize = QSize(metric * 2, metric * 2);
+
+ // no-op
+ QCOMPARE(mw.iconSize(), defaultIconSize);
+ mw.setIconSize(defaultIconSize);
+ QCOMPARE(mw.iconSize(), defaultIconSize);
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ mw.setIconSize(largeIconSize);
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ QCOMPARE(tb.iconSize(), largeIconSize);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(mwSpy.first().first().toSize(), largeIconSize);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(tbSpy.first().first().toSize(), largeIconSize);
+ mwSpy.clear();
+ tbSpy.clear();
+
+ // no-op
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ mw.setIconSize(largeIconSize);
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ QCOMPARE(tb.iconSize(), largeIconSize);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ mw.setIconSize(smallIconSize);
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(mwSpy.first().first().toSize(), smallIconSize);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(tbSpy.first().first().toSize(), smallIconSize);
+ mwSpy.clear();
+ tbSpy.clear();
+
+ // no-op
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ mw.setIconSize(smallIconSize);
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ // setting the icon size to an invalid QSize will reset the
+ // iconSize property to the default
+ mw.setIconSize(QSize());
+ QCOMPARE(mw.iconSize(), defaultIconSize);
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(mwSpy.first().first().toSize(), defaultIconSize);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(tbSpy.first().first().toSize(), defaultIconSize);
+ mwSpy.clear();
+ tbSpy.clear();
+ }
+
+ {
+ QMainWindow mw;
+ QSignalSpy mwSpy(&mw, SIGNAL(iconSizeChanged(QSize)));
+
+ // the default is determined by the style
+ const int metric = mw.style()->pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QSize defaultIconSize = QSize(metric, metric);
+ const QSize smallIconSize = QSize(metric / 2, metric / 2);
+ const QSize largeIconSize = QSize(metric * 2, metric * 2);
+
+ mw.setIconSize(smallIconSize);
+ QCOMPARE(mw.iconSize(), smallIconSize);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(mwSpy.first().first().toSize(), smallIconSize);
+ mwSpy.clear();
+
+ QToolBar tb;
+ QSignalSpy tbSpy(&tb, SIGNAL(iconSizeChanged(QSize)));
+
+ mw.addToolBar(&tb);
+
+ // newly added toolbars should also automatically pick up any
+ // size set on the main window
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(tbSpy.first().first().toSize(), smallIconSize);
+ tbSpy.clear();
+
+ mw.removeToolBar(&tb);
+
+ // removed toolbars should keep their existing size and ignore
+ // mainwindow icon size changes
+ mw.setIconSize(largeIconSize);
+ QCOMPARE(mw.iconSize(), largeIconSize);
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(mwSpy.first().first().toSize(), largeIconSize);
+ QCOMPARE(tbSpy.size(), 0);
+ mwSpy.clear();
+ }
+}
+
+void tst_QMainWindow::toolButtonStyle()
+{
+ {
+ QMainWindow mw;
+
+ QSignalSpy spy(&mw, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+
+ // no-op
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(spy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(spy.first().first().constData()),
+ Qt::ToolButtonTextOnly);
+ spy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonTextOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(spy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(spy.first().first().constData()),
+ Qt::ToolButtonTextBesideIcon);
+ spy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(spy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(spy.first().first().constData()),
+ Qt::ToolButtonTextUnderIcon);
+ spy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(spy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(spy.first().first().constData()),
+ Qt::ToolButtonIconOnly);
+ spy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(spy.size(), 0);
+ }
+
+ {
+ // toolbars should follow the mainwindow's tool button style
+ QMainWindow mw;
+ QToolBar tb;
+ mw.addToolBar(&tb);
+
+ QSignalSpy mwSpy(&mw, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+ QSignalSpy tbSpy(&tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+
+ // no-op
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(mwSpy.first().first().constData()),
+ Qt::ToolButtonTextOnly);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(tbSpy.first().first().constData()),
+ Qt::ToolButtonTextOnly);
+ mwSpy.clear();
+ tbSpy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonTextOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(mwSpy.first().first().constData()),
+ Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(tbSpy.first().first().constData()),
+ Qt::ToolButtonTextBesideIcon);
+ mwSpy.clear();
+ tbSpy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(mwSpy.first().first().constData()),
+ Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(tbSpy.first().first().constData()),
+ Qt::ToolButtonTextUnderIcon);
+ mwSpy.clear();
+ tbSpy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(mwSpy.first().first().constData()),
+ Qt::ToolButtonIconOnly);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(tbSpy.first().first().constData()),
+ Qt::ToolButtonIconOnly);
+ mwSpy.clear();
+ tbSpy.clear();
+
+ // no-op
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(mwSpy.size(), 0);
+ QCOMPARE(tbSpy.size(), 0);
+ }
+
+ {
+ QMainWindow mw;
+ QSignalSpy mwSpy(&mw, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(mwSpy.first().first().constData()),
+ Qt::ToolButtonTextBesideIcon);
+ mwSpy.clear();
+
+ QToolBar tb;
+ QSignalSpy tbSpy(&tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+
+ mw.addToolBar(&tb);
+
+ // newly added toolbars should also automatically pick up any
+ // size set on the main window
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(tbSpy.first().first().constData()),
+ Qt::ToolButtonTextBesideIcon);
+ tbSpy.clear();
+
+ mw.removeToolBar(&tb);
+
+ // removed toolbars should keep their existing size and ignore
+ // mainwindow icon size changes
+ mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(mw.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(mwSpy.size(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolButtonStyle *>(mwSpy.first().first().constData()),
+ Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(tbSpy.size(), 0);
+ mwSpy.clear();
+ }
+}
+
+// With native menubar integration on Windows Mobile the menubar is not a child
+#ifndef Q_WS_WINCE_WM
+void tst_QMainWindow::menuBar()
+{
+ {
+ QMainWindow mw;
+ QVERIFY(mw.menuBar() != 0);
+ }
+
+ {
+ QMainWindow mw;
+ QPointer<QMenuBar> mb1 = new QMenuBar;
+ QPointer<QMenuBar> mb2 = new QMenuBar;
+
+ mw.setMenuBar(mb1);
+ QVERIFY(mw.menuBar() != 0);
+ QCOMPARE(mw.menuBar(), (QMenuBar *)mb1);
+ QCOMPARE(mb1->parentWidget(), (QWidget *)&mw);
+
+ mw.setMenuBar(0);
+ QVERIFY(mw.menuBar() != 0);
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(mb1 == 0);
+
+ mw.setMenuBar(mb2);
+ QVERIFY(mw.menuBar() != 0);
+ QCOMPARE(mw.menuBar(), (QMenuBar *)mb2);
+ QCOMPARE(mb2->parentWidget(), (QWidget *)&mw);
+
+ mw.setMenuBar(0);
+ QVERIFY(mw.menuBar() != 0);
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(mb2 == 0);
+
+ mb1 = new QMenuBar;
+ mw.setMenuBar(mb1);
+ QVERIFY(mw.menuBar() != 0);
+ QCOMPARE(mw.menuBar(), (QMenuBar *)mb1);
+
+ mb2 = new QMenuBar;
+ mw.setMenuBar(mb2);
+ QVERIFY(mw.menuBar() != 0);
+ QCOMPARE(mw.menuBar(), (QMenuBar *)mb2);
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(mb1 == 0);
+
+ mb1 = new QMenuBar;
+ mw.setMenuBar(mb1);
+ QVERIFY(mw.menuBar() != 0);
+ QCOMPARE(mw.menuBar(), (QMenuBar *)mb1);
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(mb2 == 0);
+
+ QPointer<QWidget> topLeftCornerWidget = new QWidget;
+ mb1->setCornerWidget(topLeftCornerWidget, Qt::TopLeftCorner);
+ QPointer<QWidget> topRightCornerWidget = new QWidget;
+ mb1->setCornerWidget(topRightCornerWidget, Qt::TopRightCorner);
+
+ mb2 = new QMenuBar;
+ mw.setMenuBar(mb2);
+ QVERIFY(mw.menuBar() != 0);
+ QCOMPARE(mw.menuBar(), (QMenuBar *)mb2);
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(mb1 == 0);
+
+ QVERIFY(topLeftCornerWidget);
+ QCOMPARE(mb2->cornerWidget(Qt::TopLeftCorner), static_cast<QWidget *>(topLeftCornerWidget));
+ QVERIFY(topRightCornerWidget);
+ QCOMPARE(mb2->cornerWidget(Qt::TopRightCorner), static_cast<QWidget *>(topRightCornerWidget));
+
+ mw.setMenuBar(0);
+ QVERIFY(mw.menuBar() != 0);
+ //we now call deleteLater on the previous menubar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(mb2 == 0);
+
+ QVERIFY(!topLeftCornerWidget);
+ QVERIFY(!topRightCornerWidget);
+ }
+}
+#endif
+
+void tst_QMainWindow::statusBar()
+{
+ {
+ QMainWindow mw;
+ QVERIFY(mw.statusBar() != 0);
+ }
+
+ {
+ QMainWindow mw;
+ QPointer<QStatusBar> sb1 = new QStatusBar;
+ QPointer<QStatusBar> sb2 = new QStatusBar;
+
+ mw.setStatusBar(sb1);
+ QVERIFY(mw.statusBar() != 0);
+ QCOMPARE(mw.statusBar(), (QStatusBar *)sb1);
+ QCOMPARE(sb1->parentWidget(), (QWidget *)&mw);
+
+ mw.setStatusBar(0);
+ QVERIFY(mw.statusBar() != 0);
+ //we now call deleteLater on the previous statusbar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(sb1 == 0);
+
+ mw.setStatusBar(sb2);
+ QVERIFY(mw.statusBar() != 0);
+ QCOMPARE(mw.statusBar(), (QStatusBar *)sb2);
+ QCOMPARE(sb2->parentWidget(), (QWidget *)&mw);
+
+ mw.setStatusBar(0);
+ QVERIFY(mw.statusBar() != 0);
+ //we now call deleteLater on the previous statusbar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(sb2 == 0);
+
+ sb1 = new QStatusBar;
+ mw.setStatusBar(sb1);
+ QVERIFY(mw.statusBar() != 0);
+ QCOMPARE(mw.statusBar(), (QStatusBar *)sb1);
+ QCOMPARE(sb1->parentWidget(), (QWidget *)&mw);
+
+ sb2 = new QStatusBar;
+ mw.setStatusBar(sb2);
+ QVERIFY(mw.statusBar() != 0);
+ QCOMPARE(mw.statusBar(), (QStatusBar *)sb2);
+ QCOMPARE(sb2->parentWidget(), (QWidget *)&mw);
+ //we now call deleteLater on the previous statusbar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(sb1 == 0);
+
+ sb1 = new QStatusBar;
+ mw.setStatusBar(sb1);
+ QVERIFY(mw.statusBar() != 0);
+ QCOMPARE(mw.statusBar(), (QStatusBar *)sb1);
+ QCOMPARE(sb1->parentWidget(), (QWidget *)&mw);
+ //we now call deleteLater on the previous statusbar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(sb2 == 0);
+
+ sb2 = new QStatusBar;
+ mw.setStatusBar(sb2);
+ QVERIFY(mw.statusBar() != 0);
+ QCOMPARE(mw.statusBar(), (QStatusBar *)sb2);
+ QCOMPARE(sb2->parentWidget(), (QWidget *)&mw);
+ //we now call deleteLater on the previous statusbar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(sb1 == 0);
+ }
+
+ {
+ // deleting the status bar should remove it from the main window
+ QMainWindow mw;
+ QStatusBar *sb = mw.statusBar();
+ QMainWindowLayout *l = qFindChild<QMainWindowLayout *>(&mw);
+ QVERIFY(l);
+ int indexOfSb = l->indexOf(sb);
+ QVERIFY(indexOfSb != -1);
+ delete sb;
+ indexOfSb = l->indexOf(sb);
+ QVERIFY(indexOfSb == -1);
+ }
+}
+
+void tst_QMainWindow::centralWidget()
+{
+ {
+ QMainWindow mw;
+ QVERIFY(mw.centralWidget() == 0);
+ }
+
+ {
+ QMainWindow mw;
+ QPointer<QWidget> w1 = new QWidget;
+ QPointer<QWidget> w2 = new QWidget;
+
+ QVERIFY(mw.centralWidget() == 0);
+
+ mw.setCentralWidget(w1);
+ QVERIFY(mw.centralWidget() != 0);
+ QCOMPARE(mw.centralWidget(), (QWidget *)w1);
+ QCOMPARE(w1->parentWidget(), (QWidget *)&mw);
+
+ mw.setCentralWidget(w2);
+ QVERIFY(mw.centralWidget() != 0);
+ QCOMPARE(mw.centralWidget(), (QWidget *)w2);
+ QCOMPARE(w2->parentWidget(), (QWidget *)&mw);
+
+ mw.setCentralWidget(0);
+ QVERIFY(mw.centralWidget() == 0);
+
+ //we now call deleteLater on the previous central widgets
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(w1 == 0);
+ QVERIFY(w2 == 0);
+ }
+
+ {
+ // do it again, this time with the mainwindow shown, since
+ // this tends will activate the layout when setting the new
+ // central widget
+
+ QMainWindow mw;
+ mw.show();
+
+ QPointer<QWidget> w1 = new QWidget;
+ QPointer<QWidget> w2 = new QWidget;
+
+ QVERIFY(mw.centralWidget() == 0);
+
+ mw.setCentralWidget(w1);
+ QVERIFY(mw.centralWidget() != 0);
+ QCOMPARE(mw.centralWidget(), (QWidget *)w1);
+ QCOMPARE(w1->parentWidget(), (QWidget *)&mw);
+
+ mw.setCentralWidget(w2);
+ QVERIFY(mw.centralWidget() != 0);
+ QCOMPARE(mw.centralWidget(), (QWidget *)w2);
+ QCOMPARE(w2->parentWidget(), (QWidget *)&mw);
+
+ mw.setCentralWidget(0);
+ QVERIFY(mw.centralWidget() == 0);
+
+ //we now call deleteLater on the previous central widgets
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(w1 == 0);
+ QVERIFY(w2 == 0);
+ }
+}
+
+void tst_QMainWindow::corner()
+{
+ {
+ QMainWindow mw;
+
+ QCOMPARE(mw.corner(Qt::TopLeftCorner), Qt::TopDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::TopRightCorner), Qt::TopDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::BottomLeftCorner), Qt::BottomDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::BottomRightCorner), Qt::BottomDockWidgetArea);
+ }
+
+ {
+ QMainWindow mw;
+
+ mw.setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::TopLeftCorner), Qt::LeftDockWidgetArea);
+ mw.setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::TopLeftCorner), Qt::TopDockWidgetArea);
+
+ mw.setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::TopRightCorner), Qt::RightDockWidgetArea);
+ mw.setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::TopRightCorner), Qt::TopDockWidgetArea);
+
+ mw.setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::BottomLeftCorner), Qt::LeftDockWidgetArea);
+ mw.setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::BottomLeftCorner), Qt::BottomDockWidgetArea);
+
+ mw.setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::BottomRightCorner), Qt::RightDockWidgetArea);
+ mw.setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
+ QCOMPARE(mw.corner(Qt::BottomRightCorner), Qt::BottomDockWidgetArea);
+ }
+}
+
+void tst_QMainWindow::addToolBarBreak()
+{
+ {
+ QMainWindow mw;
+ QToolBar tb1(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb1);
+ mw.addToolBarBreak(Qt::TopToolBarArea);
+ QToolBar tb2(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb2);
+ mw.addToolBarBreak(Qt::TopToolBarArea);
+ QToolBar tb3(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb3);
+ mw.addToolBarBreak(Qt::TopToolBarArea);
+ QToolBar tb4(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb4);
+
+ mw.layout()->invalidate();
+ mw.layout()->activate();
+
+ QCOMPARE(tb1.x(), 0);
+ QCOMPARE(tb1.y(), 0);
+ QCOMPARE(tb2.x(), 0);
+ QVERIFY(tb1.y() != tb2.y());
+ QCOMPARE(tb3.x(), 0);
+ QVERIFY(tb2.y() != tb3.y());
+ QCOMPARE(tb4.x(), 0);
+ QVERIFY(tb3.y() != tb4.y());
+ }
+
+ {
+ QMainWindow mw;
+ // should not crash, should get a warning instead
+ QTest::ignoreMessage(QtWarningMsg, "QMainWindow::addToolBarBreak: invalid 'area' argument");
+ mw.addToolBarBreak(Qt::NoToolBarArea);
+ }
+}
+
+void tst_QMainWindow::insertToolBarBreak()
+{
+ QMainWindow mw;
+ QToolBar tb1(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb1);
+ QToolBar tb2(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb2);
+ QToolBar tb3(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb3);
+ QToolBar tb4(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb4);
+
+ mw.insertToolBarBreak(&tb2);
+ mw.insertToolBarBreak(&tb3);
+ mw.insertToolBarBreak(&tb4);
+
+ mw.layout()->invalidate();
+ mw.layout()->activate();
+
+ QCOMPARE(tb1.x(), 0);
+ QCOMPARE(tb1.y(), 0);
+ QCOMPARE(tb2.x(), 0);
+ QVERIFY(tb1.y() != tb2.y());
+ QCOMPARE(tb3.x(), 0);
+ QVERIFY(tb2.y() != tb3.y());
+ QCOMPARE(tb4.x(), 0);
+ QVERIFY(tb3.y() != tb4.y());
+
+ QVERIFY(!mw.toolBarBreak(&tb1));
+ QVERIFY(mw.toolBarBreak(&tb4));
+ mw.removeToolBarBreak(&tb4);
+ QVERIFY(!mw.toolBarBreak(&tb4));
+
+}
+
+static bool findWidgetRecursively(QLayoutItem *li, QWidget *w)
+{
+ QLayout *lay = li->layout();
+ if (!lay)
+ return false;
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = lay->itemAt(i))) {
+ if (child->widget() == w) {
+ return true;
+ } else if (findWidgetRecursively(child, w)) {
+ return true;
+ } else {
+ ++i;
+ }
+ }
+ return false;
+}
+
+void tst_QMainWindow::addToolBar()
+{
+ Qt::ToolBarArea areas[] = {
+ Qt::LeftToolBarArea,
+ Qt::RightToolBarArea,
+ Qt::TopToolBarArea,
+ Qt::BottomToolBarArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::ToolBarArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::ToolBarArea area = areas[i];
+
+ QMainWindow mw;
+ QToolBar tb(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &tb));
+ mw.addToolBar(area, &tb);
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb));
+ }
+
+ {
+ // addToolBar() with no area, equivalent to top
+ QMainWindow mw;
+ QToolBar tb(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &tb));
+ mw.addToolBar(&tb);
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb));
+ }
+
+ {
+ QMainWindow mw;
+ QToolBar tb(&mw);
+ // should not crash, should get a warning instead
+ QTest::ignoreMessage(QtWarningMsg, "QMainWindow::addToolBar: invalid 'area' argument");
+ mw.addToolBar(Qt::NoToolBarArea, &tb);
+ }
+}
+
+void tst_QMainWindow::insertToolBar()
+{
+ Qt::ToolBarArea areas[] = {
+ Qt::LeftToolBarArea,
+ Qt::RightToolBarArea,
+ Qt::TopToolBarArea,
+ Qt::BottomToolBarArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::ToolBarArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::ToolBarArea area = areas[i];
+
+ QMainWindow mw;
+ QToolBar tb1(&mw);
+ mw.addToolBar(area, &tb1);
+ QToolBar tb2(&mw);
+ mw.insertToolBar(&tb1, &tb2);
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb1));
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb2));
+ }
+
+ {
+ QMainWindow window;
+ QToolBar *bar1 = new QToolBar(QObject::tr("bar1"), &window);
+ bar1->addWidget(new QPushButton(QObject::tr("bar1")));
+ QToolBar *bar2 = new QToolBar(QLatin1String("bar2"));
+ bar2->addWidget(new QPushButton(QLatin1String("bar2")));
+ QToolBar *bar3 = new QToolBar(QLatin1String("bar3"));
+ bar3->addWidget(new QPushButton(QLatin1String("bar3")));
+
+ window.addToolBar(bar1);
+ window.addToolBar(bar3);
+ window.insertToolBar(bar1,bar2);
+ window.insertToolBar(bar1, bar3);
+
+ QVERIFY(!window.isVisible());
+ QVERIFY(!bar1->isVisible());
+ QVERIFY(!bar2->isVisible());
+ QVERIFY(!bar3->isVisible());
+
+ window.show();
+
+ QVERIFY(window.isVisible());
+ QVERIFY(bar1->isVisible());
+ QVERIFY(bar2->isVisible());
+ QVERIFY(bar3->isVisible());
+ }
+}
+
+void tst_QMainWindow::removeToolBar()
+{
+ Qt::ToolBarArea areas[] = {
+ Qt::LeftToolBarArea,
+ Qt::RightToolBarArea,
+ Qt::TopToolBarArea,
+ Qt::BottomToolBarArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::ToolBarArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::ToolBarArea area = areas[i];
+
+ QMainWindow mw;
+ QToolBar tb1(&mw);
+ mw.addToolBar(area, &tb1);
+ QToolBar tb2(&mw);
+ mw.insertToolBar(&tb1, &tb2);
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb1));
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb2));
+
+ mw.removeToolBar(&tb1);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &tb1));
+ QVERIFY(findWidgetRecursively(mw.layout(), &tb2));
+
+ mw.removeToolBar(&tb2);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &tb1));
+ QVERIFY(!findWidgetRecursively(mw.layout(), &tb2));
+ }
+}
+
+void tst_QMainWindow::toolBarArea()
+{
+ Qt::ToolBarArea areas[] = {
+ Qt::LeftToolBarArea,
+ Qt::RightToolBarArea,
+ Qt::TopToolBarArea,
+ Qt::BottomToolBarArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::ToolBarArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::ToolBarArea area = areas[i];
+
+ QMainWindow mw;
+ QToolBar tb(&mw);
+
+ for (int j = 0; j < areaCount; ++j) {
+ Qt::ToolBarArea otherArea = areas[j];
+
+ mw.addToolBar(area, &tb);
+ QCOMPARE(mw.toolBarArea(&tb), area);
+ mw.addToolBar(otherArea, &tb);
+ QCOMPARE(mw.toolBarArea(&tb), otherArea);
+ }
+ }
+
+ {
+ // addToolBar() with no area, equivalent to top
+ QMainWindow mw;
+ QToolBar tb(&mw);
+
+ for (int j = 0; j < areaCount; ++j) {
+ Qt::ToolBarArea otherArea = areas[j];
+
+ mw.addToolBar(&tb);
+ QCOMPARE(mw.toolBarArea(&tb), Qt::TopToolBarArea);
+ mw.addToolBar(otherArea, &tb);
+ QCOMPARE(mw.toolBarArea(&tb), otherArea);
+ }
+ }
+}
+
+void tst_QMainWindow::addDockWidget()
+{
+ Qt::DockWidgetArea areas[] = {
+ Qt::LeftDockWidgetArea,
+ Qt::RightDockWidgetArea,
+ Qt::TopDockWidgetArea,
+ Qt::BottomDockWidgetArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::DockWidgetArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::DockWidgetArea area = areas[i];
+
+ QMainWindow mw;
+ QDockWidget dw(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw));
+ mw.addDockWidget(area, &dw);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw));
+ }
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::DockWidgetArea area = areas[i];
+
+ {
+ QMainWindow mw;
+ QDockWidget dw(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw));
+ mw.addDockWidget(area, &dw, Qt::Horizontal);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw));
+ }
+
+ {
+ QMainWindow mw;
+ QDockWidget dw(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw));
+ mw.addDockWidget(area, &dw, Qt::Vertical);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw));
+ }
+ }
+
+ {
+ QMainWindow mw;
+ QDockWidget dw(&mw);
+ // should not crash, should get a warning instead
+ QTest::ignoreMessage(QtWarningMsg, "QMainWindow::addDockWidget: invalid 'area' argument");
+ mw.addDockWidget(Qt::NoDockWidgetArea, &dw);
+ }
+}
+
+void tst_QMainWindow::splitDockWidget()
+{
+ Qt::DockWidgetArea areas[] = {
+ Qt::LeftDockWidgetArea,
+ Qt::RightDockWidgetArea,
+ Qt::TopDockWidgetArea,
+ Qt::BottomDockWidgetArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::DockWidgetArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::DockWidgetArea area = areas[i];
+
+ {
+ QMainWindow mw;
+ QDockWidget dw1(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw1));
+ mw.addDockWidget(area, &dw1);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw1));
+ QDockWidget dw2(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw2));
+ mw.splitDockWidget(&dw1, &dw2, Qt::Horizontal);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw2));
+ }
+
+ {
+ QMainWindow mw;
+ QDockWidget dw1(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw1));
+ mw.addDockWidget(area, &dw1);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw1));
+ QDockWidget dw2(&mw);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw2));
+ mw.splitDockWidget(&dw1, &dw2, Qt::Horizontal);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw2));
+ }
+ }
+}
+
+void tst_QMainWindow::removeDockWidget()
+{
+ Qt::DockWidgetArea areas[] = {
+ Qt::LeftDockWidgetArea,
+ Qt::RightDockWidgetArea,
+ Qt::TopDockWidgetArea,
+ Qt::BottomDockWidgetArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::DockWidgetArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::DockWidgetArea area = areas[i];
+
+ QMainWindow mw;
+ QDockWidget dw1(&mw);
+ mw.addDockWidget(area, &dw1);
+ QDockWidget dw2(&mw);
+ mw.addDockWidget(area, &dw2);
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw1));
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw2));
+
+ mw.removeDockWidget(&dw1);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw1));
+ QVERIFY(findWidgetRecursively(mw.layout(), &dw2));
+
+ mw.removeDockWidget(&dw2);
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw1));
+ QVERIFY(!findWidgetRecursively(mw.layout(), &dw2));
+ }
+}
+
+void tst_QMainWindow::dockWidgetArea()
+{
+ Qt::DockWidgetArea areas[] = {
+ Qt::LeftDockWidgetArea,
+ Qt::RightDockWidgetArea,
+ Qt::TopDockWidgetArea,
+ Qt::BottomDockWidgetArea
+ };
+ const int areaCount = sizeof(areas) / sizeof(Qt::DockWidgetArea);
+
+ for (int i = 0; i < areaCount; ++i) {
+ Qt::DockWidgetArea area = areas[i];
+
+ QMainWindow mw;
+ QDockWidget dw(&mw);
+
+ for (int j = 0; j < areaCount; ++j) {
+ Qt::DockWidgetArea otherArea = areas[i];
+
+ mw.addDockWidget(area, &dw);
+ QCOMPARE(mw.dockWidgetArea(&dw), area);
+ mw.addDockWidget(otherArea, &dw);
+ QCOMPARE(mw.dockWidgetArea(&dw), otherArea);
+ }
+ }
+}
+
+void tst_QMainWindow::restoreState()
+{
+ QMainWindow mw;
+ QToolBar tb(&mw);
+ mw.addToolBar(Qt::TopToolBarArea, &tb);
+ QDockWidget dw(&mw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+
+ QByteArray state;
+
+ state = mw.saveState();
+ QVERIFY(mw.restoreState(state));
+
+ state = mw.saveState(1);
+ QVERIFY(!mw.restoreState(state));
+ QVERIFY(mw.restoreState(state, 1));
+}
+
+//tests the restoration of the previous versions of window settings
+void tst_QMainWindow::restoreStateFromPreviousVersion()
+{
+ QList<QByteArray> restoreData;
+ restoreData << QByteArray((char*)restoreData41, sizeof(restoreData41))
+ << QByteArray((char*)restoreData42, sizeof(restoreData42))
+ << QByteArray((char*)restoreData43, sizeof(restoreData43));
+
+ foreach(QByteArray ba, restoreData) {
+
+ QMainWindow win;
+ win.setCentralWidget(new QTextEdit);
+ QVector<QDockWidget*> docks;
+
+ for(int i = 0; i < 16; ++i) {
+ const QString name = QString::fromLatin1("dock %1").arg(i);
+ QDockWidget *dock = new QDockWidget(name);
+ docks += dock;
+ dock->setObjectName(name);
+ win.addDockWidget(Qt::TopDockWidgetArea, dock);
+ }
+ win.show();
+ QCOMPARE(win.restoreState(ba), true);
+
+ for( int i = 0; i < docks.size(); ++i) {
+ QCOMPARE( win.dockWidgetArea(docks[i]), Qt::DockWidgetArea(1 << i%4));
+ }
+ }
+
+}
+
+
+void tst_QMainWindow::createPopupMenu()
+{
+ {
+ QMainWindow mainwindow;
+ QVERIFY(!mainwindow.createPopupMenu());
+
+ QToolBar toolbar1(&mainwindow);
+ toolbar1.setWindowTitle("toolbar1");
+ QToolBar toolbar2(&mainwindow);
+ toolbar2.setWindowTitle("toolbar2");
+
+ mainwindow.addToolBar(&toolbar1);
+ mainwindow.addToolBar(&toolbar2);
+
+ QDockWidget dockwidget1(&mainwindow);
+ dockwidget1.setWindowTitle("dockwidget1");
+ QDockWidget dockwidget2(&mainwindow);
+ dockwidget2.setWindowTitle("dockwidget2");
+ QDockWidget dockwidget3(&mainwindow);
+ dockwidget3.setWindowTitle("dockwidget3");
+ QDockWidget dockwidget4(&mainwindow);
+ dockwidget4.setWindowTitle("dockwidget4");
+
+ mainwindow.addDockWidget(Qt::LeftDockWidgetArea, &dockwidget1);
+ mainwindow.addDockWidget(Qt::LeftDockWidgetArea, &dockwidget2);
+ mainwindow.addDockWidget(Qt::LeftDockWidgetArea, &dockwidget3);
+ mainwindow.addDockWidget(Qt::LeftDockWidgetArea, &dockwidget4);
+
+
+#ifdef QT_SOFTKEYS_ENABLED
+ // Softkeys add extra "Select" and "Back" actions to menu by default.
+ // Two first actions will be Select and Back when softkeys are enabled
+ int numSoftkeyActions = 2;
+#else
+ int numSoftkeyActions = 0;
+#endif
+
+ QMenu *menu = mainwindow.createPopupMenu();
+ QVERIFY(menu != 0);
+ QList<QAction *> actions = menu->actions();
+ QCOMPARE(actions.size(), 7 + numSoftkeyActions);
+
+ QCOMPARE(actions.at(0 + numSoftkeyActions), dockwidget1.toggleViewAction());
+ QCOMPARE(actions.at(1 + numSoftkeyActions), dockwidget2.toggleViewAction());
+ QCOMPARE(actions.at(2 + numSoftkeyActions), dockwidget3.toggleViewAction());
+ QCOMPARE(actions.at(3 + numSoftkeyActions), dockwidget4.toggleViewAction());
+ QVERIFY(actions.at(4 + numSoftkeyActions)->isSeparator());
+ QCOMPARE(actions.at(5 + numSoftkeyActions), toolbar1.toggleViewAction());
+ QCOMPARE(actions.at(6 + numSoftkeyActions), toolbar2.toggleViewAction());
+
+ delete menu;
+
+ mainwindow.removeToolBar(&toolbar1);
+ mainwindow.removeDockWidget(&dockwidget1);
+ mainwindow.removeDockWidget(&dockwidget4);
+
+ menu = mainwindow.createPopupMenu();
+ QVERIFY(menu != 0);
+ actions = menu->actions();
+ QCOMPARE(actions.size(), 4 + numSoftkeyActions);
+
+ QCOMPARE(actions.at(0 + numSoftkeyActions), dockwidget2.toggleViewAction());
+ QCOMPARE(actions.at(1 + numSoftkeyActions), dockwidget3.toggleViewAction());
+ QVERIFY(actions.at(2 + numSoftkeyActions)->isSeparator());
+ QCOMPARE(actions.at(3 + numSoftkeyActions), toolbar2.toggleViewAction());
+
+ delete menu;
+ }
+}
+
+class MyDockWidget : public QDockWidget
+{
+public:
+ MyDockWidget(QWidget * = 0) {
+ create(); // otherwise hide() doesn't result in a hide event
+ }
+};
+
+class MyWidget : public QWidget
+{
+public:
+ MyWidget(QWidget *parent = 0) : QWidget(parent)
+ {
+ }
+
+ QSize sizeHint() const
+ {
+ return QSize(200, 200);
+ }
+};
+
+void tst_QMainWindow::hideBeforeLayout()
+{
+ QMainWindow win;
+ QDockWidget *dock = new MyDockWidget(&win);
+ dock->setWidget(new QLabel("hello"));
+ win.addDockWidget(Qt::LeftDockWidgetArea, dock);
+ dock->hide();
+ win.resize(300, 300);
+ win.show();
+ dock->show();
+ QVERIFY(dock->geometry().bottomRight().x() >= 0);
+}
+
+struct AddDockWidget
+{
+ enum Mode { AddMode, SplitMode, TabMode };
+
+ AddDockWidget() {}
+ AddDockWidget(const QString &_name, Qt::DockWidgetArea _a)
+ : name(_name), mode(AddMode), a(_a) {}
+ AddDockWidget(const QString &_name, const QString &_other, Qt::Orientation _o)
+ : name(_name), mode(SplitMode), o(_o), other(_other) {}
+ AddDockWidget(const QString &_name, const QString &_other)
+ : name(_name), mode(TabMode), other(_other) {}
+
+ QString name;
+ Mode mode;
+
+ Qt::Orientation o;
+ Qt::DockWidgetArea a;
+ QString other;
+
+ void apply(QMainWindow *mw) const;
+};
+
+typedef QList<AddDockWidget> AddList;
+Q_DECLARE_METATYPE(AddList)
+
+void AddDockWidget::apply(QMainWindow *mw) const
+{
+ QDockWidget *dw = new QDockWidget();
+ QWidget *w = new QWidget();
+ w->setMinimumSize(100, 50);
+ dw->setWidget(w);
+
+ dw->setObjectName(name);
+ dw->setWindowTitle(name);
+
+ QDockWidget *other = 0;
+ if (mode == SplitMode || mode == TabMode) {
+ other = qFindChild<QDockWidget*>(mw, this->other);
+ QVERIFY(other != 0);
+ }
+
+ switch (mode) {
+ case AddMode:
+ mw->addDockWidget(a, dw);
+ break;
+ case SplitMode:
+ mw->splitDockWidget(other, dw, o);
+ break;
+ case TabMode:
+ mw->tabifyDockWidget(other, dw);
+ break;
+ }
+}
+
+#ifdef QT_BUILD_INTERNAL
+struct MoveSeparator
+{
+ MoveSeparator() {}
+ MoveSeparator(int _delta, const QString &_name)
+ : delta(_delta), name(_name) {}
+ MoveSeparator(int _delta, int _area)
+ : delta(_delta), area(_area) {}
+
+ int delta;
+ int area;
+ QString name;
+
+ void apply(QMainWindow *mw) const;
+};
+
+typedef QList<MoveSeparator> MoveList;
+Q_DECLARE_METATYPE(MoveList)
+
+void MoveSeparator::apply(QMainWindow *mw) const
+{
+ QMainWindowLayout *l = qFindChild<QMainWindowLayout *>(mw);
+ QVERIFY(l);
+
+ QList<int> path;
+ if (name.isEmpty()) {
+ path << area;
+ } else {
+ QDockWidget *dw = qFindChild<QDockWidget*>(mw, name);
+ QVERIFY(dw != 0);
+ path = l->layoutState.dockAreaLayout.indexOf(dw);
+ }
+ QVERIFY(!path.isEmpty());
+
+ l->layoutState.dockAreaLayout.separatorMove(path, QPoint(0, 0), QPoint(delta, delta));
+}
+#endif
+
+QMap<QString, QRect> dockWidgetGeometries(QMainWindow *mw)
+{
+ QMap<QString, QRect> result;
+ QList<QDockWidget*> dockWidgets = qFindChildren<QDockWidget*>(mw);
+ foreach (QDockWidget *dw, dockWidgets)
+ result.insert(dw->objectName(), dw->geometry());
+ return result;
+}
+
+#define COMPARE_DOCK_WIDGET_GEOS(_oldGeos, _newGeos) \
+{ \
+ QMap<QString, QRect> __oldGeos = _oldGeos; \
+ QMap<QString, QRect> __newGeos = _newGeos; \
+ QCOMPARE(__newGeos.keys(), __oldGeos.keys()); \
+ QStringList __keys = __newGeos.keys(); \
+ foreach (const QString &key, __keys) { \
+ QRect __r1 = __oldGeos[key]; \
+ QRect __r2 = __newGeos[key]; \
+ if (__r1 != __r2) \
+ qWarning() << key << __r1 << __r2; \
+ } \
+ QCOMPARE(__newGeos, __oldGeos); \
+}
+
+void tst_QMainWindow::saveRestore_data()
+{
+#ifdef QT_BUILD_INTERNAL
+ QTest::addColumn<AddList >("addList");
+ QTest::addColumn<MoveList >("moveList");
+
+ QTest::newRow("1") << (AddList()
+ << AddDockWidget("left", Qt::LeftDockWidgetArea))
+ << (MoveList()
+ << MoveSeparator(100, QInternal::LeftDock));
+
+ QTest::newRow("2") << (AddList()
+ << AddDockWidget("left", Qt::LeftDockWidgetArea)
+ << AddDockWidget("right", Qt::RightDockWidgetArea))
+ << (MoveList()
+ << MoveSeparator(70, QInternal::LeftDock)
+ << MoveSeparator(-40, QInternal::RightDock));
+ QTest::newRow("3") << (AddList()
+ << AddDockWidget("left", Qt::LeftDockWidgetArea)
+ << AddDockWidget("right1", Qt::RightDockWidgetArea)
+ << AddDockWidget("right2", Qt::RightDockWidgetArea))
+ << (MoveList()
+ << MoveSeparator(70, QInternal::LeftDock)
+ << MoveSeparator(-40, QInternal::RightDock));
+
+ QTest::newRow("4") << (AddList()
+ << AddDockWidget("left", Qt::LeftDockWidgetArea)
+ << AddDockWidget("right1", Qt::RightDockWidgetArea)
+ << AddDockWidget("right2a", Qt::RightDockWidgetArea)
+ << AddDockWidget("right2b", "right2a", Qt::Horizontal)
+ )
+ << (MoveList()
+ << MoveSeparator(70, QInternal::LeftDock)
+ << MoveSeparator(-40, QInternal::RightDock)
+ << MoveSeparator(-30, "right1")
+ << MoveSeparator(30, "right2a")
+ );
+#endif
+}
+
+void tst_QMainWindow::saveRestore()
+{
+#ifdef QT_BUILD_INTERNAL
+ QFETCH(AddList, addList);
+ QFETCH(MoveList, moveList);
+
+ QByteArray stateData;
+ QMap<QString, QRect> dockWidgetGeos;
+ QSize size;
+
+ {
+ QMainWindow mainWindow;
+ mainWindow.setDockNestingEnabled(true);
+ QTextEdit centralWidget("The rain in Spain falls mainly on the plains");
+ mainWindow.setCentralWidget(&centralWidget);
+
+ foreach (const AddDockWidget &adw, addList)
+ adw.apply(&mainWindow);
+
+ mainWindow.show();
+
+ foreach (const MoveSeparator &ms, moveList)
+ ms.apply(&mainWindow);
+
+ dockWidgetGeos = dockWidgetGeometries(&mainWindow);
+ size = mainWindow.size();
+ stateData = mainWindow.saveState();
+
+ mainWindow.layout()->setGeometry(mainWindow.rect());
+ COMPARE_DOCK_WIDGET_GEOS(dockWidgetGeos, dockWidgetGeometries(&mainWindow));
+
+#if 0
+ QEventLoop eventLoop;
+ QPushButton quitButton("Quit", &centralWidget);
+ quitButton.setGeometry(0, 0, 100, 40);
+ connect(&quitButton, SIGNAL(clicked()), &eventLoop, SLOT(quit()));
+ quitButton.show();
+ eventLoop.exec();
+#endif
+ }
+
+ // restoreState() after show
+ {
+ QMainWindow mainWindow;
+ mainWindow.setDockNestingEnabled(true);
+ QTextEdit centralWidget("The rain in Spain falls mainly on the plains");
+ mainWindow.setCentralWidget(&centralWidget);
+
+ foreach (const AddDockWidget &adw, addList)
+ adw.apply(&mainWindow);
+
+ mainWindow.show();
+ mainWindow.restoreState(stateData);
+
+ COMPARE_DOCK_WIDGET_GEOS(dockWidgetGeos, dockWidgetGeometries(&mainWindow));
+ }
+
+ // restoreState() before show
+ {
+ QMainWindow mainWindow;
+ mainWindow.setDockNestingEnabled(true);
+ QTextEdit centralWidget("The rain in Spain falls mainly on the plains");
+ mainWindow.setCentralWidget(&centralWidget);
+
+ foreach (const AddDockWidget &adw, addList)
+ adw.apply(&mainWindow);
+ mainWindow.resize(size);
+ mainWindow.restoreState(stateData);
+
+ mainWindow.show();
+ COMPARE_DOCK_WIDGET_GEOS(dockWidgetGeos, dockWidgetGeometries(&mainWindow));
+ }
+#endif
+}
+
+void tst_QMainWindow::isSeparator()
+{
+ QMainWindow mw;
+ QDockWidget *dockw = new QDockWidget();
+ mw.addDockWidget(Qt::LeftDockWidgetArea, dockw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, new QDockWidget());
+ dockw->resize(10,10);
+ mw.show();
+
+ //In case the separator size is 1, we increase it to 3 inside the QMainWindow class
+ const int margin = mw.style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, &mw) == 1 ? 2 : 0;
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y())));
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() - 1 - margin)));
+ QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+ QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + margin)));
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 15)));
+
+}
+
+class MainWindow : public QMainWindow {
+ public:
+ using QMainWindow::event;
+};
+
+#ifndef QT_NO_CURSOR
+void tst_QMainWindow::setCursor()
+{
+ MainWindow mw;
+ QCursor cur = Qt::WaitCursor;
+ mw.setCursor(cur);
+ QCOMPARE(cur.shape(), mw.cursor().shape());
+ mw.resize(200,200);
+ mw.show();
+ QTest::qWait(50);
+ QCOMPARE(cur.shape(), mw.cursor().shape());
+
+ QHoverEvent enterE(QEvent::HoverEnter, QPoint(10,10), QPoint());
+ mw.event(&enterE);
+ QTest::qWait(50);
+ QCOMPARE(cur.shape(), mw.cursor().shape());
+
+ QHoverEvent leaveE(QEvent::HoverLeave, QPoint(), QPoint());
+ mw.event(&leaveE);
+ QTest::qWait(50);
+ QCOMPARE(cur.shape(), mw.cursor().shape());
+}
+#endif
+
+void tst_QMainWindow::addToolbarAfterShow()
+{
+ //this is for task 243119
+ QMainWindow mainWindow;
+ mainWindow.show();
+
+ QToolBar toolBar;
+ mainWindow.addToolBar(&toolBar);
+ QTest::qWait(100);
+
+ QVERIFY(!toolBar.isHidden());
+}
+
+void tst_QMainWindow::centralWidgetSize()
+{
+ if(PlatformQuirks::isAutoMaximizing())
+ QSKIP("The platform is auto maximizing, so the test makes no sense", SkipAll);;
+
+ QMainWindow mainWindow;
+ mainWindow.menuBar()->addMenu("menu");
+
+ MyWidget widget;
+ mainWindow.setCentralWidget(&widget);
+
+ mainWindow.show();
+ QTest::qWait(100);
+ QCOMPARE(widget.size(), widget.sizeHint());
+}
+
+void tst_QMainWindow::dockWidgetSize()
+{
+ QMainWindow mainWindow;
+ mainWindow.menuBar()->addMenu("menu");
+
+ MyWidget widget;
+ mainWindow.setCentralWidget(&widget);
+
+ QDockWidget dock;
+ dock.setWidget(new MyWidget);
+ mainWindow.addDockWidget(Qt::TopDockWidgetArea, &dock);
+
+ mainWindow.show();
+ QTest::qWait(100);
+ if (mainWindow.size() == mainWindow.sizeHint()) {
+ QCOMPARE(widget.size(), widget.sizeHint());
+ QCOMPARE(dock.widget()->size(), dock.widget()->sizeHint());
+ } else {
+ //otherwise the screen is too small and the size are irrelevant
+ }
+}
+
+void tst_QMainWindow::QTBUG2774_stylechange()
+{
+
+ QMainWindow mw;
+ QDockWidget *dockw = new QDockWidget();
+ mw.addDockWidget(Qt::LeftDockWidgetArea, dockw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, new QDockWidget());
+ QTextEdit *central = new QTextEdit(&mw);
+ mw.setCentralWidget(central);
+ dockw->resize(10,10);
+ mw.show();
+ QTest::qWaitForWindowShown(&mw);
+ int centralOriginalWidth = central->width();
+
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() - 3)));
+ QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 30)));
+
+
+ {
+ QTest::qWait(1000);
+ mw.setStyleSheet("QMainWindow::separator { width: 50px; height:50px; }");
+ QTest::qWait(5000);
+ QApplication::processEvents();
+ QVERIFY(central->width() < centralOriginalWidth);
+ QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+ QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 49)));
+ }
+
+ {
+ mw.setStyleSheet("QMainWindow::separator { width: 0px; height: 0px; }");
+ QApplication::processEvents();
+ QVERIFY(central->width() > centralOriginalWidth);
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+ QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 1)));
+ }
+}
+
+#ifdef Q_OS_MAC
+void tst_QMainWindow::toggleUnifiedTitleAndToolBarOnMac()
+{
+ QMainWindow mw;
+ QToolBar *tb = new QToolBar;
+ tb->addAction("Test");
+ mw.addToolBar(tb);
+ mw.setUnifiedTitleAndToolBarOnMac(true);
+ mw.show();
+ QRect frameGeometry = mw.frameGeometry();
+ mw.setUnifiedTitleAndToolBarOnMac(false);
+ QVERIFY(frameGeometry.topLeft() == mw.frameGeometry().topLeft());
+ mw.setUnifiedTitleAndToolBarOnMac(true);
+ QVERIFY(frameGeometry.topLeft() == mw.frameGeometry().topLeft());
+}
+#endif
+
+QTEST_MAIN(tst_QMainWindow)
+#include "tst_qmainwindow.moc"
diff --git a/tests/auto/widgets/widgets/qmdiarea/.gitignore b/tests/auto/widgets/widgets/qmdiarea/.gitignore
new file mode 100644
index 0000000000..2632dbea40
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmdiarea/.gitignore
@@ -0,0 +1 @@
+tst_qmdiarea
diff --git a/tests/auto/widgets/widgets/qmdiarea/qmdiarea.pro b/tests/auto/widgets/widgets/qmdiarea/qmdiarea.pro
new file mode 100644
index 0000000000..6a12152fcc
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmdiarea/qmdiarea.pro
@@ -0,0 +1,14 @@
+load(qttest_p4)
+
+QT += gui-private widgets
+
+INCLUDEPATH += .
+SOURCES += tst_qmdiarea.cpp
+DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
+contains(QT_CONFIG, opengl):QT += opengl
+
+mac {
+ LIBS += -framework Security
+}
+
+CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
new file mode 100644
index 0000000000..a4ce94cc3d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
@@ -0,0 +1,2773 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QMdiSubWindow>
+#include <QMdiArea>
+
+#include <QApplication>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QPushButton>
+#include <QStyle>
+#include <QStyleOption>
+#include <QVBoxLayout>
+#include <QLineEdit>
+#include <QDesktopWidget>
+#include <QDockWidget>
+#include <QScrollBar>
+#include <QTextEdit>
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL>
+#endif
+#include <QMacStyle>
+
+#include "../../../platformquirks.h"
+
+static const Qt::WindowFlags DefaultWindowFlags
+ = Qt::SubWindow | Qt::WindowSystemMenuHint
+ | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
+
+Q_DECLARE_METATYPE(QMdiArea::WindowOrder)
+Q_DECLARE_METATYPE(QMdiSubWindow *)
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QTabWidget::TabPosition)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool reverse = false)
+{
+ if (!mdiArea) {
+ qWarning("Null pointer to mdi area");
+ return false;
+ }
+
+ QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+ const bool walkThrough = tabCount == -1;
+
+ if (walkThrough) {
+ QMdiSubWindow *active = reverse ? subWindows.front() : subWindows.back();
+ mdiArea->setActiveSubWindow(active);
+ if (mdiArea->activeSubWindow() != active) {
+ qWarning("Failed to set active sub window");
+ return false;
+ }
+ tabCount = subWindows.size();
+ }
+
+ QWidget *focusWidget = qApp->focusWidget();
+ if (!focusWidget) {
+ qWarning("No focus widget");
+ return false;
+ }
+
+ Qt::KeyboardModifiers modifiers = reverse ? Qt::ShiftModifier : Qt::NoModifier;
+ Qt::Key key;
+#ifdef Q_WS_MAC
+ key = Qt::Key_Meta;
+ modifiers |= Qt::MetaModifier;
+#else
+ key = Qt::Key_Control;
+ modifiers |= Qt::ControlModifier;
+#endif
+
+ QTest::keyPress(focusWidget, key, modifiers);
+ for (int i = 0; i < tabCount; ++i) {
+ QTest::keyPress(focusWidget, reverse ? Qt::Key_Backtab : Qt::Key_Tab, modifiers);
+ if (tabCount > 1)
+ QTest::qWait(500);
+ if (walkThrough) {
+ QRubberBand *rubberBand = qFindChild<QRubberBand *>(mdiArea->viewport());
+ if (!rubberBand) {
+ qWarning("No rubber band");
+ return false;
+ }
+ QMdiSubWindow *subWindow = subWindows.at(reverse ? subWindows.size() -1 - i : i);
+ if (rubberBand->geometry() != subWindow->geometry()) {
+ qWarning("Rubber band has different geometry");
+ return false;
+ }
+ }
+ qApp->processEvents();
+ }
+ QTest::keyRelease(focusWidget, key);
+
+ return true;
+}
+
+static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
+{
+ const bool rounded = (shape == QTabWidget::Rounded);
+ if (position == QTabWidget::North)
+ return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
+ if (position == QTabWidget::South)
+ return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
+ if (position == QTabWidget::East)
+ return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
+ if (position == QTabWidget::West)
+ return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
+ return QTabBar::RoundedNorth;
+}
+
+enum Arrangement {
+ Tiled,
+ Cascaded
+};
+
+static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const QList<int> &expectedIndices)
+{
+ if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty())
+ return false;
+
+ const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+ const QMdiSubWindow *const firstSubWindow = subWindows.at(0);
+
+ switch (arrangement) {
+ case Tiled:
+ {
+ // Calculate the number of rows and columns.
+ const int n = subWindows.count();
+ const int numColumns = qMax(qCeil(qSqrt(qreal(n))), 1);
+ const int numRows = qMax((n % numColumns) ? (n / numColumns + 1) : (n / numColumns), 1);
+
+ // Ensure that the geometry of all the subwindows are as expected by using
+ // QWidget::childAt starting from the middle of the topleft cell and subsequently
+ // adding rowWidth and rowHeight (going from left to right).
+ const int columnWidth = mdiArea->viewport()->width() / numColumns;
+ const int rowHeight = mdiArea->viewport()->height() / numRows;
+ QPoint subWindowPos(columnWidth / 2, rowHeight / 2);
+ for (int i = 0; i < numRows; ++i) {
+ for (int j = 0; j < numColumns; ++j) {
+ const int index = expectedIndices.at(i * numColumns + j);
+ QWidget *actual = mdiArea->viewport()->childAt(subWindowPos);
+ QMdiSubWindow *expected = subWindows.at(index);
+ if (actual != expected && !expected->isAncestorOf(actual))
+ return false;
+ subWindowPos.rx() += columnWidth;
+ }
+ subWindowPos.rx() = columnWidth / 2;
+ subWindowPos.ry() += rowHeight;
+ }
+ break;
+ }
+ case Cascaded:
+ {
+ // Calculate the delta (dx, dy) between two cascaded subwindows.
+ QStyleOptionTitleBar options;
+ options.initFrom(firstSubWindow);
+ int titleBarHeight = firstSubWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+#ifdef Q_WS_MAC
+ // ### Remove this after the mac style has been fixed
+ if (qobject_cast<QMacStyle *>(firstSubWindow->style()))
+ titleBarHeight -= 4;
+#endif
+ const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
+ const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
+ const int dx = 10;
+
+ // Current activation/stacking order.
+ const QList<QMdiSubWindow *> activationOrderList = mdiArea->subWindowList(QMdiArea::ActivationHistoryOrder);
+
+ // Ensure that the geometry of all the subwindows are as expected by using
+ // QWidget::childAt with the position of the first one and subsequently adding
+ // dx and dy.
+ QPoint subWindowPos(20, 5);
+ foreach (int expectedIndex, expectedIndices) {
+ QMdiSubWindow *expected = subWindows.at(expectedIndex);
+ expected->raise();
+ if (mdiArea->viewport()->childAt(subWindowPos) != expected)
+ return false;
+ expected->lower();
+ subWindowPos.rx() += dx;
+ subWindowPos.ry() += dy;
+ }
+
+ // Restore stacking order.
+ foreach (QMdiSubWindow *subWindow, activationOrderList) {
+ mdiArea->setActiveSubWindow(subWindow);
+ qApp->processEvents();
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+class tst_QMdiArea : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMdiArea();
+public slots:
+ void initTestCase();
+protected slots:
+ void activeChanged(QMdiSubWindow *child);
+
+private slots:
+ // Tests from QWorkspace
+ void subWindowActivated_data();
+ void subWindowActivated();
+ void subWindowActivated2();
+ void subWindowActivatedWithMinimize();
+ void showWindows();
+ void changeWindowTitle();
+ void changeModified();
+ void childSize();
+ void fixedSize();
+ // New tests
+ void minimumSizeHint();
+ void sizeHint();
+ void setActiveSubWindow();
+ void activeSubWindow();
+ void currentSubWindow();
+ void addAndRemoveWindows();
+ void addAndRemoveWindowsWithReparenting();
+ void removeSubWindow_2();
+ void closeWindows();
+ void activateNextAndPreviousWindow();
+ void subWindowList_data();
+ void subWindowList();
+ void setBackground();
+ void setViewport();
+ void tileSubWindows();
+ void cascadeAndTileSubWindows();
+ void resizeMaximizedChildWindows_data();
+ void resizeMaximizedChildWindows();
+ void focusWidgetAfterAddSubWindow();
+ void dontMaximizeSubWindowOnActivation();
+ void delayedPlacement();
+ void iconGeometryInMenuBar();
+ void resizeTimer();
+ void updateScrollBars();
+ void setActivationOrder_data();
+ void setActivationOrder();
+ void tabBetweenSubWindows();
+ void setViewMode();
+ void setTabsClosable();
+ void setTabsMovable();
+ void setTabShape();
+ void setTabPosition_data();
+ void setTabPosition();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ void nativeSubWindows();
+#endif
+ void task_209615();
+ void task_236750();
+
+private:
+ QMdiSubWindow *activeWindow;
+ bool accelPressed;
+};
+
+tst_QMdiArea::tst_QMdiArea()
+ : activeWindow(0)
+{
+ qRegisterMetaType<QMdiSubWindow *>();
+}
+
+void tst_QMdiArea::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// Old QWorkspace tests
+void tst_QMdiArea::activeChanged(QMdiSubWindow *child)
+{
+ activeWindow = child;
+}
+
+void tst_QMdiArea::subWindowActivated_data()
+{
+ // define the test elements we're going to use
+ QTest::addColumn<int>("count");
+
+ // create a first testdata instance and fill it with data
+ QTest::newRow( "data0" ) << 0;
+ QTest::newRow( "data1" ) << 1;
+ QTest::newRow( "data2" ) << 2;
+}
+
+void tst_QMdiArea::subWindowActivated()
+{
+ QMainWindow mw(0) ;
+ mw.menuBar();
+ QMdiArea *workspace = new QMdiArea(&mw);
+ workspace->setObjectName(QLatin1String("testWidget"));
+ mw.setCentralWidget(workspace);
+ QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+ mw.show();
+ qApp->setActiveWindow(&mw);
+
+ QFETCH( int, count );
+ int i;
+
+ for ( i = 0; i < count; ++i ) {
+ QWidget *widget = new QWidget(workspace, 0);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addSubWindow(widget)->show();
+ widget->show();
+ qApp->processEvents();
+ QVERIFY( activeWindow == workspace->activeSubWindow() );
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+
+ QList<QMdiSubWindow *> windows = workspace->subWindowList();
+ QCOMPARE( (int)windows.count(), count );
+
+ for ( i = 0; i < count; ++i ) {
+ QMdiSubWindow *window = windows.at(i);
+ window->showMinimized();
+ qApp->processEvents();
+ QVERIFY( activeWindow == workspace->activeSubWindow() );
+ if ( i == 1 )
+ QVERIFY( activeWindow == window );
+ }
+
+ for ( i = 0; i < count; ++i ) {
+ QMdiSubWindow *window = windows.at(i);
+ window->showNormal();
+ qApp->processEvents();
+ QVERIFY( window == activeWindow );
+ QVERIFY( activeWindow == workspace->activeSubWindow() );
+ }
+ spy.clear();
+
+ while (workspace->activeSubWindow() ) {
+ workspace->activeSubWindow()->close();
+ qApp->processEvents();
+ QVERIFY(activeWindow == workspace->activeSubWindow());
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+
+ QVERIFY(activeWindow == 0);
+ QVERIFY(workspace->activeSubWindow() == 0);
+ QCOMPARE(workspace->subWindowList().count(), 0);
+
+ {
+ workspace->hide();
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window = workspace->addSubWindow(widget);
+ widget->show();
+ QCOMPARE(spy.count(), 0);
+ workspace->show();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == window );
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == 0 );
+ }
+
+ {
+ workspace->hide();
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window = workspace->addSubWindow(widget);
+ widget->showMaximized();
+ qApp->sendPostedEvents();
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+ workspace->show();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == window );
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == 0 );
+ }
+
+ {
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window = workspace->addSubWindow(widget);
+ widget->showMinimized();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == window );
+ QVERIFY(workspace->activeSubWindow() == window);
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY(workspace->activeSubWindow() == 0);
+ QVERIFY( activeWindow == 0 );
+ }
+}
+
+#ifdef Q_WS_MAC
+#include <Security/AuthSession.h>
+bool macHasAccessToWindowsServer()
+{
+ SecuritySessionId mySession;
+ SessionAttributeBits sessionInfo;
+ SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
+ return (sessionInfo & sessionHasGraphicAccess);
+}
+#endif
+
+
+void tst_QMdiArea::subWindowActivated2()
+{
+ QMdiArea mdiArea;
+ QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ for (int i = 0; i < 5; ++i)
+ mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(spy.count(), 0);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWaitForWindowShown(&mdiArea);
+ mdiArea.activateWindow();
+ QTest::qWait(100);
+
+ QTRY_COMPARE(spy.count(), 5);
+ QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().back());
+ spy.clear();
+
+ // Just to make sure another widget is on top wrt. stacking order.
+ // This will typically become the active window if things are broken.
+ QMdiSubWindow *staysOnTopWindow = mdiArea.subWindowList().at(3);
+ staysOnTopWindow->setWindowFlags(Qt::WindowStaysOnTopHint);
+ mdiArea.setActiveSubWindow(staysOnTopWindow);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), staysOnTopWindow);
+ spy.clear();
+
+ QMdiSubWindow *activeSubWindow = mdiArea.subWindowList().at(2);
+ mdiArea.setActiveSubWindow(activeSubWindow);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+ spy.clear();
+
+ // Check that we only emit _one_ signal and the active window
+ // is unchanged after hide/show.
+ mdiArea.hide();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
+ spy.clear();
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+ spy.clear();
+
+ if (PlatformQuirks::isAutoMaximizing())
+ QSKIP("Platform is auto maximizing, so no showMinimized()", SkipAll);
+
+ // Check that we only emit _one_ signal and the active window
+ // is unchanged after showMinimized/showNormal.
+ mdiArea.showMinimized();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#elif defined (Q_WS_MAC)
+ if (!macHasAccessToWindowsServer())
+ QEXPECT_FAIL("", "showMinimized doesn't really minimize if you don't have access to the server", Abort);
+#endif
+ QTest::qWait(10);
+#if defined(Q_WS_QWS)
+ QEXPECT_FAIL("", "task 168682", Abort);
+#endif
+#ifdef Q_OS_WINCE
+ QSKIP("Not fixed yet. See Task 197453", SkipAll);
+#endif
+ QTRY_COMPARE(spy.count(), 1);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
+ spy.clear();
+
+ mdiArea.showNormal();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+ spy.clear();
+}
+
+void tst_QMdiArea::subWindowActivatedWithMinimize()
+{
+ QMainWindow mw(0) ;
+ mw.menuBar();
+ QMdiArea *workspace = new QMdiArea(&mw);
+ workspace->setObjectName(QLatin1String("testWidget"));
+ mw.setCentralWidget(workspace);
+ QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)) );
+ mw.show();
+ qApp->setActiveWindow(&mw);
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window1 = workspace->addSubWindow(widget);
+ QWidget *widget2 = new QWidget(workspace);
+ widget2->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window2 = workspace->addSubWindow(widget2);
+
+ widget->showMinimized();
+ QVERIFY( activeWindow == window1 );
+ widget2->showMinimized();
+ QVERIFY( activeWindow == window2 );
+
+ window2->close();
+ qApp->processEvents();
+ QVERIFY( activeWindow == window1 );
+
+ window1->close();
+ qApp->processEvents();
+ QVERIFY(workspace->activeSubWindow() == 0);
+ QVERIFY( activeWindow == 0 );
+
+ QVERIFY( workspace->subWindowList().count() == 0 );
+}
+
+void tst_QMdiArea::showWindows()
+{
+ QMdiArea *ws = new QMdiArea( 0 );
+
+ QWidget *widget = 0;
+ ws->show();
+
+ widget = new QWidget(ws);
+ widget->show();
+ QVERIFY( widget->isVisible() );
+
+ widget = new QWidget(ws);
+ widget->showMaximized();
+ QVERIFY( widget->isMaximized() );
+ widget->showNormal();
+ QVERIFY( !widget->isMaximized() );
+
+ widget = new QWidget(ws);
+ widget->showMinimized();
+ QVERIFY( widget->isMinimized() );
+ widget->showNormal();
+ QVERIFY( !widget->isMinimized() );
+
+ ws->hide();
+
+ widget = new QWidget(ws);
+ ws->show();
+ QVERIFY( widget->isVisible() );
+
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->showMaximized();
+ QVERIFY( widget->isMaximized() );
+ ws->show();
+ QVERIFY( widget->isVisible() );
+ QVERIFY( widget->isMaximized() );
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->showMinimized();
+ ws->show();
+ QVERIFY( widget->isMinimized() );
+ ws->hide();
+
+ delete ws;
+}
+
+
+//#define USE_SHOW
+
+void tst_QMdiArea::changeWindowTitle()
+{
+ const QString mwc = QString::fromLatin1("MainWindow's Caption");
+ const QString mwc2 = QString::fromLatin1("MainWindow's New Caption");
+ const QString wc = QString::fromLatin1("Widget's Caption");
+ const QString wc2 = QString::fromLatin1("Widget's New Caption");
+
+ QMainWindow *mw = new QMainWindow;
+ mw->setWindowTitle( mwc );
+ QMdiArea *ws = new QMdiArea( mw );
+ mw->setCentralWidget( ws );
+ mw->menuBar();
+ mw->show();
+ QTest::qWaitForWindowShown(mw);
+
+ QWidget *widget = new QWidget( ws );
+ widget->setWindowTitle( wc );
+ ws->addSubWindow(widget);
+
+ QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+#endif
+
+ mw->hide();
+ qApp->processEvents();
+ mw->show();
+ qApp->processEvents();
+ QTest::qWaitForWindowShown(mw);
+
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+#endif
+
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+ widget->setWindowTitle( wc2 );
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc2) );
+ mw->setWindowTitle( mwc2 );
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+
+ mw->show();
+ qApp->setActiveWindow(mw);
+
+#ifdef USE_SHOW
+ mw->showFullScreen();
+#else
+ mw->setWindowState(Qt::WindowFullScreen);
+#endif
+
+ qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+ QCOMPARE(mw->windowTitle(), mwc);
+#else
+ QCOMPARE( mw->windowTitle(), mwc2 );
+#endif
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+
+#ifdef USE_SHOW
+ mw->showNormal();
+#else
+ mw->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+
+ delete mw;
+}
+
+void tst_QMdiArea::changeModified()
+{
+ const QString mwc = QString::fromLatin1("MainWindow's Caption");
+ const QString wc = QString::fromLatin1("Widget's Caption[*]");
+
+ QMainWindow *mw = new QMainWindow(0);
+ mw->setWindowTitle( mwc );
+ QMdiArea *ws = new QMdiArea( mw );
+ mw->setCentralWidget( ws );
+ mw->menuBar();
+ mw->show();
+
+ QWidget *widget = new QWidget( ws );
+ widget->setWindowTitle( wc );
+ ws->addSubWindow(widget);
+
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+ widget->setWindowState(Qt::WindowMaximized);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowModified(true);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+ widget->setWindowState(Qt::WindowMaximized);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->isWindowModified(), true);
+#endif
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowMaximized);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->isWindowModified(), true);
+#endif
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowModified(false);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowModified(true);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->isWindowModified(), true);
+#endif
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ delete mw;
+}
+
+class MyChild : public QWidget
+{
+public:
+ MyChild(QWidget *parent = 0) : QWidget(parent) {}
+ QSize sizeHint() const { return QSize(234, 123); }
+};
+
+void tst_QMdiArea::childSize()
+{
+ QMdiArea ws;
+
+ MyChild *child = new MyChild(&ws);
+ child->show();
+ QCOMPARE(child->size(), child->sizeHint());
+ delete child;
+
+ child = new MyChild(&ws);
+ child->setFixedSize(200, 200);
+ child->show();
+ QCOMPARE(child->size(), child->minimumSize());
+ delete child;
+
+ child = new MyChild(&ws);
+ child->resize(150, 150);
+ child->show();
+ QCOMPARE(child->size(), QSize(150,150));
+ delete child;
+}
+
+void tst_QMdiArea::fixedSize()
+{
+ QMdiArea *ws = new QMdiArea;
+ int i;
+
+ ws->resize(500, 500);
+// ws->show();
+
+ QSize fixed(300, 300);
+ for (i = 0; i < 4; ++i) {
+ QWidget *child = new QWidget(ws);
+ child->setFixedSize(fixed);
+ child->show();
+ }
+
+ QList<QMdiSubWindow *> windows = ws->subWindowList();
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ }
+
+ ws->cascadeSubWindows();
+ ws->resize(800, 800);
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ }
+ ws->resize(500, 500);
+
+ ws->tileSubWindows();
+ ws->resize(800, 800);
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ }
+ ws->resize(500, 500);
+
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ delete child;
+ }
+
+ delete ws;
+}
+
+class LargeWidget : public QWidget
+{
+public:
+ LargeWidget(QWidget *parent = 0) : QWidget(parent) {}
+ QSize sizeHint() const { return QSize(1280, 1024); }
+ QSize minimumSizeHint() const { return QSize(300, 300); }
+};
+
+// New tests
+void tst_QMdiArea::minimumSizeHint()
+{
+ QMdiArea workspace;
+ workspace.show();
+ QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MDIMinimizedWidth),
+ workspace.style()->pixelMetric(QStyle::PM_TitleBarHeight));
+ qApp->processEvents();
+ QAbstractScrollArea dummyScrollArea;
+ dummyScrollArea.setFrameStyle(QFrame::NoFrame);
+ expectedSize = expectedSize.expandedTo(dummyScrollArea.minimumSizeHint());
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
+
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ window->show();
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(window->minimumSizeHint()));
+
+ QMdiSubWindow *subWindow = workspace.addSubWindow(new LargeWidget);
+ subWindow->show();
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(subWindow->minimumSizeHint()));
+
+ workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize);
+}
+
+void tst_QMdiArea::sizeHint()
+{
+ QMdiArea workspace;
+ workspace.show();
+ QSize desktopSize = QApplication::desktop()->size();
+ QSize expectedSize(desktopSize.width() * 2/3, desktopSize.height() * 2/3);
+ QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
+
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ window->show();
+ QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(window->sizeHint()));
+
+ QMdiSubWindow *nested = workspace.addSubWindow(new QMdiArea);
+ expectedSize = QSize(desktopSize.width() * 2/6, desktopSize.height() * 2/6);
+ QCOMPARE(nested->widget()->sizeHint(), expectedSize);
+}
+
+void tst_QMdiArea::setActiveSubWindow()
+{
+ QMdiArea workspace;
+ workspace.show();
+
+ QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+ qApp->setActiveWindow(&workspace);
+
+ // Activate hidden windows
+ const int windowCount = 10;
+ QMdiSubWindow *windows[windowCount];
+ for (int i = 0; i < windowCount; ++i) {
+ windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ qApp->processEvents();
+ QVERIFY(windows[i]->isHidden());
+ workspace.setActiveSubWindow(windows[i]);
+ }
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(!activeWindow);
+ spy.clear();
+
+ // Activate visible windows
+ for (int i = 0; i < windowCount; ++i) {
+ windows[i]->show();
+ QVERIFY(!windows[i]->isHidden());
+ workspace.setActiveSubWindow(windows[i]);
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(activeWindow, windows[i]);
+ spy.clear();
+ }
+
+ // Deactivate active window
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!activeWindow);
+ QVERIFY(!workspace.activeSubWindow());
+
+ // Activate widget which is not child of any window inside workspace
+ QMdiSubWindow fakeWindow;
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::setActiveSubWindow: window is not inside workspace");
+ workspace.setActiveSubWindow(&fakeWindow);
+
+}
+
+void tst_QMdiArea::activeSubWindow()
+{
+ QMainWindow mainWindow;
+
+ QMdiArea *mdiArea = new QMdiArea;
+ QLineEdit *subWindowLineEdit = new QLineEdit;
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(subWindowLineEdit);
+ mainWindow.setCentralWidget(mdiArea);
+
+ QDockWidget *dockWidget = new QDockWidget(QLatin1String("Dock Widget"), &mainWindow);
+ dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea);
+ QLineEdit *dockWidgetLineEdit = new QLineEdit;
+ dockWidget->setWidget(dockWidgetLineEdit);
+ mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
+
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ qApp->setActiveWindow(&mainWindow);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+ QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
+
+ dockWidgetLineEdit->setFocus();
+ QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+ QEvent deactivateEvent(QEvent::WindowDeactivate);
+ qApp->sendEvent(subWindow, &deactivateEvent);
+ QVERIFY(!mdiArea->activeSubWindow());
+ QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
+
+ QEvent activateEvent(QEvent::WindowActivate);
+ qApp->sendEvent(subWindow, &activateEvent);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+ QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
+
+ QLineEdit dummyTopLevel;
+ dummyTopLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&dummyTopLevel);
+#endif
+
+ qApp->setActiveWindow(&dummyTopLevel);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+ qApp->setActiveWindow(&mainWindow);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
+ qApp->setActiveWindow(0);
+ QVERIFY(!mdiArea->activeSubWindow());
+#endif
+
+ //task 202657
+ dockWidgetLineEdit->setFocus();
+ qApp->setActiveWindow(&mainWindow);
+ QVERIFY(dockWidgetLineEdit->hasFocus());
+}
+
+void tst_QMdiArea::currentSubWindow()
+{
+ QMdiArea mdiArea;
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ for (int i = 0; i < 5; ++i)
+ mdiArea.addSubWindow(new QLineEdit)->show();
+
+ qApp->setActiveWindow(&mdiArea);
+ QCOMPARE(qApp->activeWindow(), (QWidget *)&mdiArea);
+
+ // Check that the last added window is the active and the current.
+ QMdiSubWindow *active = mdiArea.activeSubWindow();
+ QVERIFY(active);
+ QCOMPARE(mdiArea.subWindowList().back(), active);
+ QCOMPARE(mdiArea.currentSubWindow(), active);
+
+ QLineEdit dummyTopLevel;
+ dummyTopLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&dummyTopLevel);
+#endif
+
+ // Move focus to another top-level and check that we still
+ // have an active window.
+ qApp->setActiveWindow(&dummyTopLevel);
+ QCOMPARE(qApp->activeWindow(), (QWidget *)&dummyTopLevel);
+ QVERIFY(mdiArea.activeSubWindow());
+
+ delete active;
+ active = 0;
+
+ // We just deleted the current sub-window -> current should then
+ // be the next in list (which in this case is the first sub-window).
+ QVERIFY(mdiArea.currentSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), mdiArea.subWindowList().front());
+
+ // Activate mdi area and check that active == current.
+ qApp->setActiveWindow(&mdiArea);
+ active = mdiArea.activeSubWindow();
+ QVERIFY(active);
+ QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().front());
+
+ active->hide();
+ QCOMPARE(mdiArea.activeSubWindow(), active);
+ QCOMPARE(mdiArea.currentSubWindow(), active);
+
+ qApp->setActiveWindow(&dummyTopLevel);
+ QVERIFY(mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), active);
+
+ qApp->setActiveWindow(&mdiArea);
+ active->show();
+ QCOMPARE(mdiArea.activeSubWindow(), active);
+
+ mdiArea.setActiveSubWindow(0);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QVERIFY(!mdiArea.currentSubWindow());
+
+ mdiArea.setActiveSubWindow(active);
+ QCOMPARE(mdiArea.activeSubWindow(), active);
+ QEvent windowDeactivate(QEvent::WindowDeactivate);
+ qApp->sendEvent(active, &windowDeactivate);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QVERIFY(!mdiArea.currentSubWindow());
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(active, &windowActivate);
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.currentSubWindow());
+
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
+ qApp->setActiveWindow(0);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.currentSubWindow());
+#endif
+}
+
+void tst_QMdiArea::addAndRemoveWindows()
+{
+ QWidget topLevel;
+ QMdiArea workspace(&topLevel);
+ workspace.resize(800, 600);
+ topLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ { // addSubWindow with large widget
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ QWidget *window = workspace.addSubWindow(new LargeWidget);
+ QVERIFY(window);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ QCOMPARE(window->size(), workspace.viewport()->size());
+ }
+
+ { // addSubWindow, minimumSize set.
+ QMdiSubWindow *window = new QMdiSubWindow;
+ window->setMinimumSize(900, 900);
+ workspace.addSubWindow(window);
+ QVERIFY(window);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 2);
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ QCOMPARE(window->size(), window->minimumSize());
+ }
+
+ { // addSubWindow, resized
+ QMdiSubWindow *window = new QMdiSubWindow;
+ window->setWidget(new QWidget);
+ window->resize(1500, 1500);
+ workspace.addSubWindow(window);
+ QVERIFY(window);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 3);
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ QCOMPARE(window->size(), QSize(1500, 1500));
+ }
+
+ { // addSubWindow with 0 pointer
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
+ QWidget *window = workspace.addSubWindow(0);
+ QVERIFY(!window);
+ QCOMPARE(workspace.subWindowList().count(), 3);
+ }
+
+ { // addChildWindow
+ QMdiSubWindow *window = new QMdiSubWindow;
+ workspace.addSubWindow(window);
+ qApp->processEvents();
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ window->setWidget(new QWidget);
+ QCOMPARE(workspace.subWindowList().count(), 4);
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
+ workspace.addSubWindow(window);
+ }
+
+ { // addChildWindow with 0 pointer
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
+ workspace.addSubWindow(0);
+ QCOMPARE(workspace.subWindowList().count(), 4);
+ }
+
+ // removeSubWindow
+ foreach (QWidget *window, workspace.subWindowList()) {
+ workspace.removeSubWindow(window);
+ delete window;
+ }
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ // removeSubWindow with 0 pointer
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::removeSubWindow: null pointer to widget");
+ workspace.removeSubWindow(0);
+
+ workspace.addSubWindow(new QPushButton(QLatin1String("Dummy to make workspace non-empty")));
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+
+ // removeSubWindow with window not inside workspace
+ QTest::ignoreMessage(QtWarningMsg,"QMdiArea::removeSubWindow: window is not inside workspace");
+ QMdiSubWindow *fakeWindow = new QMdiSubWindow;
+ workspace.removeSubWindow(fakeWindow);
+ delete fakeWindow;
+
+ // Check that newly added windows don't occupy maximized windows'
+ // restore space.
+ workspace.closeAllSubWindows();
+ workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ workspace.show();
+ QMdiSubWindow *window1 = workspace.addSubWindow(new QWidget);
+ window1->show();
+ const QRect window1RestoreGeometry = window1->geometry();
+ QCOMPARE(window1RestoreGeometry.topLeft(), QPoint(0, 0));
+
+ window1->showMinimized();
+
+ // Occupy space.
+ QMdiSubWindow *window2 = workspace.addSubWindow(new QWidget);
+ window2->show();
+ const QRect window2RestoreGeometry = window2->geometry();
+ QCOMPARE(window2RestoreGeometry.topLeft(), QPoint(0, 0));
+
+ window2->showMaximized();
+
+ // Don't occupy space.
+ QMdiSubWindow *window3 = workspace.addSubWindow(new QWidget);
+ window3->show();
+ QCOMPARE(window3->geometry().topLeft(), QPoint(window2RestoreGeometry.right() + 1, 0));
+}
+
+void tst_QMdiArea::addAndRemoveWindowsWithReparenting()
+{
+ QMdiArea workspace;
+ QMdiSubWindow window(&workspace);
+ QVERIFY(window.windowFlags() == DefaultWindowFlags);
+
+ // 0 because the window list contains widgets and not actual
+ // windows. Silly, but that's the behavior.
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ window.setWidget(new QWidget);
+ qApp->processEvents();
+
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ window.setParent(0); // Will also reset window flags
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ window.setParent(&workspace);
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ QVERIFY(window.windowFlags() == DefaultWindowFlags);
+
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
+ workspace.addSubWindow(&window);
+ QCOMPARE(workspace.subWindowList().count(), 1);
+}
+
+class MySubWindow : public QMdiSubWindow
+{
+public:
+ using QObject::receivers;
+};
+
+static int numberOfConnectedSignals(MySubWindow *subWindow)
+{
+ if (!subWindow)
+ return 0;
+
+ int numConnectedSignals = 0;
+ for (int i = 0; i < subWindow->metaObject()->methodCount(); ++i) {
+ QMetaMethod method = subWindow->metaObject()->method(i);
+ if (method.methodType() == QMetaMethod::Signal) {
+ QString signature(QLatin1String("2"));
+ signature += QLatin1String(method.signature());
+ numConnectedSignals += subWindow->receivers(signature.toLatin1());
+ }
+ }
+ return numConnectedSignals;
+}
+
+void tst_QMdiArea::removeSubWindow_2()
+{
+ QMdiArea mdiArea;
+ MySubWindow *subWindow = new MySubWindow;
+ QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+
+ // Connected to aboutToActivate() and windowStateChanged().
+ mdiArea.addSubWindow(subWindow);
+ QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
+
+ // Ensure we disconnect from all signals.
+ mdiArea.removeSubWindow(subWindow);
+ QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+
+ mdiArea.addSubWindow(subWindow);
+ QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
+ subWindow->setParent(0);
+ QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+}
+
+void tst_QMdiArea::closeWindows()
+{
+ QMdiArea workspace;
+ workspace.show();
+ qApp->setActiveWindow(&workspace);
+
+ // Close widget
+ QWidget *widget = new QWidget;
+ QMdiSubWindow *subWindow = workspace.addSubWindow(widget);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ subWindow->close();
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ // Close window
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ const int windowCount = 10;
+
+ // Close active window
+ for (int i = 0; i < windowCount; ++i)
+ workspace.addSubWindow(new QWidget)->show();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), windowCount);
+ int activeSubWindowCount = 0;
+ while (workspace.activeSubWindow()) {
+ workspace.activeSubWindow()->close();
+ qApp->processEvents();
+ ++activeSubWindowCount;
+ }
+ QCOMPARE(activeSubWindowCount, windowCount);
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ // Close all windows
+ for (int i = 0; i < windowCount; ++i)
+ workspace.addSubWindow(new QWidget)->show();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), windowCount);
+ QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+ workspace.closeAllSubWindows();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!activeWindow);
+}
+
+void tst_QMdiArea::activateNextAndPreviousWindow()
+{
+ QMdiArea workspace;
+ workspace.show();
+ qApp->setActiveWindow(&workspace);
+
+ const int windowCount = 10;
+ QMdiSubWindow *windows[windowCount];
+ for (int i = 0; i < windowCount; ++i) {
+ windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ windows[i]->show();
+ qApp->processEvents();
+ }
+
+ QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+
+ // activateNextSubWindow
+ for (int i = 0; i < windowCount; ++i) {
+ workspace.activateNextSubWindow();
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[i]);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QVERIFY(activeWindow);
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+ QCOMPARE(workspace.activeSubWindow(), activeWindow);
+
+ // activatePreviousSubWindow
+ for (int i = windowCount - 2; i >= 0; --i) {
+ workspace.activatePreviousSubWindow();
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[i]);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ if (i % 2 == 0)
+ windows[i]->hide(); // 10, 8, 6, 4, 2, 0
+ }
+ QVERIFY(activeWindow);
+ QCOMPARE(workspace.activeSubWindow(), windows[0]);
+ QCOMPARE(workspace.activeSubWindow(), activeWindow);
+
+ // activateNextSubWindow with every 2nd window hidden
+ for (int i = 0; i < windowCount / 2; ++i) {
+ workspace.activateNextSubWindow(); // 1, 3, 5, 7, 9
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+
+ // activatePreviousSubWindow with every 2nd window hidden
+ for (int i = 0; i < windowCount / 2; ++i) {
+ workspace.activatePreviousSubWindow(); // 7, 5, 3, 1, 9
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+
+ workspace.setActiveSubWindow(0);
+ QVERIFY(!activeWindow);
+}
+
+void tst_QMdiArea::subWindowList_data()
+{
+ QTest::addColumn<QMdiArea::WindowOrder>("windowOrder");
+ QTest::addColumn<int>("windowCount");
+ QTest::addColumn<int>("activeSubWindow");
+ QTest::addColumn<int>("staysOnTop1");
+ QTest::addColumn<int>("staysOnTop2");
+
+ QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 10 << 4 << 8 << 5;
+ QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 10 << 6 << 3 << 9;
+ QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 10 << 7 << 2 << 1;
+}
+void tst_QMdiArea::subWindowList()
+{
+ QFETCH(QMdiArea::WindowOrder, windowOrder);
+ QFETCH(int, windowCount);
+ QFETCH(int, activeSubWindow);
+ QFETCH(int, staysOnTop1);
+ QFETCH(int, staysOnTop2);
+
+ QMdiArea workspace;
+ workspace.show();
+ qApp->setActiveWindow(&workspace);
+
+ QList<QMdiSubWindow *> activationOrder;
+ QVector<QMdiSubWindow *> windows;
+ for (int i = 0; i < windowCount; ++i) {
+ windows.append(qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)));
+ windows[i]->show();
+ activationOrder.append(windows[i]);
+ }
+
+ {
+ QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
+ QCOMPARE(widgets.count(), windowCount);
+ for (int i = 0; i < widgets.count(); ++i)
+ QCOMPARE(widgets.at(i), windows[i]);
+ }
+
+ windows[staysOnTop1]->setWindowFlags(windows[staysOnTop1]->windowFlags() | Qt::WindowStaysOnTopHint);
+ workspace.setActiveSubWindow(windows[activeSubWindow]);
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
+ activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
+
+ QList<QMdiSubWindow *> subWindows = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::CreationOrder) {
+ QCOMPARE(subWindows.at(activeSubWindow), windows[activeSubWindow]);
+ QCOMPARE(subWindows.at(staysOnTop1), windows[staysOnTop1]);
+ for (int i = 0; i < windowCount; ++i)
+ QCOMPARE(subWindows.at(i), windows[i]);
+ return;
+ }
+
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(subWindows.at(subWindows.count() - 1), windows[staysOnTop1]);
+ QCOMPARE(subWindows.at(subWindows.count() - 2), windows[activeSubWindow]);
+ QCOMPARE(subWindows.count(), windowCount);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(subWindows, activationOrder);
+ }
+
+ windows[staysOnTop2]->setWindowFlags(windows[staysOnTop2]->windowFlags() | Qt::WindowStaysOnTopHint);
+ workspace.setActiveSubWindow(windows[staysOnTop2]);
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[staysOnTop2]);
+ activationOrder.move(activationOrder.indexOf(windows[staysOnTop2]), windowCount - 1);
+
+ workspace.setActiveSubWindow(windows[activeSubWindow]);
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
+ activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
+
+ QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
+ QCOMPARE(widgets.count(), windowCount);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+ } else { // ActivationHistory
+ QCOMPARE(widgets, activationOrder);
+ }
+
+ windows[activeSubWindow]->raise();
+ windows[staysOnTop2]->lower();
+
+ widgets = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[activeSubWindow]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(0), windows[staysOnTop2]);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(widgets, activationOrder);
+ }
+
+ windows[activeSubWindow]->stackUnder(windows[staysOnTop1]);
+ windows[staysOnTop2]->raise();
+
+ widgets = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(widgets, activationOrder);
+ }
+
+ workspace.setActiveSubWindow(windows[staysOnTop1]);
+ activationOrder.move(activationOrder.indexOf(windows[staysOnTop1]), windowCount - 1);
+
+ widgets = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop2]);
+ QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(widgets, activationOrder);
+ }
+}
+
+void tst_QMdiArea::setBackground()
+{
+ QMdiArea workspace;
+ QCOMPARE(workspace.background(), workspace.palette().brush(QPalette::Dark));
+ workspace.setBackground(QBrush(Qt::green));
+ QCOMPARE(workspace.background(), QBrush(Qt::green));
+}
+
+void tst_QMdiArea::setViewport()
+{
+ QMdiArea workspace;
+ workspace.show();
+
+ QWidget *firstViewport = workspace.viewport();
+ QVERIFY(firstViewport);
+
+ const int windowCount = 10;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
+ window->show();
+ if (i % 2 == 0) {
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ } else {
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ }
+ }
+
+ qApp->processEvents();
+ QList<QMdiSubWindow *> windowsBeforeViewportChange = workspace.subWindowList();
+ QCOMPARE(windowsBeforeViewportChange.count(), windowCount);
+
+ workspace.setViewport(new QWidget);
+ qApp->processEvents();
+ QVERIFY(workspace.viewport() != firstViewport);
+
+ QList<QMdiSubWindow *> windowsAfterViewportChange = workspace.subWindowList();
+ QCOMPARE(windowsAfterViewportChange.count(), windowCount);
+ QCOMPARE(windowsAfterViewportChange, windowsBeforeViewportChange);
+
+ // for (int i = 0; i < windowCount; ++i) {
+ // QMdiSubWindow *window = windowsAfterViewportChange.at(i);
+ // if (i % 2 == 0)
+ // QVERIFY(!window->isMinimized());
+ //else
+ // QVERIFY(!window->isMaximized());
+ // }
+
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea: Deleting the view port is undefined, "
+ "use setViewport instead.");
+ delete workspace.viewport();
+ qApp->processEvents();
+
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ QVERIFY(!workspace.activeSubWindow());
+}
+
+void tst_QMdiArea::tileSubWindows()
+{
+ QMdiArea workspace;
+ workspace.resize(600,480);
+ if (PlatformQuirks::isAutoMaximizing())
+ workspace.setWindowFlags(workspace.windowFlags() | Qt::X11BypassWindowManagerHint);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ const int windowCount = 10;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *subWindow = workspace.addSubWindow(new QWidget);
+ subWindow->setMinimumSize(50, 30);
+ subWindow->show();
+ }
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ QList<QMdiSubWindow *> windows = workspace.subWindowList();
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = windows.at(i);
+ for (int j = 0; j < windowCount; ++j) {
+ if (i == j)
+ continue;
+ QVERIFY(!window->geometry().intersects(windows.at(j)->geometry()));
+ }
+ }
+
+ // Keep the views tiled through any subsequent resize events.
+ for (int i = 0; i < 5; ++i) {
+ workspace.resize(workspace.size() - QSize(10, 10));
+ qApp->processEvents();
+ }
+ workspace.setActiveSubWindow(0);
+#ifndef Q_OS_WINCE //See Task 197453 ToDo
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+#endif
+
+ QMdiSubWindow *window = windows.at(0);
+
+ // Change the geometry of one of the children and verify
+ // that the views are not tiled anymore.
+ window->move(window->x() + 1, window->y());
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Close one of the children and verify that the views
+ // are not tiled anymore.
+ window->close();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ window = windows.at(1);
+
+ // Maximize one of the children and verify that the views
+ // are not tiled anymore.
+ workspace.tileSubWindows();
+ window->showMaximized();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Minimize one of the children and verify that the views
+ // are not tiled anymore.
+ workspace.tileSubWindows();
+ window->showMinimized();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Active/deactivate windows and verify that the views are tiled.
+ workspace.setActiveSubWindow(windows.at(5));
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QTest::qWait(250); // delayed re-arrange of minimized windows
+ QTRY_COMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Add another window and verify that the views are not tiled anymore.
+ workspace.addSubWindow(new QPushButton(QLatin1String("I'd like to mess up tiled views")))->show();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Cascade and verify that the views are not tiled anymore.
+ workspace.cascadeSubWindows();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+
+ // Make sure the active window is placed in top left corner regardless
+ // of whether we have any windows with staysOnTopHint or not.
+ windows.at(3)->setWindowFlags(windows.at(3)->windowFlags() | Qt::WindowStaysOnTopHint);
+ QMdiSubWindow *activeSubWindow = windows.at(6);
+ workspace.setActiveSubWindow(activeSubWindow);
+ QCOMPARE(workspace.activeSubWindow(), activeSubWindow);
+ workspace.tileSubWindows();
+ QCOMPARE(activeSubWindow->geometry().topLeft(), QPoint(0, 0));
+
+ // Verify that we try to resize the area such that all sub-windows are visible.
+ // It's important that tiled windows are NOT overlapping.
+ workspace.resize(350, 150);
+ qApp->processEvents();
+ QTRY_COMPARE(workspace.size(), QSize(350, 150));
+
+ const QSize minSize(300, 100);
+ foreach (QMdiSubWindow *subWindow, workspace.subWindowList())
+ subWindow->setMinimumSize(minSize);
+
+ QCOMPARE(workspace.size(), QSize(350, 150));
+ workspace.tileSubWindows();
+ // The sub-windows are now tiled like this:
+ // | win 1 || win 2 || win 3 |
+ // +-------++-------++-------+
+ // +-------++-------++-------+
+ // | win 4 || win 5 || win 6 |
+ // +-------++-------++-------+
+ // +-------++-------++-------+
+ // | win 7 || win 8 || win 9 |
+ workspace.setActiveSubWindow(0);
+ int frameWidth = 0;
+ if (workspace.style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, &workspace))
+ frameWidth = workspace.style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const int spacing = 2 * frameWidth + 2;
+ const QSize expectedViewportSize(3 * minSize.width() + spacing, 3 * minSize.height() + spacing);
+#ifdef Q_OS_WINCE
+ QSKIP("Not fixed yet! See task 197453", SkipAll);
+#endif
+ QTRY_COMPARE(workspace.viewport()->rect().size(), expectedViewportSize);
+
+ // Not enough space for all sub-windows to be visible -> provide scroll bars.
+ workspace.resize(150, 150);
+ qApp->processEvents();
+ QTRY_COMPARE(workspace.size(), QSize(150, 150));
+
+ // Horizontal scroll bar.
+ QScrollBar *hBar = workspace.horizontalScrollBar();
+ QCOMPARE(workspace.horizontalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+ QTRY_VERIFY(hBar->isVisible());
+ QCOMPARE(hBar->value(), 0);
+ QCOMPARE(hBar->minimum(), 0);
+
+ // Vertical scroll bar.
+ QScrollBar *vBar = workspace.verticalScrollBar();
+ QCOMPARE(workspace.verticalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+ QVERIFY(vBar->isVisible());
+ QCOMPARE(vBar->value(), 0);
+ QCOMPARE(vBar->minimum(), 0);
+
+ workspace.tileSubWindows();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+ qApp->processEvents();
+
+ QTRY_VERIFY(workspace.size() != QSize(150, 150));
+ QTRY_VERIFY(!vBar->isVisible());
+ QTRY_VERIFY(!hBar->isVisible());
+}
+
+void tst_QMdiArea::cascadeAndTileSubWindows()
+{
+ QMdiArea workspace;
+ workspace.resize(400, 400);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ const int windowCount = 10;
+ QList<QMdiSubWindow *> windows;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = workspace.addSubWindow(new MyChild);
+ if (i % 3 == 0) {
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ } else {
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ }
+ windows.append(window);
+ }
+
+ // cascadeSubWindows
+ qApp->processEvents();
+ workspace.cascadeSubWindows();
+ qApp->processEvents();
+
+ // Check dy between two cascaded windows
+ QStyleOptionTitleBar options;
+ options.initFrom(windows.at(1));
+ int titleBarHeight = windows.at(1)->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+ // ### Remove this after the mac style has been fixed
+ if (windows.at(1)->style()->inherits("QMacStyle"))
+ titleBarHeight -= 4;
+ const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
+ const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
+ QCOMPARE(windows.at(2)->geometry().top() - windows.at(1)->geometry().top(), dy);
+
+ for (int i = 0; i < windows.count(); ++i) {
+ QMdiSubWindow *window = windows.at(i);
+ if (i % 3 == 0) {
+ QVERIFY(window->isMinimized());
+ } else {
+ QVERIFY(!window->isMaximized());
+ QCOMPARE(window->size(), window->sizeHint());
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ }
+ }
+}
+
+void tst_QMdiArea::resizeMaximizedChildWindows_data()
+{
+ QTest::addColumn<int>("startSize");
+ QTest::addColumn<int>("increment");
+ QTest::addColumn<int>("windowCount");
+
+ QTest::newRow("multiple children") << 400 << 20 << 10;
+}
+
+void tst_QMdiArea::resizeMaximizedChildWindows()
+{
+ QFETCH(int, startSize);
+ QFETCH(int, increment);
+ QFETCH(int, windowCount);
+
+ QWidget topLevel;
+ QMdiArea workspace(&topLevel);
+ topLevel.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+ QTest::qWait(100);
+ workspace.resize(startSize, startSize);
+ workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ QSize workspaceSize = workspace.size();
+ QVERIFY(workspaceSize.isValid());
+ QCOMPARE(workspaceSize, QSize(startSize, startSize));
+
+ QList<QMdiSubWindow *> windows;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
+ windows.append(window);
+ qApp->processEvents();
+ window->showMaximized();
+ QTest::qWait(100);
+ QVERIFY(window->isMaximized());
+ QSize windowSize = window->size();
+ QVERIFY(windowSize.isValid());
+ QCOMPARE(window->rect(), workspace.contentsRect());
+
+ workspace.resize(workspaceSize + QSize(increment, increment));
+ QTest::qWait(100);
+ qApp->processEvents();
+ QTRY_COMPARE(workspace.size(), workspaceSize + QSize(increment, increment));
+ QTRY_COMPARE(window->size(), windowSize + QSize(increment, increment));
+ workspaceSize = workspace.size();
+ }
+
+ int newSize = startSize + increment * windowCount;
+ QCOMPARE(workspaceSize, QSize(newSize, newSize));
+ foreach (QWidget *window, windows)
+ QCOMPARE(window->rect(), workspace.contentsRect());
+}
+
+// QWidget::setParent clears focusWidget so make sure
+// we restore it after QMdiArea::addSubWindow.
+void tst_QMdiArea::focusWidgetAfterAddSubWindow()
+{
+ QWidget *view = new QWidget;
+ view->setLayout(new QVBoxLayout);
+
+ QLineEdit *lineEdit1 = new QLineEdit;
+ QLineEdit *lineEdit2 = new QLineEdit;
+ view->layout()->addWidget(lineEdit1);
+ view->layout()->addWidget(lineEdit2);
+
+ lineEdit2->setFocus();
+ QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
+
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(view);
+ QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
+
+ mdiArea.show();
+ view->show();
+ qApp->setActiveWindow(&mdiArea);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(lineEdit2));
+}
+
+void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
+{
+ QMdiArea mdiArea;
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ qApp->setActiveWindow(&mdiArea);
+
+ // Add one maximized window.
+ mdiArea.addSubWindow(new QWidget)->showMaximized();
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+
+ // Add few more windows and verify that they are maximized.
+ for (int i = 0; i < 5; ++i) {
+ QMdiSubWindow *window = mdiArea.addSubWindow(new QWidget);
+ window->show();
+ QVERIFY(window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Verify that activated windows still are maximized on activation.
+ QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QVERIFY(window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Restore active window and verify that other windows aren't
+ // maximized on activation.
+ mdiArea.activeSubWindow()->showNormal();
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QVERIFY(!window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Enable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
+ mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ mdiArea.activeSubWindow()->showMaximized();
+ int indexOfMaximized = subWindows.indexOf(mdiArea.activeSubWindow());
+
+ // Verify that windows are not maximized on activation.
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ if (indexOfMaximized != i)
+ QVERIFY(!window->isMaximized());
+ qApp->processEvents();
+ }
+ QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+
+ // Minimize all windows.
+ foreach (QMdiSubWindow *window, subWindows) {
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ qApp->processEvents();
+ }
+
+ // Disable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
+ mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation, false);
+ mdiArea.activeSubWindow()->showMaximized();
+
+ // Verify that minimized windows are maximized on activation.
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QVERIFY(window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Verify that activated windows are maximized after closing
+ // the active window
+ for (int i = 0; i < subWindows.count(); ++i) {
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+ mdiArea.activeSubWindow()->close();
+ qApp->processEvents();
+ }
+
+ QVERIFY(!mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.subWindowList().size(), 0);
+
+ // Verify that new windows are not maximized.
+ mdiArea.addSubWindow(new QWidget)->show();
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(!mdiArea.activeSubWindow()->isMaximized());
+}
+
+void tst_QMdiArea::delayedPlacement()
+{
+ QMdiArea mdiArea;
+
+ QMdiSubWindow *window1 = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+
+ QMdiSubWindow *window2 = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(window2->geometry().topLeft(), QPoint(0, 0));
+
+ QMdiSubWindow *window3 = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(window3->geometry().topLeft(), QPoint(0, 0));
+
+ mdiArea.resize(window3->minimumSizeHint().width() * 3, 400);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+ QCOMPARE(window2->geometry().topLeft(), window1->geometry().topRight() + QPoint(1, 0));
+ QCOMPARE(window3->geometry().topLeft(), window2->geometry().topRight() + QPoint(1, 0));
+}
+
+void tst_QMdiArea::iconGeometryInMenuBar()
+{
+#if !defined (Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QMainWindow mainWindow;
+ QMenuBar *menuBar = mainWindow.menuBar();
+ QMdiArea *mdiArea = new QMdiArea;
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget);
+ mainWindow.setCentralWidget(mdiArea);
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isMaximized());
+
+ QWidget *leftCornerWidget = menuBar->cornerWidget(Qt::TopLeftCorner);
+ QVERIFY(leftCornerWidget);
+ int topMargin = (menuBar->height() - leftCornerWidget->height()) / 2;
+ int leftMargin = qApp->style()->pixelMetric(QStyle::PM_MenuBarHMargin)
+ + qApp->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth);
+ QPoint pos(leftMargin, topMargin);
+ QRect geometry = QStyle::visualRect(qApp->layoutDirection(), menuBar->rect(),
+ QRect(pos, leftCornerWidget->size()));
+ QCOMPARE(leftCornerWidget->geometry(), geometry);
+#endif
+}
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QObject *object, QEvent::Type event)
+ : eventToSpy(event), _count(0)
+ {
+ if (object)
+ object->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+ void clear() { _count = 0; }
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ if (event->type() == eventToSpy)
+ ++_count;
+ return QObject::eventFilter(object, event);
+ }
+
+private:
+ QEvent::Type eventToSpy;
+ int _count;
+};
+
+void tst_QMdiArea::resizeTimer()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWaitForWindowShown(&mdiArea);
+
+#ifndef Q_OS_WINCE
+ int time = 250;
+#else
+ int time = 1000;
+#endif
+
+ QTest::qWait(time);
+
+ EventSpy timerEventSpy(subWindow, QEvent::Timer);
+ QCOMPARE(timerEventSpy.count(), 0);
+
+ mdiArea.tileSubWindows();
+ QTest::qWait(time); // Wait for timer events to occur.
+ QCOMPARE(timerEventSpy.count(), 1);
+ timerEventSpy.clear();
+
+ mdiArea.resize(mdiArea.size() + QSize(2, 2));
+ QTest::qWait(time); // Wait for timer events to occur.
+ QCOMPARE(timerEventSpy.count(), 1);
+ timerEventSpy.clear();
+
+ // Check that timers are killed.
+ QTest::qWait(time); // Wait for timer events to occur.
+ QCOMPARE(timerEventSpy.count(), 0);
+}
+
+void tst_QMdiArea::updateScrollBars()
+{
+ QMdiArea mdiArea;
+ mdiArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ mdiArea.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+
+ QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
+ QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ qApp->processEvents();
+
+ QScrollBar *hbar = mdiArea.horizontalScrollBar();
+ QVERIFY(hbar);
+ QVERIFY(!hbar->isVisible());
+
+ QScrollBar *vbar = mdiArea.verticalScrollBar();
+ QVERIFY(vbar);
+ QVERIFY(!vbar->isVisible());
+
+ // Move sub-window 2 away.
+ subWindow2->move(10000, 10000);
+ qApp->processEvents();
+ QVERIFY(hbar->isVisible());
+ QVERIFY(vbar->isVisible());
+
+ for (int i = 0; i < 2; ++i) {
+ // Maximize sub-window 1 and make sure we don't have any scroll bars.
+ subWindow1->showMaximized();
+ qApp->processEvents();
+ QVERIFY(subWindow1->isMaximized());
+ QVERIFY(!hbar->isVisible());
+ QVERIFY(!vbar->isVisible());
+
+ // We still shouldn't get any scroll bars.
+ mdiArea.resize(mdiArea.size() - QSize(20, 20));
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ qApp->processEvents();
+ QVERIFY(subWindow1->isMaximized());
+ QVERIFY(!hbar->isVisible());
+ QVERIFY(!vbar->isVisible());
+
+ // Restore sub-window 1 and make sure we have scroll bars again.
+ subWindow1->showNormal();
+ qApp->processEvents();
+ QVERIFY(!subWindow1->isMaximized());
+ QVERIFY(hbar->isVisible());
+ QVERIFY(vbar->isVisible());
+ if (i == 0) {
+ // Now, do the same when the viewport is scrolled.
+ hbar->setValue(1000);
+ vbar->setValue(1000);
+ }
+ }
+}
+
+void tst_QMdiArea::setActivationOrder_data()
+{
+ QTest::addColumn<QMdiArea::WindowOrder>("activationOrder");
+ QTest::addColumn<int>("subWindowCount");
+ QTest::addColumn<int>("staysOnTopIndex");
+ QTest::addColumn<int>("firstActiveIndex");
+ QTest::addColumn<QList<int> >("expectedActivationIndices");
+ // The order of expectedCascadeIndices:
+ // window 1 -> (index 0)
+ // window 2 -> (index 1)
+ // window 3 -> (index 2)
+ // ....
+ QTest::addColumn<QList<int> >("expectedCascadeIndices");
+
+ // The order of expectedTileIndices (the same as reading a book LTR).
+ // +--------------------+--------------------+--------------------+
+ // | window 1 (index 0) | window 2 (index 1) | window 3 (index 2) |
+ // | +--------------------+--------------------+
+ // | (index 3) | window 4 (index 4) | window 5 (index 5) |
+ // +--------------------------------------------------------------+
+ QTest::addColumn<QList<int> >("expectedTileIndices");
+
+ QList<int> list;
+ QList<int> list2;
+ QList<int> list3;
+
+ list << 2 << 1 << 0 << 1 << 2 << 3 << 4;
+ list2 << 0 << 1 << 2 << 3 << 4;
+ list3 << 1 << 4 << 3 << 1 << 2 << 0;
+ QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 5 << 3 << 1 << list << list2 << list3;
+
+ list = QList<int>();
+ list << 3 << 1 << 4 << 3 << 1 << 2 << 0;
+ list2 = QList<int>();
+ list2 << 0 << 2 << 4 << 1 << 3;
+ list3 = QList<int>();
+ list3 << 1 << 3 << 4 << 1 << 2 << 0;
+ QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3;
+
+ list = QList<int>();
+ list << 0 << 1 << 0 << 1 << 4 << 3 << 2;
+ list2 = QList<int>();
+ list2 << 0 << 2 << 3 << 4 << 1;
+ list3 = QList<int>();
+ list3 << 1 << 4 << 3 << 1 << 2 << 0;
+ QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 5 << 3 << 1 << list << list2 << list3;
+}
+
+void tst_QMdiArea::setActivationOrder()
+{
+ QFETCH(QMdiArea::WindowOrder, activationOrder);
+ QFETCH(int, subWindowCount);
+ QFETCH(int, staysOnTopIndex);
+ QFETCH(int, firstActiveIndex);
+ QFETCH(QList<int>, expectedActivationIndices);
+ QFETCH(QList<int>, expectedCascadeIndices);
+ QFETCH(QList<int>, expectedTileIndices);
+
+ // Default order.
+ QMdiArea mdiArea;
+ QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder);
+
+ // New order.
+ mdiArea.setActivationOrder(activationOrder);
+ QCOMPARE(mdiArea.activationOrder(), activationOrder);
+
+ QList<QMdiSubWindow *> subWindows;
+ for (int i = 0; i < subWindowCount; ++i)
+ subWindows << mdiArea.addSubWindow(new QPushButton(tr("%1").arg(i)));
+ QCOMPARE(mdiArea.subWindowList(activationOrder), subWindows);
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(i));
+ qApp->processEvents();
+ }
+
+ QMdiSubWindow *staysOnTop = subWindows.at(staysOnTopIndex);
+ staysOnTop->setWindowFlags(staysOnTop->windowFlags() | Qt::WindowStaysOnTopHint);
+ staysOnTop->raise();
+
+ mdiArea.setActiveSubWindow(subWindows.at(firstActiveIndex));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(firstActiveIndex));
+
+ // Verify the actual arrangement/geometry.
+ mdiArea.tileSubWindows();
+ QTest::qWait(100);
+ QVERIFY(verifyArrangement(&mdiArea, Tiled, expectedTileIndices));
+
+ mdiArea.cascadeSubWindows();
+ QVERIFY(verifyArrangement(&mdiArea, Cascaded, expectedCascadeIndices));
+ QTest::qWait(100);
+
+ mdiArea.activateNextSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+ mdiArea.activatePreviousSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+ mdiArea.activatePreviousSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+ for (int i = 0; i < subWindowCount; ++i) {
+ mdiArea.closeActiveSubWindow();
+ qApp->processEvents();
+ if (i == subWindowCount - 1) { // Last window closed.
+ QVERIFY(!mdiArea.activeSubWindow());
+ break;
+ }
+ QVERIFY(mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+ }
+
+ QVERIFY(mdiArea.subWindowList(activationOrder).isEmpty());
+ QVERIFY(expectedActivationIndices.isEmpty());
+}
+
+void tst_QMdiArea::tabBetweenSubWindows()
+{
+ QMdiArea mdiArea;
+ QList<QMdiSubWindow *> subWindows;
+ for (int i = 0; i < 5; ++i)
+ subWindows << mdiArea.addSubWindow(new QLineEdit);
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ qApp->setActiveWindow(&mdiArea);
+ QWidget *focusWidget = subWindows.back()->widget();
+ QCOMPARE(qApp->focusWidget(), focusWidget);
+
+ QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ QCOMPARE(spy.count(), 0);
+
+ // Walk through the entire list of sub windows.
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.back());
+ QCOMPARE(spy.count(), 0);
+
+ mdiArea.setActiveSubWindow(subWindows.front());
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
+ spy.clear();
+
+ // Walk through the entire list of sub windows in the opposite direction (Ctrl-Shift-Tab).
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea, -1, true));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
+ QCOMPARE(spy.count(), 0);
+
+ // Ctrl-Tab-Tab-Tab
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 3));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
+ QCOMPARE(spy.count(), 1);
+
+ mdiArea.setActiveSubWindow(subWindows.at(1));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(1));
+ spy.clear();
+
+ // Quick switch (Ctrl-Tab once) -> switch back to the previously active sub-window.
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 1));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QMdiArea::setViewMode()
+{
+ QMdiArea mdiArea;
+
+ QPixmap iconPixmap(16, 16);
+ iconPixmap.fill(Qt::red);
+ for (int i = 0; i < 5; ++i) {
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+ subWindow->setWindowTitle(QString(QLatin1String("Title %1")).arg(i));
+ subWindow->setWindowIcon(iconPixmap);
+ }
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow();
+ const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+
+ // Default.
+ QVERIFY(!activeSubWindow->isMaximized());
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
+
+ // Tabbed view.
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ QCOMPARE(mdiArea.viewMode(), QMdiArea::TabbedView);
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+ QVERIFY(tabBar->isVisible());
+
+ QCOMPARE(tabBar->count(), subWindows.count());
+ QVERIFY(activeSubWindow->isMaximized());
+ QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
+
+ // Check that tabIcon and tabText are set properly.
+ for (int i = 0; i < subWindows.size(); ++i) {
+ QMdiSubWindow *subWindow = subWindows.at(i);
+ QCOMPARE(tabBar->tabText(i), subWindow->windowTitle());
+ QCOMPARE(tabBar->tabIcon(i), subWindow->windowIcon());
+ }
+
+ // Check that tabText and tabIcon are updated.
+ activeSubWindow->setWindowTitle(QLatin1String("Dude, I want another window title"));
+ QCOMPARE(tabBar->tabText(tabBar->currentIndex()), activeSubWindow->windowTitle());
+ iconPixmap.fill(Qt::green);
+ activeSubWindow->setWindowIcon(iconPixmap);
+ QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), activeSubWindow->windowIcon());
+
+ // If there's an empty window title, tabText should return "(Untitled)" (as in firefox).
+ activeSubWindow->setWindowTitle(QString());
+ QCOMPARE(tabBar->tabText(tabBar->currentIndex()), QLatin1String("(Untitled)"));
+
+ // If there's no window icon, tabIcon should return ... an empty icon :)
+ activeSubWindow->setWindowIcon(QIcon());
+ QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), QIcon());
+
+ // Check that the current tab changes when activating another sub-window.
+ for (int i = 0; i < subWindows.size(); ++i) {
+ mdiArea.activateNextSubWindow();
+ activeSubWindow = mdiArea.activeSubWindow();
+ QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
+ }
+
+ activeSubWindow = mdiArea.activeSubWindow();
+ const int tabIndex = tabBar->currentIndex();
+
+ // The current tab should not change when the sub-window is hidden.
+ activeSubWindow->hide();
+ QCOMPARE(tabBar->currentIndex(), tabIndex);
+ activeSubWindow->show();
+ QCOMPARE(tabBar->currentIndex(), tabIndex);
+
+ // Disable the tab when the sub-window is hidden and another sub-window is activated.
+ activeSubWindow->hide();
+ mdiArea.activateNextSubWindow();
+ QVERIFY(tabBar->currentIndex() != tabIndex);
+ QVERIFY(!tabBar->isTabEnabled(tabIndex));
+
+ // Enable it again.
+ activeSubWindow->show();
+ QCOMPARE(tabBar->currentIndex(), tabIndex);
+ QVERIFY(tabBar->isTabEnabled(tabIndex));
+
+ // Remove sub-windows and make sure the tab is removed.
+ foreach (QMdiSubWindow *subWindow, subWindows) {
+ if (subWindow != activeSubWindow)
+ mdiArea.removeSubWindow(subWindow);
+ }
+ QCOMPARE(tabBar->count(), 1);
+
+ // Go back to default (QMdiArea::SubWindowView).
+ mdiArea.setViewMode(QMdiArea::SubWindowView);
+ QVERIFY(!activeSubWindow->isMaximized());
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
+}
+
+void tst_QMdiArea::setTabsClosable()
+{
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+
+ // test default
+ QCOMPARE(mdiArea.tabsClosable(), false);
+
+ // change value before tab bar exists
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ mdiArea.setTabsClosable(true);
+ QCOMPARE(mdiArea.tabsClosable(), true);
+
+ // force tab bar creation
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+
+ // value must've been propagated
+ QCOMPARE(tabBar->tabsClosable(), true);
+
+ // change value when tab bar exists
+ mdiArea.setTabsClosable(false);
+ QCOMPARE(mdiArea.tabsClosable(), false);
+ QCOMPARE(tabBar->tabsClosable(), false);
+}
+
+void tst_QMdiArea::setTabsMovable()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
+ QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
+ QMdiSubWindow *subWindow3 = mdiArea.addSubWindow(new QWidget);
+
+ // test default
+ QCOMPARE(mdiArea.tabsMovable(), false);
+
+ // change value before tab bar exists
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ mdiArea.setTabsMovable(true);
+ QCOMPARE(mdiArea.tabsMovable(), true);
+
+ // force tab bar creation
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+
+ // value must've been propagated
+ QCOMPARE(tabBar->isMovable(), true);
+
+ // test tab moving
+ QList<QMdiSubWindow *> subWindows;
+ subWindows << subWindow1 << subWindow2 << subWindow3;
+ QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows);
+ tabBar->moveTab(1, 2); // 1,3,2
+ subWindows.clear();
+ subWindows << subWindow1 << subWindow3 << subWindow2;
+ QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows);
+ tabBar->moveTab(0, 2); // 3,2,1
+ subWindows.clear();
+ subWindows << subWindow3 << subWindow2 << subWindow1;
+ QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows);
+
+ // change value when tab bar exists
+ mdiArea.setTabsMovable(false);
+ QCOMPARE(mdiArea.tabsMovable(), false);
+ QCOMPARE(tabBar->isMovable(), false);
+}
+
+void tst_QMdiArea::setTabShape()
+{
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // Default.
+ QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
+
+ // Triangular.
+ mdiArea.setTabShape(QTabWidget::Triangular);
+ QCOMPARE(mdiArea.tabShape(), QTabWidget::Triangular);
+
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+ QCOMPARE(tabBar->shape(), QTabBar::TriangularNorth);
+
+ // Back to default (Rounded).
+ mdiArea.setTabShape(QTabWidget::Rounded);
+ QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
+ QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
+}
+
+void tst_QMdiArea::setTabPosition_data()
+{
+ QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
+ QTest::addColumn<bool>("hasLeftMargin");
+ QTest::addColumn<bool>("hasTopMargin");
+ QTest::addColumn<bool>("hasRightMargin");
+ QTest::addColumn<bool>("hasBottomMargin");
+
+ QTest::newRow("North") << QTabWidget::North << false << true << false << false;
+ QTest::newRow("South") << QTabWidget::South << false << false << false << true;
+ QTest::newRow("East") << QTabWidget::East << false << false << true << false;
+ QTest::newRow("West") << QTabWidget::West << true << false << false << false;
+}
+
+void tst_QMdiArea::setTabPosition()
+{
+ QFETCH(QTabWidget::TabPosition, tabPosition);
+ QFETCH(bool, hasLeftMargin);
+ QFETCH(bool, hasTopMargin);
+ QFETCH(bool, hasRightMargin);
+ QFETCH(bool, hasBottomMargin);
+
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // Make sure there are no margins.
+ mdiArea.setContentsMargins(0, 0, 0, 0);
+
+ // Default.
+ QCOMPARE(mdiArea.tabPosition(), QTabWidget::North);
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+ QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
+
+ // New position.
+ mdiArea.setTabPosition(tabPosition);
+ QCOMPARE(mdiArea.tabPosition(), tabPosition);
+ QCOMPARE(tabBar->shape(), tabBarShapeFrom(QTabWidget::Rounded, tabPosition));
+
+ const Qt::LayoutDirection originalLayoutDirection = qApp->layoutDirection();
+
+ // Check that we have correct geometry in both RightToLeft and LeftToRight.
+ for (int i = 0; i < 2; ++i) {
+ // Check viewportMargins.
+ const QRect viewportGeometry = mdiArea.viewport()->geometry();
+ const int left = viewportGeometry.left();
+ const int top = viewportGeometry.y();
+ const int right = mdiArea.width() - viewportGeometry.width();
+ const int bottom = mdiArea.height() - viewportGeometry.height();
+
+ const QSize sizeHint = tabBar->sizeHint();
+
+ if (hasLeftMargin)
+ QCOMPARE(qApp->isLeftToRight() ? left : right, sizeHint.width());
+ if (hasRightMargin)
+ QCOMPARE(qApp->isLeftToRight() ? right : left, sizeHint.width());
+ if (hasTopMargin || hasBottomMargin)
+ QCOMPARE(hasTopMargin ? top : bottom, sizeHint.height());
+
+ // Check actual tab bar geometry.
+ const QRegion expectedTabBarGeometry = QRegion(mdiArea.rect()).subtracted(viewportGeometry);
+ QVERIFY(!expectedTabBarGeometry.isEmpty());
+ QCOMPARE(QRegion(tabBar->geometry()), expectedTabBarGeometry);
+
+ if (i == 0)
+ qApp->setLayoutDirection(originalLayoutDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight);
+ qApp->processEvents();
+ }
+
+ qApp->setLayoutDirection(originalLayoutDirection);
+}
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+void tst_QMdiArea::nativeSubWindows()
+{
+ { // Add native widgets after show.
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // No native widgets.
+ QVERIFY(!mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(!subWindow->internalWinId());
+
+ QWidget *nativeWidget = new QWidget;
+ QVERIFY(nativeWidget->winId()); // enforce native window.
+ mdiArea.addSubWindow(nativeWidget);
+
+ // The viewport and all the sub-windows must be native.
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+
+ // Add a non-native widget. This should become native.
+ QMdiSubWindow *subWindow = new QMdiSubWindow;
+ subWindow->setWidget(new QWidget);
+ QVERIFY(!subWindow->internalWinId());
+ mdiArea.addSubWindow(subWindow);
+ QVERIFY(subWindow->internalWinId());
+ }
+
+ { // Add native widgets before show.
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ QWidget *nativeWidget = new QWidget;
+ (void)nativeWidget->winId();
+ mdiArea.addSubWindow(nativeWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // The viewport and all the sub-windows must be native.
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+ }
+
+ { // Make a sub-window native *after* it's added to the area.
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QMdiSubWindow *nativeSubWindow = mdiArea.subWindowList().last();
+ QVERIFY(!nativeSubWindow->internalWinId());
+ (void)nativeSubWindow->winId();
+
+ // All the sub-windows should be native at this point
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+ }
+
+#ifndef QT_NO_OPENGL
+ {
+ if (!QGLFormat::hasOpenGL())
+ QSKIP("QGL not supported on this platform", SkipAll);
+
+ QMdiArea mdiArea;
+ QGLWidget *glViewport = new QGLWidget;
+ mdiArea.setViewport(glViewport);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ const QGLContext *context = glViewport->context();
+ if (!context || !context->isValid())
+ QSKIP("QGL is broken, cannot continue test", SkipAll);
+
+ // The viewport and all the sub-windows must be native.
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+ }
+#endif
+}
+#endif
+
+void tst_QMdiArea::task_209615()
+{
+ QTabWidget tabWidget;
+ QMdiArea *mdiArea1 = new QMdiArea;
+ QMdiArea *mdiArea2 = new QMdiArea;
+ QMdiSubWindow *subWindow = mdiArea1->addSubWindow(new QLineEdit);
+
+ tabWidget.addTab(mdiArea1, QLatin1String("1"));
+ tabWidget.addTab(mdiArea2, QLatin1String("2"));
+ tabWidget.show();
+
+ mdiArea1->removeSubWindow(subWindow);
+ mdiArea2->addSubWindow(subWindow);
+
+ // Please do not assert/crash.
+ tabWidget.setCurrentIndex(1);
+}
+
+void tst_QMdiArea::task_236750()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
+ mdiArea.show();
+
+ subWindow->setWindowFlags(subWindow->windowFlags() | Qt::FramelessWindowHint);
+ // Please do not crash (floating point exception).
+ subWindow->showMinimized();
+}
+
+QTEST_MAIN(tst_QMdiArea)
+#include "tst_qmdiarea.moc"
+
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/.gitignore b/tests/auto/widgets/widgets/qmdisubwindow/.gitignore
new file mode 100644
index 0000000000..f83a9b0895
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmdisubwindow/.gitignore
@@ -0,0 +1 @@
+tst_qmdisubwindow
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro b/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro
new file mode 100644
index 0000000000..5c5bd525df
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+QT += widgets
+INCLUDEPATH += .
+SOURCES += tst_qmdisubwindow.cpp
+DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
+
+
+mac*:CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
new file mode 100644
index 0000000000..f7593336e1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
@@ -0,0 +1,2032 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include "qmdisubwindow.h"
+#include "qmdiarea.h"
+
+#include <QLayout>
+#include <QLineEdit>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QMenu>
+#include <QGroupBox>
+#include <QTextEdit>
+#include <QLayout>
+#include <QHBoxLayout>
+#include <QByteArray>
+#include <QStyle>
+#include <QStyleOptionTitleBar>
+#include <QPushButton>
+#include <QSizeGrip>
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+#include <QMacStyle>
+#endif
+
+QT_BEGIN_NAMESPACE
+#if defined(Q_WS_X11)
+extern void qt_x11_wait_for_window_manager(QWidget *w);
+#endif
+#if !defined(Q_WS_WIN)
+extern bool qt_tab_all_widgets;
+#endif
+QT_END_NAMESPACE
+
+static inline bool tabAllWidgets()
+{
+#if !defined(Q_OS_WIN)
+ if (qApp->style()->inherits("QMacStyle"))
+ return qt_tab_all_widgets;
+#endif
+ return true;
+}
+
+static inline void triggerSignal(QMdiSubWindow *window, QMdiArea *workspace,
+ const QByteArray &signal)
+{
+ if (signal == SIGNAL(windowMaximized())) {
+ window->showMaximized();
+ qApp->processEvents();
+ if (window->parent())
+ QVERIFY(window->isMaximized());
+ } else if (signal == SIGNAL(windowMinimized())) {
+ window->showMinimized();
+ qApp->processEvents();
+ if (window->parent())
+ QVERIFY(window->isMinimized());
+ } else if (signal == SIGNAL(windowRestored())) {
+ window->showMaximized();
+ qApp->processEvents();
+ window->showNormal();
+ qApp->processEvents();
+ QVERIFY(!window->isMinimized());
+ QVERIFY(!window->isMaximized());
+ QVERIFY(!window->isShaded());
+ } else if (signal == SIGNAL(aboutToActivate())) {
+ if (window->parent()) {
+ workspace->setActiveSubWindow(window);
+ qApp->processEvents();
+ }
+ } else if (signal == SIGNAL(windowActivated())) {
+ if (window->parent()) {
+ workspace->setActiveSubWindow(window);
+ qApp->processEvents();
+ }
+ } else if (signal == SIGNAL(windowDeactivated())) {
+ if (!window->parent())
+ return;
+ workspace->setActiveSubWindow(window);
+ qApp->processEvents();
+ workspace->setActiveSubWindow(0);
+ qApp->processEvents();
+ }
+}
+
+// --- from tst_qgraphicsview.cpp ---
+static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseButtonPress, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseButtonRelease, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+// ---
+
+static void sendMouseDoubleClick(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ sendMousePress(widget, point, button);
+ sendMouseRelease(widget, point, button);
+ QMouseEvent event(QEvent::MouseButtonDblClick, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+static const Qt::WindowFlags StandardWindowFlags
+ = Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint;
+static const Qt::WindowFlags DialogWindowFlags
+ = Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
+
+Q_DECLARE_METATYPE(Qt::WindowState);
+Q_DECLARE_METATYPE(Qt::WindowStates);
+Q_DECLARE_METATYPE(Qt::WindowType);
+Q_DECLARE_METATYPE(Qt::WindowFlags);
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QMdiSubWindow : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void sizeHint();
+ void minimumSizeHint();
+ void minimumSize();
+ void setWidget();
+ void setWindowState_data();
+ void setWindowState();
+ void mainWindowSupport();
+ void emittingOfSignals_data();
+ void emittingOfSignals();
+ void showShaded();
+ void showNormal_data();
+ void showNormal();
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE_WM)
+ void setOpaqueResizeAndMove_data();
+ void setOpaqueResizeAndMove();
+#endif
+ void setWindowFlags_data();
+ void setWindowFlags();
+ void mouseDoubleClick();
+ void setSystemMenu();
+ void restoreFocus();
+ void changeFocusWithTab();
+ void closeEvent();
+ void setWindowTitle();
+ void resizeEvents_data();
+ void resizeEvents();
+#if defined(Q_WS_MAC)
+ void defaultSizeGrip();
+#endif
+ void hideAndShow();
+ void keepWindowMaximizedState();
+ void explicitlyHiddenWidget();
+ void resizeTimer();
+ void fixedMinMaxSize();
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ void replaceMenuBarWhileMaximized();
+ void closeOnDoubleClick();
+#endif
+ void setFont();
+ void task_188849();
+ void mdiArea();
+ void task_182852();
+ void task_233197();
+ void task_226929();
+};
+
+void tst_QMdiSubWindow::initTestCase()
+{
+ qRegisterMetaType<Qt::WindowStates>("Qt::WindowStates");
+}
+
+void tst_QMdiSubWindow::sizeHint()
+{
+ QMdiSubWindow *window = new QMdiSubWindow;
+ QCOMPARE(window->sizeHint(), window->minimumSizeHint());
+ window->show();
+ QCOMPARE(window->sizeHint(), window->minimumSizeHint());
+ QMdiArea workspace;
+ workspace.addSubWindow(window);
+ QCOMPARE(window->sizeHint(), window->minimumSizeHint());
+}
+
+void tst_QMdiSubWindow::minimumSizeHint()
+{
+ QMdiSubWindow window;
+ window.show();
+
+ QCOMPARE(window.minimumSizeHint(), qApp->globalStrut());
+
+ window.setWidget(new QWidget);
+ QCOMPARE(window.minimumSizeHint(), window.layout()->minimumSize()
+ .expandedTo(qApp->globalStrut()));
+
+ delete window.widget();
+ delete window.layout();
+ window.setWidget(new QWidget);
+ QCOMPARE(window.minimumSizeHint(), qApp->globalStrut());
+
+ window.widget()->show();
+ QCOMPARE(window.minimumSizeHint(), window.widget()->minimumSizeHint()
+ .expandedTo(qApp->globalStrut()));
+}
+
+void tst_QMdiSubWindow::minimumSize()
+{
+ QMdiArea mdiArea;
+ mdiArea.resize(200, 200);
+
+ // Check that we respect the minimum size set on the sub-window itself.
+ QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
+ subWindow1->setMinimumSize(1000, 1000);
+ mdiArea.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QCOMPARE(subWindow1->size(), QSize(1000, 1000));
+
+ // Check that we respect the minimum size set on the internal widget.
+ QWidget *widget = new QWidget;
+ widget->setMinimumSize(1000, 1000);
+ QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(widget);
+ QVERIFY(subWindow2->size() != mdiArea.viewport()->size());
+ QCOMPARE(subWindow2->size(), subWindow2->minimumSizeHint());
+}
+
+void tst_QMdiSubWindow::setWidget()
+{
+ QMdiSubWindow window;
+ window.show();
+ QVERIFY(window.layout());
+ QVERIFY(!window.widget());
+
+ // QPointer so we can check if the widget is deleted
+ QPointer<QWidget> widget = new QWidget;
+ widget->setWindowTitle(QString::fromLatin1("DummyTitle"));
+ QCOMPARE(widget->windowTitle(), QString::fromLatin1("DummyTitle"));
+ window.setWidget(widget);
+ QCOMPARE(window.windowTitle(), window.widget()->windowTitle());
+ QCOMPARE(widget->parentWidget(), static_cast<QWidget *>(&window));
+ QVERIFY(!widget->isVisible());
+ QCOMPARE(window.layout()->count(), 1);
+
+ QTest::ignoreMessage(QtWarningMsg,"QMdiSubWindow::setWidget: widget is already set");
+ window.setWidget(widget);
+ QCOMPARE(window.widget(), static_cast<QWidget *>(widget));
+ QCOMPARE(widget->parentWidget(), static_cast<QWidget *>(&window));
+
+ window.setWidget(0);
+ QVERIFY(widget);
+ QVERIFY(!widget->parent());
+ QVERIFY(!window.widget());
+ QCOMPARE(window.layout()->count(), 0);
+
+ window.setWidget(widget);
+ delete window.layout();
+ QVERIFY(!window.layout());
+ QVERIFY(window.widget());
+ QCOMPARE(window.widget()->parentWidget(), static_cast<QWidget *>(&window));
+
+ delete window.widget();
+ QVERIFY(!widget);
+ QVERIFY(!window.widget());
+}
+
+void tst_QMdiSubWindow::setWindowState_data()
+{
+ QTest::addColumn<Qt::WindowState>("windowState");
+
+ QTest::newRow("maximized") << Qt::WindowMaximized;
+ QTest::newRow("minimized") << Qt::WindowMinimized;
+ QTest::newRow("normalized") << Qt::WindowNoState;
+}
+
+void tst_QMdiSubWindow::setWindowState()
+{
+ QFETCH(Qt::WindowState, windowState);
+ QMdiArea workspace;
+ QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QLineEdit));
+ window->show();
+ workspace.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ QWidget *testWidget = 0;
+ for (int iteration = 0; iteration < 2; ++iteration) {
+ if (iteration == 0)
+ testWidget = window;
+ else
+ testWidget = window->widget();
+
+ testWidget->setWindowState(windowState);
+
+ Qt::WindowStates windowStateWindow = window->windowState();
+ windowStateWindow &= ~Qt::WindowActive;
+ Qt::WindowStates windowStateWidget = window->widget()->windowState();
+ windowStateWidget &= ~Qt::WindowActive;
+ QCOMPARE(windowStateWindow, windowStateWidget);
+
+ switch (windowState) {
+ case Qt::WindowNoState:
+ QVERIFY(!window->widget()->isMinimized());
+ QVERIFY(!window->widget()->isMaximized());
+ QVERIFY(!window->isMinimized());
+ QVERIFY(!window->isMaximized());
+ break;
+ case Qt::WindowMinimized:
+ QVERIFY(window->widget()->isMinimized());
+ QVERIFY(window->isMinimized());
+ break;
+ case Qt::WindowMaximized:
+ QVERIFY(window->widget()->isMaximized());
+ QVERIFY(window->isMaximized());
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void tst_QMdiSubWindow::mainWindowSupport()
+{
+ QList<QMdiSubWindow *> windows;
+ QMdiArea *workspace = new QMdiArea;
+ QMainWindow mainWindow;
+ mainWindow.setCentralWidget(workspace);
+ mainWindow.show();
+ mainWindow.menuBar()->setVisible(true);
+ qApp->setActiveWindow(&mainWindow);
+
+ // QMainWindow's window title is empty
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ {
+ QCOMPARE(mainWindow.windowTitle(), QString());
+ QMdiSubWindow *window = workspace->addSubWindow(new QPushButton(QLatin1String("Test")));
+ QString expectedTitle = QLatin1String("MainWindow's title is empty");
+ window->setWindowTitle(expectedTitle);
+ QCOMPARE(window->windowTitle(), expectedTitle);
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ QCOMPARE(window->windowTitle(), expectedTitle);
+ QCOMPARE(mainWindow.windowTitle(), expectedTitle);
+ window->showNormal();
+ QCOMPARE(window->windowTitle(), expectedTitle);
+ QCOMPARE(mainWindow.windowTitle(), QString());
+ window->close();
+ }
+#endif
+
+ QString originalWindowTitle = QString::fromLatin1("MainWindow");
+ mainWindow.setWindowTitle(originalWindowTitle);
+
+ for (int i = 0; i < 5; ++i) {
+ mainWindow.menuBar()->setVisible(false);
+
+ QMdiSubWindow *window = new QMdiSubWindow;
+ windows.append(window);
+ QVERIFY(!window->maximizedButtonsWidget());
+ QVERIFY(!window->maximizedSystemMenuIconWidget());
+
+ QMdiArea *nestedWorkspace = new QMdiArea; // :-)
+ window->setWidget(nestedWorkspace);
+ window->widget()->setWindowTitle(QString::fromLatin1("Window %1").arg(i));
+
+ workspace->addSubWindow(window);
+ QVERIFY(!window->maximizedButtonsWidget());
+ QVERIFY(!window->maximizedSystemMenuIconWidget());
+ window->show();
+
+ // mainWindow.menuBar() is not visible
+ window->showMaximized();
+ qApp->processEvents();
+ QVERIFY(window->isMaximized());
+ QVERIFY(!window->maximizedButtonsWidget());
+ QVERIFY(!window->maximizedSystemMenuIconWidget());
+ window->showNormal();
+
+ // Now it is
+ mainWindow.menuBar()->setVisible(true);
+
+ window->showMaximized();
+ qApp->processEvents();
+ QVERIFY(window->isMaximized());
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QVERIFY(window->maximizedButtonsWidget());
+ QCOMPARE(window->maximizedButtonsWidget(), mainWindow.menuBar()->cornerWidget(Qt::TopRightCorner));
+ QVERIFY(window->maximizedSystemMenuIconWidget());
+ QCOMPARE(window->maximizedSystemMenuIconWidget(), qobject_cast<QWidget *>(mainWindow.menuBar()
+ ->cornerWidget(Qt::TopLeftCorner)));
+ QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]")
+ .arg(originalWindowTitle, window->widget()->windowTitle()));
+#endif
+
+ // Check that nested child windows don't set window title
+ nestedWorkspace->show();
+ QMdiSubWindow *nestedWindow = new QMdiSubWindow;
+ nestedWindow->setWidget(new QWidget);
+ nestedWorkspace->addSubWindow(nestedWindow);
+ nestedWindow->widget()->setWindowTitle(QString::fromLatin1("NestedWindow %1").arg(i));
+ nestedWindow->showMaximized();
+ qApp->processEvents();
+ QVERIFY(nestedWindow->isMaximized());
+ QVERIFY(!nestedWindow->maximizedButtonsWidget());
+ QVERIFY(!nestedWindow->maximizedSystemMenuIconWidget());
+
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]")
+ .arg(originalWindowTitle, window->widget()->windowTitle()));
+#endif
+ }
+
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+ return;
+#endif
+
+ workspace->activateNextSubWindow();
+ qApp->processEvents();
+ foreach (QMdiSubWindow *window, windows) {
+ QCOMPARE(workspace->activeSubWindow(), window);
+ QVERIFY(window->isMaximized());
+ QVERIFY(window->maximizedButtonsWidget());
+ QCOMPARE(window->maximizedButtonsWidget(), mainWindow.menuBar()->cornerWidget(Qt::TopRightCorner));
+ QVERIFY(window->maximizedSystemMenuIconWidget());
+ QCOMPARE(window->maximizedSystemMenuIconWidget(), qobject_cast<QWidget *>(mainWindow.menuBar()
+ ->cornerWidget(Qt::TopLeftCorner)));
+ QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]")
+ .arg(originalWindowTitle, window->widget()->windowTitle()));
+ workspace->activateNextSubWindow();
+ qApp->processEvents();
+ }
+}
+
+// This test was written when QMdiSubWindow emitted separate signals
+void tst_QMdiSubWindow::emittingOfSignals_data()
+{
+ QTest::addColumn<QByteArray>("signal");
+ QTest::addColumn<Qt::WindowState>("watchedState");
+
+ QTest::newRow("windowMaximized") << QByteArray(SIGNAL(windowMaximized())) << Qt::WindowMaximized;
+ QTest::newRow("windowMinimized") << QByteArray(SIGNAL(windowMinimized())) << Qt::WindowMinimized;
+ QTest::newRow("windowRestored") << QByteArray(SIGNAL(windowRestored())) << Qt::WindowNoState;
+ QTest::newRow("aboutToActivate") << QByteArray(SIGNAL(aboutToActivate())) << Qt::WindowNoState;
+ QTest::newRow("windowActivated") << QByteArray(SIGNAL(windowActivated())) << Qt::WindowActive;
+ QTest::newRow("windowDeactivated") << QByteArray(SIGNAL(windowDeactivated())) << Qt::WindowActive;
+}
+
+void tst_QMdiSubWindow::emittingOfSignals()
+{
+ QFETCH(QByteArray, signal);
+ QFETCH(Qt::WindowState, watchedState);
+ QMdiArea workspace;
+ workspace.show();
+ qApp->processEvents();
+ qApp->setActiveWindow(&workspace);
+ QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ qApp->processEvents();
+ window->show();
+ if (signal != SIGNAL(windowRestored()))
+ workspace.setActiveSubWindow(0);
+ qApp->processEvents();
+
+ QSignalSpy spy(window, signal == SIGNAL(aboutToActivate())
+ ? signal.data()
+ : SIGNAL(windowStateChanged(Qt::WindowStates, Qt::WindowStates)));
+ QVERIFY(spy.isEmpty());
+ triggerSignal(window, &workspace, signal);
+ // Unless the signal is windowRestored or windowDeactivated,
+ // we're already in correct state and nothing should happen.
+ if (signal != SIGNAL(windowRestored()) && signal != SIGNAL(windowDeactivated()))
+ triggerSignal(window, &workspace, signal);
+
+ int count = 0;
+ if (signal == SIGNAL(aboutToActivate())) {
+ count += spy.count();
+ } else {
+ for (int i = 0; i < spy.count(); ++i) {
+ Qt::WindowStates oldState = qvariant_cast<Qt::WindowStates>(spy.at(i).at(0));
+ Qt::WindowStates newState = qvariant_cast<Qt::WindowStates>(spy.at(i).at(1));
+ if (watchedState != Qt::WindowNoState) {
+ if (!(oldState & watchedState) && (newState & watchedState))
+ ++count;
+ } else {
+ if ((oldState & (Qt::WindowMinimized | Qt::WindowMaximized))
+ && (newState & (watchedState | Qt::WindowActive))) {
+ ++count;
+ }
+ }
+ }
+ }
+ QCOMPARE(count, 1);
+
+ window->setParent(0);
+ window->showNormal();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(window);
+#endif
+ qApp->processEvents();
+
+ spy.clear();
+ triggerSignal(window, &workspace, signal);
+ QCOMPARE(spy.count(), 0);
+
+ delete window;
+ window = 0;
+}
+
+void tst_QMdiSubWindow::showShaded()
+{
+ QMdiArea workspace;
+ QMdiSubWindow *window = workspace.addSubWindow(new QLineEdit);
+ window->resize(300, 300);
+ qApp->processEvents();
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ QVERIFY(!window->isShaded());
+ QVERIFY(!window->isMaximized());
+
+ QCOMPARE(window->size(), QSize(300, 300));
+ QRect restoreGeometry = window->geometry();
+ window->showShaded();
+ QVERIFY(window->isShaded());
+ QVERIFY(window->isMinimized());
+
+ window->showNormal();
+ QVERIFY(!window->isShaded());
+ QVERIFY(!window->isMinimized());
+ QCOMPARE(window->geometry(), restoreGeometry);
+ window->showShaded();
+
+ window->showNormal();
+ QVERIFY(!window->isShaded());
+ QVERIFY(!window->isMinimized());
+ QCOMPARE(window->geometry(), restoreGeometry);
+ window->showMinimized();
+ window->showMaximized();
+ window->showShaded();
+ QCOMPARE(window->width(), workspace.contentsRect().width());
+ window->showNormal();
+ QCOMPARE(window->geometry(), workspace.contentsRect());
+
+ window->resize(300, 300);
+ QCOMPARE(window->size(), QSize(300, 300));
+ window->showShaded();
+ window->showNormal();
+ QTest::qWait(250);
+
+#ifdef Q_OS_WINCE
+ QSKIP("Until we have a QEvent::WindowFlagsChange event, this will skip", SkipAll);
+#endif
+
+ const QSize minimumSizeHint = window->minimumSizeHint();
+ QVERIFY(minimumSizeHint.height() < 300);
+ const int maxHeightDiff = 300 - minimumSizeHint.height();
+
+ // Calculate mouse position for bottom right corner and simulate a
+ // vertical resize with the mouse.
+ int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2;
+ QPoint mousePosition(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2));
+ QWidget *mouseReceiver = 0;
+#ifdef Q_WS_MAC
+ if (qobject_cast<QMacStyle*>(window->style()))
+ mouseReceiver = qFindChild<QSizeGrip *>(window);
+ else
+#endif
+ mouseReceiver = window;
+ QVERIFY(mouseReceiver);
+ sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton);
+ sendMousePress(mouseReceiver, mousePosition);
+
+ for (int i = 0; i < maxHeightDiff + 20; ++i) {
+ --mousePosition.ry();
+ sendMouseMove(mouseReceiver, mousePosition);
+ }
+
+ sendMouseRelease(mouseReceiver, mousePosition);
+ // Make sure we respect the minimumSizeHint!
+ QCOMPARE(window->height(), minimumSizeHint.height());
+
+ window->showShaded();
+ window->setParent(0);
+ window->show();
+ QVERIFY(!window->isShaded());
+
+ delete window;
+}
+
+void tst_QMdiSubWindow::showNormal_data()
+{
+ QTest::addColumn<QByteArray>("slot");
+
+ QTest::newRow("showMinimized") << QByteArray("showMinimized");
+ QTest::newRow("showMaximized") << QByteArray("showMaximized");
+ QTest::newRow("showShaded") << QByteArray("showShaded");
+}
+
+void tst_QMdiSubWindow::showNormal()
+{
+ QFETCH(QByteArray, slot);
+
+ QMdiArea workspace;
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ workspace.show();
+ window->show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ QRect originalGeometry = window->geometry();
+ QVERIFY(QMetaObject::invokeMethod(window, slot.data()));
+ qApp->processEvents();
+ window->showNormal();
+ qApp->processEvents();
+ QCOMPARE(window->geometry(), originalGeometry);
+}
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QObject *object, QEvent::Type event)
+ : eventToSpy(event), _count(0)
+ {
+ if (object)
+ object->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+ void clear() { _count = 0; }
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ if (event->type() == eventToSpy)
+ ++_count;
+ return QObject::eventFilter(object, event);
+ }
+
+private:
+ QEvent::Type eventToSpy;
+ int _count;
+};
+
+// This test requires cursor support, which is absent on WinCE
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE_WM)
+void tst_QMdiSubWindow::setOpaqueResizeAndMove_data()
+{
+ QTest::addColumn<bool>("opaqueMode");
+ QTest::addColumn<int>("geometryCount");
+ QTest::addColumn<int>("expectedGeometryCount");
+ QTest::addColumn<QSize>("workspaceSize");
+ QTest::addColumn<QSize>("windowSize");
+
+ QTest::newRow("normal mode") << true<< 20 << 20 << QSize(400, 400) << QSize(200, 200);
+ QTest::newRow("rubberband mode") << false << 20 << 1 << QSize(400, 400) << QSize(200, 200);
+}
+
+void tst_QMdiSubWindow::setOpaqueResizeAndMove()
+{
+ QFETCH(bool, opaqueMode);
+ QFETCH(int, geometryCount);
+ QFETCH(int, expectedGeometryCount);
+ QFETCH(QSize, workspaceSize);
+ QFETCH(QSize, windowSize);
+
+ QMdiArea workspace;
+ QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ qApp->processEvents();
+ workspace.resize(workspaceSize);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ QWidget *mouseReceiver = 0;
+ if (window->style()->inherits("QMacStyle"))
+ mouseReceiver = qFindChild<QSizeGrip *>(window);
+ else
+ mouseReceiver = window;
+ QVERIFY(mouseReceiver);
+
+ // ----------------------------- resize -----------------------------
+ {
+ // setOpaqueResize
+ window->setOption(QMdiSubWindow::RubberBandResize, !opaqueMode);
+ QCOMPARE(window->testOption(QMdiSubWindow::RubberBandResize), !opaqueMode);
+
+ // Check that the event spy actually works
+ EventSpy resizeSpy(window, QEvent::Resize);
+ QCOMPARE(resizeSpy.count(), 0);
+ window->resize(windowSize);
+ QCOMPARE(window->size(), windowSize);
+ QCOMPARE(resizeSpy.count(), 1);
+ resizeSpy.clear();
+ QCOMPARE(resizeSpy.count(), 0);
+
+ QTest::qWait(250); // delayed update of dirty regions
+
+ // Enter resize mode.
+ int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2;
+ QPoint mousePosition(mouseReceiver->width() - qMax(offset, 2), mouseReceiver->height() - qMax(offset, 2));
+ sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton);
+ sendMousePress(mouseReceiver, mousePosition);
+
+ // The window itself is the grabber in rubberband mode
+ if (!opaqueMode) {
+ mouseReceiver = window;
+ mousePosition = QPoint(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2));
+ }
+
+ // Trigger resize events
+ for (int i = 0; i < geometryCount; ++i) {
+ if (mouseReceiver == window) {
+ ++mousePosition.rx();
+ ++mousePosition.ry();
+ sendMouseMove(mouseReceiver, mousePosition);
+ } else {
+ sendMouseMove(mouseReceiver, mousePosition + QPoint(1, 1));
+ }
+ }
+
+ // Leave resize mode
+ sendMouseRelease(mouseReceiver, mousePosition);
+ QCOMPARE(resizeSpy.count(), expectedGeometryCount);
+ QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount));
+ }
+
+ // ------------------------------ move ------------------------------
+ {
+ // setOpaqueMove
+ window->setOption(QMdiSubWindow::RubberBandMove, !opaqueMode);
+ QCOMPARE(window->testOption(QMdiSubWindow::RubberBandMove), !opaqueMode);
+
+ EventSpy moveSpy(window, QEvent::Move);
+ QCOMPARE(moveSpy.count(), 0);
+ window->move(30, 30);
+ QCOMPARE(moveSpy.count(), 1);
+ moveSpy.clear();
+
+ // Enter move mode
+ QStyleOptionTitleBar options;
+ options.initFrom(window);
+ int height = window->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+#if defined(Q_WS_MAC)
+ // ### Remove this after mac style has been fixed
+ height -= 4;
+#endif
+ QPoint mousePosition(window->width() / 2, height - 1);
+ sendMouseMove(window, mousePosition, Qt::NoButton);
+ sendMousePress(window, mousePosition);
+
+ // Trigger move events
+ for (int i = 0; i < geometryCount; ++i) {
+ ++mousePosition.rx();
+ ++mousePosition.ry();
+ sendMouseMove(window, mousePosition);
+ }
+
+ // Leave move mode
+ sendMouseRelease(window, mousePosition);
+ QCOMPARE(moveSpy.count(), expectedGeometryCount);
+ QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount));
+ }
+}
+#endif
+
+void tst_QMdiSubWindow::setWindowFlags_data()
+{
+ QTest::addColumn<Qt::WindowType>("windowType");
+ QTest::addColumn<Qt::WindowType>("expectedWindowType");
+ QTest::addColumn<Qt::WindowFlags>("customFlags");
+ QTest::addColumn<Qt::WindowFlags>("expectedCustomFlags");
+
+ // NB! If 'expectedCustomFlags' is set to 'Qt::WindowFlags(0)'
+ // and nothing else, it means we're expecting the same as customFlags.
+
+ // Standard window types with no custom flags set.
+ QTest::newRow("Qt::Widget") << Qt::Widget << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::Window") << Qt::Window << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::Dialog") << Qt::Dialog << Qt::SubWindow
+ << Qt::WindowFlags(0) << DialogWindowFlags;
+ QTest::newRow("Qt::Sheet") << Qt::Sheet << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::Drawer") << Qt::Drawer << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::Popup") << Qt::Popup << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::Tool") << Qt::Tool << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::ToolTip") << Qt::ToolTip << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::SplashScreen") << Qt::SplashScreen << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::Desktop") << Qt::Desktop << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+ QTest::newRow("Qt::SubWindow") << Qt::SubWindow << Qt::SubWindow
+ << Qt::WindowFlags(0) << StandardWindowFlags;
+
+ // Custom flags
+ QTest::newRow("Title") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowTitleHint | Qt::WindowFlags(0))
+ << Qt::WindowFlags(0);
+ QTest::newRow("TitleAndMin") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("TitleAndMax") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowTitleHint | Qt::WindowMaximizeButtonHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("TitleAndMinMax") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("Standard") << Qt::SubWindow << Qt::SubWindow
+ << StandardWindowFlags
+ << Qt::WindowFlags(0);
+ QTest::newRow("StandardAndShade") << Qt::SubWindow << Qt::SubWindow
+ << (StandardWindowFlags | Qt::WindowShadeButtonHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("StandardAndContext") << Qt::SubWindow << Qt::SubWindow
+ << (StandardWindowFlags | Qt::WindowContextHelpButtonHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("StandardAndStaysOnTop") << Qt::SubWindow << Qt::SubWindow
+ << (StandardWindowFlags | Qt::WindowStaysOnTopHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("StandardAndFrameless") << Qt::SubWindow << Qt::SubWindow
+ << (StandardWindowFlags | Qt::FramelessWindowHint)
+ << (Qt::FramelessWindowHint | Qt::WindowFlags(0));
+ QTest::newRow("StandardAndFramelessAndStaysOnTop") << Qt::SubWindow << Qt::SubWindow
+ << (StandardWindowFlags | Qt::FramelessWindowHint
+ | Qt::WindowStaysOnTopHint)
+ << (Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ QTest::newRow("Shade") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowShadeButtonHint | Qt::WindowFlags(0))
+ << (StandardWindowFlags | Qt::WindowShadeButtonHint);
+ QTest::newRow("ShadeAndCustomize") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowShadeButtonHint | Qt::CustomizeWindowHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("Context") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowContextHelpButtonHint | Qt::WindowFlags(0))
+ << (StandardWindowFlags | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("ContextAndCustomize") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowContextHelpButtonHint | Qt::CustomizeWindowHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("ShadeAndContext") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint)
+ << (StandardWindowFlags | Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("ShadeAndContextAndCustomize") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint | Qt::CustomizeWindowHint)
+ << Qt::WindowFlags(0);
+ QTest::newRow("OnlyCustomize") << Qt::SubWindow << Qt::SubWindow
+ << (Qt::CustomizeWindowHint | Qt::WindowFlags(0))
+ << Qt::WindowFlags(0);
+}
+
+void tst_QMdiSubWindow::setWindowFlags()
+{
+ QSKIP("Until we have a QEvent::WindowFlagsChange event, this will skip", SkipAll);
+ QFETCH(Qt::WindowType, windowType);
+ QFETCH(Qt::WindowType, expectedWindowType);
+ QFETCH(Qt::WindowFlags, customFlags);
+ QFETCH(Qt::WindowFlags, expectedCustomFlags);
+
+ QMdiArea workspace;
+ QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ qApp->processEvents();
+ workspace.show();
+ window->show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ window->setWindowFlags(windowType | customFlags);
+ QCOMPARE(window->windowType(), expectedWindowType);
+ if (!expectedCustomFlags) // We expect the same as 'customFlags'
+ QCOMPARE(window->windowFlags() & ~expectedWindowType, customFlags);
+ else
+ QCOMPARE(window->windowFlags() & ~expectedWindowType, expectedCustomFlags);
+
+}
+
+void tst_QMdiSubWindow::mouseDoubleClick()
+{
+ QMdiArea workspace;
+ QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ qApp->processEvents();
+ workspace.show();
+ window->show();
+
+ QVERIFY(!window->isMaximized());
+ QVERIFY(!window->isShaded());
+
+ QRect originalGeometry = window->geometry();
+
+ // Calculate mouse position
+ QStyleOptionTitleBar options;
+ options.initFrom(window);
+ int height = window->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+ // ### Remove this after mac style has been fixed
+ if (window->style()->inherits("QMacStyle"))
+ height -= 4;
+ // has border
+ if (!window->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, window))
+ height += window->isMinimized() ? 8 : 4;
+ QPoint mousePosition(window->width() / 2, height - 1);
+ sendMouseMove(window, mousePosition, Qt::NoButton);
+
+ // Without Qt::WindowShadeButtonHint flag set
+ sendMouseDoubleClick(window, mousePosition);
+ qApp->processEvents();
+ QVERIFY(window->isMaximized());
+
+ sendMouseDoubleClick(window, mousePosition);
+ qApp->processEvents();
+ QVERIFY(!window->isMaximized());
+ QCOMPARE(window->geometry(), originalGeometry);
+
+ // With Qt::WindowShadeButtonHint flag set
+ QSKIP("Until we have a QEvent::WindowFlagsChange event, this will skip", SkipAll);
+ window->setWindowFlags(window->windowFlags() | Qt::WindowShadeButtonHint);
+ QVERIFY(window->windowFlags() & Qt::WindowShadeButtonHint);
+ originalGeometry = window->geometry();
+ sendMouseDoubleClick(window, mousePosition);
+ qApp->processEvents();
+ QVERIFY(window->isShaded());
+
+ sendMouseDoubleClick(window, mousePosition);
+ qApp->processEvents();
+ QVERIFY(!window->isShaded());
+ QCOMPARE(window->geometry(), originalGeometry);
+
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ sendMouseDoubleClick(window, mousePosition);
+ QVERIFY(!window->isMinimized());
+ QCOMPARE(window->geometry(), originalGeometry);
+}
+
+void tst_QMdiSubWindow::setSystemMenu()
+{
+ QMdiSubWindow *subWindow = new QMdiSubWindow;
+ subWindow->resize(200, 50);
+ QPointer<QMenu>systemMenu = subWindow->systemMenu();
+ QVERIFY(systemMenu);
+ QCOMPARE(subWindow->actions(), systemMenu->actions());
+
+ QMainWindow mainWindow;
+ QMdiArea *mdiArea = new QMdiArea;
+ mdiArea->addSubWindow(subWindow);
+ mainWindow.setCentralWidget(mdiArea);
+ mainWindow.menuBar();
+ mainWindow.show();
+ QTest::qWaitForWindowShown(&mainWindow);
+ QTest::qWait(60);
+
+
+ QTRY_VERIFY(subWindow->isVisible());
+ QPoint globalPopupPos;
+
+ // Show system menu
+ QVERIFY(!qApp->activePopupWidget());
+ subWindow->showSystemMenu();
+ QTest::qWait(25);
+ QTRY_COMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu));
+ QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)),
+ (globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topLeft())) );
+
+ systemMenu->hide();
+ QVERIFY(!qApp->activePopupWidget());
+
+ QTest::ignoreMessage(QtWarningMsg, "QMdiSubWindow::setSystemMenu: system menu is already set");
+ subWindow->setSystemMenu(systemMenu);
+
+ subWindow->setSystemMenu(0);
+ QVERIFY(!systemMenu); // systemMenu is QPointer
+
+ systemMenu = new QMenu(subWindow);
+ systemMenu->addAction(QIcon(subWindow->style()->standardIcon(QStyle::SP_TitleBarCloseButton)),
+ QObject::tr("&Close"), subWindow, SLOT(close()));
+ subWindow->setSystemMenu(systemMenu);
+ QCOMPARE(subWindow->systemMenu(), qobject_cast<QMenu *>(systemMenu));
+ QCOMPARE(subWindow->systemMenu()->parentWidget(), static_cast<QWidget *>(subWindow));
+ QCOMPARE(subWindow->systemMenu()->actions().count(), 1);
+
+ // Show the new system menu
+ QVERIFY(!qApp->activePopupWidget());
+ subWindow->showSystemMenu();
+ QTest::qWait(25);
+ QTRY_COMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu));
+ QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos);
+
+ systemMenu->hide();
+ QVERIFY(!qApp->activePopupWidget());
+
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ // System menu in menu bar.
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isMaximized());
+ QWidget *menuLabel = subWindow->maximizedSystemMenuIconWidget();
+ QVERIFY(menuLabel);
+ subWindow->showSystemMenu();
+ QTest::qWait(25);
+ QTRY_COMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu));
+ QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)),
+ (globalPopupPos = menuLabel->mapToGlobal(QPoint(0, menuLabel->y() + menuLabel->height()))));
+ systemMenu->hide();
+ QTRY_VERIFY(!qApp->activePopupWidget());
+ subWindow->showNormal();
+#endif
+
+ // Reverse
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ qApp->processEvents();
+ mainWindow.updateGeometry();
+ QTest::qWait(150);
+
+ subWindow->showSystemMenu();
+ QTest::qWait(250);
+ QTRY_COMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu));
+ // + QPoint(1, 0) because topRight() == QPoint(left() + width() -1, top())
+ globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topRight()) + QPoint(1, 0);
+ globalPopupPos -= QPoint(systemMenu->sizeHint().width(), 0);
+ QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos);
+
+ systemMenu->hide();
+ QVERIFY(!qApp->activePopupWidget());
+
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ // System menu in menu bar in reverse mode.
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isMaximized());
+ menuLabel = subWindow->maximizedSystemMenuIconWidget();
+ QVERIFY(menuLabel);
+ subWindow->showSystemMenu();
+ QTest::qWait(250);
+ QTRY_COMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu));
+ globalPopupPos = menuLabel->mapToGlobal(QPoint(menuLabel->width(), menuLabel->y() + menuLabel->height()));
+ globalPopupPos -= QPoint(systemMenu->sizeHint().width(), 0);
+ QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos);
+#endif
+
+ delete systemMenu;
+ QVERIFY(!qApp->activePopupWidget());
+ QVERIFY(!subWindow->systemMenu());
+
+ // Restore layout direction.
+ qApp->setLayoutDirection(Qt::LeftToRight);
+}
+
+void tst_QMdiSubWindow::restoreFocus()
+{
+ // Create complex layout.
+ QGroupBox *box = new QGroupBox(tr("GroupBox"));
+ box->setCheckable(true);
+
+ QGroupBox *box1 = new QGroupBox(tr("&TopLeft"));
+ box1->setLayout(new QHBoxLayout);
+ box1->layout()->addWidget(new QTextEdit);
+
+ QGroupBox *box2 = new QGroupBox(tr("&TopRight"));
+ box2->setLayout(new QHBoxLayout);
+ box2->layout()->addWidget(new QTextEdit);
+
+ QGroupBox *box3 = new QGroupBox(tr("&BottomLeft"));
+ box3->setLayout(new QHBoxLayout);
+ box3->layout()->addWidget(new QTextEdit);
+
+ QGroupBox *box4 = new QGroupBox(tr("&BottomRight"));
+ box4->setLayout(new QHBoxLayout);
+ QMdiArea *nestedWorkspace = new QMdiArea;
+ for (int i = 0; i < 4; ++i)
+ nestedWorkspace->addSubWindow(new QTextEdit)->show();
+ qApp->processEvents();
+ nestedWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ nestedWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ box4->layout()->addWidget(nestedWorkspace);
+
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(box1, 0, 0);
+ layout->addWidget(box2, 0, 1);
+ layout->addWidget(box3, 1, 0);
+ layout->addWidget(box4, 1, 1);
+
+ box->setLayout(layout);
+
+ // Add complex widget to workspace.
+ QMdiArea topArea;
+ QMdiSubWindow *complexWindow = topArea.addSubWindow(box);
+ topArea.show();
+ box->show();
+
+ qApp->setActiveWindow(&topArea);
+ QMdiSubWindow *expectedFocusWindow = nestedWorkspace->subWindowList().last();
+ QVERIFY(expectedFocusWindow);
+ QVERIFY(expectedFocusWindow->widget());
+ QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget());
+
+ // Normal -> minimized
+ expectedFocusWindow->showMinimized();
+ qApp->processEvents();
+ QVERIFY(expectedFocusWindow->isMinimized());
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow));
+
+ // Minimized -> normal
+ expectedFocusWindow->showNormal();
+ qApp->processEvents();
+ QVERIFY(!expectedFocusWindow->isMinimized());
+ QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget());
+
+ // Normal -> maximized
+ expectedFocusWindow->showMaximized();
+ qApp->processEvents();
+ QVERIFY(expectedFocusWindow->isMaximized());
+ QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget());
+
+ // Maximized -> normal
+ expectedFocusWindow->showNormal();
+ qApp->processEvents();
+ QVERIFY(!expectedFocusWindow->isMaximized());
+ QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget());
+
+ // Minimized -> maximized
+ expectedFocusWindow->showMinimized();
+ qApp->processEvents();
+ QVERIFY(expectedFocusWindow->isMinimized());
+ expectedFocusWindow->showMaximized();
+ qApp->processEvents();
+ QVERIFY(expectedFocusWindow->isMaximized());
+ QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget());
+
+ // Maximized -> minimized
+ expectedFocusWindow->showNormal();
+ qApp->processEvents();
+ QVERIFY(!expectedFocusWindow->isMaximized());
+ expectedFocusWindow->showMaximized();
+ qApp->processEvents();
+ QVERIFY(expectedFocusWindow->isMaximized());
+ expectedFocusWindow->showMinimized();
+ qApp->processEvents();
+ QVERIFY(expectedFocusWindow->isMinimized());
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow));
+
+ complexWindow->showMinimized();
+ qApp->processEvents();
+ QVERIFY(complexWindow->isMinimized());
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(complexWindow));
+
+ complexWindow->showNormal();
+ qApp->processEvents();
+ QVERIFY(!complexWindow->isMinimized());
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow));
+}
+
+void tst_QMdiSubWindow::changeFocusWithTab()
+{
+ QWidget *widget = new QWidget;
+ widget->setLayout(new QVBoxLayout);
+
+ QLineEdit *firstLineEdit = new QLineEdit;
+ widget->layout()->addWidget(firstLineEdit);
+ QLineEdit *secondLineEdit = new QLineEdit;
+ widget->layout()->addWidget(secondLineEdit);
+ QLineEdit *thirdLineEdit = new QLineEdit;
+ widget->layout()->addWidget(thirdLineEdit);
+
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(widget);
+ mdiArea.show();
+ QCOMPARE(mdiArea.subWindowList().count(), 1);
+
+ qApp->setActiveWindow(&mdiArea);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(firstLineEdit));
+
+ // Next
+ QTest::keyPress(widget, Qt::Key_Tab);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(secondLineEdit));
+
+ // Next
+ QTest::keyPress(widget, Qt::Key_Tab);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(thirdLineEdit));
+
+ // Previous
+ QTest::keyPress(widget, Qt::Key_Backtab);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(secondLineEdit));
+
+ // Previous
+ QTest::keyPress(widget, Qt::Key_Backtab);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(firstLineEdit));
+
+ QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton);
+ window->show();
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+
+ // Check that we don't give away focus to another window by
+ // just hitting tab if the child widget does not accept
+ // focus (which is the case for a QPushButton).
+ QTest::keyPress(window, Qt::Key_Tab);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QCOMPARE(qApp->focusWidget(), tabAllWidgets() ? window->widget() : window);
+ QTest::keyPress(window, Qt::Key_Tab);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QCOMPARE(qApp->focusWidget(), tabAllWidgets() ? window->widget() : window);
+}
+
+class MyTextEdit : public QTextEdit
+{
+public:
+ MyTextEdit(QWidget *parent = 0) : QTextEdit(parent), acceptClose(false) {}
+ void setAcceptClose(bool enable = true) { acceptClose = enable; }
+protected:
+ void closeEvent(QCloseEvent *closeEvent)
+ {
+ if (!acceptClose)
+ closeEvent->ignore();
+ }
+
+private:
+ bool acceptClose;
+};
+
+void tst_QMdiSubWindow::closeEvent()
+{
+ QMdiArea mdiArea;
+ mdiArea.show();
+
+ MyTextEdit *textEdit = new MyTextEdit;
+ textEdit->setAcceptClose(false);
+ QMdiSubWindow *window = mdiArea.addSubWindow(textEdit);
+ EventSpy closeSpy(window->widget(), QEvent::Close);
+ window->show();
+
+ QCOMPARE(closeSpy.count(), 0);
+ QVERIFY(window->isVisible());
+ QVERIFY(textEdit->isVisible());
+
+ QVERIFY(!window->close());
+ QCOMPARE(closeSpy.count(), 1);
+ QVERIFY(window->isVisible());
+ QVERIFY(textEdit->isVisible());
+
+ QVERIFY(!textEdit->close());
+ QCOMPARE(closeSpy.count(), 2);
+ QVERIFY(window->isVisible());
+ QVERIFY(textEdit->isVisible());
+
+ textEdit->setAcceptClose(true);
+
+ QVERIFY(window->close());
+ QCOMPARE(closeSpy.count(), 3);
+ QCOMPARE(mdiArea.subWindowList().count(), 0);
+}
+
+// There exists more tests in QMdiArea which covers window title support
+// related to QMainWindow. This test is specific for QMdiSubWindow and its
+// widget.
+void tst_QMdiSubWindow::setWindowTitle()
+{
+ QString expectedWindowTitle = QLatin1String("This is teh shit[*]");
+ QTextEdit *textEdit = new QTextEdit;
+ textEdit->setWindowTitle(expectedWindowTitle);
+ QCOMPARE(textEdit->windowTitle(), expectedWindowTitle);
+ textEdit->setWindowModified(true);
+ QCOMPARE(textEdit->isWindowModified(), true);
+
+ QMdiArea mdiArea;
+ QMdiSubWindow *window = new QMdiSubWindow;
+ mdiArea.addSubWindow(window);
+ QCOMPARE(window->windowTitle(), QString());
+ QVERIFY(!window->isWindowModified());
+
+ window->setWidget(textEdit);
+ QVERIFY(window->isWindowModified());
+ QCOMPARE(textEdit->windowTitle(), expectedWindowTitle);
+ QCOMPARE(window->windowTitle(), window->widget()->windowTitle());
+
+ textEdit->setWindowModified(false);
+ QVERIFY(!textEdit->isWindowModified());
+ QVERIFY(!window->isWindowModified());
+ // This will return the title including the astrix, but the
+ // actual window title does not contain the astrix. This behavior
+ // seems a bit odd, but is equal to e.g. QTextEdit (and probably all
+ // other widgets which are not real top-level widgets).
+ QCOMPARE(window->windowTitle(), expectedWindowTitle);
+
+ textEdit->setWindowModified(true);;
+ expectedWindowTitle = QLatin1String("Override child title");
+ window->setWindowTitle(expectedWindowTitle);
+ QVERIFY(window->isWindowModified());
+ QCOMPARE(window->windowTitle(), expectedWindowTitle);
+
+ textEdit->setWindowTitle(QLatin1String("My parent overrides me"));
+ QCOMPARE(window->windowTitle(), expectedWindowTitle);
+
+ textEdit->setWindowModified(false);
+ QVERIFY(window->isWindowModified());
+ QCOMPARE(window->windowTitle(), expectedWindowTitle);
+
+ window->setWindowModified(false);
+ QVERIFY(!window->isWindowModified());
+ window->setWindowTitle(QString());
+ QCOMPARE(window->windowTitle(), QString());
+
+ expectedWindowTitle = QLatin1String("My parent doesn't have any title so now I can set one[*]");
+ textEdit->setWindowTitle(expectedWindowTitle);
+ QCOMPARE(window->windowTitle(), expectedWindowTitle);
+ textEdit->setWindowModified(true);
+ QVERIFY(window->isWindowModified());
+
+ window->setWidget(0);
+ QCOMPARE(window->windowTitle(), QString());
+ QVERIFY(!window->isWindowModified());
+ delete textEdit;
+}
+
+void tst_QMdiSubWindow::resizeEvents_data()
+{
+ QTest::addColumn<Qt::WindowState>("windowState");
+ QTest::addColumn<int>("expectedWindowResizeEvents");
+ QTest::addColumn<int>("expectedWidgetResizeEvents");
+ QTest::addColumn<bool>("isShadeMode");
+
+ QTest::newRow("minimized") << Qt::WindowMinimized << 1 << 0 << false;
+ QTest::newRow("maximized") << Qt::WindowMaximized << 1 << 1 << false;
+ QTest::newRow("shaded") << Qt::WindowMinimized << 1 << 0 << true;
+}
+
+void tst_QMdiSubWindow::resizeEvents()
+{
+ QFETCH(Qt::WindowState, windowState);
+ QFETCH(int, expectedWindowResizeEvents);
+ QFETCH(int, expectedWidgetResizeEvents);
+ QFETCH(bool, isShadeMode);
+
+ QMainWindow mainWindow;
+ QMdiArea *mdiArea = new QMdiArea;
+ mainWindow.setCentralWidget(mdiArea);
+ mainWindow.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ QMdiSubWindow *window = mdiArea->addSubWindow(new QTextEdit);
+ window->show();
+
+ EventSpy windowResizeEventSpy(window, QEvent::Resize);
+ QCOMPARE(windowResizeEventSpy.count(), 0);
+ EventSpy widgetResizeEventSpy(window->widget(), QEvent::Resize);
+ QCOMPARE(widgetResizeEventSpy.count(), 0);
+
+ // Set the window state.
+ if (!isShadeMode)
+ window->setWindowState(windowState);
+ else
+ window->showShaded();
+
+ // Check that the window state is correct.
+ QCOMPARE(window->windowState(), windowState | Qt::WindowActive);
+ QCOMPARE(window->widget()->windowState(), windowState);
+
+ // Make sure we got as many resize events as expected.
+ QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents);
+ QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents);
+ windowResizeEventSpy.clear();
+ widgetResizeEventSpy.clear();
+
+ // Normalize.
+ window->showNormal();
+
+ // Check that the window state is correct.
+ QCOMPARE(window->windowState(), Qt::WindowNoState | Qt::WindowActive);
+ QCOMPARE(window->widget()->windowState(), Qt::WindowNoState);
+
+ // Make sure we got as many resize events as expected.
+ QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents);
+ QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents);
+}
+
+#if defined(Q_WS_MAC)
+void tst_QMdiSubWindow::defaultSizeGrip()
+{
+ if (!qApp->style()->inherits("QMacStyle"))
+ return;
+ QMdiArea mdiArea;
+ mdiArea.show();
+
+ // QSizeGrip on windows with decoration.
+ QMdiSubWindow *windowWithDecoration = mdiArea.addSubWindow(new QWidget);
+ windowWithDecoration->show();
+ QVERIFY(qFindChild<QSizeGrip *>(windowWithDecoration));
+
+ // ...but not on windows without decoration (Qt::FramelessWindowHint).
+ QMdiSubWindow *windowWithoutDecoration = mdiArea.addSubWindow(new QWidget, Qt::FramelessWindowHint);
+ windowWithoutDecoration->show();
+ QVERIFY(!qFindChild<QSizeGrip *>(windowWithoutDecoration));
+}
+#endif
+
+void tst_QMdiSubWindow::hideAndShow()
+{
+ // Create a QTabWidget with two tabs; QMdiArea and QTextEdit.
+ QTabWidget *tabWidget = new QTabWidget;
+ QMdiArea *mdiArea = new QMdiArea;
+ tabWidget->addTab(mdiArea, QLatin1String("QMdiArea"));
+ tabWidget->addTab(new QTextEdit, QLatin1String("Dummy"));
+
+ // Set the tab widget as the central widget in QMainWindow.
+ QMainWindow mainWindow;
+ mainWindow.setGeometry(0, 0, 640, 480);
+ QMenuBar *menuBar = mainWindow.menuBar();
+ mainWindow.setCentralWidget(tabWidget);
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner));
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QTextEdit);
+ subWindow->showMaximized();
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ QVERIFY(menuBar->cornerWidget(Qt::TopRightCorner));
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+#endif
+
+ // Hide QMdiArea.
+ tabWidget->setCurrentIndex(1);
+
+ QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner));
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+
+ // Show QMdiArea.
+ tabWidget->setCurrentIndex(0);
+
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ QVERIFY(menuBar->cornerWidget(Qt::TopRightCorner));
+ QVERIFY(subWindow->maximizedButtonsWidget());
+ QVERIFY(subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+#endif
+
+ // Hide QMdiArea.
+ tabWidget->setCurrentIndex(1);
+
+ // Add few more windows.
+ for (int i = 0; i < 5; ++i)
+ mdiArea->addSubWindow(new QTextEdit);
+
+ // Show QMdiArea.
+ tabWidget->setCurrentIndex(0);
+ qApp->processEvents();
+
+ subWindow = mdiArea->subWindowList().back();
+ QVERIFY(subWindow);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ QVERIFY(menuBar->cornerWidget(Qt::TopRightCorner));
+ QVERIFY(subWindow->maximizedButtonsWidget());
+ QVERIFY(subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+#endif
+
+ subWindow->showNormal();
+ QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner));
+
+ // Check that newly added windows got right sizes.
+ foreach (QMdiSubWindow *window, mdiArea->subWindowList())
+ QCOMPARE(window->size(), window->sizeHint());
+
+ subWindow->showMaximized();
+#ifndef Q_WS_MAC
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+#endif
+
+ subWindow->hide();
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+ QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner));
+
+ subWindow->show();
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ QVERIFY(subWindow->maximizedButtonsWidget());
+ QVERIFY(subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+#endif
+
+ // Hide QMainWindow.
+ mainWindow.hide();
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+ QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner));
+
+ // Show QMainWindow.
+ mainWindow.show();
+#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE)
+ QVERIFY(subWindow->maximizedButtonsWidget());
+ QVERIFY(subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+#endif
+}
+
+void tst_QMdiSubWindow::keepWindowMaximizedState()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isMaximized());
+
+ // move
+ const QPoint newPosition = subWindow->pos() + QPoint(10, 10);
+ subWindow->move(newPosition);
+ QCOMPARE(subWindow->pos(), newPosition);
+ QVERIFY(subWindow->isMaximized());
+
+ // resize
+ const QSize newSize = subWindow->size() - QSize(10, 10);
+ subWindow->resize(newSize);
+ QCOMPARE(subWindow->size(), newSize);
+ QVERIFY(subWindow->isMaximized());
+
+ // setGeometry
+ const QRect newGeometry = QRect(newPosition - QPoint(10, 10), newSize + QSize(10, 10));
+ subWindow->setGeometry(newGeometry);
+ QCOMPARE(subWindow->geometry(), newGeometry);
+ QVERIFY(subWindow->isMaximized());
+
+ subWindow->showNormal();
+
+ // Verify that we don't force Qt::WindowMaximized.
+ QVERIFY(!subWindow->isMaximized());
+ subWindow->setGeometry(QRect(newPosition, newSize));
+ QCOMPARE(subWindow->geometry(), QRect(newPosition, newSize));
+ QVERIFY(!subWindow->isMaximized());
+}
+
+void tst_QMdiSubWindow::explicitlyHiddenWidget()
+{
+ QMdiArea mdiArea;
+ QTextEdit *textEdit = new QTextEdit;
+ textEdit->hide();
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(textEdit);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QVERIFY(subWindow->isVisible());
+ QVERIFY(!textEdit->isVisible());
+
+ textEdit->show();
+ QVERIFY(textEdit->isVisible());
+
+ // normal -> minimized
+ subWindow->showMinimized();
+ QVERIFY(subWindow->isVisible());
+ QVERIFY(!textEdit->isVisible());
+
+ // minimized -> normal
+ subWindow->showNormal();
+ QVERIFY(subWindow->isVisible());
+ QVERIFY(textEdit->isVisible());
+
+ // minimized -> maximized
+ subWindow->showMinimized();
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isVisible());
+ QVERIFY(textEdit->isVisible());
+
+ textEdit->hide();
+
+ // maximized -> normal
+ subWindow->showNormal();
+ QVERIFY(subWindow->isVisible());
+ QVERIFY(!textEdit->isVisible());
+
+ textEdit->show();
+
+ subWindow->showMinimized();
+ subWindow->setWidget(0);
+ delete textEdit;
+ textEdit = new QTextEdit;
+ textEdit->hide();
+ subWindow->setWidget(textEdit);
+ subWindow->showNormal();
+ QVERIFY(subWindow->isVisible());
+ QVERIFY(!textEdit->isVisible());
+}
+
+void tst_QMdiSubWindow::resizeTimer()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+ QTest::qWaitForWindowShown(&mdiArea);
+ QTest::qWait(300);
+
+
+ EventSpy timerEventSpy(subWindow, QEvent::Timer);
+ QCOMPARE(timerEventSpy.count(), 0);
+
+ for (int i = 0; i < 20; ++i) {
+ subWindow->resize(subWindow->size() + QSize(2, 2));
+ qApp->processEvents();
+ }
+
+ QTest::qWait(500); // Wait for timer events to occur.
+
+ QTRY_VERIFY(timerEventSpy.count() > 0);
+}
+
+void tst_QMdiSubWindow::fixedMinMaxSize()
+{
+ QMdiArea mdiArea;
+ mdiArea.setGeometry(0, 0, 640, 480);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ const QSize minimumSize = QSize(250, 150);
+ const QSize maximumSize = QSize(300, 200);
+
+ // Add the sub window to QMdiArea and set min/max size.
+ QMdiSubWindow *subWindow = new QMdiSubWindow;
+ subWindow->setMinimumSize(minimumSize);
+ QCOMPARE(subWindow->minimumSize(), minimumSize);
+ subWindow->setMaximumSize(maximumSize);
+ QCOMPARE(subWindow->maximumSize(), maximumSize);
+ mdiArea.addSubWindow(subWindow);
+ subWindow->show();
+ QCOMPARE(subWindow->size(), minimumSize);
+
+ // Calculate the size of a minimized sub window.
+ QStyleOptionTitleBar options;
+ options.initFrom(subWindow);
+ int minimizedHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+ // ### Remove this after mac style has been fixed
+ if (qobject_cast<QMacStyle *>(subWindow->style()))
+ minimizedHeight -= 4;
+#endif
+ if (!subWindow->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, subWindow))
+ minimizedHeight += 8;
+ int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MDIMinimizedWidth, &options);
+ const QSize minimizedSize = QSize(minimizedWidth, minimizedHeight);
+
+ // Even though the sub window has a minimum size set, it should be possible
+ // to minimize the window.
+ subWindow->showMinimized();
+ QVERIFY(subWindow->isMinimized());
+ QCOMPARE(subWindow->size(), minimizedSize);
+ QCOMPARE(subWindow->minimumSize(), minimizedSize);
+
+ // Restore minimum size.
+ subWindow->showNormal();
+ QVERIFY(!subWindow->isMinimized());
+ QCOMPARE(subWindow->size(), minimumSize);
+ QCOMPARE(subWindow->minimumSize(), minimumSize);
+
+ // Well, the logic here is of course broken (calling showMaximized on a window with
+ // maximum size set), but we should handle it :)
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isMaximized());
+ QCOMPARE(subWindow->size(), maximumSize);
+
+ subWindow->showNormal();
+ QVERIFY(!subWindow->isMaximized());
+ QCOMPARE(subWindow->size(), minimumSize);
+}
+
+#if !defined( Q_WS_MAC) && !defined( Q_OS_WINCE)
+void tst_QMdiSubWindow::replaceMenuBarWhileMaximized()
+{
+
+ QMainWindow mainWindow;
+
+ QMdiArea *mdiArea = new QMdiArea;
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QTextEdit);
+ subWindow->showMaximized();
+
+ mainWindow.setCentralWidget(mdiArea);
+ QMenuBar *menuBar = mainWindow.menuBar();
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ qApp->processEvents();
+
+ QVERIFY(subWindow->maximizedButtonsWidget());
+ QVERIFY(subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopLeftCorner), subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+
+ // Replace.
+ mainWindow.setMenuBar(new QMenuBar);
+ menuBar = mainWindow.menuBar();
+ qApp->processEvents();
+
+ QVERIFY(subWindow->maximizedButtonsWidget());
+ QVERIFY(subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopLeftCorner), subWindow->maximizedSystemMenuIconWidget());
+ QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
+
+ subWindow->showNormal();
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+ QVERIFY(!menuBar->cornerWidget(Qt::TopLeftCorner));
+ QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner));
+
+ // Delete and replace.
+ subWindow->showMaximized();
+ delete menuBar;
+ mainWindow.setMenuBar(new QMenuBar);
+ qApp->processEvents();
+
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+
+ subWindow->showNormal();
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+
+ // Delete.
+ subWindow->showMaximized();
+ mainWindow.setMenuBar(0);
+ qApp->processEvents();
+ QVERIFY(!mainWindow.menuWidget());
+
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+
+ subWindow->showNormal();
+ QVERIFY(!subWindow->maximizedButtonsWidget());
+ QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
+}
+
+void tst_QMdiSubWindow::closeOnDoubleClick()
+{
+ QMdiArea mdiArea;
+ QPointer<QMdiSubWindow> subWindow = mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ subWindow->showSystemMenu();
+ QTest::qWait(200);
+
+ QPointer<QMenu> systemMenu = subWindow->systemMenu();
+ QVERIFY(systemMenu);
+ QVERIFY(systemMenu->isVisible());
+
+ sendMouseDoubleClick(systemMenu, QPoint(10, 10));
+ if (qApp->activePopupWidget() == static_cast<QWidget *>(systemMenu))
+ systemMenu->hide();
+ qApp->processEvents();
+ QVERIFY(!subWindow || !subWindow->isVisible());
+ QVERIFY(!systemMenu || !systemMenu->isVisible());
+}
+#endif
+
+void tst_QMdiSubWindow::setFont()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QPushButton(QLatin1String("test")));
+ subWindow->resize(300, 100);
+ subWindow->setWindowTitle(QLatin1String("Window title"));
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ const QFont originalFont = QApplication::font("QWorkspaceTitleBar");
+ QStyleOptionTitleBar opt;
+ opt.initFrom(subWindow);
+ const int titleBarHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt);
+ const QRect titleBarRect = QRect(0, 0, subWindow->width(), titleBarHeight);
+ const QImage originalTitleBar = QPixmap::grabWidget(subWindow, titleBarRect).toImage();
+
+ QFont newFont(QLatin1String("Helvetica"), 16);
+ newFont.setBold(true);
+ subWindow->setFont(newFont);
+ qApp->processEvents();
+ const QFont &swFont = subWindow->font();
+ QCOMPARE(swFont.family(), newFont.family());
+ QCOMPARE(swFont.pointSize(), newFont.pointSize());
+ QCOMPARE(swFont.weight(), newFont.weight());
+ QImage newTitleBar = QPixmap::grabWidget(subWindow, titleBarRect).toImage();
+ QVERIFY(newTitleBar != originalTitleBar);
+
+ subWindow->setFont(originalFont);
+ qApp->processEvents();
+ QCOMPARE(subWindow->font(), originalFont);
+ newTitleBar = QPixmap::grabWidget(subWindow, titleBarRect).toImage();
+ QCOMPARE(newTitleBar, originalTitleBar);
+}
+
+void tst_QMdiSubWindow::task_188849()
+{
+ QMainWindow mainWindow;
+ // Sets a regular QWidget (and NOT a QMenuBar) as the menu bar.
+ mainWindow.setMenuWidget(new QWidget);
+
+ QMdiArea *mdiArea = new QMdiArea;
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget);
+ mainWindow.setCentralWidget(mdiArea);
+ mainWindow.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ // QMdiSubWindow will now try to show its buttons in the menu bar.
+ // Without checking that the menu bar is actually a QMenuBar
+ // and not a regular QWidget, this will crash.
+ subWindow->showMaximized();
+}
+
+void tst_QMdiSubWindow::mdiArea()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(subWindow->mdiArea(), &mdiArea);
+
+ subWindow->setParent(0);
+ QVERIFY(!subWindow->mdiArea());
+
+ // Child of the area's corner widget.
+ mdiArea.setCornerWidget(new QWidget);
+ subWindow->setParent(mdiArea.cornerWidget());
+ QVERIFY(!subWindow->mdiArea());
+
+ // Nested mdi area.
+ QMdiArea *nestedArea = new QMdiArea;
+ mdiArea.addSubWindow(nestedArea);
+ nestedArea->addSubWindow(subWindow);
+ QCOMPARE(subWindow->mdiArea(), nestedArea);
+ nestedArea->setViewport(new QWidget);
+ QCOMPARE(subWindow->mdiArea(), nestedArea);
+}
+
+void tst_QMdiSubWindow::task_182852()
+{
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+
+ QMdiArea *workspace = new QMdiArea;
+ QMainWindow mainWindow;
+ mainWindow.setCentralWidget(workspace);
+ mainWindow.show();
+ mainWindow.menuBar()->setVisible(true);
+ qApp->setActiveWindow(&mainWindow);
+
+ QString originalWindowTitle = QString::fromLatin1("MainWindow - [foo]");
+ mainWindow.setWindowTitle(originalWindowTitle);
+
+ QMdiSubWindow *window = new QMdiSubWindow;
+
+ QMdiArea *nestedWorkspace = new QMdiArea; // :-)
+ window->setWidget(nestedWorkspace);
+ window->widget()->setWindowTitle(QString::fromLatin1("Window"));
+
+ workspace->addSubWindow(window);
+
+ window->showMaximized();
+ qApp->processEvents();
+ QVERIFY(window->isMaximized());
+
+ QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]")
+ .arg(originalWindowTitle, window->widget()->windowTitle()));
+
+ window->showNormal();
+ QCOMPARE(mainWindow.windowTitle(), originalWindowTitle);
+
+ window->widget()->setWindowTitle(QString::fromLatin1("foo"));
+ window->showMaximized();
+
+ QCOMPARE(mainWindow.windowTitle(), originalWindowTitle);
+
+ window->showNormal();
+ QCOMPARE(mainWindow.windowTitle(), originalWindowTitle);
+
+ window->widget()->setWindowTitle(QString::fromLatin1("bar"));
+ window->showMaximized();
+
+ QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]")
+ .arg(originalWindowTitle, window->widget()->windowTitle()));
+
+
+#endif
+}
+
+void tst_QMdiSubWindow::task_233197()
+{
+ QMainWindow *mainWindow = new QMainWindow;
+ mainWindow->setAttribute(Qt::WA_DeleteOnClose);
+ mainWindow->resize(500, 200);
+ mainWindow->show();
+
+ QMdiArea *mdiArea = new QMdiArea(mainWindow);
+ mdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation, true);
+ mainWindow->setCentralWidget(mdiArea);
+
+ QMdiSubWindow *subWindow1 = new QMdiSubWindow();
+ mdiArea->addSubWindow(subWindow1);
+ subWindow1->showMaximized();
+
+ QMdiSubWindow *subWindow2 = new QMdiSubWindow();
+ mdiArea->addSubWindow(subWindow2);
+ subWindow2->showMaximized();
+
+ QMdiSubWindow *subWindow3 = new QMdiSubWindow();
+ mdiArea->addSubWindow(subWindow3);
+ subWindow3->showMaximized();
+
+ QMenuBar *menuBar = mainWindow->menuBar(); // force creation of a menubar
+ Q_UNUSED(menuBar);
+
+ QPushButton *focus1 = new QPushButton(QLatin1String("Focus 1"), mainWindow);
+ QObject::connect(focus1, SIGNAL(clicked()), subWindow1, SLOT(setFocus()));
+ focus1->move(5, 30);
+ focus1->show();
+
+ QPushButton *focus2 = new QPushButton(QLatin1String("Focus 2"), mainWindow);
+ QObject::connect(focus2, SIGNAL(clicked()), subWindow2, SLOT(setFocus()));
+ focus2->move(5, 60);
+ focus2->show();
+
+ QPushButton *close = new QPushButton(QLatin1String("Close"), mainWindow);
+ QObject::connect(close, SIGNAL(clicked()), mainWindow, SLOT(close()));
+ close->move(5, 90);
+ close->show();
+
+ QTest::qWait(200);
+
+ sendMousePress(focus2, QPoint());
+ sendMouseRelease(focus2, QPoint());
+
+ sendMousePress(focus1, QPoint());
+ sendMouseRelease(focus1, QPoint());
+
+ sendMousePress(focus2, QPoint());
+ sendMouseRelease(focus2, QPoint());
+
+ sendMousePress(close, QPoint());
+ sendMouseRelease(close, QPoint());
+
+ QTest::qWait(200);
+}
+
+void tst_QMdiSubWindow::task_226929()
+{
+ QMdiArea mdiArea;
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QMdiSubWindow *sub1 = mdiArea.addSubWindow(new QTextEdit);
+ sub1->showMinimized();
+
+ QMdiSubWindow *sub2 = mdiArea.addSubWindow(new QTextEdit);
+ sub2->showMaximized();
+
+ QTest::qWait(100);
+
+ // Do not assert.
+ // This window will now be activated and automatically maximized
+ // (if not QMdiArea::DontMaximizeSubWindowOnActionvation is set).
+ sub1->showNormal();
+ QVERIFY(sub1->isMaximized());
+}
+
+QTEST_MAIN(tst_QMdiSubWindow)
+#include "tst_qmdisubwindow.moc"
+
diff --git a/tests/auto/widgets/widgets/qmenu/.gitignore b/tests/auto/widgets/widgets/qmenu/.gitignore
new file mode 100644
index 0000000000..775539a653
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenu/.gitignore
@@ -0,0 +1 @@
+tst_qmenu
diff --git a/tests/auto/widgets/widgets/qmenu/qmenu.pro b/tests/auto/widgets/widgets/qmenu/qmenu.pro
new file mode 100644
index 0000000000..1fc1a7ff9d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenu/qmenu.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qmenu.cpp
+
+qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test # QTBUG-21100, unstably fails
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
new file mode 100644
index 0000000000..d115da865b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -0,0 +1,943 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <QPushButton>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QToolBar>
+#include <QToolButton>
+#include <QStatusBar>
+#include <QListWidget>
+#include <QWidgetAction>
+#include <QDesktopWidget>
+#include <qdialog.h>
+
+#include <qmenu.h>
+#include <qstyle.h>
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QMenu : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QMenu();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+private slots:
+ void getSetCheck();
+ void addActionsAndClear();
+
+ void keyboardNavigation_data();
+ void keyboardNavigation();
+ void focus();
+ void overrideMenuAction();
+ void statusTip();
+ void widgetActionFocus();
+#ifndef Q_OS_WINCE_WM
+ void mouseActivation();
+#endif
+ void tearOff();
+ void layoutDirection();
+
+ void task208001_stylesheet();
+ void activeSubMenuPosition();
+ void task242454_sizeHint();
+ void task176201_clear();
+ void task250673_activeMultiColumnSubMenuPosition();
+ void task256918_setFont();
+ void menuSizeHint();
+#ifndef Q_OS_WINCE_WM
+ void task258920_mouseBorder();
+#endif
+ void setFixedWidth();
+ void deleteActionInTriggered();
+ void pushButtonPopulateOnAboutToShow();
+ void QTBUG7907_submenus_autoselect();
+ void QTBUG7411_submenus_activate();
+ void QTBUG_10735_crashWithDialog();
+protected slots:
+ void onActivated(QAction*);
+ void onHighlighted(QAction*);
+ void onStatusMessageChanged(const QString &);
+ void onStatusTipTimer();
+ void deleteAction(QAction *a) { delete a; }
+ void populateMenu();
+private:
+ void createActions();
+ QMenu *menus[2], *lastMenu;
+ enum { num_builtins = 10 };
+ QAction *activated, *highlighted, *builtins[num_builtins];
+ QString statustip;
+};
+
+// Testing get/set functions
+void tst_QMenu::getSetCheck()
+{
+ QMenu obj1;
+ // QAction * QMenu::defaultAction()
+ // void QMenu::setDefaultAction(QAction *)
+ QAction *var1 = new QAction(0);
+ obj1.setDefaultAction(var1);
+ QCOMPARE(var1, obj1.defaultAction());
+ obj1.setDefaultAction((QAction *)0);
+ QCOMPARE((QAction *)0, obj1.defaultAction());
+ delete var1;
+
+ // QAction * QMenu::activeAction()
+ // void QMenu::setActiveAction(QAction *)
+ QAction *var2 = new QAction(0);
+ obj1.setActiveAction(var2);
+ QCOMPARE(var2, obj1.activeAction());
+ obj1.setActiveAction((QAction *)0);
+ QCOMPARE((QAction *)0, obj1.activeAction());
+ delete var2;
+}
+
+tst_QMenu::tst_QMenu()
+{
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
+}
+
+void tst_QMenu::initTestCase()
+{
+ for (int i = 0; i < num_builtins; i++)
+ builtins[i] = 0;
+ for (int i = 0; i < 2; i++) {
+ menus[i] = new QMenu;
+ QObject::connect(menus[i], SIGNAL(triggered(QAction*)), this, SLOT(onActivated(QAction*)));
+ QObject::connect(menus[i], SIGNAL(hovered(QAction*)), this, SLOT(onHighlighted(QAction*)));
+ }
+}
+
+void tst_QMenu::cleanupTestCase()
+{
+ for (int i = 0; i < 2; i++)
+ menus[i]->clear();
+ for (int i = 0; i < num_builtins; i++) {
+ bool menuAction = false;
+ for (int j = 0; j < 2; ++j)
+ if (menus[j]->menuAction() == builtins[i])
+ menuAction = true;
+ if (!menuAction)
+ delete builtins[i];
+ }
+ delete menus[0];
+ delete menus[1];
+}
+
+void tst_QMenu::init()
+{
+ activated = highlighted = 0;
+ lastMenu = 0;
+}
+
+void tst_QMenu::createActions()
+{
+ if (!builtins[0])
+ builtins[0] = new QAction("New", 0);
+ menus[0]->addAction(builtins[0]);
+
+ if (!builtins[1]) {
+ builtins[1] = new QAction(0);
+ builtins[1]->setSeparator(true);
+ }
+ menus[0]->addAction(builtins[1]);
+
+ if (!builtins[2]) {
+ builtins[2] = menus[1]->menuAction();
+ builtins[2]->setText("&Open..");
+ builtins[8] = new QAction("Close", 0);
+ menus[1]->addAction(builtins[8]);
+ builtins[9] = new QAction("Quit", 0);
+ menus[1]->addAction(builtins[9]);
+ }
+ menus[0]->addAction(builtins[2]);
+
+ if (!builtins[3])
+ builtins[3] = new QAction("Open &as..", 0);
+ menus[0]->addAction(builtins[3]);
+
+ if (!builtins[4]) {
+ builtins[4] = new QAction("Save", 0);
+ builtins[4]->setEnabled(false);
+ }
+ menus[0]->addAction(builtins[4]);
+
+ if (!builtins[5])
+ builtins[5] = new QAction("Sa&ve as..", 0);
+ menus[0]->addAction(builtins[5]);
+
+ if (!builtins[6]) {
+ builtins[6] = new QAction(0);
+ builtins[6]->setSeparator(true);
+ }
+ menus[0]->addAction(builtins[6]);
+
+ if (!builtins[7])
+ builtins[7] = new QAction("Prin&t", 0);
+ menus[0]->addAction(builtins[7]);
+}
+
+void tst_QMenu::onHighlighted(QAction *action)
+{
+ highlighted = action;
+ lastMenu = qobject_cast<QMenu*>(sender());
+}
+
+void tst_QMenu::onActivated(QAction *action)
+{
+ activated = action;
+ lastMenu = qobject_cast<QMenu*>(sender());
+}
+
+void tst_QMenu::onStatusMessageChanged(const QString &s)
+{
+ statustip=s;
+}
+
+void tst_QMenu::populateMenu()
+{
+ //just adds 3 dummy actions and a separator.
+ lastMenu->addAction("Foo");
+ lastMenu->addAction("Bar");
+ lastMenu->addAction("FooBar");
+ lastMenu->addSeparator();
+}
+
+void tst_QMenu::addActionsAndClear()
+{
+#ifdef QT_SOFTKEYS_ENABLED
+ // Softkeys add extra "Select" and "Back" actions to menu by default.
+ // Two first actions will be Select and Back when softkeys are enabled
+ int numSoftkeyActions = 2;
+#else
+ int numSoftkeyActions = 0;
+#endif
+
+ QCOMPARE(menus[0]->actions().count(), 0 + numSoftkeyActions);
+ createActions();
+ QCOMPARE(menus[0]->actions().count(), 8 + numSoftkeyActions);
+ menus[0]->clear();
+ QCOMPARE(menus[0]->actions().count(), 0);
+}
+
+// We have a separate mouseActivation test for Windows mobile.
+#ifndef Q_OS_WINCE_WM
+void tst_QMenu::mouseActivation()
+{
+ QWidget topLevel;
+ QMenu menu(&topLevel);
+ topLevel.show();
+ menu.addAction("Menu Action");
+ menu.show();
+ QTest::mouseClick(&menu, Qt::LeftButton, 0, menu.rect().center(), 300);
+ QVERIFY(!menu.isVisible());
+
+ //context menus can always be accessed with right click except on windows
+ menu.show();
+ QTest::mouseClick(&menu, Qt::RightButton, 0, menu.rect().center(), 300);
+ QVERIFY(!menu.isVisible());
+
+#ifdef Q_OS_WIN
+ //on windows normal mainwindow menus Can only be accessed with left mouse button
+ QMenuBar menubar;
+ QMenu submenu("Menu");
+ submenu.addAction("action");
+ QAction *action = menubar.addMenu(&submenu);
+ menubar.show();
+
+ QTest::mouseClick(&menubar, Qt::LeftButton, 0, menubar.actionGeometry(action).center(), 300);
+ QVERIFY(submenu.isVisible());
+ QTest::mouseClick(&submenu, Qt::LeftButton, 0, QPoint(5, 5), 300);
+ QVERIFY(!submenu.isVisible());
+
+ QTest::mouseClick(&menubar, Qt::LeftButton, 0, menubar.actionGeometry(action).center(), 300);
+ QVERIFY(submenu.isVisible());
+ QTest::mouseClick(&submenu, Qt::RightButton, 0, QPoint(5, 5), 300);
+ QVERIFY(submenu.isVisible());
+#endif
+}
+#endif
+
+void tst_QMenu::keyboardNavigation_data()
+{
+ QTest::addColumn<int>("key");
+ QTest::addColumn<int>("expected_action");
+ QTest::addColumn<int>("expected_menu");
+ QTest::addColumn<bool>("init");
+ QTest::addColumn<bool>("expected_activated");
+ QTest::addColumn<bool>("expected_highlighted");
+
+ //test up and down (order is important here)
+ QTest::newRow("data0") << int(Qt::Key_Down) << 0 << 0 << true << false << true;
+ QTest::newRow("data1") << int(Qt::Key_Down) << 2 << 0 << false << false << true; //skips the separator
+ QTest::newRow("data2") << int(Qt::Key_Down) << 3 << 0 << false << false << true;
+
+ if (QApplication::style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled))
+ QTest::newRow("data3_noMac") << int(Qt::Key_Down) << 4 << 0 << false << false << true;
+ else
+ QTest::newRow("data3_Mac") << int(Qt::Key_Down) << 5 << 0 << false << false << true;
+ QTest::newRow("data4") << int(Qt::Key_Up) << 3 << 0 << false << false << true;
+ QTest::newRow("data5") << int(Qt::Key_Up) << 2 << 0 << false << false << true;
+ QTest::newRow("data6") << int(Qt::Key_Right) << 8 << 1 << false << false << true;
+ QTest::newRow("data7") << int(Qt::Key_Down) << 9 << 1 << false << false << true;
+ QTest::newRow("data8") << int(Qt::Key_Escape) << 2 << 0 << false << false << false;
+ QTest::newRow("data9") << int(Qt::Key_Down) << 3 << 0 << false << false<< true;
+ QTest::newRow("data10") << int(Qt::Key_Return) << 3 << 0 << false << true << false;
+
+ //test shortcuts
+#if 0
+ QTest::newRow("shortcut0") << (Qt::ALT | Qt::Key_A) << 2 << 0 << true << true << false;
+#endif
+}
+
+void tst_QMenu::keyboardNavigation()
+{
+ QFETCH(int, key);
+ QFETCH(int, expected_action);
+ QFETCH(int, expected_menu);
+ QFETCH(bool, init);
+ QFETCH(bool, expected_activated);
+ QFETCH(bool, expected_highlighted);
+
+ if (init) {
+ lastMenu = menus[0];
+ lastMenu->clear();
+ createActions();
+ lastMenu->popup(QPoint(0, 0));
+ }
+
+ QTest::keyClick(lastMenu, (Qt::Key)key);
+ if (expected_activated) {
+ QCOMPARE(activated, builtins[expected_action]);
+ QCOMPARE(menus[expected_menu]->activeAction(), (QAction *)0);
+ } else {
+ QCOMPARE(menus[expected_menu]->activeAction(), builtins[expected_action]);
+ if (expected_highlighted)
+ QCOMPARE(menus[expected_menu]->activeAction(), highlighted);
+ }
+}
+
+#ifdef Q_WS_MAC
+QT_BEGIN_NAMESPACE
+ extern bool qt_tab_all_widgets; // from qapplication.cpp
+QT_END_NAMESPACE
+#endif
+
+void tst_QMenu::focus()
+{
+ QMenu menu;
+ menu.addAction("One");
+ menu.addAction("Two");
+ menu.addAction("Three");
+
+#ifdef Q_WS_MAC
+ if (!qt_tab_all_widgets)
+ QSKIP("Computer is currently set up to NOT tab to all widgets,"
+ " this test assumes you can tab to all widgets", SkipAll);
+#endif
+
+ QWidget window;
+ QPushButton button("Push me", &window);
+ window.show();
+ qApp->setActiveWindow(&window);
+
+ QVERIFY(button.hasFocus());
+ QCOMPARE(QApplication::focusWidget(), (QWidget *)&button);
+ QCOMPARE(QApplication::activeWindow(), &window);
+ menu.show();
+ QVERIFY(button.hasFocus());
+ QCOMPARE(QApplication::focusWidget(), (QWidget *)&button);
+ QCOMPARE(QApplication::activeWindow(), &window);
+ menu.hide();
+ QVERIFY(button.hasFocus());
+ QCOMPARE(QApplication::focusWidget(), (QWidget *)&button);
+ QCOMPARE(QApplication::activeWindow(), &window);
+}
+
+void tst_QMenu::overrideMenuAction()
+{
+ //test the override menu action by first creating an action to which we set its menu
+ QMainWindow w;
+
+ QAction *aFileMenu = new QAction("&File", &w);
+ w.menuBar()->addAction(aFileMenu);
+
+ QMenu *m = new QMenu(&w);
+ QAction *menuaction = m->menuAction();
+ connect(m, SIGNAL(triggered(QAction*)), SLOT(onActivated(QAction*)));
+ aFileMenu->setMenu(m); //this sets the override menu action for the QMenu
+ QCOMPARE(m->menuAction(), aFileMenu);
+
+ // On Mac and Windows CE, we need to create native key events to test menu
+ // action activation, so skip this part of the test.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QAction *aQuit = new QAction("Quit", &w);
+ aQuit->setShortcut(QKeySequence("Ctrl+X"));
+ m->addAction(aQuit);
+
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QApplication::setActiveWindow(&w);
+ w.setFocus();
+ QTRY_VERIFY(w.hasFocus());
+
+ //test of the action inside the menu
+ QTest::keyClick(&w, Qt::Key_X, Qt::ControlModifier);
+ QTRY_COMPARE(activated, aQuit);
+
+ //test if the menu still pops out
+ QTest::keyClick(&w, Qt::Key_F, Qt::AltModifier);
+ QTRY_VERIFY(m->isVisible());
+#endif
+
+ delete aFileMenu;
+
+ //after the deletion of the override menu action,
+ //the menu should have its default menu action back
+ QCOMPARE(m->menuAction(), menuaction);
+}
+
+void tst_QMenu::statusTip()
+{
+ //check that the statustip of actions inserted into the menu are displayed
+ QMainWindow w;
+ connect(w.statusBar(), SIGNAL(messageChanged(const QString &)), SLOT(onStatusMessageChanged(const QString &)));; //creates the status bar
+ QToolBar tb;
+ QAction a("main action", &tb);
+ a.setStatusTip("main action");
+ QMenu m(&tb);
+ QAction subact("sub action", &m);
+ subact.setStatusTip("sub action");
+ m.addAction(&subact);
+ a.setMenu(&m);
+ tb.addAction(&a);
+
+ w.addToolBar(&tb);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+
+ QRect rect1 = tb.actionGeometry(&a);
+ QToolButton *btn = qobject_cast<QToolButton*>(tb.childAt(rect1.center()));
+
+ QVERIFY(btn != NULL);
+
+ //because showMenu calls QMenu::exec, we need to use a singleshot
+ //to continue the test
+ QTimer::singleShot(200,this, SLOT(onStatusTipTimer()));
+ btn->showMenu();
+ QVERIFY(statustip.isEmpty());
+}
+
+//2nd part of the test
+void tst_QMenu::onStatusTipTimer()
+{
+ QMenu *menu = qobject_cast<QMenu*>(QApplication::activePopupWidget());
+ QVERIFY(menu != 0);
+ QVERIFY(menu->isVisible());
+ QTest::keyClick(menu, Qt::Key_Down);
+
+ //we store the statustip to press escape in any case
+ //otherwise, if the test fails it blocks (never gets out of QMenu::exec
+ const QString st=statustip;
+
+ menu->close(); //goes out of the menu
+
+ QCOMPARE(st, QString("sub action"));
+ QVERIFY(menu->isVisible() == false);
+}
+
+void tst_QMenu::widgetActionFocus()
+{
+ //test if the focus is correctly handled with a QWidgetAction
+ QMenu m;
+ QListWidget *l = new QListWidget(&m);
+ for (int i = 1; i<3 ; i++)
+ l->addItem(QString("item%1").arg(i));
+ QWidgetAction *wa = new QWidgetAction(&m);
+ wa->setDefaultWidget(l);
+ m.addAction(wa);
+ m.setActiveAction(wa);
+ l->setFocus(); //to ensure it has primarily the focus
+ QAction *menuitem1=m.addAction("menuitem1");
+ QAction *menuitem2=m.addAction("menuitem2");
+
+ m.popup(QPoint());
+
+ QVERIFY(m.isVisible());
+ QVERIFY(l->hasFocus());
+ QVERIFY(l->currentItem());
+ QCOMPARE(l->currentItem()->text(), QString("item1"));
+
+ QTest::keyClick(QApplication::focusWidget(), Qt::Key_Down);
+ QVERIFY(l->currentItem());
+ QCOMPARE(l->currentItem()->text(), QString("item2"));
+
+ QTest::keyClick(QApplication::focusWidget(), Qt::Key_Down);
+ QVERIFY(m.hasFocus());
+ QCOMPARE(m.activeAction(), menuitem1);
+
+ QTest::keyClick(QApplication::focusWidget(), Qt::Key_Down);
+ QVERIFY(m.hasFocus());
+ QCOMPARE(m.activeAction(), menuitem2);
+
+ QTest::keyClick(QApplication::focusWidget(), Qt::Key_Up);
+ QVERIFY(m.hasFocus());
+ QCOMPARE(m.activeAction(), menuitem1);
+
+ QTest::keyClick(QApplication::focusWidget(), Qt::Key_Up);
+ QVERIFY(l->hasFocus());
+ QCOMPARE(m.activeAction(), (QAction *)wa);
+}
+
+void tst_QMenu::tearOff()
+{
+ QWidget widget;
+ QMenu *menu = new QMenu(&widget);
+ QVERIFY(!menu->isTearOffEnabled()); //default value
+ menu->setTearOffEnabled(true);
+ menu->addAction("aaa");
+ menu->addAction("bbb");
+ QVERIFY(menu->isTearOffEnabled());
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ widget.activateWindow();
+ menu->popup(QPoint(0,0));
+ QTest::qWait(50);
+ QVERIFY(!menu->isTearOffMenuVisible());
+
+ QTest::mouseClick(menu, Qt::LeftButton, 0, QPoint(3, 3), 10);
+ QTest::qWait(100);
+
+ QVERIFY(menu->isTearOffMenuVisible());
+ QPointer<QMenu> torn = 0;
+ foreach (QWidget *w, QApplication::allWidgets()) {
+ if (w->inherits("QTornOffMenu")) {
+ torn = static_cast<QMenu *>(w);
+ break;
+ }
+ }
+ QVERIFY(torn);
+ QVERIFY(torn->isVisible());
+
+ menu->hideTearOffMenu();
+ QVERIFY(!menu->isTearOffMenuVisible());
+ QVERIFY(!torn->isVisible());
+}
+
+void tst_QMenu::layoutDirection()
+{
+ QMainWindow win;
+ win.setLayoutDirection(Qt::RightToLeft);
+
+ QMenu menu(&win);
+ menu.show();
+ QTest::qWaitForWindowShown(&menu);
+ QCOMPARE(menu.layoutDirection(), Qt::RightToLeft);
+ menu.close();
+
+ menu.setParent(0);
+ menu.show();
+ QTest::qWaitForWindowShown(&menu);
+ QCOMPARE(menu.layoutDirection(), QApplication::layoutDirection());
+ menu.close();
+
+ //now the menubar
+ QAction *action = win.menuBar()->addMenu(&menu);
+ win.menuBar()->setActiveAction(action);
+ QTest::qWaitForWindowShown(&menu);
+ QCOMPARE(menu.layoutDirection(), Qt::RightToLeft);
+}
+
+void tst_QMenu::task208001_stylesheet()
+{
+ //test if it crash
+ QMainWindow main;
+ main.setStyleSheet("QMenu [title =\"File\"] { color: red;}");
+ main.menuBar()->addMenu("File");
+}
+
+void tst_QMenu::activeSubMenuPosition()
+{
+ QPushButton lab("subMenuPosition test");
+
+ QMenu *sub = new QMenu("Submenu", &lab);
+ sub->addAction("Sub-Item1");
+ QAction *subAction = sub->addAction("Sub-Item2");
+
+ QMenu *main = new QMenu("Menu-Title", &lab);
+ (void)main->addAction("Item 1");
+ QAction *menuAction = main->addMenu(sub);
+ (void)main->addAction("Item 3");
+ (void)main->addAction("Item 4");
+
+ main->setActiveAction(menuAction);
+ sub->setActiveAction(subAction);
+ main->popup(QPoint(200,200));
+
+ QVERIFY(main->isVisible());
+ QCOMPARE(main->activeAction(), menuAction);
+ QVERIFY(sub->isVisible());
+ QVERIFY(sub->pos() != QPoint(0,0));
+ // well, it's enough to check the pos is not (0,0) but it's more safe
+ // to check that submenu is to the right of the main menu too.
+#ifndef Q_OS_WINCE_WM
+ QVERIFY(sub->pos().x() > main->pos().x());
+ QCOMPARE(sub->activeAction(), subAction);
+#endif
+}
+
+void tst_QMenu::task242454_sizeHint()
+{
+ QMenu menu;
+ QString s = QLatin1String("foo\nfoo\nfoo\nfoo");
+ menu.addAction(s);
+ QVERIFY(menu.sizeHint().width() > menu.fontMetrics().boundingRect(QRect(), Qt::TextSingleLine, s).width());
+}
+
+class Menu : public QMenu
+{
+ Q_OBJECT
+public slots:
+ void clear()
+ {
+ QMenu::clear();
+ }
+};
+
+void tst_QMenu::task176201_clear()
+{
+ //this test used to crash
+ Menu menu;
+ QAction *action = menu.addAction("test");
+ menu.connect(action, SIGNAL(triggered()), SLOT(clear()));
+ menu.popup(QPoint());
+ QTest::mouseClick(&menu, Qt::LeftButton, 0, menu.rect().center());
+}
+
+void tst_QMenu::task250673_activeMultiColumnSubMenuPosition()
+{
+ class MyMenu : public QMenu
+ {
+ public:
+ int columnCount() const { return QMenu::columnCount(); }
+ };
+
+ QMenu sub;
+
+ if (sub.style()->styleHint(QStyle::SH_Menu_Scrollable, 0, &sub)) {
+ //the style prevents the menus from getting columns
+ QSKIP("the style doesn't support multiple columns, it makes the menu scrollable", SkipSingle);
+ }
+
+ sub.addAction("Sub-Item1");
+ QAction *subAction = sub.addAction("Sub-Item2");
+
+ MyMenu main;
+ main.addAction("Item 1");
+ QAction *menuAction = main.addMenu(&sub);
+ main.popup(QPoint(200,200));
+
+ uint i = 2;
+ while (main.columnCount() < 2) {
+ main.addAction(QString("Item %1").arg(i));
+ ++i;
+ QVERIFY(i<1000);
+ }
+ main.setActiveAction(menuAction);
+ sub.setActiveAction(subAction);
+
+ QVERIFY(main.isVisible());
+ QCOMPARE(main.activeAction(), menuAction);
+ QVERIFY(sub.isVisible());
+ QVERIFY(sub.pos().x() > main.pos().x());
+
+ const int subMenuOffset = main.style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, &main);
+ QVERIFY((sub.geometry().left() - subMenuOffset + 5) < main.geometry().right());
+}
+
+void tst_QMenu::task256918_setFont()
+{
+ QMenu menu;
+ QAction *action = menu.addAction("foo");
+ QFont f;
+ f.setPointSize(30);
+ action->setFont(f);
+ menu.show(); //ensures that the actiongeometry are calculated
+ QVERIFY(menu.actionGeometry(action).height() > f.pointSize());
+}
+
+void tst_QMenu::menuSizeHint()
+{
+ QMenu menu;
+ //this is a list of arbitrary strings so that we check the geometry
+ QStringList list = QStringList() << "trer" << "ezrfgtgvqd" << "sdgzgzerzerzer" << "eerzertz" << "er";
+ foreach (QString str, list)
+ menu.addAction(str);
+
+ int left, top, right, bottom;
+ menu.getContentsMargins(&left, &top, &right, &bottom);
+ const int panelWidth = menu.style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, &menu);
+ const int hmargin = menu.style()->pixelMetric(QStyle::PM_MenuHMargin, 0, &menu),
+ vmargin = menu.style()->pixelMetric(QStyle::PM_MenuVMargin, 0, &menu);
+
+ int maxWidth =0;
+ QRect result;
+ foreach (QAction *action, menu.actions()) {
+#ifdef QT_SOFTKEYS_ENABLED
+ // Softkey actions are not widgets and have no geometry.
+ if (menu.actionGeometry(action).topLeft() == QPoint(0,0))
+ continue;
+#endif
+ maxWidth = qMax(maxWidth, menu.actionGeometry(action).width());
+ result |= menu.actionGeometry(action);
+ QCOMPARE(result.x(), left + hmargin + panelWidth);
+ QCOMPARE(result.y(), top + vmargin + panelWidth);
+ }
+
+ QStyleOption opt(0);
+ opt.rect = menu.rect();
+ opt.state = QStyle::State_None;
+
+ QSize resSize = QSize(result.x(), result.y()) + result.size() + QSize(hmargin + right + panelWidth, vmargin + top + panelWidth);
+
+ resSize = menu.style()->sizeFromContents(QStyle::CT_Menu, &opt,
+ resSize.expandedTo(QApplication::globalStrut()), &menu);
+
+ QCOMPARE(resSize, menu.sizeHint());
+}
+
+class Menu258920 : public QMenu
+{
+ Q_OBJECT
+public slots:
+ void paintEvent(QPaintEvent *e)
+ {
+ QMenu::paintEvent(e);
+ painted = true;
+ }
+
+public:
+ bool painted;
+};
+
+// Mouse move related signals for Windows Mobile unavailable.
+#ifndef Q_OS_WINCE_WM
+void tst_QMenu::task258920_mouseBorder()
+{
+#ifdef Q_WS_QPA
+ QSKIP("QTBUG-20753 QCursor::setPos() / QTest::mouseMove() doesn't work on qpa", SkipAll);
+#endif
+ Menu258920 menu;
+ // For styles which inherit from QWindowsStyle, styleHint(QStyle::SH_Menu_MouseTracking) is true.
+ menu.setMouseTracking(true);
+ QAction *action = menu.addAction("test");
+
+ menu.popup(QApplication::desktop()->availableGeometry().center());
+ QTest::qWaitForWindowShown(&menu);
+ QTest::qWait(100);
+ QRect actionRect = menu.actionGeometry(action);
+ QTest::mouseMove(&menu, actionRect.center());
+ QTest::qWait(30);
+ QTest::mouseMove(&menu, actionRect.center() + QPoint(10, 0));
+ QTest::qWait(30);
+ QCOMPARE(action, menu.activeAction());
+ menu.painted = false;
+ QTest::mouseMove(&menu, QPoint(actionRect.center().x(), actionRect.bottom() + 1));
+ QTest::qWait(30);
+ QCOMPARE(static_cast<QAction*>(0), menu.activeAction());
+ QVERIFY(menu.painted);
+}
+#endif
+
+void tst_QMenu::setFixedWidth()
+{
+ QMenu menu;
+ menu.addAction("action");
+ menu.setFixedWidth(300);
+ //the sizehint should reflect the minimumwidth because the action will try to
+ //get as much space as possible
+ QCOMPARE(menu.sizeHint().width(), menu.minimumWidth());
+}
+
+void tst_QMenu::deleteActionInTriggered()
+{
+ // should not crash
+ QMenu m;
+ QObject::connect(&m, SIGNAL(triggered(QAction*)), this, SLOT(deleteAction(QAction*)));
+ QWeakPointer<QAction> a = m.addAction("action");
+ a.data()->trigger();
+ QVERIFY(!a);
+}
+
+void tst_QMenu::pushButtonPopulateOnAboutToShow()
+{
+ QPushButton b("Test PushButton");
+ b.setWindowFlags(Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
+ lastMenu = new QMenu;
+ b.setMenu(lastMenu);
+ const int scrNumber = QApplication::desktop()->screenNumber(&b);
+ connect(lastMenu, SIGNAL(aboutToShow()), this, SLOT(populateMenu()));
+ b.show();
+ const QRect screen = QApplication::desktop()->screenGeometry(scrNumber);
+
+ QRect desiredGeometry = b.geometry();
+ desiredGeometry.moveTopLeft(QPoint(10, screen.bottom()-b.height()-5));
+
+ b.setGeometry(desiredGeometry);
+ QTest::qWaitForWindowShown(&b);
+
+ if (b.geometry() != desiredGeometry) {
+ // We are trying to put the button very close to the edge of the screen,
+ // explicitly to test behavior when the popup menu goes off the screen.
+ // However a modern window manager is quite likely to reject this requested geometry
+ // (kwin in kde4 does, for example, since the button would probably appear behind
+ // or partially behind the taskbar).
+ // Your best bet is to run this test _without_ a WM.
+ QSKIP("Your window manager won't allow a window against the bottom of the screen", SkipAll);
+ }
+
+ QTimer::singleShot(300,lastMenu, SLOT(hide()));
+ QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center());
+ QVERIFY(!lastMenu->geometry().intersects(b.geometry()));
+
+ // note: we're assuming that, if we previously got the desired geometry, we'll get it here too
+ b.move(10, screen.bottom()-lastMenu->height()-5);
+ QTimer::singleShot(300,lastMenu, SLOT(hide()));
+ QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center());
+ QVERIFY(!lastMenu->geometry().intersects(b.geometry()));
+
+}
+void tst_QMenu::QTBUG7907_submenus_autoselect()
+{
+ QMenu menu("Test Menu");
+ QMenu set1("Setting1");
+ QMenu set2("Setting2");
+ QMenu subset("Subsetting");
+ subset.addAction("Values");
+ set1.addMenu(&subset);
+ menu.addMenu(&set1);
+ menu.addMenu(&set2);
+ menu.show();
+ QTest::qWaitForWindowShown(&menu);
+ QTest::mouseClick(&menu, Qt::LeftButton, Qt::NoModifier, QPoint(5,5) );
+ QTest::qWait(500);
+ QVERIFY(!subset.isVisible());
+}
+
+void tst_QMenu::QTBUG7411_submenus_activate()
+{
+ QMenu menu("Test Menu");
+ QAction *act = menu.addAction("foo");
+ QMenu sub1("&sub1");
+ sub1.addAction("foo");
+ sub1.setTitle("&sub1");
+ QAction *act1 = menu.addMenu(&sub1);
+ menu.show();
+ QTest::qWaitForWindowShown(&menu);
+ menu.setActiveAction(act);
+ QTest::keyPress(&menu, Qt::Key_Down);
+ QCOMPARE(menu.activeAction(), act1);
+ QVERIFY(!sub1.isVisible());
+ QTest::keyPress(&menu, Qt::Key_S);
+ QTRY_VERIFY(sub1.isVisible());
+}
+
+class MyMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ MyMenu() : m_currentIndex(0)
+ {
+ for (int i = 0; i < 2; ++i)
+ dialogActions[i] = addAction( QString("dialog %1").arg(i), dialogs + i, SLOT(exec()));
+ }
+
+ void activateAction(int index)
+ {
+ m_currentIndex = index;
+ popup(QPoint());
+ QTest::qWaitForWindowShown(this);
+ setActiveAction(dialogActions[index]);
+ QTimer::singleShot(500, this, SLOT(checkVisibility()));
+ QTest::keyClick(this, Qt::Key_Enter); //activation
+ }
+
+public slots:
+ void activateLastAction()
+ {
+ activateAction(1);
+ }
+
+ void checkVisibility()
+ {
+ QTRY_VERIFY(dialogs[m_currentIndex].isVisible());
+ if (m_currentIndex == 1) {
+ QApplication::closeAllWindows(); //this is the end of the test
+ }
+ }
+
+private:
+ QAction *dialogActions[2];
+ QDialog dialogs[2];
+ int m_currentIndex;
+};
+
+void tst_QMenu::QTBUG_10735_crashWithDialog()
+{
+ MyMenu menu;
+
+ QTimer::singleShot(1000, &menu, SLOT(activateLastAction()));
+ menu.activateAction(0);
+}
+
+QTEST_MAIN(tst_QMenu)
+#include "tst_qmenu.moc"
diff --git a/tests/auto/widgets/widgets/qmenubar/.gitignore b/tests/auto/widgets/widgets/qmenubar/.gitignore
new file mode 100644
index 0000000000..b72cc79d94
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenubar/.gitignore
@@ -0,0 +1 @@
+tst_qmenubar
diff --git a/tests/auto/widgets/widgets/qmenubar/qmenubar.pro b/tests/auto/widgets/widgets/qmenubar/qmenubar.pro
new file mode 100644
index 0000000000..73c2545710
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenubar/qmenubar.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qmenubar.cpp
diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
new file mode 100644
index 0000000000..dc3b81920d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
@@ -0,0 +1,1291 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qmenubar.h>
+#include <qstyle.h>
+#include <qwindowsstyle.h>
+#include <qdesktopwidget.h>
+#include <qaction.h>
+#include <qstyleoption.h>
+
+#ifdef Q_WS_WIN
+#include <windows.h>
+#endif
+
+#include <qobject.h>
+
+QT_FORWARD_DECLARE_CLASS(QMainWindow)
+
+#include <qmenubar.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class QtTestSlot : public QObject
+{
+ Q_OBJECT
+
+public:
+ QtTestSlot( QObject* parent = 0 ): QObject( parent ) { clear(); };
+ virtual ~QtTestSlot() {};
+
+ void clear() { sel_count = 0; };
+ uint selCount() { return sel_count; };
+
+public slots:
+ void selected() { sel_count++; };
+
+private:
+ uint sel_count;
+};
+
+class Menu : public QMenu
+{
+ Q_OBJECT
+ public slots:
+ void addActions()
+ {
+ //this will change the geometry of the menu
+ addAction("action1");
+ addAction("action2");
+ }
+};
+
+class tst_QMenuBar : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMenuBar();
+ virtual ~tst_QMenuBar();
+
+ void initSimpleMenubar();
+ void initComplexMenubar();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+private slots:
+ void getSetCheck();
+
+ void clear();
+ void removeItemAt();
+ void removeItemAt_data();
+ void removeItem_data();
+ void removeItem();
+ void count();
+ void insertItem_QString_QObject();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+ void accel();
+ void activatedCount();
+#endif
+ void allowActiveAndDisabled();
+
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+ void check_accelKeys();
+ void check_cursorKeys1();
+ void check_cursorKeys2();
+ void check_cursorKeys3();
+#endif
+
+ void check_homeKey();
+ void check_endKey();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+ void check_escKey();
+#endif
+
+// void check_mouse1_data();
+// void check_mouse1();
+// void check_mouse2_data();
+// void check_mouse2();
+
+ void check_altPress();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+ void check_shortcutPress();
+ void check_menuPosition();
+#endif
+ void task223138_triggered();
+ void task256322_highlight();
+ void menubarSizeHint();
+#ifndef Q_WS_MAC
+ void taskQTBUG4965_escapeEaten();
+#endif
+ void taskQTBUG11823_crashwithInvisibleActions();
+
+protected slots:
+ void onActivated( QAction*);
+
+private:
+ QtTestSlot *menu1;
+ QtTestSlot *menu2;
+ QtTestSlot *menu3;
+ QtTestSlot *menu4;
+
+ QtTestSlot *item1_A;
+ QtTestSlot *item1_B;
+ QtTestSlot *item2_C;
+ QtTestSlot *item2_D;
+ QtTestSlot *item2_E;
+ QtTestSlot *item2_F;
+ QtTestSlot *item2_G;
+ QtTestSlot *item2_H;
+
+ void resetSlots();
+ void resetCount();
+
+ void reset() { resetSlots(); resetCount(); };
+
+ QAction* last_accel_id;
+ int activated_count;
+
+ QAction *action;
+ QAction *action1;
+ QMainWindow *mw;
+ QMenuBar *mb;
+ QMenu *pm1;
+ QMenu *pm2;
+};
+
+// Testing get/set functions
+void tst_QMenuBar::getSetCheck()
+{
+ QMenuBar obj1;
+ // QAction * QMenuBar::activeAction()
+ // void QMenuBar::setActiveAction(QAction *)
+ QAction *var1 = new QAction(0);
+ obj1.setActiveAction(var1);
+ QCOMPARE(var1, obj1.activeAction());
+ obj1.setActiveAction((QAction *)0);
+ QCOMPARE((QAction *)0, obj1.activeAction());
+ delete var1;
+}
+
+#include <qcursor.h>
+
+const int RESET = 0;
+
+/*!
+ Test plan:
+ insertItem (all flavors and combinations)
+ removing menu items
+ clearing the menu
+
+ check the common behaviour + emitted signals for:
+ accelerator keys
+ navigating tru the menu and then pressing ENTER
+ mouse clicks
+ mouse drags
+ combinations of key + mouse (if possible)
+ checked / unckecked state of menu options
+ active / inactive state
+
+ Can't test these without pixmap comparison...
+ show and hide
+ icons in a menu
+ pixmaps in a menu
+
+*/
+
+tst_QMenuBar::tst_QMenuBar()
+
+{
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
+
+
+ activated_count = 0;
+ mb = 0;
+ pm1 = 0;
+ pm2 = 0;
+ last_accel_id = 0;
+}
+
+tst_QMenuBar::~tst_QMenuBar()
+{
+ //delete mw; //#### cannot do that AFTER qapplication was destroyed!
+ mw = 0;
+}
+
+void tst_QMenuBar::initTestCase()
+{
+ // create a default mainwindow
+ // If you run a widget test, this will be replaced in the testcase by the
+ // widget under test
+ mw = new QMainWindow(0, Qt::X11BypassWindowManagerHint);
+ mb = new QMenuBar( mw );
+ connect( mb, SIGNAL(triggered(QAction *)), this, SLOT(onActivated(QAction *)) );
+
+ initSimpleMenubar();
+ mw->show();
+ QTest::qWaitForWindowShown(mw);
+ mw->activateWindow();
+
+ menu1 = new QtTestSlot( mw );
+ menu2 = new QtTestSlot( mw );
+ menu3 = new QtTestSlot( mw );
+ menu4 = new QtTestSlot( mw );
+ item1_A = new QtTestSlot( mw );
+ item1_B = new QtTestSlot( mw );
+ item2_C = new QtTestSlot( mw );
+ item2_D = new QtTestSlot( mw );
+ item2_E = new QtTestSlot( mw );
+ item2_F = new QtTestSlot( mw );
+ item2_G = new QtTestSlot( mw );
+ item2_H = new QtTestSlot( mw );
+}
+
+
+void tst_QMenuBar::cleanupTestCase()
+{
+ delete mw;
+}
+
+void tst_QMenuBar::initSimpleMenubar()
+{
+ mb->hide();
+ mb->clear();
+
+ delete pm1;
+ pm1 = mb->addMenu("&accel");
+ action = pm1->addAction( "menu1" );
+ action->setShortcut(QKeySequence("ALT+A"));
+ action->setShortcut(QKeySequence("CTRL+A"));
+
+ connect( pm1, SIGNAL(triggered(QAction*)), this, SLOT(onActivated(QAction*)));
+
+ delete pm2;
+ pm2 = mb->addMenu("accel1");
+
+ action1 = pm2->addAction( "&Open..." );
+ action1->setShortcut(Qt::Key_O);
+ connect(pm2, SIGNAL(triggered(QAction*)), this, SLOT(onActivated(QAction*)));
+
+ mb->show();
+ qApp->syncX();
+ qApp->processEvents();
+}
+
+void tst_QMenuBar::init()
+{
+ resetSlots();
+ resetCount();
+}
+
+void tst_QMenuBar::resetSlots()
+{
+ menu1->clear();
+ menu2->clear();
+ menu3->clear();
+ menu4->clear();
+ item1_A->clear();
+ item1_B->clear();
+ item2_C->clear();
+ item2_D->clear();
+ item2_E->clear();
+ item2_F->clear();
+ item2_G->clear();
+ item2_H->clear();
+}
+
+void tst_QMenuBar::resetCount()
+{
+ last_accel_id = 0;
+ activated_count = 0;
+}
+
+void tst_QMenuBar::onActivated( QAction* action )
+{
+ last_accel_id = action;
+ activated_count++;
+// printf( QString("acceleratorId: %1, count: %1\n").arg( i ).arg(activated_count) );
+}
+
+// On Mac/WinCE, native key events are needed to test menu action activation.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::accel()
+{
+ // create a popup menu with menu items set the accelerators later...
+ initSimpleMenubar();
+
+ // shortcuts won't work unless the window is active
+ QTRY_VERIFY( QApplication::activeWindow() );
+// QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_A, AltKey );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_A, Qt::ControlModifier );
+ QTest::qWait(300);
+
+ QCOMPARE( last_accel_id, action );
+}
+#endif
+
+// On Mac/WinCE, native key events are needed to test menu action activation.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::activatedCount()
+{
+ // create a popup menu with menu items set the accelerators later...
+ initSimpleMenubar();
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_A, Qt::ControlModifier );
+//wait(5000);
+ QCOMPARE( activated_count, 2 ); //1 from the popupmenu and 1 from the menubar
+}
+#endif
+
+void tst_QMenuBar::clear()
+{
+ mb->clear();
+ QVERIFY( (uint) mb->actions().size() == 0 );
+
+ mb->clear();
+ for (uint i=0; i<10; i++) {
+ QMenu *menu = mb->addMenu( QString("Menu %1"));
+ for (uint k=0; k<i; k++)
+ menu->addAction( QString("Item %1"));
+ QCOMPARE( (uint) mb->actions().size(), (uint)i+1 );
+ }
+ QCOMPARE( (uint) mb->actions().size(), 10u );
+
+ mb->clear();
+ QVERIFY( (uint) mb->actions().size() == 0 );
+}
+
+void tst_QMenuBar::count()
+{
+ mb->clear();
+ QVERIFY( mb->actions().size() == 0 );
+
+ for (uint i=0; i<10; i++) {
+ mb->addAction( QString("Menu %1"));
+ QCOMPARE( (uint) mb->actions().size(), (uint) i+1 );
+ }
+}
+
+void tst_QMenuBar::removeItem_data()
+{
+ QTest::addColumn<int>("removeIndex");
+ QTest::newRow( "first" ) << 0;
+ QTest::newRow( "middle" ) << 1;
+ QTest::newRow( "last" ) << 2;
+}
+
+// Basically the same test as removeItemAt, except that we remember and remove id's.
+void tst_QMenuBar::removeItem()
+{
+ mb->clear();
+
+ QMenu *pm;
+ pm = new QMenu( "stuff", mb );
+ pm->setTitle("Menu 1");
+ pm->addAction( QString("Item 10") );
+ QAction* action1 = mb->addMenu( pm );
+
+ pm = new QMenu( mb );
+ pm->setTitle("Menu 2");
+ pm->addAction( QString("Item 20") );
+ pm->addAction( QString("Item 21") );
+ QAction *action2 = mb->addMenu( pm );
+
+ pm = new QMenu( "Menu 3", mb );
+ pm->addAction( QString("Item 30") );
+ pm->addAction( QString("Item 31") );
+ pm->addAction( QString("Item 32") );
+ QAction *action3 = mb->addMenu( pm );
+
+ QList<QAction *> menuBarActions = mb->actions();
+
+ QCOMPARE( action1->text(), QString("Menu 1") );
+ QCOMPARE( action2->text(), QString("Menu 2") );
+ QCOMPARE( action3->text(), QString("Menu 3") );
+
+ QVERIFY( menuBarActions.at(0) == action1 );
+ QVERIFY( menuBarActions.at(1) == action2 );
+ QVERIFY( menuBarActions.at(2) == action3 );
+
+ // Ok, now that we know we have created the menu we expect, lets remove an item...
+ QFETCH( int, removeIndex );
+ switch (removeIndex )
+ {
+ case 0: {
+ mb->removeAction(action1);
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 2") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ }
+ break;
+ case 1: {
+ mb->removeAction(action2);
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ }
+ break;
+ case 2: {
+ mb->removeAction(action3);
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") );
+ }
+ break;
+ }
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QVERIFY( menuBarActions2.size() == 2 );
+}
+
+void tst_QMenuBar::removeItemAt_data()
+{
+ QTest::addColumn<int>("removeIndex");
+ QTest::newRow( "first" ) << 0;
+ QTest::newRow( "middle" ) << 1;
+ QTest::newRow( "last" ) << 2;
+}
+
+void tst_QMenuBar::removeItemAt()
+{
+ mb->clear();
+
+ QMenu *pm;
+ pm = new QMenu("Menu 1", mb);
+ pm->addAction( QString("Item 10") );
+ mb->addMenu( pm );
+
+ pm = new QMenu( "Menu 2", mb );
+ pm->addAction( QString("Item 20") );
+ pm->addAction( QString("Item 21") );
+ mb->addMenu( pm );
+
+ pm = new QMenu( "Menu 3", mb );
+ pm->addAction( QString("Item 30") );
+ pm->addAction( QString("Item 31") );
+ pm->addAction( QString("Item 32") );
+ mb->addMenu( pm );
+
+ QList<QAction *> menuBarActions = mb->actions();
+
+ QCOMPARE( menuBarActions.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions.at(1)->text(), QString("Menu 2") );
+ QCOMPARE( menuBarActions.at(2)->text(), QString("Menu 3") );
+
+ // Ok, now that we know we have created the menu we expect, lets remove an item...
+ QFETCH( int, removeIndex );
+ mb->removeAction(menuBarActions.at(removeIndex));
+ QList<QAction *> menuBarActions2 = mb->actions();
+ switch (removeIndex )
+ {
+ case 0:
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 2") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ break;
+ case 1:
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ break;
+ case 2:
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") );
+ break;
+ }
+
+ QVERIFY( menuBarActions2.size() == 2 );
+}
+
+void tst_QMenuBar::initComplexMenubar() // well, complex....
+{
+ mb->hide();
+ mb->clear();
+
+ delete pm1;
+ pm1 = mb->addMenu("Menu &1");
+ pm1->addAction( QString("Item A"), item1_A, SLOT(selected()), Qt::CTRL+Qt::Key_A );
+ pm1->addAction( QString("Item B"), item1_B, SLOT(selected()), Qt::CTRL+Qt::Key_B );
+
+ delete pm2;
+ pm2 = mb->addMenu("Menu &2");
+ pm2->addAction( QString("Item C"), item2_C, SLOT(selected()), Qt::CTRL+Qt::Key_C );
+ pm2->addAction( QString("Item D"), item2_D, SLOT(selected()), Qt::CTRL+Qt::Key_D );
+ pm2->addAction( QString("Item E"), item2_E, SLOT(selected()), Qt::CTRL+Qt::Key_E );
+ pm2->addAction( QString("Item F"), item2_F, SLOT(selected()), Qt::CTRL+Qt::Key_F );
+ pm2->addSeparator();
+ pm2->addAction( QString("Item G"), item2_G, SLOT(selected()), Qt::CTRL+Qt::Key_G );
+ pm2->addAction( QString("Item H"), item2_H, SLOT(selected()), Qt::CTRL+Qt::Key_H );
+
+ QAction *ac = mb->addAction( QString("M&enu 3"), menu3, SLOT(selected()));
+ ac->setShortcut(Qt::ALT+Qt::Key_J);
+ mb->show();
+}
+
+
+/*
+ Check the insert functions that create menu items.
+ For the moment i only check the strings and pixmaps. The rest are special cases which are
+ used less frequently.
+*/
+
+void tst_QMenuBar::insertItem_QString_QObject()
+{
+ initComplexMenubar();
+
+ QList<QAction *> actions = mb->actions();
+
+ QCOMPARE(actions.at(0)->text(), QString("Menu &1") );
+ QCOMPARE(actions.at(1)->text(), QString("Menu &2") );
+ QCOMPARE(actions.at(2)->text(), QString("M&enu 3") );
+ QVERIFY(actions.size() < 4); // there is no menu 4!
+}
+
+// On Mac/WinCE, native key events are needed to test menu action activation.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_accelKeys()
+{
+ initComplexMenubar();
+
+ // start with a bogus key that shouldn't trigger anything
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_I, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_C, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_B, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 1u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_D, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 1u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 1u);
+
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_J, Qt::AltModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 1u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 1u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 1u);
+}
+#endif
+
+// Qt/Mac,WinCE does not use the native popups/menubar.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_cursorKeys1()
+{
+ initComplexMenubar();
+
+ // start with a ALT + 1 that activates the first popupmenu
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_1, Qt::AltModifier );
+ // the Popupmenu should be visible now
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ // Simulate a cursor key down click
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ // and an Enter key
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been called
+ QCOMPARE(item1_B->selCount(), 1u); // and this should have been called by a signal now
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+}
+#endif
+
+// Qt/Mac,WinCE does not use the native popups/menubar.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_cursorKeys2()
+{
+ initComplexMenubar();
+
+ // select popupmenu2
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some cursor keys
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Left );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Right );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ // and an Enter key
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been caled
+ QCOMPARE(item1_B->selCount(), 0u); // and this should have been called by a signal ow
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 1u);
+}
+#endif
+
+/*!
+ If a popupmenu is active you can use Left to move to the menu to the left of it.
+ Qt/Mac,WinCE does not use the native popups/menubar.
+*/
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_cursorKeys3()
+{
+ initComplexMenubar();
+
+ // select Popupmenu 2
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some keys
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Left );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ // and press ENTER
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been called
+ QCOMPARE(item1_B->selCount(), 1u); // and this should have been called by a signal now
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+}
+#endif
+
+/*!
+ If a popupmenu is active you can use home to go quickly to the first item in the menu.
+*/
+void tst_QMenuBar::check_homeKey()
+{
+ // I'm temporarily shutting up this testcase.
+ // Seems like the behaviour i'm expecting isn't ok.
+ QVERIFY( TRUE );
+ return;
+
+ QEXPECT_FAIL( "0", "Popupmenu should respond to a Home key", Abort );
+
+ initComplexMenubar();
+
+ // select Popupmenu 2
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some keys
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Home );
+ // and press ENTER
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+// QVERIFY2( item2_C->selCount() == 1, "Popupmenu should respond to a Home key" );
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+ QCOMPARE(item2_E->selCount(), 0u);
+ QCOMPARE(item2_F->selCount(), 0u);
+ QCOMPARE(item2_G->selCount(), 0u);
+ QCOMPARE(item2_H->selCount(), 0u);
+}
+
+/*!
+ If a popupmenu is active you can use end to go quickly to the last item in the menu.
+*/
+void tst_QMenuBar::check_endKey()
+{
+ // I'm temporarily silenting this testcase.
+ // Seems like the behaviour i'm expecting isn't ok.
+ QVERIFY( TRUE );
+ return;
+
+ QEXPECT_FAIL( "0", "Popupmenu should respond to an End key", Abort );
+
+ initComplexMenubar();
+
+ // select Popupmenu 2
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some keys
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_End );
+ // and press ENTER
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+// QVERIFY2( item2_H->selCount() == 1, "Popupmenu should respond to an End key" );
+ QCOMPARE(item2_H->selCount(), 1u);//, "Popupmenu should respond to an End key");
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+ QCOMPARE(item2_E->selCount(), 0u);
+ QCOMPARE(item2_F->selCount(), 0u);
+ QCOMPARE(item2_G->selCount(), 0u);
+}
+
+/*!
+ If a popupmenu is active you can use esc to hide the menu and then the
+ menubar should become active.
+ If Down is pressed next the popup is activated again.
+*/
+
+// Qt/Mac,WinCE does not use the native popups/menubar.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_escKey()
+{
+ initComplexMenubar();
+
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( !pm2->isActiveWindow() );
+
+ // select Popupmenu 2
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier );
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( pm2->isActiveWindow() );
+
+ // If we press ESC, the popup should disappear
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Escape );
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( !pm2->isActiveWindow() );
+
+ if (!QApplication::style()->inherits("QWindowsStyle"))
+ return;
+
+ // If we press Down the popupmenu should be active again
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down );
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( pm2->isActiveWindow() );
+
+ // and press ENTER
+ QTest::keyClick( pm2, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QVERIFY2( item2_C->selCount() == 1, "Expected item 2C to be selected" );
+}
+#endif
+
+// void tst_QMenuBar::check_mouse1_data()
+// {
+// QTest::addColumn<QString>("popup_item");
+// QTest::addColumn<int>("itemA_count");
+// QTest::addColumn<int>("itemB_count");
+
+// QTest::newRow( "A" ) << QString( "Item A Ctrl+A" ) << 1 << 0;
+// QTest::newRow( "B" ) << QString( "Item B Ctrl+B" ) << 0 << 1;
+// }
+
+// /*!
+// Check if the correct signals are emitted if we select a popupmenu.
+// */
+// void tst_QMenuBar::check_mouse1()
+// {
+// if (QSystem::curStyle() == "Motif")
+// QSKIP("This fails in Motif due to a bug in the testing framework", SkipAll);
+// QFETCH( QString, popup_item );
+// QFETCH( int, itemA_count );
+// QFETCH( int, itemB_count );
+
+// initComplexMenubar();
+// QVERIFY( !pm1->isActiveWindow() );
+// QVERIFY( !pm2->isActiveWindow() );
+
+// QTest::qWait(1000);
+// QtTestMouse mouse;
+// mouse.mouseEvent( QtTestMouse::MouseClick, mb, "Menu &1", Qt::LeftButton );
+
+// QVERIFY( pm1->isActiveWindow() );
+// QVERIFY( !pm2->isActiveWindow() );
+
+// QTest::qWait(1000);
+// mouse.mouseEvent( QtTestMouse::MouseClick, pm1, popup_item, Qt::LeftButton );
+
+// QCOMPARE(menu3->selCount(), 0u);
+// QCOMPARE(menu4->selCount(), 0u);
+// QCOMPARE(item1_A->selCount(), (uint)itemA_count); // this option should have fired
+// QCOMPARE(item1_B->selCount(), (uint)itemB_count);
+// QCOMPARE(item2_C->selCount(), 0u);
+// QCOMPARE(item2_D->selCount(), 0u);
+// QCOMPARE(item2_E->selCount(), 0u);
+// QCOMPARE(item2_F->selCount(), 0u);
+// QCOMPARE(item2_G->selCount(), 0u);
+// }
+
+// void tst_QMenuBar::check_mouse2_data()
+// {
+// QTest::addColumn<QString>("label");
+// QTest::addColumn<int>("itemA_count");
+// QTest::addColumn<int>("itemB_count");
+// QTest::addColumn<int>("itemC_count");
+// QTest::addColumn<int>("itemD_count");
+// QTest::addColumn<int>("itemE_count");
+// QTest::addColumn<int>("itemF_count");
+// QTest::addColumn<int>("itemG_count");
+// QTest::addColumn<int>("itemH_count");
+// QTest::addColumn<int>("menu3_count");
+
+// QTest::newRow( "A" ) << QString( "Menu &1/Item A Ctrl+A" ) << 1 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "B" ) << QString( "Menu &1/Item B Ctrl+B" ) << 0 << 1 << 0 << 0 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "C" ) << QString( "Menu &2/Item C Ctrl+C" ) << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "D" ) << QString( "Menu &2/Item D Ctrl+D" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "E" ) << QString( "Menu &2/Item E Ctrl+E" ) << 0 << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0;
+// QTest::newRow( "F" ) << QString( "Menu &2/Item F Ctrl+F" ) << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 0 << 0;
+// QTest::newRow( "G" ) << QString( "Menu &2/Item G Ctrl+G" ) << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 0;
+// QTest::newRow( "H" ) << QString( "Menu &2/Item H Ctrl+H" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0;
+// QTest::newRow( "menu 3" ) << QString( "M&enu 3" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1;
+// }
+
+// /*!
+// Check if the correct signals are emitted if we select a popupmenu.
+// This time, we use a little bit more magic from the testframework.
+// */
+// void tst_QMenuBar::check_mouse2()
+// {
+// if (QSystem::curStyle() == "Motif")
+// QSKIP("This fails in Motif due to a bug in the testing framework", SkipAll);
+// QFETCH( QString, label );
+// QFETCH( int, itemA_count );
+// QFETCH( int, itemB_count );
+// QFETCH( int, itemC_count );
+// QFETCH( int, itemD_count );
+// QFETCH( int, itemE_count );
+// QFETCH( int, itemF_count );
+// QFETCH( int, itemG_count );
+// QFETCH( int, itemH_count );
+// QFETCH( int, menu3_count );
+
+// initComplexMenubar();
+// QtTestMouse mouse;
+// mouse.click( QtTestMouse::Menu, label, Qt::LeftButton );
+
+// // check if the correct signals have fired
+// QCOMPARE(menu3->selCount(), (uint)menu3_count);
+// QCOMPARE(menu4->selCount(), 0u);
+// QCOMPARE(item1_A->selCount(), (uint)itemA_count);
+// QCOMPARE(item1_B->selCount(), (uint)itemB_count);
+// QCOMPARE(item2_C->selCount(), (uint)itemC_count);
+// QCOMPARE(item2_D->selCount(), (uint)itemD_count);
+// QCOMPARE(item2_E->selCount(), (uint)itemE_count);
+// QCOMPARE(item2_F->selCount(), (uint)itemF_count);
+// QCOMPARE(item2_G->selCount(), (uint)itemG_count);
+// QCOMPARE(item2_H->selCount(), (uint)itemH_count);
+// }
+
+void
+tst_QMenuBar::allowActiveAndDisabled()
+{
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+ mb->hide();
+ mb->clear();
+
+ // Task 241043 : check that second menu is activated if only
+ // disabled menu items are added
+
+ QMenu fileMenu("&File");
+ // Task 241043 : check that second menu is activated
+ // if all items are disabled
+ QAction *act = fileMenu.addAction("Disabled");
+ act->setEnabled(false);
+
+ mb->addMenu(&fileMenu);
+ QMenu disabledMenu("Disabled");
+ disabledMenu.setEnabled(false);
+ QMenu activeMenu("Active");
+ mb->addMenu(&disabledMenu);
+ mb->addMenu(&activeMenu);
+ mb->show();
+
+
+ // Here we verify that AllowActiveAndDisabled correctly skips
+ // the disabled menu entry
+ QTest::keyClick(mb, Qt::Key_F, Qt::AltModifier );
+ QTest::keyClick(&fileMenu, (Qt::Key_Right));
+ if (qApp->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled))
+ QCOMPARE(mb->activeAction()->text(), disabledMenu.title());
+ else
+ QCOMPARE(mb->activeAction()->text(), activeMenu.title());
+
+ QTest::keyClick(mb, (Qt::Key_Left));
+ if (qApp->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled))
+ QCOMPARE(mb->activeAction()->text(), fileMenu.title());
+ else
+ QCOMPARE(mb->activeAction()->text(), fileMenu.title());
+
+ mb->hide();
+#endif //Q_WS_MAC
+}
+
+void tst_QMenuBar::check_altPress()
+{
+ if ( !qApp->style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation) ) {
+ QSKIP( QString( "this is not supposed to work in the %1 style. Skipping." ).
+ arg( qApp->style()->objectName() ).toAscii(), SkipAll );
+ }
+
+ initSimpleMenubar();
+
+ qApp->setActiveWindow(mw);
+ mw->setFocus();
+
+ QTest::keyClick( mw, Qt::Key_Alt );
+
+ QVERIFY( ::qobject_cast<QMenuBar *>(qApp->focusWidget()) );
+}
+
+// Qt/Mac,WinCE does not use the native popups/menubar.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_shortcutPress()
+{
+ initComplexMenubar();
+
+ qApp->setActiveWindow(mw);
+ QCOMPARE(menu3->selCount(), 0u);
+ QTest::keyClick(mw, Qt::Key_E, Qt::AltModifier);
+ QTest::qWait(200);
+ QCOMPARE(menu3->selCount(), 1u);
+ QVERIFY(!mb->activeAction());
+
+ QTest::keyClick(mw, Qt::Key_1, Qt::AltModifier );
+ QVERIFY(pm1->isActiveWindow());
+ QTest::keyClick(mb, Qt::Key_2);
+ QVERIFY(pm1->isActiveWindow());
+}
+#endif
+
+// Qt/Mac does not use the native popups/menubar.
+// Qt/CE uses native menubar.
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+void tst_QMenuBar::check_menuPosition()
+{
+ Menu menu;
+ initComplexMenubar();
+ menu.setTitle("&menu");
+ QRect availRect = QApplication::desktop()->availableGeometry(mw);
+ QRect screenRect = QApplication::desktop()->screenGeometry(mw);
+
+ while(menu.sizeHint().height() < (screenRect.height()*2/3)) {
+ menu.addAction("item");
+ }
+
+ QAction *menu_action = mw->menuBar()->addMenu(&menu);
+
+ qApp->setActiveWindow(mw);
+ qApp->processEvents();
+
+ //the menu should be below the menubar item
+ {
+ mw->move(availRect.topLeft());
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.bottom() + 1));
+ menu.close();
+ }
+
+ //the menu should be above the menubar item
+ {
+ mw->move(0,screenRect.bottom() - screenRect.height()/4); //just leave some place for the menubar
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.top() - menu.height()));
+ menu.close();
+ }
+
+ //the menu should be on the side of the menubar item and should be "stuck" to the bottom of the screen
+ {
+ mw->move(0,screenRect.y() + screenRect.height()/2); //put it in the middle
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QPoint firstPoint = QPoint(mbItemRect.right()+1, screenRect.bottom() - menu.height() + 1);
+ QPoint secondPoint = QPoint(mbItemRect.right()+1, availRect.bottom() - menu.height() + 1);
+ QVERIFY(menu.pos() == firstPoint || menu.pos() == secondPoint);
+ menu.close();
+ }
+
+ //in RTL, the menu should be stuck at the right of the action geometry
+ {
+ Qt::LayoutDirection dir = qApp->layoutDirection();
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ menu.clear();
+ QObject::connect(&menu, SIGNAL(aboutToShow()), &menu, SLOT(addActions()));
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QCOMPARE(menu.geometry().right(), mbItemRect.right());
+ menu.close();
+ qApp->setLayoutDirection(dir);
+ }
+}
+#endif
+
+void tst_QMenuBar::task223138_triggered()
+{
+ qRegisterMetaType<QAction *>("QAction *");
+ //we create a window with submenus and we check that both menubar and menus get the triggered signal
+ QMainWindow win;
+ QMenu *menu = win.menuBar()->addMenu("test");
+ QAction *top = menu->addAction("toplevelaction");
+ QMenu *submenu = menu->addMenu("nested menu");
+ QAction *action = submenu->addAction("nested action");
+
+ QSignalSpy menubarSpy(win.menuBar(), SIGNAL(triggered(QAction*)));
+ QSignalSpy menuSpy(menu, SIGNAL(triggered(QAction*)));
+ QSignalSpy submenuSpy(submenu, SIGNAL(triggered(QAction*)));
+
+ //let's trigger the first action
+ top->trigger();
+
+ QCOMPARE(menubarSpy.count(), 1);
+ QCOMPARE(menuSpy.count(), 1);
+ QCOMPARE(submenuSpy.count(), 0);
+
+ menubarSpy.clear();
+ menuSpy.clear();
+ submenuSpy.clear();
+
+ //let's trigger the sub action
+ action->trigger();
+ QCOMPARE(menubarSpy.count(), 1);
+ QCOMPARE(menuSpy.count(), 1);
+ QCOMPARE(submenuSpy.count(), 1);
+}
+
+void tst_QMenuBar::task256322_highlight()
+{
+ QMainWindow win;
+ win.menuBar()->setNativeMenuBar(false); //we can't check the geometry of native menubars
+ QMenu menu;
+ QAction *file = win.menuBar()->addMenu(&menu);
+ file->setText("file");
+ QMenu menu2;
+ QAction *file2 = win.menuBar()->addMenu(&menu2);
+ file2->setText("file2");
+ QAction *nothing = win.menuBar()->addAction("nothing");
+
+ win.show();
+ QTest::qWait(200);
+
+ QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center());
+ QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file).center());
+ QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center());
+ QTRY_VERIFY(menu.isVisible());
+ QVERIFY(!menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), file);
+
+ QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file2).center());
+ QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file2).center());
+ QTRY_VERIFY(!menu.isVisible());
+ QVERIFY(menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), file2);
+ QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file2).center());
+
+ QPoint nothingCenter = win.menuBar()->actionGeometry(nothing).center();
+ QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, nothingCenter);
+ QTest::mouseMove(win.menuBar(), nothingCenter);
+ QTRY_VERIFY(!menu2.isVisible());
+ QVERIFY(!menu.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), nothing);
+ QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, nothingCenter);
+}
+
+void tst_QMenuBar::menubarSizeHint()
+{
+ struct MyStyle : public QWindowsStyle
+ {
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0, const QWidget * widget = 0 ) const
+ {
+ // I chose strange values (prime numbers to be more sure that the size of the menubar is correct)
+ switch (metric)
+ {
+ case QStyle::PM_MenuBarItemSpacing:
+ return 7;
+ case PM_MenuBarHMargin:
+ return 13;
+ case PM_MenuBarVMargin:
+ return 11;
+ case PM_MenuBarPanelWidth:
+ return 1;
+ default:
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+ }
+ }
+ } style;
+
+ QMenuBar mb;
+ mb.setNativeMenuBar(false); //we can't check the geometry of native menubars
+
+ mb.setStyle(&style);
+ //this is a list of arbitrary strings so that we check the geometry
+ QStringList list = QStringList() << "trer" << "ezrfgtgvqd" << "sdgzgzerzerzer" << "eerzertz" << "er";
+ foreach(QString str, list)
+ mb.addAction(str);
+
+ const int panelWidth = style.pixelMetric(QStyle::PM_MenuBarPanelWidth);
+ const int hmargin = style.pixelMetric(QStyle::PM_MenuBarHMargin);
+ const int vmargin = style.pixelMetric(QStyle::PM_MenuBarVMargin);
+ const int spacing = style.pixelMetric(QStyle::PM_MenuBarItemSpacing);
+
+ mb.show();
+ QRect result;
+ foreach(QAction *action, mb.actions()) {
+ const QRect actionRect = mb.actionGeometry(action);
+ if (!result.isNull()) //this is the first item
+ QCOMPARE(actionRect.left() - result.right() - 1, spacing);
+ result |= actionRect;
+ QCOMPARE(result.x(), panelWidth + hmargin + spacing);
+ QCOMPARE(result.y(), panelWidth + vmargin);
+ }
+
+ //this code is copied from QMenuBar
+ //there is no public member that allows to initialize a styleoption instance
+ QStyleOptionMenuItem opt;
+ opt.rect = mb.rect();
+ opt.menuRect = mb.rect();
+ opt.state = QStyle::State_None;
+ opt.menuItemType = QStyleOptionMenuItem::Normal;
+ opt.checkType = QStyleOptionMenuItem::NotCheckable;
+ opt.palette = mb.palette();
+
+ QSize resSize = QSize(result.x(), result.y()) + result.size()
+ + QSize(panelWidth + hmargin, panelWidth + vmargin);
+
+
+ resSize = style.sizeFromContents(QStyle::CT_MenuBar, &opt,
+ resSize.expandedTo(QApplication::globalStrut()),
+ &mb);
+
+ QCOMPARE(resSize, mb.sizeHint());
+}
+
+// On Mac, do not test the menubar with escape key.
+#ifndef Q_WS_MAC
+void tst_QMenuBar::taskQTBUG4965_escapeEaten()
+{
+ QMenuBar menubar;
+ QMenu menu("menu1");
+ QAction *first = menubar.addMenu(&menu);
+ menu.addAction("quit", &menubar, SLOT(close()), QKeySequence("ESC"));
+ menubar.show();
+ QApplication::setActiveWindow(&menubar);
+ QTest::qWaitForWindowShown(&menubar);
+ menubar.setActiveAction(first);
+ QTRY_VERIFY(menu.isVisible());
+ QCOMPARE(menubar.activeAction(), first);
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Escape);
+ QVERIFY(!menu.isVisible());
+ QTRY_VERIFY(menubar.hasFocus());
+ QCOMPARE(menubar.activeAction(), first);
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Escape);
+ QVERIFY(!menubar.activeAction());
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Escape); //now the action should be triggered
+ QTRY_VERIFY(!menubar.isVisible());
+}
+#endif
+
+void tst_QMenuBar::taskQTBUG11823_crashwithInvisibleActions()
+{
+ QMenuBar menubar;
+ menubar.setNativeMenuBar(false); //we can't check the geometry of native menubars
+
+ QAction * m = menubar.addAction( "&m" );
+ QAction * a = menubar.addAction( "&a" );
+
+ menubar.show();
+ QTest::qWaitForWindowShown(&menubar);
+ QApplication::setActiveWindow(&menubar);
+ menubar.setActiveAction(m);
+ QCOMPARE(menubar.activeAction(), m);
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Right);
+ QCOMPARE(menubar.activeAction(), a);
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Right);
+ QCOMPARE(menubar.activeAction(), m);
+ a->setVisible(false);
+
+ menubar.setActiveAction(m);
+ QCOMPARE(menubar.activeAction(), m); //the active action shouldn't have changed
+
+ //it used to crash here because the action is invisible
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Right);
+ QCOMPARE(menubar.activeAction(), m); //the active action shouldn't have changed
+}
+
+QTEST_MAIN(tst_QMenuBar)
+#include "tst_qmenubar.moc"
diff --git a/tests/auto/widgets/widgets/qplaintextedit/.gitignore b/tests/auto/widgets/widgets/qplaintextedit/.gitignore
new file mode 100644
index 0000000000..5d47310409
--- /dev/null
+++ b/tests/auto/widgets/widgets/qplaintextedit/.gitignore
@@ -0,0 +1 @@
+tst_qplaintextedit
diff --git a/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro b/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro
new file mode 100644
index 0000000000..feac5e3f43
--- /dev/null
+++ b/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += gui-private
+
+INCLUDEPATH += ../
+
+HEADERS +=
+SOURCES += tst_qplaintextedit.cpp
+
diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
new file mode 100644
index 0000000000..d847f295e0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
@@ -0,0 +1,1524 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qtextedit.h>
+#include <qtextcursor.h>
+#include <qtextlist.h>
+#include <qdebug.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qtextbrowser.h>
+#include <private/qwidgettextcontrol_p.h>
+#include <qscrollbar.h>
+#include <qtextobject.h>
+
+#include <qabstracttextdocumentlayout.h>
+#include <qtextdocumentfragment.h>
+
+#include "qplaintextedit.h"
+
+//Used in copyAvailable
+typedef QPair<Qt::Key, Qt::KeyboardModifier> keyPairType;
+typedef QList<keyPairType> pairListType;
+Q_DECLARE_METATYPE(pairListType);
+Q_DECLARE_METATYPE(keyPairType);
+Q_DECLARE_METATYPE(QList<bool>);
+
+#ifdef Q_WS_MAC
+#include <Carbon/Carbon.h>
+#endif
+
+QT_FORWARD_DECLARE_CLASS(QPlainTextEdit)
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/widgets/qtextedit.h gui/widgets/qtextedit.cpp
+
+class tst_QPlainTextEdit : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QPlainTextEdit();
+
+public slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+#ifndef QT_NO_CLIPBOARD
+ void clearMustNotChangeClipboard();
+#endif
+ void clearMustNotResetRootFrameMarginToDefault();
+ void paragSeparatorOnPlaintextAppend();
+#ifndef QT_NO_CLIPBOARD
+ void selectAllSetsNotSelection();
+#endif
+ void asciiTab();
+ void setDocument();
+ void emptyAppend();
+ void appendOnEmptyDocumentShouldReuseInitialParagraph();
+ void cursorPositionChanged();
+ void setTextCursor();
+#ifndef QT_NO_CLIPBOARD
+ void undoAvailableAfterPaste();
+#endif
+ void undoRedoAvailableRepetition();
+ void appendShouldNotTouchTheSelection();
+ void backspace();
+ void shiftBackspace();
+ void undoRedo();
+ void preserveCharFormatInAppend();
+#ifndef QT_NO_CLIPBOARD
+ void copyAndSelectAllInReadonly();
+#endif
+ void ctrlAltInput();
+ void noPropertiesOnDefaultTextEditCharFormat();
+ void setPlainTextShouldEmitTextChangedOnce();
+ void overwriteMode();
+ void shiftDownInLineLastShouldSelectToEnd_data();
+ void shiftDownInLineLastShouldSelectToEnd();
+ void undoRedoShouldRepositionTextEditCursor();
+ void lineWrapModes();
+ void mouseCursorShape();
+ void implicitClear();
+ void undoRedoAfterSetContent();
+ void numPadKeyNavigation();
+ void moveCursor();
+#ifndef QT_NO_CLIPBOARD
+ void mimeDataReimplementations();
+#endif
+ void shiftEnterShouldInsertLineSeparator();
+ void selectWordsFromStringsContainingSeparators_data();
+ void selectWordsFromStringsContainingSeparators();
+#ifndef QT_NO_CLIPBOARD
+ void canPaste();
+ void copyAvailable_data();
+ void copyAvailable();
+#endif
+ void ensureCursorVisibleOnInitialShow();
+ void setTextInsideResizeEvent();
+ void colorfulAppend();
+ void ensureVisibleWithRtl();
+ void preserveCharFormatAfterSetPlainText();
+ void extraSelections();
+ void adjustScrollbars();
+ void textObscuredByScrollbars();
+ void setTextPreservesUndoRedoEnabled();
+ void wordWrapProperty();
+ void lineWrapProperty();
+ void selectionChanged();
+ void blockCountChanged();
+ void insertAndScrollToBottom();
+
+private:
+ void createSelection();
+ int blockCount() const;
+ int lineCount() const;
+ bool nativeClipboardWorking();
+
+ QPlainTextEdit *ed;
+ qreal rootFrameMargin;
+};
+
+bool tst_QPlainTextEdit::nativeClipboardWorking()
+{
+#ifdef Q_WS_MAC
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ return status == noErr;
+#endif
+ return true;
+}
+
+// Testing get/set functions
+void tst_QPlainTextEdit::getSetCheck()
+{
+ QPlainTextEdit obj1;
+ // QTextDocument * QPlainTextEdit::document()
+ // void QPlainTextEdit::setDocument(QTextDocument *)
+ QTextDocument *var1 = new QTextDocument;
+ var1->setDocumentLayout(new QPlainTextDocumentLayout(var1));
+ obj1.setDocument(var1);
+ QCOMPARE(var1, obj1.document());
+ obj1.setDocument((QTextDocument *)0);
+ QVERIFY(var1 != obj1.document()); // QPlainTextEdit creates a new document when setting 0
+ QVERIFY((QTextDocument *)0 != obj1.document());
+ delete var1;
+
+
+ // bool QPlainTextEdit::tabChangesFocus()
+ // void QPlainTextEdit::setTabChangesFocus(bool)
+ obj1.setTabChangesFocus(false);
+ QCOMPARE(false, obj1.tabChangesFocus());
+ obj1.setTabChangesFocus(true);
+ QCOMPARE(true, obj1.tabChangesFocus());
+
+ // LineWrapMode QPlainTextEdit::lineWrapMode()
+ // void QPlainTextEdit::setLineWrapMode(LineWrapMode)
+ obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::NoWrap));
+ QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::NoWrap), obj1.lineWrapMode());
+ obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::WidgetWidth));
+ QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::WidgetWidth), obj1.lineWrapMode());
+// obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedPixelWidth));
+// QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedPixelWidth), obj1.lineWrapMode());
+// obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedColumnWidth));
+// QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedColumnWidth), obj1.lineWrapMode());
+
+
+ // bool QPlainTextEdit::overwriteMode()
+ // void QPlainTextEdit::setOverwriteMode(bool)
+ obj1.setOverwriteMode(false);
+ QCOMPARE(false, obj1.overwriteMode());
+ obj1.setOverwriteMode(true);
+ QCOMPARE(true, obj1.overwriteMode());
+
+ // int QPlainTextEdit::tabStopWidth()
+ // void QPlainTextEdit::setTabStopWidth(int)
+ obj1.setTabStopWidth(0);
+ QCOMPARE(0, obj1.tabStopWidth());
+ obj1.setTabStopWidth(INT_MIN);
+ QCOMPARE(0, obj1.tabStopWidth()); // Makes no sense to set a negative tabstop value
+#if defined(QT_ARCH_WINDOWSCE)
+ // due to rounding error in qRound when qreal==float
+ // we cannot use INT_MAX for this check
+ obj1.setTabStopWidth(SHRT_MAX*2);
+ QCOMPARE(SHRT_MAX*2, obj1.tabStopWidth());
+#else
+ obj1.setTabStopWidth(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.tabStopWidth());
+#endif
+
+}
+
+class QtTestDocumentLayout : public QAbstractTextDocumentLayout
+{
+ Q_OBJECT
+public:
+ inline QtTestDocumentLayout(QPlainTextEdit *edit, QTextDocument *doc, int &itCount)
+ : QAbstractTextDocumentLayout(doc), useBiggerSize(false), ed(edit), iterationCounter(itCount) {}
+
+ virtual void draw(QPainter *, const QAbstractTextDocumentLayout::PaintContext &) {}
+
+ virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const { return 0; }
+
+ virtual void documentChanged(int, int, int) {}
+
+ virtual int pageCount() const { return 1; }
+
+ virtual QSizeF documentSize() const { return usedSize; }
+
+ virtual QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
+ virtual QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
+
+ bool useBiggerSize;
+ QSize usedSize;
+
+ QPlainTextEdit *ed;
+
+ int &iterationCounter;
+};
+
+tst_QPlainTextEdit::tst_QPlainTextEdit()
+{}
+
+void tst_QPlainTextEdit::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QPlainTextEdit::init()
+{
+ ed = new QPlainTextEdit(0);
+ rootFrameMargin = ed->document()->documentMargin();
+}
+
+void tst_QPlainTextEdit::cleanup()
+{
+ delete ed;
+ ed = 0;
+}
+
+
+void tst_QPlainTextEdit::createSelection()
+{
+ QTest::keyClicks(ed, "Hello World");
+ /* go to start */
+#ifndef Q_WS_MAC
+ QTest::keyClick(ed, Qt::Key_Home, Qt::ControlModifier);
+#else
+ QTest::keyClick(ed, Qt::Key_Home);
+#endif
+ QCOMPARE(ed->textCursor().position(), 0);
+ /* select until end of text */
+#ifndef Q_WS_MAC
+ QTest::keyClick(ed, Qt::Key_End, Qt::ControlModifier | Qt::ShiftModifier);
+#else
+ QTest::keyClick(ed, Qt::Key_End, Qt::ShiftModifier);
+#endif
+ QCOMPARE(ed->textCursor().position(), 11);
+}
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::clearMustNotChangeClipboard()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+ ed->textCursor().insertText("Hello World");
+ QString txt("This is different text");
+ QApplication::clipboard()->setText(txt);
+ ed->clear();
+ QCOMPARE(QApplication::clipboard()->text(), txt);
+}
+#endif
+
+void tst_QPlainTextEdit::clearMustNotResetRootFrameMarginToDefault()
+{
+ QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
+ ed->clear();
+ QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
+}
+
+
+void tst_QPlainTextEdit::paragSeparatorOnPlaintextAppend()
+{
+ ed->appendPlainText("Hello\nWorld");
+ int cnt = 0;
+ QTextBlock blk = ed->document()->begin();
+ while (blk.isValid()) {
+ ++cnt;
+ blk = blk.next();
+ }
+ QCOMPARE(cnt, 2);
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::selectAllSetsNotSelection()
+{
+ if (!QApplication::clipboard()->supportsSelection())
+ QSKIP("Test only relevant for systems with selection", SkipAll);
+
+ QApplication::clipboard()->setText(QString("foobar"), QClipboard::Selection);
+ QVERIFY(QApplication::clipboard()->text(QClipboard::Selection) == QString("foobar"));
+
+ ed->insertPlainText("Hello World");
+ ed->selectAll();
+
+ QCOMPARE(QApplication::clipboard()->text(QClipboard::Selection), QString::fromAscii("foobar"));
+}
+#endif
+
+void tst_QPlainTextEdit::asciiTab()
+{
+ QPlainTextEdit edit;
+ edit.setPlainText("\t");
+ edit.show();
+ qApp->processEvents();
+ QCOMPARE(edit.toPlainText().at(0), QChar('\t'));
+}
+
+void tst_QPlainTextEdit::setDocument()
+{
+ QTextDocument *document = new QTextDocument(ed);
+ document->setDocumentLayout(new QPlainTextDocumentLayout(document));
+ QTextCursor(document).insertText("Test");
+ ed->setDocument(document);
+ QCOMPARE(ed->toPlainText(), QString("Test"));
+}
+
+
+int tst_QPlainTextEdit::blockCount() const
+{
+ int blocks = 0;
+ for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
+ ++blocks;
+ return blocks;
+}
+
+int tst_QPlainTextEdit::lineCount() const
+{
+ int lines = 0;
+ for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next()) {
+ ed->document()->documentLayout()->blockBoundingRect(block);
+ lines += block.layout()->lineCount();
+ }
+ return lines;
+}
+
+// Supporter issue #56783
+void tst_QPlainTextEdit::emptyAppend()
+{
+ ed->appendPlainText("Blah");
+ QCOMPARE(blockCount(), 1);
+ ed->appendPlainText(QString::null);
+ QCOMPARE(blockCount(), 2);
+ ed->appendPlainText(QString(" "));
+ QCOMPARE(blockCount(), 3);
+}
+
+void tst_QPlainTextEdit::appendOnEmptyDocumentShouldReuseInitialParagraph()
+{
+ QCOMPARE(blockCount(), 1);
+ ed->appendPlainText("Blah");
+ QCOMPARE(blockCount(), 1);
+}
+
+
+class CursorPositionChangedRecorder : public QObject
+{
+ Q_OBJECT
+public:
+ inline CursorPositionChangedRecorder(QPlainTextEdit *ed)
+ : editor(ed)
+ {
+ connect(editor, SIGNAL(cursorPositionChanged()), this, SLOT(recordCursorPos()));
+ }
+
+ QList<int> cursorPositions;
+
+private slots:
+ void recordCursorPos()
+ {
+ cursorPositions.append(editor->textCursor().position());
+ }
+
+private:
+ QPlainTextEdit *editor;
+};
+
+void tst_QPlainTextEdit::cursorPositionChanged()
+{
+ QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
+
+ spy.clear();
+ QTest::keyClick(ed, Qt::Key_A);
+ QCOMPARE(spy.count(), 1);
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+ cursor.movePosition(QTextCursor::End);
+ spy.clear();
+ cursor.insertText("Test");
+ QCOMPARE(spy.count(), 0);
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+ cursor.movePosition(QTextCursor::Start);
+ spy.clear();
+ cursor.insertText("Test");
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ QTest::keyClick(ed, Qt::Key_Left);
+ QCOMPARE(spy.count(), 1);
+
+ CursorPositionChangedRecorder spy2(ed);
+ QVERIFY(ed->textCursor().position() > 0);
+ ed->setPlainText("Hello World");
+ QCOMPARE(spy2.cursorPositions.count(), 1);
+ QCOMPARE(spy2.cursorPositions.at(0), 0);
+ QCOMPARE(ed->textCursor().position(), 0);
+}
+
+void tst_QPlainTextEdit::setTextCursor()
+{
+ QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
+
+ ed->setPlainText("Test");
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+
+ spy.clear();
+
+ ed->setTextCursor(cursor);
+ QCOMPARE(spy.count(), 1);
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::undoAvailableAfterPaste()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+
+ QSignalSpy spy(ed->document(), SIGNAL(undoAvailable(bool)));
+
+ const QString txt("Test");
+ QApplication::clipboard()->setText(txt);
+ ed->paste();
+ QVERIFY(spy.count() >= 1);
+ QCOMPARE(ed->toPlainText(), txt);
+}
+#endif
+
+class UndoRedoRecorder : public QObject
+{
+ Q_OBJECT
+public:
+ UndoRedoRecorder(QTextDocument *doc)
+ : undoRepetitions(false)
+ , redoRepetitions(false)
+ , undoCount(0)
+ , redoCount(0)
+ {
+ connect(doc, SIGNAL(undoAvailable(bool)), this, SLOT(undoAvailable(bool)));
+ connect(doc, SIGNAL(redoAvailable(bool)), this, SLOT(redoAvailable(bool)));
+ }
+
+ bool undoRepetitions;
+ bool redoRepetitions;
+
+private slots:
+ void undoAvailable(bool enabled) {
+ if (undoCount > 0 && enabled == lastUndoEnabled)
+ undoRepetitions = true;
+
+ ++undoCount;
+ lastUndoEnabled = enabled;
+ }
+
+ void redoAvailable(bool enabled) {
+ if (redoCount > 0 && enabled == lastRedoEnabled)
+ redoRepetitions = true;
+
+ ++redoCount;
+ lastRedoEnabled = enabled;
+ }
+
+private:
+ bool lastUndoEnabled;
+ bool lastRedoEnabled;
+
+ int undoCount;
+ int redoCount;
+};
+
+void tst_QPlainTextEdit::undoRedoAvailableRepetition()
+{
+ UndoRedoRecorder spy(ed->document());
+
+ ed->textCursor().insertText("ABC\n\nDEF\n\nGHI\n");
+ ed->textCursor().insertText("foo\n");
+ ed->textCursor().insertText("bar\n");
+ ed->undo(); ed->undo(); ed->undo();
+ ed->redo(); ed->redo(); ed->redo();
+
+ QVERIFY(!spy.undoRepetitions);
+ QVERIFY(!spy.redoRepetitions);
+}
+
+void tst_QPlainTextEdit::appendShouldNotTouchTheSelection()
+{
+ QTextCursor cursor(ed->document());
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertText("H", fmt);
+ fmt.setForeground(Qt::red);
+ cursor.insertText("ey", fmt);
+
+ cursor.insertText("some random text inbetween");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
+ QCOMPARE(cursor.selectedText(), QString("Hey"));
+
+ ed->setTextCursor(cursor);
+ QVERIFY(ed->textCursor().hasSelection());
+
+ ed->appendHtml("<b>Some Bold Text</b>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
+}
+
+void tst_QPlainTextEdit::backspace()
+{
+ QTextCursor cursor = ed->textCursor();
+
+ QTextListFormat listFmt;
+ listFmt.setStyle(QTextListFormat::ListDisc);
+ listFmt.setIndent(1);
+ cursor.insertList(listFmt);
+ cursor.insertText("A");
+
+ ed->setTextCursor(cursor);
+
+ // delete 'A'
+ QTest::keyClick(ed, Qt::Key_Backspace);
+ QVERIFY(ed->textCursor().currentList());
+ // delete list
+ QTest::keyClick(ed, Qt::Key_Backspace);
+ QVERIFY(!ed->textCursor().currentList());
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
+ // outdent paragraph
+ QTest::keyClick(ed, Qt::Key_Backspace);
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
+}
+
+void tst_QPlainTextEdit::shiftBackspace()
+{
+ QTextCursor cursor = ed->textCursor();
+
+ QTextListFormat listFmt;
+ listFmt.setStyle(QTextListFormat::ListDisc);
+ listFmt.setIndent(1);
+ cursor.insertList(listFmt);
+ cursor.insertText("A");
+
+ ed->setTextCursor(cursor);
+
+ // delete 'A'
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
+ QVERIFY(ed->textCursor().currentList());
+ // delete list
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
+ QVERIFY(!ed->textCursor().currentList());
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
+ // outdent paragraph
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
+}
+
+void tst_QPlainTextEdit::undoRedo()
+{
+ ed->clear();
+ QTest::keyClicks(ed, "abc d");
+ QCOMPARE(ed->toPlainText(), QString("abc d"));
+ ed->undo();
+ QCOMPARE(ed->toPlainText(), QString());
+ ed->redo();
+ QCOMPARE(ed->toPlainText(), QString("abc d"));
+#ifdef Q_WS_WIN
+ // shortcut for undo
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::AltModifier);
+ QCOMPARE(ed->toPlainText(), QString());
+ // shortcut for redo
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier|Qt::AltModifier);
+ QCOMPARE(ed->toPlainText(), QString("abc d"));
+#endif
+}
+
+// Task #70465
+void tst_QPlainTextEdit::preserveCharFormatInAppend()
+{
+ ed->appendHtml("First para");
+ ed->appendHtml("<b>Second para</b>");
+ ed->appendHtml("third para");
+
+ QTextCursor cursor(ed->textCursor());
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
+ QCOMPARE(cursor.block().text(), QString("First para"));
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Bold);
+ QCOMPARE(cursor.block().text(), QString("Second para"));
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
+ QCOMPARE(cursor.block().text(), QString("third para"));
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::copyAndSelectAllInReadonly()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+
+ ed->setReadOnly(true);
+ ed->setPlainText("Hello World");
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.clearSelection();
+ ed->setTextCursor(cursor);
+ QVERIFY(!ed->textCursor().hasSelection());
+
+ QCOMPARE(ed->toPlainText(), QString("Hello World"));
+
+ // shouldn't do anything
+ QTest::keyClick(ed, Qt::Key_A);
+
+ QCOMPARE(ed->toPlainText(), QString("Hello World"));
+
+ QTest::keyClick(ed, Qt::Key_A, Qt::ControlModifier);
+
+ QVERIFY(ed->textCursor().hasSelection());
+
+ QApplication::clipboard()->setText(QString());
+ QVERIFY(QApplication::clipboard()->text().isEmpty());
+
+ QTest::keyClick(ed, Qt::Key_C, Qt::ControlModifier);
+ QCOMPARE(QApplication::clipboard()->text(), QString("Hello World"));
+}
+#endif
+
+void tst_QPlainTextEdit::ctrlAltInput()
+{
+ QTest::keyClick(ed, Qt::Key_At, Qt::ControlModifier | Qt::AltModifier);
+ QCOMPARE(ed->toPlainText(), QString("@"));
+}
+
+void tst_QPlainTextEdit::noPropertiesOnDefaultTextEditCharFormat()
+{
+ // there should be no properties set on the default/initial char format
+ // on a text edit. Font properties instead should be taken from the
+ // widget's font (in sync with defaultFont property in document) and the
+ // foreground color should be taken from the palette.
+ QCOMPARE(ed->textCursor().charFormat().properties().count(), 0);
+}
+
+void tst_QPlainTextEdit::setPlainTextShouldEmitTextChangedOnce()
+{
+ QSignalSpy spy(ed, SIGNAL(textChanged()));
+ ed->setPlainText("Yankee Doodle");
+ QCOMPARE(spy.count(), 1);
+ ed->setPlainText("");
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QPlainTextEdit::overwriteMode()
+{
+ QVERIFY(!ed->overwriteMode());
+ QTest::keyClicks(ed, "Some first text");
+
+ QCOMPARE(ed->toPlainText(), QString("Some first text"));
+
+ ed->setOverwriteMode(true);
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.setPosition(5);
+ ed->setTextCursor(cursor);
+
+ QTest::keyClicks(ed, "shiny");
+ QCOMPARE(ed->toPlainText(), QString("Some shiny text"));
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+
+ QTest::keyClick(ed, Qt::Key_Enter);
+
+ ed->setOverwriteMode(false);
+ QTest::keyClicks(ed, "Second paragraph");
+
+ QCOMPARE(blockCount(), 2);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::EndOfBlock);
+
+ QCOMPARE(cursor.position(), 15);
+ ed->setTextCursor(cursor);
+
+ ed->setOverwriteMode(true);
+
+ QTest::keyClicks(ed, " blah");
+
+ QCOMPARE(blockCount(), 2);
+
+ QTextBlock block = ed->document()->begin();
+ QCOMPARE(block.text(), QString("Some shiny text blah"));
+ block = block.next();
+ QCOMPARE(block.text(), QString("Second paragraph"));
+}
+
+void tst_QPlainTextEdit::shiftDownInLineLastShouldSelectToEnd_data()
+{
+ // shift cursor-down in the last line should select to the end of the document
+
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<int>("totalLineCount");
+
+ QTest::newRow("1") << QString("Foo\nBar") << 2;
+ QTest::newRow("2") << QString("Foo\nBar") + QChar(QChar::LineSeparator) + QString("Baz") << 3;
+}
+
+void tst_QPlainTextEdit::shiftDownInLineLastShouldSelectToEnd()
+{
+ QFETCH(QString, input);
+ QFETCH(int, totalLineCount);
+
+ ed->setPlainText(input);
+ ed->show();
+
+ // ensure we're layouted
+ for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
+ ed->document()->documentLayout()->blockBoundingRect(block);
+
+ QCOMPARE(blockCount(), 2);
+
+ int lineCount = 0;
+ for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
+ lineCount += block.layout()->lineCount();
+ QCOMPARE(lineCount, totalLineCount);
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+
+ for (int i = 0; i < lineCount; ++i) {
+ QTest::keyClick(ed, Qt::Key_Down, Qt::ShiftModifier);
+ }
+
+ input.replace(QLatin1Char('\n'), QChar(QChar::ParagraphSeparator));
+ QCOMPARE(ed->textCursor().selectedText(), input);
+ QVERIFY(ed->textCursor().atEnd());
+
+ // also test that without shift modifier the cursor does not move to the end
+ // for Key_Down in the last line
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+ for (int i = 0; i < lineCount; ++i) {
+ QTest::keyClick(ed, Qt::Key_Down);
+ }
+ QVERIFY(!ed->textCursor().atEnd());
+}
+
+void tst_QPlainTextEdit::undoRedoShouldRepositionTextEditCursor()
+{
+ ed->setPlainText("five\nlines\nin\nthis\ntextedit");
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+
+ ed->setUndoRedoEnabled(false);
+ ed->setUndoRedoEnabled(true);
+
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+
+ cursor.insertText("Blah");
+
+ QVERIFY(ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+
+ QVERIFY(QMetaObject::invokeMethod(ed, "undo"));
+
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(ed->document()->isRedoAvailable());
+
+ QCOMPARE(ed->textCursor().position(), 0);
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+
+ QVERIFY(QMetaObject::invokeMethod(ed, "redo"));
+
+ QVERIFY(ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+
+ QCOMPARE(ed->textCursor().position(), 4);
+}
+
+void tst_QPlainTextEdit::lineWrapModes()
+{
+ QWidget *window = new QWidget;
+ ed->setParent(window);
+ window->show();
+ ed->show();
+ ed->setPlainText("a b c d e f g h i j k l m n o p q r s t u v w x y z");
+ ed->setLineWrapMode(QPlainTextEdit::NoWrap);
+ QCOMPARE(lineCount(), 1);
+ ed->setLineWrapMode(QPlainTextEdit::WidgetWidth);
+
+ // QPlainTextEdit does lazy line layout on resize, only for the visible blocks.
+ // We thus need to make it wide enough to show something visible.
+ int minimumWidth = 2 * ed->document()->documentMargin();
+ minimumWidth += ed->fontMetrics().width(QLatin1Char('a'));
+ minimumWidth += ed->frameWidth();
+ ed->resize(minimumWidth, 1000);
+ QCOMPARE(lineCount(), 26);
+ ed->setParent(0);
+ delete window;
+}
+
+void tst_QPlainTextEdit::mouseCursorShape()
+{
+#ifndef QT_NO_CURSOR
+ // always show an IBeamCursor, see change 170146
+ QVERIFY(!ed->isReadOnly());
+ QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
+
+ ed->setReadOnly(true);
+ QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
+
+ ed->setPlainText("Foo");
+ QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
+#endif
+}
+
+void tst_QPlainTextEdit::implicitClear()
+{
+ // test that QPlainTextEdit::setHtml, etc. avoid calling clear() but instead call
+ // QTextDocument::setHtml/etc. instead, which also clear the contents and
+ // cached resource but preserve manually added resources. setHtml on a textedit
+ // should behave the same as on a document with respect to that.
+ // see also clearResources() autotest in qtextdocument
+
+ // regular resource for QTextDocument
+ QUrl testUrl(":/foobar");
+ QVariant testResource("hello world");
+
+ ed->document()->addResource(QTextDocument::ImageResource, testUrl, testResource);
+ QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ ed->setPlainText("Blah");
+ QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ ed->setPlainText("<b>Blah</b>");
+ QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ ed->clear();
+ QVERIFY(!ed->document()->resource(QTextDocument::ImageResource, testUrl).isValid());
+ QVERIFY(ed->toPlainText().isEmpty());
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::copyAvailable_data()
+{
+ QTest::addColumn<pairListType>("keystrokes");
+ QTest::addColumn<QList<bool> >("copyAvailable");
+ QTest::addColumn<QString>("function");
+
+ pairListType keystrokes;
+ QList<bool> copyAvailable;
+
+ keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_B, Qt::NoModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
+ copyAvailable << true ;
+ QTest::newRow(QString("Case1 B,B, <- + shift | signals: true").toLatin1())
+ << keystrokes << copyAvailable << QString();
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
+ copyAvailable << true << false;
+ QTest::newRow(QString("Case2 T,A,A, <- + shift, cut() | signals: true, false").toLatin1())
+ << keystrokes << copyAvailable << QString("cut");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
+ copyAvailable << true;
+ QTest::newRow(QString("Case3 T,A,A, <- + shift, <- + shift, <- + shift, copy() | signals: true").toLatin1())
+ << keystrokes << copyAvailable << QString("copy");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_X, Qt::ControlModifier);
+ copyAvailable << true << false;
+ QTest::newRow(QString("Case4 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, paste() | signals: true, false").toLatin1())
+ << keystrokes << copyAvailable << QString("paste");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_B, Qt::NoModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier);
+ copyAvailable << true << false;
+ QTest::newRow(QString("Case5 B,B, <- + shift, <- | signals: true, false").toLatin1())
+ << keystrokes << copyAvailable << QString();
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier)
+ << qMakePair(Qt::Key_Right, Qt::ShiftModifier);
+ copyAvailable << true << false << true << false;
+ QTest::newRow(QString("Case6 B,A, <- + shift, ->, <- + shift | signals: true, false, true, false").toLatin1())
+ << keystrokes << copyAvailable << QString("cut");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_X, Qt::ControlModifier);
+ copyAvailable << true << false << true;
+ QTest::newRow(QString("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true").toLatin1())
+ << keystrokes << copyAvailable << QString("undo");
+}
+
+//Tests the copyAvailable slot for several cases
+void tst_QPlainTextEdit::copyAvailable()
+{
+ QFETCH(pairListType,keystrokes);
+ QFETCH(QList<bool>, copyAvailable);
+ QFETCH(QString, function);
+
+#ifdef Q_WS_MAC
+ QSKIP("copyAvailable has never passed on Mac, task to fix is 132482", SkipAll);
+#endif
+ ed->clear();
+ QApplication::clipboard()->clear();
+ QVERIFY(!ed->canPaste());
+ QSignalSpy spyCopyAvailabe(ed, SIGNAL(copyAvailable(bool)));
+
+ //Execute Keystrokes
+ foreach(keyPairType keyPair, keystrokes) {
+ QTest::keyClick(ed, keyPair.first, keyPair.second );
+ }
+
+ //Execute ed->"function"
+ if (function == "cut")
+ ed->cut();
+ else if (function == "copy")
+ ed->copy();
+ else if (function == "paste")
+ ed->paste();
+ else if (function == "undo")
+ ed->paste();
+ else if (function == "redo")
+ ed->paste();
+
+ //Compare spied signals
+ QEXPECT_FAIL("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true",
+ "Wrong undo selection behaviour. Should be fixed in some future release. (See task: 132482)", Abort);
+ QCOMPARE(spyCopyAvailabe.count(), copyAvailable.count());
+ for (int i=0;i<spyCopyAvailabe.count(); i++) {
+ QVariant variantSpyCopyAvailable = spyCopyAvailabe.at(i).at(0);
+ QVERIFY2(variantSpyCopyAvailable.toBool() == copyAvailable.at(i), QString("Spied singnal: %1").arg(i).toLatin1());
+ }
+}
+#endif
+
+void tst_QPlainTextEdit::undoRedoAfterSetContent()
+{
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+ ed->setPlainText("Foobar");
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+ ed->setPlainText("<p>bleh</p>");
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+}
+
+void tst_QPlainTextEdit::numPadKeyNavigation()
+{
+ ed->setPlainText("Hello World");
+ QCOMPARE(ed->textCursor().position(), 0);
+ QTest::keyClick(ed, Qt::Key_Right, Qt::KeypadModifier);
+ QCOMPARE(ed->textCursor().position(), 1);
+}
+
+void tst_QPlainTextEdit::moveCursor()
+{
+ ed->setPlainText("Test");
+
+ QSignalSpy cursorMovedSpy(ed, SIGNAL(cursorPositionChanged()));
+
+ QCOMPARE(ed->textCursor().position(), 0);
+ ed->moveCursor(QTextCursor::NextCharacter);
+ QCOMPARE(ed->textCursor().position(), 1);
+ QCOMPARE(cursorMovedSpy.count(), 1);
+ ed->moveCursor(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(ed->textCursor().position(), 2);
+ QCOMPARE(cursorMovedSpy.count(), 2);
+ QCOMPARE(ed->textCursor().selectedText(), QString("e"));
+}
+
+class MyTextEdit : public QPlainTextEdit
+{
+public:
+ inline MyTextEdit()
+ : createMimeDataCallCount(0),
+ canInsertCallCount(0),
+ insertCallCount(0)
+ {}
+
+ mutable int createMimeDataCallCount;
+ mutable int canInsertCallCount;
+ mutable int insertCallCount;
+
+ virtual QMimeData *createMimeDataFromSelection() const {
+ createMimeDataCallCount++;
+ return QPlainTextEdit::createMimeDataFromSelection();
+ }
+ virtual bool canInsertFromMimeData(const QMimeData *source) const {
+ canInsertCallCount++;
+ return QPlainTextEdit::canInsertFromMimeData(source);
+ }
+ virtual void insertFromMimeData(const QMimeData *source) {
+ insertCallCount++;
+ QPlainTextEdit::insertFromMimeData(source);
+ }
+
+};
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::mimeDataReimplementations()
+{
+ MyTextEdit ed;
+ ed.setPlainText("Hello World");
+
+ QCOMPARE(ed.createMimeDataCallCount, 0);
+ QCOMPARE(ed.canInsertCallCount, 0);
+ QCOMPARE(ed.insertCallCount, 0);
+
+ ed.selectAll();
+
+ QCOMPARE(ed.createMimeDataCallCount, 0);
+ QCOMPARE(ed.canInsertCallCount, 0);
+ QCOMPARE(ed.insertCallCount, 0);
+
+ ed.copy();
+
+ QCOMPARE(ed.createMimeDataCallCount, 1);
+ QCOMPARE(ed.canInsertCallCount, 0);
+ QCOMPARE(ed.insertCallCount, 0);
+
+#ifdef QT_BUILD_INTERNAL
+ QWidgetTextControl *control = qFindChild<QWidgetTextControl *>(&ed);
+ QVERIFY(control);
+
+ control->canInsertFromMimeData(QApplication::clipboard()->mimeData());
+
+ QCOMPARE(ed.createMimeDataCallCount, 1);
+ QCOMPARE(ed.canInsertCallCount, 1);
+ QCOMPARE(ed.insertCallCount, 0);
+
+ ed.paste();
+
+ QCOMPARE(ed.createMimeDataCallCount, 1);
+ QCOMPARE(ed.canInsertCallCount, 1);
+ QCOMPARE(ed.insertCallCount, 1);
+#endif
+}
+#endif
+
+void tst_QPlainTextEdit::shiftEnterShouldInsertLineSeparator()
+{
+ QTest::keyClick(ed, Qt::Key_A);
+ QTest::keyClick(ed, Qt::Key_Enter, Qt::ShiftModifier);
+ QTest::keyClick(ed, Qt::Key_B);
+ QString expected;
+ expected += 'a';
+ expected += QChar::LineSeparator;
+ expected += 'b';
+ QCOMPARE(ed->textCursor().block().text(), expected);
+}
+
+void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators_data()
+{
+ QTest::addColumn<QString>("testString");
+ QTest::addColumn<QString>("selectedWord");
+
+ QStringList wordSeparators;
+ wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "["
+ << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp);
+
+ foreach (QString s, wordSeparators)
+ QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo");
+}
+
+void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators()
+{
+ QFETCH(QString, testString);
+ QFETCH(QString, selectedWord);
+ ed->setPlainText(testString);
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::StartOfLine);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selection().toPlainText(), selectedWord);
+ cursor.clearSelection();
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QPlainTextEdit::canPaste()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+
+ QApplication::clipboard()->setText(QString());
+ QVERIFY(!ed->canPaste());
+ QApplication::clipboard()->setText("Test");
+ QVERIFY(ed->canPaste());
+ ed->setTextInteractionFlags(Qt::NoTextInteraction);
+ QVERIFY(!ed->canPaste());
+}
+#endif
+
+void tst_QPlainTextEdit::ensureCursorVisibleOnInitialShow()
+{
+ QString manyPagesOfPlainText;
+ for (int i = 0; i < 800; ++i)
+ manyPagesOfPlainText += QLatin1String("Blah blah blah blah blah blah\n");
+
+ ed->setPlainText(manyPagesOfPlainText);
+ QCOMPARE(ed->textCursor().position(), 0);
+
+ ed->moveCursor(QTextCursor::End);
+ ed->show();
+ QVERIFY(ed->verticalScrollBar()->value() > 10);
+
+ ed->moveCursor(QTextCursor::Start);
+ QVERIFY(ed->verticalScrollBar()->value() < 10);
+ ed->hide();
+ ed->verticalScrollBar()->setValue(ed->verticalScrollBar()->maximum());
+ ed->show();
+ QCOMPARE(ed->verticalScrollBar()->value(), ed->verticalScrollBar()->maximum());
+}
+
+class TestEdit : public QPlainTextEdit
+{
+public:
+ TestEdit() : resizeEventCalled(false) {}
+
+ bool resizeEventCalled;
+
+protected:
+ virtual void resizeEvent(QResizeEvent *e)
+ {
+ QPlainTextEdit::resizeEvent(e);
+ setPlainText("<img src=qtextbrowser-resizeevent.png width=" + QString::number(size().width()) + "><br>Size is " + QString::number(size().width()) + " x " + QString::number(size().height()));
+ resizeEventCalled = true;
+ }
+};
+
+void tst_QPlainTextEdit::setTextInsideResizeEvent()
+{
+ TestEdit edit;
+ edit.show();
+ edit.resize(800, 600);
+ QVERIFY(edit.resizeEventCalled);
+}
+
+void tst_QPlainTextEdit::colorfulAppend()
+{
+ QTextCharFormat fmt;
+
+ fmt.setForeground(QBrush(Qt::red));
+ ed->mergeCurrentCharFormat(fmt);
+ ed->appendPlainText("Red");
+ fmt.setForeground(QBrush(Qt::blue));
+ ed->mergeCurrentCharFormat(fmt);
+ ed->appendPlainText("Blue");
+ fmt.setForeground(QBrush(Qt::green));
+ ed->mergeCurrentCharFormat(fmt);
+ ed->appendPlainText("Green");
+
+ QCOMPARE(ed->document()->blockCount(), 3);
+ QTextBlock block = ed->document()->begin();
+ QCOMPARE(block.begin().fragment().text(), QString("Red"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::red);
+ block = block.next();
+ QCOMPARE(block.begin().fragment().text(), QString("Blue"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::blue);
+ block = block.next();
+ QCOMPARE(block.begin().fragment().text(), QString("Green"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::green);
+}
+
+void tst_QPlainTextEdit::ensureVisibleWithRtl()
+{
+ ed->setLayoutDirection(Qt::RightToLeft);
+ ed->setLineWrapMode(QPlainTextEdit::NoWrap);
+ QString txt(500, QChar(QLatin1Char('a')));
+ QCOMPARE(txt.length(), 500);
+ ed->setPlainText(txt);
+ ed->resize(100, 100);
+ ed->show();
+
+ qApp->processEvents();
+
+ QVERIFY(ed->horizontalScrollBar()->maximum() > 0);
+
+ ed->moveCursor(QTextCursor::Start);
+ QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
+ ed->moveCursor(QTextCursor::End);
+ QCOMPARE(ed->horizontalScrollBar()->value(), 0);
+ ed->moveCursor(QTextCursor::Start);
+ QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
+ ed->moveCursor(QTextCursor::End);
+ QCOMPARE(ed->horizontalScrollBar()->value(), 0);
+}
+
+void tst_QPlainTextEdit::preserveCharFormatAfterSetPlainText()
+{
+ QTextCharFormat fmt;
+ fmt.setForeground(QBrush(Qt::blue));
+ ed->mergeCurrentCharFormat(fmt);
+ ed->setPlainText("This is blue");
+ ed->appendPlainText("This should still be blue");
+ QTextBlock block = ed->document()->begin();
+ block = block.next();
+ QCOMPARE(block.text(), QString("This should still be blue"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == QColor(Qt::blue));
+}
+
+void tst_QPlainTextEdit::extraSelections()
+{
+ ed->setPlainText("Hello World");
+
+ QTextCursor c = ed->textCursor();
+ c.movePosition(QTextCursor::Start);
+ c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ const int endPos = c.position();
+
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = c;
+ ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
+
+ c.movePosition(QTextCursor::Start);
+ c.movePosition(QTextCursor::NextWord);
+ const int wordPos = c.position();
+ c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ sel.cursor = c;
+ ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
+
+ QList<QTextEdit::ExtraSelection> selections = ed->extraSelections();
+ QCOMPARE(selections.count(), 1);
+ QCOMPARE(selections.at(0).cursor.position(), endPos);
+ QCOMPARE(selections.at(0).cursor.anchor(), wordPos);
+}
+
+void tst_QPlainTextEdit::adjustScrollbars()
+{
+// For some reason ff is defined to be << on Mac Panther / gcc 3.3
+#undef ff
+ QFont ff(ed->font());
+ ff.setFamily("Tahoma");
+ ff.setPointSize(11);
+ ed->setFont(ff);
+ ed->setMinimumSize(140, 100);
+ ed->setMaximumSize(140, 100);
+ ed->show();
+ QLatin1String txt("\nabc def ghi jkl mno pqr stu vwx");
+ ed->setPlainText(txt + txt + txt + txt);
+
+ QVERIFY(ed->verticalScrollBar()->maximum() > 0);
+
+ ed->moveCursor(QTextCursor::End);
+ int oldMaximum = ed->verticalScrollBar()->maximum();
+ QTextCursor cursor = ed->textCursor();
+ cursor.insertText(QLatin1String("\n"));
+ cursor.deletePreviousChar();
+ QCOMPARE(ed->verticalScrollBar()->maximum(), oldMaximum);
+}
+
+class SignalReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ SignalReceiver() : received(0) {}
+
+ int receivedSignals() const { return received; }
+ QTextCharFormat charFormat() const { return format; }
+
+public slots:
+ void charFormatChanged(const QTextCharFormat &tcf) { ++received; format = tcf; }
+
+private:
+ QTextCharFormat format;
+ int received;
+};
+
+void tst_QPlainTextEdit::textObscuredByScrollbars()
+{
+ ed->textCursor().insertText(
+ "ab cab cab c abca kjsdf lka sjd lfk jsal df j kasdf abc ab abc "
+ "a b c d e f g h i j k l m n o p q r s t u v w x y z "
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ );
+ ed->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ ed->show();
+
+ QSize documentSize = ed->document()->documentLayout()->documentSize().toSize();
+ QSize viewportSize = ed->viewport()->size();
+
+ QVERIFY(documentSize.width() <= viewportSize.width());
+}
+
+void tst_QPlainTextEdit::setTextPreservesUndoRedoEnabled()
+{
+ QVERIFY(ed->isUndoRedoEnabled());
+
+ ed->setPlainText("Test");
+
+ QVERIFY(ed->isUndoRedoEnabled());
+
+ ed->setUndoRedoEnabled(false);
+ QVERIFY(!ed->isUndoRedoEnabled());
+ ed->setPlainText("Test2");
+ QVERIFY(!ed->isUndoRedoEnabled());
+
+ ed->setPlainText("<p>hello");
+ QVERIFY(!ed->isUndoRedoEnabled());
+}
+
+void tst_QPlainTextEdit::wordWrapProperty()
+{
+ {
+ QPlainTextEdit edit;
+ QTextDocument *doc = new QTextDocument(&edit);
+ doc->setDocumentLayout(new QPlainTextDocumentLayout(doc));
+ edit.setDocument(doc);
+ edit.setWordWrapMode(QTextOption::NoWrap);
+ QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
+ }
+ {
+ QPlainTextEdit edit;
+ QTextDocument *doc = new QTextDocument(&edit);
+ doc->setDocumentLayout(new QPlainTextDocumentLayout(doc));
+ edit.setWordWrapMode(QTextOption::NoWrap);
+ edit.setDocument(doc);
+ QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
+ }
+}
+
+void tst_QPlainTextEdit::lineWrapProperty()
+{
+ QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
+ QVERIFY(ed->lineWrapMode() == QPlainTextEdit::WidgetWidth);
+ ed->setLineWrapMode(QPlainTextEdit::NoWrap);
+ QVERIFY(ed->lineWrapMode() == QPlainTextEdit::NoWrap);
+ QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
+ QVERIFY(ed->document()->defaultTextOption().wrapMode() == QTextOption::NoWrap);
+}
+
+void tst_QPlainTextEdit::selectionChanged()
+{
+ ed->setPlainText("Hello World");
+
+ ed->moveCursor(QTextCursor::Start);
+
+ QSignalSpy selectionChangedSpy(ed, SIGNAL(selectionChanged()));
+
+ QTest::keyClick(ed, Qt::Key_Right);
+ QCOMPARE(ed->textCursor().position(), 1);
+ QCOMPARE(selectionChangedSpy.count(), 0);
+
+ QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().position(), 2);
+ QCOMPARE(selectionChangedSpy.count(), 1);
+
+ QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().position(), 3);
+ QCOMPARE(selectionChangedSpy.count(), 2);
+
+ QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().position(), 4);
+ QCOMPARE(selectionChangedSpy.count(), 3);
+
+ QTest::keyClick(ed, Qt::Key_Right);
+ QCOMPARE(ed->textCursor().position(), 5);
+ QCOMPARE(selectionChangedSpy.count(), 4);
+
+ QTest::keyClick(ed, Qt::Key_Right);
+ QCOMPARE(ed->textCursor().position(), 6);
+ QCOMPARE(selectionChangedSpy.count(), 4);
+}
+
+void tst_QPlainTextEdit::blockCountChanged()
+{
+ QSignalSpy blockCountCpangedSpy(ed, SIGNAL(blockCountChanged(int)));
+ ed->setPlainText("Hello");
+ QCOMPARE(blockCountCpangedSpy.count(), 0);
+ ed->setPlainText("Hello World");
+ QCOMPARE(blockCountCpangedSpy.count(), 0);
+ ed->setPlainText("Hello \n World \n this \n has \n more \n blocks \n than \n just \n one");
+ QCOMPARE(blockCountCpangedSpy.count(), 1);
+ ed->setPlainText("One");
+ QCOMPARE(blockCountCpangedSpy.count(), 2);
+ ed->setPlainText("One \n Two");
+ QCOMPARE(blockCountCpangedSpy.count(), 3);
+ ed->setPlainText("Three \n Four");
+ QCOMPARE(blockCountCpangedSpy.count(), 3);
+}
+
+
+void tst_QPlainTextEdit::insertAndScrollToBottom()
+{
+ ed->setPlainText("First Line");
+ ed->show();
+ QString text;
+ for(int i = 0; i < 2000; ++i) {
+ text += QLatin1String("this is another line of text to be appended. It is quite long and will probably wrap around, meaning the number of lines is larger than the number of blocks in the text.\n");
+ }
+ QTextCursor cursor = ed->textCursor();
+ cursor.beginEditBlock();
+ cursor.insertText(text);
+ cursor.endEditBlock();
+ ed->verticalScrollBar()->setValue(ed->verticalScrollBar()->maximum());
+ QCOMPARE(ed->verticalScrollBar()->value(), ed->verticalScrollBar()->maximum());
+}
+
+
+QTEST_MAIN(tst_QPlainTextEdit)
+#include "tst_qplaintextedit.moc"
diff --git a/tests/auto/widgets/widgets/qprogressbar/.gitignore b/tests/auto/widgets/widgets/qprogressbar/.gitignore
new file mode 100644
index 0000000000..3cb22a2560
--- /dev/null
+++ b/tests/auto/widgets/widgets/qprogressbar/.gitignore
@@ -0,0 +1 @@
+tst_qprogressbar
diff --git a/tests/auto/widgets/widgets/qprogressbar/qprogressbar.pro b/tests/auto/widgets/widgets/qprogressbar/qprogressbar.pro
new file mode 100644
index 0000000000..70d8c9111f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qprogressbar/qprogressbar.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qprogressbar.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
new file mode 100644
index 0000000000..55285b42ff
--- /dev/null
+++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "qprogressbar.h"
+#include <qapplication.h>
+#include <qstyleoption.h>
+#include <qdebug.h>
+#include <qtimer.h>
+#include <QStyleFactory>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QProgressBar : public QObject
+{
+Q_OBJECT
+private slots:
+ void getSetCheck();
+ void minMaxSameValue();
+ void destroyIndeterminate();
+ void text();
+ void format();
+ void setValueRepaint();
+ void sizeHint();
+ void formatedText_data();
+ void formatedText();
+
+ void task245201_testChangeStyleAndDelete_data();
+ void task245201_testChangeStyleAndDelete();
+};
+
+// Testing get/set functions
+void tst_QProgressBar::getSetCheck()
+{
+ QProgressBar obj1;
+ // bool QProgressBar::invertedAppearance()
+ // void QProgressBar::setInvertedAppearance(bool)
+ obj1.setInvertedAppearance(false);
+ QCOMPARE(false, obj1.invertedAppearance());
+ obj1.setInvertedAppearance(true);
+ QCOMPARE(true, obj1.invertedAppearance());
+
+ // int QProgressBar::minimum()
+ // void QProgressBar::setMinimum(int)
+ obj1.setMinimum(0);
+ QCOMPARE(0, obj1.minimum());
+ obj1.setMinimum(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.minimum());
+ obj1.setMinimum(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.minimum());
+
+ // int QProgressBar::maximum()
+ // void QProgressBar::setMaximum(int)
+ obj1.setMaximum(0);
+ QCOMPARE(0, obj1.maximum());
+ obj1.setMaximum(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.maximum());
+ obj1.setMaximum(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.maximum());
+
+ // int QProgressBar::value()
+ // void QProgressBar::setValue(int)
+ obj1.setValue(0);
+ QCOMPARE(0, obj1.value());
+ obj1.setValue(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.value());
+ obj1.setValue(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.value());
+}
+
+void tst_QProgressBar::minMaxSameValue()
+{
+ QProgressBar bar;
+ bar.setRange(10, 10);
+ bar.setValue(10);
+ bar.show();
+}
+
+void tst_QProgressBar::destroyIndeterminate()
+{
+ // This test crashes on styles that animate indeterminate / busy
+ // progressbars, and forget to remove the bars from internal logics when
+ // it's deleted.
+ QPointer<QProgressBar> bar = new QProgressBar;
+ bar->setMaximum(0);
+ bar->show();
+
+ QEventLoop loop;
+ QTimer::singleShot(500, bar, SLOT(deleteLater()));
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ loop.exec();
+
+ QVERIFY(!bar);
+}
+
+void tst_QProgressBar::text()
+{
+ QProgressBar bar;
+ bar.setRange(10, 10);
+ bar.setValue(10);
+ QCOMPARE(bar.text(), QString("100%"));
+ bar.setRange(0, 10);
+ QCOMPARE(bar.text(), QString("100%"));
+ bar.setValue(5);
+ QCOMPARE(bar.text(), QString("50%"));
+ bar.setRange(0, 5);
+ bar.setValue(0);
+ bar.setRange(5, 5);
+ QCOMPARE(bar.text(), QString());
+}
+
+class ProgressBar : public QProgressBar
+{
+ void paintEvent(QPaintEvent *event)
+ {
+ repainted = true;
+ QProgressBar::paintEvent(event);
+ }
+public:
+ bool repainted;
+ using QProgressBar::initStyleOption;
+};
+
+void tst_QProgressBar::format()
+{
+ ProgressBar bar;
+ bar.setRange(0, 10);
+ bar.setValue(1);
+ bar.show();
+ QTest::qWaitForWindowShown(&bar);
+
+ QTest::qWait(20);
+ bar.repainted = false;
+ bar.setFormat("%v of %m (%p%)");
+ QTest::qWait(20);
+ QTRY_VERIFY(bar.repainted);
+ bar.repainted = false;
+ bar.setFormat("%v of %m (%p%)");
+ qApp->processEvents();
+
+#ifndef Q_WS_MAC
+ // Animated scroll bars get paint events all the time
+#ifdef Q_OS_WIN
+ if (QSysInfo::WindowsVersion < QSysInfo::WV_VISTA)
+#endif
+ QVERIFY(!bar.repainted);
+#endif
+
+ QCOMPARE(bar.text(), QString("1 of 10 (10%)"));
+ bar.setRange(5, 5);
+ bar.setValue(5);
+ QCOMPARE(bar.text(), QString("5 of 0 (100%)"));
+ bar.setRange(0, 5);
+ bar.setValue(0);
+ bar.setRange(5, 5);
+ QCOMPARE(bar.text(), QString());
+}
+
+void tst_QProgressBar::setValueRepaint()
+{
+ ProgressBar pbar;
+ pbar.setMinimum(0);
+ pbar.setMaximum(10);
+ pbar.setFormat("%v");
+ pbar.show();
+ QTest::qWaitForWindowShown(&pbar);
+
+ QApplication::processEvents();
+ for (int i = pbar.minimum(); i < pbar.maximum(); ++i) {
+ pbar.repainted = false;
+ pbar.setValue(i);
+ QTest::qWait(50);
+ QTRY_VERIFY(pbar.repainted);
+ }
+}
+
+void tst_QProgressBar::sizeHint()
+{
+ ProgressBar bar;
+ bar.setMinimum(0);
+ bar.setMaximum(10);
+ bar.setValue(5);
+
+ //test if the sizeHint is big enough
+ QFontMetrics fm = bar.fontMetrics();
+ QStyleOptionProgressBarV2 opt;
+ bar.initStyleOption(&opt);
+ QSize size = QSize(9 * 7 + fm.width(QLatin1Char('0')) * 4, fm.height() + 8);
+ size= bar.style()->sizeFromContents(QStyle::CT_ProgressBar, &opt, size, &bar);
+ QSize barSize = bar.sizeHint();
+ QVERIFY(barSize.width() >= size.width());
+ QCOMPARE(barSize.height(), size.height());
+}
+
+void tst_QProgressBar::formatedText_data()
+{
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("value");
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("1") << -100 << 100 << 0 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 50 - 0 - 200 ");
+ QTest::newRow("2") << -100 << 0 << -25 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 75 - -25 - 100 ");
+ QTest::newRow("3") << 10 << 10 << 10 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 100 - 10 - 0 ");
+ QTest::newRow("task152227") << INT_MIN << INT_MAX << 42 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 50 - 42 - 4294967295 ");
+}
+
+void tst_QProgressBar::formatedText()
+{
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, value);
+ QFETCH(QString, format);
+ QFETCH(QString, text);
+ QProgressBar bar;
+ bar.setRange(minimum, maximum);
+ bar.setValue(value);
+ bar.setFormat(format);
+ QCOMPARE(bar.text(), text);
+}
+
+void tst_QProgressBar::task245201_testChangeStyleAndDelete_data()
+{
+ QTest::addColumn<QString>("style1_str");
+ QTest::addColumn<QString>("style2_str");
+
+ QTest::newRow("plastique-windows") << QString::fromLatin1("plastique") << QString::fromLatin1("windows");
+ QTest::newRow("mlotif-windows") << QString::fromLatin1("motif") << QString::fromLatin1("windows");
+ QTest::newRow("cleanlooks-cde") << QString::fromLatin1("cleanlooks") << QString::fromLatin1("cde");
+ QTest::newRow("gtk-plastique") << QString::fromLatin1("gtk") << QString::fromLatin1("plastique");
+}
+
+void tst_QProgressBar::task245201_testChangeStyleAndDelete()
+{
+ QFETCH(QString, style1_str);
+ QFETCH(QString, style2_str);
+
+ QProgressBar *bar = new QProgressBar;
+
+ QStyle *style = QStyleFactory::create(style1_str);
+ bar->setStyle(style);
+ bar->show();
+ QStyle *style2 = QStyleFactory::create(style2_str);
+ bar->setStyle(style2);
+ QTest::qWait(10);
+
+ delete bar;
+ QTest::qWait(100); //should not crash
+ delete style;
+ delete style2;
+}
+
+QTEST_MAIN(tst_QProgressBar)
+#include "tst_qprogressbar.moc"
diff --git a/tests/auto/widgets/widgets/qpushbutton/.gitignore b/tests/auto/widgets/widgets/qpushbutton/.gitignore
new file mode 100644
index 0000000000..ac5b16970b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/.gitignore
@@ -0,0 +1 @@
+tst_qpushbutton
diff --git a/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro b/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro
new file mode 100644
index 0000000000..e2fd455951
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qpushbutton.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..8c2c08aee9
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap
new file mode 100644
index 0000000000..3c455887da
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap
new file mode 100644
index 0000000000..e655b09d29
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..8f59499d72
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap
new file mode 100644
index 0000000000..a6967a17f7
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap
new file mode 100644
index 0000000000..d7c721c960
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..ae0261a22c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Motif_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Motif_data0.qsnap
new file mode 100644
index 0000000000..039bdce748
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_data0.qsnap
new file mode 100644
index 0000000000..db40dc4726
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap
new file mode 100644
index 0000000000..c0e1279f46
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
new file mode 100644
index 0000000000..e5083553e2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
@@ -0,0 +1,637 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include "qpushbutton.h"
+#include <qapplication.h>
+
+#include <qpushbutton.h>
+#include <qmenu.h>
+#include <qtimer.h>
+#include <QDialog>
+#include <QGridLayout>
+#include <QStyleFactory>
+#include <QTabWidget>
+
+Q_DECLARE_METATYPE(QPushButton*)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QPushButton : public QObject
+{
+Q_OBJECT
+public:
+ tst_QPushButton();
+ virtual ~tst_QPushButton();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void autoRepeat();
+ void pressed();
+ void setAccel();
+ void isCheckable();
+ void setDown();
+ void popupCrash();
+ void isChecked();
+ void animateClick();
+ void toggle();
+ void clicked();
+ void toggled();
+ void defaultAndAutoDefault();
+ void sizeHint_data();
+ void sizeHint();
+/*
+ void state();
+ void group();
+ void stateChanged();
+*/
+
+protected slots:
+ void resetCounters();
+ void onClicked();
+ void onToggled( bool on );
+ void onPressed();
+ void onReleased();
+ void helperSlotDelete();
+
+private:
+ uint click_count;
+ uint toggle_count;
+ uint press_count;
+ uint release_count;
+
+ QPushButton *testWidget;
+};
+
+// Testing get/set functions
+void tst_QPushButton::getSetCheck()
+{
+ QPushButton obj1;
+ // QMenu* QPushButton::menu()
+ // void QPushButton::setMenu(QMenu*)
+ QMenu *var1 = new QMenu;
+ obj1.setMenu(var1);
+ QCOMPARE(var1, obj1.menu());
+ obj1.setMenu((QMenu *)0);
+ QCOMPARE((QMenu *)0, obj1.menu());
+ delete var1;
+}
+
+tst_QPushButton::tst_QPushButton()
+{
+}
+
+tst_QPushButton::~tst_QPushButton()
+{
+}
+
+void tst_QPushButton::initTestCase()
+{
+ // Create the test class
+ testWidget = new QPushButton( "&Start", 0 );
+ testWidget->setObjectName("testWidget");
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+
+ connect( testWidget, SIGNAL(clicked()), this, SLOT(onClicked()) );
+ connect( testWidget, SIGNAL(pressed()), this, SLOT(onPressed()) );
+ connect( testWidget, SIGNAL(released()), this, SLOT(onReleased()) );
+ connect( testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)) );
+}
+
+void tst_QPushButton::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QPushButton::init()
+{
+ testWidget->setAutoRepeat( FALSE );
+ testWidget->setDown( FALSE );
+ testWidget->setText("Test");
+ testWidget->setEnabled( TRUE );
+ QKeySequence seq;
+ testWidget->setShortcut( seq );
+
+ resetCounters();
+}
+
+void tst_QPushButton::cleanup()
+{
+}
+
+
+void tst_QPushButton::resetCounters()
+{
+ toggle_count = 0;
+ press_count = 0;
+ release_count = 0;
+ click_count = 0;
+}
+
+void tst_QPushButton::onClicked()
+{
+ click_count++;
+}
+
+void tst_QPushButton::onToggled( bool /*on*/ )
+{
+ toggle_count++;
+}
+
+void tst_QPushButton::onPressed()
+{
+ press_count++;
+}
+
+void tst_QPushButton::onReleased()
+{
+ release_count++;
+}
+
+void tst_QPushButton::autoRepeat()
+{
+ // If this changes, this test must be completely revised.
+ QVERIFY( !testWidget->isCheckable() );
+
+ // verify autorepeat is off by default.
+ QPushButton tmp( 0 );
+ tmp.setObjectName("tmp");
+ QVERIFY( !tmp.autoRepeat() );
+
+ // check if we can toggle the mode
+ testWidget->setAutoRepeat( TRUE );
+ QVERIFY( testWidget->autoRepeat() );
+
+ testWidget->setAutoRepeat( FALSE );
+ QVERIFY( !testWidget->autoRepeat() );
+
+ resetCounters();
+
+ // check that the button is down if we press space and not in autorepeat
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QTest::keyPress( testWidget, Qt::Key_Space );
+
+ QTest::qWait( 300 );
+
+ QVERIFY( testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+
+ QTest::keyRelease( testWidget, Qt::Key_Space );
+ resetCounters();
+
+ // check that the button is down if we press space while in autorepeat
+ // we can't actually confirm how many times it is fired, more than 1 is enough.
+
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( TRUE );
+ QTest::keyPress( testWidget, Qt::Key_Space );
+ QTest::qWait(900);
+ QVERIFY( testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QTest::keyRelease( testWidget, Qt::Key_Space );
+ QVERIFY(press_count == release_count);
+ QVERIFY(release_count == click_count);
+ QVERIFY(press_count > 1);
+
+ // #### shouldn't I check here to see if multiple signals have been fired???
+
+ // check that pressing ENTER has no effect
+ resetCounters();
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( FALSE );
+ QTest::keyPress( testWidget, Qt::Key_Enter );
+
+ QTest::qWait( 300 );
+
+ QVERIFY( !testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 0 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+ QTest::keyRelease( testWidget, Qt::Key_Enter );
+
+ // check that pressing ENTER has no effect
+ resetCounters();
+ testWidget->setDown( FALSE );
+ testWidget->setAutoRepeat( TRUE );
+ QTest::keyClick( testWidget, Qt::Key_Enter );
+ QTest::qWait( 300 );
+ QVERIFY( !testWidget->isDown() );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( press_count == 0 );
+ QVERIFY( release_count == 0 );
+ QVERIFY( click_count == 0 );
+}
+
+void tst_QPushButton::pressed()
+{
+ QTest::keyPress( testWidget, ' ' );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)0 );
+
+ QTest::keyRelease( testWidget, ' ' );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)1 );
+
+ QTest::keyPress( testWidget,Qt::Key_Enter );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)1 );
+
+ testWidget->setAutoDefault(true);
+ QTest::keyPress( testWidget,Qt::Key_Enter );
+// QTest::qWait( 300 );
+ QCOMPARE( press_count, (uint)2 );
+ QCOMPARE( release_count, (uint)2 );
+ testWidget->setAutoDefault(false);
+
+}
+
+void tst_QPushButton::isCheckable()
+{
+ QVERIFY( !testWidget->isCheckable() );
+}
+
+void tst_QPushButton::setDown()
+{
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isDown() );
+
+ testWidget->setDown( TRUE );
+ QVERIFY( testWidget->isDown() );
+
+ testWidget->setDown( TRUE );
+ QTest::keyClick( testWidget, Qt::Key_Escape );
+ QVERIFY( !testWidget->isDown() );
+}
+
+void tst_QPushButton::isChecked()
+{
+ testWidget->setDown( FALSE );
+ QVERIFY( !testWidget->isChecked() );
+
+ testWidget->setDown( TRUE );
+ QVERIFY( !testWidget->isChecked() );
+
+ testWidget->setDown( FALSE );
+ testWidget->toggle();
+ QVERIFY( testWidget->isChecked() == testWidget->isCheckable() );
+}
+
+void tst_QPushButton::toggle()
+{
+ // the pushbutton shouldn't toggle the button.
+ testWidget->toggle();
+ QVERIFY( testWidget->isChecked() == FALSE );
+}
+
+void tst_QPushButton::toggled()
+{
+ // the pushbutton shouldn't send a toggled signal when we call the toggle slot.
+ QVERIFY( !testWidget->isCheckable() );
+
+ testWidget->toggle();
+ QVERIFY( toggle_count == 0 );
+
+ // do it again, just to be sure
+ resetCounters();
+ testWidget->toggle();
+ QVERIFY( toggle_count == 0 );
+
+ // finally check that we can toggle using the mouse
+ resetCounters();
+ QTest::mousePress( testWidget, Qt::LeftButton );
+ QVERIFY( toggle_count == 0 );
+ QVERIFY( click_count == 0 );
+
+ QTest::mouseRelease( testWidget, Qt::LeftButton );
+ QVERIFY( click_count == 1 );
+}
+
+/*
+ If we press an accelerator key we ONLY get a pressed signal and
+ NOT a released or clicked signal.
+*/
+
+void tst_QPushButton::setAccel()
+{
+ testWidget->setText("&AccelTest");
+ QKeySequence seq( Qt::ALT + Qt::Key_A );
+ testWidget->setShortcut( seq );
+
+ // The shortcut will not be activated unless the button is in a active
+ // window and has focus
+ QApplication::setActiveWindow(testWidget);
+ testWidget->setFocus();
+ for (int i = 0; !testWidget->isActiveWindow() && i < 1000; ++i) {
+ testWidget->activateWindow();
+ QApplication::instance()->processEvents();
+ QTest::qWait(100);
+ }
+ QVERIFY(testWidget->isActiveWindow());
+ QTest::keyClick( testWidget, 'A', Qt::AltModifier );
+ QTest::qWait( 50 );
+ QTRY_VERIFY( click_count == 1 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 1 );
+ QVERIFY( toggle_count == 0 );
+
+ // wait 200 ms because setAccel uses animateClick.
+ // if we don't wait this may screw up a next test.
+ QTest::qWait(200);
+ QTRY_VERIFY( !testWidget->isDown() );
+}
+
+void tst_QPushButton::animateClick()
+{
+ QVERIFY( !testWidget->isDown() );
+ testWidget->animateClick();
+ QVERIFY( testWidget->isDown() );
+ QTest::qWait( 200 );
+ QVERIFY( !testWidget->isDown() );
+
+ QVERIFY( click_count == 1 );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 1 );
+ QVERIFY( toggle_count == 0 );
+}
+
+void tst_QPushButton::clicked()
+{
+ QTest::mousePress( testWidget, Qt::LeftButton );
+ QVERIFY( press_count == 1 );
+ QVERIFY( release_count == 0 );
+
+ QTest::mouseRelease( testWidget, Qt::LeftButton );
+ QCOMPARE( press_count, (uint)1 );
+ QCOMPARE( release_count, (uint)1 );
+
+ press_count = 0;
+ release_count = 0;
+ testWidget->setDown(FALSE);
+ for (uint i=0; i<10; i++)
+ QTest::mouseClick( testWidget, Qt::LeftButton );
+ QCOMPARE( press_count, (uint)10 );
+ QCOMPARE( release_count, (uint)10 );
+}
+
+/*
+void tst_QPushButton::group()
+{
+}
+
+void tst_QPushButton::state()
+{
+}
+
+void tst_QPushButton::stateChanged()
+{
+}
+*/
+QPushButton *pb = 0;
+void tst_QPushButton::helperSlotDelete()
+{
+ delete pb;
+ pb = 0;
+}
+
+void tst_QPushButton::popupCrash()
+{
+ pb = new QPushButton("foo");
+ QMenu *menu = new QMenu("bar", pb);
+ pb->setMenu(menu);
+ QTimer::singleShot(1000, this, SLOT(helperSlotDelete()));
+ pb->show();
+ pb->click();
+}
+
+void tst_QPushButton::defaultAndAutoDefault()
+{
+ {
+ // Adding buttons directly to QDialog
+ QDialog dialog;
+
+ QPushButton button1(&dialog);
+ QVERIFY(button1.autoDefault());
+ QVERIFY(!button1.isDefault());
+
+ QPushButton button2(&dialog);
+ QVERIFY(button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ button1.setDefault(true);
+ QVERIFY(button1.autoDefault());
+ QVERIFY(button1.isDefault());
+ QVERIFY(button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ dialog.show();
+ QVERIFY(dialog.isVisible());
+
+ QObject::connect(&button1, SIGNAL(clicked()), &dialog, SLOT(hide()));
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QApplication::sendEvent(&dialog, &event);
+ QVERIFY(!dialog.isVisible());
+ }
+
+ {
+ // Adding buttons to QDialog through a layout
+ QDialog dialog;
+
+ QPushButton button3;
+ button3.setAutoDefault(false);
+
+ QPushButton button1;
+ QVERIFY(!button1.autoDefault());
+ QVERIFY(!button1.isDefault());
+
+ QPushButton button2;
+ QVERIFY(!button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ button1.setDefault(true);
+ QVERIFY(!button1.autoDefault());
+ QVERIFY(button1.isDefault());
+ QVERIFY(!button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ QGridLayout layout;
+ layout.addWidget(&button3, 0, 3);
+ layout.addWidget(&button2, 0, 2);
+ layout.addWidget(&button1, 0, 1);
+ dialog.setLayout(&layout);
+ button3.setFocus();
+ QVERIFY(button1.autoDefault());
+ QVERIFY(button1.isDefault());
+ QVERIFY(button2.autoDefault());
+ QVERIFY(!button2.isDefault());
+
+ dialog.show();
+ QVERIFY(dialog.isVisible());
+
+ QObject::connect(&button1, SIGNAL(clicked()), &dialog, SLOT(hide()));
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QApplication::sendEvent(&dialog, &event);
+ QVERIFY(!dialog.isVisible());
+ }
+
+ {
+ // autoDefault behavior.
+ QDialog dialog;
+ QPushButton button2(&dialog);
+ QPushButton button1(&dialog);
+ dialog.show();
+ QVERIFY(dialog.isVisible());
+
+ // No default button is set, and button2 is the first autoDefault button
+ // that is next in the tab order
+ QObject::connect(&button2, SIGNAL(clicked()), &dialog, SLOT(hide()));
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QApplication::sendEvent(&dialog, &event);
+ QVERIFY(!dialog.isVisible());
+
+ // Reparenting
+ QVERIFY(button2.autoDefault());
+ button2.setParent(0);
+ QVERIFY(!button2.autoDefault());
+ button2.setAutoDefault(false);
+ button2.setParent(&dialog);
+ QVERIFY(!button2.autoDefault());
+
+ button1.setAutoDefault(true);
+ button1.setParent(0);
+ QVERIFY(button1.autoDefault());
+ }
+}
+
+void tst_QPushButton::sizeHint_data()
+{
+ QTest::addColumn<QString>("stylename");
+ QTest::newRow("motif") << QString::fromAscii("motif");
+ QTest::newRow("cde") << QString::fromAscii("cde");
+ QTest::newRow("windows") << QString::fromAscii("windows");
+ QTest::newRow("cleanlooks") << QString::fromAscii("cleanlooks");
+ QTest::newRow("gtk") << QString::fromAscii("gtk");
+ QTest::newRow("mac") << QString::fromAscii("mac");
+ QTest::newRow("plastique") << QString::fromAscii("plastique");
+ QTest::newRow("windowsxp") << QString::fromAscii("windowsxp");
+ QTest::newRow("windowsvista") << QString::fromAscii("windowsvista");
+}
+
+void tst_QPushButton::sizeHint()
+{
+ QFETCH(QString, stylename);
+
+ QStyle *style = QStyleFactory::create(stylename);
+ if (!style)
+ QSKIP(qPrintable(QString::fromLatin1("Qt has been compiled without style: %1")
+ .arg(stylename)), SkipSingle);
+ QApplication::setStyle(style);
+
+// Test 1
+ {
+ QPushButton *button = new QPushButton("123");
+ QSize initSizeHint = button->sizeHint();
+
+ QDialog *dialog = new QDialog;
+ QWidget *widget = new QWidget(dialog);
+ button->setParent(widget);
+ button->sizeHint();
+
+ widget->setParent(0);
+ delete dialog;
+ button->setDefault(false);
+ QCOMPARE(button->sizeHint(), initSizeHint);
+ delete button;
+ }
+
+// Test 2
+ {
+ QWidget *tab1 = new QWidget;
+ QHBoxLayout *layout1 = new QHBoxLayout(tab1);
+ QPushButton *button1_1 = new QPushButton("123");
+ QPushButton *button1_2 = new QPushButton("123");
+ layout1->addWidget(button1_1);
+ layout1->addWidget(button1_2);
+
+ QWidget *tab2 = new QWidget;
+ QHBoxLayout *layout2 = new QHBoxLayout(tab2);
+ QPushButton *button2_1 = new QPushButton("123");
+ QPushButton *button2_2 = new QPushButton("123");
+ layout2->addWidget(button2_1);
+ layout2->addWidget(button2_2);
+
+ QDialog *dialog = new QDialog;
+ QTabWidget *tabWidget = new QTabWidget;
+ tabWidget->addTab(tab1, "1");
+ tabWidget->addTab(tab2, "2");
+ QVBoxLayout *mainLayout = new QVBoxLayout(dialog);
+ mainLayout->addWidget(tabWidget);
+ dialog->show();
+ tabWidget->setCurrentWidget(tab2);
+ tabWidget->setCurrentWidget(tab1);
+ QTest::qWait(100);
+ QApplication::processEvents();
+
+ QCOMPARE(button1_2->size(), button2_2->size());
+ }
+}
+
+QTEST_MAIN(tst_QPushButton)
+#include "tst_qpushbutton.moc"
diff --git a/tests/auto/widgets/widgets/qradiobutton/.gitignore b/tests/auto/widgets/widgets/qradiobutton/.gitignore
new file mode 100644
index 0000000000..ac5e20c562
--- /dev/null
+++ b/tests/auto/widgets/widgets/qradiobutton/.gitignore
@@ -0,0 +1 @@
+tst_qradiobutton
diff --git a/tests/auto/widgets/widgets/qradiobutton/qradiobutton.pro b/tests/auto/widgets/widgets/qradiobutton/qradiobutton.pro
new file mode 100644
index 0000000000..82b2ff20a8
--- /dev/null
+++ b/tests/auto/widgets/widgets/qradiobutton/qradiobutton.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qradiobutton.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp b/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp
new file mode 100644
index 0000000000..79d3c8ef9a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <QRadioButton>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QLineEdit>
+
+
+class tst_QRadioButton : public QObject
+{
+Q_OBJECT
+public:
+ tst_QRadioButton(){};
+ virtual ~tst_QRadioButton(){};
+
+private slots:
+ void task190739_focus();
+ void minimumSizeHint();
+
+private:
+};
+
+void tst_QRadioButton::task190739_focus()
+{
+ QWidget widget;
+ QPushButton button1(&widget);
+ button1.setText("button1");
+ QLineEdit edit(&widget);
+ edit.setFocus();
+
+ QRadioButton radio1(&widget);
+ radio1.setText("radio1");
+ radio1.setFocusPolicy(Qt::TabFocus);
+ radio1.setShortcut(QKeySequence("Ctrl+O"));
+
+ QVBoxLayout layout(&widget);
+ layout.addWidget(&button1);
+ layout.addWidget(&edit);
+ layout.addWidget(&radio1);
+
+ widget.show();
+ widget.activateWindow();
+ QApplication::setActiveWindow(&widget);
+ QTest::qWait(100);
+
+ QVERIFY(edit.hasFocus());
+ QVERIFY(!radio1.isChecked());
+
+ QTest::keyClick(&edit, Qt::Key_O, Qt::ControlModifier, 20);
+ QTest::qWait(200);
+ QVERIFY(radio1.isChecked());
+ QVERIFY(edit.hasFocus());
+ QVERIFY(!radio1.hasFocus());
+}
+
+
+void tst_QRadioButton::minimumSizeHint()
+{
+ QRadioButton button(tr("QRadioButtons sizeHint is the same as it's minimumSizeHint"));
+ QCOMPARE(button.sizeHint(), button.minimumSizeHint());
+}
+
+
+QTEST_MAIN(tst_QRadioButton)
+#include "tst_qradiobutton.moc"
diff --git a/tests/auto/widgets/widgets/qregexpvalidator/.gitignore b/tests/auto/widgets/widgets/qregexpvalidator/.gitignore
new file mode 100644
index 0000000000..cff9b076b2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qregexpvalidator/.gitignore
@@ -0,0 +1 @@
+tst_qregexpvalidator
diff --git a/tests/auto/widgets/widgets/qregexpvalidator/qregexpvalidator.pro b/tests/auto/widgets/widgets/qregexpvalidator/qregexpvalidator.pro
new file mode 100644
index 0000000000..68e5c51677
--- /dev/null
+++ b/tests/auto/widgets/widgets/qregexpvalidator/qregexpvalidator.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qregexpvalidator.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qregexpvalidator/tst_qregexpvalidator.cpp b/tests/auto/widgets/widgets/qregexpvalidator/tst_qregexpvalidator.cpp
new file mode 100644
index 0000000000..23cd5b1ef1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qregexpvalidator/tst_qregexpvalidator.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qregexp.h>
+
+
+#include <qvalidator.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=corelib/tools/qregexp.h corelib/tools/qregexp.cpp
+
+class tst_QRegExpValidator : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QRegExpValidator();
+ virtual ~tst_QRegExpValidator();
+
+
+ // I can think of no other way to do this for the moment
+ enum State { Invalid=0, Intermediate=1, Acceptable=2 };
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void validate_data();
+ void validate();
+};
+
+tst_QRegExpValidator::tst_QRegExpValidator()
+{
+}
+
+tst_QRegExpValidator::~tst_QRegExpValidator()
+{
+
+}
+
+void tst_QRegExpValidator::init()
+{
+}
+
+void tst_QRegExpValidator::cleanup()
+{
+}
+
+void tst_QRegExpValidator::validate_data()
+{
+
+ QTest::addColumn<QString>("rx");
+ QTest::addColumn<QString>("value");
+ QTest::addColumn<int>("state");
+
+ QTest::newRow( "data0" ) << QString("[1-9]\\d{0,3}") << QString("0") << 0;
+ QTest::newRow( "data1" ) << QString("[1-9]\\d{0,3}") << QString("12345") << 0;
+ QTest::newRow( "data2" ) << QString("[1-9]\\d{0,3}") << QString("1") << 2;
+
+ QTest::newRow( "data3" ) << QString("\\S+") << QString("myfile.txt") << 2;
+ QTest::newRow( "data4" ) << QString("\\S+") << QString("my file.txt") << 0;
+
+ QTest::newRow( "data5" ) << QString("[A-C]\\d{5}[W-Z]") << QString("a12345Z") << 0;
+ QTest::newRow( "data6" ) << QString("[A-C]\\d{5}[W-Z]") << QString("A12345Z") << 2;
+ QTest::newRow( "data7" ) << QString("[A-C]\\d{5}[W-Z]") << QString("B12") << 1;
+
+ QTest::newRow( "data8" ) << QString("read\\S?me(\\.(txt|asc|1st))?") << QString("readme") << 2;
+ QTest::newRow( "data9" ) << QString("read\\S?me(\\.(txt|asc|1st))?") << QString("read me.txt") << 0;
+ QTest::newRow( "data10" ) << QString("read\\S?me(\\.(txt|asc|1st))?") << QString("readm") << 1;
+}
+
+void tst_QRegExpValidator::validate()
+{
+ QFETCH( QString, rx );
+ QFETCH( QString, value );
+ QFETCH( int, state );
+
+ QRegExpValidator rv( 0 );
+ QSignalSpy spy(&rv, SIGNAL(regExpChanged(const QRegExp&)));
+
+ rv.setRegExp( QRegExp( rx ) );
+ int dummy;
+ QCOMPARE( (int)rv.validate( value, dummy ), state );
+ QCOMPARE(spy.count(), 1);
+}
+
+QTEST_MAIN(tst_QRegExpValidator)
+#include "tst_qregexpvalidator.moc"
diff --git a/tests/auto/widgets/widgets/qscrollarea/.gitignore b/tests/auto/widgets/widgets/qscrollarea/.gitignore
new file mode 100644
index 0000000000..aace58e9b1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qscrollarea/.gitignore
@@ -0,0 +1 @@
+tst_qscrollarea
diff --git a/tests/auto/widgets/widgets/qscrollarea/qscrollarea.pro b/tests/auto/widgets/widgets/qscrollarea/qscrollarea.pro
new file mode 100644
index 0000000000..5b2602bbdb
--- /dev/null
+++ b/tests/auto/widgets/widgets/qscrollarea/qscrollarea.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qscrollarea.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qscrollarea.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
new file mode 100644
index 0000000000..8dcfb079d2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qscrollarea.h>
+#include <qlayout.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QScrollArea : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QScrollArea();
+ virtual ~tst_QScrollArea();
+
+private slots:
+ void getSetCheck();
+ void ensureMicroFocusVisible_Task_167838();
+ void checkHFW_Task_197736();
+};
+
+tst_QScrollArea::tst_QScrollArea()
+{
+}
+
+tst_QScrollArea::~tst_QScrollArea()
+{
+}
+
+// Testing get/set functions
+void tst_QScrollArea::getSetCheck()
+{
+ QScrollArea obj1;
+ // QWidget * QScrollArea::widget()
+ // void QScrollArea::setWidget(QWidget *)
+ QWidget *var1 = new QWidget();
+ obj1.setWidget(var1);
+ QCOMPARE(var1, obj1.widget());
+ obj1.setWidget((QWidget *)0);
+ QCOMPARE(var1, obj1.widget()); // Cannot set a 0-widget. Old widget returned
+ // delete var1; // No delete, since QScrollArea takes ownership
+
+ // bool QScrollArea::widgetResizable()
+ // void QScrollArea::setWidgetResizable(bool)
+ obj1.setWidgetResizable(false);
+ QCOMPARE(false, obj1.widgetResizable());
+ obj1.setWidgetResizable(true);
+ QCOMPARE(true, obj1.widgetResizable());
+}
+
+class WidgetWithMicroFocus : public QWidget
+{
+public:
+ WidgetWithMicroFocus(QWidget *parent = 0) : QWidget(parent)
+ {
+ setBackgroundRole(QPalette::Dark);
+ }
+protected:
+ QVariant inputMethodQuery(Qt::InputMethodQuery query) const
+ {
+ if (query == Qt::ImMicroFocus)
+ return QRect(width() / 2, height() / 2, 5, 5);
+ return QWidget::inputMethodQuery(query);
+ }
+// void paintEvent(QPaintEvent *event)
+// {
+// QPainter painter(this);
+// painter.fillRect(rect(), QBrush(Qt::red));
+// }
+};
+
+void tst_QScrollArea::ensureMicroFocusVisible_Task_167838()
+{
+ QScrollArea scrollArea;
+ scrollArea.resize(100, 100);
+ scrollArea.show();
+ QWidget *parent = new QWidget;
+ parent->setLayout(new QVBoxLayout);
+ QWidget *child = new WidgetWithMicroFocus;
+ parent->layout()->addWidget(child);
+ parent->resize(300, 300);
+ scrollArea.setWidget(parent);
+ scrollArea.ensureWidgetVisible(child, 10, 10);
+ QRect microFocus = child->inputMethodQuery(Qt::ImMicroFocus).toRect();
+ QPoint p = child->mapTo(scrollArea.viewport(), microFocus.topLeft());
+ microFocus.translate(p - microFocus.topLeft());
+ QVERIFY(scrollArea.viewport()->rect().contains(microFocus));
+}
+
+class HFWWidget : public QWidget
+{
+ public:
+ HFWWidget();
+ int heightForWidth(int w) const;
+};
+
+HFWWidget::HFWWidget()
+ : QWidget()
+{
+ setMinimumSize(QSize(100,50));
+ QSizePolicy s = sizePolicy();
+ s.setHeightForWidth(true);
+ setSizePolicy(s);
+}
+
+int HFWWidget::heightForWidth(int w) const
+{
+ // Mimic a label - the narrower we are, the taller we have to be
+ if (w > 0)
+ return 40000 / w;
+ else
+ return 40000;
+}
+
+void tst_QScrollArea::checkHFW_Task_197736()
+{
+ QScrollArea scrollArea;
+ HFWWidget *w = new HFWWidget;
+ scrollArea.resize(200,100);
+ scrollArea.show();
+ scrollArea.setWidgetResizable(true);
+ scrollArea.setWidget(w);
+
+ // at 200x100px, we expect HFW to be 200px tall, not 100px
+ QVERIFY(w->height() >= 200);
+
+ // at 200x300px, we expect HFW to be 300px tall (the heightForWidth is a min, not prescribed)
+ scrollArea.resize(QSize(200, 300));
+ QVERIFY(w->height() >= 250); // 50px for a fudge factor (size of frame margins/scrollbars etc)
+
+ // make sure this only happens with widget resizable
+ scrollArea.setWidgetResizable(false);
+ scrollArea.resize(QSize(100,100));
+ w->resize(QSize(200,200));
+ QVERIFY(w->width() == 200);
+ QVERIFY(w->height() == 200);
+}
+
+QTEST_MAIN(tst_QScrollArea)
+#include "tst_qscrollarea.moc"
diff --git a/tests/auto/widgets/widgets/qscrollbar/.gitignore b/tests/auto/widgets/widgets/qscrollbar/.gitignore
new file mode 100644
index 0000000000..ae4ffe1e02
--- /dev/null
+++ b/tests/auto/widgets/widgets/qscrollbar/.gitignore
@@ -0,0 +1 @@
+tst_qscrollbar
diff --git a/tests/auto/widgets/widgets/qscrollbar/qscrollbar.pro b/tests/auto/widgets/widgets/qscrollbar/qscrollbar.pro
new file mode 100644
index 0000000000..262855452f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qscrollbar/qscrollbar.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qscrollbar.cpp
+
+mac*:CONFIG+=insignificant_test
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp
new file mode 100644
index 0000000000..c4b64f3f1e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QScrollBar>
+#include <QStyleOptionSlider>
+#include <QScrollArea>
+
+class tst_QScrollBar : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void hideAndShow(int action);
+
+private slots:
+ void scrollSingleStep();
+ void task_209492();
+
+private:
+ QScrollBar *testWidget;
+};
+
+void tst_QScrollBar::initTestCase()
+{
+ testWidget = new QScrollBar(Qt::Horizontal);
+ testWidget->resize(100, testWidget->height());
+ testWidget->show();
+}
+
+void tst_QScrollBar::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QScrollBar::hideAndShow(int)
+{
+ testWidget->hide();
+ testWidget->show();
+}
+
+// Check that the scrollbar doesn't scroll after calling hide and show
+// from a slot connected to the scrollbar's actionTriggered signal.
+void tst_QScrollBar::scrollSingleStep()
+{
+ testWidget->setValue(testWidget->minimum());
+ QCOMPARE(testWidget->value(), testWidget->minimum());
+ connect(testWidget, SIGNAL(actionTriggered(int)), this, SLOT(hideAndShow(int)));
+
+ // Get rect for the area to click on
+ const QStyleOptionSlider opt = qt_qscrollbarStyleOption(testWidget);
+ QRect sr = testWidget->style()->subControlRect(QStyle::CC_ScrollBar, &opt,
+ QStyle::SC_ScrollBarAddLine, testWidget);
+
+ if (!sr.isValid())
+ QSKIP("SC_ScrollBarAddLine not valid", SkipAll);
+
+ QTest::mouseClick(testWidget, Qt::LeftButton, Qt::NoModifier, QPoint(sr.x(), sr.y()));
+ QTest::qWait(510); // initial delay is 500 for setRepeatAction
+ disconnect(testWidget, SIGNAL(actionTriggered(int)), 0, 0);
+ QCOMPARE(testWidget->value(), testWidget->singleStep());
+}
+
+void tst_QScrollBar::task_209492()
+{
+ class MyScrollArea : public QScrollArea
+ {
+ public:
+ int scrollCount;
+ MyScrollArea(QWidget *parent = 0) : QScrollArea(parent), scrollCount(0) {}
+ protected:
+ void paintEvent(QPaintEvent *) { QTest::qSleep(600); }
+ void scrollContentsBy(int, int) { ++scrollCount; viewport()->update(); }
+ };
+
+ MyScrollArea scrollArea;
+ QScrollBar *verticalScrollBar = scrollArea.verticalScrollBar();
+ verticalScrollBar->setRange(0, 1000);
+ scrollArea.show();
+ QTest::qWait(300);
+
+ QSignalSpy spy(verticalScrollBar, SIGNAL(actionTriggered(int)));
+ QCOMPARE(scrollArea.scrollCount, 0);
+ QCOMPARE(spy.count(), 0);
+
+ // Simulate a mouse click on the "scroll down button".
+ const QPoint pressPoint(verticalScrollBar->width() / 2, verticalScrollBar->height() - 10);
+ const QPoint globalPressPoint = verticalScrollBar->mapToGlobal(globalPressPoint);
+ QMouseEvent mousePressEvent(QEvent::MouseButtonPress, pressPoint, globalPressPoint,
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(verticalScrollBar, &mousePressEvent);
+ QTest::qWait(1);
+ QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, pressPoint, globalPressPoint,
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(verticalScrollBar, &mouseReleaseEvent);
+
+ // Check that the action was triggered once.
+#ifdef Q_WS_MAC
+ QEXPECT_FAIL("", "Fix does does not work on Mac due to paint architechure differences.", Abort);
+#endif
+ QCOMPARE(scrollArea.scrollCount, 1);
+ QCOMPARE(spy.count(), 1);
+}
+
+QTEST_MAIN(tst_QScrollBar)
+#include "tst_qscrollbar.moc"
diff --git a/tests/auto/widgets/widgets/qsizegrip/.gitignore b/tests/auto/widgets/widgets/qsizegrip/.gitignore
new file mode 100644
index 0000000000..ec480bcbad
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsizegrip/.gitignore
@@ -0,0 +1 @@
+tst_qsizegrip
diff --git a/tests/auto/widgets/widgets/qsizegrip/qsizegrip.pro b/tests/auto/widgets/widgets/qsizegrip/qsizegrip.pro
new file mode 100644
index 0000000000..da6dd5af49
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsizegrip/qsizegrip.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+INCLUDEPATH += .
+QT += widgets
+SOURCES += tst_qsizegrip.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp b/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp
new file mode 100644
index 0000000000..cc0710a65a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QSizeGrip>
+#include <QEvent>
+#include <QLineEdit>
+#include <QVBoxLayout>
+#include <QLabel>
+
+static inline Qt::Corner sizeGripCorner(QWidget *parent, QSizeGrip *sizeGrip)
+{
+ if (!parent || !sizeGrip)
+ return Qt::TopLeftCorner;
+
+ const QPoint sizeGripPos = sizeGrip->mapTo(parent, QPoint(0, 0));
+ bool isAtBottom = sizeGripPos.y() >= parent->height() / 2;
+ bool isAtLeft = sizeGripPos.x() <= parent->width() / 2;
+ if (isAtLeft)
+ return isAtBottom ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
+ else
+ return isAtBottom ? Qt::BottomRightCorner : Qt::TopRightCorner;
+
+}
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(Qt::WindowType);
+
+class tst_QSizeGrip : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void hideAndShowOnWindowStateChange_data();
+ void hideAndShowOnWindowStateChange();
+ void orientation();
+
+private:
+ QLineEdit *dummyWidget;
+};
+
+class TestWidget : public QWidget
+{
+public:
+ TestWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0) : QWidget(parent, flags) {}
+ QSize sizeHint() const { return QSize(300, 200); }
+ void changeEvent(QEvent *event)
+ {
+ QWidget::changeEvent(event);
+ if (isWindow() && event->type() == QEvent::WindowStateChange) {
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(this);
+#endif
+ }
+ }
+};
+
+void tst_QSizeGrip::initTestCase()
+{
+ dummyWidget = new QLineEdit;
+ dummyWidget->show();
+}
+
+void tst_QSizeGrip::cleanupTestCase()
+{
+ delete dummyWidget;
+ dummyWidget = 0;
+}
+
+void tst_QSizeGrip::hideAndShowOnWindowStateChange_data()
+{
+ QTest::addColumn<Qt::WindowType>("windowType");
+ QTest::newRow("Qt::Window") << Qt::Window;
+ QTest::newRow("Qt::SubWindow") << Qt::SubWindow;
+}
+
+void tst_QSizeGrip::hideAndShowOnWindowStateChange()
+{
+ QFETCH(Qt::WindowType, windowType);
+
+ QWidget *parentWidget = windowType == Qt::Window ? 0 : new QWidget;
+ TestWidget *widget = new TestWidget(parentWidget, Qt::WindowFlags(windowType));
+ QSizeGrip *sizeGrip = new QSizeGrip(widget);
+
+ // Normal.
+ if (parentWidget)
+ parentWidget->show();
+ else
+ widget->show();
+ QVERIFY(sizeGrip->isVisible());
+
+ widget->showFullScreen();
+ QVERIFY(!sizeGrip->isVisible());
+
+ widget->showNormal();
+ QVERIFY(sizeGrip->isVisible());
+
+ widget->showMaximized();
+#ifndef Q_WS_MAC
+ QVERIFY(!sizeGrip->isVisible());
+#else
+ QVERIFY(sizeGrip->isVisible());
+#endif
+
+ widget->showNormal();
+ QVERIFY(sizeGrip->isVisible());
+
+ sizeGrip->hide();
+ QVERIFY(!sizeGrip->isVisible());
+
+ widget->showFullScreen();
+ widget->showNormal();
+ QVERIFY(!sizeGrip->isVisible());
+ widget->showMaximized();
+ widget->showNormal();
+ QVERIFY(!sizeGrip->isVisible());
+
+ delete widget;
+ delete parentWidget;
+}
+
+void tst_QSizeGrip::orientation()
+{
+ TestWidget widget;
+ widget.setLayout(new QVBoxLayout);
+ QSizeGrip *sizeGrip = new QSizeGrip(&widget);
+ sizeGrip->setFixedSize(sizeGrip->sizeHint());
+ widget.layout()->addWidget(sizeGrip);
+ widget.layout()->setAlignment(sizeGrip, Qt::AlignBottom | Qt::AlignRight);
+
+ widget.show();
+ QCOMPARE(sizeGripCorner(&widget, sizeGrip), Qt::BottomRightCorner);
+
+ widget.setLayoutDirection(Qt::RightToLeft);
+ qApp->processEvents();
+ QCOMPARE(sizeGripCorner(&widget, sizeGrip), Qt::BottomLeftCorner);
+
+ widget.unsetLayoutDirection();
+ qApp->processEvents();
+ QCOMPARE(sizeGripCorner(&widget, sizeGrip), Qt::BottomRightCorner);
+
+ widget.layout()->setAlignment(sizeGrip, Qt::AlignTop | Qt::AlignRight);
+ qApp->processEvents();
+ QCOMPARE(sizeGripCorner(&widget, sizeGrip), Qt::TopRightCorner);
+
+ widget.setLayoutDirection(Qt::RightToLeft);
+ qApp->processEvents();
+ QCOMPARE(sizeGripCorner(&widget, sizeGrip), Qt::TopLeftCorner);
+
+ widget.unsetLayoutDirection();
+ qApp->processEvents();
+ QCOMPARE(sizeGripCorner(&widget, sizeGrip), Qt::TopRightCorner);
+}
+
+QTEST_MAIN(tst_QSizeGrip)
+#include "tst_qsizegrip.moc"
+
diff --git a/tests/auto/widgets/widgets/qslider/.gitignore b/tests/auto/widgets/widgets/qslider/.gitignore
new file mode 100644
index 0000000000..f8d833e8b4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qslider/.gitignore
@@ -0,0 +1 @@
+tst_qslider
diff --git a/tests/auto/widgets/widgets/qslider/qslider.pro b/tests/auto/widgets/widgets/qslider/qslider.pro
new file mode 100644
index 0000000000..41f011649d
--- /dev/null
+++ b/tests/auto/widgets/widgets/qslider/qslider.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qslider.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qslider.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qslider/tst_qslider.cpp b/tests/auto/widgets/widgets/qslider/tst_qslider.cpp
new file mode 100644
index 0000000000..50ee9e6a63
--- /dev/null
+++ b/tests/auto/widgets/widgets/qslider/tst_qslider.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qslider.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QSlider : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QSlider();
+ virtual ~tst_QSlider();
+
+private slots:
+ void getSetCheck();
+};
+
+tst_QSlider::tst_QSlider()
+{
+}
+
+tst_QSlider::~tst_QSlider()
+{
+}
+
+// Testing get/set functions
+void tst_QSlider::getSetCheck()
+{
+ QSlider obj1;
+ // TickPosition QSlider::tickPosition()
+ // void QSlider::setTickPosition(TickPosition)
+ obj1.setTickPosition(QSlider::TickPosition(QSlider::NoTicks));
+ QCOMPARE(QSlider::TickPosition(QSlider::NoTicks), obj1.tickPosition());
+ obj1.setTickPosition(QSlider::TickPosition(QSlider::TicksAbove));
+ QCOMPARE(QSlider::TickPosition(QSlider::TicksAbove), obj1.tickPosition());
+ obj1.setTickPosition(QSlider::TickPosition(QSlider::TicksBelow));
+ QCOMPARE(QSlider::TickPosition(QSlider::TicksBelow), obj1.tickPosition());
+ obj1.setTickPosition(QSlider::TickPosition(QSlider::TicksBothSides));
+ QCOMPARE(QSlider::TickPosition(QSlider::TicksBothSides), obj1.tickPosition());
+
+ // int QSlider::tickInterval()
+ // void QSlider::setTickInterval(int)
+ obj1.setTickInterval(0);
+ QCOMPARE(0, obj1.tickInterval());
+ obj1.setTickInterval(INT_MIN);
+ QCOMPARE(0, obj1.tickInterval()); // Can't have a negative interval
+ obj1.setTickInterval(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.tickInterval());
+}
+
+QTEST_MAIN(tst_QSlider)
+#include "tst_qslider.moc"
diff --git a/tests/auto/widgets/widgets/qspinbox/.gitignore b/tests/auto/widgets/widgets/qspinbox/.gitignore
new file mode 100644
index 0000000000..84599cf955
--- /dev/null
+++ b/tests/auto/widgets/widgets/qspinbox/.gitignore
@@ -0,0 +1 @@
+tst_qspinbox
diff --git a/tests/auto/widgets/widgets/qspinbox/qspinbox.pro b/tests/auto/widgets/widgets/qspinbox/qspinbox.pro
new file mode 100644
index 0000000000..c88dc0ee8f
--- /dev/null
+++ b/tests/auto/widgets/widgets/qspinbox/qspinbox.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qspinbox.cpp
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
new file mode 100644
index 0000000000..608dcd6705
--- /dev/null
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -0,0 +1,1049 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qdebug.h>
+#include <qapplication.h>
+#include <limits.h>
+
+#ifdef Q_WS_X11
+#include <unistd.h>
+#endif
+
+#include <qspinbox.h>
+#include <qlocale.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <QSpinBox>
+#include <QWidget>
+#include <QString>
+#include <QValidator>
+#include <QLineEdit>
+#include <QObject>
+#include <QStringList>
+#include <QList>
+#include <QLocale>
+#include <QDoubleSpinBox>
+#include <QVBoxLayout>
+#include <QKeySequence>
+#include <QStackedWidget>
+#include <QDebug>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class SpinBox : public QSpinBox
+{
+public:
+ SpinBox(QWidget *parent = 0)
+ : QSpinBox(parent)
+ {}
+ QString textFromValue(int v) const
+ {
+ return QSpinBox::textFromValue(v);
+ }
+ QValidator::State validate(QString &text, int &pos) const
+ {
+ return QSpinBox::validate(text, pos);
+ }
+ int valueFromText(const QString &text) const
+ {
+ return QSpinBox::valueFromText(text);
+ }
+
+ QLineEdit *lineEdit() const { return QSpinBox::lineEdit(); }
+};
+
+class tst_QSpinBox : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QSpinBox();
+ virtual ~tst_QSpinBox();
+public slots:
+ void initTestCase();
+ void init();
+ void cleanupTestCase();
+private slots:
+ void getSetCheck();
+ void setValue_data();
+ void setValue();
+
+ void setPrefixSuffix_data();
+ void setPrefixSuffix();
+
+ void setReadOnly();
+
+ void setTracking_data();
+ void setTracking();
+
+ void locale_data();
+ void locale();
+
+ void setWrapping_data();
+ void setWrapping();
+
+ void setSpecialValueText_data();
+ void setSpecialValueText();
+
+ void setSingleStep_data();
+ void setSingleStep();
+
+ void setMinMax_data();
+ void setMinMax();
+
+ void editingFinished();
+
+ void valueFromTextAndValidate_data();
+ void valueFromTextAndValidate();
+
+ void removeAll();
+ void startWithDash();
+ void undoRedo();
+
+ void specialValue();
+ void textFromValue();
+
+ void sizeHint();
+
+ void taskQTBUG_5008_textFromValueAndValidate();
+
+public slots:
+ void valueChangedHelper(const QString &);
+ void valueChangedHelper(int);
+private:
+ QStringList actualTexts;
+ QList<int> actualValues;
+ QWidget *testFocusWidget;
+};
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(QLocale)
+
+// Testing get/set functions
+void tst_QSpinBox::getSetCheck()
+{
+ QSpinBox obj1;
+ // int QSpinBox::singleStep()
+ // void QSpinBox::setSingleStep(int)
+ obj1.setSingleStep(0);
+ QCOMPARE(0, obj1.singleStep());
+ obj1.setSingleStep(INT_MIN);
+ QCOMPARE(0, obj1.singleStep()); // Can't have negative steps => keep old value
+ obj1.setSingleStep(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.singleStep());
+
+ // int QSpinBox::minimum()
+ // void QSpinBox::setMinimum(int)
+ obj1.setMinimum(0);
+ QCOMPARE(0, obj1.minimum());
+ obj1.setMinimum(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.minimum());
+ obj1.setMinimum(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.minimum());
+
+ // int QSpinBox::maximum()
+ // void QSpinBox::setMaximum(int)
+ obj1.setMaximum(0);
+ QCOMPARE(0, obj1.maximum());
+ obj1.setMaximum(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.maximum());
+ obj1.setMaximum(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.maximum());
+
+ // int QSpinBox::value()
+ // void QSpinBox::setValue(int)
+ obj1.setValue(0);
+ QCOMPARE(0, obj1.value());
+ obj1.setValue(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.value());
+ obj1.setValue(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.value());
+
+ QDoubleSpinBox obj2;
+ // double QDoubleSpinBox::singleStep()
+ // void QDoubleSpinBox::setSingleStep(double)
+ obj2.setSingleStep(0.0);
+ QCOMPARE(0.0, obj2.singleStep());
+ obj2.setSingleStep(1.0);
+ QCOMPARE(1.0, obj2.singleStep());
+
+ // double QDoubleSpinBox::minimum()
+ // void QDoubleSpinBox::setMinimum(double)
+ obj2.setMinimum(1.0);
+ QCOMPARE(1.0, obj2.minimum());
+ obj2.setMinimum(0.0);
+ QCOMPARE(0.0, obj2.minimum());
+ obj2.setMinimum(-1.0);
+ QCOMPARE(-1.0, obj2.minimum());
+
+ // double QDoubleSpinBox::maximum()
+ // void QDoubleSpinBox::setMaximum(double)
+ obj2.setMaximum(-1.0);
+ QCOMPARE(-1.0, obj2.maximum());
+ obj2.setMaximum(0.0);
+ QCOMPARE(0.0, obj2.maximum());
+ obj2.setMaximum(1.0);
+ QCOMPARE(1.0, obj2.maximum());
+
+ // int QDoubleSpinBox::decimals()
+ // void QDoubleSpinBox::setDecimals(int)
+ obj2.setDecimals(0);
+ QCOMPARE(0, obj2.decimals());
+ obj2.setDecimals(INT_MIN);
+ QCOMPARE(0, obj2.decimals()); // Range<0, 13>
+
+ //obj2.setDecimals(INT_MAX);
+ //QCOMPARE(13, obj2.decimals()); // Range<0, 13>
+ obj2.setDecimals(128);
+ QCOMPARE(obj2.decimals(), 128); // Range<0, 128>
+
+ // double QDoubleSpinBox::value()
+ // void QDoubleSpinBox::setValue(double)
+ obj2.setValue(-1.0);
+ QCOMPARE(-1.0, obj2.value());
+ obj2.setValue(0.0);
+ QCOMPARE(0.0, obj2.value());
+ obj2.setValue(1.0);
+ QCOMPARE(1.0, obj2.value());
+
+ // Make sure we update line edit geometry when updating
+ // buttons - see task 235747
+ QRect oldEditGeometry = obj1.childrenRect();
+ obj1.setButtonSymbols(QAbstractSpinBox::NoButtons);
+ QVERIFY(obj1.childrenRect() != oldEditGeometry);
+}
+
+tst_QSpinBox::tst_QSpinBox()
+{
+
+}
+
+tst_QSpinBox::~tst_QSpinBox()
+{
+
+}
+
+void tst_QSpinBox::initTestCase()
+{
+ testFocusWidget = new QWidget(0);
+ testFocusWidget->resize(200, 100);
+ testFocusWidget->show();
+}
+
+void tst_QSpinBox::init()
+{
+ QLocale::setDefault(QLocale(QLocale::C));
+}
+
+void tst_QSpinBox::cleanupTestCase()
+{
+ delete testFocusWidget;
+ testFocusWidget = 0;
+}
+
+void tst_QSpinBox::setValue_data()
+{
+ QTest::addColumn<int>("set");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("data0") << 0 << 0;
+ QTest::newRow("data1") << 100 << 100;
+ QTest::newRow("data2") << -100 << -100;
+ QTest::newRow("data3") << INT_MIN << INT_MIN;
+ QTest::newRow("data4") << INT_MAX << INT_MAX;
+}
+
+void tst_QSpinBox::setValue()
+{
+ QFETCH(int, set);
+ QFETCH(int, expected);
+ QSpinBox spin(0);
+ spin.setRange(INT_MIN, INT_MAX);
+ spin.setValue(set);
+ QCOMPARE(spin.value(), expected);
+}
+
+void tst_QSpinBox::setPrefixSuffix_data()
+{
+ QTest::addColumn<QString>("prefix");
+ QTest::addColumn<QString>("suffix");
+ QTest::addColumn<int>("value");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedCleanText");
+ QTest::addColumn<bool>("show");
+
+ QTest::newRow("data0") << QString() << QString() << 10 << "10" << "10" << false;
+ QTest::newRow("data1") << QString() << "cm" << 10 << "10cm" << "10" << false;
+ QTest::newRow("data2") << "cm: " << QString() << 10 << "cm: 10" << "10" << false;
+ QTest::newRow("data3") << "length: " << "cm" << 10 << "length: 10cm" << "10" << false;
+
+ QTest::newRow("data4") << QString() << QString() << 10 << "10" << "10" << true;
+ QTest::newRow("data5") << QString() << "cm" << 10 << "10cm" << "10" << true;
+ QTest::newRow("data6") << "cm: " << QString() << 10 << "cm: 10" << "10" << true;
+ QTest::newRow("data7") << "length: " << "cm" << 10 << "length: 10cm" << "10" << true;
+}
+
+void tst_QSpinBox::setPrefixSuffix()
+{
+ QFETCH(QString, prefix);
+ QFETCH(QString, suffix);
+ QFETCH(int, value);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedCleanText);
+ QFETCH(bool, show);
+
+ QSpinBox spin(0);
+ spin.setPrefix(prefix);
+ spin.setSuffix(suffix);
+ spin.setValue(value);
+ if (show)
+ spin.show();
+
+ QCOMPARE(spin.prefix(), prefix);
+ QCOMPARE(spin.suffix(), suffix);
+ QCOMPARE(spin.text(), expectedText);
+ QCOMPARE(spin.cleanText(), expectedCleanText);
+}
+
+void tst_QSpinBox::valueChangedHelper(const QString &text)
+{
+ actualTexts << text;
+}
+
+void tst_QSpinBox::valueChangedHelper(int value)
+{
+ actualValues << value;
+}
+
+void tst_QSpinBox::setReadOnly()
+{
+ QSpinBox spin(0);
+ spin.show();
+ QTest::keyClick(&spin, Qt::Key_Up);
+ QCOMPARE(spin.value(), 1);
+ spin.setReadOnly(true);
+ QTest::keyClick(&spin, Qt::Key_Up);
+ QCOMPARE(spin.value(), 1);
+ spin.stepBy(1);
+ QCOMPARE(spin.value(), 2);
+ spin.setReadOnly(false);
+ QTest::keyClick(&spin, Qt::Key_Up);
+ QCOMPARE(spin.value(), 3);
+}
+void tst_QSpinBox::setTracking_data()
+{
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QStringList>("texts");
+ QTest::addColumn<bool>("tracking");
+
+ QTestEventList keys;
+ QStringList texts1;
+ QStringList texts2;
+
+#ifdef Q_WS_MAC
+ keys.addKeyClick(Qt::Key_Right, Qt::ControlModifier);
+#else
+ keys.addKeyClick(Qt::Key_End);
+#endif
+ keys.addKeyClick('7');
+ keys.addKeyClick('9');
+ keys.addKeyClick(Qt::Key_Enter);
+ keys.addKeyClick(Qt::Key_Enter);
+ keys.addKeyClick(Qt::Key_Enter);
+ texts1 << "07" << "079" << "79" << "79" << "79";
+ texts2 << "79";
+ QTest::newRow("data1") << keys << texts1 << true;
+ QTest::newRow("data2") << keys << texts2 << false;
+}
+
+void tst_QSpinBox::setTracking()
+{
+ actualTexts.clear();
+ QFETCH(QTestEventList, keys);
+ QFETCH(QStringList, texts);
+ QFETCH(bool, tracking);
+
+ QSpinBox spin(0);
+ spin.setKeyboardTracking(tracking);
+ spin.show();
+ connect(&spin, SIGNAL(valueChanged(QString)), this, SLOT(valueChangedHelper(const QString &)));
+
+ keys.simulate(&spin);
+ QCOMPARE(actualTexts, texts);
+}
+
+void tst_QSpinBox::setWrapping_data()
+{
+ QTest::addColumn<bool>("wrapping");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("startValue");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<IntList>("expected");
+
+ QTestEventList keys;
+ IntList values;
+ keys.addKeyClick(Qt::Key_Up);
+ values << 10;
+ keys.addKeyClick(Qt::Key_Up);
+ QTest::newRow("data0") << false << 0 << 10 << 9 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_Up);
+ values << 10;
+ keys.addKeyClick(Qt::Key_Up);
+ values << 0;
+ QTest::newRow("data1") << true << 0 << 10 << 9 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_Delete); // doesn't emit because lineedit is empty so intermediate
+ keys.addKeyClick('1');
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 1 << 0;
+ QTest::newRow("data2") << false << 0 << 10 << 9 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_Delete);
+ keys.addKeyClick('1');
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 1 << 0 << 10;
+ QTest::newRow("data3") << true << 0 << 10 << 9 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 0;
+ QTest::newRow("data4") << false << 0 << 10 << 6 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_Down);
+ values << 0 << 10;
+ QTest::newRow("data5") << true << 0 << 10 << 6 << keys << values;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_PageUp);
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_PageDown);
+ keys.addKeyClick(Qt::Key_PageDown);
+ values << 10 << 0 << 10 << 0 << 10 << 0;
+ QTest::newRow("data6") << true << 0 << 10 << 6 << keys << values;
+
+}
+
+
+void tst_QSpinBox::setWrapping()
+{
+ QFETCH(bool, wrapping);
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, startValue);
+ QFETCH(QTestEventList, keys);
+ QFETCH(IntList, expected);
+
+ QSpinBox spin(0);
+ QVERIFY(!spin.wrapping());
+ spin.setMinimum(minimum);
+ spin.setMaximum(maximum);
+ spin.setValue(startValue);
+ spin.setWrapping(wrapping);
+ spin.show();
+ actualValues.clear();
+ connect(&spin, SIGNAL(valueChanged(int)), this, SLOT(valueChangedHelper(int)));
+
+ keys.simulate(&spin);
+
+ QCOMPARE(actualValues.size(), expected.size());
+ for (int i=0; i<qMin(actualValues.size(), expected.size()); ++i) {
+ QCOMPARE(actualValues.at(i), expected.at(i));
+ }
+}
+
+void tst_QSpinBox::setSpecialValueText_data()
+{
+ QTest::addColumn<QString>("specialValueText");
+ QTest::addColumn<int>("minimum");
+ QTest::addColumn<int>("maximum");
+ QTest::addColumn<int>("value");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<bool>("show");
+
+ QTest::newRow("data0") << QString() << 0 << 10 << 1 << "1" << false;
+ QTest::newRow("data1") << QString() << 0 << 10 << 1 << "1" << true;
+ QTest::newRow("data2") << "foo" << 0 << 10 << 0 << "foo" << false;
+ QTest::newRow("data3") << "foo" << 0 << 10 << 0 << "foo" << true;
+}
+
+void tst_QSpinBox::setSpecialValueText()
+{
+ QFETCH(QString, specialValueText);
+ QFETCH(int, minimum);
+ QFETCH(int, maximum);
+ QFETCH(int, value);
+ QFETCH(QString, expected);
+ QFETCH(bool, show);
+
+ QSpinBox spin(0);
+ spin.setSpecialValueText(specialValueText);
+ QCOMPARE(spin.specialValueText(), specialValueText);
+ spin.setMinimum(minimum);
+ spin.setMaximum(maximum);
+ spin.setValue(value);
+ if (show)
+ spin.show();
+
+ QCOMPARE(spin.text(), expected);
+}
+
+void tst_QSpinBox::setSingleStep_data()
+{
+ QTest::addColumn<int>("singleStep");
+ QTest::addColumn<int>("startValue");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<IntList>("expected");
+ QTest::addColumn<bool>("show");
+
+ QTestEventList keys;
+ IntList values;
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Up);
+ values << 11 << 10 << 11;
+ QTest::newRow("data0") << 1 << 10 << keys << values << false;
+ QTest::newRow("data1") << 1 << 10 << keys << values << true;
+
+ keys.clear();
+ values.clear();
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Down);
+ keys.addKeyClick(Qt::Key_Up);
+ values << 12 << 10 << 12;
+ QTest::newRow("data2") << 2 << 10 << keys << values << false;
+ QTest::newRow("data3") << 2 << 10 << keys << values << true;
+}
+
+void tst_QSpinBox::setSingleStep()
+{
+ QFETCH(int, singleStep);
+ QFETCH(int, startValue);
+ QFETCH(QTestEventList, keys);
+ QFETCH(IntList, expected);
+ QFETCH(bool, show);
+
+ QSpinBox spin(0);
+ actualValues.clear();
+ spin.setSingleStep(singleStep);
+ QCOMPARE(spin.singleStep(), singleStep);
+ spin.setValue(startValue);
+ if (show)
+ spin.show();
+ connect(&spin, SIGNAL(valueChanged(int)), this, SLOT(valueChangedHelper(int)));
+
+ QCOMPARE(actualValues.size(), 0);
+ keys.simulate(&spin);
+ QCOMPARE(actualValues.size(), expected.size());
+ for (int i=0; i<qMin(actualValues.size(), expected.size()); ++i) {
+ QCOMPARE(actualValues.at(i), expected.at(i));
+ }
+}
+
+void tst_QSpinBox::setMinMax_data()
+{
+ QTest::addColumn<int>("startValue");
+ QTest::addColumn<int>("mini");
+ QTest::addColumn<int>("maxi");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<int>("expected");
+ QTest::addColumn<bool>("show");
+
+ QTestEventList keys;
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ keys.addKeyClick(Qt::Key_Up);
+ QTest::newRow("data0") << 1 << INT_MIN << 2 << keys << 2 << false;
+ QTest::newRow("data1") << 1 << INT_MIN << 2 << keys << 2 << true;
+
+ keys.clear();
+ QTest::newRow("data2") << 2 << INT_MAX - 2 << INT_MAX << keys << INT_MAX - 2 << false;
+ QTest::newRow("data3") << 2 << INT_MAX - 2 << INT_MAX << keys << INT_MAX - 2 << true;
+}
+
+void tst_QSpinBox::setMinMax()
+{
+ QFETCH(int, startValue);
+ QFETCH(int, mini);
+ QFETCH(int, maxi);
+ QFETCH(QTestEventList, keys);
+ QFETCH(int, expected);
+ QFETCH(bool, show);
+
+ QSpinBox spin(0);
+ spin.setValue(startValue);
+ spin.setMinimum(mini);
+ spin.setMaximum(maxi);
+ QCOMPARE(spin.minimum(), mini);
+ QCOMPARE(spin.maximum(), maxi);
+ if (show)
+ spin.show();
+ keys.simulate(&spin);
+ QCOMPARE(spin.value(), expected);
+}
+
+void tst_QSpinBox::valueFromTextAndValidate_data()
+{
+ const int Intermediate = QValidator::Intermediate;
+ const int Invalid = QValidator::Invalid;
+ const int Acceptable = QValidator::Acceptable;
+
+ QTest::addColumn<QString>("txt");
+ QTest::addColumn<int>("state");
+ QTest::addColumn<int>("mini");
+ QTest::addColumn<int>("maxi");
+ QTest::addColumn<QString>("expectedText"); // if empty we don't check
+
+ QTest::newRow("data0") << QString("2") << Intermediate << 3 << 5 << QString();
+ QTest::newRow("data1") << QString() << Intermediate << 0 << 100 << QString();
+ QTest::newRow("data2") << QString("asd") << Invalid << 0 << 100 << QString();
+ QTest::newRow("data3") << QString("2") << Acceptable << 0 << 100 << QString();
+ QTest::newRow("data4") << QString() << Intermediate << 0 << 1 << QString();
+ QTest::newRow("data5") << QString() << Invalid << 0 << 0 << QString();
+ QTest::newRow("data5") << QString("5") << Intermediate << 2004 << 2005 << QString();
+ QTest::newRow("data6") << QString("50") << Intermediate << 2004 << 2005 << QString();
+ QTest::newRow("data7") << QString("205") << Intermediate << 2004 << 2005 << QString();
+ QTest::newRow("data8") << QString("2005") << Acceptable << 2004 << 2005 << QString();
+ QTest::newRow("data9") << QString("3") << Intermediate << 2004 << 2005 << QString();
+ QTest::newRow("data10") << QString("-") << Intermediate << -20 << -10 << QString();
+ QTest::newRow("data11") << QString("-1") << Intermediate << -20 << -10 << QString();
+ QTest::newRow("data12") << QString("-5") << Intermediate << -20 << -10 << QString();
+ QTest::newRow("data13") << QString("-5") << Intermediate << -20 << -16 << QString();
+ QTest::newRow("data14") << QString("-2") << Intermediate << -20 << -16 << QString();
+ QTest::newRow("data15") << QString("2") << Invalid << -20 << -16 << QString();
+ QTest::newRow("data16") << QString() << Intermediate << -20 << -16 << QString();
+ QTest::newRow("data17") << QString(" 22") << Acceptable << 0 << 1000 << QString("22");
+ QTest::newRow("data18") << QString("22 ") << Acceptable << 0 << 1000 << QString("22");
+ QTest::newRow("data19") << QString(" 22 ") << Acceptable << 0 << 1000 << QString("22");
+ QTest::newRow("data20") << QString("2 2") << Invalid << 0 << 1000 << QString();
+}
+
+static QString stateName(int state)
+{
+ switch (state) {
+ case QValidator::Acceptable: return QString("Acceptable");
+ case QValidator::Intermediate: return QString("Intermediate");
+ case QValidator::Invalid: return QString("Invalid");
+ default: break;
+ }
+ qWarning("%s %d: this should never happen", __FILE__, __LINE__);
+ return QString();
+}
+
+void tst_QSpinBox::valueFromTextAndValidate()
+{
+ QFETCH(QString, txt);
+ QFETCH(int, state);
+ QFETCH(int, mini);
+ QFETCH(int, maxi);
+ QFETCH(QString, expectedText);
+
+ SpinBox sb(0);
+ sb.show();
+ sb.setRange(mini, maxi);
+ int unused = 0;
+ QCOMPARE(stateName(sb.validate(txt, unused)), stateName(state));
+ if (!expectedText.isEmpty())
+ QCOMPARE(txt, expectedText);
+}
+
+void tst_QSpinBox::locale_data()
+{
+ QTest::addColumn<QLocale>("loc");
+ QTest::addColumn<int>("value");
+ QTest::addColumn<QString>("textFromVal");
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("valFromText");
+
+ QTest::newRow("data0") << QLocale(QLocale::Norwegian, QLocale::Norway) << 1234 << QString("1234") << QString("2345") << 2345;
+ QTest::newRow("data1") << QLocale(QLocale::German, QLocale::Germany) << 1234 << QString("1234") << QString("2345") << 2345;
+}
+
+void tst_QSpinBox::locale()
+{
+ QFETCH(QLocale, loc);
+ QFETCH(int, value);
+ QFETCH(QString, textFromVal);
+ QFETCH(QString, text);
+ QFETCH(int, valFromText);
+
+ QLocale old;
+
+ QLocale::setDefault(loc);
+ SpinBox box;
+ box.setMaximum(100000);
+ box.setValue(value);
+ QCOMPARE(box.cleanText(), textFromVal);
+
+ box.lineEdit()->setText(text);
+ QCOMPARE(box.cleanText(), text);
+ box.interpretText();
+
+ QCOMPARE(box.value(), valFromText);
+}
+
+
+void tst_QSpinBox::editingFinished()
+{
+ QVBoxLayout *layout = new QVBoxLayout(testFocusWidget);
+ QSpinBox *box = new QSpinBox(testFocusWidget);
+ layout->addWidget(box);
+ QSpinBox *box2 = new QSpinBox(testFocusWidget);
+ layout->addWidget(box2);
+
+ testFocusWidget->show();
+ QApplication::setActiveWindow(testFocusWidget);
+ QTest::qWaitForWindowShown(testFocusWidget);
+ box->activateWindow();
+ box->setFocus();
+
+ QTRY_COMPARE(qApp->focusWidget(), (QWidget *)box);
+
+ QSignalSpy editingFinishedSpy1(box, SIGNAL(editingFinished()));
+ QSignalSpy editingFinishedSpy2(box2, SIGNAL(editingFinished()));
+
+ box->setFocus();
+ QTest::keyClick(box, Qt::Key_Up);
+ QTest::keyClick(box, Qt::Key_Up);
+
+ QCOMPARE(editingFinishedSpy1.count(), 0);
+ QCOMPARE(editingFinishedSpy2.count(), 0);
+
+ QTest::keyClick(box2, Qt::Key_Up);
+ QTest::keyClick(box2, Qt::Key_Up);
+ box2->setFocus();
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+ box->setFocus();
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box, Qt::Key_Up);
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box, Qt::Key_Enter);
+ QCOMPARE(editingFinishedSpy1.count(), 2);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box, Qt::Key_Return);
+ QCOMPARE(editingFinishedSpy1.count(), 3);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ box2->setFocus();
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 1);
+ QTest::keyClick(box2, Qt::Key_Enter);
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 2);
+ QTest::keyClick(box2, Qt::Key_Return);
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 3);
+
+ testFocusWidget->hide();
+ QCOMPARE(editingFinishedSpy1.count(), 4);
+ QCOMPARE(editingFinishedSpy2.count(), 4);
+ QTest::qWait(100);
+
+ //task203285
+ editingFinishedSpy1.clear();
+ testFocusWidget->show();
+ QTest::qWait(100);
+ box->setKeyboardTracking(false);
+ qApp->setActiveWindow(testFocusWidget);
+ testFocusWidget->activateWindow();
+ box->setFocus();
+ QTRY_VERIFY(box->hasFocus());
+ box->setValue(0);
+ QTest::keyClick(box, '2');
+ QCOMPARE(box->text(), QLatin1String("20"));
+ box2->setFocus();
+ QTRY_VERIFY(qApp->focusWidget() != box);
+ QCOMPARE(box->text(), QLatin1String("20"));
+ QCOMPARE(editingFinishedSpy1.count(), 1);
+
+ testFocusWidget->hide();
+}
+
+void tst_QSpinBox::removeAll()
+{
+ SpinBox spin(0);
+ spin.setPrefix("foo");
+ spin.setSuffix("bar");
+ spin.setValue(2);
+ spin.show();
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_Home);
+#endif
+
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Right, Qt::ControlModifier|Qt::ShiftModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_End, Qt::ShiftModifier);
+#endif
+
+ QCOMPARE(spin.lineEdit()->selectedText(), QString("foo2bar"));
+ QTest::keyClick(&spin, Qt::Key_1);
+ QCOMPARE(spin.text(), QString("foo1bar"));
+}
+
+void tst_QSpinBox::startWithDash()
+{
+ SpinBox spin(0);
+ spin.show();
+#ifdef Q_WS_MAC
+ QTest::keyClick(&spin, Qt::Key_Left, Qt::ControlModifier);
+#else
+ QTest::keyClick(&spin, Qt::Key_Home);
+#endif
+ QCOMPARE(spin.text(), QString("0"));
+ QTest::keyClick(&spin, Qt::Key_Minus);
+ QCOMPARE(spin.text(), QString("0"));
+}
+
+void tst_QSpinBox::undoRedo()
+{
+ //test undo/redo feature (in conjunction with the "undoRedoEnabled" property)
+ SpinBox spin(0);
+ spin.show();
+
+ //the undo/redo is disabled by default
+
+ QCOMPARE(spin.value(), 0); //this is the default value
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+
+ spin.lineEdit()->selectAll(); //ensures everything is selected and will be cleared by typing a key
+ QTest::keyClick(&spin, Qt::Key_1); //we put 1 into the spinbox
+ QCOMPARE(spin.value(), 1);
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+
+ //testing CTRL+Z (undo)
+ int val = QKeySequence(QKeySequence::Undo)[0];
+ Qt::KeyboardModifiers mods = (Qt::KeyboardModifiers)(val & Qt::KeyboardModifierMask);
+ QTest::keyClick(&spin, val & ~mods, mods);
+
+ QCOMPARE(spin.value(), 0);
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(spin.lineEdit()->isRedoAvailable());
+
+ //testing CTRL+Y (redo)
+ val = QKeySequence(QKeySequence::Redo)[0];
+ mods = (Qt::KeyboardModifiers)(val & Qt::KeyboardModifierMask);
+ QTest::keyClick(&spin, val & ~mods, mods);
+ QCOMPARE(spin.value(), 1);
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+
+ spin.setValue(55);
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+
+ QTest::keyClick(&spin, Qt::Key_Return);
+ QTest::keyClick(&spin, '1');
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+ spin.lineEdit()->undo();
+ QCOMPARE(spin.value(), 55);
+ QVERIFY(!spin.lineEdit()->isUndoAvailable());
+ QVERIFY(spin.lineEdit()->isRedoAvailable());
+ spin.lineEdit()->redo();
+ QCOMPARE(spin.value(), 1);
+ QVERIFY(spin.lineEdit()->isUndoAvailable());
+ QVERIFY(!spin.lineEdit()->isRedoAvailable());
+}
+
+void tst_QSpinBox::specialValue()
+{
+ QString specialText="foo";
+
+ QWidget topWidget;
+ QVBoxLayout layout(&topWidget);
+ SpinBox spin(&topWidget);
+ layout.addWidget(&spin);
+ SpinBox box2(&topWidget);
+ layout.addWidget(&box2);
+
+ spin.setSpecialValueText(specialText);
+ spin.setMinimum(0);
+ spin.setMaximum(100);
+ spin.setValue(50);
+ topWidget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&topWidget);
+#endif
+ QTest::qWait(100);
+ //make sure we have the focus (even if editingFinished fails)
+ qApp->setActiveWindow(&topWidget);
+ topWidget.activateWindow();
+ spin.setFocus();
+
+ QTest::keyClick(&spin, Qt::Key_Return);
+ QTest::keyClick(&spin, '0');
+ QCOMPARE(spin.text(), QString("0"));
+ QTest::keyClick(&spin, Qt::Key_Return);
+ QCOMPARE(spin.text(), specialText);
+
+ spin.setValue(50);
+ QTest::keyClick(&spin, Qt::Key_Return);
+ QTest::keyClick(&spin, '0');
+ QCOMPARE(spin.text(), QString("0"));
+ QTest::keyClick(spin.lineEdit(), Qt::Key_Tab);
+ QCOMPARE(spin.text(), specialText);
+
+ spin.setValue(50);
+ spin.setFocus();
+ QTest::keyClick(&spin, Qt::Key_Return);
+ QTest::keyClick(&spin, '0');
+ QCOMPARE(spin.text(), QString("0"));
+ box2.setFocus();
+ QCOMPARE(spin.text(), specialText);
+}
+
+void tst_QSpinBox::textFromValue()
+{
+ SpinBox spinBox;
+ QCOMPARE(spinBox.textFromValue(INT_MIN), QString::number(INT_MIN));
+}
+
+class sizeHint_SpinBox : public QSpinBox
+{
+public:
+ QSize sizeHint() const
+ {
+ ++sizeHintRequests;
+ return QSpinBox::sizeHint();
+ }
+ mutable int sizeHintRequests;
+};
+
+void tst_QSpinBox::sizeHint()
+{
+ QWidget *widget = new QWidget;
+ QHBoxLayout *layout = new QHBoxLayout(widget);
+ sizeHint_SpinBox *spinBox = new sizeHint_SpinBox;
+ layout->addWidget(spinBox);
+ widget->show();
+ QTest::qWaitForWindowShown(widget);
+
+ // Prefix
+ spinBox->sizeHintRequests = 0;
+ spinBox->setPrefix(QLatin1String("abcdefghij"));
+ qApp->processEvents();
+ QTRY_VERIFY(spinBox->sizeHintRequests > 0);
+
+ // Suffix
+ spinBox->sizeHintRequests = 0;
+ spinBox->setSuffix(QLatin1String("abcdefghij"));
+ qApp->processEvents();
+ QTRY_VERIFY(spinBox->sizeHintRequests > 0);
+
+ // Range
+ spinBox->sizeHintRequests = 0;
+ spinBox->setRange(0, 1234567890);
+ spinBox->setValue(spinBox->maximum());
+ qApp->processEvents();
+ QTRY_VERIFY(spinBox->sizeHintRequests > 0);
+
+ delete widget;
+}
+
+void tst_QSpinBox::taskQTBUG_5008_textFromValueAndValidate()
+{
+ class DecoratedSpinBox : public QSpinBox
+ {
+ public:
+ DecoratedSpinBox()
+ {
+ setLocale(QLocale::French);
+ setMaximum(100000000);
+ setValue(1000000);
+ }
+
+ QLineEdit *lineEdit() const
+ {
+ return QSpinBox::lineEdit();
+ }
+
+ //we use the French delimiters here
+ QString textFromValue (int value) const
+ {
+ return locale().toString(value);
+ }
+
+ } spinbox;
+ spinbox.show();
+ spinbox.activateWindow();
+ spinbox.setFocus();
+ QApplication::setActiveWindow(&spinbox);
+ QTest::qWaitForWindowShown(&spinbox);
+ QTRY_VERIFY(spinbox.hasFocus());
+ QTRY_COMPARE(static_cast<QWidget *>(&spinbox), QApplication::activeWindow());
+ QCOMPARE(spinbox.text(), spinbox.locale().toString(spinbox.value()));
+ spinbox.lineEdit()->setCursorPosition(2); //just after the first thousand separator
+ QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_0); // let's insert a 0
+ QCOMPARE(spinbox.value(), 10000000); //it's been multiplied by 10
+ spinbox.clearFocus(); //make sure the value is correctly formatted
+ QCOMPARE(spinbox.text(), spinbox.locale().toString(spinbox.value()));
+}
+
+
+QTEST_MAIN(tst_QSpinBox)
+#include "tst_qspinbox.moc"
diff --git a/tests/auto/widgets/widgets/qsplitter/.gitignore b/tests/auto/widgets/widgets/qsplitter/.gitignore
new file mode 100644
index 0000000000..311db65ff0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsplitter/.gitignore
@@ -0,0 +1 @@
+tst_qsplitter
diff --git a/tests/auto/widgets/widgets/qsplitter/extradata.txt b/tests/auto/widgets/widgets/qsplitter/extradata.txt
new file mode 100644
index 0000000000..ceb46d4a82
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsplitter/extradata.txt
@@ -0,0 +1,10067 @@
+// This is a bunch of extra data that really needs to be converted over. However, the execpted values (line 3 in the data) have not been computed.
+#if 0
+
+ *t.newData("ok000000000573") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000574") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000575") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000576") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000577") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000600") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000601") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000602") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000603") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000604") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000605") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000606") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000607") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000610") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000611") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000612") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000613") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000614") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000615") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000616") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000617") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000620") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000621") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000622") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000623") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000624") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000625") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000626") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000627") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000630") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000631") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000632") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000633") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000634") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000635") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000636") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000637") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000640") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000641") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000642") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000643") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000644") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000645") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000646") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000647") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000650") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000651") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000652") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000653") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000654") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000655") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000656") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000657") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000660") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000661") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000662") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000663") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000664") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000665") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000666") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000667") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000670") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000671") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000672") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000673") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000674") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000675") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000676") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000677") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000700") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000701") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000702") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000703") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000704") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000705") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000706") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000707") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000710") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000711") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000712") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000713") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000714") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000715") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000716") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000717") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000720") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000721") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000722") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000723") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000724") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000725") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000726") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000727") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000730") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000731") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000732") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000733") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000734") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000735") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000736") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000737") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000740") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000741") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000742") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000743") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000744") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000745") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000746") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000747") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000750") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000751") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000752") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000753") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000754") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000755") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000757") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000760") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000761") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000762") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000763") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+
+ *t.newData("ok000000000764") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000765") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000766") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000767") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000770") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << true;
+
+ *t.newData("ok000000000771") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000000772") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000000773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000000774") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000000775") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000776") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000000777") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001001") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001002") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 504 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001004") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001006") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001007") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 504 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001011") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001014") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 504 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001016") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001021") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001023") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001026") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001030") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001033") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001035") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001040") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001042") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001045") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000056") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001047") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001052") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001054") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001056") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001057") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000070") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001061") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001064") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001066") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001070") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001071") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001073") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001076") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001100") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001103") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001105") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001110") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001112") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001115") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001117") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001122") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001124") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001127") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001131") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001134") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001136") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001141") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001143") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001144") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001146") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001150") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001151") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001153") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001156") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001160") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001161") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+
+ *t.newData("ok000000000172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001163") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001164") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001166") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << true;
+
+ *t.newData("ok000000001167") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001170") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001171") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001173") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000001174") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001175") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001176") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001177") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001200") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 630 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001202") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001203") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001204") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001205") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 630 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001207") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001210") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001211") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001212") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 630 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001214") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001215") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001216") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001217") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001221") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001222") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001223") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001224") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001226") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001227") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001230") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001231") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001233") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001234") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001235") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001236") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001240") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001241") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001242") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001243") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000056") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001245") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001246") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001247") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001250") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001252") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001253") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001254") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001255") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000070") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001257") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001260") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001261") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001262") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001264") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001265") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001266") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001267") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001271") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001272") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001273") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001274") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001276") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001277") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001300") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001301") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001303") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001304") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001305") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001306") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001310") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001311") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001312") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001313") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001315") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001316") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001317") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001320") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001322") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001323") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001324") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001325") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001327") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001330") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001331") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001332") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001334") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001335") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001336") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001337") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001341") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001342") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001343") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001344") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001346") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001347") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001350") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001351") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001354") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001355") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001356") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001357") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+
+ *t.newData("ok000000000172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001361") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001362") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001363") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001364") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << true;
+
+ *t.newData("ok000000001365") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001366") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001367") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001370") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001371") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000001372") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001373") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001374") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001375") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001376") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 756 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001400") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001401") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001402") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001403") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 756 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001405") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001406") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001407") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001410") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 756 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001412") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001413") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001414") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001415") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001417") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001420") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001421") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001422") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001424") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001425") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001426") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001427") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001431") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001432") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001433") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001434") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001436") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001437") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001440") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001441") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000001456") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001443") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001444") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001445") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001446") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001450") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001451") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001452") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001453") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000001454") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001455") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001456") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001457") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001460") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001462") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001463") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001464") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001465") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001467") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001470") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001471") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001472") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001474") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001475") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001476") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001477") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001501") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001502") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001503") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001504") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001506") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001507") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001510") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001511") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001513") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001514") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001515") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001516") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001520") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001521") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001522") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001523") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001525") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001526") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001527") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001530") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001532") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001533") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001534") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001535") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001537") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001540") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001541") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001542") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001544") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001545") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001546") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001547") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001552") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001553") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001554") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001555") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000000172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001557") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001560") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001561") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+ *t.newData("ok000000001562") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << true;
+
+
+ *t.newData("ok000000001563") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001564") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001565") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001566") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001567") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000001570") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001571") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001572") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001573") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001574") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 882 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001576") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001577") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001600") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001601") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 882 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001603") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001604") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001605") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001606") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 882 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001610") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001611") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001612") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001613") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001615") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001616") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001617") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001620") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001622") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001623") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001624") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001625") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001627") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001630") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001631") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001632") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001634") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001635") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001636") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001637") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000056") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001641") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001642") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001643") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001644") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001646") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001647") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001650") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001651") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000070") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001653") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001654") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001655") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001656") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001660") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001661") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001662") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001663") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001665") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001666") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001667") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001670") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001672") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001673") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001674") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001675") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001677") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001700") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001701") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001702") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001704") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001705") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001706") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001707") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001711") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001712") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001713") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001714") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001716") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001717") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001720") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001721") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001723") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001724") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001725") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001726") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001730") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001731") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001732") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001733") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001735") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001736") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001737") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001740") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001742") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001743") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001744") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001745") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001750") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001751") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001752") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001753") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+
+ *t.newData("ok000000000172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001755") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001756") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001757") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+
+ *t.newData("ok000000001760") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << true;
+ *t.newData("ok000000001761") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001762") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001763") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001764") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001765") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000001766") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001767") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001770") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001771") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001772") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000001773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001774") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001775") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001776") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000001777") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002001") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002002") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002003") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002004") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002006") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002007") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002010") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002011") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002014") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002015") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002016") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002021") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002022") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002023") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002026") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002027") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002030") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002033") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002034") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002035") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002040") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002041") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002042") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002045") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002046") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002047") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002052") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002053") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002054") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002056") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002057") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002060") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002061") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002064") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002065") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002066") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002070") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002071") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002072") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002073") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002076") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002077") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002100") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002103") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002104") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002105") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002110") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002111") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002112") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002115") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002116") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002117") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002122") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002123") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002124") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002127") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002130") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002131") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002134") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002135") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002136") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002141") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002142") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002143") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002146") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002147") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002150") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002151") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002153") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002154") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002155") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+ *t.newData("ok000000002156") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << true)
+ << false;
+
+
+ *t.newData("ok000000002157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002160") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002161") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002162") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002163") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002164") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002166") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002167") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002170") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002171") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002173") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002174") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002175") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002176") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002177") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002200") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002201") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002202") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002203") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002204") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002205") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002206") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002207") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002210") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002211") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002212") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002213") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002214") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002215") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002216") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002217") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002220") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002221") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002222") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002223") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002224") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002225") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002226") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002227") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002230") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002231") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002232") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002233") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002234") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002235") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002236") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002237") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002240") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002241") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002242") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002243") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002244") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002245") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002246") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002247") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002250") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002251") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002252") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002253") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002254") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002255") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002256") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002257") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002260") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002261") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002262") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002263") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002264") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002265") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002266") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002267") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002270") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002271") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002272") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002273") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002274") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002275") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002276") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002277") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002300") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002301") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002302") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002303") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002304") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002305") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002306") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002307") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002310") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002311") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002312") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002313") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002314") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002315") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002316") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002317") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002320") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002321") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002322") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002323") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002324") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002325") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002326") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002327") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002330") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002331") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002332") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002333") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002334") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002335") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002336") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002337") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002340") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002341") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002343") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002344") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002345") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002346") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002347") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+
+ *t.newData("ok000000002350") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002351") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002352") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002353") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002354") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << true << false)
+ << false;
+
+ *t.newData("ok000000002355") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002356") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002357") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002360") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002361") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002362") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002363") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002364") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002365") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002366") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002367") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002370") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002371") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002372") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002373") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002374") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002375") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002376") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002377") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002400") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002401") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002402") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002403") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002404") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002405") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002406") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002407") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002410") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002411") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002412") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002413") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002414") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002415") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002416") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002417") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002420") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002421") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002422") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002423") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002424") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002425") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002426") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002427") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002430") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002431") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002432") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002433") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002434") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002435") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002436") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002437") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002440") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002441") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002442") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002443") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002444") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002445") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002446") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002447") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002450") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002451") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002452") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002453") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002454") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002455") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002456") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002457") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002460") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002461") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002462") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002463") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002464") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002465") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002466") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002467") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002470") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002471") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002472") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002473") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002474") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002475") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002476") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002477") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002500") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002501") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002502") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002503") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002504") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002505") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002506") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002507") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002510") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002511") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002512") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002513") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002514") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002515") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002516") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002517") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002520") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002521") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002522") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002523") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002524") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002525") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002526") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002527") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002530") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002531") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002532") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002533") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002534") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002535") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002536") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002537") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002541") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002542") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002543") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002544") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002545") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+
+ *t.newData("ok000000002546") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002547") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002550") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002551") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002552") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << true)
+ << false;
+
+ *t.newData("ok000000002553") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002554") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002555") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002556") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002557") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002560") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002561") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002562") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002563") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002564") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002565") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002566") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002567") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002570") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002571") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002572") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002573") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002574") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002575") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002576") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002577") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002600") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002601") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002602") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002603") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002604") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002605") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002606") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002607") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002610") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002611") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002612") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002613") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002614") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002615") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002616") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002617") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002620") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002621") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002622") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002623") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002624") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002625") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002626") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002627") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002630") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002631") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002632") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002633") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002634") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002635") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002636") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002637") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002640") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002641") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002642") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002643") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002644") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002645") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002646") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002647") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002650") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002651") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002652") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002653") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002654") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002655") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002656") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002657") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002660") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002661") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002662") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002663") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002664") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002665") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002666") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002667") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002670") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002671") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002672") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002673") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002674") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002675") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002676") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002677") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002700") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002701") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002702") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002703") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002704") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002705") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002706") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002707") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002710") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002711") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002712") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002713") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002714") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002715") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002716") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002717") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002720") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002721") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002722") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002723") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002724") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002725") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002726") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002727") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002730") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002731") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002732") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002733") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002734") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002735") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002737") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002740") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002741") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002742") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002743") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+
+ *t.newData("ok000000002744") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002745") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002746") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002747") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002750") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << true << false << false)
+ << false;
+
+ *t.newData("ok000000002751") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002752") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002753") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002754") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002755") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002756") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002757") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002760") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002761") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002762") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000001773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 504 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002764") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002765") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002766") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002767") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 504 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002771") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002772") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002774") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 504 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002776") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000002777") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003001") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003003") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003004") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003006") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003010") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003011") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003013") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003015") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003016") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003020") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003022") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003023") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003025") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 554 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003027") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003030") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003032") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003034") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003035") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003037") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003041") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003042") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003044") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003046") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003047") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003051") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003053") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003054") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003056") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 604 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003060") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003061") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003063") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003065") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003066") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003070") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003072") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003073") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003075") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003077") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003100") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003102") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003104") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003105") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003107") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 704 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003111") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003112") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003114") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003116") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003117") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003121") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003123") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003124") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003126") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003130") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003131") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003133") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003136") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003140") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003141") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+
+ *t.newData("ok000000002152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1004 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003143") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003144") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003146") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << true)
+ << false;
+
+ *t.newData("ok000000003147") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003150") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003151") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003153") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000003154") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003155") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003156") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003157") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003160") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000001773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 630 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003162") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003163") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003164") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003165") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 630 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003167") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003170") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003171") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003172") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 630 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003174") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003175") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003176") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003177") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003201") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003202") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003203") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003204") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003206") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003207") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003210") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003211") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003213") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003214") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003215") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003216") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003220") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003221") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003222") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003223") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 680 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003225") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003226") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003227") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003230") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003232") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003233") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003234") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003235") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003237") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003240") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003241") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003242") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003244") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003245") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003246") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003247") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003251") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003252") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003253") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003254") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 730 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003256") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003257") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003260") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003261") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003263") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003264") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003265") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003266") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003270") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003271") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003272") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003273") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003275") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003276") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003277") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003300") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003302") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003303") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003304") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003305") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 830 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003307") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003310") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003311") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003312") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003314") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003315") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003316") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003317") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003321") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003322") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003323") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003324") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003326") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003327") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003330") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003331") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003334") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003335") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003336") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003337") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+
+ *t.newData("ok000000002152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1130 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003341") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003342") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003343") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003344") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << true << false)
+ << false;
+
+ *t.newData("ok000000003345") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003346") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003347") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003350") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003351") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000003352") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003353") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003354") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003355") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003356") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000001773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 756 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003360") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003361") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003362") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003363") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 756 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003365") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003366") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003367") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003370") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 756 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003372") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003373") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003374") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003375") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003377") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003400") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003401") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003402") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003404") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003405") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003406") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003407") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003411") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003412") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003413") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003414") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003416") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003417") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003420") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003421") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 806 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003423") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003424") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003425") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003426") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003430") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003431") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003432") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003433") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003435") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003436") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003437") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003440") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003442") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003443") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003444") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003445") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003447") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003450") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003451") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003452") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 856 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003454") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003455") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003456") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003457") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003461") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003462") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003463") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003464") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003466") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003467") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003470") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003471") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003473") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003474") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003475") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003476") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003500") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003501") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003502") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003503") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 956 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003505") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003506") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003507") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003510") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003512") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003513") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003514") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003515") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003517") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003520") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003521") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003522") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003524") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003525") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003526") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003527") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003532") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003533") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003534") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003535") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000002152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1256 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003537") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003540") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003541") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+ *t.newData("ok000000003542") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << true)
+ << false;
+
+
+ *t.newData("ok000000003543") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003544") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003545") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003546") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003547") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000003550") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003551") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003552") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003553") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003554") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000001773") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 882 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003556") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003557") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003560") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003561") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002000") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 882 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003563") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003564") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003565") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003566") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002005") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 882 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003570") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003571") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003572") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003573") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002012") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003575") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003576") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003577") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003600") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002017") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003602") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003603") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003604") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003605") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002024") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003607") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003610") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003611") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003612") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002031") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003614") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003615") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003616") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003617") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002036") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 932 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003621") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003622") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003623") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003624") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 50 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002043") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003626") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003627") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003630") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003631") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002050") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003633") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003634") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003635") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003636") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002055") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003640") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003641") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003642") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003643") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002062") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003645") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003646") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003647") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003650") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002067") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 982 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003652") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003653") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003654") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003655") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 100 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002074") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003657") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003660") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003661") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003662") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002101") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003664") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003665") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003666") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003667") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002106") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003671") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003672") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003673") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003674") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002113") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003676") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003677") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003700") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003701") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002120") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1082 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003703") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003704") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003705") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003706") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 200 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002125") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 0 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003710") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003711") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003712") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003713") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 0 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002132") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 50 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003715") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003716") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003717") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003720") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 50 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002137") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 100 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003722") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003723") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003724") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003725") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 100 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002145") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 200 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003730") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003731") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003732") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003733") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 200 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+
+ *t.newData("ok000000002152") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 1382 << 500 << 0)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003735") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 50)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003736") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 100)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003737") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 200)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+
+ *t.newData("ok000000003740") << (IntList() << 100 << 100 << 100)
+ << (IntList() << 500 << 500 << 500)
+ << (IntList() << 0 << 0 << 1000)
+ << (IntList() << false << false << false)
+ << false;
+#endif
diff --git a/tests/auto/widgets/widgets/qsplitter/qsplitter.pro b/tests/auto/widgets/widgets/qsplitter/qsplitter.pro
new file mode 100644
index 0000000000..9942c899ca
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsplitter/qsplitter.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qsplitter.cpp
+
+wince* {
+ addFiles.files = extradata.txt setSizes3.dat
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+ DEFINES += SRCDIR=\\\"./\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
diff --git a/tests/auto/widgets/widgets/qsplitter/setSizes3.dat b/tests/auto/widgets/widgets/qsplitter/setSizes3.dat
new file mode 100644
index 0000000000..5d8a73d6f9
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsplitter/setSizes3.dat
@@ -0,0 +1,2250 @@
+ok000000000001
+100 100 100
+0 0 0
+0 0 0
+1 1 1
+1
+ok000000000002
+100 100 100
+0 0 50
+0 0 600
+1 1 1
+1
+ok000000000003
+100 100 100
+0 0 100
+0 0 600
+1 1 1
+1
+ok000000000004
+100 100 100
+0 0 200
+0 0 600
+1 1 1
+1
+ok000000000005
+100 100 100
+0 0 500
+0 0 600
+1 1 1
+1
+ok000000000006
+100 100 100
+0 50 0
+0 600 0
+1 1 1
+1
+ok000000000007
+100 100 100
+0 50 50
+0 300 300
+1 1 1
+1
+ok000000000010
+100 100 100
+0 50 100
+0 300 300
+1 1 1
+1
+ok000000000011
+100 100 100
+0 50 200
+0 200 400
+1 1 1
+1
+ok000000000012
+100 100 100
+0 50 500
+0 100 500
+1 1 1
+1
+ok000000000013
+100 100 100
+0 100 0
+0 600 0
+1 1 1
+1
+ok000000000014
+100 100 100
+0 100 50
+0 300 300
+1 1 1
+1
+ok000000000015
+100 100 100
+0 100 100
+0 300 300
+1 1 1
+1
+ok000000000016
+100 100 100
+0 100 200
+0 200 400
+1 1 1
+1
+ok000000000017
+100 100 100
+0 100 500
+0 100 500
+1 1 1
+1
+ok000000000020
+100 100 100
+0 200 0
+0 600 0
+1 1 1
+1
+ok000000000021
+100 100 100
+0 200 50
+0 400 200
+1 1 1
+1
+ok000000000022
+100 100 100
+0 200 100
+0 400 200
+1 1 1
+1
+ok000000000023
+100 100 100
+0 200 200
+0 300 300
+1 1 1
+1
+ok000000000024
+100 100 100
+0 200 500
+0 171 429
+1 1 1
+1
+ok000000000025
+100 100 100
+0 500 0
+0 600 0
+1 1 1
+1
+ok000000000026
+100 100 100
+0 500 50
+0 500 100
+1 1 1
+1
+ok000000000027
+100 100 100
+0 500 100
+0 500 100
+1 1 1
+1
+ok000000000030
+100 100 100
+0 500 200
+0 429 171
+1 1 1
+1
+ok000000000031
+100 100 100
+0 500 500
+0 300 300
+1 1 1
+1
+ok000000000032
+100 100 100
+50 0 0
+600 0 0
+1 1 1
+1
+ok000000000033
+100 100 100
+50 0 50
+300 0 300
+1 1 1
+1
+ok000000000034
+100 100 100
+50 0 100
+300 0 300
+1 1 1
+1
+ok000000000035
+100 100 100
+50 0 200
+200 0 400
+1 1 1
+1
+ok000000000036
+100 100 100
+50 0 500
+100 0 500
+1 1 1
+1
+ok000000000037
+100 100 100
+50 50 0
+300 300 0
+1 1 1
+1
+ok000000000040
+100 100 100
+50 50 50
+200 200 200
+1 1 1
+1
+ok000000000041
+100 100 100
+50 50 100
+200 200 200
+1 1 1
+1
+ok000000000042
+100 100 100
+50 50 200
+150 150 300
+1 1 1
+1
+ok000000000043
+100 100 100
+50 50 500
+100 100 400
+1 1 1
+1
+ok000000000044
+100 100 100
+50 100 0
+300 300 0
+1 1 1
+1
+ok000000000045
+100 100 100
+50 100 50
+200 200 200
+1 1 1
+1
+ok000000000046
+100 100 100
+50 100 100
+200 200 200
+1 1 1
+1
+ok000000000047
+100 100 100
+50 100 200
+150 150 300
+1 1 1
+1
+ok000000000050
+100 100 100
+50 100 500
+100 100 400
+1 1 1
+1
+ok000000000051
+100 100 100
+50 200 0
+200 400 0
+1 1 1
+1
+ok000000000052
+100 100 100
+50 200 50
+150 300 150
+1 1 1
+1
+ok000000000053
+100 100 100
+50 200 100
+150 300 150
+1 1 1
+1
+ok000000000054
+100 100 100
+50 200 200
+120 240 240
+1 1 1
+1
+ok000000000055
+100 100 100
+50 200 500
+100 143 357
+1 1 1
+1
+ok000000000056
+100 100 100
+50 500 0
+100 500 0
+1 1 1
+1
+ok000000000057
+100 100 100
+50 500 50
+100 400 100
+1 1 1
+1
+ok000000000060
+100 100 100
+50 500 100
+100 400 100
+1 1 1
+1
+ok000000000061
+100 100 100
+50 500 200
+100 357 143
+1 1 1
+1
+ok000000000062
+100 100 100
+50 500 500
+100 250 250
+1 1 1
+1
+ok000000000063
+100 100 100
+100 0 0
+600 0 0
+1 1 1
+1
+ok000000000064
+100 100 100
+100 0 50
+300 0 300
+1 1 1
+1
+ok000000000065
+100 100 100
+100 0 100
+300 0 300
+1 1 1
+1
+ok000000000066
+100 100 100
+100 0 200
+200 0 400
+1 1 1
+1
+ok000000000067
+100 100 100
+100 0 500
+100 0 500
+1 1 1
+1
+ok000000000070
+100 100 100
+100 50 0
+300 300 0
+1 1 1
+1
+ok000000000071
+100 100 100
+100 50 50
+200 200 200
+1 1 1
+1
+ok000000000072
+100 100 100
+100 50 100
+200 200 200
+1 1 1
+1
+ok000000000073
+100 100 100
+100 50 200
+150 150 300
+1 1 1
+1
+ok000000000074
+100 100 100
+100 50 500
+100 100 400
+1 1 1
+1
+ok000000000075
+100 100 100
+100 100 0
+300 300 0
+1 1 1
+1
+ok000000000076
+100 100 100
+100 100 50
+200 200 200
+1 1 1
+1
+ok000000000077
+100 100 100
+100 100 100
+200 200 200
+1 1 1
+1
+ok000000000100
+100 100 100
+100 100 200
+150 150 300
+1 1 1
+1
+ok000000000101
+100 100 100
+100 100 500
+100 100 400
+1 1 1
+1
+ok000000000102
+100 100 100
+100 200 0
+200 400 0
+1 1 1
+1
+ok000000000103
+100 100 100
+100 200 50
+150 300 150
+1 1 1
+1
+ok000000000104
+100 100 100
+100 200 100
+150 300 150
+1 1 1
+1
+ok000000000105
+100 100 100
+100 200 200
+120 240 240
+1 1 1
+1
+ok000000000106
+100 100 100
+100 200 500
+100 143 357
+1 1 1
+1
+ok000000000107
+100 100 100
+100 500 0
+100 500 0
+1 1 1
+1
+ok000000000110
+100 100 100
+100 500 50
+100 400 100
+1 1 1
+1
+ok000000000111
+100 100 100
+100 500 100
+100 400 100
+1 1 1
+1
+ok000000000112
+100 100 100
+100 500 200
+100 357 143
+1 1 1
+1
+ok000000000113
+100 100 100
+100 500 500
+100 250 250
+1 1 1
+1
+ok000000000114
+100 100 100
+200 0 0
+600 0 0
+1 1 1
+1
+ok000000000115
+100 100 100
+200 0 50
+400 0 200
+1 1 1
+1
+ok000000000116
+100 100 100
+200 0 100
+400 0 200
+1 1 1
+1
+ok000000000117
+100 100 100
+200 0 200
+300 0 300
+1 1 1
+1
+ok000000000120
+100 100 100
+200 0 500
+171 0 429
+1 1 1
+1
+ok000000000121
+100 100 100
+200 50 0
+400 200 0
+1 1 1
+1
+ok000000000122
+100 100 100
+200 50 50
+300 150 150
+1 1 1
+1
+ok000000000123
+100 100 100
+200 50 100
+300 150 150
+1 1 1
+1
+ok000000000124
+100 100 100
+200 50 200
+240 120 240
+1 1 1
+1
+ok000000000125
+100 100 100
+200 50 500
+143 100 357
+1 1 1
+1
+ok000000000126
+100 100 100
+200 100 0
+400 200 0
+1 1 1
+1
+ok000000000127
+100 100 100
+200 100 50
+300 150 150
+1 1 1
+1
+ok000000000130
+100 100 100
+200 100 100
+300 150 150
+1 1 1
+1
+ok000000000131
+100 100 100
+200 100 200
+240 120 240
+1 1 1
+1
+ok000000000132
+100 100 100
+200 100 500
+143 100 357
+1 1 1
+1
+ok000000000133
+100 100 100
+200 200 0
+300 300 0
+1 1 1
+1
+ok000000000134
+100 100 100
+200 200 50
+240 240 120
+1 1 1
+1
+ok000000000135
+100 100 100
+200 200 100
+240 240 120
+1 1 1
+1
+ok000000000136
+100 100 100
+200 200 200
+200 200 200
+1 1 1
+1
+ok000000000137
+100 100 100
+200 200 500
+133 134 333
+1 1 1
+1
+ok000000000140
+100 100 100
+200 500 0
+171 429 0
+1 1 1
+1
+ok000000000141
+100 100 100
+200 500 50
+143 357 100
+1 1 1
+1
+ok000000000142
+100 100 100
+200 500 100
+143 357 100
+1 1 1
+1
+ok000000000143
+100 100 100
+200 500 200
+133 334 133
+1 1 1
+1
+ok000000000144
+100 100 100
+200 500 500
+100 250 250
+1 1 1
+1
+ok000000000145
+100 100 100
+500 0 0
+600 0 0
+1 1 1
+1
+ok000000000146
+100 100 100
+500 0 50
+500 0 100
+1 1 1
+1
+ok000000000147
+100 100 100
+500 0 100
+500 0 100
+1 1 1
+1
+ok000000000150
+100 100 100
+500 0 200
+429 0 171
+1 1 1
+1
+ok000000000151
+100 100 100
+500 0 500
+300 0 300
+1 1 1
+1
+ok000000000152
+100 100 100
+500 50 0
+500 100 0
+1 1 1
+1
+ok000000000153
+100 100 100
+500 50 50
+400 100 100
+1 1 1
+1
+ok000000000154
+100 100 100
+500 50 100
+400 100 100
+1 1 1
+1
+ok000000000155
+100 100 100
+500 50 200
+357 100 143
+1 1 1
+1
+ok000000000156
+100 100 100
+500 50 500
+250 100 250
+1 1 1
+1
+ok000000000157
+100 100 100
+500 100 0
+500 100 0
+1 1 1
+1
+ok000000000160
+100 100 100
+500 100 50
+400 100 100
+1 1 1
+1
+ok000000000161
+100 100 100
+500 100 100
+400 100 100
+1 1 1
+1
+ok000000000162
+100 100 100
+500 100 200
+357 100 143
+1 1 1
+1
+ok000000000163
+100 100 100
+500 100 500
+250 100 250
+1 1 1
+1
+ok000000000165
+100 100 100
+500 200 0
+429 171 0
+1 1 1
+1
+ok000000000166
+100 100 100
+500 200 50
+357 143 100
+1 1 1
+1
+ok000000000167
+100 100 100
+500 200 100
+357 143 100
+1 1 1
+1
+ok000000000170
+100 100 100
+500 200 200
+333 134 133
+1 1 1
+1
+ok000000000171
+100 100 100
+500 200 500
+250 100 250
+1 1 1
+1
+ok000000000172
+100 100 100
+500 500 0
+300 300 0
+1 1 1
+1
+ok000000000173
+100 100 100
+500 500 50
+250 250 100
+1 1 1
+1
+ok000000000174
+100 100 100
+500 500 100
+250 250 100
+1 1 1
+1
+ok000000000175
+100 100 100
+500 500 200
+250 250 100
+1 1 1
+1
+ok000000000176
+100 100 100
+500 500 500
+200 200 200
+1 1 1
+1
+ok000000000177
+100 100 100
+0 0 0
+0 0 600
+1 1 0
+1
+ok000000000200
+100 100 100
+0 0 50
+0 0 600
+1 1 0
+1
+ok000000000201
+100 100 100
+0 0 100
+0 0 600
+1 1 0
+1
+ok000000000202
+100 100 100
+0 0 200
+0 0 600
+1 1 0
+1
+ok000000000203
+100 100 100
+0 0 500
+0 0 600
+1 1 0
+1
+ok000000000204
+100 100 100
+0 50 0
+0 300 300
+1 1 0
+1
+ok000000000205
+100 100 100
+0 50 50
+0 300 300
+1 1 0
+1
+ok000000000206
+100 100 100
+0 50 100
+0 300 300
+1 1 0
+1
+ok000000000207
+100 100 100
+0 50 200
+0 200 400
+1 1 0
+1
+ok000000000210
+100 100 100
+0 50 500
+0 100 500
+1 1 0
+1
+ok000000000211
+100 100 100
+0 100 0
+0 300 300
+1 1 0
+1
+ok000000000212
+100 100 100
+0 100 50
+0 300 300
+1 1 0
+1
+ok000000000213
+100 100 100
+0 100 100
+0 300 300
+1 1 0
+1
+ok000000000214
+100 100 100
+0 100 200
+0 200 400
+1 1 0
+1
+ok000000000215
+100 100 100
+0 100 500
+0 100 500
+1 1 0
+1
+ok000000000216
+100 100 100
+0 200 0
+0 400 200
+1 1 0
+1
+ok000000000217
+100 100 100
+0 200 50
+0 400 200
+1 1 0
+1
+ok000000000220
+100 100 100
+0 200 100
+0 400 200
+1 1 0
+1
+ok000000000221
+100 100 100
+0 200 200
+0 300 300
+1 1 0
+1
+ok000000000222
+100 100 100
+0 200 500
+0 171 429
+1 1 0
+1
+ok000000000223
+100 100 100
+0 500 0
+0 500 100
+1 1 0
+1
+ok000000000224
+100 100 100
+0 500 50
+0 500 100
+1 1 0
+1
+ok000000000225
+100 100 100
+0 500 100
+0 500 100
+1 1 0
+1
+ok000000000226
+100 100 100
+0 500 200
+0 429 171
+1 1 0
+1
+ok000000000227
+100 100 100
+0 500 500
+0 300 300
+1 1 0
+1
+ok000000000230
+100 100 100
+50 0 0
+300 0 300
+1 1 0
+1
+ok000000000231
+100 100 100
+50 0 50
+300 0 300
+1 1 0
+1
+ok000000000232
+100 100 100
+50 0 100
+300 0 300
+1 1 0
+1
+ok000000000233
+100 100 100
+50 0 200
+200 0 400
+1 1 0
+1
+ok000000000234
+100 100 100
+50 0 500
+100 0 500
+1 1 0
+1
+ok000000000235
+100 100 100
+50 50 0
+200 200 200
+1 1 0
+1
+ok000000000236
+100 100 100
+50 50 50
+200 200 200
+1 1 0
+1
+ok000000000237
+100 100 100
+50 50 100
+200 200 200
+1 1 0
+1
+ok000000000240
+100 100 100
+50 50 200
+150 150 300
+1 1 0
+1
+ok000000000241
+100 100 100
+50 50 500
+100 100 400
+1 1 0
+1
+ok000000000242
+100 100 100
+50 100 0
+200 200 200
+1 1 0
+1
+ok000000000243
+100 100 100
+50 100 50
+200 200 200
+1 1 0
+1
+ok000000000244
+100 100 100
+50 100 100
+200 200 200
+1 1 0
+1
+ok000000000245
+100 100 100
+50 100 200
+150 150 300
+1 1 0
+1
+ok000000000246
+100 100 100
+50 100 500
+100 100 400
+1 1 0
+1
+ok000000000247
+100 100 100
+50 200 0
+150 300 150
+1 1 0
+1
+ok000000000250
+100 100 100
+50 200 50
+150 300 150
+1 1 0
+1
+ok000000000251
+100 100 100
+50 200 100
+150 300 150
+1 1 0
+1
+ok000000000252
+100 100 100
+50 200 200
+120 240 240
+1 1 0
+1
+ok000000000253
+100 100 100
+50 200 500
+100 143 357
+1 1 0
+1
+ok000000000254
+100 100 100
+50 500 0
+100 400 100
+1 1 0
+1
+ok000000000255
+100 100 100
+50 500 50
+100 400 100
+1 1 0
+1
+ok000000000256
+100 100 100
+50 500 100
+100 400 100
+1 1 0
+1
+ok000000000257
+100 100 100
+50 500 200
+100 357 143
+1 1 0
+1
+ok000000000260
+100 100 100
+50 500 500
+100 250 250
+1 1 0
+1
+ok000000000261
+100 100 100
+100 0 0
+300 0 300
+1 1 0
+1
+ok000000000262
+100 100 100
+100 0 50
+300 0 300
+1 1 0
+1
+ok000000000263
+100 100 100
+100 0 100
+300 0 300
+1 1 0
+1
+ok000000000264
+100 100 100
+100 0 200
+200 0 400
+1 1 0
+1
+ok000000000265
+100 100 100
+100 0 500
+100 0 500
+1 1 0
+1
+ok000000000266
+100 100 100
+100 50 0
+200 200 200
+1 1 0
+1
+ok000000000267
+100 100 100
+100 50 50
+200 200 200
+1 1 0
+1
+ok000000000270
+100 100 100
+100 50 100
+200 200 200
+1 1 0
+1
+ok000000000271
+100 100 100
+100 50 200
+150 150 300
+1 1 0
+1
+ok000000000272
+100 100 100
+100 50 500
+100 100 400
+1 1 0
+1
+ok000000000273
+100 100 100
+100 100 0
+200 200 200
+1 1 0
+1
+ok000000000274
+100 100 100
+100 100 50
+200 200 200
+1 1 0
+1
+ok000000000275
+100 100 100
+100 100 100
+200 200 200
+1 1 0
+1
+ok000000000276
+100 100 100
+100 100 200
+150 150 300
+1 1 0
+1
+ok000000000277
+100 100 100
+100 100 500
+100 100 400
+1 1 0
+1
+ok000000000300
+100 100 100
+100 200 0
+150 300 150
+1 1 0
+1
+ok000000000301
+100 100 100
+100 200 50
+150 300 150
+1 1 0
+1
+ok000000000302
+100 100 100
+100 200 100
+150 300 150
+1 1 0
+1
+ok000000000303
+100 100 100
+100 200 200
+120 240 240
+1 1 0
+1
+ok000000000304
+100 100 100
+100 200 500
+100 143 357
+1 1 0
+1
+ok000000000305
+100 100 100
+100 500 0
+100 400 100
+1 1 0
+1
+ok000000000306
+100 100 100
+100 500 50
+100 400 100
+1 1 0
+1
+ok000000000307
+100 100 100
+100 500 100
+100 400 100
+1 1 0
+1
+ok000000000310
+100 100 100
+100 500 200
+100 357 143
+1 1 0
+1
+ok000000000311
+100 100 100
+100 500 500
+100 250 250
+1 1 0
+1
+ok000000000312
+100 100 100
+200 0 0
+400 0 200
+1 1 0
+1
+ok000000000313
+100 100 100
+200 0 50
+400 0 200
+1 1 0
+1
+ok000000000314
+100 100 100
+200 0 100
+400 0 200
+1 1 0
+1
+ok000000000315
+100 100 100
+200 0 200
+300 0 300
+1 1 0
+1
+ok000000000316
+100 100 100
+200 0 500
+171 0 429
+1 1 0
+1
+ok000000000317
+100 100 100
+200 50 0
+300 150 150
+1 1 0
+1
+ok000000000320
+100 100 100
+200 50 50
+300 150 150
+1 1 0
+1
+ok000000000321
+100 100 100
+200 50 100
+300 150 150
+1 1 0
+1
+ok000000000322
+100 100 100
+200 50 200
+240 120 240
+1 1 0
+1
+ok000000000323
+100 100 100
+200 50 500
+143 100 357
+1 1 0
+1
+ok000000000324
+100 100 100
+200 100 0
+300 150 150
+1 1 0
+1
+ok000000000325
+100 100 100
+200 100 50
+300 150 150
+1 1 0
+1
+ok000000000326
+100 100 100
+200 100 100
+300 150 150
+1 1 0
+1
+ok000000000327
+100 100 100
+200 100 200
+240 120 240
+1 1 0
+1
+ok000000000330
+100 100 100
+200 100 500
+143 100 357
+1 1 0
+1
+ok000000000331
+100 100 100
+200 200 0
+240 240 120
+1 1 0
+1
+ok000000000332
+100 100 100
+200 200 50
+240 240 120
+1 1 0
+1
+ok000000000333
+100 100 100
+200 200 100
+240 240 120
+1 1 0
+1
+ok000000000334
+100 100 100
+200 200 200
+200 200 200
+1 1 0
+1
+ok000000000335
+100 100 100
+200 200 500
+133 134 333
+1 1 0
+1
+ok000000000336
+100 100 100
+200 500 0
+143 357 100
+1 1 0
+1
+ok000000000337
+100 100 100
+200 500 50
+143 357 100
+1 1 0
+1
+ok000000000340
+100 100 100
+200 500 100
+143 357 100
+1 1 0
+1
+ok000000000341
+100 100 100
+200 500 200
+133 334 133
+1 1 0
+1
+ok000000000342
+100 100 100
+200 500 500
+100 250 250
+1 1 0
+1
+ok000000000343
+100 100 100
+500 0 0
+500 0 100
+1 1 0
+1
+ok000000000344
+100 100 100
+500 0 50
+500 0 100
+1 1 0
+1
+ok000000000345
+100 100 100
+500 0 100
+500 0 100
+1 1 0
+1
+ok000000000346
+100 100 100
+500 0 200
+429 0 171
+1 1 0
+1
+ok000000000347
+100 100 100
+500 0 500
+300 0 300
+1 1 0
+1
+ok000000000350
+100 100 100
+500 50 0
+400 100 100
+1 1 0
+1
+ok000000000351
+100 100 100
+500 50 50
+400 100 100
+1 1 0
+1
+ok000000000352
+100 100 100
+500 50 100
+400 100 100
+1 1 0
+1
+ok000000000353
+100 100 100
+500 50 200
+357 100 143
+1 1 0
+1
+ok000000000354
+100 100 100
+500 50 500
+250 100 250
+1 1 0
+1
+ok000000000355
+100 100 100
+500 100 0
+400 100 100
+1 1 0
+1
+ok000000000356
+100 100 100
+500 100 50
+400 100 100
+1 1 0
+1
+ok000000000357
+100 100 100
+500 100 100
+400 100 100
+1 1 0
+1
+ok000000000360
+100 100 100
+500 100 200
+357 100 143
+1 1 0
+1
+ok000000000361
+100 100 100
+500 100 500
+250 100 250
+1 1 0
+1
+ok000000000363
+100 100 100
+500 200 0
+357 143 100
+1 1 0
+1
+ok000000000364
+100 100 100
+500 200 50
+357 143 100
+1 1 0
+1
+ok000000000365
+100 100 100
+500 200 100
+357 143 100
+1 1 0
+1
+ok000000000366
+100 100 100
+500 200 200
+333 134 133
+1 1 0
+1
+ok000000000367
+100 100 100
+500 200 500
+250 100 250
+1 1 0
+1
+ok000000000370
+100 100 100
+500 500 0
+250 250 100
+1 1 0
+1
+ok000000000371
+100 100 100
+500 500 50
+250 250 100
+1 1 0
+1
+ok000000000372
+100 100 100
+500 500 100
+250 250 100
+1 1 0
+1
+ok000000000373
+100 100 100
+500 500 200
+250 250 100
+1 1 0
+1
+ok000000000374
+100 100 100
+500 500 500
+200 200 200
+1 1 0
+1
+ok000000000375
+100 100 100
+0 0 0
+0 600 0
+1 0 1
+1
+ok000000000376
+100 100 100
+0 0 50
+0 300 300
+1 0 1
+1
+ok000000000377
+100 100 100
+0 0 100
+0 300 300
+1 0 1
+1
+ok000000000400
+100 100 100
+0 0 200
+0 200 400
+1 0 1
+1
+ok000000000401
+100 100 100
+0 0 500
+0 100 500
+1 0 1
+1
+ok000000000402
+100 100 100
+0 50 0
+0 600 0
+1 0 1
+1
+ok000000000403
+100 100 100
+0 50 50
+0 300 300
+1 0 1
+1
+ok000000000404
+100 100 100
+0 50 100
+0 300 300
+1 0 1
+1
+ok000000000405
+100 100 100
+0 50 200
+0 200 400
+1 0 1
+1
+ok000000000406
+100 100 100
+0 50 500
+0 100 500
+1 0 1
+1
+ok000000000407
+100 100 100
+0 100 0
+0 600 0
+1 0 1
+1
+ok000000000410
+100 100 100
+0 100 50
+0 300 300
+1 0 1
+1
+ok000000000411
+100 100 100
+0 100 100
+0 300 300
+1 0 1
+1
+ok000000000412
+100 100 100
+0 100 200
+0 200 400
+1 0 1
+1
+ok000000000413
+100 100 100
+0 100 500
+0 100 500
+1 0 1
+1
+ok000000000414
+100 100 100
+0 200 0
+0 600 0
+1 0 1
+1
+ok000000000415
+100 100 100
+0 200 50
+0 400 200
+1 0 1
+1
+ok000000000416
+100 100 100
+0 200 100
+0 400 200
+1 0 1
+1
+ok000000000417
+100 100 100
+0 200 200
+0 300 300
+1 0 1
+1
+ok000000000420
+100 100 100
+0 200 500
+0 171 429
+1 0 1
+1
+ok000000000421
+100 100 100
+0 500 0
+0 600 0
+1 0 1
+1
+ok000000000422
+100 100 100
+0 500 50
+0 500 100
+1 0 1
+1
+ok000000000423
+100 100 100
+0 500 100
+0 500 100
+1 0 1
+1
+ok000000000424
+100 100 100
+0 500 200
+0 429 171
+1 0 1
+1
+ok000000000425
+100 100 100
+0 500 500
+0 300 300
+1 0 1
+1
+ok000000000426
+100 100 100
+50 0 0
+300 300 0
+1 0 1
+1
+ok000000000427
+100 100 100
+50 0 50
+200 200 200
+1 0 1
+1
+ok000000000430
+100 100 100
+50 0 100
+200 200 200
+1 0 1
+1
+ok000000000431
+100 100 100
+50 0 200
+150 150 300
+1 0 1
+1
+ok000000000432
+100 100 100
+50 0 500
+100 100 400
+1 0 1
+1
+ok000000000433
+100 100 100
+50 50 0
+300 300 0
+1 0 1
+1
+ok000000000434
+100 100 100
+50 50 50
+200 200 200
+1 0 1
+1
+ok000000000435
+100 100 100
+50 50 100
+200 200 200
+1 0 1
+1
+ok000000000436
+100 100 100
+50 50 200
+150 150 300
+1 0 1
+1
+ok000000000437
+100 100 100
+50 50 500
+100 100 400
+1 0 1
+1
+ok000000000440
+100 100 100
+50 100 0
+300 300 0
+1 0 1
+1
+ok000000000441
+100 100 100
+50 100 50
+200 200 200
+1 0 1
+1
+ok000000000442
+100 100 100
+50 100 100
+200 200 200
+1 0 1
+1
+ok000000000443
+100 100 100
+50 100 200
+150 150 300
+1 0 1
+1
+ok000000000444
+100 100 100
+50 100 500
+100 100 400
+1 0 1
+1
+ok000000000445
+100 100 100
+50 200 0
+200 400 0
+1 0 1
+1
+ok000000000446
+100 100 100
+50 200 50
+150 300 150
+1 0 1
+1
+ok000000000447
+100 100 100
+50 200 100
+150 300 150
+1 0 1
+1
+ok000000000450
+100 100 100
+50 200 200
+120 240 240
+1 0 1
+1
+ok000000000451
+100 100 100
+50 200 500
+100 143 357
+1 0 1
+1
+ok000000000452
+100 100 100
+50 500 0
+100 500 0
+1 0 1
+1
+ok000000000453
+100 100 100
+50 500 50
+100 400 100
+1 0 1
+1
+ok000000000454
+100 100 100
+50 500 100
+100 400 100
+1 0 1
+1
+ok000000000455
+100 100 100
+50 500 200
+100 357 143
+1 0 1
+1
+ok000000000456
+100 100 100
+50 500 500
+100 250 250
+1 0 1
+1
+ok000000000457
+100 100 100
+100 0 0
+300 300 0
+1 0 1
+1
+ok000000000460
+100 100 100
+100 0 50
+200 200 200
+1 0 1
+1
+ok000000000461
+100 100 100
+100 0 100
+200 200 200
+1 0 1
+1
+ok000000000462
+100 100 100
+100 0 200
+150 150 300
+1 0 1
+1
+ok000000000463
+100 100 100
+100 0 500
+100 100 400
+1 0 1
+1
+ok000000000464
+100 100 100
+100 50 0
+300 300 0
+1 0 1
+1
+ok000000000465
+100 100 100
+100 50 50
+200 200 200
+1 0 1
+1
+ok000000000466
+100 100 100
+100 50 100
+200 200 200
+1 0 1
+1
+ok000000000467
+100 100 100
+100 50 200
+150 150 300
+1 0 1
+1
+ok000000000470
+100 100 100
+100 50 500
+100 100 400
+1 0 1
+1
+ok000000000471
+100 100 100
+100 100 0
+300 300 0
+1 0 1
+1
+ok000000000472
+100 100 100
+100 100 50
+200 200 200
+1 0 1
+1
+ok000000000473
+100 100 100
+100 100 100
+200 200 200
+1 0 1
+1
+ok000000000474
+100 100 100
+100 100 200
+150 150 300
+1 0 1
+1
+ok000000000475
+100 100 100
+100 100 500
+100 100 400
+1 0 1
+1
+ok000000000476
+100 100 100
+100 200 0
+200 400 0
+1 0 1
+1
+ok000000000477
+100 100 100
+100 200 50
+150 300 150
+1 0 1
+1
+ok000000000500
+100 100 100
+100 200 100
+150 300 150
+1 0 1
+1
+ok000000000501
+100 100 100
+100 200 200
+120 240 240
+1 0 1
+1
+ok000000000502
+100 100 100
+100 200 500
+100 143 357
+1 0 1
+1
+ok000000000503
+100 100 100
+100 500 0
+100 500 0
+1 0 1
+1
+ok000000000504
+100 100 100
+100 500 50
+100 400 100
+1 0 1
+1
+ok000000000505
+100 100 100
+100 500 100
+100 400 100
+1 0 1
+1
+ok000000000506
+100 100 100
+100 500 200
+100 357 143
+1 0 1
+1
+ok000000000507
+100 100 100
+100 500 500
+100 250 250
+1 0 1
+1
+ok000000000510
+100 100 100
+200 0 0
+400 200 0
+1 0 1
+1
+ok000000000511
+100 100 100
+200 0 50
+300 150 150
+1 0 1
+1
+ok000000000512
+100 100 100
+200 0 100
+300 150 150
+1 0 1
+1
+ok000000000513
+100 100 100
+200 0 200
+240 120 240
+1 0 1
+1
+ok000000000514
+100 100 100
+200 0 500
+143 100 357
+1 0 1
+1
+ok000000000515
+100 100 100
+200 50 0
+400 200 0
+1 0 1
+1
+ok000000000516
+100 100 100
+200 50 50
+300 150 150
+1 0 1
+1
+ok000000000517
+100 100 100
+200 50 100
+300 150 150
+1 0 1
+1
+ok000000000520
+100 100 100
+200 50 200
+240 120 240
+1 0 1
+1
+ok000000000521
+100 100 100
+200 50 500
+143 100 357
+1 0 1
+1
+ok000000000522
+100 100 100
+200 100 0
+400 200 0
+1 0 1
+1
+ok000000000523
+100 100 100
+200 100 50
+300 150 150
+1 0 1
+1
+ok000000000524
+100 100 100
+200 100 100
+300 150 150
+1 0 1
+1
+ok000000000525
+100 100 100
+200 100 200
+240 120 240
+1 0 1
+1
+ok000000000526
+100 100 100
+200 100 500
+143 100 357
+1 0 1
+1
+ok000000000527
+100 100 100
+200 200 0
+300 300 0
+1 0 1
+1
+ok000000000530
+100 100 100
+200 200 50
+240 240 120
+1 0 1
+1
+ok000000000531
+100 100 100
+200 200 100
+240 240 120
+1 0 1
+1
+ok000000000532
+100 100 100
+200 200 200
+200 200 200
+1 0 1
+1
+ok000000000533
+100 100 100
+200 200 500
+133 134 333
+1 0 1
+1
+ok000000000534
+100 100 100
+200 500 0
+171 429 0
+1 0 1
+1
+ok000000000535
+100 100 100
+200 500 50
+143 357 100
+1 0 1
+1
+ok000000000536
+100 100 100
+200 500 100
+143 357 100
+1 0 1
+1
+ok000000000537
+100 100 100
+200 500 200
+133 334 133
+1 0 1
+1
+ok000000000540
+100 100 100
+200 500 500
+100 250 250
+1 0 1
+1
+ok000000000541
+100 100 100
+500 0 0
+500 100 0
+1 0 1
+1
+ok000000000542
+100 100 100
+500 0 50
+400 100 100
+1 0 1
+1
+ok000000000543
+100 100 100
+500 0 100
+400 100 100
+1 0 1
+1
+ok000000000544
+100 100 100
+500 0 200
+357 100 143
+1 0 1
+1
+ok000000000545
+100 100 100
+500 0 500
+250 100 250
+1 0 1
+1
+ok000000000546
+100 100 100
+500 50 0
+500 100 0
+1 0 1
+1
+ok000000000547
+100 100 100
+500 50 50
+400 100 100
+1 0 1
+1
+ok000000000550
+100 100 100
+500 50 100
+400 100 100
+1 0 1
+1
+ok000000000551
+100 100 100
+500 50 200
+357 100 143
+1 0 1
+1
+ok000000000552
+100 100 100
+500 50 500
+250 100 250
+1 0 1
+1
+ok000000000553
+100 100 100
+500 100 0
+500 100 0
+1 0 1
+1
+ok000000000554
+100 100 100
+500 100 50
+400 100 100
+1 0 1
+1
+ok000000000555
+100 100 100
+500 100 100
+400 100 100
+1 0 1
+1
+ok000000000556
+100 100 100
+500 100 200
+357 100 143
+1 0 1
+1
+ok000000000557
+100 100 100
+500 100 500
+250 100 250
+1 0 1
+1
+ok000000000561
+100 100 100
+500 200 0
+429 171 0
+1 0 1
+1
+ok000000000562
+100 100 100
+500 200 50
+357 143 100
+1 0 1
+1
+ok000000000563
+100 100 100
+500 200 100
+357 143 100
+1 0 1
+1
+ok000000000564
+100 100 100
+500 200 200
+333 134 133
+1 0 1
+1
+ok000000000565
+100 100 100
+500 200 500
+250 100 250
+1 0 1
+1
+ok000000000566
+100 100 100
+500 500 0
+300 300 0
+1 0 1
+1
+ok000000000567
+100 100 100
+500 500 50
+250 250 100
+1 0 1
+1
+ok000000000570
+100 100 100
+500 500 100
+250 250 100
+1 0 1
+1
+ok000000000571
+100 100 100
+500 500 200
+250 250 100
+1 0 1
+1
+ok000000000572
+100 100 100
+500 500 500
+200 200 200
+1 0 1
+1
diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
new file mode 100644
index 0000000000..836286e8ae
--- /dev/null
+++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
@@ -0,0 +1,777 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qsplitter.h>
+#include <qstyle.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qlayout.h>
+#include <qabstractscrollarea.h>
+#include <qgraphicsview.h>
+#include <qmdiarea.h>
+#include <qscrollarea.h>
+#include <qtextedit.h>
+#include <qtreeview.h>
+#include <qlabel.h>
+#include <qdebug.h> // for file error messages
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+QT_FORWARD_DECLARE_CLASS(QSplitter)
+QT_FORWARD_DECLARE_CLASS(QWidget)
+class tst_QSplitter : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSplitter();
+ virtual ~tst_QSplitter();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+private slots:
+ void getSetCheck();
+ void setSizes();
+ void setSizes_data();
+ void saveAndRestoreState();
+ void saveAndRestoreState_data();
+ void saveState_data();
+ void addWidget();
+ void insertWidget();
+ void setStretchFactor_data();
+ void setStretchFactor();
+ void testShowHide_data();
+ void testShowHide();
+ void testRemoval();
+ void rubberBandNotInSplitter();
+ void saveAndRestoreStateOfNotYetShownSplitter();
+
+ // task-specific tests below me:
+ void task187373_addAbstractScrollAreas();
+ void task187373_addAbstractScrollAreas_data();
+ void task169702_sizes();
+ void taskQTBUG_4101_ensureOneNonCollapsedWidget_data();
+ void taskQTBUG_4101_ensureOneNonCollapsedWidget();
+
+private:
+ void removeThirdWidget();
+ void addThirdWidget();
+ QSplitter *splitter;
+ QWidget *w1;
+ QWidget *w2;
+ QWidget *w3;
+};
+
+// Testing get/set functions
+void tst_QSplitter::getSetCheck()
+{
+ QSplitter obj1;
+ // bool QSplitter::opaqueResize()
+ // void QSplitter::setOpaqueResize(bool)
+ obj1.setOpaqueResize(false);
+ QCOMPARE(false, obj1.opaqueResize());
+ obj1.setOpaqueResize(true);
+ QCOMPARE(true, obj1.opaqueResize());
+}
+
+tst_QSplitter::tst_QSplitter()
+ : w1(0), w2(0), w3(0)
+{
+}
+
+tst_QSplitter::~tst_QSplitter()
+{
+}
+
+void tst_QSplitter::initTestCase()
+{
+ splitter = new QSplitter(Qt::Horizontal);
+ w1 = new QWidget;
+ w2 = new QWidget;
+ splitter->addWidget(w1);
+ splitter->addWidget(w2);
+}
+
+void tst_QSplitter::init()
+{
+ removeThirdWidget();
+ w1->show();
+ w2->show();
+ w1->setMinimumSize(0, 0);
+ w2->setMinimumSize(0, 0);
+ splitter->setSizes(QList<int>() << 200 << 200);
+ qApp->sendPostedEvents();
+}
+
+void tst_QSplitter::removeThirdWidget()
+{
+ delete w3;
+ w3 = 0;
+ int handleWidth = splitter->style()->pixelMetric(QStyle::PM_SplitterWidth);
+ splitter->setFixedSize(400 + handleWidth, 400);
+}
+
+void tst_QSplitter::addThirdWidget()
+{
+ if (!w3) {
+ w3 = new QWidget;
+ splitter->addWidget(w3);
+ int handleWidth = splitter->style()->pixelMetric(QStyle::PM_SplitterWidth);
+ splitter->setFixedSize(600 + 2 * handleWidth, 400);
+ }
+}
+
+void tst_QSplitter::cleanupTestCase()
+{
+}
+
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+void tst_QSplitter::setSizes()
+{
+ QFETCH(IntList, minimumSizes);
+ QFETCH(IntList, splitterSizes);
+ QFETCH(IntList, collapsibleStates);
+ QFETCH(bool, childrenCollapse);
+
+ QCOMPARE(minimumSizes.size(), splitterSizes.size());
+ if (minimumSizes.size() > 2)
+ addThirdWidget();
+ for (int i = 0; i < minimumSizes.size(); ++i) {
+ QWidget *w = splitter->widget(i);
+ w->setMinimumWidth(minimumSizes.at(i));
+ splitter->setCollapsible(splitter->indexOf(w), collapsibleStates.at(i));
+ }
+ splitter->setChildrenCollapsible(childrenCollapse);
+ splitter->setSizes(splitterSizes);
+ QTEST(splitter->sizes(), "expectedSizes");
+}
+
+void tst_QSplitter::setSizes_data()
+{
+ QTest::addColumn<IntList>("minimumSizes");
+ QTest::addColumn<IntList>("splitterSizes");
+ QTest::addColumn<IntList>("expectedSizes");
+ QTest::addColumn<IntList>("collapsibleStates");
+ QTest::addColumn<bool>("childrenCollapse");
+
+ QFile file(SRCDIR "setSizes3.dat");
+ if (!file.open(QIODevice::ReadOnly)) {
+ qDebug() << "Can't open file, reason:" << file.errorString();
+ return;
+ }
+ QTextStream ts(&file);
+ ts.setIntegerBase(10);
+
+ QString dataName;
+ IntList minimumSizes;
+ IntList splitterSizes;
+ IntList expectedSizes;
+ IntList collapsibleStates;
+ int childrenCollapse;
+ while (!ts.atEnd()) {
+ int i1, i2, i3;
+ minimumSizes.clear();
+ splitterSizes.clear();
+ expectedSizes.clear();
+ collapsibleStates.clear();
+ ts >> dataName;
+ ts >> i1 >> i2 >> i3;
+ minimumSizes << i1 << i2 << i3;
+ ts >> i1 >> i2 >> i3;
+ splitterSizes << i1 << i2 << i3;
+ ts >> i1 >> i2 >> i3;
+ expectedSizes << i1 << i2 << i3;
+ ts >> i1 >> i2 >> i3;
+ collapsibleStates << i1 << i2 << i3;
+ ts >> childrenCollapse;
+ QTest::newRow(dataName.toLocal8Bit()) << minimumSizes << splitterSizes << expectedSizes << collapsibleStates << bool(childrenCollapse);
+ ts.skipWhiteSpace();
+ }
+}
+
+void tst_QSplitter::saveAndRestoreState_data()
+{
+ saveState_data();
+}
+
+void tst_QSplitter::saveAndRestoreState()
+{
+ QFETCH(IntList, initialSizes);
+ splitter->setSizes(initialSizes);
+ QApplication::instance()->sendPostedEvents();
+
+ QSplitter *splitter2 = new QSplitter(splitter->orientation() == Qt::Horizontal ?
+ Qt::Vertical : Qt::Horizontal);
+ for (int i = 0; i < splitter->count(); ++i) {
+ splitter2->addWidget(new QWidget());
+ }
+ splitter2->resize(splitter->size());
+ splitter2->setChildrenCollapsible(!splitter->childrenCollapsible());
+ splitter2->setOpaqueResize(!splitter->opaqueResize());
+ splitter2->setHandleWidth(splitter->handleWidth()+3);
+
+ QByteArray ba = splitter->saveState();
+ QVERIFY(splitter2->restoreState(ba));
+
+ QCOMPARE(splitter2->orientation(), splitter->orientation());
+ QCOMPARE(splitter2->handleWidth(), splitter->handleWidth());
+ QCOMPARE(splitter2->opaqueResize(), splitter->opaqueResize());
+ QCOMPARE(splitter2->childrenCollapsible(), splitter->childrenCollapsible());
+
+ QList<int> l1 = splitter->sizes();
+ QList<int> l2 = splitter2->sizes();
+ QCOMPARE(l1.size(), l2.size());
+ for (int i = 0; i < splitter->sizes().size(); ++i) {
+ QCOMPARE(l2.at(i), l1.at(i));
+ }
+
+ // destroy version and magic number
+ for (int i = 0; i < ba.size(); ++i)
+ ba[i] = ~ba.at(i);
+ QVERIFY(!splitter2->restoreState(ba));
+
+ delete splitter2;
+}
+
+void tst_QSplitter::saveAndRestoreStateOfNotYetShownSplitter()
+{
+ QSplitter *spl = new QSplitter;
+ QLabel *l1 = new QLabel;
+ QLabel *l2 = new QLabel;
+ spl->addWidget(l1);
+ spl->addWidget(l2);
+
+ QByteArray ba = spl->saveState();
+ spl->restoreState(ba);
+ spl->show();
+ QTest::qWait(500);
+
+ QCOMPARE(l1->geometry().isValid(), true);
+ QCOMPARE(l2->geometry().isValid(), true);
+
+ delete spl;
+}
+
+void tst_QSplitter::saveState_data()
+{
+ QTest::addColumn<IntList>("initialSizes");
+ QTest::addColumn<bool>("hideWidget1");
+ QTest::addColumn<bool>("hideWidget2");
+ QTest::addColumn<QByteArray>("finalBa");
+
+ QTest::newRow("ok0") << (IntList() << 200 << 200) << bool(false) << bool(false) << QByteArray("[200,200]");
+ QTest::newRow("ok1") << (IntList() << 300 << 100) << bool(false) << bool(false) << QByteArray("[300,100]");
+ QTest::newRow("ok2") << (IntList() << 100 << 300) << bool(false) << bool(false) << QByteArray("[100,300]");
+ QTest::newRow("ok3") << (IntList() << 200 << 200) << bool(false) << bool(true) << QByteArray("[200,H]");
+ QTest::newRow("ok4") << (IntList() << 200 << 200) << bool(true) << bool(false) << QByteArray("[H,200]");
+ QTest::newRow("ok5") << (IntList() << 200 << 200) << bool(false) << bool(false) << QByteArray("[200,200]");
+ QTest::newRow("ok6") << (IntList() << 200 << 200) << bool(false) << bool(false) << QByteArray("[200,200]");
+ QTest::newRow("ok7") << (IntList() << 200 << 200) << bool(false) << bool(false) << QByteArray("[200,200]");
+ QTest::newRow("ok8") << (IntList() << 200 << 200) << bool(true) << bool(true) << QByteArray("[H,H]");
+}
+
+void tst_QSplitter::addWidget()
+{
+ QSplitter split;
+
+ // Simple case
+ QWidget *widget1 = new QWidget;
+ QWidget *widget2 = new QWidget;
+ split.addWidget(widget1);
+ split.addWidget(widget2);
+ QCOMPARE(split.count(), 2);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.indexOf(widget2), 1);
+ QCOMPARE(split.widget(0), widget1);
+ QCOMPARE(split.widget(1), widget2);
+
+
+ // Implicit Add
+ QWidget *widget3 = new QWidget(&split);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget3), 2);
+ QCOMPARE(split.widget(2), widget3);
+
+ // Try and add it again
+ split.addWidget(widget3);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget3), 2);
+ QCOMPARE(split.widget(2), widget3);
+
+ // Add a widget that is already in the splitter
+ split.addWidget(widget1);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget1), 2);
+ QCOMPARE(split.widget(0), widget2);
+ QCOMPARE(split.widget(1), widget3);
+ QCOMPARE(split.widget(2), widget1);
+
+ // Change a widget's parent
+ widget2->setParent(0);
+ QCOMPARE(split.count(), 2);
+ QCOMPARE(split.indexOf(widget2), -1);
+
+
+ // Add the widget in again.
+ split.addWidget(widget2);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget2), 2);
+ QCOMPARE(split.widget(0), widget3);
+ QCOMPARE(split.widget(1), widget1);
+ QCOMPARE(split.widget(2), widget2);
+
+ // Delete a widget
+ delete widget1;
+ QCOMPARE(split.count(), 2);
+ QCOMPARE(split.indexOf(widget1), -1); // Nasty
+ QCOMPARE(split.widget(0), widget3);
+ QCOMPARE(split.widget(1), widget2);
+
+ delete widget2;
+}
+
+void tst_QSplitter::insertWidget()
+{
+ QSplitter split;
+ QWidget *widget1 = new QWidget;
+ QWidget *widget2 = new QWidget;
+ QWidget *widget3 = new QWidget;
+
+ split.insertWidget(0, widget1);
+ QCOMPARE(split.count(), 1);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.widget(0), widget1);
+
+ split.insertWidget(0, widget2);
+ QCOMPARE(split.count(), 2);
+ QCOMPARE(split.indexOf(widget1), 1);
+ QCOMPARE(split.indexOf(widget2), 0);
+ QCOMPARE(split.widget(0), widget2);
+ QCOMPARE(split.widget(1), widget1);
+
+ split.insertWidget(1, widget3);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget1), 2);
+ QCOMPARE(split.indexOf(widget2), 0);
+ QCOMPARE(split.indexOf(widget3), 1);
+ QCOMPARE(split.widget(0), widget2);
+ QCOMPARE(split.widget(1), widget3);
+ QCOMPARE(split.widget(2), widget1);
+
+ delete widget3;
+ QCOMPARE(split.count(), 2);
+ QCOMPARE(split.indexOf(widget1), 1);
+ QCOMPARE(split.indexOf(widget2), 0);
+ QCOMPARE(split.widget(0), widget2);
+ QCOMPARE(split.widget(1), widget1);
+
+ widget3 = new QWidget;
+ split.insertWidget(split.count() + 1, widget3);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget1), 1);
+ QCOMPARE(split.indexOf(widget2), 0);
+ QCOMPARE(split.indexOf(widget3), 2);
+ QCOMPARE(split.widget(0), widget2);
+ QCOMPARE(split.widget(1), widget1);
+ QCOMPARE(split.widget(2), widget3);
+
+
+ // Try it again,
+ split.insertWidget(split.count() + 1, widget3);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget1), 1);
+ QCOMPARE(split.indexOf(widget2), 0);
+ QCOMPARE(split.indexOf(widget3), 2);
+ QCOMPARE(split.widget(0), widget2);
+ QCOMPARE(split.widget(1), widget1);
+ QCOMPARE(split.widget(2), widget3);
+
+ // Try to move widget2 to a bad place
+ split.insertWidget(-1, widget2);
+ QCOMPARE(split.count(), 3);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.indexOf(widget2), 2);
+ QCOMPARE(split.indexOf(widget3), 1);
+ QCOMPARE(split.widget(0), widget1);
+ QCOMPARE(split.widget(1), widget3);
+ QCOMPARE(split.widget(2), widget2);
+
+ QWidget *widget4 = new QWidget(&split);
+ QCOMPARE(split.count(), 4);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.indexOf(widget2), 2);
+ QCOMPARE(split.indexOf(widget3), 1);
+ QCOMPARE(split.indexOf(widget4), 3);
+ QCOMPARE(split.widget(0), widget1);
+ QCOMPARE(split.widget(1), widget3);
+ QCOMPARE(split.widget(2), widget2);
+ QCOMPARE(split.widget(3), widget4);
+
+ QWidget *widget5 = new QWidget(&split);
+ QCOMPARE(split.count(), 5);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.indexOf(widget2), 2);
+ QCOMPARE(split.indexOf(widget3), 1);
+ QCOMPARE(split.indexOf(widget4), 3);
+ QCOMPARE(split.indexOf(widget5), 4);
+ QCOMPARE(split.widget(0), widget1);
+ QCOMPARE(split.widget(1), widget3);
+ QCOMPARE(split.widget(2), widget2);
+ QCOMPARE(split.widget(3), widget4);
+ QCOMPARE(split.widget(4), widget5);
+
+ split.insertWidget(2, widget4);
+ QCOMPARE(split.count(), 5);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.indexOf(widget2), 3);
+ QCOMPARE(split.indexOf(widget3), 1);
+ QCOMPARE(split.indexOf(widget4), 2);
+ QCOMPARE(split.indexOf(widget5), 4);
+ QCOMPARE(split.widget(0), widget1);
+ QCOMPARE(split.widget(1), widget3);
+ QCOMPARE(split.widget(2), widget4);
+ QCOMPARE(split.widget(3), widget2);
+ QCOMPARE(split.widget(4), widget5);
+
+ split.insertWidget(1, widget5);
+ QCOMPARE(split.count(), 5);
+ QCOMPARE(split.indexOf(widget1), 0);
+ QCOMPARE(split.indexOf(widget2), 4);
+ QCOMPARE(split.indexOf(widget3), 2);
+ QCOMPARE(split.indexOf(widget4), 3);
+ QCOMPARE(split.indexOf(widget5), 1);
+ QCOMPARE(split.widget(0), widget1);
+ QCOMPARE(split.widget(1), widget5);
+ QCOMPARE(split.widget(2), widget3);
+ QCOMPARE(split.widget(3), widget4);
+ QCOMPARE(split.widget(4), widget2);
+}
+
+void tst_QSplitter::setStretchFactor_data()
+{
+ QTest::addColumn<int>("orientation");
+ QTest::addColumn<int>("widgetIndex");
+ QTest::addColumn<int>("stretchFactor");
+ QTest::addColumn<int>("expectedHStretch");
+ QTest::addColumn<int>("expectedVStretch");
+
+ QTest::newRow("ok01") << int(Qt::Horizontal) << 1 << 2 << 2 << 2;
+ QTest::newRow("ok02") << int(Qt::Horizontal) << 2 << 0 << 0 << 0;
+ QTest::newRow("ok03") << int(Qt::Horizontal) << 3 << 1 << 1 << 1;
+ QTest::newRow("ok04") << int(Qt::Horizontal) << 0 << 7 << 7 << 7;
+ QTest::newRow("ok05") << int(Qt::Vertical) << 0 << 0 << 0 << 0;
+ QTest::newRow("ok06") << int(Qt::Vertical) << 1 << 1 << 1 << 1;
+ QTest::newRow("ok07") << int(Qt::Vertical) << 2 << 2 << 2 << 2;
+ QTest::newRow("ok08") << int(Qt::Vertical) << 3 << 5 << 5 << 5;
+ QTest::newRow("ok08") << int(Qt::Vertical) << -1 << 5 << 0 << 0;
+}
+
+void tst_QSplitter::setStretchFactor()
+{
+ QFETCH(int, orientation);
+ Qt::Orientation orient = Qt::Orientation(orientation);
+ QSplitter split(orient);
+ QWidget *w = new QWidget;
+ split.addWidget(w);
+ w = new QWidget;
+ split.addWidget(w);
+ w = new QWidget;
+ split.addWidget(w);
+ w = new QWidget;
+ split.addWidget(w);
+
+ QFETCH(int, widgetIndex);
+ QFETCH(int, stretchFactor);
+ w = split.widget(widgetIndex);
+ QSizePolicy sp;
+ if (w) {
+ QCOMPARE(sp.horizontalStretch(), 0);
+ QCOMPARE(sp.verticalStretch(), 0);
+ }
+ split.setStretchFactor(widgetIndex, stretchFactor);
+ if (w)
+ sp = w->sizePolicy();
+ QTEST(sp.horizontalStretch(), "expectedHStretch");
+ QTEST(sp.verticalStretch(), "expectedVStretch");
+}
+
+void tst_QSplitter::testShowHide_data()
+{
+ QTest::addColumn<bool>("hideWidget1");
+ QTest::addColumn<bool>("hideWidget2");
+ QTest::addColumn<QList<int> >("finalValues");
+ QTest::addColumn<bool>("handleVisible");
+
+ QSplitter *split = new QSplitter(Qt::Horizontal);
+ QTest::newRow("hideNone") << false << false << (QList<int>() << 200 << 200) << true;
+ QTest::newRow("hide2") << false << true << (QList<int>() << 400 + split->handleWidth() << 0) << false;
+ QTest::newRow("hide1") << true << false << (QList<int>() << 0 << 400 + split->handleWidth()) << false;
+ QTest::newRow("hideall") << true << true << (QList<int>() << 0 << 0) << false;
+ delete split;
+}
+
+void tst_QSplitter::testShowHide()
+{
+ QFETCH(bool, hideWidget1);
+ QFETCH(bool, hideWidget2);
+
+ QSplitter *split = new QSplitter(Qt::Horizontal);
+
+ QWidget topLevel;
+ QWidget widget(&topLevel);
+ widget.resize(400 + split->handleWidth(), 200);
+ QVBoxLayout *lay=new QVBoxLayout(&widget);
+ lay->setMargin(0);
+ lay->setSpacing(0);
+ split->addWidget(new QWidget);
+ split->addWidget(new QWidget);
+ split->setSizes(QList<int>() << 200 << 200);
+ lay->addWidget(split);
+ widget.setLayout(lay);
+ topLevel.show();
+
+ QTest::qWait(100);
+
+ widget.hide();
+ split->widget(0)->setHidden(hideWidget1);
+ split->widget(1)->setHidden(hideWidget2);
+ widget.show();
+ QTest::qWait(100);
+
+ QTEST(split->sizes(), "finalValues");
+ QTEST(split->handle(1)->isVisible(), "handleVisible");
+}
+
+void tst_QSplitter::testRemoval()
+{
+
+ // This test relies on the internal structure of QSplitter That is, that
+ // there is a handle before every splitter, but sometimes that handle is
+ // hidden. But definiately when something is removed the front handle
+ // should not be visible.
+
+ QSplitter split;
+ split.addWidget(new QWidget);
+ split.addWidget(new QWidget);
+ split.show();
+ QTest::qWait(100);
+
+ QCOMPARE(split.handle(0)->isVisible(), false);
+ QSplitterHandle *handle = split.handle(1);
+ QCOMPARE(handle->isVisible(), true);
+
+ delete split.widget(0);
+ QSplitterHandle *sameHandle = split.handle(0);
+ QCOMPARE(handle, sameHandle);
+ QCOMPARE(sameHandle->isVisible(), false);
+}
+
+class MyFriendlySplitter : public QSplitter
+{
+public:
+ MyFriendlySplitter(QWidget *parent = 0) : QSplitter(parent) {}
+ void setRubberBand(int pos) { QSplitter::setRubberBand(pos); }
+
+ friend class tst_QSplitter;
+};
+
+void tst_QSplitter::rubberBandNotInSplitter()
+{
+ MyFriendlySplitter split;
+ split.addWidget(new QWidget);
+ split.addWidget(new QWidget);
+ split.setOpaqueResize(false);
+ QCOMPARE(split.count(), 2);
+ split.setRubberBand(2);
+ QCOMPARE(split.count(), 2);
+}
+
+void tst_QSplitter::task187373_addAbstractScrollAreas_data()
+{
+ QTest::addColumn<QString>("className");
+ QTest::addColumn<bool>("addInConstructor");
+ QTest::addColumn<bool>("addOutsideConstructor");
+
+ QStringList classNames;
+ classNames << QLatin1String("QGraphicsView");
+ classNames << QLatin1String("QMdiArea");
+ classNames << QLatin1String("QScrollArea");
+ classNames << QLatin1String("QTextEdit");
+ classNames << QLatin1String("QTreeView");
+
+ foreach (QString className, classNames) {
+ QTest::newRow(qPrintable(QString("%1 1").arg(className))) << className << false << true;
+ QTest::newRow(qPrintable(QString("%1 2").arg(className))) << className << true << false;
+ QTest::newRow(qPrintable(QString("%1 3").arg(className))) << className << true << true;
+ }
+}
+
+static QAbstractScrollArea *task187373_createScrollArea(
+ QSplitter *splitter, const QString &className, bool addInConstructor)
+{
+ if (className == QLatin1String("QGraphicsView"))
+ return new QGraphicsView(addInConstructor ? splitter : 0);
+ if (className == QLatin1String("QMdiArea"))
+ return new QMdiArea(addInConstructor ? splitter : 0);
+ if (className == QLatin1String("QScrollArea"))
+ return new QScrollArea(addInConstructor ? splitter : 0);
+ if (className == QLatin1String("QTextEdit"))
+ return new QTextEdit(addInConstructor ? splitter : 0);
+ if (className == QLatin1String("QTreeView"))
+ return new QTreeView(addInConstructor ? splitter : 0);
+ return 0;
+}
+
+void tst_QSplitter::task187373_addAbstractScrollAreas()
+{
+ QFETCH(QString, className);
+ QFETCH(bool, addInConstructor);
+ QFETCH(bool, addOutsideConstructor);
+ QVERIFY(addInConstructor || addOutsideConstructor);
+
+ QSplitter *splitter = new QSplitter;
+ splitter->show();
+ QVERIFY(splitter->isVisible());
+
+ QAbstractScrollArea *w = task187373_createScrollArea(splitter, className, addInConstructor);
+ QVERIFY(w);
+ if (addOutsideConstructor)
+ splitter->addWidget(w);
+
+ QTRY_VERIFY(w->isVisible());
+ QVERIFY(!w->isHidden());
+ QVERIFY(w->viewport()->isVisible());
+ QVERIFY(!w->viewport()->isHidden());
+}
+
+//! A simple QTextEdit which can switch between two different size states
+class MyTextEdit : public QTextEdit
+{
+ public:
+ MyTextEdit(const QString & text, QWidget* parent = NULL)
+ : QTextEdit(text, parent) , m_iFactor(1)
+ {
+ setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+ }
+ virtual QSize minimumSizeHint () const
+ {
+ return QSize(200, 200) * m_iFactor;
+ }
+ virtual QSize sizeHint() const
+ {
+ return QSize(390, 390) * m_iFactor;
+ }
+ int m_iFactor;
+};
+
+void tst_QSplitter::task169702_sizes()
+{
+ QWidget topLevel;
+ // Create two nested (non-collapsible) splitters
+ QSplitter* outerSplitter = new QSplitter(Qt::Vertical, &topLevel);
+ outerSplitter->setChildrenCollapsible(false);
+ QSplitter* splitter = new QSplitter(Qt::Horizontal, outerSplitter);
+ splitter->setChildrenCollapsible(false);
+
+ // populate the outer splitter
+ outerSplitter->addWidget(new QTextEdit("Foo"));
+ outerSplitter->addWidget(splitter);
+ outerSplitter->setStretchFactor(0, 1);
+ outerSplitter->setStretchFactor(1, 0);
+
+ // populate the inner splitter
+ MyTextEdit* testW = new MyTextEdit("TextEdit with size restriction");
+ splitter->addWidget(testW);
+ splitter->addWidget(new QTextEdit("Bar"));
+
+ outerSplitter->setGeometry(100, 100, 500, 500);
+ topLevel.show();
+
+ QTest::qWait(100);
+ testW->m_iFactor++;
+ testW->updateGeometry();
+ QTest::qWait(500);//100 is too fast for Maemo
+
+ //Make sure the minimimSizeHint is respected
+ QCOMPARE(testW->size().height(), testW->minimumSizeHint().height());
+}
+
+void tst_QSplitter::taskQTBUG_4101_ensureOneNonCollapsedWidget_data()
+{
+ QTest::addColumn<bool>("testingHide");
+
+ QTest::newRow("last non collapsed hidden") << true;
+ QTest::newRow("last non collapsed deleted") << false;
+}
+
+void tst_QSplitter::taskQTBUG_4101_ensureOneNonCollapsedWidget()
+{
+ QFETCH(bool, testingHide);
+
+ MyFriendlySplitter s;
+ QLabel *l;
+ for (int i = 0; i < 5; ++i) {
+ l = new QLabel(QString("Label ") + QChar('A' + i));
+ l->setAlignment(Qt::AlignCenter);
+ s.addWidget(l);
+ s.moveSplitter(0, i); // Collapse all the labels except the last one.
+ }
+
+ s.show();
+ if (testingHide)
+ l->hide();
+ else
+ delete l;
+ QTest::qWait(100);
+ QVERIFY(s.sizes().at(0) > 0);
+}
+
+QTEST_MAIN(tst_QSplitter)
+#include "tst_qsplitter.moc"
diff --git a/tests/auto/widgets/widgets/qstackedwidget/.gitignore b/tests/auto/widgets/widgets/qstackedwidget/.gitignore
new file mode 100644
index 0000000000..172554eedb
--- /dev/null
+++ b/tests/auto/widgets/widgets/qstackedwidget/.gitignore
@@ -0,0 +1 @@
+tst_qstackedwidget
diff --git a/tests/auto/widgets/widgets/qstackedwidget/qstackedwidget.pro b/tests/auto/widgets/widgets/qstackedwidget/qstackedwidget.pro
new file mode 100644
index 0000000000..c9436c6a86
--- /dev/null
+++ b/tests/auto/widgets/widgets/qstackedwidget/qstackedwidget.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qstackedwidget.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qstackedwidget.cpp
+
+
diff --git a/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp b/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp
new file mode 100644
index 0000000000..a4e71eca51
--- /dev/null
+++ b/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qstackedwidget.h>
+#include <qpushbutton.h>
+#include <QHBoxLayout>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QStackedWidget : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QStackedWidget();
+ virtual ~tst_QStackedWidget();
+
+private slots:
+ void getSetCheck();
+ void testMinimumSize();
+};
+
+tst_QStackedWidget::tst_QStackedWidget()
+{
+}
+
+tst_QStackedWidget::~tst_QStackedWidget()
+{
+}
+
+// Testing that stackedwidget respect the minimum size of it's contents (task 95319)
+void tst_QStackedWidget::testMinimumSize()
+{
+ QWidget w;
+ QStackedWidget sw(&w);
+ QPushButton button("Text", &sw);
+ sw.addWidget(&button);
+ QHBoxLayout hboxLayout;
+ hboxLayout.addWidget(&sw);
+ w.setLayout(&hboxLayout);
+ w.show();
+ QVERIFY(w.minimumSize() != QSize(0, 0));
+}
+
+// Testing get/set functions
+void tst_QStackedWidget::getSetCheck()
+{
+ QStackedWidget obj1;
+ // int QStackedWidget::currentIndex()
+ // void QStackedWidget::setCurrentIndex(int)
+ obj1.setCurrentIndex(0);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(-1, obj1.currentIndex());
+
+ // QWidget * QStackedWidget::currentWidget()
+ // void QStackedWidget::setCurrentWidget(QWidget *)
+ QWidget *var2 = new QWidget();
+ obj1.addWidget(var2);
+ obj1.setCurrentWidget(var2);
+ QCOMPARE(var2, obj1.currentWidget());
+
+// Disabled, task to fix is 128939.
+#if 0
+ // Layouts assert on any unknown widgets here, 0-pointers included.
+ // This seems wrong behavior, since the setCurrentIndex(int), which
+ // is really a convenience function for setCurrentWidget(QWidget*),
+ // has no problem handling out-of-bounds indices.
+ // ("convenience function" => "just another way of achieving the
+ // same goal")
+ obj1.setCurrentWidget((QWidget *)0);
+ QCOMPARE(obj1.currentWidget(), var2);
+#endif
+ delete var2;
+}
+
+QTEST_MAIN(tst_QStackedWidget)
+#include "tst_qstackedwidget.moc"
diff --git a/tests/auto/widgets/widgets/qstatusbar/.gitignore b/tests/auto/widgets/widgets/qstatusbar/.gitignore
new file mode 100644
index 0000000000..14454b0693
--- /dev/null
+++ b/tests/auto/widgets/widgets/qstatusbar/.gitignore
@@ -0,0 +1 @@
+tst_qstatusbar
diff --git a/tests/auto/widgets/widgets/qstatusbar/qstatusbar.pro b/tests/auto/widgets/widgets/qstatusbar/qstatusbar.pro
new file mode 100644
index 0000000000..51ec0e9cdb
--- /dev/null
+++ b/tests/auto/widgets/widgets/qstatusbar/qstatusbar.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qstatusbar.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp
new file mode 100644
index 0000000000..a4a232951a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp
@@ -0,0 +1,279 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qstatusbar.h>
+#include <QLabel>
+#include <QMainWindow>
+#include <QSizeGrip>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QStatusBar: public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QStatusBar();
+ virtual ~tst_QStatusBar();
+
+
+protected slots:
+ void messageChanged(const QString&);
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void tempMessage();
+ void insertWidget();
+ void insertPermanentWidget();
+ void setSizeGripEnabled();
+ void task194017_hiddenWidget();
+ void QTBUG4334_hiddenOnMaximizedWindow();
+
+private:
+ QStatusBar *testWidget;
+ QString currentMessage;
+};
+
+tst_QStatusBar::tst_QStatusBar()
+{
+}
+
+tst_QStatusBar::~tst_QStatusBar()
+{
+}
+
+void tst_QStatusBar::init()
+{
+ testWidget = new QStatusBar;
+ connect(testWidget, SIGNAL(messageChanged(QString)), this, SLOT(messageChanged(QString)));
+
+ QWidget *item1 = new QWidget(testWidget);
+ testWidget->addWidget(item1);
+}
+
+void tst_QStatusBar::cleanup()
+{
+ delete testWidget;
+}
+
+void tst_QStatusBar::initTestCase()
+{
+}
+
+void tst_QStatusBar::cleanupTestCase()
+{
+}
+
+void tst_QStatusBar::messageChanged(const QString &m)
+{
+ currentMessage = m;
+}
+
+void tst_QStatusBar::tempMessage()
+{
+ QVERIFY(testWidget->currentMessage().isNull());
+ QVERIFY(currentMessage.isNull());
+
+ testWidget->showMessage("Ready", 500);
+ QCOMPARE(testWidget->currentMessage(), QString("Ready"));
+ QCOMPARE(testWidget->currentMessage(), currentMessage);
+
+ QTest::qWait(1000);
+
+ QVERIFY(testWidget->currentMessage().isNull());
+ QVERIFY(currentMessage.isNull());
+
+ testWidget->showMessage("Ready again", 500);
+ QCOMPARE(testWidget->currentMessage(), QString("Ready again"));
+ QCOMPARE(testWidget->currentMessage(), currentMessage);
+
+ testWidget->clearMessage();
+ QVERIFY(testWidget->currentMessage().isNull());
+ QVERIFY(currentMessage.isNull());
+}
+
+void tst_QStatusBar::insertWidget()
+{
+ QStatusBar sb;
+ sb.addPermanentWidget(new QLabel("foo"));
+ QTest::ignoreMessage(QtWarningMsg, "QStatusBar::insertWidget: Index out of range (-1), appending widget");
+ QCOMPARE(sb.insertWidget(-1, new QLabel("foo")), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QStatusBar::insertWidget: Index out of range (2), appending widget");
+ QCOMPARE(sb.insertWidget(2, new QLabel("foo")), 1);
+ QCOMPARE(sb.insertWidget(0, new QLabel("foo")), 0);
+ QCOMPARE(sb.insertWidget(3, new QLabel("foo")), 3);
+}
+
+void tst_QStatusBar::insertPermanentWidget()
+{
+ QStatusBar sb;
+ sb.addWidget(new QLabel("foo"));
+ QTest::ignoreMessage(QtWarningMsg, "QStatusBar::insertPermanentWidget: Index out of range (-1), appending widget");
+ QCOMPARE(sb.insertPermanentWidget(-1, new QLabel("foo")), 1);
+ QTest::ignoreMessage(QtWarningMsg, "QStatusBar::insertPermanentWidget: Index out of range (0), appending widget");
+ QCOMPARE(sb.insertPermanentWidget(0, new QLabel("foo")), 2);
+ QCOMPARE(sb.insertPermanentWidget(2, new QLabel("foo")), 2);
+ QTest::ignoreMessage(QtWarningMsg, "QStatusBar::insertPermanentWidget: Index out of range (5), appending widget");
+ QCOMPARE(sb.insertPermanentWidget(5, new QLabel("foo")), 4);
+ QCOMPARE(sb.insertWidget(1, new QLabel("foo")), 1);
+ QTest::ignoreMessage(QtWarningMsg, "QStatusBar::insertPermanentWidget: Index out of range (1), appending widget");
+ QCOMPARE(sb.insertPermanentWidget(1, new QLabel("foo")), 6);
+}
+
+void tst_QStatusBar::setSizeGripEnabled()
+{
+ QMainWindow mainWindow;
+ QPointer<QStatusBar> statusBar = mainWindow.statusBar();
+ QVERIFY(statusBar);
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ QTRY_VERIFY(statusBar->isVisible());
+ QPointer<QSizeGrip> sizeGrip = qFindChild<QSizeGrip *>(statusBar);
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+
+ statusBar->setSizeGripEnabled(true);
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+
+ statusBar->hide();
+ QVERIFY(!sizeGrip->isVisible());
+ statusBar->show();
+ QVERIFY(sizeGrip->isVisible());
+
+ sizeGrip->setVisible(false);
+ QVERIFY(!sizeGrip->isVisible());
+ statusBar->hide();
+ statusBar->show();
+ QVERIFY(!sizeGrip->isVisible());
+
+ statusBar->setSizeGripEnabled(false);
+ QVERIFY(!sizeGrip);
+
+ qApp->processEvents();
+ mainWindow.showFullScreen();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+ qApp->processEvents();
+
+ mainWindow.setStatusBar(new QStatusBar(&mainWindow));
+ //we now call deleteLater on the previous statusbar
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!statusBar);
+ statusBar = mainWindow.statusBar();
+ QVERIFY(statusBar);
+
+ sizeGrip = qFindChild<QSizeGrip *>(statusBar);
+ QVERIFY(sizeGrip);
+ QVERIFY(!sizeGrip->isVisible());
+
+ statusBar->setSizeGripEnabled(true);
+ QVERIFY(!sizeGrip->isVisible());
+
+ qApp->processEvents();
+ mainWindow.showNormal();
+ qApp->processEvents();
+ QTRY_VERIFY(sizeGrip->isVisible());
+}
+
+void tst_QStatusBar::task194017_hiddenWidget()
+{
+ QStatusBar sb;
+
+ QWidget *label= new QLabel("bar",&sb);
+ sb.addWidget(label);
+ sb.show();
+ QVERIFY(label->isVisible());
+ sb.showMessage("messssage");
+ QVERIFY(!label->isVisible());
+ sb.hide();
+ QVERIFY(!label->isVisible());
+ sb.show();
+ QVERIFY(!label->isVisible());
+ sb.clearMessage();
+ QVERIFY(label->isVisible());
+ label->hide();
+ QVERIFY(!label->isVisible());
+ sb.showMessage("messssage");
+ QVERIFY(!label->isVisible());
+ sb.clearMessage();
+ QVERIFY(!label->isVisible());
+ sb.hide();
+ QVERIFY(!label->isVisible());
+ sb.show();
+ QVERIFY(!label->isVisible());
+}
+
+void tst_QStatusBar::QTBUG4334_hiddenOnMaximizedWindow()
+{
+ QMainWindow main;
+ QStatusBar statusbar;
+ statusbar.setSizeGripEnabled(true);
+ main.setStatusBar(&statusbar);
+ main.showMaximized();
+ QTest::qWaitForWindowShown(&main);
+#ifndef Q_WS_MAC
+ QVERIFY(!statusbar.findChild<QSizeGrip*>()->isVisible());
+#endif
+ main.showNormal();
+ QTest::qWaitForWindowShown(&main);
+ QVERIFY(statusbar.findChild<QSizeGrip*>()->isVisible());
+ main.showFullScreen();
+ QTest::qWaitForWindowShown(&main);
+ QVERIFY(!statusbar.findChild<QSizeGrip*>()->isVisible());
+}
+
+QTEST_MAIN(tst_QStatusBar)
+#include "tst_qstatusbar.moc"
diff --git a/tests/auto/widgets/widgets/qtabbar/.gitignore b/tests/auto/widgets/widgets/qtabbar/.gitignore
new file mode 100644
index 0000000000..3f8338e1fe
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtabbar/.gitignore
@@ -0,0 +1 @@
+tst_qtabbar
diff --git a/tests/auto/widgets/widgets/qtabbar/qtabbar.pro b/tests/auto/widgets/widgets/qtabbar/qtabbar.pro
new file mode 100644
index 0000000000..befe5704ba
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtabbar/qtabbar.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtabbar.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
new file mode 100644
index 0000000000..a1a8f3b0aa
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
@@ -0,0 +1,655 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qtabbar.h>
+
+#include <qpushbutton.h>
+#include <qstyle.h>
+
+class tst_QTabBar : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTabBar();
+ virtual ~tst_QTabBar();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+
+private slots:
+ void getSetCheck();
+ void setIconSize();
+ void setIconSize_data();
+
+ void testCurrentChanged_data();
+ void testCurrentChanged();
+
+ void insertAtCurrentIndex();
+
+ void removeTab_data();
+ void removeTab();
+
+ void setElideMode_data();
+ void setElideMode();
+ void sizeHints();
+
+ void setUsesScrollButtons_data();
+ void setUsesScrollButtons();
+
+ void removeLastTab();
+
+ void closeButton();
+
+ void tabButton_data();
+ void tabButton();
+
+ void selectionBehaviorOnRemove_data();
+ void selectionBehaviorOnRemove();
+
+ void moveTab_data();
+ void moveTab();
+
+ void task251184_removeTab();
+ void changeTitleWhileDoubleClickingTab();
+
+ void taskQTBUG_10052_widgetLayoutWhenMoving();
+};
+
+// Testing get/set functions
+void tst_QTabBar::getSetCheck()
+{
+ QTabBar obj1;
+ obj1.addTab("Tab1");
+ obj1.addTab("Tab2");
+ obj1.addTab("Tab3");
+ obj1.addTab("Tab4");
+ obj1.addTab("Tab5");
+ // Shape QTabBar::shape()
+ // void QTabBar::setShape(Shape)
+ obj1.setShape(QTabBar::Shape(QTabBar::RoundedNorth));
+ QCOMPARE(QTabBar::Shape(QTabBar::RoundedNorth), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::RoundedSouth));
+ QCOMPARE(QTabBar::Shape(QTabBar::RoundedSouth), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::RoundedWest));
+ QCOMPARE(QTabBar::Shape(QTabBar::RoundedWest), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::RoundedEast));
+ QCOMPARE(QTabBar::Shape(QTabBar::RoundedEast), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::TriangularNorth));
+ QCOMPARE(QTabBar::Shape(QTabBar::TriangularNorth), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::TriangularSouth));
+ QCOMPARE(QTabBar::Shape(QTabBar::TriangularSouth), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::TriangularWest));
+ QCOMPARE(QTabBar::Shape(QTabBar::TriangularWest), obj1.shape());
+ obj1.setShape(QTabBar::Shape(QTabBar::TriangularEast));
+ QCOMPARE(QTabBar::Shape(QTabBar::TriangularEast), obj1.shape());
+
+ // bool QTabBar::drawBase()
+ // void QTabBar::setDrawBase(bool)
+ obj1.setDrawBase(false);
+ QCOMPARE(false, obj1.drawBase());
+ obj1.setDrawBase(true);
+ QCOMPARE(true, obj1.drawBase());
+
+ // int QTabBar::currentIndex()
+ // void QTabBar::setCurrentIndex(int)
+ obj1.setCurrentIndex(0);
+ QCOMPARE(0, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(0, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(0, obj1.currentIndex());
+ obj1.setCurrentIndex(4);
+ QCOMPARE(4, obj1.currentIndex());
+}
+
+tst_QTabBar::tst_QTabBar()
+{
+}
+
+tst_QTabBar::~tst_QTabBar()
+{
+}
+
+void tst_QTabBar::initTestCase()
+{
+}
+
+void tst_QTabBar::cleanupTestCase()
+{
+}
+
+void tst_QTabBar::init()
+{
+}
+
+void tst_QTabBar::setIconSize_data()
+{
+ QTest::addColumn<int>("sizeToSet");
+ QTest::addColumn<int>("expectedWidth");
+
+ const int iconDefault = qApp->style()->pixelMetric(QStyle::PM_TabBarIconSize);
+ const int smallIconSize = qApp->style()->pixelMetric(QStyle::PM_SmallIconSize);
+ const int largeIconSize = qApp->style()->pixelMetric(QStyle::PM_LargeIconSize);
+ QTest::newRow("default") << -1 << iconDefault;
+ QTest::newRow("zero") << 0 << 0;
+ QTest::newRow("same as default") << iconDefault << iconDefault;
+ QTest::newRow("large") << largeIconSize << largeIconSize;
+ QTest::newRow("small") << smallIconSize << smallIconSize;
+}
+
+void tst_QTabBar::setIconSize()
+{
+ QFETCH(int, sizeToSet);
+ QFETCH(int, expectedWidth);
+ QTabBar tabBar;
+ tabBar.setIconSize(QSize(sizeToSet, sizeToSet));
+ QCOMPARE(tabBar.iconSize().width(), expectedWidth);
+}
+
+void tst_QTabBar::testCurrentChanged_data()
+{
+ QTest::addColumn<int>("tabToSet");
+ QTest::addColumn<int>("expectedCount");
+
+ QTest::newRow("pressAntotherTab") << 1 << 2;
+ QTest::newRow("pressTheSameTab") << 0 << 1;
+}
+
+void tst_QTabBar::testCurrentChanged()
+{
+ QFETCH(int, tabToSet);
+ QFETCH(int, expectedCount);
+ QTabBar tabBar;
+ QSignalSpy spy(&tabBar, SIGNAL(currentChanged(int)));
+ tabBar.addTab("Tab1");
+ tabBar.addTab("Tab2");
+ QCOMPARE(tabBar.currentIndex(), 0);
+ tabBar.setCurrentIndex(tabToSet);
+ QCOMPARE(tabBar.currentIndex(), tabToSet);
+ QCOMPARE(spy.count(), expectedCount);
+}
+
+void tst_QTabBar::insertAtCurrentIndex()
+{
+ QTabBar tabBar;
+ tabBar.addTab("Tab1");
+ QCOMPARE(tabBar.currentIndex(), 0);
+ tabBar.insertTab(0, "Tab2");
+ QCOMPARE(tabBar.currentIndex(), 1);
+ tabBar.insertTab(0, "Tab3");
+ QCOMPARE(tabBar.currentIndex(), 2);
+ tabBar.insertTab(2, "Tab4");
+ QCOMPARE(tabBar.currentIndex(), 3);
+}
+
+void tst_QTabBar::removeTab_data()
+{
+ QTest::addColumn<int>("currentIndex");
+ QTest::addColumn<int>("deleteIndex");
+ QTest::addColumn<int>("spyCount");
+ QTest::addColumn<int>("finalIndex");
+
+ QTest::newRow("deleteEnd") << 0 << 2 << 0 << 0;
+ QTest::newRow("deleteEndWithIndexOnEnd") << 2 << 2 << 1 << 1;
+ QTest::newRow("deleteMiddle") << 2 << 1 << 1 << 1;
+ QTest::newRow("deleteMiddleOnMiddle") << 1 << 1 << 1 << 1;
+}
+void tst_QTabBar::removeTab()
+{
+ QTabBar tabbar;
+
+ QFETCH(int, currentIndex);
+ QFETCH(int, deleteIndex);
+ tabbar.addTab("foo");
+ tabbar.addTab("bar");
+ tabbar.addTab("baz");
+ tabbar.setCurrentIndex(currentIndex);
+ QSignalSpy spy(&tabbar, SIGNAL(currentChanged(int)));
+ tabbar.removeTab(deleteIndex);
+ QTEST(spy.count(), "spyCount");
+ QTEST(tabbar.currentIndex(), "finalIndex");
+}
+
+void tst_QTabBar::setElideMode_data()
+{
+ QTest::addColumn<int>("tabElideMode");
+ QTest::addColumn<int>("expectedMode");
+
+ QTest::newRow("default") << -128 << qApp->style()->styleHint(QStyle::SH_TabBar_ElideMode);
+ QTest::newRow("explicit default") << qApp->style()->styleHint(QStyle::SH_TabBar_ElideMode)
+ << qApp->style()->styleHint(QStyle::SH_TabBar_ElideMode);
+ QTest::newRow("None") << int(Qt::ElideNone) << int(Qt::ElideNone);
+ QTest::newRow("Left") << int(Qt::ElideLeft) << int(Qt::ElideLeft);
+ QTest::newRow("Center") << int(Qt::ElideMiddle) << int(Qt::ElideMiddle);
+ QTest::newRow("Right") << int(Qt::ElideRight) << int(Qt::ElideRight);
+}
+
+void tst_QTabBar::setElideMode()
+{
+ QFETCH(int, tabElideMode);
+ QTabBar tabBar;
+ if (tabElideMode != -128)
+ tabBar.setElideMode(Qt::TextElideMode(tabElideMode));
+ QTEST(int(tabBar.elideMode()), "expectedMode");
+ // Make sure style sheet does not override user set mode
+ tabBar.setStyleSheet("QWidget { background-color: #ABA8A6;}");
+ QTEST(int(tabBar.elideMode()), "expectedMode");
+}
+
+void tst_QTabBar::sizeHints()
+{
+ QTabBar tabBar;
+ QSKIP("To be fixed on Mac (font size below not large enough) and Linux QWS (probably too large for the screen).", SkipSingle);
+ tabBar.setFont(QFont("Arial", 10));
+ tabBar.addTab("tab 01");
+ tabBar.addTab("tab 02");
+ tabBar.addTab("tab 03");
+ tabBar.addTab("tab 04");
+ tabBar.addTab("tab 05");
+ tabBar.addTab("tab 06");
+ tabBar.addTab("This is tab7");
+ tabBar.addTab("This is tab8");
+ tabBar.addTab("This is tab9 with a very long title");
+
+ // No eliding and no scrolling -> tabbar becomes very wide
+ tabBar.setUsesScrollButtons(false);
+ tabBar.setElideMode(Qt::ElideNone);
+// qDebug() << tabBar.minimumSizeHint() << tabBar.sizeHint();
+ QVERIFY(tabBar.minimumSizeHint().width() > 700);
+ QVERIFY(tabBar.sizeHint().width() > 700);
+
+ // Scrolling enabled -> no reason to become very wide
+ tabBar.setUsesScrollButtons(true);
+ // qDebug() << tabBar.minimumSizeHint() << tabBar.sizeHint();
+ QVERIFY(tabBar.minimumSizeHint().width() < 200);
+ QVERIFY(tabBar.sizeHint().width() > 700); // unchanged
+
+ // Eliding enabled -> no reason to become very wide
+ tabBar.setUsesScrollButtons(false);
+ tabBar.setElideMode(Qt::ElideRight);
+// qDebug() << tabBar.minimumSizeHint() << tabBar.sizeHint();
+ QVERIFY(tabBar.minimumSizeHint().width() < 500);
+ QVERIFY(tabBar.sizeHint().width() > 700); // unchanged
+
+ tabBar.addTab("This is tab10 with a very long title");
+ QVERIFY(tabBar.minimumSizeHint().width() < 600);
+ QVERIFY(tabBar.sizeHint().width() > 700); // unchanged
+}
+
+void tst_QTabBar::setUsesScrollButtons_data()
+{
+ QTest::addColumn<int>("usesArrows");
+ QTest::addColumn<bool>("expectedArrows");
+
+ QTest::newRow("default") << -128 << !qApp->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows);
+ QTest::newRow("explicit default")
+ << int(!qApp->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows))
+ << !qApp->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows);
+ QTest::newRow("No") << int(false) << false;
+ QTest::newRow("Yes") << int(true) << true;
+}
+
+void tst_QTabBar::setUsesScrollButtons()
+{
+ QFETCH(int, usesArrows);
+ QTabBar tabBar;
+ if (usesArrows != -128)
+ tabBar.setUsesScrollButtons(usesArrows);
+ QTEST(tabBar.usesScrollButtons(), "expectedArrows");
+
+ // Make sure style sheet does not override user set mode
+ tabBar.setStyleSheet("QWidget { background-color: #ABA8A6;}");
+ QTEST(tabBar.usesScrollButtons(), "expectedArrows");
+}
+
+void tst_QTabBar::removeLastTab()
+{
+ QTabBar tabbar;
+ QSignalSpy spy(&tabbar, SIGNAL(currentChanged(int)));
+ int index = tabbar.addTab("foo");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), index);
+ spy.clear();
+
+ tabbar.removeTab(index);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), -1);
+ spy.clear();
+}
+
+void tst_QTabBar::closeButton()
+{
+ QTabBar tabbar;
+ QCOMPARE(tabbar.tabsClosable(), false);
+ tabbar.setTabsClosable(true);
+ QCOMPARE(tabbar.tabsClosable(), true);
+ tabbar.addTab("foo");
+
+ QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition)tabbar.style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, &tabbar);
+ QTabBar::ButtonPosition otherSide = (closeSide == QTabBar::LeftSide ? QTabBar::RightSide : QTabBar::LeftSide);
+ QVERIFY(tabbar.tabButton(0, otherSide) == 0);
+ QVERIFY(tabbar.tabButton(0, closeSide) != 0);
+
+ QAbstractButton *button = static_cast<QAbstractButton*>(tabbar.tabButton(0, closeSide));
+ QVERIFY(button);
+ QSignalSpy spy(&tabbar, SIGNAL(tabCloseRequested(int)));
+ button->click();
+ QCOMPARE(tabbar.count(), 1);
+ QCOMPARE(spy.count(), 1);
+}
+
+Q_DECLARE_METATYPE(QTabBar::ButtonPosition)
+void tst_QTabBar::tabButton_data()
+{
+ QTest::addColumn<QTabBar::ButtonPosition>("position");
+
+ QTest::newRow("left") << QTabBar::LeftSide;
+ QTest::newRow("right") << QTabBar::RightSide;
+}
+
+// QTabBar::setTabButton(index, closeSide, closeButton);
+void tst_QTabBar::tabButton()
+{
+ QFETCH(QTabBar::ButtonPosition, position);
+ QTabBar::ButtonPosition otherSide = (position == QTabBar::LeftSide ? QTabBar::RightSide : QTabBar::LeftSide);
+
+ QTabBar tabbar;
+ tabbar.resize(500, 200);
+ tabbar.show();
+ QTRY_VERIFY(tabbar.isVisible());
+
+ tabbar.setTabButton(-1, position, 0);
+ QVERIFY(tabbar.tabButton(-1, position) == 0);
+ QVERIFY(tabbar.tabButton(0, position) == 0);
+
+ tabbar.addTab("foo");
+ QCOMPARE(tabbar.count(), 1);
+ tabbar.setTabButton(0, position, 0);
+ QVERIFY(tabbar.tabButton(0, position) == 0);
+
+ QPushButton *button = new QPushButton;
+ button->show();
+ button->setText("hi");
+ button->resize(10, 10);
+ QTRY_VERIFY(button->isVisible());
+ QTRY_VERIFY(button->isVisible());
+
+ tabbar.setTabButton(0, position, button);
+
+ QCOMPARE(tabbar.tabButton(0, position), static_cast<QWidget *>(button));
+ QTRY_VERIFY(!button->isHidden());
+ QVERIFY(tabbar.tabButton(0, otherSide) == 0);
+ QCOMPARE(button->parent(), static_cast<QObject *>(&tabbar));
+ QVERIFY(button->pos() != QPoint(0, 0));
+
+ QPushButton *button2 = new QPushButton;
+ tabbar.setTabButton(0, position, button2);
+ QVERIFY(button->isHidden());
+}
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(QTabBar::SelectionBehavior)
+Q_DECLARE_METATYPE(IntList)
+#define ONE(x) (IntList() << x)
+void tst_QTabBar::selectionBehaviorOnRemove_data()
+{
+ QTest::addColumn<QTabBar::SelectionBehavior>("selectionBehavior");
+ QTest::addColumn<int>("tabs");
+ QTest::addColumn<IntList>("select");
+ QTest::addColumn<IntList>("remove");
+ QTest::addColumn<int>("expected");
+
+ // Count select remove current
+ QTest::newRow("left-1") << QTabBar::SelectLeftTab << 3 << (IntList() << 0) << ONE(0) << 0;
+
+ QTest::newRow("left-2") << QTabBar::SelectLeftTab << 3 << (IntList() << 0) << ONE(1) << 0; // not removing current
+ QTest::newRow("left-3") << QTabBar::SelectLeftTab << 3 << (IntList() << 0) << ONE(2) << 0; // not removing current
+ QTest::newRow("left-4") << QTabBar::SelectLeftTab << 3 << (IntList() << 1) << ONE(0) << 0; // not removing current
+ QTest::newRow("left-5") << QTabBar::SelectLeftTab << 3 << (IntList() << 1) << ONE(1) << 0;
+ QTest::newRow("left-6") << QTabBar::SelectLeftTab << 3 << (IntList() << 1) << ONE(2) << 1;
+ QTest::newRow("left-7") << QTabBar::SelectLeftTab << 3 << (IntList() << 2) << ONE(0) << 1; // not removing current
+ QTest::newRow("left-8") << QTabBar::SelectLeftTab << 3 << (IntList() << 2) << ONE(1) << 1; // not removing current
+ QTest::newRow("left-9") << QTabBar::SelectLeftTab << 3 << (IntList() << 2) << ONE(2) << 1;
+
+ QTest::newRow("right-1") << QTabBar::SelectRightTab << 3 << (IntList() << 0) << ONE(0) << 0;
+ QTest::newRow("right-2") << QTabBar::SelectRightTab << 3 << (IntList() << 0) << ONE(1) << 0; // not removing current
+ QTest::newRow("right-3") << QTabBar::SelectRightTab << 3 << (IntList() << 0) << ONE(2) << 0; // not removing current
+ QTest::newRow("right-4") << QTabBar::SelectRightTab << 3 << (IntList() << 1) << ONE(0) << 0; // not removing current
+ QTest::newRow("right-5") << QTabBar::SelectRightTab << 3 << (IntList() << 1) << ONE(1) << 1;
+ QTest::newRow("right-6") << QTabBar::SelectRightTab << 3 << (IntList() << 1) << ONE(2) << 1; // not removing current
+ QTest::newRow("right-7") << QTabBar::SelectRightTab << 3 << (IntList() << 2) << ONE(0) << 1; // not removing current
+ QTest::newRow("right-8") << QTabBar::SelectRightTab << 3 << (IntList() << 2) << ONE(1) << 1; // not removing current
+ QTest::newRow("right-9") << QTabBar::SelectRightTab << 3 << (IntList() << 2) << ONE(2) << 1;
+
+ QTest::newRow("previous-0") << QTabBar::SelectPreviousTab << 3 << (IntList()) << ONE(0) << 0;
+ QTest::newRow("previous-1") << QTabBar::SelectPreviousTab << 3 << (IntList()) << ONE(1) << 0; // not removing current
+ QTest::newRow("previous-2") << QTabBar::SelectPreviousTab << 3 << (IntList()) << ONE(2) << 0; // not removing current
+
+ QTest::newRow("previous-3") << QTabBar::SelectPreviousTab << 3 << (IntList() << 2) << ONE(0) << 1; // not removing current
+ QTest::newRow("previous-4") << QTabBar::SelectPreviousTab << 3 << (IntList() << 2) << ONE(1) << 1; // not removing current
+ QTest::newRow("previous-5") << QTabBar::SelectPreviousTab << 3 << (IntList() << 2) << ONE(2) << 0;
+
+ // go back one
+ QTest::newRow("previous-6") << QTabBar::SelectPreviousTab << 4 << (IntList() << 0 << 2 << 3 << 1) << (IntList() << 1) << 2;
+ // go back two
+ QTest::newRow("previous-7") << QTabBar::SelectPreviousTab << 4 << (IntList() << 0 << 2 << 3 << 1) << (IntList() << 1 << 2) << 1;
+ // go back three
+ QTest::newRow("previous-8") << QTabBar::SelectPreviousTab << 4 << (IntList() << 0 << 2 << 3 << 1) << (IntList() << 1 << 2 << 1) << 0;
+
+ // pick from the middle
+ QTest::newRow("previous-9") << QTabBar::SelectPreviousTab << 4 << (IntList() << 0 << 2 << 3 << 1) << (IntList() << 2 << 1) << 1;
+
+ // every other one
+ QTest::newRow("previous-10") << QTabBar::SelectPreviousTab << 7 << (IntList() << 0 << 2 << 4 << 6) << (IntList() << 6 << 4) << 2;
+
+
+}
+
+void tst_QTabBar::selectionBehaviorOnRemove()
+{
+ QFETCH(QTabBar::SelectionBehavior, selectionBehavior);
+ QFETCH(int, tabs);
+ QFETCH(IntList, select);
+ QFETCH(IntList, remove);
+ QFETCH(int, expected);
+
+ QTabBar tabbar;
+ tabbar.setSelectionBehaviorOnRemove(selectionBehavior);
+ while(--tabs >= 0)
+ tabbar.addTab(QString::number(tabs));
+ QCOMPARE(tabbar.currentIndex(), 0);
+ while(!select.isEmpty())
+ tabbar.setCurrentIndex(select.takeFirst());
+ while(!remove.isEmpty())
+ tabbar.removeTab(remove.takeFirst());
+ QVERIFY(tabbar.count() > 0);
+ QCOMPARE(tabbar.currentIndex(), expected);
+}
+
+class TabBar : public QTabBar
+{
+ Q_OBJECT
+public:
+ void callMoveTab(int from, int to){ moveTab(from, to); }
+};
+
+
+Q_DECLARE_METATYPE(QTabBar::Shape)
+void tst_QTabBar::moveTab_data()
+{
+ QTest::addColumn<QTabBar::Shape>("shape");
+ QTest::addColumn<int>("tabs");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+
+ QTest::newRow("null-0") << QTabBar::RoundedNorth << 0 << -1 << -1;
+ QTest::newRow("null-1") << QTabBar::RoundedEast << 0 << -1 << -1;
+ QTest::newRow("null-2") << QTabBar::RoundedEast << 1 << 0 << 0;
+
+ QTest::newRow("two-0") << QTabBar::RoundedNorth << 2 << 0 << 1;
+ QTest::newRow("two-1") << QTabBar::RoundedNorth << 2 << 1 << 0;
+
+ QTest::newRow("five-0") << QTabBar::RoundedNorth << 5 << 1 << 3; // forward
+ QTest::newRow("five-1") << QTabBar::RoundedNorth << 5 << 3 << 1; // reverse
+
+ QTest::newRow("five-2") << QTabBar::RoundedNorth << 5 << 0 << 4; // forward
+ QTest::newRow("five-3") << QTabBar::RoundedNorth << 5 << 1 << 4; // forward
+ QTest::newRow("five-4") << QTabBar::RoundedNorth << 5 << 3 << 4; // forward
+}
+
+void tst_QTabBar::moveTab()
+{
+ QFETCH(QTabBar::Shape, shape);
+ QFETCH(int, tabs);
+ QFETCH(int, from);
+ QFETCH(int, to);
+
+ TabBar bar;
+ bar.setShape(shape);
+ while(--tabs >= 0)
+ bar.addTab(QString::number(tabs));
+ bar.callMoveTab(from, to);
+}
+
+
+class MyTabBar : public QTabBar
+{
+ Q_OBJECT
+public slots:
+ void onCurrentChanged()
+ {
+ //we just want this to be done once
+ disconnect(this, SIGNAL(currentChanged(int)), this, SLOT(onCurrentChanged()));
+ removeTab(0);
+ }
+};
+
+void tst_QTabBar::task251184_removeTab()
+{
+ MyTabBar bar;
+ bar.addTab("bar1");
+ bar.addTab("bar2");
+ QCOMPARE(bar.count(), 2);
+ QCOMPARE(bar.currentIndex(), 0);
+
+ bar.connect(&bar, SIGNAL(currentChanged(int)), SLOT(onCurrentChanged()));
+ bar.setCurrentIndex(1);
+
+ QCOMPARE(bar.count(), 1);
+ QCOMPARE(bar.currentIndex(), 0);
+ QCOMPARE(bar.tabText(bar.currentIndex()), QString("bar2"));
+}
+
+
+class TitleChangeTabBar : public QTabBar
+{
+ Q_OBJECT
+
+ QTimer timer;
+ int count;
+
+public:
+ TitleChangeTabBar(QWidget * parent = 0) : QTabBar(parent), count(0)
+ {
+ setMovable(true);
+ addTab("0");
+ connect(&timer, SIGNAL(timeout()), this, SLOT(updateTabText()));
+ timer.start(1);
+ }
+
+public slots:
+ void updateTabText()
+ {
+ count++;
+ setTabText(0, QString("%1").arg(count));
+ }
+};
+
+void tst_QTabBar::changeTitleWhileDoubleClickingTab()
+{
+ TitleChangeTabBar bar;
+ QPoint tabPos = bar.tabRect(0).center();
+
+ for(int i=0; i < 10; i++)
+ QTest::mouseDClick(&bar, Qt::LeftButton, 0, tabPos);
+}
+
+class Widget10052 : public QWidget
+{
+public:
+ Widget10052(QWidget *parent) : QWidget(parent), moved(false)
+ { }
+
+ void moveEvent(QMoveEvent *e)
+ {
+ moved = e->oldPos() != e->pos();
+ QWidget::moveEvent(e);
+ }
+
+ bool moved;
+};
+
+void tst_QTabBar::taskQTBUG_10052_widgetLayoutWhenMoving()
+{
+ QTabBar tabBar;
+ tabBar.insertTab(0, "My first tab");
+ Widget10052 w1(&tabBar);
+ tabBar.setTabButton(0, QTabBar::RightSide, &w1);
+ tabBar.insertTab(1, "My other tab");
+ Widget10052 w2(&tabBar);
+ tabBar.setTabButton(1, QTabBar::RightSide, &w2);
+
+ tabBar.show();
+ QTest::qWaitForWindowShown(&tabBar);
+ w1.moved = w2.moved = false;
+ tabBar.moveTab(0, 1);
+ QTRY_VERIFY(w1.moved);
+ QVERIFY(w2.moved);
+}
+
+QTEST_MAIN(tst_QTabBar)
+#include "tst_qtabbar.moc"
diff --git a/tests/auto/widgets/widgets/qtabwidget/.gitignore b/tests/auto/widgets/widgets/qtabwidget/.gitignore
new file mode 100644
index 0000000000..d8f924a3df
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtabwidget/.gitignore
@@ -0,0 +1 @@
+tst_qtabwidget
diff --git a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
new file mode 100644
index 0000000000..d551c66500
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+
+INCLUDEPATH += ../
+
+HEADERS +=
+SOURCES += tst_qtabwidget.cpp
+
+win32:!wince*:LIBS += -luser32
+
+CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp
new file mode 100644
index 0000000000..6d356dee9b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp
@@ -0,0 +1,680 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qtabwidget.h>
+#include <qdebug.h>
+#include <qapplication.h>
+#include <qlabel.h>
+#include <QtWidgets/qboxlayout.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+# include <qt_windows.h>
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("desktop is not visible, this test would fail", SkipSingle);
+#else
+#define Q_CHECK_PAINTEVENTS
+#endif
+#if defined(Q_WS_X11)
+# include <private/qt_x11_p.h>
+# include <qx11info_x11.h>
+#elif defined(Q_WS_QWS)
+# include <qwindowsystem_qws.h>
+#endif
+
+class QTabWidgetChild:public QTabWidget {
+ public:
+ QTabWidgetChild():tabCount(0) {
+ QVERIFY(tabBar() != NULL);
+ QWidget *w = new QWidget;
+ int index = addTab(w, "test");
+ QCOMPARE(tabCount, 1);
+ removeTab(index);
+ QCOMPARE(tabCount, 0);
+
+ // Test bad arguments
+ // This will assert, so don't do it :)
+ //setTabBar(NULL);
+ };
+
+ protected:
+ virtual void tabInserted(int /*index */ ) {
+ tabCount++;
+ };
+ virtual void tabRemoved(int /*index */ ) {
+ tabCount--;
+ };
+ int tabCount;
+};
+
+class tst_QTabWidget:public QObject {
+ Q_OBJECT
+ public:
+ tst_QTabWidget();
+
+ public slots:
+ void init();
+ void cleanup();
+ private slots:
+ void getSetCheck();
+ void testChild();
+ void addRemoveTab();
+ void tabPosition();
+ void tabEnabled();
+ void tabText();
+ void tabShape();
+ void tabTooltip();
+ void tabIcon();
+ void indexOf();
+ void currentWidget();
+ void currentIndex();
+ void cornerWidget();
+ void removeTab();
+ void clear();
+ void keyboardNavigation();
+ void paintEventCount();
+ void minimumSizeHint();
+ void heightForWidth_data();
+ void heightForWidth();
+
+ private:
+ int addPage();
+ void removePage(int index);
+ QTabWidget *tw;
+};
+
+// Testing get/set functions
+void tst_QTabWidget::getSetCheck()
+{
+ QTabWidget obj1;
+ QWidget *w1 = new QWidget;
+ QWidget *w2 = new QWidget;
+ QWidget *w3 = new QWidget;
+ QWidget *w4 = new QWidget;
+ QWidget *w5 = new QWidget;
+
+ obj1.addTab(w1, "Page 1");
+ obj1.addTab(w2, "Page 2");
+ obj1.addTab(w3, "Page 3");
+ obj1.addTab(w4, "Page 4");
+ obj1.addTab(w5, "Page 5");
+
+ // TabShape QTabWidget::tabShape()
+ // void QTabWidget::setTabShape(TabShape)
+ obj1.setTabShape(QTabWidget::TabShape(QTabWidget::Rounded));
+ QCOMPARE(QTabWidget::TabShape(QTabWidget::Rounded), obj1.tabShape());
+ obj1.setTabShape(QTabWidget::TabShape(QTabWidget::Triangular));
+ QCOMPARE(QTabWidget::TabShape(QTabWidget::Triangular), obj1.tabShape());
+
+ // int QTabWidget::currentIndex()
+ // void QTabWidget::setCurrentIndex(int)
+ obj1.setCurrentIndex(0);
+ QCOMPARE(0, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(0, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(0, obj1.currentIndex());
+ obj1.setCurrentIndex(4);
+ QCOMPARE(4, obj1.currentIndex());
+
+ // QWidget * QTabWidget::currentWidget()
+ // void QTabWidget::setCurrentWidget(QWidget *)
+ obj1.setCurrentWidget(w1);
+ QCOMPARE(w1, obj1.currentWidget());
+ obj1.setCurrentWidget(w5);
+ QCOMPARE(w5, obj1.currentWidget());
+ obj1.setCurrentWidget((QWidget *)0);
+ QCOMPARE(w5, obj1.currentWidget()); // current not changed
+}
+
+tst_QTabWidget::tst_QTabWidget()
+{
+}
+
+void tst_QTabWidget::init()
+{
+ tw = new QTabWidget(0);
+ QCOMPARE(tw->count(), 0);
+ QCOMPARE(tw->currentIndex(), -1);
+ QVERIFY(tw->currentWidget() == NULL);
+}
+
+void tst_QTabWidget::cleanup()
+{
+ delete tw;
+ tw = 0;
+}
+
+void tst_QTabWidget::testChild()
+{
+ QTabWidgetChild t;
+}
+
+#define LABEL "TEST"
+#define TIP "TIP"
+int tst_QTabWidget::addPage()
+{
+ QWidget *w = new QWidget();
+ return tw->addTab(w, LABEL);
+}
+
+void tst_QTabWidget::removePage(int index)
+{
+ QWidget *w = tw->widget(index);
+ tw->removeTab(index);
+ delete w;
+}
+
+/**
+ * Tests:
+ * addTab(...) which really calls -> insertTab(...)
+ * widget(...)
+ * removeTab(...);
+ * If this fails then many others probably will too.
+ */
+void tst_QTabWidget::addRemoveTab()
+{
+ // Test bad arguments
+ tw->addTab(NULL, LABEL);
+ QCOMPARE(tw->count(), 0);
+ tw->removeTab(-1);
+ QCOMPARE(tw->count(), 0);
+ QVERIFY(tw->widget(-1) == 0);
+
+ QWidget *w = new QWidget();
+ int index = tw->addTab(w, LABEL);
+ // return value
+ QCOMPARE(tw->indexOf(w), index);
+
+ QCOMPARE(tw->count(), 1);
+ QVERIFY(tw->widget(index) == w);
+ QCOMPARE(tw->tabText(index), QString(LABEL));
+
+ removePage(index);
+ QCOMPARE(tw->count(), 0);
+}
+
+void tst_QTabWidget::tabPosition()
+{
+ tw->setTabPosition(QTabWidget::North);
+ QCOMPARE(tw->tabPosition(), QTabWidget::North);
+ tw->setTabPosition(QTabWidget::South);
+ QCOMPARE(tw->tabPosition(), QTabWidget::South);
+ tw->setTabPosition(QTabWidget::East);
+ QCOMPARE(tw->tabPosition(), QTabWidget::East);
+ tw->setTabPosition(QTabWidget::West);
+ QCOMPARE(tw->tabPosition(), QTabWidget::West);
+}
+
+void tst_QTabWidget::tabEnabled()
+{
+ // Test bad arguments
+ QVERIFY(tw->isTabEnabled(-1) == false);
+ tw->setTabEnabled(-1, false);
+
+ int index = addPage();
+
+ tw->setTabEnabled(index, true);
+ QVERIFY(tw->isTabEnabled(index));
+ QVERIFY(tw->widget(index)->isEnabled());
+ tw->setTabEnabled(index, false);
+ QVERIFY(!tw->isTabEnabled(index));
+ QVERIFY(!tw->widget(index)->isEnabled());
+ tw->setTabEnabled(index, true);
+ QVERIFY(tw->isTabEnabled(index));
+ QVERIFY(tw->widget(index)->isEnabled());
+
+ removePage(index);
+}
+
+void tst_QTabWidget::tabText()
+{
+ // Test bad arguments
+ QCOMPARE(tw->tabText(-1), QString(""));
+ tw->setTabText(-1, LABEL);
+
+ int index = addPage();
+
+ tw->setTabText(index, "new");
+ QCOMPARE(tw->tabText(index), QString("new"));
+ tw->setTabText(index, LABEL);
+ QCOMPARE(tw->tabText(index), QString(LABEL));
+
+ removePage(index);
+}
+
+void tst_QTabWidget::tabShape()
+{
+ int index = addPage();
+
+ tw->setTabShape(QTabWidget::Rounded);
+ QCOMPARE(tw->tabShape(), QTabWidget::Rounded);
+ tw->setTabShape(QTabWidget::Triangular);
+ QCOMPARE(tw->tabShape(), QTabWidget::Triangular);
+ tw->setTabShape(QTabWidget::Rounded);
+ QCOMPARE(tw->tabShape(), QTabWidget::Rounded);
+
+ removePage(index);
+}
+
+void tst_QTabWidget::tabTooltip()
+{
+ // Test bad arguments
+ QCOMPARE(tw->tabToolTip(-1), QString(""));
+ tw->setTabText(-1, TIP);
+
+ int index = addPage();
+
+ tw->setTabToolTip(index, "tip");
+ QCOMPARE(tw->tabToolTip(index), QString("tip"));
+ tw->setTabToolTip(index, TIP);
+ QCOMPARE(tw->tabToolTip(index), QString(TIP));
+
+ removePage(index);
+}
+
+void tst_QTabWidget::tabIcon()
+{
+ // Test bad arguments
+ QVERIFY(tw->tabToolTip(-1).isNull());
+ tw->setTabIcon(-1, QIcon());
+
+ int index = addPage();
+
+ QIcon icon;
+ tw->setTabIcon(index, icon);
+ QVERIFY(tw->tabIcon(index).isNull());
+
+ removePage(index);
+}
+
+void tst_QTabWidget::indexOf()
+{
+ // Test bad arguments
+ QCOMPARE(tw->indexOf(NULL), -1);
+
+ int index = addPage();
+ QWidget *w = tw->widget(index);
+ QCOMPARE(tw->indexOf(w), index);
+
+ removePage(index);
+}
+
+void tst_QTabWidget::currentWidget()
+{
+ // Test bad arguments
+ tw->setCurrentWidget(NULL);
+ QVERIFY(tw->currentWidget() == NULL);
+
+ int index = addPage();
+ QWidget *w = tw->widget(index);
+ QVERIFY(tw->currentWidget() == w);
+ QCOMPARE(tw->currentIndex(), index);
+
+ tw->setCurrentWidget(NULL);
+ QVERIFY(tw->currentWidget() == w);
+ QCOMPARE(tw->currentIndex(), index);
+
+ int index2 = addPage();
+ QWidget *w2 = tw->widget(index2);
+ Q_UNUSED(w2);
+ QVERIFY(tw->currentWidget() == w);
+ QCOMPARE(tw->currentIndex(), index);
+
+ removePage(index2);
+ removePage(index);
+}
+
+/**
+ * setCurrentWidget(..) calls setCurrentIndex(..)
+ * currentChanged(..) SIGNAL
+ */
+void tst_QTabWidget::currentIndex()
+{
+ // Test bad arguments
+ QSignalSpy spy(tw, SIGNAL(currentChanged(int)));
+ QCOMPARE(tw->currentIndex(), -1);
+ tw->setCurrentIndex(-1);
+ QCOMPARE(tw->currentIndex(), -1);
+ QCOMPARE(spy.count(), 0);
+
+ int firstIndex = addPage();
+ tw->setCurrentIndex(firstIndex);
+ QCOMPARE(tw->currentIndex(), firstIndex);
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QVERIFY(arguments.at(0).toInt() == firstIndex);
+
+ int index = addPage();
+ QCOMPARE(tw->currentIndex(), firstIndex);
+ tw->setCurrentIndex(index);
+ QCOMPARE(tw->currentIndex(), index);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QVERIFY(arguments.at(0).toInt() == index);
+
+ removePage(index);
+ QCOMPARE(tw->currentIndex(), firstIndex);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QVERIFY(arguments.at(0).toInt() == firstIndex);
+
+ removePage(firstIndex);
+ QCOMPARE(tw->currentIndex(), -1);
+ QCOMPARE(spy.count(), 1);
+ arguments = spy.takeFirst();
+ QVERIFY(arguments.at(0).toInt() == -1);
+}
+
+void tst_QTabWidget::cornerWidget()
+{
+ // Test bad arguments
+ tw->setCornerWidget(NULL, Qt::TopRightCorner);
+
+ QVERIFY(tw->cornerWidget(Qt::TopLeftCorner) == 0);
+ QVERIFY(tw->cornerWidget(Qt::TopRightCorner) == 0);
+ QVERIFY(tw->cornerWidget(Qt::BottomLeftCorner) == 0);
+ QVERIFY(tw->cornerWidget(Qt::BottomRightCorner) == 0);
+
+ QWidget *w = new QWidget(0);
+ tw->setCornerWidget(w, Qt::TopLeftCorner);
+ QCOMPARE(w->parent(), (QObject *)tw);
+ QVERIFY(tw->cornerWidget(Qt::TopLeftCorner) == w);
+ tw->setCornerWidget(w, Qt::TopRightCorner);
+ QVERIFY(tw->cornerWidget(Qt::TopRightCorner) == w);
+ tw->setCornerWidget(w, Qt::BottomLeftCorner);
+ QVERIFY(tw->cornerWidget(Qt::BottomLeftCorner) == w);
+ tw->setCornerWidget(w, Qt::BottomRightCorner);
+ QVERIFY(tw->cornerWidget(Qt::BottomRightCorner) == w);
+
+ tw->setCornerWidget(0, Qt::TopRightCorner);
+ QVERIFY(tw->cornerWidget(Qt::TopRightCorner) == 0);
+ QCOMPARE(w->isHidden(), true);
+}
+
+//test that the QTabWidget::count() is correct at the moment the currentChanged signal is emit
+class RemoveTabObject : public QObject
+{
+ Q_OBJECT
+ public:
+ RemoveTabObject(QTabWidget *_tw) : tw(_tw), count(-1) {
+ connect(tw, SIGNAL(currentChanged(int)), this, SLOT(currentChanged()));
+ }
+
+ QTabWidget *tw;
+ int count;
+ public slots:
+ void currentChanged() { count = tw->count(); }
+};
+
+void tst_QTabWidget::removeTab()
+{
+ tw->show();
+ QCOMPARE(tw->count(), 0);
+ RemoveTabObject ob(tw);
+ tw->addTab(new QLabel("1"), "1");
+ QCOMPARE(ob.count, 1);
+ tw->addTab(new QLabel("2"), "2");
+ tw->addTab(new QLabel("3"), "3");
+ tw->addTab(new QLabel("4"), "4");
+ tw->addTab(new QLabel("5"), "5");
+ QCOMPARE(ob.count, 1);
+ QCOMPARE(tw->count(), 5);
+
+ tw->setCurrentIndex(4);
+ QCOMPARE(ob.count,5);
+ tw->removeTab(4);
+ QCOMPARE(ob.count, 4);
+ QCOMPARE(tw->count(), 4);
+ QCOMPARE(tw->currentIndex(), 3);
+
+ tw->setCurrentIndex(1);
+ tw->removeTab(1);
+ QCOMPARE(ob.count, 3);
+ QCOMPARE(tw->count(), 3);
+ QCOMPARE(tw->currentIndex(), 1);
+
+ delete tw->widget(1);
+ QCOMPARE(tw->count(), 2);
+ QCOMPARE(ob.count, 2);
+ QCOMPARE(tw->currentIndex(), 1);
+ delete tw->widget(1);
+ QCOMPARE(tw->count(), 1);
+ QCOMPARE(ob.count, 1);
+ tw->removeTab(0);
+ QCOMPARE(tw->count(), 0);
+ QCOMPARE(ob.count, 0);
+}
+
+void tst_QTabWidget::clear()
+{
+ tw->addTab(new QWidget, "1");
+ tw->addTab(new QWidget, "2");
+ tw->addTab(new QWidget, "3");
+ tw->addTab(new QWidget, "4");
+ tw->addTab(new QWidget, "5");
+ tw->setCurrentIndex(4);
+ tw->clear();
+ QCOMPARE(tw->count(), 0);
+ QCOMPARE(tw->currentIndex(), -1);
+}
+
+void tst_QTabWidget::keyboardNavigation()
+{
+ int firstIndex = addPage();
+ addPage();
+ addPage();
+ tw->setCurrentIndex(firstIndex);
+ QCOMPARE(tw->currentIndex(), firstIndex);
+
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier);
+ QCOMPARE(tw->currentIndex(), 1);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier);
+ QCOMPARE(tw->currentIndex(), 2);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier);
+ QCOMPARE(tw->currentIndex(), 0);
+ tw->setTabEnabled(1, false);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier);
+ QCOMPARE(tw->currentIndex(), 2);
+
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier | Qt::ShiftModifier);
+ QCOMPARE(tw->currentIndex(), 0);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier | Qt::ShiftModifier);
+ QCOMPARE(tw->currentIndex(), 2);
+ tw->setTabEnabled(1, true);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier | Qt::ShiftModifier);
+ QCOMPARE(tw->currentIndex(), 1);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier | Qt::ShiftModifier);
+ QCOMPARE(tw->currentIndex(), 0);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier | Qt::ShiftModifier);
+ QCOMPARE(tw->currentIndex(), 2);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier);
+ QCOMPARE(tw->currentIndex(), 0);
+
+ // Disable all and try to go to the next. It should not move anywhere, and more importantly
+ // it should not loop forever. (a naive "search for the first enabled tabbar") implementation
+ // might do that)
+ tw->setTabEnabled(0, false);
+ tw->setTabEnabled(1, false);
+ tw->setTabEnabled(2, false);
+ QTest::keyClick(tw, Qt::Key_Tab, Qt::ControlModifier);
+ // TODO: Disabling the current tab will move current tab to the next,
+ // but what if next tab is also disabled. We should look into this.
+ QVERIFY(tw->currentIndex() < 3 && tw->currentIndex() >= 0);
+}
+
+class PaintCounter : public QWidget
+{
+public:
+ PaintCounter() :count(0) { setAttribute(Qt::WA_OpaquePaintEvent); }
+ int count;
+protected:
+ void paintEvent(QPaintEvent*) {
+ ++count;
+ }
+};
+
+
+void tst_QTabWidget::paintEventCount()
+{
+ Q_CHECK_PAINTEVENTS
+
+ PaintCounter *tab1 = new PaintCounter;
+ PaintCounter *tab2 = new PaintCounter;
+
+ tw->addTab(tab1, "one");
+ tw->addTab(tab2, "two");
+
+ QCOMPARE(tab1->count, 0);
+ QCOMPARE(tab2->count, 0);
+ QCOMPARE(tw->currentIndex(), 0);
+
+ tw->show();
+
+ QTest::qWait(1000);
+
+ // Mac, Windows and Windows CE get multiple repaints on the first show, so use those as a starting point.
+ static const int MaxInitialPaintCount =
+#if defined(Q_OS_WINCE)
+ 4;
+#elif defined(Q_WS_WIN)
+ 2;
+#elif defined(Q_WS_MAC)
+ 5;
+#else
+ 2;
+#endif
+ QVERIFY(tab1->count <= MaxInitialPaintCount);
+ QCOMPARE(tab2->count, 0);
+
+ const int initalPaintCount = tab1->count;
+
+ tw->setCurrentIndex(1);
+
+ QTest::qWait(100);
+
+ QCOMPARE(tab1->count, initalPaintCount);
+ QCOMPARE(tab2->count, 1);
+
+ tw->setCurrentIndex(0);
+
+ QTest::qWait(100);
+
+ QCOMPARE(tab1->count, initalPaintCount + 1);
+ QCOMPARE(tab2->count, 1);
+}
+
+void tst_QTabWidget::minimumSizeHint()
+{
+ QTabWidget tw;
+ QWidget *page = new QWidget;
+ QVBoxLayout *lay = new QVBoxLayout;
+
+ QLabel *label = new QLabel(QLatin1String("XXgypq lorem ipsum must be long, must be long. lorem ipsumMMMW"));
+ lay->addWidget(label);
+
+ page->setLayout(lay);
+
+ tw.addTab(page, QLatin1String("page1"));
+
+ tw.show();
+ QTest::qWaitForWindowShown(&tw);
+ tw.resize(tw.minimumSizeHint());
+
+ QSize minSize = label->minimumSizeHint();
+ QSize actSize = label->geometry().size();
+ QVERIFY(minSize.width() <= actSize.width());
+ QVERIFY(minSize.height() <= actSize.height());
+}
+
+void tst_QTabWidget::heightForWidth_data()
+{
+ QTest::addColumn<int>("tabPosition");
+ QTest::newRow("West") << int(QTabWidget::West);
+ QTest::newRow("North") << int(QTabWidget::North);
+ QTest::newRow("East") << int(QTabWidget::East);
+ QTest::newRow("South") << int(QTabWidget::South);
+}
+
+void tst_QTabWidget::heightForWidth()
+{
+ QFETCH(int, tabPosition);
+
+ QWidget *window = new QWidget;
+ QVBoxLayout *lay = new QVBoxLayout(window);
+ lay->setMargin(0);
+ lay->setSpacing(0);
+ QTabWidget *tabWid = new QTabWidget(window);
+ QWidget *w = new QWidget;
+ tabWid->addTab(w, QLatin1String("HFW page"));
+ tabWid->setTabPosition(QTabWidget::TabPosition(tabPosition));
+ QVBoxLayout *lay2 = new QVBoxLayout(w);
+ QLabel *label = new QLabel("Label with wordwrap turned on makes it trade height for width."
+ " Make it a really long text so that it spans on several lines"
+ " when the label is on its narrowest."
+ " I don't like to repeat myself."
+ " I don't like to repeat myself."
+ " I don't like to repeat myself."
+ " I don't like to repeat myself."
+ );
+ label->setWordWrap(true);
+ lay2->addWidget(label);
+ lay2->setMargin(0);
+
+ lay->addWidget(tabWid);
+ int h = window->heightForWidth(160);
+ window->resize(160, h);
+ window->show();
+
+ QTest::qWaitForWindowShown(window);
+ QVERIFY(label->height() >= label->heightForWidth(label->width()));
+
+ delete window;
+}
+
+
+QTEST_MAIN(tst_QTabWidget)
+#include "tst_qtabwidget.moc"
diff --git a/tests/auto/widgets/widgets/qtextbrowser/.gitignore b/tests/auto/widgets/widgets/qtextbrowser/.gitignore
new file mode 100644
index 0000000000..1ec6f00de1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/.gitignore
@@ -0,0 +1 @@
+tst_qtextbrowser
diff --git a/tests/auto/widgets/widgets/qtextbrowser/anchor.html b/tests/auto/widgets/widgets/qtextbrowser/anchor.html
new file mode 100644
index 0000000000..e347a2bb4c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/anchor.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<title>Sample Anchor</title>
+</head>
+<body>
+<p><a href="file.html#anchor">Click Me!</a></p>
+<p>
+<a name="jumphere"></a>Here's a destination to jump to.
+</p>
+</body>
+</html>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/bigpage.html b/tests/auto/widgets/widgets/qtextbrowser/bigpage.html
new file mode 100644
index 0000000000..125c7a096e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/bigpage.html
@@ -0,0 +1,934 @@
+<html><body>
+<p>
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+Blah blah blah blah blah blah blah blah blah
+</p>
+<p id="id-anchor">Paragraph with id</p>
+<a name="bottom"></a>Here's the bottom of the page.
+</body></html>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/firstpage.html b/tests/auto/widgets/widgets/qtextbrowser/firstpage.html
new file mode 100644
index 0000000000..fa35fce92c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/firstpage.html
@@ -0,0 +1,2 @@
+<p> Blah blah <a href="secondpage.html">Link to second page</a> blah
+<p> Another link here: <a href="thirdpage.html">Link to third page</a>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/pagewithbg.html b/tests/auto/widgets/widgets/qtextbrowser/pagewithbg.html
new file mode 100644
index 0000000000..07609a2b06
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/pagewithbg.html
@@ -0,0 +1 @@
+<html><title>Page With BG</title><body bgcolor="blue">This page has a blue background</body></html>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/pagewithimage.html b/tests/auto/widgets/widgets/qtextbrowser/pagewithimage.html
new file mode 100644
index 0000000000..49060d3792
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/pagewithimage.html
@@ -0,0 +1 @@
+<p><img src="foobar.png"/></p>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/pagewithoutbg.html b/tests/auto/widgets/widgets/qtextbrowser/pagewithoutbg.html
new file mode 100644
index 0000000000..5a7f9f592b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/pagewithoutbg.html
@@ -0,0 +1 @@
+<html><body>This page has no background color</body></html>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
new file mode 100644
index 0000000000..ae5177686b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
@@ -0,0 +1,15 @@
+load(qttest_p4)
+SOURCES += tst_qtextbrowser.cpp
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+QT += widgets
+
+wince* {
+ addFiles.files = *.html
+ addFiles.path = .
+ addDir.files = subdir/*
+ addDir.path = subdir
+ DEPLOYMENT += addFiles addDir
+}
+
+CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/widgets/qtextbrowser/secondpage.html b/tests/auto/widgets/widgets/qtextbrowser/secondpage.html
new file mode 100644
index 0000000000..39018a71b2
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/secondpage.html
@@ -0,0 +1 @@
+<p>blub blub <a href="thirdpage.html">Link to third page from second page</a>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/subdir/index.html b/tests/auto/widgets/widgets/qtextbrowser/subdir/index.html
new file mode 100644
index 0000000000..95593cc925
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/subdir/index.html
@@ -0,0 +1 @@
+This is a dummy, do not remove me!
diff --git a/tests/auto/widgets/widgets/qtextbrowser/thirdpage.html b/tests/auto/widgets/widgets/qtextbrowser/thirdpage.html
new file mode 100644
index 0000000000..215dc08aa0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/thirdpage.html
@@ -0,0 +1 @@
+<p>this is the third page...
diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
new file mode 100644
index 0000000000..a1592e5e2b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
@@ -0,0 +1,672 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qtextbrowser.h>
+#include <qdatetime.h>
+#include <qapplication.h>
+#include <qscrollbar.h>
+
+#include <qtextbrowser.h>
+#include <qtextobject.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class TestBrowser : public QTextBrowser
+{
+public:
+ inline TestBrowser() : htmlLoadAttempts(0) {
+ show();
+ QApplication::setActiveWindow(this);
+ QTest::qWaitForWindowShown(this);
+ activateWindow();
+ setFocus();
+ QTest::qWait(50);
+ QTRY_VERIFY(hasFocus());
+ }
+
+ virtual QVariant loadResource(int type, const QUrl &name);
+
+ int htmlLoadAttempts;
+ QUrl lastResource;
+ QUrl sourceInsideLoadResource;
+};
+
+QVariant TestBrowser::loadResource(int type, const QUrl &name)
+{
+ if (type == QTextDocument::HtmlResource)
+ htmlLoadAttempts++;
+ lastResource = name;
+ sourceInsideLoadResource = source();
+ return QTextBrowser::loadResource(type, name);
+}
+
+class tst_QTextBrowser : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QTextBrowser();
+ virtual ~tst_QTextBrowser();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void noReloadOnAnchorJump();
+ void bgColorOnSourceChange();
+ void forwardButton();
+ void viewportPositionInHistory();
+ void relativeLinks();
+ void anchors();
+ void resourceAutoDetection();
+ void forwardBackwardAvailable();
+ void clearHistory();
+ void sourceInsideLoadResource();
+ void textInteractionFlags_vs_readOnly();
+ void anchorsWithSelfBuiltHtml();
+ void relativeNonLocalUrls();
+ void adjacentAnchors();
+ void loadResourceOnRelativeLocalFiles();
+ void focusIndicator();
+ void focusHistory();
+ void urlEncoding();
+
+private:
+ TestBrowser *browser;
+};
+
+tst_QTextBrowser::tst_QTextBrowser()
+{
+}
+
+tst_QTextBrowser::~tst_QTextBrowser()
+{
+}
+void tst_QTextBrowser::init()
+{
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_WINCE)
+ QDir::setCurrent(SRCDIR);
+#endif
+ browser = new TestBrowser;
+ browser->show();
+}
+
+void tst_QTextBrowser::cleanup()
+{
+ delete browser;
+ browser = 0;
+}
+
+void tst_QTextBrowser::noReloadOnAnchorJump()
+{
+ QUrl url("anchor.html");
+
+ browser->htmlLoadAttempts = 0;
+ browser->setSource(url);
+ QCOMPARE(browser->htmlLoadAttempts, 1);
+ QVERIFY(!browser->toPlainText().isEmpty());
+
+ url.setFragment("jumphere"); // anchor.html#jumphere
+ browser->setSource(url);
+ QCOMPARE(browser->htmlLoadAttempts, 1);
+ QVERIFY(!browser->toPlainText().isEmpty());
+ QVERIFY(browser->source() == url);
+}
+
+void tst_QTextBrowser::bgColorOnSourceChange()
+{
+ browser->setSource(QUrl("pagewithbg.html"));
+ QVERIFY(browser->document()->rootFrame()->frameFormat().hasProperty(QTextFormat::BackgroundBrush));
+ QVERIFY(browser->document()->rootFrame()->frameFormat().background().color() == Qt::blue);
+
+ browser->setSource(QUrl("pagewithoutbg.html"));
+ QVERIFY(!browser->document()->rootFrame()->frameFormat().hasProperty(QTextFormat::BackgroundBrush));
+}
+
+void tst_QTextBrowser::forwardButton()
+{
+ QSignalSpy forwardEmissions(browser, SIGNAL(forwardAvailable(bool)));
+ QSignalSpy backwardEmissions(browser, SIGNAL(backwardAvailable(bool)));
+
+ QVERIFY(browser->historyTitle(-1).isEmpty());
+ QVERIFY(browser->historyTitle(0).isEmpty());
+ QVERIFY(browser->historyTitle(1).isEmpty());
+
+ browser->setSource(QUrl("pagewithbg.html"));
+
+ QVERIFY(!forwardEmissions.isEmpty());
+ QVariant val = forwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == false);
+
+ QVERIFY(!backwardEmissions.isEmpty());
+ val = backwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == false);
+
+ QVERIFY(browser->historyTitle(-1).isEmpty());
+ QCOMPARE(browser->historyUrl(0), QUrl("pagewithbg.html"));
+ QCOMPARE(browser->documentTitle(), QString("Page With BG"));
+ QCOMPARE(browser->historyTitle(0), QString("Page With BG"));
+ QVERIFY(browser->historyTitle(1).isEmpty());
+
+ browser->setSource(QUrl("anchor.html"));
+
+ QVERIFY(!forwardEmissions.isEmpty());
+ val = forwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == false);
+
+ QVERIFY(!backwardEmissions.isEmpty());
+ val = backwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == true);
+
+ QCOMPARE(browser->historyTitle(-1), QString("Page With BG"));
+ QCOMPARE(browser->historyTitle(0), QString("Sample Anchor"));
+ QVERIFY(browser->historyTitle(1).isEmpty());
+
+ browser->backward();
+
+ QVERIFY(!forwardEmissions.isEmpty());
+ val = forwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == true);
+
+ QVERIFY(!backwardEmissions.isEmpty());
+ val = backwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == false);
+
+ QVERIFY(browser->historyTitle(-1).isEmpty());
+ QCOMPARE(browser->historyTitle(0), QString("Page With BG"));
+ QCOMPARE(browser->historyTitle(1), QString("Sample Anchor"));
+
+ browser->setSource(QUrl("pagewithoutbg.html"));
+
+ QVERIFY(!forwardEmissions.isEmpty());
+ val = forwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == false);
+
+ QVERIFY(!backwardEmissions.isEmpty());
+ val = backwardEmissions.takeLast()[0];
+ QVERIFY(val.type() == QVariant::Bool);
+ QVERIFY(val.toBool() == true);
+}
+
+void tst_QTextBrowser::viewportPositionInHistory()
+{
+ browser->setSource(QUrl("bigpage.html"));
+ browser->scrollToAnchor("bottom");
+ QVERIFY(browser->verticalScrollBar()->value() > 0);
+
+ browser->setSource(QUrl("pagewithbg.html"));
+ QCOMPARE(browser->verticalScrollBar()->value(), 0);
+
+ browser->backward();
+ QVERIFY(browser->verticalScrollBar()->value() > 0);
+}
+
+void tst_QTextBrowser::relativeLinks()
+{
+ qRegisterMetaType<QUrl>("QUrl");
+ QSignalSpy sourceChangedSpy(browser, SIGNAL(sourceChanged(const QUrl &)));
+ browser->setSource(QUrl("../qtextbrowser.html"));
+ QVERIFY(sourceChangedSpy.count() == 1);
+ QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("../qtextbrowser.html"));
+ browser->setSource(QUrl("qtextbrowser/subdir/index.html"));
+ QVERIFY(sourceChangedSpy.count() == 1);
+ QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("qtextbrowser/subdir/index.html"));
+ browser->setSource(QUrl("../anchor.html"));
+ QVERIFY(sourceChangedSpy.count() == 1);
+ QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("../anchor.html"));
+ browser->setSource(QUrl("subdir/index.html"));
+ QVERIFY(sourceChangedSpy.count() == 1);
+ QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("subdir/index.html"));
+
+ // using QUrl::fromLocalFile()
+ browser->setSource(QUrl::fromLocalFile("anchor.html"));
+ QVERIFY(sourceChangedSpy.count() == 1);
+ QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("file:anchor.html"));
+ browser->setSource(QUrl("../qtextbrowser.html"));
+ QVERIFY(sourceChangedSpy.count() == 1);
+ QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("../qtextbrowser.html"));
+}
+
+void tst_QTextBrowser::anchors()
+{
+ browser->setSource(QUrl("bigpage.html"));
+ browser->setSource(QUrl("#bottom"));
+ QVERIFY(browser->verticalScrollBar()->value() > 0);
+
+ browser->setSource(QUrl("bigpage.html"));
+ browser->setSource(QUrl("#id-anchor"));
+ QVERIFY(browser->verticalScrollBar()->value() > 0);
+}
+
+void tst_QTextBrowser::resourceAutoDetection()
+{
+ browser->setHtml("<img src=\":/some/resource\"/>");
+ QCOMPARE(browser->lastResource.toString(), QString("qrc:/some/resource"));
+}
+
+void tst_QTextBrowser::forwardBackwardAvailable()
+{
+ QSignalSpy backwardSpy(browser, SIGNAL(backwardAvailable(bool)));
+ QSignalSpy forwardSpy(browser, SIGNAL(forwardAvailable(bool)));
+
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+
+ browser->setSource(QUrl("anchor.html"));
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(!backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->setSource(QUrl("bigpage.html"));
+ QVERIFY(browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->setSource(QUrl("pagewithbg.html"));
+ QVERIFY(browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->backward();
+ QVERIFY(browser->isBackwardAvailable());
+ QVERIFY(browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->backward();
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(!backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->forward();
+ QVERIFY(browser->isBackwardAvailable());
+ QVERIFY(browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->forward();
+ QVERIFY(browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+}
+
+void tst_QTextBrowser::clearHistory()
+{
+ QSignalSpy backwardSpy(browser, SIGNAL(backwardAvailable(bool)));
+ QSignalSpy forwardSpy(browser, SIGNAL(forwardAvailable(bool)));
+
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+
+ browser->clearHistory();
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(!backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+ QVERIFY(browser->historyTitle(-1).isEmpty());
+ QVERIFY(browser->historyTitle(0).isEmpty());
+ QVERIFY(browser->historyTitle(1).isEmpty());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->setSource(QUrl("anchor.html"));
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(!backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->setSource(QUrl("bigpage.html"));
+ QVERIFY(browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+
+ backwardSpy.clear();
+ forwardSpy.clear();
+
+ browser->clearHistory();
+ QVERIFY(!browser->isBackwardAvailable());
+ QVERIFY(!browser->isForwardAvailable());
+ QCOMPARE(backwardSpy.count(), 1);
+ QVERIFY(!backwardSpy.at(0).at(0).toBool());
+ QCOMPARE(forwardSpy.count(), 1);
+ QVERIFY(!forwardSpy.at(0).at(0).toBool());
+ QVERIFY(browser->historyTitle(-1).isEmpty());
+ QVERIFY(browser->historyTitle(1).isEmpty());
+
+ QCOMPARE(browser->source(), QUrl("bigpage.html"));
+ browser->backward();
+ QCOMPARE(browser->source(), QUrl("bigpage.html"));
+ browser->home();
+ QCOMPARE(browser->source(), QUrl("bigpage.html"));
+}
+
+void tst_QTextBrowser::sourceInsideLoadResource()
+{
+ QUrl url("pagewithimage.html");
+ browser->setSource(url);
+ QCOMPARE(browser->lastResource.toString(), QUrl::fromLocalFile(QDir::current().filePath("foobar.png")).toString());
+ QEXPECT_FAIL("", "This is currently not supported", Continue);
+ QCOMPARE(browser->sourceInsideLoadResource.toString(), url.toString());
+}
+
+void tst_QTextBrowser::textInteractionFlags_vs_readOnly()
+{
+ QVERIFY(browser->isReadOnly());
+ QVERIFY(browser->textInteractionFlags() == Qt::TextBrowserInteraction);
+ browser->setReadOnly(true);
+ QVERIFY(browser->textInteractionFlags() == Qt::TextBrowserInteraction);
+ browser->setReadOnly(false);
+ QVERIFY(browser->textInteractionFlags() == Qt::TextEditorInteraction);
+ browser->setReadOnly(true);
+ QVERIFY(browser->textInteractionFlags() == Qt::TextBrowserInteraction);
+}
+
+void tst_QTextBrowser::anchorsWithSelfBuiltHtml()
+{
+ browser->setHtml("<p>Hello <a href=\"#anchor\">Link</a>"
+ "<p><a name=\"anchor\"/>Blah</p>");
+ QVERIFY(browser->document()->blockCount() > 1);
+ browser->setSource(QUrl("#anchor"));
+ QVERIFY(browser->document()->blockCount() > 1);
+}
+
+class HelpBrowser : public QTextBrowser
+{
+public:
+ virtual QVariant loadResource(int /*type*/, const QUrl &name) {
+ QString url = name.toString();
+ if(url == "qhelp://docs/index.html") {
+ return "index";
+ } else if (url == "qhelp://docs/classes.html") {
+ return "classes";
+ } else if (url == "qhelp://docs/someclass.html") {
+ return "someclass";
+ }
+ return QVariant();
+ }
+};
+
+void tst_QTextBrowser::relativeNonLocalUrls()
+{
+ HelpBrowser browser;
+ browser.setSource(QUrl("qhelp://docs/index.html"));
+ QCOMPARE(browser.toPlainText(), QString("index"));
+ browser.setSource(QUrl("classes.html"));
+ QCOMPARE(browser.toPlainText(), QString("classes"));
+ browser.setSource(QUrl("someclass.html"));
+ QCOMPARE(browser.toPlainText(), QString("someclass"));
+}
+
+class HackBrowser : public TestBrowser
+{
+public:
+ inline bool focusTheNextChild() { return QTextBrowser::focusNextChild(); }
+ inline bool focusThePreviousChild() { return QTextBrowser::focusPreviousChild(); }
+};
+
+void tst_QTextBrowser::adjacentAnchors()
+{
+ HackBrowser *browser = new HackBrowser;
+ browser->setHtml("<a href=\"#foo\">foo</a><a href=\"#bar\">bar</a>");
+ QVERIFY(browser->focusTheNextChild());
+ QCOMPARE(browser->textCursor().selectedText(), QString("foo"));
+
+ QVERIFY(browser->focusTheNextChild());
+ QCOMPARE(browser->textCursor().selectedText(), QString("bar"));
+
+ QVERIFY(!browser->focusTheNextChild());
+
+ browser->moveCursor(QTextCursor::End);
+ QVERIFY(browser->focusThePreviousChild());
+ QCOMPARE(browser->textCursor().selectedText(), QString("bar"));
+ QVERIFY(browser->focusThePreviousChild());
+ QCOMPARE(browser->textCursor().selectedText(), QString("foo"));
+
+ delete browser;
+}
+
+void tst_QTextBrowser::loadResourceOnRelativeLocalFiles()
+{
+ browser->setSource(QUrl("subdir/index.html"));
+ QVERIFY(!browser->toPlainText().isEmpty());
+ QVariant v = browser->loadResource(QTextDocument::HtmlResource, QUrl("../anchor.html"));
+ QVERIFY(v.isValid());
+ QVERIFY(v.type() == QVariant::ByteArray);
+ QVERIFY(!v.toByteArray().isEmpty());
+}
+
+void tst_QTextBrowser::focusIndicator()
+{
+ HackBrowser *browser = new HackBrowser;
+ browser->setSource(QUrl("firstpage.html"));
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ browser->focusTheNextChild();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to second page"));
+
+#ifdef QT_KEYPAD_NAVIGATION
+ browser->setEditFocus(true);
+#endif
+ QTest::keyClick(browser, Qt::Key_Enter);
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ browser->focusTheNextChild();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page from second page"));
+
+ QTest::keyClick(browser, Qt::Key_Enter);
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ browser->backward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page from second page"));
+
+ browser->backward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to second page"));
+
+ browser->forward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page from second page"));
+
+ browser->backward();
+ browser->backward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to second page"));
+
+ QTest::keyClick(browser, Qt::Key_Enter);
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ delete browser;
+}
+
+void tst_QTextBrowser::focusHistory()
+{
+ HackBrowser *browser = new HackBrowser;
+ browser->setSource(QUrl("firstpage.html"));
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ browser->focusTheNextChild();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to second page"));
+
+#ifdef QT_KEYPAD_NAVIGATION
+ browser->setEditFocus(true);
+#endif
+ QTest::keyClick(browser, Qt::Key_Enter);
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ browser->focusTheNextChild();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page from second page"));
+
+ browser->backward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to second page"));
+
+ browser->focusTheNextChild();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page"));
+
+ // Despite the third page link being highlighted, going forward should go to second,
+ // and going back after that should still highlight the third link
+ browser->forward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page from second page"));
+
+ browser->backward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page"));
+
+ browser->forward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page from second page"));
+
+ QTest::keyClick(browser, Qt::Key_Enter);
+ QVERIFY(!browser->textCursor().hasSelection());
+
+ browser->backward();
+ browser->backward();
+
+ QVERIFY(browser->textCursor().hasSelection());
+ QCOMPARE(browser->textCursor().selectedText(), QString("Link to third page"));
+
+ delete browser;
+}
+
+void tst_QTextBrowser::urlEncoding()
+{
+ HackBrowser *browser = new HackBrowser;
+ browser->setOpenLinks(false);
+ browser->setHtml("<a href=\"http://www.google.com/q=%22\">link</a>");
+ browser->focusTheNextChild();
+
+ QSignalSpy spy(browser, SIGNAL(anchorClicked(const QUrl &)));
+
+#ifdef QT_KEYPAD_NAVIGATION
+ browser->setEditFocus(true);
+#endif
+ QTest::keyClick(browser, Qt::Key_Enter);
+ QCOMPARE(spy.count(), 1);
+
+ QUrl url = spy.at(0).at(0).toUrl();
+ QVERIFY(url.toEncoded() == QByteArray("http://www.google.com/q=%22"));
+
+ delete browser;
+}
+
+QTEST_MAIN(tst_QTextBrowser)
+#include "tst_qtextbrowser.moc"
diff --git a/tests/auto/widgets/widgets/qtextedit/.gitignore b/tests/auto/widgets/widgets/qtextedit/.gitignore
new file mode 100644
index 0000000000..8665a3a3d3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/.gitignore
@@ -0,0 +1,2 @@
+tst_qtextedit
+foo.png
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-fully-selected.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-fully-selected.png
new file mode 100644
index 0000000000..ced6eb6e5b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-fully-selected.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-partly-selected.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-partly-selected.png
new file mode 100644
index 0000000000..481b99c7fc
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-partly-selected.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-line.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-line.png
new file mode 100644
index 0000000000..292d3f9d4c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-line.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-parag.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-parag.png
new file mode 100644
index 0000000000..69b72ede09
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-parag.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/multiple-full-width-lines.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/multiple-full-width-lines.png
new file mode 100644
index 0000000000..467b91e6e0
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/multiple-full-width-lines.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/nowrap_long.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/nowrap_long.png
new file mode 100644
index 0000000000..cce921b0cc
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/nowrap_long.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/single-full-width-line.png b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/single-full-width-line.png
new file mode 100644
index 0000000000..937494ac3c
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/single-full-width-line.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qtextedit/qtextedit.pro b/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
new file mode 100644
index 0000000000..f29a2d2850
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+QT += widgets widgets-private gui-private
+INCLUDEPATH += ../
+
+HEADERS +=
+SOURCES += tst_qtextedit.cpp
+
+wince* {
+ addImages.files = fullWidthSelection/*
+ addImages.path = fullWidthSelection
+ DEPLOYMENT += addImages
+ DEFINES += SRCDIR=\\\"./\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
new file mode 100644
index 0000000000..481bda962a
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
@@ -0,0 +1,2391 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qtextedit.h>
+#include <qtextcursor.h>
+#include <qtextlist.h>
+#include <qdebug.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qtextbrowser.h>
+#include <private/qwidgettextcontrol_p.h>
+#include <qscrollbar.h>
+#include <qtextobject.h>
+#include <qtexttable.h>
+#include <qpainter.h>
+#include <qimagereader.h>
+#include <qimagewriter.h>
+#include <qcommonstyle.h>
+#include <qlayout.h>
+
+#include <qabstracttextdocumentlayout.h>
+#include <qtextdocumentfragment.h>
+
+//Used in copyAvailable
+typedef QPair<Qt::Key, Qt::KeyboardModifier> keyPairType;
+typedef QList<keyPairType> pairListType;
+Q_DECLARE_METATYPE(pairListType);
+Q_DECLARE_METATYPE(keyPairType);
+Q_DECLARE_METATYPE(QList<bool>);
+Q_DECLARE_METATYPE(QList<int>);
+
+#ifdef Q_WS_MAC
+#include <Carbon/Carbon.h>
+#endif
+
+bool nativeClipboardWorking()
+{
+#ifdef Q_WS_MAC
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ return status == noErr;
+#endif
+ return true;
+}
+
+
+QT_FORWARD_DECLARE_CLASS(QTextEdit)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTextEdit : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QTextEdit();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void inlineAttributesOnInsert();
+ void inlineAttributesOnSelection();
+ void inlineAttributeSymmetry();
+ void inlineAttributeSymmetryWithSelection();
+ void autoBulletList1();
+ void autoBulletList2();
+ void preserveCharFormatAfterNewline();
+#ifndef QT_NO_CLIPBOARD
+ void clearMustNotChangeClipboard();
+#endif
+ void clearMustNotResetRootFrameMarginToDefault();
+ void clearShouldPreserveTheCurrentCharFormat();
+ void clearShouldClearExtraSelections();
+ void paragSeparatorOnPlaintextAppend();
+ void layoutingLoop();
+#ifndef QT_NO_CLIPBOARD
+ void selectAllSetsNotSelection();
+#endif
+ void asciiTab();
+ void setDocument();
+ void setDocument_shared();
+ void mergeCurrentCharFormat();
+ void mergeCurrentBlockCharFormat();
+ void emptyAppend();
+ void appendOnEmptyDocumentShouldReuseInitialParagraph();
+ void cursorPositionChanged();
+ void setTextCursor();
+#ifndef QT_NO_CLIPBOARD
+ void undoAvailableAfterPaste();
+#endif
+ void undoRedoAvailableRepetition();
+ void appendShouldUseCurrentFormat();
+ void appendShouldNotTouchTheSelection();
+ void backspace();
+ void shiftBackspace();
+ void undoRedo();
+ void preserveCharFormatInAppend();
+#ifndef QT_NO_CLIPBOARD
+ void copyAndSelectAllInReadonly();
+#endif
+ void ctrlAltInput();
+ void noPropertiesOnDefaultTextEditCharFormat();
+ void setPlainTextShouldUseCurrentCharFormat();
+ void setPlainTextShouldEmitTextChangedOnce();
+ void overwriteMode();
+ void shiftDownInLineLastShouldSelectToEnd_data();
+ void shiftDownInLineLastShouldSelectToEnd();
+ void undoRedoShouldRepositionTextEditCursor();
+ void lineWrapModes();
+ void mouseCursorShape();
+ void implicitClear();
+ void undoRedoAfterSetContent();
+ void numPadKeyNavigation();
+ void moveCursor();
+#ifndef QT_NO_CLIPBOARD
+ void mimeDataReimplementations();
+#endif
+ void ctrlEnterShouldInsertLineSeparator_NOT();
+ void shiftEnterShouldInsertLineSeparator();
+ void selectWordsFromStringsContainingSeparators_data();
+ void selectWordsFromStringsContainingSeparators();
+#ifndef QT_NO_CLIPBOARD
+ void canPaste();
+ void copyAvailable_data();
+ void copyAvailable();
+#endif
+ void ensureCursorVisibleOnInitialShow();
+ void setHtmlInsideResizeEvent();
+ void colorfulAppend();
+ void ensureVisibleWithRtl();
+ void preserveCharFormatAfterSetPlainText();
+ void extraSelections();
+ void adjustScrollbars();
+ void currentCharFormatChanged();
+ void textObscuredByScrollbars();
+ void setTextPreservesUndoRedoEnabled();
+ void wordWrapProperty();
+ void lineWrapProperty();
+ void selectionChanged();
+ void copyPasteBackgroundImage();
+ void setText();
+ void fullWidthSelection_data();
+ void fullWidthSelection();
+ void fullWidthSelection2();
+ void cursorRect();
+ void setDocumentPreservesPalette();
+ void pasteFromQt3RichText();
+ void noWrapBackgrounds();
+ void preserveCharFormatAfterUnchangingSetPosition();
+ void twoSameInputMethodEvents();
+#ifndef QT_NO_CONTEXTMENU
+ void taskQTBUG_7902_contextMenuCrash();
+#endif
+ void bidiVisualMovement_data();
+ void bidiVisualMovement();
+
+ void bidiLogicalMovement_data();
+ void bidiLogicalMovement();
+
+ void inputMethodSelection();
+
+private:
+ void createSelection();
+ int blockCount() const;
+ bool nativeClipboardWorking();
+ void compareWidgetAndImage(QTextEdit &widget, const QString &imageFileName);
+
+ QTextEdit *ed;
+ qreal rootFrameMargin;
+};
+
+bool tst_QTextEdit::nativeClipboardWorking()
+{
+#ifdef Q_WS_MAC
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ return status == noErr;
+#endif
+ return true;
+}
+
+// Testing get/set functions
+void tst_QTextEdit::getSetCheck()
+{
+ QTextEdit obj1;
+ // QTextDocument * QTextEdit::document()
+ // void QTextEdit::setDocument(QTextDocument *)
+ QTextDocument *var1 = new QTextDocument;
+ obj1.setDocument(var1);
+ QCOMPARE(var1, obj1.document());
+ obj1.setDocument((QTextDocument *)0);
+ QVERIFY(var1 != obj1.document()); // QTextEdit creates a new document when setting 0
+ QVERIFY((QTextDocument *)0 != obj1.document());
+ delete var1;
+
+ // AutoFormatting QTextEdit::autoFormatting()
+ // void QTextEdit::setAutoFormatting(AutoFormatting)
+ obj1.setAutoFormatting(QTextEdit::AutoFormatting(QTextEdit::AutoNone));
+ QCOMPARE(QTextEdit::AutoFormatting(QTextEdit::AutoNone), obj1.autoFormatting());
+ obj1.setAutoFormatting(QTextEdit::AutoFormatting(QTextEdit::AutoBulletList));
+ QCOMPARE(QTextEdit::AutoFormatting(QTextEdit::AutoBulletList), obj1.autoFormatting());
+ obj1.setAutoFormatting(QTextEdit::AutoFormatting(QTextEdit::AutoAll));
+ QCOMPARE(QTextEdit::AutoFormatting(QTextEdit::AutoAll), obj1.autoFormatting());
+
+ // bool QTextEdit::tabChangesFocus()
+ // void QTextEdit::setTabChangesFocus(bool)
+ obj1.setTabChangesFocus(false);
+ QCOMPARE(false, obj1.tabChangesFocus());
+ obj1.setTabChangesFocus(true);
+ QCOMPARE(true, obj1.tabChangesFocus());
+
+ // LineWrapMode QTextEdit::lineWrapMode()
+ // void QTextEdit::setLineWrapMode(LineWrapMode)
+ obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::NoWrap));
+ QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::NoWrap), obj1.lineWrapMode());
+ obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::WidgetWidth));
+ QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::WidgetWidth), obj1.lineWrapMode());
+ obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::FixedPixelWidth));
+ QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::FixedPixelWidth), obj1.lineWrapMode());
+ obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::FixedColumnWidth));
+ QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::FixedColumnWidth), obj1.lineWrapMode());
+
+ // int QTextEdit::lineWrapColumnOrWidth()
+ // void QTextEdit::setLineWrapColumnOrWidth(int)
+ obj1.setLineWrapColumnOrWidth(0);
+ QCOMPARE(0, obj1.lineWrapColumnOrWidth());
+ obj1.setLineWrapColumnOrWidth(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.lineWrapColumnOrWidth());
+ obj1.setLineWrapColumnOrWidth(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.lineWrapColumnOrWidth());
+
+ // bool QTextEdit::overwriteMode()
+ // void QTextEdit::setOverwriteMode(bool)
+ obj1.setOverwriteMode(false);
+ QCOMPARE(false, obj1.overwriteMode());
+ obj1.setOverwriteMode(true);
+ QCOMPARE(true, obj1.overwriteMode());
+
+ // int QTextEdit::tabStopWidth()
+ // void QTextEdit::setTabStopWidth(int)
+ obj1.setTabStopWidth(0);
+ QCOMPARE(0, obj1.tabStopWidth());
+ obj1.setTabStopWidth(INT_MIN);
+ QCOMPARE(0, obj1.tabStopWidth()); // Makes no sense to set a negative tabstop value
+#if defined(QT_ARCH_WINDOWSCE)
+ // due to rounding error in qRound when qreal==float
+ // we cannot use INT_MAX for this check
+ obj1.setTabStopWidth(SHRT_MAX*2);
+ QCOMPARE(SHRT_MAX*2, obj1.tabStopWidth());
+#else
+ obj1.setTabStopWidth(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.tabStopWidth());
+#endif
+
+ // bool QTextEdit::acceptRichText()
+ // void QTextEdit::setAcceptRichText(bool)
+ obj1.setAcceptRichText(false);
+ QCOMPARE(false, obj1.acceptRichText());
+ obj1.setAcceptRichText(true);
+ QCOMPARE(true, obj1.acceptRichText());
+
+ // qreal QTextEdit::fontPointSize()
+ // void QTextEdit::setFontPointSize(qreal)
+ obj1.setFontPointSize(qreal(1.1));
+ QCOMPARE(qreal(1.1), obj1.fontPointSize());
+ // we currently assert in QFont::setPointSizeF for that
+ //obj1.setFontPointSize(0.0);
+ //QCOMPARE(1.1, obj1.fontPointSize()); // Should not accept 0.0 => keep old
+
+ // int QTextEdit::fontWeight()
+ // void QTextEdit::setFontWeight(int)
+ obj1.setFontWeight(1);
+ QCOMPARE(1, obj1.fontWeight()); // Range<1, 99>
+ obj1.setFontWeight(99);
+ QCOMPARE(99, obj1.fontWeight()); // Range<1, 99>
+ /* assertion in qfont.cpp
+ obj1.setFontWeight(INT_MIN);
+ QCOMPARE(1, obj1.fontWeight()); // Range<1, 99>
+ obj1.setFontWeight(INT_MAX);
+ QCOMPARE(99, obj1.fontWeight()); // Range<1, 99>
+ */
+
+ // bool QTextEdit::fontUnderline()
+ // void QTextEdit::setFontUnderline(bool)
+ obj1.setFontUnderline(false);
+ QCOMPARE(false, obj1.fontUnderline());
+ obj1.setFontUnderline(true);
+ QCOMPARE(true, obj1.fontUnderline());
+
+ // bool QTextEdit::fontItalic()
+ // void QTextEdit::setFontItalic(bool)
+ obj1.setFontItalic(false);
+ QCOMPARE(false, obj1.fontItalic());
+ obj1.setFontItalic(true);
+ QCOMPARE(true, obj1.fontItalic());
+}
+
+class QtTestDocumentLayout : public QAbstractTextDocumentLayout
+{
+ Q_OBJECT
+public:
+ inline QtTestDocumentLayout(QTextEdit *edit, QTextDocument *doc, int &itCount)
+ : QAbstractTextDocumentLayout(doc), useBiggerSize(false), ed(edit), iterationCounter(itCount) {}
+
+ virtual void draw(QPainter *, const QAbstractTextDocumentLayout::PaintContext &) {}
+
+ virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const { return 0; }
+
+ virtual void documentChanged(int, int, int) {}
+
+ virtual int pageCount() const { return 1; }
+
+ virtual QSizeF documentSize() const { return usedSize; }
+
+ virtual QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
+ virtual QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
+
+ bool useBiggerSize;
+ QSize usedSize;
+
+ QTextEdit *ed;
+
+ int &iterationCounter;
+};
+
+tst_QTextEdit::tst_QTextEdit()
+{}
+
+void tst_QTextEdit::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+
+ ed = new QTextEdit(0);
+ rootFrameMargin = ed->document()->documentMargin();
+}
+
+void tst_QTextEdit::cleanup()
+{
+ delete ed;
+ ed = 0;
+}
+
+void tst_QTextEdit::inlineAttributesOnInsert()
+{
+ QVERIFY(ed->textCursor().charFormat().foreground().color() != Qt::blue);
+
+ ed->setTextColor(Qt::blue);
+ QTest::keyClick(ed, Qt::Key_A);
+
+ QVERIFY(ed->textCursor().charFormat().foreground().color() == Qt::blue);
+}
+
+void tst_QTextEdit::inlineAttributesOnSelection()
+{
+ createSelection();
+
+ ed->setFontItalic(true);
+
+ QVERIFY(ed->textCursor().charFormat().fontItalic());
+}
+
+void tst_QTextEdit::inlineAttributeSymmetry()
+{
+ ed->setFontPointSize(42.0);
+ QCOMPARE(double(ed->fontPointSize()), 42.0);
+
+ ed->setFontFamily("Test");
+ QCOMPARE(ed->fontFamily(), QString("Test"));
+
+ ed->setFontWeight(QFont::Bold);
+ QCOMPARE((int)ed->fontWeight(), (int)QFont::Bold);
+
+ ed->setFontUnderline(true);
+ QCOMPARE(ed->fontUnderline(), true);
+
+ ed->setFontItalic(true);
+ QCOMPARE(ed->fontItalic(), true);
+
+ ed->setTextColor(Qt::blue);
+ QCOMPARE(ed->textColor(), QColor(Qt::blue));
+
+ ed->setTextBackgroundColor(Qt::red);
+ QCOMPARE(ed->textBackgroundColor(), QColor(Qt::red));
+
+ ed->setAlignment(Qt::AlignRight);
+ QCOMPARE((int)ed->alignment(), (int)Qt::AlignRight);
+}
+
+void tst_QTextEdit::inlineAttributeSymmetryWithSelection()
+{
+ createSelection();
+
+ inlineAttributeSymmetry();
+}
+
+void tst_QTextEdit::autoBulletList1()
+{
+ ed->setAutoFormatting(QTextEdit::AutoBulletList);
+
+ QTest::keyClick(ed, Qt::Key_Return);
+ QTest::keyClicks(ed, "*This should become a list");
+
+ QVERIFY(ed->textCursor().currentList());
+ QVERIFY(ed->textCursor().currentList()->format().style() == QTextListFormat::ListDisc);
+}
+
+void tst_QTextEdit::autoBulletList2()
+{
+ ed->setAutoFormatting(QTextEdit::AutoNone);
+ QTest::keyClick(ed, Qt::Key_Return);
+ QTest::keyClicks(ed, "*This should NOT become a list");
+
+ QVERIFY(!ed->textCursor().currentList());
+}
+
+void tst_QTextEdit::preserveCharFormatAfterNewline()
+{
+ ed->setTextColor(Qt::blue);
+ QTest::keyClicks(ed, "Hello");
+
+ QTest::keyClick(ed, Qt::Key_Return);
+
+ QCOMPARE(ed->textColor(), QColor(Qt::blue));
+}
+
+void tst_QTextEdit::createSelection()
+{
+ QTest::keyClicks(ed, "Hello World");
+ /* go to start */
+#ifndef Q_WS_MAC
+ QTest::keyClick(ed, Qt::Key_Home, Qt::ControlModifier);
+#else
+ QTest::keyClick(ed, Qt::Key_Home);
+#endif
+ QCOMPARE(ed->textCursor().position(), 0);
+ /* select until end of text */
+#ifndef Q_WS_MAC
+ QTest::keyClick(ed, Qt::Key_End, Qt::ControlModifier | Qt::ShiftModifier);
+#else
+ QTest::keyClick(ed, Qt::Key_End, Qt::ShiftModifier);
+#endif
+ QCOMPARE(ed->textCursor().position(), 11);
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::clearMustNotChangeClipboard()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+ ed->textCursor().insertText("Hello World");
+ QString txt("This is different text");
+ QApplication::clipboard()->setText(txt);
+ ed->clear();
+ QCOMPARE(QApplication::clipboard()->text(), txt);
+}
+#endif
+
+void tst_QTextEdit::clearMustNotResetRootFrameMarginToDefault()
+{
+ QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
+ ed->clear();
+ QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
+}
+
+void tst_QTextEdit::clearShouldPreserveTheCurrentCharFormat()
+{
+ ed->setFontUnderline(true);
+ QVERIFY(ed->fontUnderline());
+ ed->clear();
+ QVERIFY(ed->fontUnderline());
+}
+
+void tst_QTextEdit::clearShouldClearExtraSelections()
+{
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = ed->textCursor();
+ sel.format.setProperty(QTextFormat::FullWidthSelection, true);
+ ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
+ QCOMPARE(ed->extraSelections().count(), 1);
+ ed->clear();
+ QCOMPARE(ed->extraSelections().count(), 0);
+}
+
+void tst_QTextEdit::paragSeparatorOnPlaintextAppend()
+{
+ ed->append("Hello\nWorld");
+ int cnt = 0;
+ QTextBlock blk = ed->document()->begin();
+ while (blk.isValid()) {
+ ++cnt;
+ blk = blk.next();
+ }
+ QCOMPARE(cnt, 2);
+}
+
+void tst_QTextEdit::layoutingLoop()
+{
+ QPointer<QTextEdit> ed = new QTextEdit(0);
+ // this is a testcase for an ugly layouting problem, causing an infinite loop.
+ // QTextEdit's resizeEvent has a long comment about what and why it can happen.
+
+ int callsToSetPageSize = 0;
+
+ QTextDocument *doc = new QTextDocument;
+ QtTestDocumentLayout *lout = new QtTestDocumentLayout(ed, doc, callsToSetPageSize);
+ doc->setDocumentLayout(lout);
+ ed->setDocument(doc);
+
+ ed->show();
+ ed->resize(100, 100);
+
+ qApp->processEvents();
+ delete doc;
+ delete ed;
+
+ // ###### should need less!
+ QVERIFY(callsToSetPageSize < 10);
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::selectAllSetsNotSelection()
+{
+ if (!QApplication::clipboard()->supportsSelection()) {
+ QSKIP("Test only relevant for systems with selection", SkipAll);
+ return;
+ }
+
+ QApplication::clipboard()->setText(QString("foobar"), QClipboard::Selection);
+ QVERIFY(QApplication::clipboard()->text(QClipboard::Selection) == QString("foobar"));
+
+ ed->insertPlainText("Hello World");
+ ed->selectAll();
+
+ QCOMPARE(QApplication::clipboard()->text(QClipboard::Selection), QString::fromAscii("foobar"));
+}
+#endif
+void tst_QTextEdit::asciiTab()
+{
+ QTextEdit edit;
+ edit.setPlainText("\t");
+ edit.show();
+ qApp->processEvents();
+ QCOMPARE(edit.toPlainText().at(0), QChar('\t'));
+}
+
+
+void tst_QTextEdit::setDocument()
+{
+ QTextDocument *document = new QTextDocument(ed);
+ QCOMPARE(document->isModified(), false);
+ QCOMPARE(document->isUndoAvailable(), false);
+ QTextCursor(document).insertText("Test");
+ QCOMPARE(document->isUndoAvailable(), true);
+ QCOMPARE(document->isModified(), true);
+ ed->setDocument(document);
+ QCOMPARE(ed->toPlainText(), QString("Test"));
+ QCOMPARE(document->isUndoAvailable(), true);
+ QCOMPARE(document->isModified(), true);
+}
+
+void tst_QTextEdit::setDocument_shared()
+{
+ QTextDocument *document = new QTextDocument(ed);
+ QCOMPARE(document->isModified(), false);
+ QCOMPARE(document->isUndoAvailable(), false);
+ QTextCursor(document).insertText("Test");
+ QCOMPARE(document->isUndoAvailable(), true);
+ document->setModified(false);
+ ed->setDocument(document);
+ QCOMPARE(ed->toPlainText(), QString("Test"));
+ QCOMPARE(document->isUndoAvailable(), true);
+ QCOMPARE(document->isModified(), false);
+ QTextCursor(document).insertText("Test2");
+ QCOMPARE(document->isModified(), true);
+ QTextEdit editor2;
+ editor2.setDocument(document);
+ QCOMPARE(document->isUndoAvailable(), true);
+ QCOMPARE(document->isModified(), true);
+}
+
+void tst_QTextEdit::mergeCurrentCharFormat()
+{
+ ed->setPlainText("Hello Test World");
+ QTextCursor cursor = ed->textCursor();
+ cursor.setPosition(7);
+ ed->setTextCursor(cursor);
+
+ QTextCharFormat mod;
+ mod.setFontItalic(true);
+ mod.setForeground(Qt::red);
+ ed->mergeCurrentCharFormat(mod);
+
+ cursor.movePosition(QTextCursor::Right);
+ cursor.movePosition(QTextCursor::Right);
+ // do NOT select the current word under the cursor, /JUST/
+ // call mergeCharFormat on the cursor
+ QVERIFY(!cursor.charFormat().fontItalic());
+ QVERIFY(cursor.charFormat().foreground().color() != Qt::red);
+}
+
+void tst_QTextEdit::mergeCurrentBlockCharFormat()
+{
+ ed->setPlainText("FirstLine\n\nThirdLine");
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::Down);
+
+ // make sure we're in the empty second line
+ QVERIFY(cursor.atBlockStart());
+ QVERIFY(cursor.atBlockEnd());
+
+ ed->setTextCursor(cursor);
+
+ QTextCharFormat mod;
+ mod.setForeground(Qt::red);
+ ed->mergeCurrentCharFormat(mod);
+
+ QVERIFY(cursor.blockCharFormat().foreground().color() != Qt::red);
+ cursor.movePosition(QTextCursor::Up);
+ QVERIFY(cursor.blockCharFormat().foreground().color() != Qt::red);
+ cursor.movePosition(QTextCursor::Down);
+ cursor.movePosition(QTextCursor::Down);
+ QVERIFY(cursor.blockCharFormat().foreground().color() != Qt::red);
+}
+
+int tst_QTextEdit::blockCount() const
+{
+ int blocks = 0;
+ for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
+ ++blocks;
+ return blocks;
+}
+
+// Supporter issue #56783
+void tst_QTextEdit::emptyAppend()
+{
+ ed->append("Blah");
+ QCOMPARE(blockCount(), 1);
+ ed->append(QString::null);
+ QCOMPARE(blockCount(), 2);
+ ed->append(QString(" "));
+ QCOMPARE(blockCount(), 3);
+}
+
+void tst_QTextEdit::appendOnEmptyDocumentShouldReuseInitialParagraph()
+{
+ QCOMPARE(blockCount(), 1);
+ ed->append("Blah");
+ QCOMPARE(blockCount(), 1);
+}
+
+class CursorPositionChangedRecorder : public QObject
+{
+ Q_OBJECT
+public:
+ inline CursorPositionChangedRecorder(QTextEdit *ed)
+ : editor(ed)
+ {
+ connect(editor, SIGNAL(cursorPositionChanged()), this, SLOT(recordCursorPos()));
+ }
+
+ QList<int> cursorPositions;
+
+private slots:
+ void recordCursorPos()
+ {
+ cursorPositions.append(editor->textCursor().position());
+ }
+
+private:
+ QTextEdit *editor;
+};
+
+void tst_QTextEdit::cursorPositionChanged()
+{
+ QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
+ ed->show();
+
+ spy.clear();
+ QTest::keyClick(ed, Qt::Key_A);
+ QCOMPARE(spy.count(), 1);
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+ cursor.movePosition(QTextCursor::End);
+ spy.clear();
+ cursor.insertText("Test");
+ QCOMPARE(spy.count(), 0);
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+ cursor.movePosition(QTextCursor::Start);
+ spy.clear();
+ cursor.insertText("Test");
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ QTest::keyClick(ed, Qt::Key_Left);
+ QCOMPARE(spy.count(), 1);
+
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+ spy.clear();
+ QVERIFY(!ed->textCursor().hasSelection());
+ QTest::mouseDClick(ed->viewport(), Qt::LeftButton, 0, ed->cursorRect().center());
+ QVERIFY(ed->textCursor().hasSelection());
+
+ QCOMPARE(spy.count(), 1);
+
+ CursorPositionChangedRecorder spy2(ed);
+ QVERIFY(ed->textCursor().position() > 0);
+ ed->setPlainText("Hello World");
+ QCOMPARE(spy2.cursorPositions.count(), 1);
+ QCOMPARE(spy2.cursorPositions.at(0), 0);
+ QCOMPARE(ed->textCursor().position(), 0);
+}
+
+void tst_QTextEdit::setTextCursor()
+{
+ QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
+
+ ed->setPlainText("Test");
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+
+ spy.clear();
+
+ ed->setTextCursor(cursor);
+ QCOMPARE(spy.count(), 1);
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::undoAvailableAfterPaste()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+
+ QSignalSpy spy(ed->document(), SIGNAL(undoAvailable(bool)));
+
+ const QString txt("Test");
+ QApplication::clipboard()->setText(txt);
+ ed->paste();
+ QVERIFY(spy.count() >= 1);
+ QCOMPARE(ed->toPlainText(), txt);
+}
+#endif
+
+class UndoRedoRecorder : public QObject
+{
+ Q_OBJECT
+public:
+ UndoRedoRecorder(QTextDocument *doc)
+ : undoRepetitions(false)
+ , redoRepetitions(false)
+ , undoCount(0)
+ , redoCount(0)
+ {
+ connect(doc, SIGNAL(undoAvailable(bool)), this, SLOT(undoAvailable(bool)));
+ connect(doc, SIGNAL(redoAvailable(bool)), this, SLOT(redoAvailable(bool)));
+ }
+
+ bool undoRepetitions;
+ bool redoRepetitions;
+
+private slots:
+ void undoAvailable(bool enabled) {
+ if (undoCount > 0 && enabled == lastUndoEnabled)
+ undoRepetitions = true;
+
+ ++undoCount;
+ lastUndoEnabled = enabled;
+ }
+
+ void redoAvailable(bool enabled) {
+ if (redoCount > 0 && enabled == lastRedoEnabled)
+ redoRepetitions = true;
+
+ ++redoCount;
+ lastRedoEnabled = enabled;
+ }
+
+private:
+ bool lastUndoEnabled;
+ bool lastRedoEnabled;
+
+ int undoCount;
+ int redoCount;
+};
+
+void tst_QTextEdit::undoRedoAvailableRepetition()
+{
+ UndoRedoRecorder spy(ed->document());
+
+ ed->textCursor().insertText("ABC\n\nDEF\n\nGHI\n");
+ ed->textCursor().insertText("foo\n");
+ ed->textCursor().insertText("bar\n");
+ ed->undo(); ed->undo(); ed->undo();
+ ed->redo(); ed->redo(); ed->redo();
+
+ QVERIFY(!spy.undoRepetitions);
+ QVERIFY(!spy.redoRepetitions);
+}
+
+void tst_QTextEdit::appendShouldUseCurrentFormat()
+{
+ ed->textCursor().insertText("A");
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ fmt.setFontItalic(true);
+ ed->setCurrentCharFormat(fmt);
+ ed->append("Hello");
+
+ QTextCursor cursor(ed->document());
+
+ QVERIFY(cursor.movePosition(QTextCursor::NextCharacter));
+ QVERIFY(cursor.charFormat().foreground().color() != Qt::blue);
+ QVERIFY(!cursor.charFormat().fontItalic());
+
+ QVERIFY(cursor.movePosition(QTextCursor::NextBlock));
+
+ {
+ QTextCursor tmp = cursor;
+ tmp.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ QCOMPARE(tmp.selectedText(), QString::fromLatin1("Hello"));
+ }
+
+ QVERIFY(cursor.movePosition(QTextCursor::NextCharacter));
+ QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
+ QVERIFY(cursor.charFormat().fontItalic());
+}
+
+void tst_QTextEdit::appendShouldNotTouchTheSelection()
+{
+ QTextCursor cursor(ed->document());
+ QTextCharFormat fmt;
+ fmt.setForeground(Qt::blue);
+ cursor.insertText("H", fmt);
+ fmt.setForeground(Qt::red);
+ cursor.insertText("ey", fmt);
+
+ cursor.insertText("some random text inbetween");
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
+ QCOMPARE(cursor.selectedText(), QString("Hey"));
+
+ ed->setTextCursor(cursor);
+ QVERIFY(ed->textCursor().hasSelection());
+
+ ed->append("<b>Some Bold Text</b>");
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
+}
+
+void tst_QTextEdit::backspace()
+{
+ QTextCursor cursor = ed->textCursor();
+
+ QTextListFormat listFmt;
+ listFmt.setStyle(QTextListFormat::ListDisc);
+ listFmt.setIndent(1);
+ cursor.insertList(listFmt);
+ cursor.insertText("A");
+
+ ed->setTextCursor(cursor);
+
+ // delete 'A'
+ QTest::keyClick(ed, Qt::Key_Backspace);
+ QVERIFY(ed->textCursor().currentList());
+ // delete list
+ QTest::keyClick(ed, Qt::Key_Backspace);
+ QVERIFY(!ed->textCursor().currentList());
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
+ // outdent paragraph
+ QTest::keyClick(ed, Qt::Key_Backspace);
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
+}
+
+void tst_QTextEdit::shiftBackspace()
+{
+ QTextCursor cursor = ed->textCursor();
+
+ QTextListFormat listFmt;
+ listFmt.setStyle(QTextListFormat::ListDisc);
+ listFmt.setIndent(1);
+ cursor.insertList(listFmt);
+ cursor.insertText("A");
+
+ ed->setTextCursor(cursor);
+
+ // delete 'A'
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
+ QVERIFY(ed->textCursor().currentList());
+ // delete list
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
+ QVERIFY(!ed->textCursor().currentList());
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
+ // outdent paragraph
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
+}
+
+void tst_QTextEdit::undoRedo()
+{
+ ed->clear();
+ QTest::keyClicks(ed, "abc d");
+ QCOMPARE(ed->toPlainText(), QString("abc d"));
+ ed->undo();
+ QCOMPARE(ed->toPlainText(), QString());
+ ed->redo();
+ QCOMPARE(ed->toPlainText(), QString("abc d"));
+#ifdef Q_WS_WIN
+ // shortcut for undo
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::AltModifier);
+ QCOMPARE(ed->toPlainText(), QString());
+ // shortcut for redo
+ QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier|Qt::AltModifier);
+ QCOMPARE(ed->toPlainText(), QString("abc d"));
+#endif
+}
+
+// Task #70465
+void tst_QTextEdit::preserveCharFormatInAppend()
+{
+ ed->append("First para");
+ ed->append("<b>Second para</b>");
+ ed->append("third para");
+
+ QTextCursor cursor(ed->textCursor());
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
+ QCOMPARE(cursor.block().text(), QString("First para"));
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Bold);
+ QCOMPARE(cursor.block().text(), QString("Second para"));
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
+ QCOMPARE(cursor.block().text(), QString("third para"));
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::copyAndSelectAllInReadonly()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+
+ ed->setReadOnly(true);
+ ed->setPlainText("Hello World");
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.clearSelection();
+ ed->setTextCursor(cursor);
+ QVERIFY(!ed->textCursor().hasSelection());
+
+ QCOMPARE(ed->toPlainText(), QString("Hello World"));
+
+ // shouldn't do anything
+ QTest::keyClick(ed, Qt::Key_A);
+
+ QCOMPARE(ed->toPlainText(), QString("Hello World"));
+
+ QTest::keyClick(ed, Qt::Key_A, Qt::ControlModifier);
+
+ QVERIFY(ed->textCursor().hasSelection());
+
+ QApplication::clipboard()->setText(QString());
+ QVERIFY(QApplication::clipboard()->text().isEmpty());
+
+ QTest::keyClick(ed, Qt::Key_C, Qt::ControlModifier);
+ QCOMPARE(QApplication::clipboard()->text(), QString("Hello World"));
+}
+#endif
+
+void tst_QTextEdit::ctrlAltInput()
+{
+ QTest::keyClick(ed, Qt::Key_At, Qt::ControlModifier | Qt::AltModifier);
+ QCOMPARE(ed->toPlainText(), QString("@"));
+}
+
+void tst_QTextEdit::noPropertiesOnDefaultTextEditCharFormat()
+{
+ // there should be no properties set on the default/initial char format
+ // on a text edit. Font properties instead should be taken from the
+ // widget's font (in sync with defaultFont property in document) and the
+ // foreground color should be taken from the palette.
+ QCOMPARE(ed->currentCharFormat().properties().count(), 0);
+}
+
+void tst_QTextEdit::setPlainTextShouldUseCurrentCharFormat()
+{
+ ed->setFontUnderline(true);
+ ed->setPlainText("Hello World");
+ QTextCursor cursor(ed->document());
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontUnderline(), true);
+
+ ed->setHtml("<p style=\"color:blue\">Foo</p>");
+ ed->setPlainText("Hello World");
+ cursor = QTextCursor(ed->document());
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().fontUnderline(), true);
+}
+
+void tst_QTextEdit::setPlainTextShouldEmitTextChangedOnce()
+{
+ QSignalSpy spy(ed, SIGNAL(textChanged()));
+ ed->setPlainText("Yankee Doodle");
+ QCOMPARE(spy.count(), 1);
+ ed->setPlainText("");
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QTextEdit::overwriteMode()
+{
+ QVERIFY(!ed->overwriteMode());
+ QTest::keyClicks(ed, "Some first text");
+
+ QCOMPARE(ed->toPlainText(), QString("Some first text"));
+
+ ed->setOverwriteMode(true);
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.setPosition(5);
+ ed->setTextCursor(cursor);
+
+ QTest::keyClicks(ed, "shiny");
+ QCOMPARE(ed->toPlainText(), QString("Some shiny text"));
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+
+ QTest::keyClick(ed, Qt::Key_Enter);
+
+ ed->setOverwriteMode(false);
+ QTest::keyClicks(ed, "Second paragraph");
+
+ QCOMPARE(blockCount(), 2);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::EndOfBlock);
+
+ QCOMPARE(cursor.position(), 15);
+ ed->setTextCursor(cursor);
+
+ ed->setOverwriteMode(true);
+
+ QTest::keyClicks(ed, " blah");
+
+ QCOMPARE(blockCount(), 2);
+
+ QTextBlock block = ed->document()->begin();
+ QCOMPARE(block.text(), QString("Some shiny text blah"));
+ block = block.next();
+ QCOMPARE(block.text(), QString("Second paragraph"));
+}
+
+void tst_QTextEdit::shiftDownInLineLastShouldSelectToEnd_data()
+{
+ // shift cursor-down in the last line should select to the end of the document
+
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<int>("totalLineCount");
+
+ QTest::newRow("1") << QString("Foo\nBar") << 2;
+ QTest::newRow("2") << QString("Foo\nBar") + QChar(QChar::LineSeparator) + QString("Baz") << 3;
+}
+
+void tst_QTextEdit::shiftDownInLineLastShouldSelectToEnd()
+{
+ QFETCH(QString, input);
+ QFETCH(int, totalLineCount);
+
+ ed->setPlainText(input);
+ ed->show();
+
+ // ensure we're layouted
+ ed->document()->documentLayout()->documentSize();
+
+ QCOMPARE(blockCount(), 2);
+
+ int lineCount = 0;
+ for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
+ lineCount += block.layout()->lineCount();
+ QCOMPARE(lineCount, totalLineCount);
+
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+
+ for (int i = 0; i < lineCount; ++i) {
+ QTest::keyClick(ed, Qt::Key_Down, Qt::ShiftModifier);
+ }
+
+ input.replace(QLatin1Char('\n'), QChar(QChar::ParagraphSeparator));
+ QCOMPARE(ed->textCursor().selectedText(), input);
+ QVERIFY(ed->textCursor().atEnd());
+
+ // also test that without shift modifier the cursor does not move to the end
+ // for Key_Down in the last line
+ cursor.movePosition(QTextCursor::Start);
+ ed->setTextCursor(cursor);
+ for (int i = 0; i < lineCount; ++i) {
+ QTest::keyClick(ed, Qt::Key_Down);
+ }
+ QVERIFY(!ed->textCursor().atEnd());
+}
+
+void tst_QTextEdit::undoRedoShouldRepositionTextEditCursor()
+{
+ ed->setPlainText("five\nlines\nin\nthis\ntextedit");
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::Start);
+
+ ed->setUndoRedoEnabled(false);
+ ed->setUndoRedoEnabled(true);
+
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+
+ cursor.insertText("Blah");
+
+ QVERIFY(ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+
+ QVERIFY(QMetaObject::invokeMethod(ed, "undo"));
+
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(ed->document()->isRedoAvailable());
+
+ QCOMPARE(ed->textCursor().position(), 0);
+
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+
+ QVERIFY(QMetaObject::invokeMethod(ed, "redo"));
+
+ QVERIFY(ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+
+ QCOMPARE(ed->textCursor().position(), 4);
+}
+
+void tst_QTextEdit::lineWrapModes()
+{
+ ed->setLineWrapMode(QTextEdit::NoWrap);
+ // NoWrap at the same time as having all lines that are all left aligned means we optimize to only layout once. The effect is that the width is always 0
+ QVERIFY(ed->document()->pageSize().width() == qreal(0));
+
+ QTextCursor cursor = QTextCursor(ed->document());
+ cursor.insertText(QString("A simple line"));
+ cursor.insertBlock();
+ QTextBlockFormat fmt;
+ fmt.setAlignment(Qt::AlignRight);
+ cursor.mergeBlockFormat(fmt);
+ cursor.insertText(QString("Another line"));
+ ed->show(); // relayout;
+ QVERIFY(ed->document()->pageSize().width() > qreal(0));
+
+ ed->setLineWrapColumnOrWidth(10);
+ ed->setLineWrapMode(QTextEdit::FixedColumnWidth);
+ QVERIFY(!qIsNull(ed->document()->pageSize().width()));
+
+ ed->setLineWrapColumnOrWidth(1000);
+ ed->setLineWrapMode(QTextEdit::FixedPixelWidth);
+ QCOMPARE(ed->document()->pageSize().width(), qreal(1000));
+}
+
+void tst_QTextEdit::mouseCursorShape()
+{
+#ifndef QT_NO_CURSOR
+ // always show an IBeamCursor, see change 170146
+ QVERIFY(!ed->isReadOnly());
+ QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
+
+ ed->setReadOnly(true);
+ QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
+
+ ed->setPlainText("Foo");
+ QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
+#endif
+}
+
+void tst_QTextEdit::implicitClear()
+{
+ // test that QTextEdit::setHtml, etc. avoid calling clear() but instead call
+ // QTextDocument::setHtml/etc. instead, which also clear the contents and
+ // cached resource but preserve manually added resources. setHtml on a textedit
+ // should behave the same as on a document with respect to that.
+ // see also clearResources() autotest in qtextdocument
+
+ // regular resource for QTextDocument
+ QUrl testUrl(":/foobar");
+ QVariant testResource("hello world");
+
+ ed->document()->addResource(QTextDocument::ImageResource, testUrl, testResource);
+ QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ ed->setPlainText("Blah");
+ QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ ed->setPlainText("<b>Blah</b>");
+ QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
+
+ ed->clear();
+ QVERIFY(!ed->document()->resource(QTextDocument::ImageResource, testUrl).isValid());
+ QVERIFY(ed->toPlainText().isEmpty());
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::copyAvailable_data()
+{
+ QTest::addColumn<pairListType>("keystrokes");
+ QTest::addColumn<QList<bool> >("copyAvailable");
+ QTest::addColumn<QString>("function");
+
+ pairListType keystrokes;
+ QList<bool> copyAvailable;
+
+ keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_B, Qt::NoModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
+ copyAvailable << true ;
+ QTest::newRow(QString("Case1 B,B, <- + shift | signals: true").toLatin1())
+ << keystrokes << copyAvailable << QString();
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
+ copyAvailable << true << false;
+ QTest::newRow(QString("Case2 T,A,A, <- + shift, cut() | signals: true, false").toLatin1())
+ << keystrokes << copyAvailable << QString("cut");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
+ copyAvailable << true;
+ QTest::newRow(QString("Case3 T,A,A, <- + shift, <- + shift, <- + shift, copy() | signals: true").toLatin1())
+ << keystrokes << copyAvailable << QString("copy");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_X, Qt::ControlModifier);
+ copyAvailable << true << false;
+ QTest::newRow(QString("Case4 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, paste() | signals: true, false").toLatin1())
+ << keystrokes << copyAvailable << QString("paste");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_B, Qt::NoModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier);
+ copyAvailable << true << false;
+ QTest::newRow(QString("Case5 B,B, <- + shift, <- | signals: true, false").toLatin1())
+ << keystrokes << copyAvailable << QString();
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier)
+ << qMakePair(Qt::Key_Right, Qt::ShiftModifier);
+ copyAvailable << true << false << true << false;
+ QTest::newRow(QString("Case6 B,A, <- + shift, ->, <- + shift | signals: true, false, true, false").toLatin1())
+ << keystrokes << copyAvailable << QString("cut");
+
+ keystrokes.clear();
+ copyAvailable.clear();
+
+ keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
+ << qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
+ << qMakePair(Qt::Key_X, Qt::ControlModifier);
+ copyAvailable << true << false << true;
+ QTest::newRow(QString("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true").toLatin1())
+ << keystrokes << copyAvailable << QString("undo");
+}
+
+//Tests the copyAvailable slot for several cases
+void tst_QTextEdit::copyAvailable()
+{
+ QFETCH(pairListType,keystrokes);
+ QFETCH(QList<bool>, copyAvailable);
+ QFETCH(QString, function);
+
+#ifdef Q_WS_MAC
+ QSKIP("copyAvailable has never passed on Mac, task to fix is 132482", SkipAll);
+#endif
+ ed->clear();
+ QApplication::clipboard()->clear();
+ QVERIFY(!ed->canPaste());
+ QSignalSpy spyCopyAvailabe(ed, SIGNAL(copyAvailable(bool)));
+
+ //Execute Keystrokes
+ foreach(keyPairType keyPair, keystrokes) {
+ QTest::keyClick(ed, keyPair.first, keyPair.second );
+ }
+
+ //Execute ed->"function"
+ if (function == "cut")
+ ed->cut();
+ else if (function == "copy")
+ ed->copy();
+ else if (function == "paste")
+ ed->paste();
+ else if (function == "undo")
+ ed->paste();
+ else if (function == "redo")
+ ed->paste();
+
+ //Compare spied signals
+ QEXPECT_FAIL("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true",
+ "Wrong undo selection behaviour. Should be fixed in some future release. (See task: 132482)", Abort);
+ QCOMPARE(spyCopyAvailabe.count(), copyAvailable.count());
+ for (int i=0;i<spyCopyAvailabe.count(); i++) {
+ QVariant variantSpyCopyAvailable = spyCopyAvailabe.at(i).at(0);
+ QVERIFY2(variantSpyCopyAvailable.toBool() == copyAvailable.at(i), QString("Spied singnal: %1").arg(i).toLatin1());
+ }
+}
+#endif
+
+void tst_QTextEdit::undoRedoAfterSetContent()
+{
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+ ed->setPlainText("Foobar");
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+ ed->setHtml("<p>bleh</p>");
+ QVERIFY(!ed->document()->isUndoAvailable());
+ QVERIFY(!ed->document()->isRedoAvailable());
+}
+
+void tst_QTextEdit::numPadKeyNavigation()
+{
+ ed->setText("Hello World");
+ QCOMPARE(ed->textCursor().position(), 0);
+ QTest::keyClick(ed, Qt::Key_Right, Qt::KeypadModifier);
+ QCOMPARE(ed->textCursor().position(), 1);
+}
+
+void tst_QTextEdit::moveCursor()
+{
+ ed->setText("Test");
+
+ QSignalSpy cursorMovedSpy(ed, SIGNAL(cursorPositionChanged()));
+
+ QCOMPARE(ed->textCursor().position(), 0);
+ ed->moveCursor(QTextCursor::NextCharacter);
+ QCOMPARE(ed->textCursor().position(), 1);
+ QCOMPARE(cursorMovedSpy.count(), 1);
+ ed->moveCursor(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ QCOMPARE(ed->textCursor().position(), 2);
+ QCOMPARE(cursorMovedSpy.count(), 2);
+ QCOMPARE(ed->textCursor().selectedText(), QString("e"));
+}
+
+class MyTextEdit : public QTextEdit
+{
+public:
+ inline MyTextEdit()
+ : createMimeDataCallCount(0),
+ canInsertCallCount(0),
+ insertCallCount(0)
+ {}
+
+ mutable int createMimeDataCallCount;
+ mutable int canInsertCallCount;
+ mutable int insertCallCount;
+
+ virtual QMimeData *createMimeDataFromSelection() const {
+ createMimeDataCallCount++;
+ return QTextEdit::createMimeDataFromSelection();
+ }
+ virtual bool canInsertFromMimeData(const QMimeData *source) const {
+ canInsertCallCount++;
+ return QTextEdit::canInsertFromMimeData(source);
+ }
+ virtual void insertFromMimeData(const QMimeData *source) {
+ insertCallCount++;
+ QTextEdit::insertFromMimeData(source);
+ }
+
+};
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::mimeDataReimplementations()
+{
+ MyTextEdit ed;
+ ed.setPlainText("Hello World");
+
+ QCOMPARE(ed.createMimeDataCallCount, 0);
+ QCOMPARE(ed.canInsertCallCount, 0);
+ QCOMPARE(ed.insertCallCount, 0);
+
+ ed.selectAll();
+
+ QCOMPARE(ed.createMimeDataCallCount, 0);
+ QCOMPARE(ed.canInsertCallCount, 0);
+ QCOMPARE(ed.insertCallCount, 0);
+
+ ed.copy();
+
+ QCOMPARE(ed.createMimeDataCallCount, 1);
+ QCOMPARE(ed.canInsertCallCount, 0);
+ QCOMPARE(ed.insertCallCount, 0);
+
+#ifdef QT_BUILD_INTERNAL
+ QWidgetTextControl *control = qFindChild<QWidgetTextControl *>(&ed);
+ QVERIFY(control);
+
+ control->canInsertFromMimeData(QApplication::clipboard()->mimeData());
+
+ QCOMPARE(ed.createMimeDataCallCount, 1);
+ QCOMPARE(ed.canInsertCallCount, 1);
+ QCOMPARE(ed.insertCallCount, 0);
+
+ ed.paste();
+
+ QCOMPARE(ed.createMimeDataCallCount, 1);
+ QCOMPARE(ed.canInsertCallCount, 1);
+ QCOMPARE(ed.insertCallCount, 1);
+#endif
+}
+#endif
+
+void tst_QTextEdit::ctrlEnterShouldInsertLineSeparator_NOT()
+{
+ QTest::keyClick(ed, Qt::Key_A);
+ QTest::keyClick(ed, Qt::Key_Enter, Qt::ControlModifier);
+ QTest::keyClick(ed, Qt::Key_B);
+ QString expected;
+ expected += 'a';
+// expected += QChar::LineSeparator; // do NOT insert
+ expected += 'b';
+ QCOMPARE(ed->textCursor().block().text(), expected);
+}
+
+void tst_QTextEdit::shiftEnterShouldInsertLineSeparator()
+{
+ QTest::keyClick(ed, Qt::Key_A);
+ QTest::keyClick(ed, Qt::Key_Enter, Qt::ShiftModifier);
+ QTest::keyClick(ed, Qt::Key_B);
+ QString expected;
+ expected += 'a';
+ expected += QChar::LineSeparator;
+ expected += 'b';
+ QCOMPARE(ed->textCursor().block().text(), expected);
+}
+
+void tst_QTextEdit::selectWordsFromStringsContainingSeparators_data()
+{
+ QTest::addColumn<QString>("testString");
+ QTest::addColumn<QString>("selectedWord");
+
+ QStringList wordSeparators;
+ wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "["
+ << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp);
+
+ foreach (QString s, wordSeparators)
+ QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo");
+}
+
+void tst_QTextEdit::selectWordsFromStringsContainingSeparators()
+{
+ QFETCH(QString, testString);
+ QFETCH(QString, selectedWord);
+ ed->setText(testString);
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::StartOfLine);
+ cursor.select(QTextCursor::WordUnderCursor);
+ QVERIFY(cursor.hasSelection());
+ QCOMPARE(cursor.selection().toPlainText(), selectedWord);
+ cursor.clearSelection();
+}
+
+#ifndef QT_NO_CLIPBOARD
+void tst_QTextEdit::canPaste()
+{
+ if (!nativeClipboardWorking())
+ QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
+
+ QApplication::clipboard()->setText(QString());
+ QVERIFY(!ed->canPaste());
+ QApplication::clipboard()->setText("Test");
+ QVERIFY(ed->canPaste());
+ ed->setTextInteractionFlags(Qt::NoTextInteraction);
+ QVERIFY(!ed->canPaste());
+}
+#endif
+
+void tst_QTextEdit::ensureCursorVisibleOnInitialShow()
+{
+ QString manyPagesOfPlainText;
+ for (int i = 0; i < 800; ++i)
+ manyPagesOfPlainText += QLatin1String("Blah blah blah blah blah blah\n");
+
+ ed->setPlainText(manyPagesOfPlainText);
+ QCOMPARE(ed->textCursor().position(), 0);
+
+ ed->moveCursor(QTextCursor::End);
+ ed->show();
+ QVERIFY(ed->verticalScrollBar()->value() > 10);
+
+ ed->moveCursor(QTextCursor::Start);
+ QVERIFY(ed->verticalScrollBar()->value() < 10);
+ ed->hide();
+ ed->verticalScrollBar()->setValue(ed->verticalScrollBar()->maximum());
+ ed->show();
+ QCOMPARE(ed->verticalScrollBar()->value(), ed->verticalScrollBar()->maximum());
+}
+
+class TestEdit : public QTextEdit
+{
+public:
+ TestEdit() : resizeEventCalled(false) {}
+
+ bool resizeEventCalled;
+
+protected:
+ virtual void resizeEvent(QResizeEvent *e)
+ {
+ QTextEdit::resizeEvent(e);
+ setHtml("<img src=qtextbrowser-resizeevent.png width=" + QString::number(size().width()) + "><br>Size is " + QString::number(size().width()) + " x " + QString::number(size().height()));
+ resizeEventCalled = true;
+ }
+};
+
+void tst_QTextEdit::setHtmlInsideResizeEvent()
+{
+ TestEdit edit;
+ edit.show();
+ edit.resize(800, 600);
+ QVERIFY(edit.resizeEventCalled);
+}
+
+void tst_QTextEdit::colorfulAppend()
+{
+ ed->setTextColor(Qt::red);
+ ed->append("Red");
+ ed->setTextColor(Qt::blue);
+ ed->append("Blue");
+ ed->setTextColor(Qt::green);
+ ed->append("Green");
+
+ QCOMPARE(ed->document()->blockCount(), 3);
+ QTextBlock block = ed->document()->begin();
+ QCOMPARE(block.begin().fragment().text(), QString("Red"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::red);
+ block = block.next();
+ QCOMPARE(block.begin().fragment().text(), QString("Blue"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::blue);
+ block = block.next();
+ QCOMPARE(block.begin().fragment().text(), QString("Green"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::green);
+}
+
+void tst_QTextEdit::ensureVisibleWithRtl()
+{
+ ed->setLayoutDirection(Qt::RightToLeft);
+ ed->setLineWrapMode(QTextEdit::NoWrap);
+ QString txt(500, QChar(QLatin1Char('a')));
+ QCOMPARE(txt.length(), 500);
+ ed->setPlainText(txt);
+ ed->resize(100, 100);
+ ed->show();
+
+ qApp->processEvents();
+
+ QVERIFY(ed->horizontalScrollBar()->maximum() > 0);
+
+ ed->moveCursor(QTextCursor::Start);
+ QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
+ ed->moveCursor(QTextCursor::End);
+ QCOMPARE(ed->horizontalScrollBar()->value(), 0);
+ ed->moveCursor(QTextCursor::Start);
+ QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
+ ed->moveCursor(QTextCursor::End);
+ QCOMPARE(ed->horizontalScrollBar()->value(), 0);
+}
+
+void tst_QTextEdit::preserveCharFormatAfterSetPlainText()
+{
+ ed->setTextColor(Qt::blue);
+ ed->setPlainText("This is blue");
+ ed->append("This should still be blue");
+ QTextBlock block = ed->document()->begin();
+ block = block.next();
+ QCOMPARE(block.text(), QString("This should still be blue"));
+ QVERIFY(block.begin().fragment().charFormat().foreground().color() == QColor(Qt::blue));
+}
+
+void tst_QTextEdit::extraSelections()
+{
+ ed->setPlainText("Hello World");
+
+ QTextCursor c = ed->textCursor();
+ c.movePosition(QTextCursor::Start);
+ c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ const int endPos = c.position();
+
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = c;
+ ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
+
+ c.movePosition(QTextCursor::Start);
+ c.movePosition(QTextCursor::NextWord);
+ const int wordPos = c.position();
+ c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ sel.cursor = c;
+ ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
+
+ QList<QTextEdit::ExtraSelection> selections = ed->extraSelections();
+ QCOMPARE(selections.count(), 1);
+ QCOMPARE(selections.at(0).cursor.position(), endPos);
+ QCOMPARE(selections.at(0).cursor.anchor(), wordPos);
+}
+
+void tst_QTextEdit::adjustScrollbars()
+{
+// For some reason ff is defined to be << on Mac Panther / gcc 3.3
+#undef ff
+ QFont ff(ed->font());
+ ff.setFamily("Tahoma");
+ ff.setPointSize(11);
+ ed->setFont(ff);
+ ed->setMinimumSize(140, 100);
+ ed->setMaximumSize(140, 100);
+ ed->show();
+ QLatin1String txt("\nabc def ghi jkl mno pqr stu vwx");
+ ed->setText(txt + txt + txt + txt);
+
+ QVERIFY(ed->verticalScrollBar()->maximum() > 0);
+
+ ed->moveCursor(QTextCursor::End);
+ int oldMaximum = ed->verticalScrollBar()->maximum();
+ QTextCursor cursor = ed->textCursor();
+ cursor.insertText(QLatin1String("\n"));
+ cursor.deletePreviousChar();
+ QCOMPARE(ed->verticalScrollBar()->maximum(), oldMaximum);
+}
+
+class SignalReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ SignalReceiver() : received(0) {}
+
+ int receivedSignals() const { return received; }
+ QTextCharFormat charFormat() const { return format; }
+
+public slots:
+ void charFormatChanged(const QTextCharFormat &tcf) { ++received; format = tcf; }
+
+private:
+ QTextCharFormat format;
+ int received;
+};
+
+void tst_QTextEdit::currentCharFormatChanged()
+{
+ QFont ff(ed->font());
+ ff.setFamily("Tahoma");
+ ff.setPointSize(11);
+
+ SignalReceiver receiver;
+ QObject::connect(ed, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)) , &receiver, SLOT(charFormatChanged(const QTextCharFormat &)));
+
+ ed->show();
+ ed->setCurrentFont(ff);
+
+ QVERIFY(receiver.receivedSignals() > 0);
+ QCOMPARE(receiver.charFormat().font(), ff);
+}
+
+void tst_QTextEdit::textObscuredByScrollbars()
+{
+ ed->textCursor().insertText(
+ "ab cab cab c abca kjsdf lka sjd lfk jsal df j kasdf abc ab abc "
+ "a b c d e f g h i j k l m n o p q r s t u v w x y z "
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
+ "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
+ );
+ ed->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ ed->show();
+
+ QSize documentSize = ed->document()->documentLayout()->documentSize().toSize();
+ QSize viewportSize = ed->viewport()->size();
+
+ QVERIFY(documentSize.width() <= viewportSize.width());
+}
+
+void tst_QTextEdit::setTextPreservesUndoRedoEnabled()
+{
+ QVERIFY(ed->isUndoRedoEnabled());
+
+ ed->setPlainText("Test");
+
+ QVERIFY(ed->isUndoRedoEnabled());
+
+ ed->setUndoRedoEnabled(false);
+ QVERIFY(!ed->isUndoRedoEnabled());
+ ed->setPlainText("Test2");
+ QVERIFY(!ed->isUndoRedoEnabled());
+
+ ed->setHtml("<p>hello");
+ QVERIFY(!ed->isUndoRedoEnabled());
+}
+
+void tst_QTextEdit::wordWrapProperty()
+{
+ {
+ QTextEdit edit;
+ QTextDocument *doc = new QTextDocument(&edit);
+ edit.setDocument(doc);
+ edit.setWordWrapMode(QTextOption::NoWrap);
+ QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
+ }
+ {
+ QTextEdit edit;
+ QTextDocument *doc = new QTextDocument(&edit);
+ edit.setWordWrapMode(QTextOption::NoWrap);
+ edit.setDocument(doc);
+ QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
+ }
+}
+
+void tst_QTextEdit::lineWrapProperty()
+{
+ QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
+ QVERIFY(ed->lineWrapMode() == QTextEdit::WidgetWidth);
+ ed->setLineWrapMode(QTextEdit::NoWrap);
+ QVERIFY(ed->lineWrapMode() == QTextEdit::NoWrap);
+ QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
+ QVERIFY(ed->document()->defaultTextOption().wrapMode() == QTextOption::NoWrap);
+}
+
+void tst_QTextEdit::selectionChanged()
+{
+ ed->setPlainText("Hello World");
+
+ ed->moveCursor(QTextCursor::Start);
+
+ QSignalSpy selectionChangedSpy(ed, SIGNAL(selectionChanged()));
+
+ QTest::keyClick(ed, Qt::Key_Right);
+ QCOMPARE(ed->textCursor().position(), 1);
+ QCOMPARE(selectionChangedSpy.count(), 0);
+
+ QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().position(), 2);
+ QCOMPARE(selectionChangedSpy.count(), 1);
+
+ QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().position(), 3);
+ QCOMPARE(selectionChangedSpy.count(), 2);
+
+ QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
+ QCOMPARE(ed->textCursor().position(), 4);
+ QCOMPARE(selectionChangedSpy.count(), 3);
+
+ QTest::keyClick(ed, Qt::Key_Right);
+ QCOMPARE(ed->textCursor().position(), 5);
+ QCOMPARE(selectionChangedSpy.count(), 4);
+
+ QTest::keyClick(ed, Qt::Key_Right);
+ QCOMPARE(ed->textCursor().position(), 6);
+ QCOMPARE(selectionChangedSpy.count(), 4);
+}
+
+void tst_QTextEdit::copyPasteBackgroundImage()
+{
+#ifndef QT_NO_CLIPBOARD
+ if (!nativeClipboardWorking())
+ QSKIP("Native clipboard not working in this setup", SkipAll);
+
+ QImage foo(16, 16, QImage::Format_ARGB32_Premultiplied);
+ foo.save("foo.png");
+ ed->setHtml("<body><table><tr><td background=\"foo.png\">Foo</td></tr></table></body>");
+
+ ed->moveCursor(QTextCursor::Start);
+ ed->moveCursor(QTextCursor::End, QTextCursor::KeepAnchor);
+
+ ed->copy();
+
+ ed->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
+ ed->paste();
+
+ ed->moveCursor(QTextCursor::Start);
+
+ ed->moveCursor(QTextCursor::NextBlock);
+ QTextTable *a = ed->textCursor().currentTable();
+
+ ed->moveCursor(QTextCursor::End);
+ ed->moveCursor(QTextCursor::PreviousBlock);
+ QTextTable *b = ed->textCursor().currentTable();
+
+ QVERIFY(a);
+ QVERIFY(b);
+ QVERIFY(a != b);
+
+ QBrush ba = a->cellAt(0, 0).format().background();
+ QBrush bb = b->cellAt(0, 0).format().background();
+
+ QCOMPARE(ba.style(), Qt::TexturePattern);
+ QCOMPARE(ba.style(), bb.style());
+
+ // we don't want a copy/paste of the background image to cause
+ // a new image/pixmap to be created, it should use the cached resource
+ // already in the document
+ QVERIFY(ba.textureImage().cacheKey() == bb.textureImage().cacheKey() ||
+ ba.texture().cacheKey() == bb.texture().cacheKey());
+ QFile::remove(QLatin1String("foo.png"));
+#endif
+}
+
+void tst_QTextEdit::setText()
+{
+ QTextEdit browser;
+ browser.setText(QLatin1String("hello"));
+ QCOMPARE(browser.toPlainText(), QLatin1String("hello"));
+ browser.setText(QLatin1String("<b>bold bold</b>"));
+ QCOMPARE(browser.toPlainText(), QLatin1String("bold bold"));
+ browser.setText(QLatin1String("with space"));
+ QCOMPARE(browser.toPlainText(), QLatin1String("with space"));
+}
+
+QT_BEGIN_NAMESPACE
+extern void qt_setQtEnableTestFont(bool value);
+QT_END_NAMESPACE
+
+void tst_QTextEdit::fullWidthSelection_data()
+{
+ QTest::addColumn<int>("cursorFrom");
+ QTest::addColumn<int>("cursorTo");
+ QTest::addColumn<QString>("imageFileName");
+
+ QTest::newRow("centered fully selected") << 0 << 15 << QString("fullWidthSelection/centered-fully-selected.png");
+ QTest::newRow("centered partly selected") << 2 << 15 << QString("fullWidthSelection/centered-partly-selected.png");
+ QTest::newRow("last char on line") << 42 << 44 << QString("fullWidthSelection/last-char-on-line.png");
+ QTest::newRow("last char on parag") << 545 << 548 << QString("fullWidthSelection/last-char-on-parag.png");
+ QTest::newRow("multiple full width lines") << 20 << 60 << QString("fullWidthSelection/multiple-full-width-lines.png");
+ QTest::newRow("single full width line") << 20 << 30 << QString("fullWidthSelection/single-full-width-line.png");
+}
+
+void tst_QTextEdit::fullWidthSelection()
+{
+ QFETCH(int, cursorFrom);
+ QFETCH(int, cursorTo);
+ QFETCH(QString, imageFileName);
+
+ // enable full-width-selection for our test widget.
+ class FullWidthStyle : public QCommonStyle {
+ int styleHint(StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const {
+ if (stylehint == QStyle::SH_RichText_FullWidthSelection)
+ return 1;
+ return QCommonStyle::styleHint(stylehint, opt, widget, returnData);
+ };
+ };
+ FullWidthStyle myStyle;
+
+ QPalette myPalette = myStyle.standardPalette();
+ myPalette.setColor(QPalette::All, QPalette::HighlightedText, QColor(0,0,0,0));
+ myPalette.setColor(QPalette::All, QPalette::Highlight, QColor(239,221,85));
+
+ QTextEdit widget;
+ widget.document()->setDocumentMargin(2);
+ widget.setPalette(myPalette);
+ widget.setStyle(&myStyle);
+ QTextCursor cursor = widget.textCursor();
+ QTextBlockFormat bf1;
+ bf1.setAlignment(Qt::AlignCenter);
+ cursor.setBlockFormat(bf1);
+
+ // use the test font so we always know where stuff will end up.
+ qt_setQtEnableTestFont(true);
+ QFont testFont;
+ testFont.setFamily("__Qt__Box__Engine__");
+ testFont.setPixelSize(11);
+ testFont.setWeight(QFont::Normal);
+ QTextCharFormat cf;
+ cf.setFont(testFont);
+ cf.setForeground(QColor(0,0,0,0)); // tricky bit, this :)
+ cursor.setCharFormat(cf);
+
+ // populate with some demo text.
+ cursor.insertText("centered");
+ QTextBlockFormat bf;
+ cursor.insertBlock(bf, cf);
+ cursor.insertText("Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo cons.\nfoo\n");
+
+ // Usecase 1 for full-width-selections; the 'show-cursor-position' one.
+ QList<QTextEdit::ExtraSelection> selections;
+ QTextCursor cursor2(widget.document());
+ QTextEdit::ExtraSelection es;
+ cursor2.setPosition(300);
+ es.cursor = cursor2;
+ es.format.setProperty( QTextFormat::FullWidthSelection, true );
+ es.format.setBackground(QColor(255, 0, 0));
+ selections.append(es);
+ widget.setExtraSelections(selections);
+
+ // Usecase 2; show it based on the style.
+ // Select part of the centered text and part of the next; which means we should show the part right of the centered text.
+ cursor.setPosition(cursorFrom);
+ cursor.setPosition(cursorTo, QTextCursor::KeepAnchor);
+ widget.setTextCursor(cursor);
+
+ compareWidgetAndImage(widget, imageFileName);
+}
+
+void tst_QTextEdit::fullWidthSelection2()
+{
+ QPalette myPalette;
+ myPalette.setColor(QPalette::All, QPalette::HighlightedText, QColor(0,0,0,0));
+ myPalette.setColor(QPalette::All, QPalette::Highlight, QColor(239,221,85));
+
+ QTextEdit widget;
+ widget.setPalette(myPalette);
+ widget.setLineWrapMode(QTextEdit::NoWrap);
+ QTextCursor cursor = widget.textCursor();
+
+ // use the test font so we always know where stuff will end up.
+ qt_setQtEnableTestFont(true);
+ QFont testFont;
+ testFont.setFamily("__Qt__Box__Engine__");
+ testFont.setPixelSize(11);
+ testFont.setWeight(QFont::Normal);
+ QTextCharFormat cf;
+ cf.setFont(testFont);
+ cf.setForeground(QColor(0,0,0,0)); // tricky bit, this :)
+ cursor.setCharFormat(cf);
+ cursor.insertText("foo");
+
+ QList<QTextEdit::ExtraSelection> selections;
+ QTextCursor cursor2(widget.document());
+ QTextEdit::ExtraSelection es;
+ cursor2.setPosition(1);
+ es.cursor = cursor2;
+ es.format.setProperty( QTextFormat::FullWidthSelection, true );
+ es.format.setBackground(QColor(255, 0, 0));
+ selections.append(es);
+ widget.setExtraSelections(selections);
+
+ compareWidgetAndImage(widget, "fullWidthSelection/nowrap_long.png");
+
+ QTextLine line = widget.document()->begin().layout()->lineAt(0);
+ // qDebug() << line.width();
+}
+
+void tst_QTextEdit::compareWidgetAndImage(QTextEdit &widget, const QString &imageFileName)
+{
+ widget.setGeometry(0, 0, 300, 390);
+ widget.setFrameShape(QFrame::NoFrame);
+
+ QImage image(300, 390, QImage::Format_RGB32);
+ QPainter painter(&image);
+ widget.viewport()->render(&painter);
+ painter.end();
+ // qDebug() << "file: " << QString(SRCDIR) + imageFileName;
+ QImageReader reader(QString(SRCDIR) + imageFileName, "PNG");
+ QImage original = reader.read();
+
+ QCOMPARE(original.isNull(), false);
+ QCOMPARE(original.size(), image.size());
+ QCOMPARE(image.depth(), 32);
+ QCOMPARE(original.depth(), image.depth());
+
+ const int bytesPerLine = image.bytesPerLine();
+ const int width = image.width();
+ const int height = image.height();
+
+ for (int y = 0; y < height; ++y) {
+ const QRgb * const firstLine = reinterpret_cast<const QRgb *>(image.scanLine(y));
+ const QRgb * const secondLine = reinterpret_cast<const QRgb *>(original.scanLine(y));
+
+ if (memcmp(firstLine, secondLine, bytesPerLine) != 0) {
+ for (int x = 0; x < width; ++x) {
+ const QRgb a = firstLine[x];
+ const QRgb b = secondLine[x];
+ const bool same = qAbs(qRed(a) - qRed(b)) <= 20
+ && qAbs(qGreen(a) - qGreen(b)) <= 20
+ && qAbs(qBlue(a) - qBlue(b)) <= 20;
+ if (!same) {
+ QString fileName = imageFileName;
+ QImageWriter writer("failed_"+ fileName.replace('/','_'), "PNG");
+ writer.write(image);
+ }
+ QVERIFY(same);
+ }
+ }
+ }
+}
+
+void tst_QTextEdit::cursorRect()
+{
+ ed->show();
+ ed->setPlainText("Hello Test World");
+ ed->setCursorWidth(1);
+ QCOMPARE(ed->cursorRect().width(), 1);
+ ed->setCursorWidth(2);
+ QCOMPARE(ed->cursorRect().width(), 2);
+ ed->setCursorWidth(4);
+ QCOMPARE(ed->cursorRect().width(), 4);
+ ed->setCursorWidth(10);
+ QCOMPARE(ed->cursorRect().width(), 10);
+}
+
+void tst_QTextEdit::setDocumentPreservesPalette()
+{
+#ifdef QT_BUILD_INTERNAL
+ QWidgetTextControl *control = qFindChild<QWidgetTextControl *>(ed);
+ QVERIFY(control);
+
+ QPalette defaultPal = ed->palette();
+ QPalette whitePal = ed->palette();
+ whitePal.setColor(QPalette::Active, QPalette::Text, "white");
+
+
+ QVERIFY(whitePal != ed->palette());
+ ed->setPalette(whitePal);
+ QVERIFY(whitePal.color(QPalette::Active, QPalette::Text)
+ == ed->palette().color(QPalette::Active, QPalette::Text));
+ QVERIFY(whitePal.color(QPalette::Active, QPalette::Text)
+ == control->palette().color(QPalette::Active, QPalette::Text));
+
+ QTextDocument *newDoc = new QTextDocument(ed);
+ ed->setDocument(newDoc);
+ QVERIFY(control->document() == newDoc);
+ QVERIFY(whitePal.color(QPalette::Active, QPalette::Text)
+ == control->palette().color(QPalette::Active, QPalette::Text));
+#endif
+}
+
+class PublicTextEdit : public QTextEdit
+{
+public:
+ void publicInsertFromMimeData(const QMimeData *source)
+ { insertFromMimeData(source); }
+};
+
+void tst_QTextEdit::pasteFromQt3RichText()
+{
+ QByteArray richtext("<!--StartFragment--><p> QTextEdit is an ");
+
+ QMimeData mimeData;
+ mimeData.setData("application/x-qrichtext", richtext);
+
+ static_cast<PublicTextEdit *>(ed)->publicInsertFromMimeData(&mimeData);
+
+ QCOMPARE(ed->toPlainText(), QString::fromLatin1(" QTextEdit is an "));
+ ed->clear();
+
+ richtext = "<!--StartFragment--> QTextEdit is an ";
+ mimeData.setData("application/x-qrichtext", richtext);
+
+ static_cast<PublicTextEdit *>(ed)->publicInsertFromMimeData(&mimeData);
+
+ QCOMPARE(ed->toPlainText(), QString::fromLatin1(" QTextEdit is an "));
+}
+
+void tst_QTextEdit::noWrapBackgrounds()
+{
+ QWidget topLevel;
+ QVBoxLayout *layout = new QVBoxLayout(&topLevel);
+
+ QTextEdit edit;
+ edit.setLineWrapMode(QTextEdit::NoWrap);
+
+ // hide the cursor in order to make the image comparison below reliable
+ edit.setCursorWidth(0);
+
+ QTextFrame *root = edit.document()->rootFrame();
+ QTextFrameFormat frameFormat = root->frameFormat();
+ frameFormat.setLeftMargin(2);
+ frameFormat.setRightMargin(2);
+ root->setFrameFormat(frameFormat);
+
+ QTextBlockFormat format;
+ format.setBackground(Qt::red);
+ edit.textCursor().setBlockFormat(format);
+ edit.insertPlainText(QLatin1String(" \n \n \n \n"));
+ edit.setFixedSize(100, 200);
+
+ layout->addWidget(&edit);
+ topLevel.show();
+
+ QImage img = QPixmap::grabWidget(edit.viewport()).toImage();
+ QCOMPARE(img, img.mirrored(true, false));
+}
+
+void tst_QTextEdit::preserveCharFormatAfterUnchangingSetPosition()
+{
+ QColor color(Qt::yellow);
+ QTextEdit edit;
+ edit.setTextColor(color);
+
+ QTextCursor c = edit.textCursor();
+ c.setPosition(c.position());
+ edit.setTextCursor(c);
+
+ QCOMPARE(edit.textColor(), color);
+}
+
+// Regression test for QTBUG-4696
+void tst_QTextEdit::twoSameInputMethodEvents()
+{
+ ed->setText("testLine");
+ ed->show();
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ ed->textCursor().position(),
+ 0,
+ QVariant()));
+
+ QInputMethodEvent event("PreEditText", attributes);
+ QApplication::sendEvent(ed, &event);
+ QCOMPARE(ed->document()->firstBlock().layout()->lineCount(), 1);
+ QApplication::sendEvent(ed, &event);
+ QCOMPARE(ed->document()->firstBlock().layout()->lineCount(), 1);
+}
+
+#ifndef QT_NO_CONTEXTMENU
+void tst_QTextEdit::taskQTBUG_7902_contextMenuCrash()
+{
+ QTextEdit *w = new QTextEdit;
+ w->show();
+ QTest::qWaitForWindowShown(w);
+
+ QTimer ti;
+ w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
+ ti.start(200);
+
+ QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
+ qApp->postEvent(w->viewport(), cme);
+
+ QTest::qWait(300);
+ // No crash, it's allright.
+}
+#endif
+
+void tst_QTextEdit::bidiVisualMovement_data()
+{
+ QTest::addColumn<QString>("logical");
+ QTest::addColumn<int>("basicDir");
+ QTest::addColumn<QList<int> >("positionList");
+
+ QTest::newRow("Latin text")
+ << QString::fromUtf8("abc")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 3);
+ QTest::newRow("Hebrew text, one item")
+ << QString::fromUtf8("\327\220\327\221\327\222")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 3);
+ QTest::newRow("Hebrew text after Latin text")
+ << QString::fromUtf8("abc\327\220\327\221\327\222")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 6 << 5 << 4 << 3);
+ QTest::newRow("Latin text after Hebrew text")
+ << QString::fromUtf8("\327\220\327\221\327\222abc")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 6 << 5 << 4 << 3);
+ QTest::newRow("LTR, 3 items")
+ << QString::fromUtf8("abc\327\220\327\221\327\222abc")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 9);
+ QTest::newRow("RTL, 3 items")
+ << QString::fromUtf8("\327\220\327\221\327\222abc\327\220\327\221\327\222")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 9);
+ QTest::newRow("LTR, 4 items")
+ << QString::fromUtf8("abc\327\220\327\221\327\222abc\327\220\327\221\327\222")
+ << (int) QChar::DirL
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 12 << 11 << 10 << 9);
+ QTest::newRow("RTL, 4 items")
+ << QString::fromUtf8("\327\220\327\221\327\222abc\327\220\327\221\327\222abc")
+ << (int) QChar::DirR
+ << (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 12 << 11 << 10 << 9);
+}
+
+void tst_QTextEdit::bidiVisualMovement()
+{
+ QFETCH(QString, logical);
+ QFETCH(int, basicDir);
+ QFETCH(QList<int>, positionList);
+
+ ed->setText(logical);
+
+ QTextOption option = ed->document()->defaultTextOption();
+ option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft);
+ ed->document()->setDefaultTextOption(option);
+
+ ed->document()->setDefaultCursorMoveStyle(Qt::VisualMoveStyle);
+ ed->moveCursor(QTextCursor::Start);
+ ed->show();
+
+ bool moved;
+ int i = 0, oldPos, newPos = 0;
+
+ do {
+ oldPos = newPos;
+ QVERIFY(oldPos == positionList[i]);
+ if (basicDir == QChar::DirL) {
+ ed->moveCursor(QTextCursor::Right);
+ } else
+ {
+ ed->moveCursor(QTextCursor::Left);
+ }
+ newPos = ed->textCursor().position();
+ moved = (oldPos != newPos);
+ i++;
+ } while (moved);
+
+ QVERIFY(i == positionList.size());
+
+ do {
+ i--;
+ oldPos = newPos;
+ QVERIFY(oldPos == positionList[i]);
+ if (basicDir == QChar::DirL) {
+ ed->moveCursor(QTextCursor::Left);
+ } else
+ {
+ ed->moveCursor(QTextCursor::Right);
+ }
+ newPos = ed->textCursor().position();
+ moved = (oldPos != newPos);
+ } while (moved && i >= 0);
+}
+
+void tst_QTextEdit::bidiLogicalMovement_data()
+{
+ bidiVisualMovement_data();
+}
+
+void tst_QTextEdit::bidiLogicalMovement()
+{
+ QFETCH(QString, logical);
+ QFETCH(int, basicDir);
+
+ ed->setText(logical);
+
+ QTextOption option = ed->document()->defaultTextOption();
+ option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft);
+ ed->document()->setDefaultTextOption(option);
+
+ ed->document()->setDefaultCursorMoveStyle(Qt::LogicalMoveStyle);
+ ed->moveCursor(QTextCursor::Start);
+ ed->show();
+
+ bool moved;
+ int i = 0, oldPos, newPos = 0;
+
+ do {
+ oldPos = newPos;
+ QVERIFY(oldPos == i);
+ if (basicDir == QChar::DirL) {
+ ed->moveCursor(QTextCursor::Right);
+ } else
+ {
+ ed->moveCursor(QTextCursor::Left);
+ }
+ newPos = ed->textCursor().position();
+ moved = (oldPos != newPos);
+ i++;
+ } while (moved);
+
+ do {
+ i--;
+ oldPos = newPos;
+ QVERIFY(oldPos == i);
+ if (basicDir == QChar::DirL) {
+ ed->moveCursor(QTextCursor::Left);
+ } else
+ {
+ ed->moveCursor(QTextCursor::Right);
+ }
+ newPos = ed->textCursor().position();
+ moved = (oldPos != newPos);
+ } while (moved && i >= 0);
+}
+
+void tst_QTextEdit::inputMethodSelection()
+{
+ ed->setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+
+ QSignalSpy selectionSpy(ed, SIGNAL(selectionChanged()));
+ QTextCursor cursor = ed->textCursor();
+ cursor.setPosition(0);
+ cursor.setPosition(5, QTextCursor::KeepAnchor);
+ ed->setTextCursor(cursor);
+
+ QCOMPARE(selectionSpy.count(), 1);
+ QCOMPARE(ed->textCursor().selectionStart(), 0);
+ QCOMPARE(ed->textCursor().selectionEnd(), 5);
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 12, 5, QVariant());
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(ed, &event);
+
+ QCOMPARE(selectionSpy.count(), 2);
+ QCOMPARE(ed->textCursor().selectionStart(), 12);
+ QCOMPARE(ed->textCursor().selectionEnd(), 17);
+}
+
+
+QTEST_MAIN(tst_QTextEdit)
+#include "tst_qtextedit.moc"
diff --git a/tests/auto/widgets/widgets/qtoolbar/.gitignore b/tests/auto/widgets/widgets/qtoolbar/.gitignore
new file mode 100644
index 0000000000..971c9f9dfe
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbar/.gitignore
@@ -0,0 +1 @@
+tst_qtoolbar
diff --git a/tests/auto/widgets/widgets/qtoolbar/qtoolbar.pro b/tests/auto/widgets/widgets/qtoolbar/qtoolbar.pro
new file mode 100644
index 0000000000..b340097d81
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbar/qtoolbar.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += gui-private
+SOURCES += tst_qtoolbar.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp b/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp
new file mode 100644
index 0000000000..eb043aced8
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp
@@ -0,0 +1,1101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+
+#include <qabstractbutton.h>
+#include <qaction.h>
+#include <qlayout.h>
+#include <qmainwindow.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qtoolbar.h>
+#include <qwidgetaction.h>
+#include <qtoolbutton.h>
+#include <qlineedit.h>
+#include <qkeysequence.h>
+#include <qmenu.h>
+#include <private/qtoolbarextension_p.h>
+
+//TESTED_FILES=
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+class tst_QToolBar : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QToolBar();
+
+public slots:
+ void slot();
+ void slot(QAction *action);
+
+private slots:
+ void isMovable();
+ void allowedAreas();
+ void orientation();
+ void addAction();
+ void insertAction();
+ void addSeparator();
+ void insertSeparator();
+ void addWidget();
+ void insertWidget();
+ void actionGeometry();
+ void toggleViewAction();
+ void iconSize();
+ void toolButtonStyle();
+ void actionTriggered();
+ void visibilityChanged();
+ void actionOwnership();
+ void widgetAction();
+ void accel();
+
+ void task191727_layout();
+ void task197996_visibility();
+};
+
+
+QAction *triggered = 0;
+
+tst_QToolBar::tst_QToolBar()
+{
+ qRegisterMetaType<QSize>("QSize");
+ qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
+ qRegisterMetaType<Qt::ToolBarAreas>("Qt::ToolBarAreas");
+ qRegisterMetaType<Qt::ToolButtonStyle>("Qt::ToolButtonStyle");
+}
+
+void tst_QToolBar::slot()
+{ }
+
+void tst_QToolBar::slot(QAction *action)
+{ ::triggered = action; }
+
+void tst_QToolBar::isMovable()
+{
+#define DO_TEST \
+ do { \
+ QVERIFY(tb.isMovable()); \
+ tb.setMovable(false); \
+ QVERIFY(!tb.isMovable()); \
+ QCOMPARE(spy.count(), 1); \
+ QCOMPARE(spy.at(0).value(0).toBool(), tb.isMovable()); \
+ spy.clear(); \
+ tb.setMovable(tb.isMovable()); \
+ QCOMPARE(spy.count(), 0); \
+ spy.clear(); \
+ tb.setMovable(true); \
+ QVERIFY(tb.isMovable()); \
+ QCOMPARE(spy.count(), 1); \
+ QCOMPARE(spy.at(0).value(0).toBool(), tb.isMovable()); \
+ spy.clear(); \
+ tb.setMovable(tb.isMovable()); \
+ QCOMPARE(spy.count(), 0); \
+ spy.clear(); \
+ } while (false)
+
+ QMainWindow mw;
+ QToolBar tb;
+
+ QCOMPARE(tb.isMovable(), (bool)qApp->style()->styleHint(QStyle::SH_ToolBar_Movable));
+ if (!tb.isMovable())
+ tb.setMovable(true);
+
+ QSignalSpy spy(&tb, SIGNAL(movableChanged(bool)));
+
+ DO_TEST;
+ mw.addToolBar(&tb);
+ DO_TEST;
+ mw.removeToolBar(&tb);
+ DO_TEST;
+}
+
+void tst_QToolBar::allowedAreas()
+{
+ QToolBar tb;
+
+ QSignalSpy spy(&tb, SIGNAL(allowedAreasChanged(Qt::ToolBarAreas)));
+
+ // default
+ QCOMPARE((int)tb.allowedAreas(), (int)Qt::AllToolBarAreas);
+ QVERIFY(tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea));
+
+ // a single dock window area
+ tb.setAllowedAreas(Qt::LeftToolBarArea);
+ QCOMPARE((int)tb.allowedAreas(), (int)Qt::LeftToolBarArea);
+ QVERIFY(tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setAllowedAreas(Qt::RightToolBarArea);
+ QCOMPARE((int)tb.allowedAreas(), (int)Qt::RightToolBarArea);
+ QVERIFY(!tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setAllowedAreas(Qt::TopToolBarArea);
+ QCOMPARE((int)tb.allowedAreas(), (int)Qt::TopToolBarArea);
+ QVERIFY(!tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setAllowedAreas(Qt::BottomToolBarArea);
+ QCOMPARE((int)tb.allowedAreas(), (int)Qt::BottomToolBarArea);
+ QVERIFY(!tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ // multiple dock window areas
+ tb.setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
+ QCOMPARE(tb.allowedAreas(), Qt::TopToolBarArea | Qt::BottomToolBarArea);
+ QVERIFY(!tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
+ QCOMPARE(tb.allowedAreas(), Qt::LeftToolBarArea | Qt::RightToolBarArea);
+ QVERIFY(tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setAllowedAreas(Qt::TopToolBarArea | Qt::LeftToolBarArea);
+ QCOMPARE(tb.allowedAreas(), Qt::TopToolBarArea | Qt::LeftToolBarArea);
+ QVERIFY(tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setAllowedAreas(Qt::BottomToolBarArea | Qt::RightToolBarArea);
+ QCOMPARE(tb.allowedAreas(), Qt::BottomToolBarArea | Qt::RightToolBarArea);
+ QVERIFY(!tb.isAreaAllowed(Qt::LeftToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea));
+ QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea));
+ QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()),
+ tb.allowedAreas());
+ spy.clear();
+ tb.setAllowedAreas(tb.allowedAreas());
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QToolBar::orientation()
+{
+ QToolBar tb;
+ QCOMPARE(tb.orientation(), Qt::Horizontal);
+
+ QSignalSpy spy(&tb, SIGNAL(orientationChanged(Qt::Orientation)));
+
+ tb.setOrientation(Qt::Vertical);
+ QCOMPARE(tb.orientation(), Qt::Vertical);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()),
+ tb.orientation());
+ spy.clear();
+ tb.setOrientation(tb.orientation());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setOrientation(Qt::Horizontal);
+ QCOMPARE(tb.orientation(), Qt::Horizontal);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()),
+ tb.orientation());
+ spy.clear();
+ tb.setOrientation(tb.orientation());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setOrientation(Qt::Vertical);
+ QCOMPARE(tb.orientation(), Qt::Vertical);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()),
+ tb.orientation());
+ spy.clear();
+ tb.setOrientation(tb.orientation());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setOrientation(Qt::Horizontal);
+ QCOMPARE(tb.orientation(), Qt::Horizontal);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()),
+ tb.orientation());
+ spy.clear();
+ tb.setOrientation(tb.orientation());
+ QCOMPARE(spy.count(), 0);
+
+ tb.setOrientation(Qt::Vertical);
+ QCOMPARE(tb.orientation(), Qt::Vertical);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()),
+ tb.orientation());
+ spy.clear();
+ tb.setOrientation(tb.orientation());
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QToolBar::addAction()
+{
+ QToolBar tb;
+
+ {
+ QAction action(0);
+
+ QCOMPARE(tb.actions().count(), 0);
+ tb.addAction(&action);
+ QCOMPARE(tb.actions().count(), 1);
+ QCOMPARE(tb.actions()[0], &action);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+ }
+
+ {
+ QString text = "text";
+ QPixmap pm(32, 32);
+ pm.fill(Qt::blue);
+ QIcon icon = pm;
+
+ QAction *action1 = tb.addAction(text);
+ QCOMPARE(text, action1->text());
+
+ QAction *action2 = tb.addAction(icon, text);
+ QCOMPARE(icon, action2->icon());
+ QCOMPARE(text, action2->text());
+
+ QAction *action3 = tb.addAction(text, this, SLOT(slot()));
+ QCOMPARE(text, action3->text());
+
+ QAction *action4 = tb.addAction(icon, text, this, SLOT(slot()));
+ QCOMPARE(icon, action4->icon());
+ QCOMPARE(text, action4->text());
+
+ QCOMPARE(tb.actions().count(), 4);
+ QCOMPARE(tb.actions()[0], action1);
+ QCOMPARE(tb.actions()[1], action2);
+ QCOMPARE(tb.actions()[2], action3);
+ QCOMPARE(tb.actions()[3], action4);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+ }
+}
+
+void tst_QToolBar::insertAction()
+{
+ QToolBar tb;
+ QAction action1(0);
+ QAction action2(0);
+ QAction action3(0);
+ QAction action4(0);
+
+ QCOMPARE(tb.actions().count(), 0);
+ tb.insertAction(0, &action1);
+ tb.insertAction(&action1, &action2);
+ tb.insertAction(&action2, &action3);
+ tb.insertAction(&action3, &action4);
+ QCOMPARE(tb.actions().count(), 4);
+ QCOMPARE(tb.actions()[0], &action4);
+ QCOMPARE(tb.actions()[1], &action3);
+ QCOMPARE(tb.actions()[2], &action2);
+ QCOMPARE(tb.actions()[3], &action1);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+}
+
+void tst_QToolBar::addSeparator()
+{
+ QToolBar tb;
+
+ QAction action1(0);
+ QAction action2(0);
+
+ tb.addAction(&action1);
+ QAction *sep = tb.addSeparator();
+ tb.addAction(&action2);
+
+ QCOMPARE(tb.actions().count(), 3);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], sep);
+ QCOMPARE(tb.actions()[2], &action2);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+}
+
+void tst_QToolBar::insertSeparator()
+{
+ QToolBar tb;
+
+ QAction action1(0);
+ QAction action2(0);
+
+ tb.addAction(&action1);
+ tb.addAction(&action2);
+ QAction *sep = tb.insertSeparator(&action2);
+
+ QCOMPARE(tb.actions().count(), 3);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], sep);
+ QCOMPARE(tb.actions()[2], &action2);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+}
+
+void tst_QToolBar::addWidget()
+{
+ QToolBar tb;
+ QWidget w(&tb);
+
+ QAction action1(0);
+ QAction action2(0);
+
+ tb.addAction(&action1);
+ QAction *widget = tb.addWidget(&w);
+ tb.addAction(&action2);
+
+ QCOMPARE(tb.actions().count(), 3);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], widget);
+ QCOMPARE(tb.actions()[2], &action2);
+
+ // it should be possible to reuse the action returned by
+ // addWidget() to place the widget somewhere else in the toolbar
+ tb.removeAction(widget);
+ QCOMPARE(tb.actions().count(), 2);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], &action2);
+
+ tb.addAction(widget);
+ QCOMPARE(tb.actions().count(), 3);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], &action2);
+ QCOMPARE(tb.actions()[2], widget);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+}
+
+void tst_QToolBar::insertWidget()
+{
+ QToolBar tb;
+ QWidget w(&tb);
+
+ QAction action1(0);
+ QAction action2(0);
+
+ tb.addAction(&action1);
+ tb.addAction(&action2);
+ QAction *widget = tb.insertWidget(&action2, &w);
+
+ QCOMPARE(tb.actions().count(), 3);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], widget);
+ QCOMPARE(tb.actions()[2], &action2);
+
+ // it should be possible to reuse the action returned by
+ // addWidget() to place the widget somewhere else in the toolbar
+ tb.removeAction(widget);
+ QCOMPARE(tb.actions().count(), 2);
+ QCOMPARE(tb.actions()[0], &action1);
+ QCOMPARE(tb.actions()[1], &action2);
+
+ tb.insertAction(&action1, widget);
+ QCOMPARE(tb.actions().count(), 3);
+ QCOMPARE(tb.actions()[0], widget);
+ QCOMPARE(tb.actions()[1], &action1);
+ QCOMPARE(tb.actions()[2], &action2);
+
+ tb.clear();
+ QCOMPARE(tb.actions().count(), 0);
+
+ {
+ QToolBar tb;
+ QPointer<QWidget> widget = new QWidget;
+ QAction *action = tb.addWidget(widget);
+ QVERIFY(action->parent() == &tb);
+
+ QToolBar tb2;
+ tb.removeAction(action);
+ tb2.addAction(action);
+ QVERIFY(widget && widget->parent() == &tb2);
+ QVERIFY(action->parent() == &tb2);
+ }
+}
+
+void tst_QToolBar::actionGeometry()
+{
+ QToolBar tb;
+
+ QAction action1(0);
+ QAction action2(0);
+ QAction action3(0);
+ QAction action4(0);
+
+ tb.addAction(&action1);
+ tb.addAction(&action2);
+ tb.addAction(&action3);
+ tb.addAction(&action4);
+
+ tb.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&tb);
+#endif
+
+ QList<QToolBarExtension *> extensions = tb.findChildren<QToolBarExtension *>();
+
+ QRect rect01;
+ QRect rect02;
+ QRect rect03;
+ QRect rect04;
+ QMenu *popupMenu;
+
+ if (extensions.size() != 0)
+ {
+ QToolBarExtension *extension = extensions.at(0);
+ if (extension->isVisible()) {
+ QRect rect0 = extension->geometry();
+ QTest::mouseClick( extension, Qt::LeftButton, 0, rect0.center(), -1 );
+ QApplication::processEvents();
+ popupMenu = qobject_cast<QMenu *>(extension->menu());
+ rect01 = popupMenu->actionGeometry(&action1);
+ rect02 = popupMenu->actionGeometry(&action2);
+ rect03 = popupMenu->actionGeometry(&action3);
+ rect04 = popupMenu->actionGeometry(&action4);
+ }
+ }
+
+ QRect rect1 = tb.actionGeometry(&action1);
+ QRect rect2 = tb.actionGeometry(&action2);
+ QRect rect3 = tb.actionGeometry(&action3);
+ QRect rect4 = tb.actionGeometry(&action4);
+
+ QVERIFY(rect1.isValid());
+ QVERIFY(!rect1.isNull());
+ QVERIFY(!rect1.isEmpty());
+
+ QVERIFY(rect2.isValid());
+ QVERIFY(!rect2.isNull());
+ QVERIFY(!rect2.isEmpty());
+
+ QVERIFY(rect3.isValid());
+ QVERIFY(!rect3.isNull());
+ QVERIFY(!rect3.isEmpty());
+
+ QVERIFY(rect4.isValid());
+ QVERIFY(!rect4.isNull());
+ QVERIFY(!rect4.isEmpty());
+
+ if (rect01.isValid())
+ QCOMPARE(popupMenu->actionAt(rect01.center()), &action1);
+ else
+ QCOMPARE(tb.actionAt(rect1.center()), &action1);
+
+ if (rect02.isValid())
+ QCOMPARE(popupMenu->actionAt(rect02.center()), &action2);
+ else
+ QCOMPARE(tb.actionAt(rect2.center()), &action2);
+
+ if (rect03.isValid())
+ QCOMPARE(popupMenu->actionAt(rect03.center()), &action3);
+ else
+ QCOMPARE(tb.actionAt(rect3.center()), &action3);
+
+ if (rect04.isValid())
+ QCOMPARE(popupMenu->actionAt(rect04.center()), &action4);
+ else
+ QCOMPARE(tb.actionAt(rect4.center()), &action4);
+}
+
+void tst_QToolBar::toggleViewAction()
+{
+ {
+ QToolBar tb;
+ QAction *toggleViewAction = tb.toggleViewAction();
+ QVERIFY(tb.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(!tb.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(tb.isHidden());
+ }
+
+ {
+ QMainWindow mw;
+ QToolBar tb(&mw);
+ mw.addToolBar(&tb);
+ mw.show();
+ QAction *toggleViewAction = tb.toggleViewAction();
+ QVERIFY(!tb.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(tb.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(!tb.isHidden());
+ toggleViewAction->trigger();
+ QVERIFY(tb.isHidden());
+ }
+}
+
+void tst_QToolBar::iconSize()
+{
+ {
+ QToolBar tb;
+
+ QSignalSpy spy(&tb, SIGNAL(iconSizeChanged(QSize)));
+
+ // the default is determined by the style
+ const int metric = tb.style()->pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QSize defaultIconSize = QSize(metric, metric);
+ const QSize smallIconSize = QSize(metric / 2, metric / 2);
+ const QSize largeIconSize = QSize(metric * 2, metric * 2);
+
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ tb.setIconSize(defaultIconSize);
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(spy.count(), 0);
+
+ spy.clear();
+ tb.setIconSize(largeIconSize);
+ QCOMPARE(tb.iconSize(), largeIconSize);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.first().first().toSize(), largeIconSize);
+
+ // no-op
+ spy.clear();
+ tb.setIconSize(largeIconSize);
+ QCOMPARE(tb.iconSize(), largeIconSize);
+ QCOMPARE(spy.count(), 0);
+
+ spy.clear();
+ tb.setIconSize(defaultIconSize);
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.first().first().toSize(), defaultIconSize);
+
+ // no-op
+ spy.clear();
+ tb.setIconSize(defaultIconSize);
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(spy.count(), 0);
+
+ spy.clear();
+ tb.setIconSize(smallIconSize);
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.first().first().toSize(), smallIconSize);
+
+ // no-op
+ spy.clear();
+ tb.setIconSize(smallIconSize);
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(spy.count(), 0);
+
+ // setting the icon size to an invalid QSize will reset the
+ // iconSize property to the default
+ tb.setIconSize(QSize());
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(spy.first().first().toSize(), defaultIconSize);
+ spy.clear();
+ }
+
+ {
+ QMainWindow mw;
+ QToolBar tb;
+ QSignalSpy mwSpy(&mw, SIGNAL(iconSizeChanged(QSize)));
+ QSignalSpy tbSpy(&tb, SIGNAL(iconSizeChanged(QSize)));
+
+ // the default is determined by the style
+ const int metric = tb.style()->pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QSize defaultIconSize = QSize(metric, metric);
+ const QSize smallIconSize = QSize(metric / 2, metric / 2);
+ const QSize largeIconSize = QSize(metric * 2, metric * 2);
+
+ mw.setIconSize(smallIconSize);
+
+ // explicitly set it to the default
+ tb.setIconSize(defaultIconSize);
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.addToolBar(&tb);
+
+ // tb icon size should not change since it has been explicitly set
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.setIconSize(largeIconSize);
+
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.setIconSize(defaultIconSize);
+
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.setIconSize(smallIconSize);
+
+ QCOMPARE(tb.iconSize(), defaultIconSize);
+ QCOMPARE(tbSpy.count(), 0);
+
+ // resetting to the default should cause the toolbar to take
+ // on the mainwindow's icon size
+ tb.setIconSize(QSize());
+ QCOMPARE(tb.iconSize(), smallIconSize);
+ QCOMPARE(tbSpy.size(), 1);
+ QCOMPARE(tbSpy.first().first().toSize(), smallIconSize);
+ tbSpy.clear();
+ }
+}
+
+void tst_QToolBar::toolButtonStyle()
+{
+ {
+ QToolBar tb;
+
+ QSignalSpy spy(&tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+
+ // no-op
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ tb.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(spy.count(), 0);
+
+ tb.setToolButtonStyle(Qt::ToolButtonTextOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+
+ // no-op
+ tb.setToolButtonStyle(Qt::ToolButtonTextOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextOnly);
+ QCOMPARE(spy.count(), 0);
+
+ tb.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+
+ // no-op
+ tb.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(spy.count(), 0);
+
+ tb.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+
+ // no-op
+ tb.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon);
+ QCOMPARE(spy.count(), 0);
+
+ tb.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+
+ // no-op
+ tb.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon);
+ QCOMPARE(spy.count(), 0);
+
+ tb.setToolButtonStyle(Qt::ToolButtonFollowStyle);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonFollowStyle);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ {
+ QMainWindow mw;
+ QToolBar tb;
+ QSignalSpy mwSpy(&mw, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+ QSignalSpy tbSpy(&tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)));
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+
+ // explicitly set the tb to the default
+ tb.setToolButtonStyle(Qt::ToolButtonIconOnly);
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.addToolBar(&tb);
+
+ // tb icon size should not change since it has been explicitly set
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonIconOnly);
+
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextOnly);
+
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tbSpy.count(), 0);
+
+ mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+
+ QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly);
+ QCOMPARE(tbSpy.count(), 0);
+
+ // note: there is no way to clear the explicitly set tool
+ // button style... once you explicitly set it, the toolbar
+ // will never follow the mainwindow again
+ }
+}
+
+void tst_QToolBar::actionTriggered()
+{
+ QToolBar tb;
+ connect(&tb, SIGNAL(actionTriggered(QAction *)), SLOT(slot(QAction *)));
+
+ QAction action1(0);
+ QAction action2(0);
+ QAction action3(0);
+ QAction action4(0);
+
+ tb.addAction(&action1);
+ tb.addAction(&action2);
+ tb.addAction(&action3);
+ tb.addAction(&action4);
+
+ tb.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&tb);
+#endif
+
+ QList<QToolBarExtension *> extensions = tb.findChildren<QToolBarExtension *>();
+
+ QRect rect01;
+ QRect rect02;
+ QRect rect03;
+ QRect rect04;
+ QMenu *popupMenu;
+
+ if (extensions.size() != 0)
+ {
+ QToolBarExtension *extension = extensions.at(0);
+ if (extension->isVisible()) {
+ QRect rect0 = extension->geometry();
+ QTest::mouseClick( extension, Qt::LeftButton, 0, rect0.center(), -1 );
+ QApplication::processEvents();
+ popupMenu = qobject_cast<QMenu *>(extension->menu());
+ rect01 = popupMenu->actionGeometry(&action1);
+ rect02 = popupMenu->actionGeometry(&action2);
+ rect03 = popupMenu->actionGeometry(&action3);
+ rect04 = popupMenu->actionGeometry(&action4);
+ }
+ }
+
+ QRect rect1 = tb.actionGeometry(&action1);
+ QRect rect2 = tb.actionGeometry(&action2);
+ QRect rect3 = tb.actionGeometry(&action3);
+ QRect rect4 = tb.actionGeometry(&action4);
+
+ QAbstractButton *button1;
+ QAbstractButton *button2;
+ QAbstractButton *button3;
+ QAbstractButton *button4;
+
+ if (!rect01.isValid()) {
+ button1 = qobject_cast<QAbstractButton *>(tb.childAt(rect1.center()));
+ QVERIFY(button1 != 0);
+ }
+ if (!rect02.isValid()) {
+ button2 = qobject_cast<QAbstractButton *>(tb.childAt(rect2.center()));
+ QVERIFY(button2 != 0);
+ }
+ if (!rect03.isValid()) {
+ button3 = qobject_cast<QAbstractButton *>(tb.childAt(rect3.center()));
+ QVERIFY(button3 != 0);
+ }
+ if (!rect04.isValid()) {
+ button4 = qobject_cast<QAbstractButton *>(tb.childAt(rect4.center()));
+ QVERIFY(button4 != 0);
+ }
+
+ ::triggered = 0;
+ if (!rect01.isValid())
+ QTest::mouseClick(button1, Qt::LeftButton);
+ else
+ QTest::mouseClick(popupMenu, Qt::LeftButton, 0, rect01.center(), -1 );
+ QCOMPARE(::triggered, &action1);
+
+ ::triggered = 0;
+ if (!rect02.isValid())
+ QTest::mouseClick(button2, Qt::LeftButton);
+ else
+ QTest::mouseClick(popupMenu, Qt::LeftButton, 0, rect02.center(), -1 );
+ QCOMPARE(::triggered, &action2);
+
+ ::triggered = 0;
+ if (!rect03.isValid())
+ QTest::mouseClick(button3, Qt::LeftButton);
+ else
+ QTest::mouseClick(popupMenu, Qt::LeftButton, 0, rect03.center(), -1 );
+ QCOMPARE(::triggered, &action3);
+
+ ::triggered = 0;
+ if (!rect04.isValid())
+ QTest::mouseClick(button4, Qt::LeftButton);
+ else
+ QTest::mouseClick(popupMenu, Qt::LeftButton, 0, rect04.center(), -1 );
+ QCOMPARE(::triggered, &action4);
+}
+
+void tst_QToolBar::visibilityChanged()
+{
+ QMainWindow mw;
+ QToolBar tb;
+ QSignalSpy spy(&tb, SIGNAL(visibilityChanged(bool)));
+
+ mw.addToolBar(&tb);
+ mw.show();
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+ spy.clear();
+
+ tb.hide();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), false);
+ spy.clear();
+
+ tb.hide();
+ QCOMPARE(spy.count(), 0);
+
+ tb.show();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+ spy.clear();
+
+ tb.show();
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QToolBar::actionOwnership()
+{
+ {
+ QToolBar *tb1 = new QToolBar;
+ QToolBar *tb2 = new QToolBar;
+
+ QPointer<QAction> action = tb1->addAction("test");
+ QVERIFY(action->parent() == tb1);
+
+ tb2->addAction(action);
+ QVERIFY(action->parent() == tb1);
+
+ delete tb1;
+ QVERIFY(!action);
+ delete tb2;
+ }
+ {
+ QToolBar *tb1 = new QToolBar;
+ QToolBar *tb2 = new QToolBar;
+
+ QPointer<QAction> action = tb1->addAction("test");
+ QVERIFY(action->parent() == tb1);
+
+ tb1->removeAction(action);
+ QVERIFY(action->parent() == tb1);
+
+ tb2->addAction(action);
+ QVERIFY(action->parent() == tb1);
+
+ delete tb1;
+ QVERIFY(!action);
+ delete tb2;
+ }
+}
+
+void tst_QToolBar::widgetAction()
+{
+ // ensure that a QWidgetAction without widget behaves like a normal action
+ QToolBar tb;
+ QWidgetAction *a = new QWidgetAction(0);
+ a->setIconText("Blah");
+
+ tb.addAction(a);
+ QWidget *w = tb.widgetForAction(a);
+ QVERIFY(w);
+ QToolButton *button = qobject_cast<QToolButton *>(w);
+ QVERIFY(button);
+ QCOMPARE(a->iconText(), button->text());
+
+ delete a;
+}
+
+void tst_QToolBar::accel()
+{
+#ifdef Q_WS_MAC
+ extern void qt_set_sequence_auto_mnemonic(bool b);
+ qt_set_sequence_auto_mnemonic(true);
+#endif
+ QMainWindow mw;
+ QToolBar *toolBar = mw.addToolBar("test");
+ QAction *action = toolBar->addAction("&test");
+ action->setIconText(action->text()); // we really want that mnemonic in the button!
+
+ QSignalSpy spy(action, SIGNAL(triggered(bool)));
+
+ mw.show();
+ QApplication::setActiveWindow(&mw);
+ QTest::qWait(100);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&mw));
+
+ QTest::keyClick(&mw, Qt::Key_T, Qt::AltModifier);
+ QTest::qWait(300);
+
+ QTRY_COMPARE(spy.count(), 1);
+#ifdef Q_WS_MAC
+ qt_set_sequence_auto_mnemonic(false);
+#endif
+}
+
+void tst_QToolBar::task191727_layout()
+{
+ QMainWindow mw;
+ QToolBar *toolBar = mw.addToolBar("test");
+ toolBar->addAction("one");
+ QAction *action = toolBar->addAction("two");
+
+ QLineEdit *lineedit = new QLineEdit;
+ lineedit->setMaximumWidth(50);
+ toolBar->addWidget(lineedit);
+
+ mw.resize(400, 400);
+ mw.show();
+
+ QWidget *actionwidget = toolBar->widgetForAction(action);
+ QVERIFY(qAbs(lineedit->pos().x() - (actionwidget->geometry().right() + 1 + toolBar->layout()->spacing())) < 2);
+}
+
+void tst_QToolBar::task197996_visibility()
+{
+ QMainWindow mw;
+ QToolBar *toolBar = new QToolBar(&mw);
+
+ mw.addToolBar(toolBar);
+ toolBar->addAction(new QAction("Foo", &mw));
+ QAction *pAction = new QAction("Test", &mw);
+ toolBar->addAction(pAction);
+
+ pAction->setVisible(false);
+ toolBar->setVisible(false);
+
+ toolBar->setVisible(true);
+ pAction->setVisible(true);
+
+ mw.show();
+
+ QVERIFY(toolBar->widgetForAction(pAction)->isVisible());
+
+ toolBar->setVisible(false);
+ pAction->setVisible(false);
+
+ toolBar->setVisible(true);
+ pAction->setVisible(true);
+
+ QTest::qWait(100);
+
+ QVERIFY(toolBar->widgetForAction(pAction)->isVisible());
+
+}
+
+QTEST_MAIN(tst_QToolBar)
+#include "tst_qtoolbar.moc"
diff --git a/tests/auto/widgets/widgets/qtoolbox/.gitignore b/tests/auto/widgets/widgets/qtoolbox/.gitignore
new file mode 100644
index 0000000000..f586175dcb
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbox/.gitignore
@@ -0,0 +1 @@
+tst_qtoolbox
diff --git a/tests/auto/widgets/widgets/qtoolbox/qtoolbox.pro b/tests/auto/widgets/widgets/qtoolbox/qtoolbox.pro
new file mode 100644
index 0000000000..24f3ea6cb9
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbox/qtoolbox.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtoolbox.cpp
+
+
+
diff --git a/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp b/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp
new file mode 100644
index 0000000000..2288eee5f4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qtoolbox.h>
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+QT_FORWARD_DECLARE_CLASS(QToolBox)
+
+class tst_QToolBoxPrivate;
+
+class tst_QToolBox : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QToolBox();
+ virtual ~tst_QToolBox();
+
+protected slots:
+ void currentChanged(int);
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void populate();
+ void change();
+ void clear();
+
+private:
+ QToolBox *testWidget;
+ int currentIndex;
+
+ tst_QToolBoxPrivate *d;
+};
+
+// Testing get/set functions
+void tst_QToolBox::getSetCheck()
+{
+ QToolBox obj1;
+ QWidget *w1 = new QWidget;
+ QWidget *w2 = new QWidget;
+ QWidget *w3 = new QWidget;
+ QWidget *w4 = new QWidget;
+ QWidget *w5 = new QWidget;
+ obj1.addItem(w1, "Page1");
+ obj1.addItem(w2, "Page2");
+ obj1.addItem(w3, "Page3");
+ obj1.addItem(w4, "Page4");
+ obj1.addItem(w5, "Page5");
+
+ // int QToolBox::currentIndex()
+ // void QToolBox::setCurrentIndex(int)
+ obj1.setCurrentIndex(3);
+ QCOMPARE(3, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(3, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(3, obj1.currentIndex());
+ obj1.setCurrentIndex(4);
+ QCOMPARE(4, obj1.currentIndex());
+
+ // QWidget * QToolBox::currentWidget()
+ // void QToolBox::setCurrentWidget(QWidget *)
+ obj1.setCurrentWidget(w1);
+ QCOMPARE(w1, obj1.currentWidget());
+ obj1.setCurrentWidget(w3);
+ QCOMPARE(w3, obj1.currentWidget());
+
+ obj1.setCurrentWidget((QWidget *)0);
+ QCOMPARE(w3, obj1.currentWidget());
+}
+
+tst_QToolBox::tst_QToolBox()
+{
+}
+
+tst_QToolBox::~tst_QToolBox()
+{
+}
+
+class tst_QToolBoxPrivate
+{
+public:
+ int count0, count1, count2, count3, count4;
+ int idx1, idx2, idx3, idx32;
+ int i0, i1, i2, i3, i4;
+ int ci0, ci1, ci2, ci3, ci4;
+ bool ci_correct;
+
+ int manual_count;
+};
+
+void tst_QToolBox::init()
+{
+ currentIndex = -1;
+ testWidget = new QToolBox;
+ connect(testWidget, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)));
+
+ d = new tst_QToolBoxPrivate;
+
+
+ d->count0 = testWidget->count();
+ d->ci0 = currentIndex;
+
+ QWidget *item1 = new QWidget( testWidget );
+ testWidget->addItem( item1, "Item1" );
+
+ d->count1 = testWidget->count();
+ d->idx1 = testWidget->indexOf(item1);
+ d->ci1 = currentIndex;
+ d->ci_correct = testWidget->widget(testWidget->currentIndex()) == item1;
+
+ currentIndex = -1; // reset to make sure signal doesn't fire
+
+ QWidget *item3 = new QWidget( testWidget );
+ testWidget->addItem( item3, "Item3" );
+
+ d->count2 = testWidget->count();
+ d->idx3 = testWidget->indexOf(item3);
+ d->ci2 = currentIndex;
+
+
+ QWidget *item2 = new QWidget( testWidget );
+ testWidget->insertItem( 1, item2, "Item2");
+
+ d->count3 = testWidget->count();
+ d->idx2 = testWidget->indexOf(item2);
+ d->idx32 = testWidget->indexOf(item3);
+ d->ci3 = currentIndex;
+
+ QWidget *item0 = new QWidget( testWidget );
+ testWidget->insertItem( 0, item0, "Item0");
+
+ d->count4 = testWidget->count();
+ d->i0 = testWidget->indexOf(item0);
+ d->i1 = testWidget->indexOf(item1);
+ d->i2 = testWidget->indexOf(item2);
+ d->i3 = testWidget->indexOf(item3);
+ d->ci4 = currentIndex;
+
+ d->manual_count = 4;
+}
+
+void tst_QToolBox::cleanup()
+{
+ delete testWidget;
+ delete d;
+}
+
+void tst_QToolBox::initTestCase()
+{
+}
+
+void tst_QToolBox::cleanupTestCase()
+{
+}
+
+void tst_QToolBox::currentChanged(int index)
+{
+ currentIndex = index;
+}
+
+void tst_QToolBox::populate()
+{
+ // verify preconditions
+ QCOMPARE( d->count0, 0 );
+ QCOMPARE( d->ci0, -1 );
+ QVERIFY( d->ci_correct );
+
+ QCOMPARE( d->count1, 1 );
+ QCOMPARE( d->idx1, 0 );
+ QCOMPARE( d->ci1, 0 );
+
+ QCOMPARE( d->count2, 2 );
+ QCOMPARE( d->idx3, 1 );
+ QCOMPARE( d->ci2, -1 );
+
+ QCOMPARE( d->count3, 3 );
+ QCOMPARE( d->idx2, 1 );
+ QCOMPARE( d->idx32, 2 );
+ QCOMPARE( d->ci3, -1 );
+
+
+ QCOMPARE( d->count4, 4 );
+ QCOMPARE( d->i0, 0 );
+ QCOMPARE( d->i1, 1 );
+ QCOMPARE( d->i2, 2 );
+ QCOMPARE( d->i3, 3 );
+ QCOMPARE( d->ci4, 1 );
+
+ QCOMPARE (testWidget->count(), d->manual_count);
+ int oldcount = testWidget->count();
+
+ QWidget *item = new QWidget( testWidget );
+ testWidget->addItem( item, "Item");
+ d->manual_count++;
+
+ QCOMPARE( testWidget->count(), oldcount+1 );
+ QCOMPARE( testWidget->indexOf(item), oldcount );
+ QCOMPARE( testWidget->widget(oldcount), item );
+}
+
+void tst_QToolBox::change()
+{
+ QWidget *lastItem = testWidget->widget(testWidget->count());
+ QVERIFY( !lastItem );
+ lastItem = testWidget->widget(testWidget->count() - 1);
+ QVERIFY( lastItem );
+
+ for ( int c = 0; c < testWidget->count(); ++c ) {
+ QString label = "Item " + QString::number(c);
+ testWidget->setItemText(c, label);
+ QCOMPARE( testWidget->itemText(c), label );
+ }
+
+ testWidget->setCurrentIndex( 0 );
+ QCOMPARE( currentIndex, 0 );
+
+ currentIndex = -1; // reset to make sure signal doesn't fire
+ testWidget->setCurrentIndex( 0 );
+ QCOMPARE( currentIndex, -1 );
+ QCOMPARE( testWidget->currentIndex(), 0 );
+
+ testWidget->setCurrentIndex( testWidget->count() );
+ QCOMPARE( currentIndex, -1 );
+ QCOMPARE( testWidget->currentIndex(), 0 );
+
+ testWidget->setCurrentIndex( 1 );
+ QCOMPARE( currentIndex, 1 );
+ QCOMPARE( testWidget->currentIndex(), 1 );
+
+ testWidget->setItemEnabled( testWidget->currentIndex(), FALSE );
+ QCOMPARE( currentIndex, 2 );
+ QCOMPARE( testWidget->currentIndex(), 2 );
+
+ currentIndex = -1;
+ testWidget->setItemEnabled( testWidget->indexOf(lastItem), FALSE );
+ QCOMPARE( currentIndex, -1 );
+ QCOMPARE( testWidget->currentIndex(), 2 );
+
+ testWidget->setItemEnabled( testWidget->currentIndex(), FALSE );
+ QCOMPARE( currentIndex, 0 );
+
+ currentIndex = -1;
+ testWidget->setItemEnabled( testWidget->currentIndex(), FALSE );
+ QCOMPARE( currentIndex, -1 );
+
+ testWidget->setItemEnabled( 1, TRUE );
+}
+
+void tst_QToolBox::clear()
+{
+ // precondition: only item(1) is enabled
+ QCOMPARE( testWidget->count(), 4 );
+ testWidget->setCurrentIndex(0);
+ currentIndex = -1;
+
+ // delete current item(0)
+ QPointer<QWidget> item = testWidget->widget(testWidget->currentIndex());
+ testWidget->removeItem(testWidget->indexOf(item));
+ QVERIFY(item);
+ QCOMPARE( testWidget->count(), 3 );
+ QCOMPARE( testWidget->indexOf(item), -1 );
+ QCOMPARE( testWidget->currentIndex(), 0 );
+ QCOMPARE(currentIndex, 0 );
+
+ currentIndex = -1;
+
+ item = testWidget->widget(1);
+ testWidget->removeItem(testWidget->indexOf(item));
+ QVERIFY( item );
+ QCOMPARE( currentIndex, -1 );
+ QCOMPARE( testWidget->currentIndex(), 0 );
+ QCOMPARE( testWidget->count(), 2 );
+ QCOMPARE( testWidget->indexOf(item), -1 );
+
+ item = testWidget->widget(1);
+ delete item;
+ QCOMPARE( testWidget->count(), 1 );
+ QCOMPARE( currentIndex, -1 );
+ currentIndex = testWidget->currentIndex();
+
+ item = testWidget->widget(0);
+ testWidget->removeItem(testWidget->indexOf(item));
+ QCOMPARE( testWidget->count(), 0 );
+ QCOMPARE( currentIndex, -1 );
+}
+
+QTEST_MAIN(tst_QToolBox)
+#include "tst_qtoolbox.moc"
diff --git a/tests/auto/widgets/widgets/qtoolbutton/.gitignore b/tests/auto/widgets/widgets/qtoolbutton/.gitignore
new file mode 100644
index 0000000000..91e11101e1
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbutton/.gitignore
@@ -0,0 +1 @@
+tst_qtoolbutton
diff --git a/tests/auto/widgets/widgets/qtoolbutton/qtoolbutton.pro b/tests/auto/widgets/widgets/qtoolbutton/qtoolbutton.pro
new file mode 100644
index 0000000000..5f082682ad
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbutton/qtoolbutton.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtoolbutton.cpp
diff --git a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
new file mode 100644
index 0000000000..0e21ea6611
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qtoolbutton.h>
+#include <qmenu.h>
+#include <qaction.h>
+#include <qwindowsstyle.h>
+#include <qstyleoption.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QToolButton : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QToolButton();
+ virtual ~tst_QToolButton();
+
+private slots:
+ void getSetCheck();
+ void triggered();
+ void collapseTextOnPriority();
+ void task230994_iconSize();
+ void task176137_autoRepeatOfAction();
+
+protected slots:
+ void sendMouseClick();
+private:
+ QWidget *w;
+};
+
+tst_QToolButton::tst_QToolButton()
+{
+}
+
+tst_QToolButton::~tst_QToolButton()
+{
+}
+
+// Testing get/set functions
+void tst_QToolButton::getSetCheck()
+{
+ QToolButton obj1;
+ // QMenu* QToolButton::menu()
+ // void QToolButton::setMenu(QMenu*)
+ QMenu *var1 = new QMenu;
+ obj1.setMenu(var1);
+ QCOMPARE(var1, obj1.menu());
+ obj1.setMenu((QMenu *)0);
+ QCOMPARE((QMenu *)0, obj1.menu());
+ delete var1;
+
+ // ToolButtonPopupMode QToolButton::popupMode()
+ // void QToolButton::setPopupMode(ToolButtonPopupMode)
+ obj1.setPopupMode(QToolButton::ToolButtonPopupMode(QToolButton::DelayedPopup));
+ QCOMPARE(QToolButton::ToolButtonPopupMode(QToolButton::DelayedPopup), obj1.popupMode());
+ obj1.setPopupMode(QToolButton::ToolButtonPopupMode(QToolButton::MenuButtonPopup));
+ QCOMPARE(QToolButton::ToolButtonPopupMode(QToolButton::MenuButtonPopup), obj1.popupMode());
+ obj1.setPopupMode(QToolButton::ToolButtonPopupMode(QToolButton::InstantPopup));
+ QCOMPARE(QToolButton::ToolButtonPopupMode(QToolButton::InstantPopup), obj1.popupMode());
+
+ // bool QToolButton::autoRaise()
+ // void QToolButton::setAutoRaise(bool)
+ obj1.setAutoRaise(false);
+ QCOMPARE(false, obj1.autoRaise());
+ obj1.setAutoRaise(true);
+ QCOMPARE(true, obj1.autoRaise());
+
+ // QAction * QToolButton::defaultAction()
+ // void QToolButton::setDefaultAction(QAction *)
+ QAction *var4 = new QAction(0);
+ obj1.setDefaultAction(var4);
+ QCOMPARE(var4, obj1.defaultAction());
+ obj1.setDefaultAction((QAction *)0);
+ QCOMPARE((QAction *)0, obj1.defaultAction());
+ delete var4;
+}
+
+Q_DECLARE_METATYPE(QAction*)
+
+void tst_QToolButton::triggered()
+{
+ qRegisterMetaType<QAction *>("QAction *");
+ QToolButton tb;
+ tb.show();
+ QSignalSpy spy(&tb,SIGNAL(triggered(QAction*)));
+ QMenu *menu = new QMenu("Menu");
+ QAction *one = menu->addAction("one");
+ menu->addAction("two");
+ QAction *def = new QAction("def", this);
+
+ tb.setMenu(menu);
+ tb.setDefaultAction(def);
+
+#ifdef Q_WS_QWS
+ QApplication::processEvents(); //wait for the window system to show the tool button
+#endif
+
+ def->trigger();
+ QCOMPARE(spy.count(),1);
+ QCOMPARE(qvariant_cast<QAction *>(spy.at(0).at(0)), def);
+
+ w = menu;
+ QTimer::singleShot(30, this, SLOT(sendMouseClick()));
+ tb.showMenu();
+ QTest::qWait(20);
+ QCOMPARE(spy.count(),2);
+ QCOMPARE(qvariant_cast<QAction *>(spy.at(1).at(0)), one);
+ delete menu;
+}
+
+void tst_QToolButton::collapseTextOnPriority()
+{
+ class MyToolButton : public QToolButton
+ {
+ friend class tst_QToolButton;
+ public:
+ void initStyleOption(QStyleOptionToolButton *option)
+ {
+ QToolButton::initStyleOption(option);
+ }
+ };
+
+ MyToolButton button;
+ button.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ QAction action(button.style()->standardIcon(QStyle::SP_ArrowBack), "test", 0);
+ button.setDefaultAction(&action);
+
+ QStyleOptionToolButton option;
+ button.initStyleOption(&option);
+ QVERIFY(option.toolButtonStyle == Qt::ToolButtonTextBesideIcon);
+ action.setPriority(QAction::LowPriority);
+ button.initStyleOption(&option);
+ QVERIFY(option.toolButtonStyle == Qt::ToolButtonIconOnly);
+}
+
+
+void tst_QToolButton::task230994_iconSize()
+{
+ //we check that the iconsize returned bu initStyleOption is valid
+ //when the toolbutton has no parent
+ class MyToolButton : public QToolButton
+ {
+ friend class tst_QToolButton;
+ public:
+ void initStyleOption(QStyleOptionToolButton *option)
+ {
+ QToolButton::initStyleOption(option);
+ }
+ };
+
+ MyToolButton button;
+ QStyleOptionToolButton option;
+ button.initStyleOption(&option);
+ QVERIFY(option.iconSize.isValid());
+}
+
+void tst_QToolButton::task176137_autoRepeatOfAction()
+{
+ QAction action(0);
+ QToolButton tb;
+ tb.setDefaultAction (&action);
+ tb.show();
+ QSignalSpy spy(&action,SIGNAL(triggered()));
+ QTest::mousePress ( &tb, Qt::LeftButton);
+ QTest::mouseRelease ( &tb, Qt::LeftButton, 0, QPoint (), 2000);
+ QCOMPARE(spy.count(),1);
+
+ // try again with auto repeat
+ tb.setAutoRepeat (true);
+ QSignalSpy repeatSpy(&action,SIGNAL(triggered())); // new spy
+ QTest::mousePress ( &tb, Qt::LeftButton);
+ QTest::mouseRelease ( &tb, Qt::LeftButton, 0, QPoint (), 3000);
+ qreal expected = (3000 - tb.autoRepeatDelay()) / tb.autoRepeatInterval() + 1;
+ //we check that the difference is less than 10% (on some systems timers are not super accurate)
+ QVERIFY ( qAbs( (expected - repeatSpy.count()) / expected) < 0.1);
+}
+
+
+void tst_QToolButton::sendMouseClick()
+{
+ QTest::mouseClick(w, Qt::LeftButton, 0, QPoint(7,7));
+}
+
+QTEST_MAIN(tst_QToolButton)
+#include "tst_qtoolbutton.moc"
diff --git a/tests/auto/widgets/widgets/qworkspace/.gitignore b/tests/auto/widgets/widgets/qworkspace/.gitignore
new file mode 100644
index 0000000000..73facc366e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qworkspace/.gitignore
@@ -0,0 +1 @@
+tst_qworkspace
diff --git a/tests/auto/widgets/widgets/qworkspace/qworkspace.pro b/tests/auto/widgets/widgets/qworkspace/qworkspace.pro
new file mode 100644
index 0000000000..0b8a604fe8
--- /dev/null
+++ b/tests/auto/widgets/widgets/qworkspace/qworkspace.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qworkspace.cpp
diff --git a/tests/auto/widgets/widgets/qworkspace/tst_qworkspace.cpp b/tests/auto/widgets/widgets/qworkspace/tst_qworkspace.cpp
new file mode 100644
index 0000000000..a996c38438
--- /dev/null
+++ b/tests/auto/widgets/widgets/qworkspace/tst_qworkspace.cpp
@@ -0,0 +1,679 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qmenubar.h>
+#include <qworkspace.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QWorkspace : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWorkspace();
+ virtual ~tst_QWorkspace();
+
+
+protected slots:
+ void activeChanged( QWidget *w );
+ void accelActivated();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void windowActivated_data();
+ void windowActivated();
+ void windowActivatedWithMinimize();
+ void showWindows();
+ void changeWindowTitle();
+ void changeModified();
+ void childSize();
+ void fixedSize();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ void nativeSubWindows();
+#endif
+ void task206368();
+
+private:
+ QWidget *activeWidget;
+ bool accelPressed;
+};
+
+// Testing get/set functions
+void tst_QWorkspace::getSetCheck()
+{
+ QWorkspace obj1;
+ // bool QWorkspace::scrollBarsEnabled()
+ // void QWorkspace::setScrollBarsEnabled(bool)
+ obj1.setScrollBarsEnabled(false);
+ QCOMPARE(false, obj1.scrollBarsEnabled());
+ obj1.setScrollBarsEnabled(true);
+ QCOMPARE(true, obj1.scrollBarsEnabled());
+}
+
+tst_QWorkspace::tst_QWorkspace()
+ : activeWidget( 0 )
+{
+}
+
+tst_QWorkspace::~tst_QWorkspace()
+{
+
+}
+
+// initTestCase will be executed once before the first testfunction is executed.
+void tst_QWorkspace::initTestCase()
+{
+
+}
+
+// cleanupTestCase will be executed once after the last testfunction is executed.
+void tst_QWorkspace::cleanupTestCase()
+{
+}
+
+// init() will be executed immediately before each testfunction is run.
+void tst_QWorkspace::init()
+{
+// TODO: Add testfunction specific initialization code here.
+}
+
+// cleanup() will be executed immediately after each testfunction is run.
+void tst_QWorkspace::cleanup()
+{
+// TODO: Add testfunction specific cleanup code here.
+}
+
+void tst_QWorkspace::activeChanged( QWidget *w )
+{
+ activeWidget = w;
+}
+
+void tst_QWorkspace::windowActivated_data()
+{
+ // define the test elements we're going to use
+ QTest::addColumn<int>("count");
+
+ // create a first testdata instance and fill it with data
+ QTest::newRow( "data0" ) << 0;
+ QTest::newRow( "data1" ) << 1;
+ QTest::newRow( "data2" ) << 2;
+}
+
+void tst_QWorkspace::windowActivated()
+{
+ QMainWindow mw(0, Qt::X11BypassWindowManagerHint);
+ mw.menuBar();
+ QWorkspace *workspace = new QWorkspace(&mw);
+ workspace->setObjectName("testWidget");
+ mw.setCentralWidget(workspace);
+ QSignalSpy spy(workspace, SIGNAL(windowActivated(QWidget*)));
+ connect( workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(activeChanged(QWidget*)) );
+ mw.show();
+ qApp->setActiveWindow(&mw);
+
+ QFETCH( int, count );
+ int i;
+
+ for ( i = 0; i < count; ++i ) {
+ QWidget *widget = new QWidget(workspace, 0);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addWindow(widget);
+ widget->show();
+ qApp->processEvents();
+ QVERIFY( activeWidget == workspace->activeWindow() );
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+
+ QWidgetList windows = workspace->windowList();
+ QCOMPARE( (int)windows.count(), count );
+
+ for ( i = 0; i < count; ++i ) {
+ QWidget *window = windows.at(i);
+ window->showMinimized();
+ qApp->processEvents();
+ QVERIFY( activeWidget == workspace->activeWindow() );
+ if ( i == 1 )
+ QVERIFY( activeWidget == window );
+ }
+
+ for ( i = 0; i < count; ++i ) {
+ QWidget *window = windows.at(i);
+ window->showNormal();
+ qApp->processEvents();
+ QVERIFY( window == activeWidget );
+ QVERIFY( activeWidget == workspace->activeWindow() );
+ }
+ spy.clear();
+
+ while ( workspace->activeWindow() ) {
+ workspace->activeWindow()->close();
+ qApp->processEvents();
+ QVERIFY( activeWidget == workspace->activeWindow() );
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QVERIFY(activeWidget == 0);
+ QVERIFY(workspace->activeWindow() == 0);
+ QVERIFY(workspace->windowList().count() == 0);
+
+ {
+ workspace->hide();
+ QWidget *widget = new QWidget(workspace);
+ widget->setObjectName("normal");
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addWindow(widget);
+ widget->show();
+ QCOMPARE(spy.count(), 0);
+ workspace->show();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWidget == widget );
+ widget->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWidget == 0 );
+ }
+
+ {
+ workspace->hide();
+ QWidget *widget = new QWidget(workspace);
+ widget->setObjectName("maximized");
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addWindow(widget);
+ widget->showMaximized();
+ qApp->sendPostedEvents();
+#ifdef Q_WS_MAC
+ QEXPECT_FAIL("", "This test has never passed on Mac. QWorkspace is obsoleted -> won't fix", Abort);
+#endif
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+ workspace->show();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWidget == widget );
+ widget->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWidget == 0 );
+ }
+
+ {
+ QWidget *widget = new QWidget(workspace);
+ widget->setObjectName("minimized");
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addWindow(widget);
+ widget->showMinimized();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWidget == widget );
+ QVERIFY(workspace->activeWindow() == widget);
+ widget->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY(workspace->activeWindow() == 0);
+ QVERIFY( activeWidget == 0 );
+ }
+}
+void tst_QWorkspace::windowActivatedWithMinimize()
+{
+ QMainWindow mw(0, Qt::X11BypassWindowManagerHint) ;
+ mw.menuBar();
+ QWorkspace *workspace = new QWorkspace(&mw);
+ workspace->setObjectName("testWidget");
+ mw.setCentralWidget(workspace);
+ QSignalSpy spy(workspace, SIGNAL(windowActivated(QWidget*)));
+ connect( workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(activeChanged(QWidget*)) );
+ mw.show();
+ qApp->setActiveWindow(&mw);
+ QWidget *widget = new QWidget(workspace);
+ widget->setObjectName("minimized1");
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addWindow(widget);
+ QWidget *widget2 = new QWidget(workspace);
+ widget2->setObjectName("minimized2");
+ widget2->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addWindow(widget2);
+
+ widget->showMinimized();
+ QVERIFY( activeWidget == widget );
+ widget2->showMinimized();
+ QVERIFY( activeWidget == widget2 );
+
+ widget2->close();
+ qApp->processEvents();
+ QVERIFY( activeWidget == widget );
+
+ widget->close();
+ qApp->processEvents();
+ QVERIFY(workspace->activeWindow() == 0);
+ QVERIFY( activeWidget == 0 );
+
+ QVERIFY( workspace->windowList().count() == 0 );
+}
+
+void tst_QWorkspace::accelActivated()
+{
+ accelPressed = TRUE;
+}
+
+void tst_QWorkspace::showWindows()
+{
+ QWorkspace *ws = new QWorkspace( 0 );
+
+ QWidget *widget = 0;
+ ws->show();
+
+ widget = new QWidget(ws);
+ widget->setObjectName("plain1");
+ widget->show();
+ QVERIFY( widget->isVisible() );
+
+ widget = new QWidget(ws);
+ widget->setObjectName("maximized1");
+ widget->showMaximized();
+ QVERIFY( widget->isMaximized() );
+ widget->showNormal();
+ QVERIFY( !widget->isMaximized() );
+
+ widget = new QWidget(ws);
+ widget->setObjectName("minimized1");
+ widget->showMinimized();
+ QVERIFY( widget->isMinimized() );
+ widget->showNormal();
+ QVERIFY( !widget->isMinimized() );
+
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->setObjectName("plain2");
+ ws->show();
+ QVERIFY( widget->isVisible() );
+
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->setObjectName("maximized2");
+ widget->showMaximized();
+ QVERIFY( widget->isMaximized() );
+ ws->show();
+ QVERIFY( widget->isVisible() );
+ QVERIFY( widget->isMaximized() );
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->setObjectName("minimized2");
+ widget->showMinimized();
+ ws->show();
+ QVERIFY( widget->isMinimized() );
+ ws->hide();
+
+ delete ws;
+}
+
+
+//#define USE_SHOW
+
+void tst_QWorkspace::changeWindowTitle()
+{
+#ifdef Q_OS_WINCE
+ QSKIP( "Test fails on Windows CE due to QWorkspace state handling", SkipAll);
+#endif
+ const QString mwc( "MainWindow's Caption" );
+ const QString mwc2( "MainWindow's New Caption" );
+ const QString wc( "Widget's Caption" );
+ const QString wc2( "Widget's New Caption" );
+
+ QMainWindow *mw = new QMainWindow(0, Qt::X11BypassWindowManagerHint);
+ mw->setWindowTitle( mwc );
+ QWorkspace *ws = new QWorkspace( mw );
+ mw->setCentralWidget( ws );
+
+
+ QWidget *widget = new QWidget( ws );
+ widget->setWindowTitle( wc );
+ ws->addWindow(widget);
+
+ QCOMPARE( mw->windowTitle(), mwc );
+
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc).arg(wc) );
+
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc).arg(wc) );
+ widget->setWindowTitle( wc2 );
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc).arg(wc2) );
+ mw->setWindowTitle( mwc2 );
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc2).arg(wc2) );
+
+ mw->show();
+ qApp->setActiveWindow(mw);
+
+#ifdef USE_SHOW
+ mw->showFullScreen();
+#else
+ mw->setWindowState(Qt::WindowFullScreen);
+#endif
+
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc2).arg(wc2) );
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), mwc2 );
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc2).arg(wc2) );
+
+#ifdef USE_SHOW
+ mw->showNormal();
+#else
+ mw->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), QString("%1 - [%2]").arg(mwc2).arg(wc2) );
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ QCOMPARE( mw->windowTitle(), mwc2 );
+
+ delete mw;
+}
+
+void tst_QWorkspace::changeModified()
+{
+ const QString mwc( "MainWindow's Caption" );
+ const QString wc( "Widget's Caption[*]" );
+
+ QMainWindow *mw = new QMainWindow(0, Qt::X11BypassWindowManagerHint);
+ mw->setWindowTitle( mwc );
+ QWorkspace *ws = new QWorkspace( mw );
+ mw->setCentralWidget( ws );
+
+ QWidget *widget = new QWidget( ws );
+ widget->setWindowTitle( wc );
+ ws->addWindow(widget);
+
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+ widget->setWindowState(Qt::WindowMaximized);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowModified(true);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+ widget->setWindowState(Qt::WindowMaximized);
+ QCOMPARE( mw->isWindowModified(), true);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowMaximized);
+ QCOMPARE( mw->isWindowModified(), true);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowModified(false);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowModified(true);
+ QCOMPARE( mw->isWindowModified(), true);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ delete mw;
+}
+
+class MyChild : public QWidget
+{
+public:
+ MyChild(QWidget *parent = 0, Qt::WFlags f = 0)
+ : QWidget(parent, f)
+ {
+ }
+
+ QSize sizeHint() const
+ {
+ return QSize(234, 123);
+ }
+};
+
+void tst_QWorkspace::childSize()
+{
+ QWorkspace ws;
+
+ MyChild *child = new MyChild(&ws);
+ child->show();
+ QCOMPARE(child->size(), child->sizeHint());
+ delete child;
+
+ child = new MyChild(&ws);
+ child->setFixedSize(200, 200);
+ child->show();
+ QCOMPARE(child->size(), child->minimumSize());
+ delete child;
+
+ child = new MyChild(&ws);
+ child->resize(150, 150);
+ child->show();
+ QCOMPARE(child->size(), QSize(150,150));
+ delete child;
+}
+
+void tst_QWorkspace::fixedSize()
+{
+ QWorkspace *ws = new QWorkspace;
+ int i;
+
+ ws->resize(500, 500);
+// ws->show();
+
+ QSize fixed(300, 300);
+ for (i = 0; i < 4; ++i) {
+ QWidget *child = new QWidget(ws);
+ child->setFixedSize(fixed);
+ child->show();
+ }
+
+ QWidgetList windows = ws->windowList();
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QWidget *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ QCOMPARE(child->visibleRegion().boundingRect().size(), fixed);
+ }
+
+ ws->cascade();
+ ws->resize(800, 800);
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QWidget *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ QCOMPARE(child->visibleRegion().boundingRect().size(), fixed);
+ }
+ ws->resize(500, 500);
+
+ ws->tile();
+ ws->resize(800, 800);
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QWidget *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ QCOMPARE(child->visibleRegion().boundingRect().size(), fixed);
+ }
+ ws->resize(500, 500);
+
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QWidget *child = windows.at(i);
+ delete child;
+ }
+
+ delete ws;
+}
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+void tst_QWorkspace::nativeSubWindows()
+{
+ { // Add native widgets after show.
+ QWorkspace workspace;
+ workspace.addWindow(new QWidget);
+ workspace.addWindow(new QWidget);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ // No native widgets.
+ foreach (QWidget *subWindow, workspace.windowList())
+ QVERIFY(!subWindow->parentWidget()->internalWinId());
+
+ QWidget *nativeWidget = new QWidget;
+ QVERIFY(nativeWidget->winId()); // enforce native window.
+ workspace.addWindow(nativeWidget);
+
+ // All the sub-windows must be native.
+ foreach (QWidget *subWindow, workspace.windowList())
+ QVERIFY(subWindow->parentWidget()->internalWinId());
+
+ // Add a non-native widget. This should become native.
+ QWidget *subWindow = workspace.addWindow(new QWidget);
+ QVERIFY(subWindow->parentWidget()->internalWinId());
+ }
+
+ { // Add native widgets before show.
+ QWorkspace workspace;
+ workspace.addWindow(new QWidget);
+ QWidget *nativeWidget = new QWidget;
+ (void)nativeWidget->winId();
+ workspace.addWindow(nativeWidget);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ // All the sub-windows must be native.
+ foreach (QWidget *subWindow, workspace.windowList())
+ QVERIFY(subWindow->parentWidget()->internalWinId());
+ }
+
+ { // Make a sub-window native *after* it's added to the area.
+ QWorkspace workspace;
+ workspace.addWindow(new QWidget);
+ workspace.addWindow(new QWidget);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ QWidget *nativeSubWindow = workspace.windowList().last()->parentWidget();
+ QVERIFY(!nativeSubWindow->internalWinId());
+ (void)nativeSubWindow->winId();
+
+ // All the sub-windows should be native at this point.
+ foreach (QWidget *subWindow, workspace.windowList())
+ QVERIFY(subWindow->parentWidget()->internalWinId());
+ }
+}
+#endif
+
+void tst_QWorkspace::task206368()
+{
+ // Make sure the internal list of iconified windows doesn't contain dangling pointers.
+ QWorkspace workspace;
+ QWidget *child = new QWidget;
+ QWidget *window = workspace.addWindow(child);
+ workspace.show();
+ child->showMinimized();
+ delete window;
+ // This shouldn't crash.
+ workspace.arrangeIcons();
+}
+
+QTEST_MAIN(tst_QWorkspace)
+#include "tst_qworkspace.moc"
diff --git a/tests/auto/widgets/widgets/widgets.pro b/tests/auto/widgets/widgets/widgets.pro
new file mode 100644
index 0000000000..e77c311cde
--- /dev/null
+++ b/tests/auto/widgets/widgets/widgets.pro
@@ -0,0 +1,57 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qabstractbutton \
+ qabstractscrollarea \
+ qabstractslider \
+ qabstractspinbox \
+ qbuttongroup \
+ qcalendarwidget \
+ qcheckbox \
+ qcombobox \
+ qcommandlinkbutton \
+ qdatetimeedit \
+ qdial \
+ qdialogbuttonbox \
+ qdockwidget \
+ qdoublespinbox \
+ qdoublevalidator \
+ qfocusframe \
+ qfontcombobox \
+ qgroupbox \
+ qintvalidator \
+ qlabel \
+ qlcdnumber \
+ qlineedit \
+ qmainwindow \
+ qmdiarea \
+ qmdisubwindow \
+ qmenu \
+ qmenubar \
+ qplaintextedit \
+ qprogressbar \
+ qpushbutton \
+ qradiobutton \
+ qregexpvalidator \
+ qscrollarea \
+ qscrollbar \
+ qsizegrip \
+ qslider \
+ qspinbox \
+ qsplitter \
+ qstackedwidget \
+ qstatusbar \
+ qtabbar \
+ qtabwidget \
+ qtextbrowser \
+ qtextedit \
+ qtoolbar \
+ qtoolbox \
+ qtoolbutton \
+ qworkspace \
+
+# The following tests depend on private API:
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qcombobox \
+ qmainwindow \
+ qtextedit \
+ qtoolbar \