From 9f1aa866bda7678261f2f441d4cfd5bb524c2411 Mon Sep 17 00:00:00 2001 From: Jo Asplin Date: Thu, 20 Oct 2011 13:17:26 +0200 Subject: Moved tests into integrationtests/ and widgets/ Task-number: QTBUG-19013 Change-Id: Ibb776f5967c0645ce6d22ef7afdc40657c575461 Reviewed-by: Holger Ihrig --- tests/auto/auto.pro | 2 + tests/auto/collections/.gitignore | 1 - tests/auto/collections/collections.pro | 4 - tests/auto/collections/tst_collections.cpp | 3846 ------- tests/auto/corelib.pro | 2 - tests/auto/corelib/kernel/kernel.pro | 2 +- .../qabstractitemmodel/qabstractitemmodel.pro | 10 +- tests/auto/exceptionsafety/.gitignore | 1 - tests/auto/exceptionsafety/exceptionsafety.pro | 4 - tests/auto/exceptionsafety/tst_exceptionsafety.cpp | 734 -- .../exceptionsafety_objects/3rdparty/memcheck.h | 319 - .../exceptionsafety_objects/3rdparty/valgrind.h | 3924 ------- .../exceptionsafety_objects.pro | 6 - tests/auto/exceptionsafety_objects/oomsimulator.h | 283 - .../tst_exceptionsafety_objects.cpp | 801 -- tests/auto/gestures/gestures.pro | 5 - tests/auto/gestures/tst_gestures.cpp | 2345 ---- tests/auto/gui.pro | 153 - tests/auto/integrationtests/collections/.gitignore | 1 + .../integrationtests/collections/collections.pro | 4 + .../collections/tst_collections.cpp | 3846 +++++++ .../integrationtests/exceptionsafety/.gitignore | 1 + .../exceptionsafety/exceptionsafety.pro | 4 + .../exceptionsafety/tst_exceptionsafety.cpp | 734 ++ .../exceptionsafety_objects/3rdparty/memcheck.h | 319 + .../exceptionsafety_objects/3rdparty/valgrind.h | 3924 +++++++ .../exceptionsafety_objects.pro | 6 + .../exceptionsafety_objects/oomsimulator.h | 283 + .../tst_exceptionsafety_objects.cpp | 801 ++ tests/auto/integrationtests/gestures/gestures.pro | 5 + .../integrationtests/gestures/tst_gestures.cpp | 2345 ++++ tests/auto/integrationtests/integrationtests.pro | 35 + tests/auto/integrationtests/lancelot/.gitignore | 1 + tests/auto/integrationtests/lancelot/images.qrc | 34 + .../integrationtests/lancelot/images/alpha.png | Bin 0 -> 2422 bytes .../integrationtests/lancelot/images/alpha2x2.png | Bin 0 -> 169 bytes .../integrationtests/lancelot/images/bitmap.png | Bin 0 -> 254 bytes .../integrationtests/lancelot/images/border.png | Bin 0 -> 182 bytes .../lancelot/images/borderimage.png | Bin 0 -> 826 bytes .../lancelot/images/dome_argb32.png | Bin 0 -> 18234 bytes .../lancelot/images/dome_indexed.png | Bin 0 -> 7946 bytes .../lancelot/images/dome_indexed_mask.png | Bin 0 -> 5411 bytes .../integrationtests/lancelot/images/dome_mono.png | Bin 0 -> 1391 bytes .../lancelot/images/dome_mono_128.png | Bin 0 -> 2649 bytes .../lancelot/images/dome_mono_palette.png | Bin 0 -> 1404 bytes .../lancelot/images/dome_rgb32.png | Bin 0 -> 17890 bytes .../auto/integrationtests/lancelot/images/dot.png | Bin 0 -> 287 bytes .../auto/integrationtests/lancelot/images/face.png | Bin 0 -> 2414 bytes .../integrationtests/lancelot/images/gam030.png | Bin 0 -> 213 bytes .../integrationtests/lancelot/images/gam045.png | Bin 0 -> 216 bytes .../integrationtests/lancelot/images/gam056.png | Bin 0 -> 216 bytes .../integrationtests/lancelot/images/gam100.png | Bin 0 -> 205 bytes .../integrationtests/lancelot/images/gam200.png | Bin 0 -> 187 bytes .../integrationtests/lancelot/images/image.png | Bin 0 -> 169554 bytes .../auto/integrationtests/lancelot/images/mask.png | Bin 0 -> 274 bytes .../integrationtests/lancelot/images/mask_100.png | Bin 0 -> 319 bytes .../integrationtests/lancelot/images/masked.png | Bin 0 -> 788 bytes .../auto/integrationtests/lancelot/images/sign.png | Bin 0 -> 10647 bytes .../integrationtests/lancelot/images/solid.png | Bin 0 -> 607 bytes .../integrationtests/lancelot/images/solid2x2.png | Bin 0 -> 169 bytes .../lancelot/images/struct-image-01.jpg | Bin 0 -> 4751 bytes .../lancelot/images/struct-image-01.png | Bin 0 -> 63238 bytes .../integrationtests/lancelot/images/zebra.png | Bin 0 -> 426 bytes tests/auto/integrationtests/lancelot/lancelot.pro | 15 + .../integrationtests/lancelot/paintcommands.cpp | 2590 +++++ .../auto/integrationtests/lancelot/paintcommands.h | 334 + .../integrationtests/lancelot/scripts/aliasing.qps | 156 + .../integrationtests/lancelot/scripts/arcs.qps | 68 + .../integrationtests/lancelot/scripts/arcs2.qps | 47 + .../lancelot/scripts/background.qps | 136 + .../lancelot/scripts/background_brush.qps | 5 + .../integrationtests/lancelot/scripts/beziers.qps | 147 + .../integrationtests/lancelot/scripts/bitmaps.qps | 166 + .../lancelot/scripts/borderimage.qps | 120 + .../lancelot/scripts/brush_pens.qps | 104 + .../integrationtests/lancelot/scripts/brushes.qps | 79 + .../lancelot/scripts/clippaths.qps | 60 + .../integrationtests/lancelot/scripts/clipping.qps | 182 + .../lancelot/scripts/clipping_state.qps | 47 + .../lancelot/scripts/cliprects.qps | 59 + .../lancelot/scripts/conical_gradients.qps | 85 + .../scripts/conical_gradients_perspectives.qps | 64 + .../integrationtests/lancelot/scripts/dashes.qps | 268 + .../lancelot/scripts/degeneratebeziers.qps | 10 + .../lancelot/scripts/deviceclipping.qps | 48 + .../lancelot/scripts/drawpoints.qps | 101 + .../integrationtests/lancelot/scripts/ellipses.qps | 86 + .../integrationtests/lancelot/scripts/filltest.qps | 413 + .../lancelot/scripts/gradients.qps | 44 + .../integrationtests/lancelot/scripts/hinting.qps | 26 + .../lancelot/scripts/image_formats.qps | 81 + .../integrationtests/lancelot/scripts/images.qps | 106 + .../integrationtests/lancelot/scripts/images2.qps | 145 + .../lancelot/scripts/join_cap_styles.qps | 63 + .../join_cap_styles_duplicate_control_points.qps | 68 + .../lancelot/scripts/linear_gradients.qps | 144 + .../scripts/linear_gradients_perspectives.qps | 62 + .../scripts/linear_resolving_gradients.qps | 66 + .../lancelot/scripts/lineconsistency.qps | 72 + .../lancelot/scripts/linedashes.qps | 94 + .../lancelot/scripts/linedashes2.qps | 154 + .../lancelot/scripts/linedashes2_aa.qps | 5 + .../integrationtests/lancelot/scripts/lines.qps | 558 + .../integrationtests/lancelot/scripts/lines2.qps | 179 + .../integrationtests/lancelot/scripts/pathfill.qps | 38 + .../integrationtests/lancelot/scripts/paths.qps | 34 + .../integrationtests/lancelot/scripts/paths_aa.qps | 4 + .../integrationtests/lancelot/scripts/pens.qps | 133 + .../integrationtests/lancelot/scripts/pens_aa.qps | 6 + .../lancelot/scripts/pens_cosmetic.qps | 110 + .../lancelot/scripts/perspectives.qps | 72 + .../lancelot/scripts/perspectives2.qps | 309 + .../lancelot/scripts/pixmap_rotation.qps | 30 + .../lancelot/scripts/pixmap_scaling.qps | 224 + .../lancelot/scripts/pixmap_subpixel.qps | 117 + .../integrationtests/lancelot/scripts/pixmaps.qps | 106 + .../lancelot/scripts/porter_duff.qps | 251 + .../lancelot/scripts/porter_duff2.qps | 261 + .../lancelot/scripts/primitives.qps | 184 + .../lancelot/scripts/radial_gradients.qps | 99 + .../scripts/radial_gradients_perspectives.qps | 62 + .../lancelot/scripts/rasterops.qps | 87 + .../integrationtests/lancelot/scripts/sizes.qps | 90 + .../lancelot/scripts/statictext.qps | 122 + .../integrationtests/lancelot/scripts/text.qps | 124 + .../lancelot/scripts/text_perspectives.qps | 102 + .../lancelot/scripts/tiled_pixmap.qps | 84 + .../integrationtests/lancelot/tst_lancelot.cpp | 356 + .../integrationtests/languagechange/.gitignore | 1 + .../languagechange/languagechange.pro | 5 + .../languagechange/tst_languagechange.cpp | 286 + tests/auto/integrationtests/macgui/.gitignore | 1 + tests/auto/integrationtests/macgui/guitest.cpp | 350 + tests/auto/integrationtests/macgui/guitest.h | 186 + tests/auto/integrationtests/macgui/macgui.pro | 14 + tests/auto/integrationtests/macgui/tst_macgui.cpp | 242 + .../macnativeevents/expectedeventlist.cpp | 214 + .../macnativeevents/expectedeventlist.h | 71 + .../macnativeevents/macnativeevents.pro | 16 + .../macnativeevents/nativeeventlist.cpp | 114 + .../macnativeevents/nativeeventlist.h | 82 + .../macnativeevents/qnativeevents.cpp | 378 + .../macnativeevents/qnativeevents.h | 228 + .../macnativeevents/qnativeevents_mac.cpp | 382 + .../macnativeevents/tst_macnativeevents.cpp | 522 + tests/auto/integrationtests/macplist/app/app.pro | 11 + tests/auto/integrationtests/macplist/app/main.cpp | 50 + tests/auto/integrationtests/macplist/macplist.pro | 7 + tests/auto/integrationtests/macplist/test/test.pro | 11 + .../integrationtests/macplist/tst_macplist.cpp | 194 + .../modeltest/dynamictreemodel.cpp | 340 + .../integrationtests/modeltest/dynamictreemodel.h | 197 + .../auto/integrationtests/modeltest/modeltest.cpp | 564 + tests/auto/integrationtests/modeltest/modeltest.h | 94 + .../auto/integrationtests/modeltest/modeltest.pro | 7 + .../integrationtests/modeltest/tst_modeltest.cpp | 342 + .../networkselftest/networkselftest.pro | 16 + .../integrationtests/networkselftest/rfc3252.txt | 899 ++ .../networkselftest/tst_networkselftest.cpp | 1029 ++ .../integrationtests/qaccessibility/.gitignore | 1 + .../qaccessibility/qaccessibility.pro | 12 + .../qaccessibility/tst_qaccessibility.cpp | 3372 ++++++ .../auto/integrationtests/qcomplextext/.gitignore | 1 + .../qcomplextext/bidireorderstring.h | 151 + .../integrationtests/qcomplextext/qcomplextext.pro | 5 + .../qcomplextext/tst_qcomplextext.cpp | 294 + .../integrationtests/qdirectpainter/.gitignore | 2 + .../qdirectpainter/qdirectpainter.pro | 5 + .../qdirectpainter/runDirectPainter/main.cpp | 81 + .../runDirectPainter/runDirectPainter.pro | 6 + .../integrationtests/qdirectpainter/test/test.pro | 7 + .../qdirectpainter/tst_qdirectpainter.cpp | 245 + tests/auto/integrationtests/qfocusevent/.gitignore | 1 + .../integrationtests/qfocusevent/qfocusevent.pro | 3 + .../qfocusevent/tst_qfocusevent.cpp | 395 + .../auto/integrationtests/qmultiscreen/.gitignore | 1 + .../integrationtests/qmultiscreen/qmultiscreen.pro | 6 + .../qmultiscreen/tst_qmultiscreen.cpp | 166 + .../qnetworkaccessmanager_and_qprogressdialog.pro | 3 + ...t_qnetworkaccessmanager_and_qprogressdialog.cpp | 155 + .../qsharedpointer_and_qwidget.pro | 4 + .../tst_qsharedpointer_and_qwidget.cpp | 152 + .../windowsmobile/test/ddhelper.cpp | 161 + .../integrationtests/windowsmobile/test/ddhelper.h | 62 + .../integrationtests/windowsmobile/test/test.pro | 23 + .../windowsmobile/test/testQMenuBar_current.png | Bin 0 -> 22964 bytes .../test/testSimpleWidget_current.png | Bin 0 -> 23841 bytes .../windowsmobile/test/tst_windowsmobile.cpp | 208 + .../windowsmobile/test/windowsmobile.qrc | 6 + .../windowsmobile/testQMenuBar/main.cpp | 111 + .../windowsmobile/testQMenuBar/testQMenuBar.pro | 4 + .../windowsmobile/windowsmobile.pro | 9 + tests/auto/lancelot/.gitignore | 1 - tests/auto/lancelot/images.qrc | 34 - tests/auto/lancelot/images/alpha.png | Bin 2422 -> 0 bytes tests/auto/lancelot/images/alpha2x2.png | Bin 169 -> 0 bytes tests/auto/lancelot/images/bitmap.png | Bin 254 -> 0 bytes tests/auto/lancelot/images/border.png | Bin 182 -> 0 bytes tests/auto/lancelot/images/borderimage.png | Bin 826 -> 0 bytes tests/auto/lancelot/images/dome_argb32.png | Bin 18234 -> 0 bytes tests/auto/lancelot/images/dome_indexed.png | Bin 7946 -> 0 bytes tests/auto/lancelot/images/dome_indexed_mask.png | Bin 5411 -> 0 bytes tests/auto/lancelot/images/dome_mono.png | Bin 1391 -> 0 bytes tests/auto/lancelot/images/dome_mono_128.png | Bin 2649 -> 0 bytes tests/auto/lancelot/images/dome_mono_palette.png | Bin 1404 -> 0 bytes tests/auto/lancelot/images/dome_rgb32.png | Bin 17890 -> 0 bytes tests/auto/lancelot/images/dot.png | Bin 287 -> 0 bytes tests/auto/lancelot/images/face.png | Bin 2414 -> 0 bytes tests/auto/lancelot/images/gam030.png | Bin 213 -> 0 bytes tests/auto/lancelot/images/gam045.png | Bin 216 -> 0 bytes tests/auto/lancelot/images/gam056.png | Bin 216 -> 0 bytes tests/auto/lancelot/images/gam100.png | Bin 205 -> 0 bytes tests/auto/lancelot/images/gam200.png | Bin 187 -> 0 bytes tests/auto/lancelot/images/image.png | Bin 169554 -> 0 bytes tests/auto/lancelot/images/mask.png | Bin 274 -> 0 bytes tests/auto/lancelot/images/mask_100.png | Bin 319 -> 0 bytes tests/auto/lancelot/images/masked.png | Bin 788 -> 0 bytes tests/auto/lancelot/images/sign.png | Bin 10647 -> 0 bytes tests/auto/lancelot/images/solid.png | Bin 607 -> 0 bytes tests/auto/lancelot/images/solid2x2.png | Bin 169 -> 0 bytes tests/auto/lancelot/images/struct-image-01.jpg | Bin 4751 -> 0 bytes tests/auto/lancelot/images/struct-image-01.png | Bin 63238 -> 0 bytes tests/auto/lancelot/images/zebra.png | Bin 426 -> 0 bytes tests/auto/lancelot/lancelot.pro | 15 - tests/auto/lancelot/paintcommands.cpp | 2590 ----- tests/auto/lancelot/paintcommands.h | 334 - tests/auto/lancelot/scripts/aliasing.qps | 156 - tests/auto/lancelot/scripts/arcs.qps | 68 - tests/auto/lancelot/scripts/arcs2.qps | 47 - tests/auto/lancelot/scripts/background.qps | 136 - tests/auto/lancelot/scripts/background_brush.qps | 5 - tests/auto/lancelot/scripts/beziers.qps | 147 - tests/auto/lancelot/scripts/bitmaps.qps | 166 - tests/auto/lancelot/scripts/borderimage.qps | 120 - tests/auto/lancelot/scripts/brush_pens.qps | 104 - tests/auto/lancelot/scripts/brushes.qps | 79 - tests/auto/lancelot/scripts/clippaths.qps | 60 - tests/auto/lancelot/scripts/clipping.qps | 182 - tests/auto/lancelot/scripts/clipping_state.qps | 47 - tests/auto/lancelot/scripts/cliprects.qps | 59 - tests/auto/lancelot/scripts/conical_gradients.qps | 85 - .../scripts/conical_gradients_perspectives.qps | 64 - tests/auto/lancelot/scripts/dashes.qps | 268 - tests/auto/lancelot/scripts/degeneratebeziers.qps | 10 - tests/auto/lancelot/scripts/deviceclipping.qps | 48 - tests/auto/lancelot/scripts/drawpoints.qps | 101 - tests/auto/lancelot/scripts/ellipses.qps | 86 - tests/auto/lancelot/scripts/filltest.qps | 413 - tests/auto/lancelot/scripts/gradients.qps | 44 - tests/auto/lancelot/scripts/hinting.qps | 26 - tests/auto/lancelot/scripts/image_formats.qps | 81 - tests/auto/lancelot/scripts/images.qps | 106 - tests/auto/lancelot/scripts/images2.qps | 145 - tests/auto/lancelot/scripts/join_cap_styles.qps | 63 - .../join_cap_styles_duplicate_control_points.qps | 68 - tests/auto/lancelot/scripts/linear_gradients.qps | 144 - .../scripts/linear_gradients_perspectives.qps | 62 - .../scripts/linear_resolving_gradients.qps | 66 - tests/auto/lancelot/scripts/lineconsistency.qps | 72 - tests/auto/lancelot/scripts/linedashes.qps | 94 - tests/auto/lancelot/scripts/linedashes2.qps | 154 - tests/auto/lancelot/scripts/linedashes2_aa.qps | 5 - tests/auto/lancelot/scripts/lines.qps | 558 - tests/auto/lancelot/scripts/lines2.qps | 179 - tests/auto/lancelot/scripts/pathfill.qps | 38 - tests/auto/lancelot/scripts/paths.qps | 34 - tests/auto/lancelot/scripts/paths_aa.qps | 4 - tests/auto/lancelot/scripts/pens.qps | 133 - tests/auto/lancelot/scripts/pens_aa.qps | 6 - tests/auto/lancelot/scripts/pens_cosmetic.qps | 110 - tests/auto/lancelot/scripts/perspectives.qps | 72 - tests/auto/lancelot/scripts/perspectives2.qps | 309 - tests/auto/lancelot/scripts/pixmap_rotation.qps | 30 - tests/auto/lancelot/scripts/pixmap_scaling.qps | 224 - tests/auto/lancelot/scripts/pixmap_subpixel.qps | 117 - tests/auto/lancelot/scripts/pixmaps.qps | 106 - tests/auto/lancelot/scripts/porter_duff.qps | 251 - tests/auto/lancelot/scripts/porter_duff2.qps | 261 - tests/auto/lancelot/scripts/primitives.qps | 184 - tests/auto/lancelot/scripts/radial_gradients.qps | 99 - .../scripts/radial_gradients_perspectives.qps | 62 - tests/auto/lancelot/scripts/rasterops.qps | 87 - tests/auto/lancelot/scripts/sizes.qps | 90 - tests/auto/lancelot/scripts/statictext.qps | 122 - tests/auto/lancelot/scripts/text.qps | 124 - tests/auto/lancelot/scripts/text_perspectives.qps | 102 - tests/auto/lancelot/scripts/tiled_pixmap.qps | 84 - tests/auto/lancelot/tst_lancelot.cpp | 356 - tests/auto/languagechange/.gitignore | 1 - tests/auto/languagechange/languagechange.pro | 5 - tests/auto/languagechange/tst_languagechange.cpp | 286 - tests/auto/macgui/.gitignore | 1 - tests/auto/macgui/guitest.cpp | 350 - tests/auto/macgui/guitest.h | 186 - tests/auto/macgui/macgui.pro | 14 - tests/auto/macgui/tst_macgui.cpp | 242 - tests/auto/macnativeevents/expectedeventlist.cpp | 214 - tests/auto/macnativeevents/expectedeventlist.h | 71 - tests/auto/macnativeevents/macnativeevents.pro | 16 - tests/auto/macnativeevents/nativeeventlist.cpp | 114 - tests/auto/macnativeevents/nativeeventlist.h | 82 - tests/auto/macnativeevents/qnativeevents.cpp | 378 - tests/auto/macnativeevents/qnativeevents.h | 228 - tests/auto/macnativeevents/qnativeevents_mac.cpp | 382 - tests/auto/macnativeevents/tst_macnativeevents.cpp | 522 - tests/auto/macplist/app/app.pro | 11 - tests/auto/macplist/app/main.cpp | 50 - tests/auto/macplist/macplist.pro | 7 - tests/auto/macplist/test/test.pro | 11 - tests/auto/macplist/tst_macplist.cpp | 194 - tests/auto/modeltest/dynamictreemodel.cpp | 340 - tests/auto/modeltest/dynamictreemodel.h | 197 - tests/auto/modeltest/modeltest.cpp | 564 - tests/auto/modeltest/modeltest.h | 94 - tests/auto/modeltest/modeltest.pro | 7 - tests/auto/modeltest/tst_modeltest.cpp | 342 - tests/auto/network.pro | 1 - tests/auto/networkselftest/networkselftest.pro | 16 - tests/auto/networkselftest/rfc3252.txt | 899 -- tests/auto/networkselftest/tst_networkselftest.cpp | 1029 -- tests/auto/other.pro | 41 - tests/auto/qabstractbutton/.gitignore | 1 - tests/auto/qabstractbutton/qabstractbutton.pro | 5 - tests/auto/qabstractbutton/tst_qabstractbutton.cpp | 650 -- tests/auto/qabstractitemview/.gitignore | 1 - tests/auto/qabstractitemview/qabstractitemview.pro | 3 - .../qabstractitemview/tst_qabstractitemview.cpp | 1504 --- tests/auto/qabstractprintdialog/.gitignore | 1 - .../qabstractprintdialog/qabstractprintdialog.pro | 9 - .../tst_qabstractprintdialog.cpp | 146 - tests/auto/qabstractproxymodel/.gitignore | 1 - .../qabstractproxymodel/qabstractproxymodel.pro | 3 - .../tst_qabstractproxymodel.cpp | 449 - tests/auto/qabstractscrollarea/.gitignore | 1 - .../qabstractscrollarea/qabstractscrollarea.pro | 9 - .../tst_qabstractscrollarea.cpp | 390 - tests/auto/qabstractslider/.gitignore | 1 - tests/auto/qabstractslider/qabstractslider.pro | 5 - tests/auto/qabstractslider/tst_qabstractslider.cpp | 1247 -- tests/auto/qabstractspinbox/.gitignore | 1 - tests/auto/qabstractspinbox/qabstractspinbox.pro | 9 - .../auto/qabstractspinbox/tst_qabstractspinbox.cpp | 163 - tests/auto/qaccessibility/.gitignore | 1 - tests/auto/qaccessibility/qaccessibility.pro | 12 - tests/auto/qaccessibility/tst_qaccessibility.cpp | 3372 ------ tests/auto/qaction/.gitignore | 1 - tests/auto/qaction/qaction.pro | 5 - tests/auto/qaction/tst_qaction.cpp | 373 - tests/auto/qactiongroup/.gitignore | 1 - tests/auto/qactiongroup/qactiongroup.pro | 5 - tests/auto/qactiongroup/tst_qactiongroup.cpp | 247 - tests/auto/qapplication/.gitignore | 3 - .../desktopsettingsaware/desktopsettingsaware.pro | 14 - .../qapplication/desktopsettingsaware/main.cpp | 54 - tests/auto/qapplication/heart.svg | 55 - tests/auto/qapplication/modal/base.cpp | 62 - tests/auto/qapplication/modal/base.h | 64 - tests/auto/qapplication/modal/main.cpp | 54 - tests/auto/qapplication/modal/modal.pro | 9 - tests/auto/qapplication/qapplication.pro | 7 - tests/auto/qapplication/test/test.pro | 27 - tests/auto/qapplication/tmp/README | 3 - tests/auto/qapplication/tst_qapplication.cpp | 2107 ---- tests/auto/qapplication/wincmdline/main.cpp | 53 - tests/auto/qapplication/wincmdline/wincmdline.pro | 8 - tests/auto/qboxlayout/.gitignore | 1 - tests/auto/qboxlayout/qboxlayout.pro | 5 - tests/auto/qboxlayout/tst_qboxlayout.cpp | 280 - tests/auto/qbuttongroup/.gitignore | 1 - tests/auto/qbuttongroup/qbuttongroup.pro | 6 - tests/auto/qbuttongroup/tst_qbuttongroup.cpp | 525 - tests/auto/qcalendarwidget/.gitignore | 1 - tests/auto/qcalendarwidget/qcalendarwidget.pro | 5 - tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp | 368 - tests/auto/qcheckbox/.gitignore | 1 - tests/auto/qcheckbox/qcheckbox.pro | 6 - tests/auto/qcheckbox/tst_qcheckbox.cpp | 358 - tests/auto/qcolordialog/.gitignore | 1 - tests/auto/qcolordialog/qcolordialog.pro | 6 - tests/auto/qcolordialog/tst_qcolordialog.cpp | 164 - tests/auto/qcolumnview/.gitignore | 1 - tests/auto/qcolumnview/qcolumnview.pro | 6 - tests/auto/qcolumnview/tst_qcolumnview.cpp | 1040 -- tests/auto/qcombobox/.gitignore | 1 - tests/auto/qcombobox/qcombobox.pro | 3 - tests/auto/qcombobox/tst_qcombobox.cpp | 2579 ----- tests/auto/qcommandlinkbutton/.gitignore | 1 - .../auto/qcommandlinkbutton/qcommandlinkbutton.pro | 6 - .../qcommandlinkbutton/tst_qcommandlinkbutton.cpp | 590 - tests/auto/qcompleter/.gitignore | 1 - tests/auto/qcompleter/qcompleter.pro | 11 - tests/auto/qcompleter/tst_qcompleter.cpp | 1519 --- tests/auto/qcomplextext/.gitignore | 1 - tests/auto/qcomplextext/bidireorderstring.h | 151 - tests/auto/qcomplextext/qcomplextext.pro | 5 - tests/auto/qcomplextext/tst_qcomplextext.cpp | 294 - tests/auto/qdatawidgetmapper/.gitignore | 1 - tests/auto/qdatawidgetmapper/qdatawidgetmapper.pro | 5 - .../qdatawidgetmapper/tst_qdatawidgetmapper.cpp | 411 - tests/auto/qdatetimeedit/.gitignore | 1 - tests/auto/qdatetimeedit/qdatetimeedit.pro | 8 - tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp | 3458 ------ tests/auto/qdesktopwidget/.gitignore | 1 - tests/auto/qdesktopwidget/qdesktopwidget.pro | 3 - tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp | 187 - tests/auto/qdial/.gitignore | 1 - tests/auto/qdial/qdial.pro | 5 - tests/auto/qdial/tst_qdial.cpp | 211 - tests/auto/qdialog/.gitignore | 1 - tests/auto/qdialog/qdialog.pro | 5 - tests/auto/qdialog/tst_qdialog.cpp | 609 - tests/auto/qdialogbuttonbox/.gitignore | 1 - tests/auto/qdialogbuttonbox/qdialogbuttonbox.pro | 7 - .../auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp | 810 -- tests/auto/qdirectpainter/.gitignore | 2 - tests/auto/qdirectpainter/qdirectpainter.pro | 5 - .../auto/qdirectpainter/runDirectPainter/main.cpp | 81 - .../runDirectPainter/runDirectPainter.pro | 6 - tests/auto/qdirectpainter/test/test.pro | 7 - tests/auto/qdirectpainter/tst_qdirectpainter.cpp | 245 - tests/auto/qdirmodel/.gitignore | 1 - tests/auto/qdirmodel/dirtest/test1/dummy | 1 - tests/auto/qdirmodel/dirtest/test1/test | 0 tests/auto/qdirmodel/qdirmodel.pro | 20 - tests/auto/qdirmodel/test/file01.tst | 0 tests/auto/qdirmodel/test/file02.tst | 0 tests/auto/qdirmodel/test/file03.tst | 0 tests/auto/qdirmodel/test/file04.tst | 0 tests/auto/qdirmodel/tst_qdirmodel.cpp | 698 -- tests/auto/qdockwidget/.gitignore | 1 - tests/auto/qdockwidget/qdockwidget.pro | 7 - tests/auto/qdockwidget/tst_qdockwidget.cpp | 877 -- tests/auto/qdoublespinbox/.gitignore | 1 - tests/auto/qdoublespinbox/qdoublespinbox.pro | 5 - tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp | 1111 -- tests/auto/qdoublevalidator/.gitignore | 1 - tests/auto/qdoublevalidator/qdoublevalidator.pro | 5 - .../auto/qdoublevalidator/tst_qdoublevalidator.cpp | 387 - tests/auto/qerrormessage/.gitignore | 1 - tests/auto/qerrormessage/qerrormessage.pro | 10 - tests/auto/qerrormessage/tst_qerrormessage.cpp | 158 - tests/auto/qfiledialog/.gitignore | 1 - tests/auto/qfiledialog/qfiledialog.pro | 23 - tests/auto/qfiledialog/resources/file.txt | 1 - tests/auto/qfiledialog/tst_qfiledialog.cpp | 1349 --- tests/auto/qfiledialog2/qfiledialog2.pro | 20 - tests/auto/qfiledialog2/tst_qfiledialog2.cpp | 1213 -- tests/auto/qfileiconprovider/.gitignore | 1 - tests/auto/qfileiconprovider/qfileiconprovider.pro | 5 - .../qfileiconprovider/tst_qfileiconprovider.cpp | 181 - tests/auto/qfilesystemmodel/.gitignore | 1 - tests/auto/qfilesystemmodel/qfilesystemmodel.pro | 7 - .../auto/qfilesystemmodel/tst_qfilesystemmodel.cpp | 1046 -- tests/auto/qfocusevent/.gitignore | 1 - tests/auto/qfocusevent/qfocusevent.pro | 3 - tests/auto/qfocusevent/tst_qfocusevent.cpp | 395 - tests/auto/qfocusframe/.gitignore | 1 - tests/auto/qfocusframe/qfocusframe.pro | 9 - tests/auto/qfocusframe/tst_qfocusframe.cpp | 89 - tests/auto/qfontcombobox/.gitignore | 1 - tests/auto/qfontcombobox/qfontcombobox.pro | 5 - tests/auto/qfontcombobox/tst_qfontcombobox.cpp | 303 - tests/auto/qfontdialog/.gitignore | 1 - tests/auto/qfontdialog/qfontdialog.pro | 12 - tests/auto/qfontdialog/tst_qfontdialog.cpp | 186 - .../qfontdialog/tst_qfontdialog_mac_helpers.mm | 67 - tests/auto/qformlayout/.gitignore | 1 - tests/auto/qformlayout/qformlayout.pro | 3 - tests/auto/qformlayout/tst_qformlayout.cpp | 913 -- .../qgraphicsanchorlayout.pro | 5 - .../tst_qgraphicsanchorlayout.cpp | 2091 ---- .../qgraphicsanchorlayout1.pro | 5 - .../tst_qgraphicsanchorlayout1.cpp | 3111 ----- tests/auto/qgraphicseffect/qgraphicseffect.pro | 7 - tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 760 -- .../qgraphicseffectsource.pro | 7 - .../tst_qgraphicseffectsource.cpp | 422 - tests/auto/qgraphicsgridlayout/.gitignore | 1 - .../qgraphicsgridlayout/qgraphicsgridlayout.pro | 6 - .../tst_qgraphicsgridlayout.cpp | 3465 ------ tests/auto/qgraphicsitem/.gitignore | 1 - tests/auto/qgraphicsitem/qgraphicsitem.pro | 9 - tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 11402 ------------------- tests/auto/qgraphicsitemanimation/.gitignore | 1 - .../qgraphicsitemanimation.pro | 6 - .../tst_qgraphicsitemanimation.cpp | 192 - tests/auto/qgraphicslayout/.gitignore | 1 - tests/auto/qgraphicslayout/qgraphicslayout.pro | 9 - tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp | 992 -- tests/auto/qgraphicslayoutitem/.gitignore | 1 - .../qgraphicslayoutitem/qgraphicslayoutitem.pro | 5 - .../tst_qgraphicslayoutitem.cpp | 376 - tests/auto/qgraphicslinearlayout/.gitignore | 1 - .../qgraphicslinearlayout.pro | 5 - .../tst_qgraphicslinearlayout.cpp | 1650 --- tests/auto/qgraphicsobject/qgraphicsobject.pro | 7 - tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp | 297 - tests/auto/qgraphicspixmapitem/.gitignore | 1 - .../qgraphicspixmapitem/qgraphicspixmapitem.pro | 5 - .../tst_qgraphicspixmapitem.cpp | 427 - tests/auto/qgraphicspolygonitem/.gitignore | 1 - .../qgraphicspolygonitem/qgraphicspolygonitem.pro | 5 - .../tst_qgraphicspolygonitem.cpp | 349 - tests/auto/qgraphicsproxywidget/.gitignore | 1 - .../qgraphicsproxywidget/qgraphicsproxywidget.pro | 8 - .../tst_qgraphicsproxywidget.cpp | 3649 ------ tests/auto/qgraphicsscene/.gitignore | 1 - tests/auto/qgraphicsscene/Ash_European.jpg | Bin 4751 -> 0 bytes .../qgraphicsscene/graphicsScene_selection.data | Bin 854488 -> 0 bytes tests/auto/qgraphicsscene/images.qrc | 5 - tests/auto/qgraphicsscene/qgraphicsscene.pro | 20 - .../testData/render/all-all-45-deg-left.png | Bin 2181 -> 0 bytes .../testData/render/all-all-45-deg-right.png | Bin 1953 -> 0 bytes .../testData/render/all-all-scale-2x.png | Bin 2399 -> 0 bytes .../testData/render/all-all-translate-0-50.png | Bin 1872 -> 0 bytes .../testData/render/all-all-translate-50-0.png | Bin 1884 -> 0 bytes .../render/all-all-untransformed-clip-ellipse.png | Bin 1819 -> 0 bytes .../render/all-all-untransformed-clip-rect.png | Bin 1255 -> 0 bytes .../testData/render/all-all-untransformed.png | Bin 1896 -> 0 bytes .../render/all-bottomleft-untransformed.png | Bin 1560 -> 0 bytes .../render/all-bottomright-untransformed.png | Bin 1550 -> 0 bytes .../testData/render/all-topleft-untransformed.png | Bin 1566 -> 0 bytes .../testData/render/all-topright-untransformed.png | Bin 1547 -> 0 bytes .../render/bottom-bottomright-untransformed.png | Bin 1172 -> 0 bytes .../render/bottom-topleft-untransformed.png | Bin 1690 -> 0 bytes .../render/bottomleft-all-untransformed.png | Bin 1736 -> 0 bytes .../render/bottomleft-topleft-untransformed.png | Bin 1642 -> 0 bytes .../render/bottomright-all-untransformed.png | Bin 1093 -> 0 bytes .../render/bottomright-topleft-untransformed.png | Bin 1661 -> 0 bytes .../render/left-bottomright-untransformed.png | Bin 1289 -> 0 bytes .../testData/render/left-topleft-untransformed.png | Bin 1823 -> 0 bytes .../render/right-bottomright-untransformed.png | Bin 1236 -> 0 bytes .../render/right-topleft-untransformed.png | Bin 1839 -> 0 bytes .../render/top-bottomright-untransformed.png | Bin 1174 -> 0 bytes .../testData/render/top-topleft-untransformed.png | Bin 1703 -> 0 bytes .../testData/render/topleft-all-untransformed.png | Bin 1973 -> 0 bytes .../render/topleft-topleft-untransformed.png | Bin 1650 -> 0 bytes .../testData/render/topright-all-untransformed.png | Bin 2018 -> 0 bytes .../render/topright-topleft-untransformed.png | Bin 1669 -> 0 bytes tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 4710 -------- .../qgraphicssceneindex/qgraphicssceneindex.pro | 6 - .../tst_qgraphicssceneindex.cpp | 366 - .../auto/qgraphicstransform/qgraphicstransform.pro | 6 - .../qgraphicstransform/tst_qgraphicstransform.cpp | 408 - tests/auto/qgraphicsview/.gitignore | 1 - tests/auto/qgraphicsview/qgraphicsview.pro | 9 - tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 4558 -------- tests/auto/qgraphicsview/tst_qgraphicsview_2.cpp | 976 -- tests/auto/qgraphicswidget/.gitignore | 1 - tests/auto/qgraphicswidget/qgraphicswidget.pro | 10 - tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 3361 ------ tests/auto/qgridlayout/.gitignore | 1 - tests/auto/qgridlayout/qgridlayout.pro | 10 - tests/auto/qgridlayout/sortdialog.ui | 135 - tests/auto/qgridlayout/tst_qgridlayout.cpp | 1646 --- tests/auto/qgroupbox/.gitignore | 1 - tests/auto/qgroupbox/qgroupbox.pro | 6 - tests/auto/qgroupbox/tst_qgroupbox.cpp | 475 - tests/auto/qheaderview/.gitignore | 1 - tests/auto/qheaderview/qheaderview.pro | 8 - tests/auto/qheaderview/tst_qheaderview.cpp | 2135 ---- .../qidentityproxymodel/qidentityproxymodel.pro | 7 - .../tst_qidentityproxymodel.cpp | 333 - tests/auto/qinputcontext/qinputcontext.pro | 7 - tests/auto/qinputcontext/tst_qinputcontext.cpp | 398 - tests/auto/qinputdialog/.gitignore | 1 - tests/auto/qinputdialog/qinputdialog.pro | 5 - tests/auto/qinputdialog/tst_qinputdialog.cpp | 430 - tests/auto/qintvalidator/.gitignore | 1 - tests/auto/qintvalidator/qintvalidator.pro | 4 - tests/auto/qintvalidator/tst_qintvalidator.cpp | 255 - tests/auto/qitemdelegate/.gitignore | 1 - tests/auto/qitemdelegate/qitemdelegate.pro | 6 - tests/auto/qitemdelegate/tst_qitemdelegate.cpp | 1216 -- tests/auto/qitemeditorfactory/.gitignore | 1 - .../auto/qitemeditorfactory/qitemeditorfactory.pro | 5 - .../qitemeditorfactory/tst_qitemeditorfactory.cpp | 105 - tests/auto/qitemselectionmodel/.gitignore | 1 - .../qitemselectionmodel/qitemselectionmodel.pro | 5 - .../tst_qitemselectionmodel.cpp | 2714 ----- tests/auto/qitemview/.gitignore | 1 - tests/auto/qitemview/qitemview.pro | 5 - tests/auto/qitemview/tst_qitemview.cpp | 928 -- tests/auto/qitemview/viewstotest.cpp | 165 - tests/auto/qlabel/.gitignore | 1 - tests/auto/qlabel/green.png | Bin 97 -> 0 bytes tests/auto/qlabel/qlabel.pro | 15 - tests/auto/qlabel/red.png | Bin 105 -> 0 bytes .../qlabel/testdata/acc_01/res_Windows_data0.qsnap | Bin 328 -> 0 bytes .../testdata/acc_01/res_Windows_win32_data0.qsnap | Bin 330 -> 0 bytes .../setAlignment/alignRes_Motif_data0.qsnap | Bin 322 -> 0 bytes .../setAlignment/alignRes_Motif_data1.qsnap | Bin 328 -> 0 bytes .../setAlignment/alignRes_Motif_data10.qsnap | Bin 330 -> 0 bytes .../setAlignment/alignRes_Motif_data2.qsnap | Bin 324 -> 0 bytes .../setAlignment/alignRes_Motif_data3.qsnap | Bin 320 -> 0 bytes .../setAlignment/alignRes_Motif_data4.qsnap | Bin 322 -> 0 bytes .../setAlignment/alignRes_Motif_data5.qsnap | Bin 328 -> 0 bytes .../setAlignment/alignRes_Motif_data6.qsnap | Bin 330 -> 0 bytes .../setAlignment/alignRes_Motif_data7.qsnap | Bin 318 -> 0 bytes .../setAlignment/alignRes_Motif_data8.qsnap | Bin 324 -> 0 bytes .../setAlignment/alignRes_Motif_data9.qsnap | Bin 332 -> 0 bytes .../setAlignment/alignRes_Windows_data0.qsnap | Bin 316 -> 0 bytes .../setAlignment/alignRes_Windows_data1.qsnap | Bin 322 -> 0 bytes .../setAlignment/alignRes_Windows_data10.qsnap | Bin 324 -> 0 bytes .../setAlignment/alignRes_Windows_data2.qsnap | Bin 318 -> 0 bytes .../setAlignment/alignRes_Windows_data3.qsnap | Bin 314 -> 0 bytes .../setAlignment/alignRes_Windows_data4.qsnap | Bin 316 -> 0 bytes .../setAlignment/alignRes_Windows_data5.qsnap | Bin 322 -> 0 bytes .../setAlignment/alignRes_Windows_data6.qsnap | Bin 324 -> 0 bytes .../setAlignment/alignRes_Windows_data7.qsnap | Bin 312 -> 0 bytes .../setAlignment/alignRes_Windows_data8.qsnap | Bin 318 -> 0 bytes .../setAlignment/alignRes_Windows_data9.qsnap | Bin 326 -> 0 bytes .../alignRes_Windows_win32_data0.qsnap | Bin 318 -> 0 bytes .../alignRes_Windows_win32_data1.qsnap | Bin 324 -> 0 bytes .../alignRes_Windows_win32_data10.qsnap | Bin 326 -> 0 bytes .../alignRes_Windows_win32_data2.qsnap | Bin 320 -> 0 bytes .../alignRes_Windows_win32_data3.qsnap | Bin 316 -> 0 bytes .../alignRes_Windows_win32_data4.qsnap | Bin 318 -> 0 bytes .../alignRes_Windows_win32_data5.qsnap | Bin 324 -> 0 bytes .../alignRes_Windows_win32_data6.qsnap | Bin 326 -> 0 bytes .../alignRes_Windows_win32_data7.qsnap | Bin 314 -> 0 bytes .../alignRes_Windows_win32_data8.qsnap | Bin 320 -> 0 bytes .../alignRes_Windows_win32_data9.qsnap | Bin 328 -> 0 bytes .../testdata/setIndent/indentRes_Motif_data0.qsnap | Bin 344 -> 0 bytes .../testdata/setIndent/indentRes_Motif_data1.qsnap | Bin 346 -> 0 bytes .../testdata/setIndent/indentRes_Motif_data2.qsnap | Bin 346 -> 0 bytes .../setIndent/indentRes_Windows_data0.qsnap | Bin 338 -> 0 bytes .../setIndent/indentRes_Windows_data1.qsnap | Bin 340 -> 0 bytes .../setIndent/indentRes_Windows_data2.qsnap | Bin 340 -> 0 bytes .../setIndent/indentRes_Windows_win32_data0.qsnap | Bin 340 -> 0 bytes .../setIndent/indentRes_Windows_win32_data1.qsnap | Bin 342 -> 0 bytes .../setIndent/indentRes_Windows_win32_data2.qsnap | Bin 342 -> 0 bytes .../testdata/setPixmap/Vpix_Motif_data0.qsnap | Bin 405 -> 0 bytes .../testdata/setPixmap/Vpix_Windows_data0.qsnap | Bin 399 -> 0 bytes .../setPixmap/Vpix_Windows_win32_data0.qsnap | Bin 397 -> 0 bytes .../testdata/setPixmap/empty_Motif_data0.qsnap | Bin 257 -> 0 bytes .../testdata/setPixmap/empty_Windows_data0.qsnap | Bin 251 -> 0 bytes .../setPixmap/empty_Windows_win32_data0.qsnap | Bin 249 -> 0 bytes .../setPixmap/scaledVpix_Motif_data0.qsnap | Bin 1040 -> 0 bytes .../setPixmap/scaledVpix_Windows_data0.qsnap | Bin 1034 -> 0 bytes .../setPixmap/scaledVpix_Windows_win32_data0.qsnap | Bin 984 -> 0 bytes .../qlabel/testdata/setText/res_Motif_data0.qsnap | Bin 352 -> 0 bytes .../qlabel/testdata/setText/res_Motif_data1.qsnap | Bin 398 -> 0 bytes .../qlabel/testdata/setText/res_Motif_data2.qsnap | Bin 448 -> 0 bytes .../qlabel/testdata/setText/res_Motif_data3.qsnap | Bin 744 -> 0 bytes .../testdata/setText/res_Windows_data0.qsnap | Bin 346 -> 0 bytes .../testdata/setText/res_Windows_data1.qsnap | Bin 392 -> 0 bytes .../testdata/setText/res_Windows_data2.qsnap | Bin 442 -> 0 bytes .../testdata/setText/res_Windows_data3.qsnap | Bin 738 -> 0 bytes .../testdata/setText/res_Windows_win32_data0.qsnap | Bin 344 -> 0 bytes .../testdata/setText/res_Windows_win32_data1.qsnap | Bin 390 -> 0 bytes .../testdata/setText/res_Windows_win32_data2.qsnap | Bin 440 -> 0 bytes .../testdata/setText/res_Windows_win32_data3.qsnap | Bin 736 -> 0 bytes tests/auto/qlabel/tst_qlabel.cpp | 581 - tests/auto/qlayout/.gitignore | 1 - tests/auto/qlayout/baseline/smartmaxsize | 1792 --- tests/auto/qlayout/qlayout.pro | 16 - tests/auto/qlayout/tst_qlayout.cpp | 345 - tests/auto/qlcdnumber/.gitignore | 1 - tests/auto/qlcdnumber/qlcdnumber.pro | 9 - tests/auto/qlcdnumber/tst_qlcdnumber.cpp | 88 - tests/auto/qlineedit/.gitignore | 1 - tests/auto/qlineedit/qlineedit.pro | 5 - .../testdata/frame/noFrame_Motif-32x96x96_win.png | Bin 30154 -> 0 bytes .../frame/noFrame_Windows-32x96x96_win.png | Bin 30154 -> 0 bytes .../testdata/frame/useFrame_Motif-32x96x96_win.png | Bin 30154 -> 0 bytes .../frame/useFrame_Windows-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/auto_Motif-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/auto_Windows-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/hcenter_Motif-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/hcenter_Windows-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/left_Motif-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/left_Windows-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/right_Motif-32x96x96_win.png | Bin 30154 -> 0 bytes .../setAlignment/right_Windows-32x96x96_win.png | Bin 30154 -> 0 bytes tests/auto/qlineedit/tst_qlineedit.cpp | 3835 ------- tests/auto/qlistview/.gitignore | 1 - tests/auto/qlistview/qlistview.pro | 6 - tests/auto/qlistview/tst_qlistview.cpp | 2073 ---- tests/auto/qlistwidget/.gitignore | 1 - tests/auto/qlistwidget/qlistwidget.pro | 6 - tests/auto/qlistwidget/tst_qlistwidget.cpp | 1685 --- tests/auto/qmacstyle/.gitignore | 1 - tests/auto/qmacstyle/qmacstyle.pro | 6 - tests/auto/qmacstyle/tst_qmacstyle.cpp | 413 - tests/auto/qmainwindow/.gitignore | 1 - tests/auto/qmainwindow/qmainwindow.pro | 3 - tests/auto/qmainwindow/tst_qmainwindow.cpp | 1742 --- tests/auto/qmdiarea/.gitignore | 1 - tests/auto/qmdiarea/qmdiarea.pro | 14 - tests/auto/qmdiarea/tst_qmdiarea.cpp | 2773 ----- tests/auto/qmdisubwindow/.gitignore | 1 - tests/auto/qmdisubwindow/qmdisubwindow.pro | 8 - tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp | 2032 ---- tests/auto/qmenu/.gitignore | 1 - tests/auto/qmenu/qmenu.pro | 5 - tests/auto/qmenu/tst_qmenu.cpp | 943 -- tests/auto/qmenubar/.gitignore | 1 - tests/auto/qmenubar/qmenubar.pro | 3 - tests/auto/qmenubar/tst_qmenubar.cpp | 1291 --- tests/auto/qmessagebox/.gitignore | 1 - tests/auto/qmessagebox/qmessagebox.pro | 9 - tests/auto/qmessagebox/tst_qmessagebox.cpp | 674 -- tests/auto/qmultiscreen/.gitignore | 1 - tests/auto/qmultiscreen/qmultiscreen.pro | 6 - tests/auto/qmultiscreen/tst_qmultiscreen.cpp | 166 - .../qnetworkaccessmanager_and_qprogressdialog.pro | 3 - ...t_qnetworkaccessmanager_and_qprogressdialog.cpp | 155 - tests/auto/qplaintextedit/.gitignore | 1 - tests/auto/qplaintextedit/qplaintextedit.pro | 10 - tests/auto/qplaintextedit/tst_qplaintextedit.cpp | 1524 --- tests/auto/qprogressbar/.gitignore | 1 - tests/auto/qprogressbar/qprogressbar.pro | 6 - tests/auto/qprogressbar/tst_qprogressbar.cpp | 295 - tests/auto/qprogressdialog/.gitignore | 1 - tests/auto/qprogressdialog/qprogressdialog.pro | 9 - tests/auto/qprogressdialog/tst_qprogressdialog.cpp | 157 - tests/auto/qpushbutton/.gitignore | 1 - tests/auto/qpushbutton/qpushbutton.pro | 6 - .../setEnabled/disabled_Windows_win32_data0.qsnap | Bin 890 -> 0 bytes .../testdata/setEnabled/enabled_Motif_data0.qsnap | Bin 758 -> 0 bytes .../setEnabled/enabled_Windows_data0.qsnap | Bin 725 -> 0 bytes .../setEnabled/enabled_Windows_win32_data0.qsnap | Bin 735 -> 0 bytes .../testdata/setPixmap/Vpix_Motif_data0.qsnap | Bin 829 -> 0 bytes .../testdata/setPixmap/Vpix_Windows_data0.qsnap | Bin 796 -> 0 bytes .../setPixmap/Vpix_Windows_win32_data0.qsnap | Bin 796 -> 0 bytes .../testdata/setText/simple_Motif_data0.qsnap | Bin 742 -> 0 bytes .../testdata/setText/simple_Windows_data0.qsnap | Bin 709 -> 0 bytes .../setText/simple_Windows_win32_data0.qsnap | Bin 719 -> 0 bytes tests/auto/qpushbutton/tst_qpushbutton.cpp | 637 -- tests/auto/qradiobutton/.gitignore | 1 - tests/auto/qradiobutton/qradiobutton.pro | 6 - tests/auto/qradiobutton/tst_qradiobutton.cpp | 108 - tests/auto/qregexpvalidator/.gitignore | 1 - tests/auto/qregexpvalidator/qregexpvalidator.pro | 4 - .../auto/qregexpvalidator/tst_qregexpvalidator.cpp | 127 - tests/auto/qscrollarea/.gitignore | 1 - tests/auto/qscrollarea/qscrollarea.pro | 9 - tests/auto/qscrollarea/tst_qscrollarea.cpp | 185 - tests/auto/qscrollbar/.gitignore | 1 - tests/auto/qscrollbar/qscrollbar.pro | 6 - tests/auto/qscrollbar/tst_qscrollbar.cpp | 147 - tests/auto/qscroller/qscroller.pro | 4 - tests/auto/qscroller/tst_qscroller.cpp | 530 - .../qsharedpointer_and_qwidget.pro | 4 - .../tst_qsharedpointer_and_qwidget.cpp | 152 - tests/auto/qsidebar/.gitignore | 1 - tests/auto/qsidebar/qsidebar.pro | 6 - tests/auto/qsidebar/tst_qsidebar.cpp | 231 - tests/auto/qsizegrip/.gitignore | 1 - tests/auto/qsizegrip/qsizegrip.pro | 6 - tests/auto/qsizegrip/tst_qsizegrip.cpp | 201 - tests/auto/qslider/.gitignore | 1 - tests/auto/qslider/qslider.pro | 9 - tests/auto/qslider/tst_qslider.cpp | 98 - tests/auto/qsortfilterproxymodel/.gitignore | 1 - .../qsortfilterproxymodel.pro | 9 - .../tst_qsortfilterproxymodel.cpp | 3274 ------ tests/auto/qsound/.gitignore | 1 - tests/auto/qsound/4.wav | Bin 5538 -> 0 bytes tests/auto/qsound/qsound.pro | 10 - tests/auto/qsound/tst_qsound.cpp | 88 - tests/auto/qspinbox/.gitignore | 1 - tests/auto/qspinbox/qspinbox.pro | 3 - tests/auto/qspinbox/tst_qspinbox.cpp | 1049 -- tests/auto/qsplitter/.gitignore | 1 - tests/auto/qsplitter/extradata.txt | 10067 ---------------- tests/auto/qsplitter/qsplitter.pro | 12 - tests/auto/qsplitter/setSizes3.dat | 2250 ---- tests/auto/qsplitter/tst_qsplitter.cpp | 777 -- tests/auto/qstackedlayout/.gitignore | 1 - tests/auto/qstackedlayout/qstackedlayout.pro | 6 - tests/auto/qstackedlayout/tst_qstackedlayout.cpp | 372 - tests/auto/qstackedwidget/.gitignore | 1 - tests/auto/qstackedwidget/qstackedwidget.pro | 9 - tests/auto/qstackedwidget/tst_qstackedwidget.cpp | 124 - tests/auto/qstandarditem/.gitignore | 1 - tests/auto/qstandarditem/qstandarditem.pro | 5 - tests/auto/qstandarditem/tst_qstandarditem.cpp | 1110 -- tests/auto/qstandarditemmodel/.gitignore | 1 - .../auto/qstandarditemmodel/qstandarditemmodel.pro | 8 - .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 1666 --- tests/auto/qstatusbar/.gitignore | 1 - tests/auto/qstatusbar/qstatusbar.pro | 6 - tests/auto/qstatusbar/tst_qstatusbar.cpp | 279 - tests/auto/qstringlistmodel/.gitignore | 1 - tests/auto/qstringlistmodel/qmodellistener.h | 75 - tests/auto/qstringlistmodel/qstringlistmodel.pro | 8 - .../auto/qstringlistmodel/tst_qstringlistmodel.cpp | 286 - tests/auto/qstyle/.gitignore | 1 - tests/auto/qstyle/images/mac/button.png | Bin 1785 -> 0 bytes tests/auto/qstyle/images/mac/combobox.png | Bin 1808 -> 0 bytes tests/auto/qstyle/images/mac/lineedit.png | Bin 953 -> 0 bytes tests/auto/qstyle/images/mac/mdi.png | Bin 3092 -> 0 bytes tests/auto/qstyle/images/mac/menu.png | Bin 1139 -> 0 bytes tests/auto/qstyle/images/mac/radiobutton.png | Bin 1498 -> 0 bytes tests/auto/qstyle/images/mac/slider.png | Bin 1074 -> 0 bytes tests/auto/qstyle/images/mac/spinbox.png | Bin 1299 -> 0 bytes tests/auto/qstyle/images/vista/button.png | Bin 722 -> 0 bytes tests/auto/qstyle/images/vista/combobox.png | Bin 809 -> 0 bytes tests/auto/qstyle/images/vista/lineedit.png | Bin 530 -> 0 bytes tests/auto/qstyle/images/vista/menu.png | Bin 646 -> 0 bytes tests/auto/qstyle/images/vista/radiobutton.png | Bin 844 -> 0 bytes tests/auto/qstyle/images/vista/slider.png | Bin 575 -> 0 bytes tests/auto/qstyle/images/vista/spinbox.png | Bin 583 -> 0 bytes tests/auto/qstyle/qstyle.pro | 13 - tests/auto/qstyle/task_25863.png | Bin 910 -> 0 bytes tests/auto/qstyle/tst_qstyle.cpp | 794 -- tests/auto/qstyleoption/.gitignore | 1 - tests/auto/qstyleoption/qstyleoption.pro | 11 - tests/auto/qstyleoption/tst_qstyleoption.cpp | 161 - tests/auto/qstylesheetstyle/.gitignore | 1 - tests/auto/qstylesheetstyle/images/testimage.png | Bin 299 -> 0 bytes tests/auto/qstylesheetstyle/qstylesheetstyle.pro | 7 - tests/auto/qstylesheetstyle/resources.qrc | 6 - .../auto/qstylesheetstyle/tst_qstylesheetstyle.cpp | 1644 --- tests/auto/qsystemtrayicon/.gitignore | 1 - tests/auto/qsystemtrayicon/icons/icon.png | Bin 1086 -> 0 bytes tests/auto/qsystemtrayicon/qsystemtrayicon.pro | 9 - tests/auto/qsystemtrayicon/tst_qsystemtrayicon.cpp | 152 - tests/auto/qtabbar/.gitignore | 1 - tests/auto/qtabbar/qtabbar.pro | 6 - tests/auto/qtabbar/tst_qtabbar.cpp | 655 -- tests/auto/qtableview/.gitignore | 1 - tests/auto/qtableview/qtableview.pro | 7 - tests/auto/qtableview/tst_qtableview.cpp | 4075 ------- tests/auto/qtablewidget/.gitignore | 1 - tests/auto/qtablewidget/qtablewidget.pro | 3 - tests/auto/qtablewidget/tst_qtablewidget.cpp | 1500 --- tests/auto/qtabwidget/.gitignore | 1 - tests/auto/qtabwidget/qtabwidget.pro | 12 - tests/auto/qtabwidget/tst_qtabwidget.cpp | 680 -- tests/auto/qtextbrowser/.gitignore | 1 - tests/auto/qtextbrowser/anchor.html | 11 - tests/auto/qtextbrowser/bigpage.html | 934 -- tests/auto/qtextbrowser/firstpage.html | 2 - tests/auto/qtextbrowser/pagewithbg.html | 1 - tests/auto/qtextbrowser/pagewithimage.html | 1 - tests/auto/qtextbrowser/pagewithoutbg.html | 1 - tests/auto/qtextbrowser/qtextbrowser.pro | 15 - tests/auto/qtextbrowser/secondpage.html | 1 - tests/auto/qtextbrowser/subdir/index.html | 1 - tests/auto/qtextbrowser/thirdpage.html | 1 - tests/auto/qtextbrowser/tst_qtextbrowser.cpp | 672 -- tests/auto/qtextedit/.gitignore | 2 - .../fullWidthSelection/centered-fully-selected.png | Bin 1232 -> 0 bytes .../centered-partly-selected.png | Bin 1231 -> 0 bytes .../fullWidthSelection/last-char-on-line.png | Bin 1226 -> 0 bytes .../fullWidthSelection/last-char-on-parag.png | Bin 1223 -> 0 bytes .../multiple-full-width-lines.png | Bin 1236 -> 0 bytes .../qtextedit/fullWidthSelection/nowrap_long.png | Bin 1199 -> 0 bytes .../fullWidthSelection/single-full-width-line.png | Bin 1225 -> 0 bytes tests/auto/qtextedit/qtextedit.pro | 18 - tests/auto/qtextedit/tst_qtextedit.cpp | 2391 ---- tests/auto/qtoolbar/.gitignore | 1 - tests/auto/qtoolbar/qtoolbar.pro | 7 - tests/auto/qtoolbar/tst_qtoolbar.cpp | 1101 -- tests/auto/qtoolbox/.gitignore | 1 - tests/auto/qtoolbox/qtoolbox.pro | 6 - tests/auto/qtoolbox/tst_qtoolbox.cpp | 338 - tests/auto/qtoolbutton/.gitignore | 1 - tests/auto/qtoolbutton/qtoolbutton.pro | 3 - tests/auto/qtoolbutton/tst_qtoolbutton.cpp | 231 - tests/auto/qtooltip/.gitignore | 1 - tests/auto/qtooltip/qtooltip.pro | 5 - tests/auto/qtooltip/tst_qtooltip.cpp | 186 - tests/auto/qtreeview/.gitignore | 1 - tests/auto/qtreeview/qtreeview.pro | 3 - tests/auto/qtreeview/tst_qtreeview.cpp | 3942 ------- tests/auto/qtreewidget/.gitignore | 1 - tests/auto/qtreewidget/qtreewidget.pro | 3 - tests/auto/qtreewidget/tst_qtreewidget.cpp | 3349 ------ tests/auto/qtreewidgetitemiterator/.gitignore | 1 - .../qtreewidgetitemiterator.pro | 5 - .../tst_qtreewidgetitemiterator.cpp | 1243 -- tests/auto/qundogroup/.gitignore | 1 - tests/auto/qundogroup/qundogroup.pro | 4 - tests/auto/qundogroup/testdata/qundogroup.ts | 25 - tests/auto/qundogroup/tst_qundogroup.cpp | 668 -- tests/auto/qundostack/.gitignore | 1 - tests/auto/qundostack/qundostack.pro | 4 - tests/auto/qundostack/testdata/qundostack.ts | 25 - tests/auto/qundostack/tst_qundostack.cpp | 3039 ----- tests/auto/qwidget/.gitignore | 1 - tests/auto/qwidget/geometry-fullscreen.dat | Bin 46 -> 0 bytes tests/auto/qwidget/geometry-maximized.dat | Bin 46 -> 0 bytes tests/auto/qwidget/geometry.dat | Bin 46 -> 0 bytes tests/auto/qwidget/qwidget.pro | 23 - tests/auto/qwidget/qwidget.qrc | 7 - .../testdata/paintEvent/res_Motif_data0.qsnap | Bin 722 -> 0 bytes .../testdata/paintEvent/res_Motif_data1.qsnap | Bin 1509 -> 0 bytes .../testdata/paintEvent/res_Motif_data2.qsnap | Bin 7965 -> 0 bytes .../testdata/paintEvent/res_Motif_data3.qsnap | Bin 8265 -> 0 bytes .../testdata/paintEvent/res_Windows_data0.qsnap | Bin 710 -> 0 bytes .../testdata/paintEvent/res_Windows_data1.qsnap | Bin 1497 -> 0 bytes .../testdata/paintEvent/res_Windows_data2.qsnap | Bin 7953 -> 0 bytes .../testdata/paintEvent/res_Windows_data3.qsnap | Bin 8253 -> 0 bytes tests/auto/qwidget/tst_qwidget.cpp | 9472 --------------- tests/auto/qwidget/tst_qwidget_mac_helpers.h | 52 - tests/auto/qwidget/tst_qwidget_mac_helpers.mm | 83 - tests/auto/qwidget_window/.gitignore | 1 - tests/auto/qwidget_window/qwidget_window.pro | 8 - tests/auto/qwidget_window/tst_qwidget_window.cpp | 326 - tests/auto/qwidgetaction/.gitignore | 1 - tests/auto/qwidgetaction/qwidgetaction.pro | 5 - tests/auto/qwidgetaction/tst_qwidgetaction.cpp | 405 - tests/auto/qwizard/.gitignore | 1 - tests/auto/qwizard/images/background.png | Bin 22932 -> 0 bytes tests/auto/qwizard/images/banner.png | Bin 4230 -> 0 bytes tests/auto/qwizard/images/logo.png | Bin 1661 -> 0 bytes tests/auto/qwizard/images/watermark.png | Bin 15788 -> 0 bytes tests/auto/qwizard/qwizard.pro | 4 - tests/auto/qwizard/qwizard.qrc | 8 - tests/auto/qwizard/tst_qwizard.cpp | 2645 ----- tests/auto/qworkspace/.gitignore | 1 - tests/auto/qworkspace/qworkspace.pro | 3 - tests/auto/qworkspace/tst_qworkspace.cpp | 679 -- tests/auto/widgets/dialogs/dialogs.pro | 18 + .../dialogs/qabstractprintdialog/.gitignore | 1 + .../qabstractprintdialog/qabstractprintdialog.pro | 9 + .../tst_qabstractprintdialog.cpp | 146 + tests/auto/widgets/dialogs/qcolordialog/.gitignore | 1 + .../widgets/dialogs/qcolordialog/qcolordialog.pro | 6 + .../dialogs/qcolordialog/tst_qcolordialog.cpp | 164 + tests/auto/widgets/dialogs/qdialog/.gitignore | 1 + tests/auto/widgets/dialogs/qdialog/qdialog.pro | 5 + tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp | 609 + .../auto/widgets/dialogs/qerrormessage/.gitignore | 1 + .../dialogs/qerrormessage/qerrormessage.pro | 10 + .../dialogs/qerrormessage/tst_qerrormessage.cpp | 158 + tests/auto/widgets/dialogs/qfiledialog/.gitignore | 1 + .../widgets/dialogs/qfiledialog/qfiledialog.pro | 23 + .../widgets/dialogs/qfiledialog/resources/file.txt | 1 + .../dialogs/qfiledialog/tst_qfiledialog.cpp | 1349 +++ .../widgets/dialogs/qfiledialog2/qfiledialog2.pro | 20 + .../dialogs/qfiledialog2/tst_qfiledialog2.cpp | 1213 ++ .../widgets/dialogs/qfilesystemmodel/.gitignore | 1 + .../dialogs/qfilesystemmodel/qfilesystemmodel.pro | 7 + .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 1046 ++ tests/auto/widgets/dialogs/qfontdialog/.gitignore | 1 + .../widgets/dialogs/qfontdialog/qfontdialog.pro | 12 + .../dialogs/qfontdialog/tst_qfontdialog.cpp | 186 + .../qfontdialog/tst_qfontdialog_mac_helpers.mm | 67 + tests/auto/widgets/dialogs/qinputdialog/.gitignore | 1 + .../widgets/dialogs/qinputdialog/qinputdialog.pro | 5 + .../dialogs/qinputdialog/tst_qinputdialog.cpp | 430 + tests/auto/widgets/dialogs/qmessagebox/.gitignore | 1 + .../widgets/dialogs/qmessagebox/qmessagebox.pro | 9 + .../dialogs/qmessagebox/tst_qmessagebox.cpp | 674 ++ .../widgets/dialogs/qprogressdialog/.gitignore | 1 + .../dialogs/qprogressdialog/qprogressdialog.pro | 9 + .../qprogressdialog/tst_qprogressdialog.cpp | 157 + tests/auto/widgets/dialogs/qsidebar/.gitignore | 1 + tests/auto/widgets/dialogs/qsidebar/qsidebar.pro | 6 + .../auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp | 231 + tests/auto/widgets/dialogs/qwizard/.gitignore | 1 + .../widgets/dialogs/qwizard/images/background.png | Bin 0 -> 22932 bytes .../auto/widgets/dialogs/qwizard/images/banner.png | Bin 0 -> 4230 bytes tests/auto/widgets/dialogs/qwizard/images/logo.png | Bin 0 -> 1661 bytes .../widgets/dialogs/qwizard/images/watermark.png | Bin 0 -> 15788 bytes tests/auto/widgets/dialogs/qwizard/qwizard.pro | 4 + tests/auto/widgets/dialogs/qwizard/qwizard.qrc | 8 + tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp | 2645 +++++ tests/auto/widgets/effects/effects.pro | 4 + .../effects/qgraphicseffect/qgraphicseffect.pro | 7 + .../qgraphicseffect/tst_qgraphicseffect.cpp | 760 ++ tests/auto/widgets/graphicsview/graphicsview.pro | 32 + .../qgraphicsanchorlayout.pro | 5 + .../tst_qgraphicsanchorlayout.cpp | 2091 ++++ .../qgraphicsanchorlayout1.pro | 5 + .../tst_qgraphicsanchorlayout1.cpp | 3111 +++++ .../qgraphicseffectsource.pro | 7 + .../tst_qgraphicseffectsource.cpp | 422 + .../graphicsview/qgraphicsgridlayout/.gitignore | 1 + .../qgraphicsgridlayout/qgraphicsgridlayout.pro | 6 + .../tst_qgraphicsgridlayout.cpp | 3465 ++++++ .../widgets/graphicsview/qgraphicsitem/.gitignore | 1 + .../graphicsview/qgraphicsitem/qgraphicsitem.pro | 9 + .../qgraphicsitem/tst_qgraphicsitem.cpp | 11402 +++++++++++++++++++ .../graphicsview/qgraphicsitemanimation/.gitignore | 1 + .../qgraphicsitemanimation.pro | 6 + .../tst_qgraphicsitemanimation.cpp | 192 + .../graphicsview/qgraphicslayout/.gitignore | 1 + .../qgraphicslayout/qgraphicslayout.pro | 9 + .../qgraphicslayout/tst_qgraphicslayout.cpp | 992 ++ .../graphicsview/qgraphicslayoutitem/.gitignore | 1 + .../qgraphicslayoutitem/qgraphicslayoutitem.pro | 5 + .../tst_qgraphicslayoutitem.cpp | 376 + .../graphicsview/qgraphicslinearlayout/.gitignore | 1 + .../qgraphicslinearlayout.pro | 5 + .../tst_qgraphicslinearlayout.cpp | 1650 +++ .../qgraphicsobject/qgraphicsobject.pro | 7 + .../qgraphicsobject/tst_qgraphicsobject.cpp | 297 + .../graphicsview/qgraphicspixmapitem/.gitignore | 1 + .../qgraphicspixmapitem/qgraphicspixmapitem.pro | 5 + .../tst_qgraphicspixmapitem.cpp | 427 + .../graphicsview/qgraphicspolygonitem/.gitignore | 1 + .../qgraphicspolygonitem/qgraphicspolygonitem.pro | 5 + .../tst_qgraphicspolygonitem.cpp | 349 + .../graphicsview/qgraphicsproxywidget/.gitignore | 1 + .../qgraphicsproxywidget/qgraphicsproxywidget.pro | 8 + .../tst_qgraphicsproxywidget.cpp | 3649 ++++++ .../widgets/graphicsview/qgraphicsscene/.gitignore | 1 + .../graphicsview/qgraphicsscene/Ash_European.jpg | Bin 0 -> 4751 bytes .../qgraphicsscene/graphicsScene_selection.data | Bin 0 -> 854488 bytes .../widgets/graphicsview/qgraphicsscene/images.qrc | 5 + .../graphicsview/qgraphicsscene/qgraphicsscene.pro | 20 + .../testData/render/all-all-45-deg-left.png | Bin 0 -> 2181 bytes .../testData/render/all-all-45-deg-right.png | Bin 0 -> 1953 bytes .../testData/render/all-all-scale-2x.png | Bin 0 -> 2399 bytes .../testData/render/all-all-translate-0-50.png | Bin 0 -> 1872 bytes .../testData/render/all-all-translate-50-0.png | Bin 0 -> 1884 bytes .../render/all-all-untransformed-clip-ellipse.png | Bin 0 -> 1819 bytes .../render/all-all-untransformed-clip-rect.png | Bin 0 -> 1255 bytes .../testData/render/all-all-untransformed.png | Bin 0 -> 1896 bytes .../render/all-bottomleft-untransformed.png | Bin 0 -> 1560 bytes .../render/all-bottomright-untransformed.png | Bin 0 -> 1550 bytes .../testData/render/all-topleft-untransformed.png | Bin 0 -> 1566 bytes .../testData/render/all-topright-untransformed.png | Bin 0 -> 1547 bytes .../render/bottom-bottomright-untransformed.png | Bin 0 -> 1172 bytes .../render/bottom-topleft-untransformed.png | Bin 0 -> 1690 bytes .../render/bottomleft-all-untransformed.png | Bin 0 -> 1736 bytes .../render/bottomleft-topleft-untransformed.png | Bin 0 -> 1642 bytes .../render/bottomright-all-untransformed.png | Bin 0 -> 1093 bytes .../render/bottomright-topleft-untransformed.png | Bin 0 -> 1661 bytes .../render/left-bottomright-untransformed.png | Bin 0 -> 1289 bytes .../testData/render/left-topleft-untransformed.png | Bin 0 -> 1823 bytes .../render/right-bottomright-untransformed.png | Bin 0 -> 1236 bytes .../render/right-topleft-untransformed.png | Bin 0 -> 1839 bytes .../render/top-bottomright-untransformed.png | Bin 0 -> 1174 bytes .../testData/render/top-topleft-untransformed.png | Bin 0 -> 1703 bytes .../testData/render/topleft-all-untransformed.png | Bin 0 -> 1973 bytes .../render/topleft-topleft-untransformed.png | Bin 0 -> 1650 bytes .../testData/render/topright-all-untransformed.png | Bin 0 -> 2018 bytes .../render/topright-topleft-untransformed.png | Bin 0 -> 1669 bytes .../qgraphicsscene/tst_qgraphicsscene.cpp | 4710 ++++++++ .../qgraphicssceneindex/qgraphicssceneindex.pro | 6 + .../tst_qgraphicssceneindex.cpp | 366 + .../qgraphicstransform/qgraphicstransform.pro | 6 + .../qgraphicstransform/tst_qgraphicstransform.cpp | 408 + .../widgets/graphicsview/qgraphicsview/.gitignore | 1 + .../graphicsview/qgraphicsview/qgraphicsview.pro | 9 + .../qgraphicsview/tst_qgraphicsview.cpp | 4558 ++++++++ .../qgraphicsview/tst_qgraphicsview_2.cpp | 976 ++ .../graphicsview/qgraphicswidget/.gitignore | 1 + .../qgraphicswidget/qgraphicswidget.pro | 10 + .../qgraphicswidget/tst_qgraphicswidget.cpp | 3361 ++++++ tests/auto/widgets/itemviews/itemviews.pro | 33 + .../widgets/itemviews/qabstractitemview/.gitignore | 1 + .../qabstractitemview/qabstractitemview.pro | 3 + .../qabstractitemview/tst_qabstractitemview.cpp | 1504 +++ .../itemviews/qabstractproxymodel/.gitignore | 1 + .../qabstractproxymodel/qabstractproxymodel.pro | 3 + .../tst_qabstractproxymodel.cpp | 449 + .../auto/widgets/itemviews/qcolumnview/.gitignore | 1 + .../widgets/itemviews/qcolumnview/qcolumnview.pro | 6 + .../itemviews/qcolumnview/tst_qcolumnview.cpp | 1040 ++ .../widgets/itemviews/qdatawidgetmapper/.gitignore | 1 + .../qdatawidgetmapper/qdatawidgetmapper.pro | 5 + .../qdatawidgetmapper/tst_qdatawidgetmapper.cpp | 411 + tests/auto/widgets/itemviews/qdirmodel/.gitignore | 1 + .../itemviews/qdirmodel/dirtest/test1/dummy | 1 + .../widgets/itemviews/qdirmodel/dirtest/test1/test | 0 .../auto/widgets/itemviews/qdirmodel/qdirmodel.pro | 20 + .../widgets/itemviews/qdirmodel/test/file01.tst | 0 .../widgets/itemviews/qdirmodel/test/file02.tst | 0 .../widgets/itemviews/qdirmodel/test/file03.tst | 0 .../widgets/itemviews/qdirmodel/test/file04.tst | 0 .../widgets/itemviews/qdirmodel/tst_qdirmodel.cpp | 698 ++ .../widgets/itemviews/qfileiconprovider/.gitignore | 1 + .../qfileiconprovider/qfileiconprovider.pro | 5 + .../qfileiconprovider/tst_qfileiconprovider.cpp | 181 + .../auto/widgets/itemviews/qheaderview/.gitignore | 1 + .../widgets/itemviews/qheaderview/qheaderview.pro | 8 + .../itemviews/qheaderview/tst_qheaderview.cpp | 2135 ++++ .../qidentityproxymodel/qidentityproxymodel.pro | 7 + .../tst_qidentityproxymodel.cpp | 333 + .../widgets/itemviews/qitemdelegate/.gitignore | 1 + .../itemviews/qitemdelegate/qitemdelegate.pro | 6 + .../itemviews/qitemdelegate/tst_qitemdelegate.cpp | 1216 ++ .../itemviews/qitemeditorfactory/.gitignore | 1 + .../qitemeditorfactory/qitemeditorfactory.pro | 5 + .../qitemeditorfactory/tst_qitemeditorfactory.cpp | 105 + .../itemviews/qitemselectionmodel/.gitignore | 1 + .../qitemselectionmodel/qitemselectionmodel.pro | 5 + .../tst_qitemselectionmodel.cpp | 2714 +++++ tests/auto/widgets/itemviews/qitemview/.gitignore | 1 + .../auto/widgets/itemviews/qitemview/qitemview.pro | 5 + .../widgets/itemviews/qitemview/tst_qitemview.cpp | 928 ++ .../widgets/itemviews/qitemview/viewstotest.cpp | 165 + tests/auto/widgets/itemviews/qlistview/.gitignore | 1 + .../auto/widgets/itemviews/qlistview/qlistview.pro | 6 + .../widgets/itemviews/qlistview/tst_qlistview.cpp | 2073 ++++ .../auto/widgets/itemviews/qlistwidget/.gitignore | 1 + .../widgets/itemviews/qlistwidget/qlistwidget.pro | 6 + .../itemviews/qlistwidget/tst_qlistwidget.cpp | 1685 +++ .../itemviews/qsortfilterproxymodel/.gitignore | 1 + .../qsortfilterproxymodel.pro | 8 + .../tst_qsortfilterproxymodel.cpp | 3274 ++++++ .../widgets/itemviews/qstandarditem/.gitignore | 1 + .../itemviews/qstandarditem/qstandarditem.pro | 5 + .../itemviews/qstandarditem/tst_qstandarditem.cpp | 1110 ++ .../itemviews/qstandarditemmodel/.gitignore | 1 + .../qstandarditemmodel/qstandarditemmodel.pro | 8 + .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 1666 +++ .../widgets/itemviews/qstringlistmodel/.gitignore | 1 + .../itemviews/qstringlistmodel/qmodellistener.h | 75 + .../qstringlistmodel/qstringlistmodel.pro | 8 + .../qstringlistmodel/tst_qstringlistmodel.cpp | 286 + tests/auto/widgets/itemviews/qtableview/.gitignore | 1 + .../widgets/itemviews/qtableview/qtableview.pro | 7 + .../itemviews/qtableview/tst_qtableview.cpp | 4075 +++++++ .../auto/widgets/itemviews/qtablewidget/.gitignore | 1 + .../itemviews/qtablewidget/qtablewidget.pro | 3 + .../itemviews/qtablewidget/tst_qtablewidget.cpp | 1500 +++ tests/auto/widgets/itemviews/qtreeview/.gitignore | 1 + .../auto/widgets/itemviews/qtreeview/qtreeview.pro | 3 + .../widgets/itemviews/qtreeview/tst_qtreeview.cpp | 3942 +++++++ .../auto/widgets/itemviews/qtreewidget/.gitignore | 1 + .../widgets/itemviews/qtreewidget/qtreewidget.pro | 3 + .../itemviews/qtreewidget/tst_qtreewidget.cpp | 3349 ++++++ .../itemviews/qtreewidgetitemiterator/.gitignore | 1 + .../qtreewidgetitemiterator.pro | 5 + .../tst_qtreewidgetitemiterator.cpp | 1243 ++ tests/auto/widgets/kernel/kernel.pro | 17 + tests/auto/widgets/kernel/qaction/.gitignore | 1 + tests/auto/widgets/kernel/qaction/qaction.pro | 5 + tests/auto/widgets/kernel/qaction/tst_qaction.cpp | 373 + tests/auto/widgets/kernel/qactiongroup/.gitignore | 1 + .../widgets/kernel/qactiongroup/qactiongroup.pro | 5 + .../kernel/qactiongroup/tst_qactiongroup.cpp | 247 + tests/auto/widgets/kernel/qapplication/.gitignore | 3 + .../desktopsettingsaware/desktopsettingsaware.pro | 14 + .../qapplication/desktopsettingsaware/main.cpp | 54 + tests/auto/widgets/kernel/qapplication/heart.svg | 55 + .../widgets/kernel/qapplication/modal/base.cpp | 62 + .../auto/widgets/kernel/qapplication/modal/base.h | 64 + .../widgets/kernel/qapplication/modal/main.cpp | 54 + .../widgets/kernel/qapplication/modal/modal.pro | 9 + .../widgets/kernel/qapplication/qapplication.pro | 7 + .../auto/widgets/kernel/qapplication/test/test.pro | 27 + tests/auto/widgets/kernel/qapplication/tmp/README | 3 + .../kernel/qapplication/tst_qapplication.cpp | 2107 ++++ .../kernel/qapplication/wincmdline/main.cpp | 53 + .../kernel/qapplication/wincmdline/wincmdline.pro | 8 + tests/auto/widgets/kernel/qboxlayout/.gitignore | 1 + .../auto/widgets/kernel/qboxlayout/qboxlayout.pro | 5 + .../widgets/kernel/qboxlayout/tst_qboxlayout.cpp | 280 + .../auto/widgets/kernel/qdesktopwidget/.gitignore | 1 + .../kernel/qdesktopwidget/qdesktopwidget.pro | 3 + .../kernel/qdesktopwidget/tst_qdesktopwidget.cpp | 187 + tests/auto/widgets/kernel/qformlayout/.gitignore | 1 + .../widgets/kernel/qformlayout/qformlayout.pro | 3 + .../widgets/kernel/qformlayout/tst_qformlayout.cpp | 913 ++ tests/auto/widgets/kernel/qgridlayout/.gitignore | 1 + .../widgets/kernel/qgridlayout/qgridlayout.pro | 10 + .../auto/widgets/kernel/qgridlayout/sortdialog.ui | 135 + .../widgets/kernel/qgridlayout/tst_qgridlayout.cpp | 1646 +++ .../widgets/kernel/qinputcontext/qinputcontext.pro | 7 + .../kernel/qinputcontext/tst_qinputcontext.cpp | 398 + tests/auto/widgets/kernel/qlayout/.gitignore | 1 + .../widgets/kernel/qlayout/baseline/smartmaxsize | 1792 +++ tests/auto/widgets/kernel/qlayout/qlayout.pro | 16 + tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp | 345 + tests/auto/widgets/kernel/qsound/.gitignore | 1 + tests/auto/widgets/kernel/qsound/4.wav | Bin 0 -> 5538 bytes tests/auto/widgets/kernel/qsound/qsound.pro | 10 + tests/auto/widgets/kernel/qsound/tst_qsound.cpp | 88 + .../auto/widgets/kernel/qstackedlayout/.gitignore | 1 + .../kernel/qstackedlayout/qstackedlayout.pro | 6 + .../kernel/qstackedlayout/tst_qstackedlayout.cpp | 372 + tests/auto/widgets/kernel/qtooltip/.gitignore | 1 + tests/auto/widgets/kernel/qtooltip/qtooltip.pro | 5 + .../auto/widgets/kernel/qtooltip/tst_qtooltip.cpp | 186 + tests/auto/widgets/kernel/qwidget/.gitignore | 1 + .../widgets/kernel/qwidget/geometry-fullscreen.dat | Bin 0 -> 46 bytes .../widgets/kernel/qwidget/geometry-maximized.dat | Bin 0 -> 46 bytes tests/auto/widgets/kernel/qwidget/geometry.dat | Bin 0 -> 46 bytes tests/auto/widgets/kernel/qwidget/qwidget.pro | 23 + tests/auto/widgets/kernel/qwidget/qwidget.qrc | 7 + .../testdata/paintEvent/res_Motif_data0.qsnap | Bin 0 -> 722 bytes .../testdata/paintEvent/res_Motif_data1.qsnap | Bin 0 -> 1509 bytes .../testdata/paintEvent/res_Motif_data2.qsnap | Bin 0 -> 7965 bytes .../testdata/paintEvent/res_Motif_data3.qsnap | Bin 0 -> 8265 bytes .../testdata/paintEvent/res_Windows_data0.qsnap | Bin 0 -> 710 bytes .../testdata/paintEvent/res_Windows_data1.qsnap | Bin 0 -> 1497 bytes .../testdata/paintEvent/res_Windows_data2.qsnap | Bin 0 -> 7953 bytes .../testdata/paintEvent/res_Windows_data3.qsnap | Bin 0 -> 8253 bytes tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 9472 +++++++++++++++ .../kernel/qwidget/tst_qwidget_mac_helpers.h | 52 + .../kernel/qwidget/tst_qwidget_mac_helpers.mm | 83 + .../auto/widgets/kernel/qwidget_window/.gitignore | 1 + .../kernel/qwidget_window/qwidget_window.pro | 8 + .../kernel/qwidget_window/tst_qwidget_window.cpp | 326 + tests/auto/widgets/kernel/qwidgetaction/.gitignore | 1 + .../widgets/kernel/qwidgetaction/qwidgetaction.pro | 5 + .../kernel/qwidgetaction/tst_qwidgetaction.cpp | 405 + tests/auto/widgets/styles/qmacstyle/.gitignore | 1 + tests/auto/widgets/styles/qmacstyle/qmacstyle.pro | 6 + .../widgets/styles/qmacstyle/tst_qmacstyle.cpp | 413 + tests/auto/widgets/styles/qstyle/.gitignore | 1 + .../widgets/styles/qstyle/images/mac/button.png | Bin 0 -> 1785 bytes .../widgets/styles/qstyle/images/mac/combobox.png | Bin 0 -> 1808 bytes .../widgets/styles/qstyle/images/mac/lineedit.png | Bin 0 -> 953 bytes .../auto/widgets/styles/qstyle/images/mac/mdi.png | Bin 0 -> 3092 bytes .../auto/widgets/styles/qstyle/images/mac/menu.png | Bin 0 -> 1139 bytes .../styles/qstyle/images/mac/radiobutton.png | Bin 0 -> 1498 bytes .../widgets/styles/qstyle/images/mac/slider.png | Bin 0 -> 1074 bytes .../widgets/styles/qstyle/images/mac/spinbox.png | Bin 0 -> 1299 bytes .../widgets/styles/qstyle/images/vista/button.png | Bin 0 -> 722 bytes .../styles/qstyle/images/vista/combobox.png | Bin 0 -> 809 bytes .../styles/qstyle/images/vista/lineedit.png | Bin 0 -> 530 bytes .../widgets/styles/qstyle/images/vista/menu.png | Bin 0 -> 646 bytes .../styles/qstyle/images/vista/radiobutton.png | Bin 0 -> 844 bytes .../widgets/styles/qstyle/images/vista/slider.png | Bin 0 -> 575 bytes .../widgets/styles/qstyle/images/vista/spinbox.png | Bin 0 -> 583 bytes tests/auto/widgets/styles/qstyle/qstyle.pro | 13 + tests/auto/widgets/styles/qstyle/task_25863.png | Bin 0 -> 910 bytes tests/auto/widgets/styles/qstyle/tst_qstyle.cpp | 794 ++ tests/auto/widgets/styles/qstyleoption/.gitignore | 1 + .../widgets/styles/qstyleoption/qstyleoption.pro | 11 + .../styles/qstyleoption/tst_qstyleoption.cpp | 161 + .../widgets/styles/qstylesheetstyle/.gitignore | 1 + .../styles/qstylesheetstyle/images/testimage.png | Bin 0 -> 299 bytes .../styles/qstylesheetstyle/qstylesheetstyle.pro | 7 + .../widgets/styles/qstylesheetstyle/resources.qrc | 6 + .../qstylesheetstyle/tst_qstylesheetstyle.cpp | 1644 +++ tests/auto/widgets/styles/styles.pro | 13 + tests/auto/widgets/util/qcompleter/.gitignore | 1 + tests/auto/widgets/util/qcompleter/qcompleter.pro | 11 + .../widgets/util/qcompleter/tst_qcompleter.cpp | 1519 +++ tests/auto/widgets/util/qscroller/qscroller.pro | 4 + .../auto/widgets/util/qscroller/tst_qscroller.cpp | 530 + tests/auto/widgets/util/qsystemtrayicon/.gitignore | 1 + .../widgets/util/qsystemtrayicon/icons/icon.png | Bin 0 -> 1086 bytes .../util/qsystemtrayicon/qsystemtrayicon.pro | 9 + .../util/qsystemtrayicon/tst_qsystemtrayicon.cpp | 152 + tests/auto/widgets/util/qundogroup/.gitignore | 1 + tests/auto/widgets/util/qundogroup/qundogroup.pro | 4 + .../widgets/util/qundogroup/testdata/qundogroup.ts | 25 + .../widgets/util/qundogroup/tst_qundogroup.cpp | 668 ++ tests/auto/widgets/util/qundostack/.gitignore | 1 + tests/auto/widgets/util/qundostack/qundostack.pro | 4 + .../widgets/util/qundostack/testdata/qundostack.ts | 25 + .../widgets/util/qundostack/tst_qundostack.cpp | 3039 +++++ tests/auto/widgets/util/util.pro | 11 + tests/auto/widgets/widgets.pro | 10 + .../widgets/widgets/qabstractbutton/.gitignore | 1 + .../widgets/qabstractbutton/qabstractbutton.pro | 5 + .../qabstractbutton/tst_qabstractbutton.cpp | 650 ++ .../widgets/widgets/qabstractscrollarea/.gitignore | 1 + .../qabstractscrollarea/qabstractscrollarea.pro | 9 + .../tst_qabstractscrollarea.cpp | 390 + .../widgets/widgets/qabstractslider/.gitignore | 1 + .../widgets/qabstractslider/qabstractslider.pro | 5 + .../qabstractslider/tst_qabstractslider.cpp | 1247 ++ .../widgets/widgets/qabstractspinbox/.gitignore | 1 + .../widgets/qabstractspinbox/qabstractspinbox.pro | 9 + .../qabstractspinbox/tst_qabstractspinbox.cpp | 163 + tests/auto/widgets/widgets/qbuttongroup/.gitignore | 1 + .../widgets/widgets/qbuttongroup/qbuttongroup.pro | 6 + .../widgets/qbuttongroup/tst_qbuttongroup.cpp | 525 + .../widgets/widgets/qcalendarwidget/.gitignore | 1 + .../widgets/qcalendarwidget/qcalendarwidget.pro | 5 + .../qcalendarwidget/tst_qcalendarwidget.cpp | 368 + tests/auto/widgets/widgets/qcheckbox/.gitignore | 1 + tests/auto/widgets/widgets/qcheckbox/qcheckbox.pro | 6 + .../widgets/widgets/qcheckbox/tst_qcheckbox.cpp | 358 + tests/auto/widgets/widgets/qcombobox/.gitignore | 1 + tests/auto/widgets/widgets/qcombobox/qcombobox.pro | 3 + .../widgets/widgets/qcombobox/tst_qcombobox.cpp | 2579 +++++ .../widgets/widgets/qcommandlinkbutton/.gitignore | 1 + .../qcommandlinkbutton/qcommandlinkbutton.pro | 6 + .../qcommandlinkbutton/tst_qcommandlinkbutton.cpp | 590 + .../auto/widgets/widgets/qdatetimeedit/.gitignore | 1 + .../widgets/qdatetimeedit/qdatetimeedit.pro | 8 + .../widgets/qdatetimeedit/tst_qdatetimeedit.cpp | 3458 ++++++ tests/auto/widgets/widgets/qdial/.gitignore | 1 + tests/auto/widgets/widgets/qdial/qdial.pro | 5 + tests/auto/widgets/widgets/qdial/tst_qdial.cpp | 211 + .../widgets/widgets/qdialogbuttonbox/.gitignore | 1 + .../widgets/qdialogbuttonbox/qdialogbuttonbox.pro | 7 + .../qdialogbuttonbox/tst_qdialogbuttonbox.cpp | 810 ++ tests/auto/widgets/widgets/qdockwidget/.gitignore | 1 + .../widgets/widgets/qdockwidget/qdockwidget.pro | 7 + .../widgets/qdockwidget/tst_qdockwidget.cpp | 877 ++ .../auto/widgets/widgets/qdoublespinbox/.gitignore | 1 + .../widgets/qdoublespinbox/qdoublespinbox.pro | 5 + .../widgets/qdoublespinbox/tst_qdoublespinbox.cpp | 1111 ++ .../widgets/widgets/qdoublevalidator/.gitignore | 1 + .../widgets/qdoublevalidator/qdoublevalidator.pro | 5 + .../qdoublevalidator/tst_qdoublevalidator.cpp | 387 + tests/auto/widgets/widgets/qfocusframe/.gitignore | 1 + .../widgets/widgets/qfocusframe/qfocusframe.pro | 9 + .../widgets/qfocusframe/tst_qfocusframe.cpp | 89 + .../auto/widgets/widgets/qfontcombobox/.gitignore | 1 + .../widgets/qfontcombobox/qfontcombobox.pro | 5 + .../widgets/qfontcombobox/tst_qfontcombobox.cpp | 303 + tests/auto/widgets/widgets/qgroupbox/.gitignore | 1 + tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro | 6 + .../widgets/widgets/qgroupbox/tst_qgroupbox.cpp | 475 + .../auto/widgets/widgets/qintvalidator/.gitignore | 1 + .../widgets/qintvalidator/qintvalidator.pro | 4 + .../widgets/qintvalidator/tst_qintvalidator.cpp | 255 + tests/auto/widgets/widgets/qlabel/.gitignore | 1 + tests/auto/widgets/widgets/qlabel/green.png | Bin 0 -> 97 bytes tests/auto/widgets/widgets/qlabel/qlabel.pro | 15 + tests/auto/widgets/widgets/qlabel/red.png | Bin 0 -> 105 bytes .../qlabel/testdata/acc_01/res_Windows_data0.qsnap | Bin 0 -> 328 bytes .../testdata/acc_01/res_Windows_win32_data0.qsnap | Bin 0 -> 330 bytes .../setAlignment/alignRes_Motif_data0.qsnap | Bin 0 -> 322 bytes .../setAlignment/alignRes_Motif_data1.qsnap | Bin 0 -> 328 bytes .../setAlignment/alignRes_Motif_data10.qsnap | Bin 0 -> 330 bytes .../setAlignment/alignRes_Motif_data2.qsnap | Bin 0 -> 324 bytes .../setAlignment/alignRes_Motif_data3.qsnap | Bin 0 -> 320 bytes .../setAlignment/alignRes_Motif_data4.qsnap | Bin 0 -> 322 bytes .../setAlignment/alignRes_Motif_data5.qsnap | Bin 0 -> 328 bytes .../setAlignment/alignRes_Motif_data6.qsnap | Bin 0 -> 330 bytes .../setAlignment/alignRes_Motif_data7.qsnap | Bin 0 -> 318 bytes .../setAlignment/alignRes_Motif_data8.qsnap | Bin 0 -> 324 bytes .../setAlignment/alignRes_Motif_data9.qsnap | Bin 0 -> 332 bytes .../setAlignment/alignRes_Windows_data0.qsnap | Bin 0 -> 316 bytes .../setAlignment/alignRes_Windows_data1.qsnap | Bin 0 -> 322 bytes .../setAlignment/alignRes_Windows_data10.qsnap | Bin 0 -> 324 bytes .../setAlignment/alignRes_Windows_data2.qsnap | Bin 0 -> 318 bytes .../setAlignment/alignRes_Windows_data3.qsnap | Bin 0 -> 314 bytes .../setAlignment/alignRes_Windows_data4.qsnap | Bin 0 -> 316 bytes .../setAlignment/alignRes_Windows_data5.qsnap | Bin 0 -> 322 bytes .../setAlignment/alignRes_Windows_data6.qsnap | Bin 0 -> 324 bytes .../setAlignment/alignRes_Windows_data7.qsnap | Bin 0 -> 312 bytes .../setAlignment/alignRes_Windows_data8.qsnap | Bin 0 -> 318 bytes .../setAlignment/alignRes_Windows_data9.qsnap | Bin 0 -> 326 bytes .../alignRes_Windows_win32_data0.qsnap | Bin 0 -> 318 bytes .../alignRes_Windows_win32_data1.qsnap | Bin 0 -> 324 bytes .../alignRes_Windows_win32_data10.qsnap | Bin 0 -> 326 bytes .../alignRes_Windows_win32_data2.qsnap | Bin 0 -> 320 bytes .../alignRes_Windows_win32_data3.qsnap | Bin 0 -> 316 bytes .../alignRes_Windows_win32_data4.qsnap | Bin 0 -> 318 bytes .../alignRes_Windows_win32_data5.qsnap | Bin 0 -> 324 bytes .../alignRes_Windows_win32_data6.qsnap | Bin 0 -> 326 bytes .../alignRes_Windows_win32_data7.qsnap | Bin 0 -> 314 bytes .../alignRes_Windows_win32_data8.qsnap | Bin 0 -> 320 bytes .../alignRes_Windows_win32_data9.qsnap | Bin 0 -> 328 bytes .../testdata/setIndent/indentRes_Motif_data0.qsnap | Bin 0 -> 344 bytes .../testdata/setIndent/indentRes_Motif_data1.qsnap | Bin 0 -> 346 bytes .../testdata/setIndent/indentRes_Motif_data2.qsnap | Bin 0 -> 346 bytes .../setIndent/indentRes_Windows_data0.qsnap | Bin 0 -> 338 bytes .../setIndent/indentRes_Windows_data1.qsnap | Bin 0 -> 340 bytes .../setIndent/indentRes_Windows_data2.qsnap | Bin 0 -> 340 bytes .../setIndent/indentRes_Windows_win32_data0.qsnap | Bin 0 -> 340 bytes .../setIndent/indentRes_Windows_win32_data1.qsnap | Bin 0 -> 342 bytes .../setIndent/indentRes_Windows_win32_data2.qsnap | Bin 0 -> 342 bytes .../testdata/setPixmap/Vpix_Motif_data0.qsnap | Bin 0 -> 405 bytes .../testdata/setPixmap/Vpix_Windows_data0.qsnap | Bin 0 -> 399 bytes .../setPixmap/Vpix_Windows_win32_data0.qsnap | Bin 0 -> 397 bytes .../testdata/setPixmap/empty_Motif_data0.qsnap | Bin 0 -> 257 bytes .../testdata/setPixmap/empty_Windows_data0.qsnap | Bin 0 -> 251 bytes .../setPixmap/empty_Windows_win32_data0.qsnap | Bin 0 -> 249 bytes .../setPixmap/scaledVpix_Motif_data0.qsnap | Bin 0 -> 1040 bytes .../setPixmap/scaledVpix_Windows_data0.qsnap | Bin 0 -> 1034 bytes .../setPixmap/scaledVpix_Windows_win32_data0.qsnap | Bin 0 -> 984 bytes .../qlabel/testdata/setText/res_Motif_data0.qsnap | Bin 0 -> 352 bytes .../qlabel/testdata/setText/res_Motif_data1.qsnap | Bin 0 -> 398 bytes .../qlabel/testdata/setText/res_Motif_data2.qsnap | Bin 0 -> 448 bytes .../qlabel/testdata/setText/res_Motif_data3.qsnap | Bin 0 -> 744 bytes .../testdata/setText/res_Windows_data0.qsnap | Bin 0 -> 346 bytes .../testdata/setText/res_Windows_data1.qsnap | Bin 0 -> 392 bytes .../testdata/setText/res_Windows_data2.qsnap | Bin 0 -> 442 bytes .../testdata/setText/res_Windows_data3.qsnap | Bin 0 -> 738 bytes .../testdata/setText/res_Windows_win32_data0.qsnap | Bin 0 -> 344 bytes .../testdata/setText/res_Windows_win32_data1.qsnap | Bin 0 -> 390 bytes .../testdata/setText/res_Windows_win32_data2.qsnap | Bin 0 -> 440 bytes .../testdata/setText/res_Windows_win32_data3.qsnap | Bin 0 -> 736 bytes tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp | 581 + tests/auto/widgets/widgets/qlcdnumber/.gitignore | 1 + .../auto/widgets/widgets/qlcdnumber/qlcdnumber.pro | 9 + .../widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp | 88 + tests/auto/widgets/widgets/qlineedit/.gitignore | 1 + tests/auto/widgets/widgets/qlineedit/qlineedit.pro | 5 + .../testdata/frame/noFrame_Motif-32x96x96_win.png | Bin 0 -> 30154 bytes .../frame/noFrame_Windows-32x96x96_win.png | Bin 0 -> 30154 bytes .../testdata/frame/useFrame_Motif-32x96x96_win.png | Bin 0 -> 30154 bytes .../frame/useFrame_Windows-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/auto_Motif-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/auto_Windows-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/hcenter_Motif-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/hcenter_Windows-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/left_Motif-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/left_Windows-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/right_Motif-32x96x96_win.png | Bin 0 -> 30154 bytes .../setAlignment/right_Windows-32x96x96_win.png | Bin 0 -> 30154 bytes .../widgets/widgets/qlineedit/tst_qlineedit.cpp | 3835 +++++++ tests/auto/widgets/widgets/qmainwindow/.gitignore | 1 + .../widgets/widgets/qmainwindow/qmainwindow.pro | 3 + .../widgets/qmainwindow/tst_qmainwindow.cpp | 1742 +++ tests/auto/widgets/widgets/qmdiarea/.gitignore | 1 + tests/auto/widgets/widgets/qmdiarea/qmdiarea.pro | 14 + .../auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp | 2773 +++++ .../auto/widgets/widgets/qmdisubwindow/.gitignore | 1 + .../widgets/qmdisubwindow/qmdisubwindow.pro | 8 + .../widgets/qmdisubwindow/tst_qmdisubwindow.cpp | 2032 ++++ tests/auto/widgets/widgets/qmenu/.gitignore | 1 + tests/auto/widgets/widgets/qmenu/qmenu.pro | 5 + tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp | 943 ++ tests/auto/widgets/widgets/qmenubar/.gitignore | 1 + tests/auto/widgets/widgets/qmenubar/qmenubar.pro | 3 + .../auto/widgets/widgets/qmenubar/tst_qmenubar.cpp | 1291 +++ .../auto/widgets/widgets/qplaintextedit/.gitignore | 1 + .../widgets/qplaintextedit/qplaintextedit.pro | 10 + .../widgets/qplaintextedit/tst_qplaintextedit.cpp | 1524 +++ tests/auto/widgets/widgets/qprogressbar/.gitignore | 1 + .../widgets/widgets/qprogressbar/qprogressbar.pro | 6 + .../widgets/qprogressbar/tst_qprogressbar.cpp | 295 + tests/auto/widgets/widgets/qpushbutton/.gitignore | 1 + .../widgets/widgets/qpushbutton/qpushbutton.pro | 6 + .../setEnabled/disabled_Windows_win32_data0.qsnap | Bin 0 -> 890 bytes .../testdata/setEnabled/enabled_Motif_data0.qsnap | Bin 0 -> 758 bytes .../setEnabled/enabled_Windows_data0.qsnap | Bin 0 -> 725 bytes .../setEnabled/enabled_Windows_win32_data0.qsnap | Bin 0 -> 735 bytes .../testdata/setPixmap/Vpix_Motif_data0.qsnap | Bin 0 -> 829 bytes .../testdata/setPixmap/Vpix_Windows_data0.qsnap | Bin 0 -> 796 bytes .../setPixmap/Vpix_Windows_win32_data0.qsnap | Bin 0 -> 796 bytes .../testdata/setText/simple_Motif_data0.qsnap | Bin 0 -> 742 bytes .../testdata/setText/simple_Windows_data0.qsnap | Bin 0 -> 709 bytes .../setText/simple_Windows_win32_data0.qsnap | Bin 0 -> 719 bytes .../widgets/qpushbutton/tst_qpushbutton.cpp | 637 ++ tests/auto/widgets/widgets/qradiobutton/.gitignore | 1 + .../widgets/widgets/qradiobutton/qradiobutton.pro | 6 + .../widgets/qradiobutton/tst_qradiobutton.cpp | 108 + .../widgets/widgets/qregexpvalidator/.gitignore | 1 + .../widgets/qregexpvalidator/qregexpvalidator.pro | 4 + .../qregexpvalidator/tst_qregexpvalidator.cpp | 127 + tests/auto/widgets/widgets/qscrollarea/.gitignore | 1 + .../widgets/widgets/qscrollarea/qscrollarea.pro | 9 + .../widgets/qscrollarea/tst_qscrollarea.cpp | 185 + tests/auto/widgets/widgets/qscrollbar/.gitignore | 1 + .../auto/widgets/widgets/qscrollbar/qscrollbar.pro | 6 + .../widgets/widgets/qscrollbar/tst_qscrollbar.cpp | 147 + tests/auto/widgets/widgets/qsizegrip/.gitignore | 1 + tests/auto/widgets/widgets/qsizegrip/qsizegrip.pro | 6 + .../widgets/widgets/qsizegrip/tst_qsizegrip.cpp | 201 + tests/auto/widgets/widgets/qslider/.gitignore | 1 + tests/auto/widgets/widgets/qslider/qslider.pro | 9 + tests/auto/widgets/widgets/qslider/tst_qslider.cpp | 98 + tests/auto/widgets/widgets/qspinbox/.gitignore | 1 + tests/auto/widgets/widgets/qspinbox/qspinbox.pro | 3 + .../auto/widgets/widgets/qspinbox/tst_qspinbox.cpp | 1049 ++ tests/auto/widgets/widgets/qsplitter/.gitignore | 1 + tests/auto/widgets/widgets/qsplitter/extradata.txt | 10067 ++++++++++++++++ tests/auto/widgets/widgets/qsplitter/qsplitter.pro | 12 + tests/auto/widgets/widgets/qsplitter/setSizes3.dat | 2250 ++++ .../widgets/widgets/qsplitter/tst_qsplitter.cpp | 777 ++ .../auto/widgets/widgets/qstackedwidget/.gitignore | 1 + .../widgets/qstackedwidget/qstackedwidget.pro | 9 + .../widgets/qstackedwidget/tst_qstackedwidget.cpp | 124 + tests/auto/widgets/widgets/qstatusbar/.gitignore | 1 + .../auto/widgets/widgets/qstatusbar/qstatusbar.pro | 6 + .../widgets/widgets/qstatusbar/tst_qstatusbar.cpp | 279 + tests/auto/widgets/widgets/qtabbar/.gitignore | 1 + tests/auto/widgets/widgets/qtabbar/qtabbar.pro | 6 + tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp | 655 ++ tests/auto/widgets/widgets/qtabwidget/.gitignore | 1 + .../auto/widgets/widgets/qtabwidget/qtabwidget.pro | 12 + .../widgets/widgets/qtabwidget/tst_qtabwidget.cpp | 680 ++ tests/auto/widgets/widgets/qtextbrowser/.gitignore | 1 + .../auto/widgets/widgets/qtextbrowser/anchor.html | 11 + .../auto/widgets/widgets/qtextbrowser/bigpage.html | 934 ++ .../widgets/widgets/qtextbrowser/firstpage.html | 2 + .../widgets/widgets/qtextbrowser/pagewithbg.html | 1 + .../widgets/qtextbrowser/pagewithimage.html | 1 + .../widgets/qtextbrowser/pagewithoutbg.html | 1 + .../widgets/widgets/qtextbrowser/qtextbrowser.pro | 15 + .../widgets/widgets/qtextbrowser/secondpage.html | 1 + .../widgets/widgets/qtextbrowser/subdir/index.html | 1 + .../widgets/widgets/qtextbrowser/thirdpage.html | 1 + .../widgets/qtextbrowser/tst_qtextbrowser.cpp | 672 ++ tests/auto/widgets/widgets/qtextedit/.gitignore | 2 + .../fullWidthSelection/centered-fully-selected.png | Bin 0 -> 1232 bytes .../centered-partly-selected.png | Bin 0 -> 1231 bytes .../fullWidthSelection/last-char-on-line.png | Bin 0 -> 1226 bytes .../fullWidthSelection/last-char-on-parag.png | Bin 0 -> 1223 bytes .../multiple-full-width-lines.png | Bin 0 -> 1236 bytes .../qtextedit/fullWidthSelection/nowrap_long.png | Bin 0 -> 1199 bytes .../fullWidthSelection/single-full-width-line.png | Bin 0 -> 1225 bytes tests/auto/widgets/widgets/qtextedit/qtextedit.pro | 18 + .../widgets/widgets/qtextedit/tst_qtextedit.cpp | 2391 ++++ tests/auto/widgets/widgets/qtoolbar/.gitignore | 1 + tests/auto/widgets/widgets/qtoolbar/qtoolbar.pro | 7 + .../auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp | 1101 ++ tests/auto/widgets/widgets/qtoolbox/.gitignore | 1 + tests/auto/widgets/widgets/qtoolbox/qtoolbox.pro | 6 + .../auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp | 338 + tests/auto/widgets/widgets/qtoolbutton/.gitignore | 1 + .../widgets/widgets/qtoolbutton/qtoolbutton.pro | 3 + .../widgets/qtoolbutton/tst_qtoolbutton.cpp | 231 + tests/auto/widgets/widgets/qworkspace/.gitignore | 1 + .../auto/widgets/widgets/qworkspace/qworkspace.pro | 3 + .../widgets/widgets/qworkspace/tst_qworkspace.cpp | 679 ++ tests/auto/widgets/widgets/widgets.pro | 57 + tests/auto/windowsmobile/test/ddhelper.cpp | 161 - tests/auto/windowsmobile/test/ddhelper.h | 62 - tests/auto/windowsmobile/test/test.pro | 23 - .../windowsmobile/test/testQMenuBar_current.png | Bin 22964 -> 0 bytes .../test/testSimpleWidget_current.png | Bin 23841 -> 0 bytes .../auto/windowsmobile/test/tst_windowsmobile.cpp | 208 - tests/auto/windowsmobile/test/windowsmobile.qrc | 6 - tests/auto/windowsmobile/testQMenuBar/main.cpp | 111 - .../windowsmobile/testQMenuBar/testQMenuBar.pro | 4 - tests/auto/windowsmobile/windowsmobile.pro | 9 - 1509 files changed, 207663 insertions(+), 207631 deletions(-) delete mode 100644 tests/auto/collections/.gitignore delete mode 100644 tests/auto/collections/collections.pro delete mode 100644 tests/auto/collections/tst_collections.cpp delete mode 100644 tests/auto/exceptionsafety/.gitignore delete mode 100644 tests/auto/exceptionsafety/exceptionsafety.pro delete mode 100644 tests/auto/exceptionsafety/tst_exceptionsafety.cpp delete mode 100644 tests/auto/exceptionsafety_objects/3rdparty/memcheck.h delete mode 100644 tests/auto/exceptionsafety_objects/3rdparty/valgrind.h delete mode 100644 tests/auto/exceptionsafety_objects/exceptionsafety_objects.pro delete mode 100644 tests/auto/exceptionsafety_objects/oomsimulator.h delete mode 100644 tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp delete mode 100644 tests/auto/gestures/gestures.pro delete mode 100644 tests/auto/gestures/tst_gestures.cpp create mode 100644 tests/auto/integrationtests/collections/.gitignore create mode 100644 tests/auto/integrationtests/collections/collections.pro create mode 100644 tests/auto/integrationtests/collections/tst_collections.cpp create mode 100644 tests/auto/integrationtests/exceptionsafety/.gitignore create mode 100644 tests/auto/integrationtests/exceptionsafety/exceptionsafety.pro create mode 100644 tests/auto/integrationtests/exceptionsafety/tst_exceptionsafety.cpp create mode 100644 tests/auto/integrationtests/exceptionsafety_objects/3rdparty/memcheck.h create mode 100644 tests/auto/integrationtests/exceptionsafety_objects/3rdparty/valgrind.h create mode 100644 tests/auto/integrationtests/exceptionsafety_objects/exceptionsafety_objects.pro create mode 100644 tests/auto/integrationtests/exceptionsafety_objects/oomsimulator.h create mode 100644 tests/auto/integrationtests/exceptionsafety_objects/tst_exceptionsafety_objects.cpp create mode 100644 tests/auto/integrationtests/gestures/gestures.pro create mode 100644 tests/auto/integrationtests/gestures/tst_gestures.cpp create mode 100644 tests/auto/integrationtests/integrationtests.pro create mode 100644 tests/auto/integrationtests/lancelot/.gitignore create mode 100644 tests/auto/integrationtests/lancelot/images.qrc create mode 100644 tests/auto/integrationtests/lancelot/images/alpha.png create mode 100644 tests/auto/integrationtests/lancelot/images/alpha2x2.png create mode 100644 tests/auto/integrationtests/lancelot/images/bitmap.png create mode 100644 tests/auto/integrationtests/lancelot/images/border.png create mode 100644 tests/auto/integrationtests/lancelot/images/borderimage.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_argb32.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_indexed.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_indexed_mask.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_mono.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_mono_128.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_mono_palette.png create mode 100644 tests/auto/integrationtests/lancelot/images/dome_rgb32.png create mode 100644 tests/auto/integrationtests/lancelot/images/dot.png create mode 100644 tests/auto/integrationtests/lancelot/images/face.png create mode 100644 tests/auto/integrationtests/lancelot/images/gam030.png create mode 100644 tests/auto/integrationtests/lancelot/images/gam045.png create mode 100644 tests/auto/integrationtests/lancelot/images/gam056.png create mode 100644 tests/auto/integrationtests/lancelot/images/gam100.png create mode 100644 tests/auto/integrationtests/lancelot/images/gam200.png create mode 100644 tests/auto/integrationtests/lancelot/images/image.png create mode 100644 tests/auto/integrationtests/lancelot/images/mask.png create mode 100644 tests/auto/integrationtests/lancelot/images/mask_100.png create mode 100644 tests/auto/integrationtests/lancelot/images/masked.png create mode 100644 tests/auto/integrationtests/lancelot/images/sign.png create mode 100644 tests/auto/integrationtests/lancelot/images/solid.png create mode 100644 tests/auto/integrationtests/lancelot/images/solid2x2.png create mode 100644 tests/auto/integrationtests/lancelot/images/struct-image-01.jpg create mode 100644 tests/auto/integrationtests/lancelot/images/struct-image-01.png create mode 100644 tests/auto/integrationtests/lancelot/images/zebra.png create mode 100644 tests/auto/integrationtests/lancelot/lancelot.pro create mode 100644 tests/auto/integrationtests/lancelot/paintcommands.cpp create mode 100644 tests/auto/integrationtests/lancelot/paintcommands.h create mode 100644 tests/auto/integrationtests/lancelot/scripts/aliasing.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/arcs.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/arcs2.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/background.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/background_brush.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/beziers.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/bitmaps.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/borderimage.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/brush_pens.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/brushes.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/clippaths.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/clipping.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/clipping_state.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/cliprects.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/conical_gradients.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/conical_gradients_perspectives.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/dashes.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/degeneratebeziers.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/deviceclipping.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/drawpoints.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/ellipses.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/filltest.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/gradients.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/hinting.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/image_formats.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/images.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/images2.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/join_cap_styles.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/join_cap_styles_duplicate_control_points.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/linear_gradients.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/linear_gradients_perspectives.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/linear_resolving_gradients.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/lineconsistency.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/linedashes.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/linedashes2.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/linedashes2_aa.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/lines.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/lines2.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pathfill.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/paths.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/paths_aa.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pens.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pens_aa.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pens_cosmetic.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/perspectives.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/perspectives2.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pixmap_rotation.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pixmap_scaling.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pixmap_subpixel.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/pixmaps.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/porter_duff.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/porter_duff2.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/primitives.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/radial_gradients.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/radial_gradients_perspectives.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/rasterops.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/sizes.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/statictext.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/text.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/text_perspectives.qps create mode 100644 tests/auto/integrationtests/lancelot/scripts/tiled_pixmap.qps create mode 100644 tests/auto/integrationtests/lancelot/tst_lancelot.cpp create mode 100644 tests/auto/integrationtests/languagechange/.gitignore create mode 100644 tests/auto/integrationtests/languagechange/languagechange.pro create mode 100644 tests/auto/integrationtests/languagechange/tst_languagechange.cpp create mode 100644 tests/auto/integrationtests/macgui/.gitignore create mode 100644 tests/auto/integrationtests/macgui/guitest.cpp create mode 100644 tests/auto/integrationtests/macgui/guitest.h create mode 100644 tests/auto/integrationtests/macgui/macgui.pro create mode 100644 tests/auto/integrationtests/macgui/tst_macgui.cpp create mode 100644 tests/auto/integrationtests/macnativeevents/expectedeventlist.cpp create mode 100644 tests/auto/integrationtests/macnativeevents/expectedeventlist.h create mode 100644 tests/auto/integrationtests/macnativeevents/macnativeevents.pro create mode 100644 tests/auto/integrationtests/macnativeevents/nativeeventlist.cpp create mode 100644 tests/auto/integrationtests/macnativeevents/nativeeventlist.h create mode 100644 tests/auto/integrationtests/macnativeevents/qnativeevents.cpp create mode 100644 tests/auto/integrationtests/macnativeevents/qnativeevents.h create mode 100644 tests/auto/integrationtests/macnativeevents/qnativeevents_mac.cpp create mode 100644 tests/auto/integrationtests/macnativeevents/tst_macnativeevents.cpp create mode 100644 tests/auto/integrationtests/macplist/app/app.pro create mode 100644 tests/auto/integrationtests/macplist/app/main.cpp create mode 100644 tests/auto/integrationtests/macplist/macplist.pro create mode 100644 tests/auto/integrationtests/macplist/test/test.pro create mode 100644 tests/auto/integrationtests/macplist/tst_macplist.cpp create mode 100644 tests/auto/integrationtests/modeltest/dynamictreemodel.cpp create mode 100644 tests/auto/integrationtests/modeltest/dynamictreemodel.h create mode 100644 tests/auto/integrationtests/modeltest/modeltest.cpp create mode 100644 tests/auto/integrationtests/modeltest/modeltest.h create mode 100644 tests/auto/integrationtests/modeltest/modeltest.pro create mode 100644 tests/auto/integrationtests/modeltest/tst_modeltest.cpp create mode 100644 tests/auto/integrationtests/networkselftest/networkselftest.pro create mode 100644 tests/auto/integrationtests/networkselftest/rfc3252.txt create mode 100644 tests/auto/integrationtests/networkselftest/tst_networkselftest.cpp create mode 100644 tests/auto/integrationtests/qaccessibility/.gitignore create mode 100644 tests/auto/integrationtests/qaccessibility/qaccessibility.pro create mode 100644 tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp create mode 100644 tests/auto/integrationtests/qcomplextext/.gitignore create mode 100644 tests/auto/integrationtests/qcomplextext/bidireorderstring.h create mode 100644 tests/auto/integrationtests/qcomplextext/qcomplextext.pro create mode 100644 tests/auto/integrationtests/qcomplextext/tst_qcomplextext.cpp create mode 100644 tests/auto/integrationtests/qdirectpainter/.gitignore create mode 100644 tests/auto/integrationtests/qdirectpainter/qdirectpainter.pro create mode 100644 tests/auto/integrationtests/qdirectpainter/runDirectPainter/main.cpp create mode 100644 tests/auto/integrationtests/qdirectpainter/runDirectPainter/runDirectPainter.pro create mode 100644 tests/auto/integrationtests/qdirectpainter/test/test.pro create mode 100644 tests/auto/integrationtests/qdirectpainter/tst_qdirectpainter.cpp create mode 100644 tests/auto/integrationtests/qfocusevent/.gitignore create mode 100644 tests/auto/integrationtests/qfocusevent/qfocusevent.pro create mode 100644 tests/auto/integrationtests/qfocusevent/tst_qfocusevent.cpp create mode 100644 tests/auto/integrationtests/qmultiscreen/.gitignore create mode 100644 tests/auto/integrationtests/qmultiscreen/qmultiscreen.pro create mode 100644 tests/auto/integrationtests/qmultiscreen/tst_qmultiscreen.cpp create mode 100644 tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro create mode 100644 tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp create mode 100644 tests/auto/integrationtests/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro create mode 100644 tests/auto/integrationtests/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp create mode 100644 tests/auto/integrationtests/windowsmobile/test/ddhelper.cpp create mode 100644 tests/auto/integrationtests/windowsmobile/test/ddhelper.h create mode 100644 tests/auto/integrationtests/windowsmobile/test/test.pro create mode 100644 tests/auto/integrationtests/windowsmobile/test/testQMenuBar_current.png create mode 100644 tests/auto/integrationtests/windowsmobile/test/testSimpleWidget_current.png create mode 100644 tests/auto/integrationtests/windowsmobile/test/tst_windowsmobile.cpp create mode 100644 tests/auto/integrationtests/windowsmobile/test/windowsmobile.qrc create mode 100644 tests/auto/integrationtests/windowsmobile/testQMenuBar/main.cpp create mode 100644 tests/auto/integrationtests/windowsmobile/testQMenuBar/testQMenuBar.pro create mode 100644 tests/auto/integrationtests/windowsmobile/windowsmobile.pro delete mode 100644 tests/auto/lancelot/.gitignore delete mode 100644 tests/auto/lancelot/images.qrc delete mode 100644 tests/auto/lancelot/images/alpha.png delete mode 100644 tests/auto/lancelot/images/alpha2x2.png delete mode 100644 tests/auto/lancelot/images/bitmap.png delete mode 100644 tests/auto/lancelot/images/border.png delete mode 100644 tests/auto/lancelot/images/borderimage.png delete mode 100644 tests/auto/lancelot/images/dome_argb32.png delete mode 100644 tests/auto/lancelot/images/dome_indexed.png delete mode 100644 tests/auto/lancelot/images/dome_indexed_mask.png delete mode 100644 tests/auto/lancelot/images/dome_mono.png delete mode 100644 tests/auto/lancelot/images/dome_mono_128.png delete mode 100644 tests/auto/lancelot/images/dome_mono_palette.png delete mode 100644 tests/auto/lancelot/images/dome_rgb32.png delete mode 100644 tests/auto/lancelot/images/dot.png delete mode 100644 tests/auto/lancelot/images/face.png delete mode 100644 tests/auto/lancelot/images/gam030.png delete mode 100644 tests/auto/lancelot/images/gam045.png delete mode 100644 tests/auto/lancelot/images/gam056.png delete mode 100644 tests/auto/lancelot/images/gam100.png delete mode 100644 tests/auto/lancelot/images/gam200.png delete mode 100644 tests/auto/lancelot/images/image.png delete mode 100644 tests/auto/lancelot/images/mask.png delete mode 100644 tests/auto/lancelot/images/mask_100.png delete mode 100644 tests/auto/lancelot/images/masked.png delete mode 100644 tests/auto/lancelot/images/sign.png delete mode 100644 tests/auto/lancelot/images/solid.png delete mode 100644 tests/auto/lancelot/images/solid2x2.png delete mode 100644 tests/auto/lancelot/images/struct-image-01.jpg delete mode 100644 tests/auto/lancelot/images/struct-image-01.png delete mode 100644 tests/auto/lancelot/images/zebra.png delete mode 100644 tests/auto/lancelot/lancelot.pro delete mode 100644 tests/auto/lancelot/paintcommands.cpp delete mode 100644 tests/auto/lancelot/paintcommands.h delete mode 100644 tests/auto/lancelot/scripts/aliasing.qps delete mode 100644 tests/auto/lancelot/scripts/arcs.qps delete mode 100644 tests/auto/lancelot/scripts/arcs2.qps delete mode 100644 tests/auto/lancelot/scripts/background.qps delete mode 100644 tests/auto/lancelot/scripts/background_brush.qps delete mode 100644 tests/auto/lancelot/scripts/beziers.qps delete mode 100644 tests/auto/lancelot/scripts/bitmaps.qps delete mode 100644 tests/auto/lancelot/scripts/borderimage.qps delete mode 100644 tests/auto/lancelot/scripts/brush_pens.qps delete mode 100644 tests/auto/lancelot/scripts/brushes.qps delete mode 100644 tests/auto/lancelot/scripts/clippaths.qps delete mode 100644 tests/auto/lancelot/scripts/clipping.qps delete mode 100644 tests/auto/lancelot/scripts/clipping_state.qps delete mode 100644 tests/auto/lancelot/scripts/cliprects.qps delete mode 100644 tests/auto/lancelot/scripts/conical_gradients.qps delete mode 100644 tests/auto/lancelot/scripts/conical_gradients_perspectives.qps delete mode 100644 tests/auto/lancelot/scripts/dashes.qps delete mode 100644 tests/auto/lancelot/scripts/degeneratebeziers.qps delete mode 100644 tests/auto/lancelot/scripts/deviceclipping.qps delete mode 100644 tests/auto/lancelot/scripts/drawpoints.qps delete mode 100644 tests/auto/lancelot/scripts/ellipses.qps delete mode 100644 tests/auto/lancelot/scripts/filltest.qps delete mode 100644 tests/auto/lancelot/scripts/gradients.qps delete mode 100644 tests/auto/lancelot/scripts/hinting.qps delete mode 100644 tests/auto/lancelot/scripts/image_formats.qps delete mode 100644 tests/auto/lancelot/scripts/images.qps delete mode 100644 tests/auto/lancelot/scripts/images2.qps delete mode 100644 tests/auto/lancelot/scripts/join_cap_styles.qps delete mode 100644 tests/auto/lancelot/scripts/join_cap_styles_duplicate_control_points.qps delete mode 100644 tests/auto/lancelot/scripts/linear_gradients.qps delete mode 100644 tests/auto/lancelot/scripts/linear_gradients_perspectives.qps delete mode 100644 tests/auto/lancelot/scripts/linear_resolving_gradients.qps delete mode 100644 tests/auto/lancelot/scripts/lineconsistency.qps delete mode 100644 tests/auto/lancelot/scripts/linedashes.qps delete mode 100644 tests/auto/lancelot/scripts/linedashes2.qps delete mode 100644 tests/auto/lancelot/scripts/linedashes2_aa.qps delete mode 100644 tests/auto/lancelot/scripts/lines.qps delete mode 100644 tests/auto/lancelot/scripts/lines2.qps delete mode 100644 tests/auto/lancelot/scripts/pathfill.qps delete mode 100644 tests/auto/lancelot/scripts/paths.qps delete mode 100644 tests/auto/lancelot/scripts/paths_aa.qps delete mode 100644 tests/auto/lancelot/scripts/pens.qps delete mode 100644 tests/auto/lancelot/scripts/pens_aa.qps delete mode 100644 tests/auto/lancelot/scripts/pens_cosmetic.qps delete mode 100644 tests/auto/lancelot/scripts/perspectives.qps delete mode 100644 tests/auto/lancelot/scripts/perspectives2.qps delete mode 100644 tests/auto/lancelot/scripts/pixmap_rotation.qps delete mode 100644 tests/auto/lancelot/scripts/pixmap_scaling.qps delete mode 100644 tests/auto/lancelot/scripts/pixmap_subpixel.qps delete mode 100644 tests/auto/lancelot/scripts/pixmaps.qps delete mode 100644 tests/auto/lancelot/scripts/porter_duff.qps delete mode 100644 tests/auto/lancelot/scripts/porter_duff2.qps delete mode 100644 tests/auto/lancelot/scripts/primitives.qps delete mode 100644 tests/auto/lancelot/scripts/radial_gradients.qps delete mode 100644 tests/auto/lancelot/scripts/radial_gradients_perspectives.qps delete mode 100644 tests/auto/lancelot/scripts/rasterops.qps delete mode 100644 tests/auto/lancelot/scripts/sizes.qps delete mode 100644 tests/auto/lancelot/scripts/statictext.qps delete mode 100644 tests/auto/lancelot/scripts/text.qps delete mode 100644 tests/auto/lancelot/scripts/text_perspectives.qps delete mode 100644 tests/auto/lancelot/scripts/tiled_pixmap.qps delete mode 100644 tests/auto/lancelot/tst_lancelot.cpp delete mode 100644 tests/auto/languagechange/.gitignore delete mode 100644 tests/auto/languagechange/languagechange.pro delete mode 100644 tests/auto/languagechange/tst_languagechange.cpp delete mode 100644 tests/auto/macgui/.gitignore delete mode 100644 tests/auto/macgui/guitest.cpp delete mode 100644 tests/auto/macgui/guitest.h delete mode 100644 tests/auto/macgui/macgui.pro delete mode 100644 tests/auto/macgui/tst_macgui.cpp delete mode 100644 tests/auto/macnativeevents/expectedeventlist.cpp delete mode 100644 tests/auto/macnativeevents/expectedeventlist.h delete mode 100644 tests/auto/macnativeevents/macnativeevents.pro delete mode 100644 tests/auto/macnativeevents/nativeeventlist.cpp delete mode 100644 tests/auto/macnativeevents/nativeeventlist.h delete mode 100644 tests/auto/macnativeevents/qnativeevents.cpp delete mode 100644 tests/auto/macnativeevents/qnativeevents.h delete mode 100644 tests/auto/macnativeevents/qnativeevents_mac.cpp delete mode 100644 tests/auto/macnativeevents/tst_macnativeevents.cpp delete mode 100644 tests/auto/macplist/app/app.pro delete mode 100644 tests/auto/macplist/app/main.cpp delete mode 100644 tests/auto/macplist/macplist.pro delete mode 100644 tests/auto/macplist/test/test.pro delete mode 100644 tests/auto/macplist/tst_macplist.cpp delete mode 100644 tests/auto/modeltest/dynamictreemodel.cpp delete mode 100644 tests/auto/modeltest/dynamictreemodel.h delete mode 100644 tests/auto/modeltest/modeltest.cpp delete mode 100644 tests/auto/modeltest/modeltest.h delete mode 100644 tests/auto/modeltest/modeltest.pro delete mode 100644 tests/auto/modeltest/tst_modeltest.cpp delete mode 100644 tests/auto/networkselftest/networkselftest.pro delete mode 100644 tests/auto/networkselftest/rfc3252.txt delete mode 100644 tests/auto/networkselftest/tst_networkselftest.cpp delete mode 100644 tests/auto/qabstractbutton/.gitignore delete mode 100644 tests/auto/qabstractbutton/qabstractbutton.pro delete mode 100644 tests/auto/qabstractbutton/tst_qabstractbutton.cpp delete mode 100644 tests/auto/qabstractitemview/.gitignore delete mode 100644 tests/auto/qabstractitemview/qabstractitemview.pro delete mode 100644 tests/auto/qabstractitemview/tst_qabstractitemview.cpp delete mode 100644 tests/auto/qabstractprintdialog/.gitignore delete mode 100644 tests/auto/qabstractprintdialog/qabstractprintdialog.pro delete mode 100644 tests/auto/qabstractprintdialog/tst_qabstractprintdialog.cpp delete mode 100644 tests/auto/qabstractproxymodel/.gitignore delete mode 100644 tests/auto/qabstractproxymodel/qabstractproxymodel.pro delete mode 100644 tests/auto/qabstractproxymodel/tst_qabstractproxymodel.cpp delete mode 100644 tests/auto/qabstractscrollarea/.gitignore delete mode 100644 tests/auto/qabstractscrollarea/qabstractscrollarea.pro delete mode 100644 tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp delete mode 100644 tests/auto/qabstractslider/.gitignore delete mode 100644 tests/auto/qabstractslider/qabstractslider.pro delete mode 100644 tests/auto/qabstractslider/tst_qabstractslider.cpp delete mode 100644 tests/auto/qabstractspinbox/.gitignore delete mode 100644 tests/auto/qabstractspinbox/qabstractspinbox.pro delete mode 100644 tests/auto/qabstractspinbox/tst_qabstractspinbox.cpp delete mode 100644 tests/auto/qaccessibility/.gitignore delete mode 100644 tests/auto/qaccessibility/qaccessibility.pro delete mode 100644 tests/auto/qaccessibility/tst_qaccessibility.cpp delete mode 100644 tests/auto/qaction/.gitignore delete mode 100644 tests/auto/qaction/qaction.pro delete mode 100644 tests/auto/qaction/tst_qaction.cpp delete mode 100644 tests/auto/qactiongroup/.gitignore delete mode 100644 tests/auto/qactiongroup/qactiongroup.pro delete mode 100644 tests/auto/qactiongroup/tst_qactiongroup.cpp delete mode 100644 tests/auto/qapplication/.gitignore delete mode 100644 tests/auto/qapplication/desktopsettingsaware/desktopsettingsaware.pro delete mode 100644 tests/auto/qapplication/desktopsettingsaware/main.cpp delete mode 100644 tests/auto/qapplication/heart.svg delete mode 100644 tests/auto/qapplication/modal/base.cpp delete mode 100644 tests/auto/qapplication/modal/base.h delete mode 100644 tests/auto/qapplication/modal/main.cpp delete mode 100644 tests/auto/qapplication/modal/modal.pro delete mode 100644 tests/auto/qapplication/qapplication.pro delete mode 100644 tests/auto/qapplication/test/test.pro delete mode 100644 tests/auto/qapplication/tmp/README delete mode 100644 tests/auto/qapplication/tst_qapplication.cpp delete mode 100644 tests/auto/qapplication/wincmdline/main.cpp delete mode 100644 tests/auto/qapplication/wincmdline/wincmdline.pro delete mode 100644 tests/auto/qboxlayout/.gitignore delete mode 100644 tests/auto/qboxlayout/qboxlayout.pro delete mode 100644 tests/auto/qboxlayout/tst_qboxlayout.cpp delete mode 100644 tests/auto/qbuttongroup/.gitignore delete mode 100644 tests/auto/qbuttongroup/qbuttongroup.pro delete mode 100644 tests/auto/qbuttongroup/tst_qbuttongroup.cpp delete mode 100644 tests/auto/qcalendarwidget/.gitignore delete mode 100644 tests/auto/qcalendarwidget/qcalendarwidget.pro delete mode 100644 tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp delete mode 100644 tests/auto/qcheckbox/.gitignore delete mode 100644 tests/auto/qcheckbox/qcheckbox.pro delete mode 100644 tests/auto/qcheckbox/tst_qcheckbox.cpp delete mode 100644 tests/auto/qcolordialog/.gitignore delete mode 100644 tests/auto/qcolordialog/qcolordialog.pro delete mode 100644 tests/auto/qcolordialog/tst_qcolordialog.cpp delete mode 100644 tests/auto/qcolumnview/.gitignore delete mode 100644 tests/auto/qcolumnview/qcolumnview.pro delete mode 100644 tests/auto/qcolumnview/tst_qcolumnview.cpp delete mode 100644 tests/auto/qcombobox/.gitignore delete mode 100644 tests/auto/qcombobox/qcombobox.pro delete mode 100644 tests/auto/qcombobox/tst_qcombobox.cpp delete mode 100644 tests/auto/qcommandlinkbutton/.gitignore delete mode 100644 tests/auto/qcommandlinkbutton/qcommandlinkbutton.pro delete mode 100644 tests/auto/qcommandlinkbutton/tst_qcommandlinkbutton.cpp delete mode 100644 tests/auto/qcompleter/.gitignore delete mode 100644 tests/auto/qcompleter/qcompleter.pro delete mode 100644 tests/auto/qcompleter/tst_qcompleter.cpp delete mode 100644 tests/auto/qcomplextext/.gitignore delete mode 100644 tests/auto/qcomplextext/bidireorderstring.h delete mode 100644 tests/auto/qcomplextext/qcomplextext.pro delete mode 100644 tests/auto/qcomplextext/tst_qcomplextext.cpp delete mode 100644 tests/auto/qdatawidgetmapper/.gitignore delete mode 100644 tests/auto/qdatawidgetmapper/qdatawidgetmapper.pro delete mode 100644 tests/auto/qdatawidgetmapper/tst_qdatawidgetmapper.cpp delete mode 100644 tests/auto/qdatetimeedit/.gitignore delete mode 100644 tests/auto/qdatetimeedit/qdatetimeedit.pro delete mode 100644 tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp delete mode 100644 tests/auto/qdesktopwidget/.gitignore delete mode 100644 tests/auto/qdesktopwidget/qdesktopwidget.pro delete mode 100644 tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp delete mode 100644 tests/auto/qdial/.gitignore delete mode 100644 tests/auto/qdial/qdial.pro delete mode 100644 tests/auto/qdial/tst_qdial.cpp delete mode 100644 tests/auto/qdialog/.gitignore delete mode 100644 tests/auto/qdialog/qdialog.pro delete mode 100644 tests/auto/qdialog/tst_qdialog.cpp delete mode 100644 tests/auto/qdialogbuttonbox/.gitignore delete mode 100644 tests/auto/qdialogbuttonbox/qdialogbuttonbox.pro delete mode 100644 tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp delete mode 100644 tests/auto/qdirectpainter/.gitignore delete mode 100644 tests/auto/qdirectpainter/qdirectpainter.pro delete mode 100644 tests/auto/qdirectpainter/runDirectPainter/main.cpp delete mode 100644 tests/auto/qdirectpainter/runDirectPainter/runDirectPainter.pro delete mode 100644 tests/auto/qdirectpainter/test/test.pro delete mode 100644 tests/auto/qdirectpainter/tst_qdirectpainter.cpp delete mode 100644 tests/auto/qdirmodel/.gitignore delete mode 100644 tests/auto/qdirmodel/dirtest/test1/dummy delete mode 100644 tests/auto/qdirmodel/dirtest/test1/test delete mode 100644 tests/auto/qdirmodel/qdirmodel.pro delete mode 100644 tests/auto/qdirmodel/test/file01.tst delete mode 100644 tests/auto/qdirmodel/test/file02.tst delete mode 100644 tests/auto/qdirmodel/test/file03.tst delete mode 100644 tests/auto/qdirmodel/test/file04.tst delete mode 100644 tests/auto/qdirmodel/tst_qdirmodel.cpp delete mode 100644 tests/auto/qdockwidget/.gitignore delete mode 100644 tests/auto/qdockwidget/qdockwidget.pro delete mode 100644 tests/auto/qdockwidget/tst_qdockwidget.cpp delete mode 100644 tests/auto/qdoublespinbox/.gitignore delete mode 100644 tests/auto/qdoublespinbox/qdoublespinbox.pro delete mode 100644 tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp delete mode 100644 tests/auto/qdoublevalidator/.gitignore delete mode 100644 tests/auto/qdoublevalidator/qdoublevalidator.pro delete mode 100644 tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp delete mode 100644 tests/auto/qerrormessage/.gitignore delete mode 100644 tests/auto/qerrormessage/qerrormessage.pro delete mode 100644 tests/auto/qerrormessage/tst_qerrormessage.cpp delete mode 100644 tests/auto/qfiledialog/.gitignore delete mode 100644 tests/auto/qfiledialog/qfiledialog.pro delete mode 100644 tests/auto/qfiledialog/resources/file.txt delete mode 100644 tests/auto/qfiledialog/tst_qfiledialog.cpp delete mode 100644 tests/auto/qfiledialog2/qfiledialog2.pro delete mode 100644 tests/auto/qfiledialog2/tst_qfiledialog2.cpp delete mode 100644 tests/auto/qfileiconprovider/.gitignore delete mode 100644 tests/auto/qfileiconprovider/qfileiconprovider.pro delete mode 100644 tests/auto/qfileiconprovider/tst_qfileiconprovider.cpp delete mode 100644 tests/auto/qfilesystemmodel/.gitignore delete mode 100644 tests/auto/qfilesystemmodel/qfilesystemmodel.pro delete mode 100644 tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp delete mode 100644 tests/auto/qfocusevent/.gitignore delete mode 100644 tests/auto/qfocusevent/qfocusevent.pro delete mode 100644 tests/auto/qfocusevent/tst_qfocusevent.cpp delete mode 100644 tests/auto/qfocusframe/.gitignore delete mode 100644 tests/auto/qfocusframe/qfocusframe.pro delete mode 100644 tests/auto/qfocusframe/tst_qfocusframe.cpp delete mode 100644 tests/auto/qfontcombobox/.gitignore delete mode 100644 tests/auto/qfontcombobox/qfontcombobox.pro delete mode 100644 tests/auto/qfontcombobox/tst_qfontcombobox.cpp delete mode 100644 tests/auto/qfontdialog/.gitignore delete mode 100644 tests/auto/qfontdialog/qfontdialog.pro delete mode 100644 tests/auto/qfontdialog/tst_qfontdialog.cpp delete mode 100644 tests/auto/qfontdialog/tst_qfontdialog_mac_helpers.mm delete mode 100644 tests/auto/qformlayout/.gitignore delete mode 100644 tests/auto/qformlayout/qformlayout.pro delete mode 100644 tests/auto/qformlayout/tst_qformlayout.cpp delete mode 100644 tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro delete mode 100644 tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp delete mode 100644 tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro delete mode 100644 tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp delete mode 100644 tests/auto/qgraphicseffect/qgraphicseffect.pro delete mode 100644 tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp delete mode 100644 tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro delete mode 100644 tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp delete mode 100644 tests/auto/qgraphicsgridlayout/.gitignore delete mode 100644 tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro delete mode 100644 tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp delete mode 100644 tests/auto/qgraphicsitem/.gitignore delete mode 100644 tests/auto/qgraphicsitem/qgraphicsitem.pro delete mode 100644 tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp delete mode 100644 tests/auto/qgraphicsitemanimation/.gitignore delete mode 100644 tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro delete mode 100644 tests/auto/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp delete mode 100644 tests/auto/qgraphicslayout/.gitignore delete mode 100644 tests/auto/qgraphicslayout/qgraphicslayout.pro delete mode 100644 tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp delete mode 100644 tests/auto/qgraphicslayoutitem/.gitignore delete mode 100644 tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro delete mode 100644 tests/auto/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp delete mode 100644 tests/auto/qgraphicslinearlayout/.gitignore delete mode 100644 tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro delete mode 100644 tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp delete mode 100644 tests/auto/qgraphicsobject/qgraphicsobject.pro delete mode 100644 tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp delete mode 100644 tests/auto/qgraphicspixmapitem/.gitignore delete mode 100644 tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro delete mode 100644 tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp delete mode 100644 tests/auto/qgraphicspolygonitem/.gitignore delete mode 100644 tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro delete mode 100644 tests/auto/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp delete mode 100644 tests/auto/qgraphicsproxywidget/.gitignore delete mode 100644 tests/auto/qgraphicsproxywidget/qgraphicsproxywidget.pro delete mode 100644 tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp delete mode 100644 tests/auto/qgraphicsscene/.gitignore delete mode 100644 tests/auto/qgraphicsscene/Ash_European.jpg delete mode 100644 tests/auto/qgraphicsscene/graphicsScene_selection.data delete mode 100644 tests/auto/qgraphicsscene/images.qrc delete mode 100644 tests/auto/qgraphicsscene/qgraphicsscene.pro delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-45-deg-left.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-45-deg-right.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-scale-2x.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-translate-0-50.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-translate-50-0.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-all-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-bottomleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-bottomright-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/all-topright-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/bottom-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/bottomleft-all-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/bottomright-all-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/left-bottomright-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/left-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/right-bottomright-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/right-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/top-bottomright-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/top-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/topleft-all-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/topleft-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/topright-all-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/testData/render/topright-topleft-untransformed.png delete mode 100644 tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp delete mode 100644 tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro delete mode 100644 tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp delete mode 100644 tests/auto/qgraphicstransform/qgraphicstransform.pro delete mode 100644 tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp delete mode 100644 tests/auto/qgraphicsview/.gitignore delete mode 100644 tests/auto/qgraphicsview/qgraphicsview.pro delete mode 100644 tests/auto/qgraphicsview/tst_qgraphicsview.cpp delete mode 100644 tests/auto/qgraphicsview/tst_qgraphicsview_2.cpp delete mode 100644 tests/auto/qgraphicswidget/.gitignore delete mode 100644 tests/auto/qgraphicswidget/qgraphicswidget.pro delete mode 100644 tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp delete mode 100644 tests/auto/qgridlayout/.gitignore delete mode 100644 tests/auto/qgridlayout/qgridlayout.pro delete mode 100644 tests/auto/qgridlayout/sortdialog.ui delete mode 100644 tests/auto/qgridlayout/tst_qgridlayout.cpp delete mode 100644 tests/auto/qgroupbox/.gitignore delete mode 100644 tests/auto/qgroupbox/qgroupbox.pro delete mode 100644 tests/auto/qgroupbox/tst_qgroupbox.cpp delete mode 100644 tests/auto/qheaderview/.gitignore delete mode 100644 tests/auto/qheaderview/qheaderview.pro delete mode 100644 tests/auto/qheaderview/tst_qheaderview.cpp delete mode 100644 tests/auto/qidentityproxymodel/qidentityproxymodel.pro delete mode 100644 tests/auto/qidentityproxymodel/tst_qidentityproxymodel.cpp delete mode 100644 tests/auto/qinputcontext/qinputcontext.pro delete mode 100644 tests/auto/qinputcontext/tst_qinputcontext.cpp delete mode 100644 tests/auto/qinputdialog/.gitignore delete mode 100644 tests/auto/qinputdialog/qinputdialog.pro delete mode 100644 tests/auto/qinputdialog/tst_qinputdialog.cpp delete mode 100644 tests/auto/qintvalidator/.gitignore delete mode 100644 tests/auto/qintvalidator/qintvalidator.pro delete mode 100644 tests/auto/qintvalidator/tst_qintvalidator.cpp delete mode 100644 tests/auto/qitemdelegate/.gitignore delete mode 100644 tests/auto/qitemdelegate/qitemdelegate.pro delete mode 100644 tests/auto/qitemdelegate/tst_qitemdelegate.cpp delete mode 100644 tests/auto/qitemeditorfactory/.gitignore delete mode 100644 tests/auto/qitemeditorfactory/qitemeditorfactory.pro delete mode 100644 tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp delete mode 100644 tests/auto/qitemselectionmodel/.gitignore delete mode 100644 tests/auto/qitemselectionmodel/qitemselectionmodel.pro delete mode 100644 tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp delete mode 100644 tests/auto/qitemview/.gitignore delete mode 100644 tests/auto/qitemview/qitemview.pro delete mode 100644 tests/auto/qitemview/tst_qitemview.cpp delete mode 100644 tests/auto/qitemview/viewstotest.cpp delete mode 100644 tests/auto/qlabel/.gitignore delete mode 100644 tests/auto/qlabel/green.png delete mode 100644 tests/auto/qlabel/qlabel.pro delete mode 100644 tests/auto/qlabel/red.png delete mode 100644 tests/auto/qlabel/testdata/acc_01/res_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap delete mode 100644 tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Motif_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Motif_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Motif_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Motif_data3.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_data3.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_win32_data1.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_win32_data2.qsnap delete mode 100644 tests/auto/qlabel/testdata/setText/res_Windows_win32_data3.qsnap delete mode 100644 tests/auto/qlabel/tst_qlabel.cpp delete mode 100644 tests/auto/qlayout/.gitignore delete mode 100644 tests/auto/qlayout/baseline/smartmaxsize delete mode 100644 tests/auto/qlayout/qlayout.pro delete mode 100644 tests/auto/qlayout/tst_qlayout.cpp delete mode 100644 tests/auto/qlcdnumber/.gitignore delete mode 100644 tests/auto/qlcdnumber/qlcdnumber.pro delete mode 100644 tests/auto/qlcdnumber/tst_qlcdnumber.cpp delete mode 100644 tests/auto/qlineedit/.gitignore delete mode 100644 tests/auto/qlineedit/qlineedit.pro delete mode 100644 tests/auto/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png delete mode 100644 tests/auto/qlineedit/tst_qlineedit.cpp delete mode 100644 tests/auto/qlistview/.gitignore delete mode 100644 tests/auto/qlistview/qlistview.pro delete mode 100644 tests/auto/qlistview/tst_qlistview.cpp delete mode 100644 tests/auto/qlistwidget/.gitignore delete mode 100644 tests/auto/qlistwidget/qlistwidget.pro delete mode 100644 tests/auto/qlistwidget/tst_qlistwidget.cpp delete mode 100644 tests/auto/qmacstyle/.gitignore delete mode 100644 tests/auto/qmacstyle/qmacstyle.pro delete mode 100644 tests/auto/qmacstyle/tst_qmacstyle.cpp delete mode 100644 tests/auto/qmainwindow/.gitignore delete mode 100644 tests/auto/qmainwindow/qmainwindow.pro delete mode 100644 tests/auto/qmainwindow/tst_qmainwindow.cpp delete mode 100644 tests/auto/qmdiarea/.gitignore delete mode 100644 tests/auto/qmdiarea/qmdiarea.pro delete mode 100644 tests/auto/qmdiarea/tst_qmdiarea.cpp delete mode 100644 tests/auto/qmdisubwindow/.gitignore delete mode 100644 tests/auto/qmdisubwindow/qmdisubwindow.pro delete mode 100644 tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp delete mode 100644 tests/auto/qmenu/.gitignore delete mode 100644 tests/auto/qmenu/qmenu.pro delete mode 100644 tests/auto/qmenu/tst_qmenu.cpp delete mode 100644 tests/auto/qmenubar/.gitignore delete mode 100644 tests/auto/qmenubar/qmenubar.pro delete mode 100644 tests/auto/qmenubar/tst_qmenubar.cpp delete mode 100644 tests/auto/qmessagebox/.gitignore delete mode 100644 tests/auto/qmessagebox/qmessagebox.pro delete mode 100644 tests/auto/qmessagebox/tst_qmessagebox.cpp delete mode 100644 tests/auto/qmultiscreen/.gitignore delete mode 100644 tests/auto/qmultiscreen/qmultiscreen.pro delete mode 100644 tests/auto/qmultiscreen/tst_qmultiscreen.cpp delete mode 100644 tests/auto/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro delete mode 100644 tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp delete mode 100644 tests/auto/qplaintextedit/.gitignore delete mode 100644 tests/auto/qplaintextedit/qplaintextedit.pro delete mode 100644 tests/auto/qplaintextedit/tst_qplaintextedit.cpp delete mode 100644 tests/auto/qprogressbar/.gitignore delete mode 100644 tests/auto/qprogressbar/qprogressbar.pro delete mode 100644 tests/auto/qprogressbar/tst_qprogressbar.cpp delete mode 100644 tests/auto/qprogressdialog/.gitignore delete mode 100644 tests/auto/qprogressdialog/qprogressdialog.pro delete mode 100644 tests/auto/qprogressdialog/tst_qprogressdialog.cpp delete mode 100644 tests/auto/qpushbutton/.gitignore delete mode 100644 tests/auto/qpushbutton/qpushbutton.pro delete mode 100644 tests/auto/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setText/simple_Motif_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setText/simple_Windows_data0.qsnap delete mode 100644 tests/auto/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap delete mode 100644 tests/auto/qpushbutton/tst_qpushbutton.cpp delete mode 100644 tests/auto/qradiobutton/.gitignore delete mode 100644 tests/auto/qradiobutton/qradiobutton.pro delete mode 100644 tests/auto/qradiobutton/tst_qradiobutton.cpp delete mode 100644 tests/auto/qregexpvalidator/.gitignore delete mode 100644 tests/auto/qregexpvalidator/qregexpvalidator.pro delete mode 100644 tests/auto/qregexpvalidator/tst_qregexpvalidator.cpp delete mode 100644 tests/auto/qscrollarea/.gitignore delete mode 100644 tests/auto/qscrollarea/qscrollarea.pro delete mode 100644 tests/auto/qscrollarea/tst_qscrollarea.cpp delete mode 100644 tests/auto/qscrollbar/.gitignore delete mode 100644 tests/auto/qscrollbar/qscrollbar.pro delete mode 100644 tests/auto/qscrollbar/tst_qscrollbar.cpp delete mode 100644 tests/auto/qscroller/qscroller.pro delete mode 100644 tests/auto/qscroller/tst_qscroller.cpp delete mode 100644 tests/auto/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro delete mode 100644 tests/auto/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp delete mode 100644 tests/auto/qsidebar/.gitignore delete mode 100644 tests/auto/qsidebar/qsidebar.pro delete mode 100644 tests/auto/qsidebar/tst_qsidebar.cpp delete mode 100644 tests/auto/qsizegrip/.gitignore delete mode 100644 tests/auto/qsizegrip/qsizegrip.pro delete mode 100644 tests/auto/qsizegrip/tst_qsizegrip.cpp delete mode 100644 tests/auto/qslider/.gitignore delete mode 100644 tests/auto/qslider/qslider.pro delete mode 100644 tests/auto/qslider/tst_qslider.cpp delete mode 100644 tests/auto/qsortfilterproxymodel/.gitignore delete mode 100644 tests/auto/qsortfilterproxymodel/qsortfilterproxymodel.pro delete mode 100644 tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp delete mode 100644 tests/auto/qsound/.gitignore delete mode 100644 tests/auto/qsound/4.wav delete mode 100644 tests/auto/qsound/qsound.pro delete mode 100644 tests/auto/qsound/tst_qsound.cpp delete mode 100644 tests/auto/qspinbox/.gitignore delete mode 100644 tests/auto/qspinbox/qspinbox.pro delete mode 100644 tests/auto/qspinbox/tst_qspinbox.cpp delete mode 100644 tests/auto/qsplitter/.gitignore delete mode 100644 tests/auto/qsplitter/extradata.txt delete mode 100644 tests/auto/qsplitter/qsplitter.pro delete mode 100644 tests/auto/qsplitter/setSizes3.dat delete mode 100644 tests/auto/qsplitter/tst_qsplitter.cpp delete mode 100644 tests/auto/qstackedlayout/.gitignore delete mode 100644 tests/auto/qstackedlayout/qstackedlayout.pro delete mode 100644 tests/auto/qstackedlayout/tst_qstackedlayout.cpp delete mode 100644 tests/auto/qstackedwidget/.gitignore delete mode 100644 tests/auto/qstackedwidget/qstackedwidget.pro delete mode 100644 tests/auto/qstackedwidget/tst_qstackedwidget.cpp delete mode 100644 tests/auto/qstandarditem/.gitignore delete mode 100644 tests/auto/qstandarditem/qstandarditem.pro delete mode 100644 tests/auto/qstandarditem/tst_qstandarditem.cpp delete mode 100644 tests/auto/qstandarditemmodel/.gitignore delete mode 100644 tests/auto/qstandarditemmodel/qstandarditemmodel.pro delete mode 100644 tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp delete mode 100644 tests/auto/qstatusbar/.gitignore delete mode 100644 tests/auto/qstatusbar/qstatusbar.pro delete mode 100644 tests/auto/qstatusbar/tst_qstatusbar.cpp delete mode 100644 tests/auto/qstringlistmodel/.gitignore delete mode 100644 tests/auto/qstringlistmodel/qmodellistener.h delete mode 100644 tests/auto/qstringlistmodel/qstringlistmodel.pro delete mode 100644 tests/auto/qstringlistmodel/tst_qstringlistmodel.cpp delete mode 100644 tests/auto/qstyle/.gitignore delete mode 100644 tests/auto/qstyle/images/mac/button.png delete mode 100644 tests/auto/qstyle/images/mac/combobox.png delete mode 100644 tests/auto/qstyle/images/mac/lineedit.png delete mode 100644 tests/auto/qstyle/images/mac/mdi.png delete mode 100644 tests/auto/qstyle/images/mac/menu.png delete mode 100644 tests/auto/qstyle/images/mac/radiobutton.png delete mode 100644 tests/auto/qstyle/images/mac/slider.png delete mode 100644 tests/auto/qstyle/images/mac/spinbox.png delete mode 100644 tests/auto/qstyle/images/vista/button.png delete mode 100644 tests/auto/qstyle/images/vista/combobox.png delete mode 100644 tests/auto/qstyle/images/vista/lineedit.png delete mode 100644 tests/auto/qstyle/images/vista/menu.png delete mode 100644 tests/auto/qstyle/images/vista/radiobutton.png delete mode 100644 tests/auto/qstyle/images/vista/slider.png delete mode 100644 tests/auto/qstyle/images/vista/spinbox.png delete mode 100644 tests/auto/qstyle/qstyle.pro delete mode 100644 tests/auto/qstyle/task_25863.png delete mode 100644 tests/auto/qstyle/tst_qstyle.cpp delete mode 100644 tests/auto/qstyleoption/.gitignore delete mode 100644 tests/auto/qstyleoption/qstyleoption.pro delete mode 100644 tests/auto/qstyleoption/tst_qstyleoption.cpp delete mode 100644 tests/auto/qstylesheetstyle/.gitignore delete mode 100644 tests/auto/qstylesheetstyle/images/testimage.png delete mode 100644 tests/auto/qstylesheetstyle/qstylesheetstyle.pro delete mode 100644 tests/auto/qstylesheetstyle/resources.qrc delete mode 100644 tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp delete mode 100644 tests/auto/qsystemtrayicon/.gitignore delete mode 100644 tests/auto/qsystemtrayicon/icons/icon.png delete mode 100644 tests/auto/qsystemtrayicon/qsystemtrayicon.pro delete mode 100644 tests/auto/qsystemtrayicon/tst_qsystemtrayicon.cpp delete mode 100644 tests/auto/qtabbar/.gitignore delete mode 100644 tests/auto/qtabbar/qtabbar.pro delete mode 100644 tests/auto/qtabbar/tst_qtabbar.cpp delete mode 100644 tests/auto/qtableview/.gitignore delete mode 100644 tests/auto/qtableview/qtableview.pro delete mode 100644 tests/auto/qtableview/tst_qtableview.cpp delete mode 100644 tests/auto/qtablewidget/.gitignore delete mode 100644 tests/auto/qtablewidget/qtablewidget.pro delete mode 100644 tests/auto/qtablewidget/tst_qtablewidget.cpp delete mode 100644 tests/auto/qtabwidget/.gitignore delete mode 100644 tests/auto/qtabwidget/qtabwidget.pro delete mode 100644 tests/auto/qtabwidget/tst_qtabwidget.cpp delete mode 100644 tests/auto/qtextbrowser/.gitignore delete mode 100644 tests/auto/qtextbrowser/anchor.html delete mode 100644 tests/auto/qtextbrowser/bigpage.html delete mode 100644 tests/auto/qtextbrowser/firstpage.html delete mode 100644 tests/auto/qtextbrowser/pagewithbg.html delete mode 100644 tests/auto/qtextbrowser/pagewithimage.html delete mode 100644 tests/auto/qtextbrowser/pagewithoutbg.html delete mode 100644 tests/auto/qtextbrowser/qtextbrowser.pro delete mode 100644 tests/auto/qtextbrowser/secondpage.html delete mode 100644 tests/auto/qtextbrowser/subdir/index.html delete mode 100644 tests/auto/qtextbrowser/thirdpage.html delete mode 100644 tests/auto/qtextbrowser/tst_qtextbrowser.cpp delete mode 100644 tests/auto/qtextedit/.gitignore delete mode 100644 tests/auto/qtextedit/fullWidthSelection/centered-fully-selected.png delete mode 100644 tests/auto/qtextedit/fullWidthSelection/centered-partly-selected.png delete mode 100644 tests/auto/qtextedit/fullWidthSelection/last-char-on-line.png delete mode 100644 tests/auto/qtextedit/fullWidthSelection/last-char-on-parag.png delete mode 100644 tests/auto/qtextedit/fullWidthSelection/multiple-full-width-lines.png delete mode 100644 tests/auto/qtextedit/fullWidthSelection/nowrap_long.png delete mode 100644 tests/auto/qtextedit/fullWidthSelection/single-full-width-line.png delete mode 100644 tests/auto/qtextedit/qtextedit.pro delete mode 100644 tests/auto/qtextedit/tst_qtextedit.cpp delete mode 100644 tests/auto/qtoolbar/.gitignore delete mode 100644 tests/auto/qtoolbar/qtoolbar.pro delete mode 100644 tests/auto/qtoolbar/tst_qtoolbar.cpp delete mode 100644 tests/auto/qtoolbox/.gitignore delete mode 100644 tests/auto/qtoolbox/qtoolbox.pro delete mode 100644 tests/auto/qtoolbox/tst_qtoolbox.cpp delete mode 100644 tests/auto/qtoolbutton/.gitignore delete mode 100644 tests/auto/qtoolbutton/qtoolbutton.pro delete mode 100644 tests/auto/qtoolbutton/tst_qtoolbutton.cpp delete mode 100644 tests/auto/qtooltip/.gitignore delete mode 100644 tests/auto/qtooltip/qtooltip.pro delete mode 100644 tests/auto/qtooltip/tst_qtooltip.cpp delete mode 100644 tests/auto/qtreeview/.gitignore delete mode 100644 tests/auto/qtreeview/qtreeview.pro delete mode 100644 tests/auto/qtreeview/tst_qtreeview.cpp delete mode 100644 tests/auto/qtreewidget/.gitignore delete mode 100644 tests/auto/qtreewidget/qtreewidget.pro delete mode 100644 tests/auto/qtreewidget/tst_qtreewidget.cpp delete mode 100644 tests/auto/qtreewidgetitemiterator/.gitignore delete mode 100644 tests/auto/qtreewidgetitemiterator/qtreewidgetitemiterator.pro delete mode 100644 tests/auto/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp delete mode 100644 tests/auto/qundogroup/.gitignore delete mode 100644 tests/auto/qundogroup/qundogroup.pro delete mode 100644 tests/auto/qundogroup/testdata/qundogroup.ts delete mode 100644 tests/auto/qundogroup/tst_qundogroup.cpp delete mode 100644 tests/auto/qundostack/.gitignore delete mode 100644 tests/auto/qundostack/qundostack.pro delete mode 100644 tests/auto/qundostack/testdata/qundostack.ts delete mode 100644 tests/auto/qundostack/tst_qundostack.cpp delete mode 100644 tests/auto/qwidget/.gitignore delete mode 100644 tests/auto/qwidget/geometry-fullscreen.dat delete mode 100644 tests/auto/qwidget/geometry-maximized.dat delete mode 100644 tests/auto/qwidget/geometry.dat delete mode 100644 tests/auto/qwidget/qwidget.pro delete mode 100644 tests/auto/qwidget/qwidget.qrc delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Motif_data0.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Motif_data1.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Motif_data2.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Motif_data3.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Windows_data0.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Windows_data1.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Windows_data2.qsnap delete mode 100644 tests/auto/qwidget/testdata/paintEvent/res_Windows_data3.qsnap delete mode 100644 tests/auto/qwidget/tst_qwidget.cpp delete mode 100644 tests/auto/qwidget/tst_qwidget_mac_helpers.h delete mode 100644 tests/auto/qwidget/tst_qwidget_mac_helpers.mm delete mode 100644 tests/auto/qwidget_window/.gitignore delete mode 100644 tests/auto/qwidget_window/qwidget_window.pro delete mode 100644 tests/auto/qwidget_window/tst_qwidget_window.cpp delete mode 100644 tests/auto/qwidgetaction/.gitignore delete mode 100644 tests/auto/qwidgetaction/qwidgetaction.pro delete mode 100644 tests/auto/qwidgetaction/tst_qwidgetaction.cpp delete mode 100644 tests/auto/qwizard/.gitignore delete mode 100644 tests/auto/qwizard/images/background.png delete mode 100644 tests/auto/qwizard/images/banner.png delete mode 100644 tests/auto/qwizard/images/logo.png delete mode 100644 tests/auto/qwizard/images/watermark.png delete mode 100644 tests/auto/qwizard/qwizard.pro delete mode 100644 tests/auto/qwizard/qwizard.qrc delete mode 100644 tests/auto/qwizard/tst_qwizard.cpp delete mode 100644 tests/auto/qworkspace/.gitignore delete mode 100644 tests/auto/qworkspace/qworkspace.pro delete mode 100644 tests/auto/qworkspace/tst_qworkspace.cpp create mode 100644 tests/auto/widgets/dialogs/dialogs.pro create mode 100644 tests/auto/widgets/dialogs/qabstractprintdialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qabstractprintdialog/qabstractprintdialog.pro create mode 100644 tests/auto/widgets/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp create mode 100644 tests/auto/widgets/dialogs/qcolordialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro create mode 100644 tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp create mode 100644 tests/auto/widgets/dialogs/qdialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qdialog/qdialog.pro create mode 100644 tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp create mode 100644 tests/auto/widgets/dialogs/qerrormessage/.gitignore create mode 100644 tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro create mode 100644 tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp create mode 100644 tests/auto/widgets/dialogs/qfiledialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro create mode 100644 tests/auto/widgets/dialogs/qfiledialog/resources/file.txt create mode 100644 tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp create mode 100644 tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro create mode 100644 tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp create mode 100644 tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore create mode 100644 tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro create mode 100644 tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp create mode 100644 tests/auto/widgets/dialogs/qfontdialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro create mode 100644 tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp create mode 100644 tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm create mode 100644 tests/auto/widgets/dialogs/qinputdialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro create mode 100644 tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp create mode 100644 tests/auto/widgets/dialogs/qmessagebox/.gitignore create mode 100644 tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro create mode 100644 tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp create mode 100644 tests/auto/widgets/dialogs/qprogressdialog/.gitignore create mode 100644 tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro create mode 100644 tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp create mode 100644 tests/auto/widgets/dialogs/qsidebar/.gitignore create mode 100644 tests/auto/widgets/dialogs/qsidebar/qsidebar.pro create mode 100644 tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp create mode 100644 tests/auto/widgets/dialogs/qwizard/.gitignore create mode 100644 tests/auto/widgets/dialogs/qwizard/images/background.png create mode 100644 tests/auto/widgets/dialogs/qwizard/images/banner.png create mode 100644 tests/auto/widgets/dialogs/qwizard/images/logo.png create mode 100644 tests/auto/widgets/dialogs/qwizard/images/watermark.png create mode 100644 tests/auto/widgets/dialogs/qwizard/qwizard.pro create mode 100644 tests/auto/widgets/dialogs/qwizard/qwizard.qrc create mode 100644 tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp create mode 100644 tests/auto/widgets/effects/effects.pro create mode 100644 tests/auto/widgets/effects/qgraphicseffect/qgraphicseffect.pro create mode 100644 tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp create mode 100644 tests/auto/widgets/graphicsview/graphicsview.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png create mode 100644 tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsview/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp create mode 100644 tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore create mode 100644 tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro create mode 100644 tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp create mode 100644 tests/auto/widgets/itemviews/itemviews.pro create mode 100644 tests/auto/widgets/itemviews/qabstractitemview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro create mode 100644 tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp create mode 100644 tests/auto/widgets/itemviews/qabstractproxymodel/.gitignore create mode 100644 tests/auto/widgets/itemviews/qabstractproxymodel/qabstractproxymodel.pro create mode 100644 tests/auto/widgets/itemviews/qabstractproxymodel/tst_qabstractproxymodel.cpp create mode 100644 tests/auto/widgets/itemviews/qcolumnview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qcolumnview/qcolumnview.pro create mode 100644 tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp create mode 100644 tests/auto/widgets/itemviews/qdatawidgetmapper/.gitignore create mode 100644 tests/auto/widgets/itemviews/qdatawidgetmapper/qdatawidgetmapper.pro create mode 100644 tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp create mode 100644 tests/auto/widgets/itemviews/qdirmodel/.gitignore create mode 100644 tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/dummy create mode 100644 tests/auto/widgets/itemviews/qdirmodel/dirtest/test1/test create mode 100644 tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro create mode 100644 tests/auto/widgets/itemviews/qdirmodel/test/file01.tst create mode 100644 tests/auto/widgets/itemviews/qdirmodel/test/file02.tst create mode 100644 tests/auto/widgets/itemviews/qdirmodel/test/file03.tst create mode 100644 tests/auto/widgets/itemviews/qdirmodel/test/file04.tst create mode 100644 tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp create mode 100644 tests/auto/widgets/itemviews/qfileiconprovider/.gitignore create mode 100644 tests/auto/widgets/itemviews/qfileiconprovider/qfileiconprovider.pro create mode 100644 tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp create mode 100644 tests/auto/widgets/itemviews/qheaderview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qheaderview/qheaderview.pro create mode 100644 tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp create mode 100644 tests/auto/widgets/itemviews/qidentityproxymodel/qidentityproxymodel.pro create mode 100644 tests/auto/widgets/itemviews/qidentityproxymodel/tst_qidentityproxymodel.cpp create mode 100644 tests/auto/widgets/itemviews/qitemdelegate/.gitignore create mode 100644 tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro create mode 100644 tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp create mode 100644 tests/auto/widgets/itemviews/qitemeditorfactory/.gitignore create mode 100644 tests/auto/widgets/itemviews/qitemeditorfactory/qitemeditorfactory.pro create mode 100644 tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp create mode 100644 tests/auto/widgets/itemviews/qitemselectionmodel/.gitignore create mode 100644 tests/auto/widgets/itemviews/qitemselectionmodel/qitemselectionmodel.pro create mode 100644 tests/auto/widgets/itemviews/qitemselectionmodel/tst_qitemselectionmodel.cpp create mode 100644 tests/auto/widgets/itemviews/qitemview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qitemview/qitemview.pro create mode 100644 tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp create mode 100644 tests/auto/widgets/itemviews/qitemview/viewstotest.cpp create mode 100644 tests/auto/widgets/itemviews/qlistview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qlistview/qlistview.pro create mode 100644 tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp create mode 100644 tests/auto/widgets/itemviews/qlistwidget/.gitignore create mode 100644 tests/auto/widgets/itemviews/qlistwidget/qlistwidget.pro create mode 100644 tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp create mode 100644 tests/auto/widgets/itemviews/qsortfilterproxymodel/.gitignore create mode 100644 tests/auto/widgets/itemviews/qsortfilterproxymodel/qsortfilterproxymodel.pro create mode 100644 tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp create mode 100644 tests/auto/widgets/itemviews/qstandarditem/.gitignore create mode 100644 tests/auto/widgets/itemviews/qstandarditem/qstandarditem.pro create mode 100644 tests/auto/widgets/itemviews/qstandarditem/tst_qstandarditem.cpp create mode 100644 tests/auto/widgets/itemviews/qstandarditemmodel/.gitignore create mode 100644 tests/auto/widgets/itemviews/qstandarditemmodel/qstandarditemmodel.pro create mode 100644 tests/auto/widgets/itemviews/qstandarditemmodel/tst_qstandarditemmodel.cpp create mode 100644 tests/auto/widgets/itemviews/qstringlistmodel/.gitignore create mode 100644 tests/auto/widgets/itemviews/qstringlistmodel/qmodellistener.h create mode 100644 tests/auto/widgets/itemviews/qstringlistmodel/qstringlistmodel.pro create mode 100644 tests/auto/widgets/itemviews/qstringlistmodel/tst_qstringlistmodel.cpp create mode 100644 tests/auto/widgets/itemviews/qtableview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qtableview/qtableview.pro create mode 100644 tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp create mode 100644 tests/auto/widgets/itemviews/qtablewidget/.gitignore create mode 100644 tests/auto/widgets/itemviews/qtablewidget/qtablewidget.pro create mode 100644 tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp create mode 100644 tests/auto/widgets/itemviews/qtreeview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qtreeview/qtreeview.pro create mode 100644 tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp create mode 100644 tests/auto/widgets/itemviews/qtreewidget/.gitignore create mode 100644 tests/auto/widgets/itemviews/qtreewidget/qtreewidget.pro create mode 100644 tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp create mode 100644 tests/auto/widgets/itemviews/qtreewidgetitemiterator/.gitignore create mode 100644 tests/auto/widgets/itemviews/qtreewidgetitemiterator/qtreewidgetitemiterator.pro create mode 100644 tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp create mode 100644 tests/auto/widgets/kernel/kernel.pro create mode 100644 tests/auto/widgets/kernel/qaction/.gitignore create mode 100644 tests/auto/widgets/kernel/qaction/qaction.pro create mode 100644 tests/auto/widgets/kernel/qaction/tst_qaction.cpp create mode 100644 tests/auto/widgets/kernel/qactiongroup/.gitignore create mode 100644 tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro create mode 100644 tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp create mode 100644 tests/auto/widgets/kernel/qapplication/.gitignore create mode 100644 tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro create mode 100644 tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp create mode 100644 tests/auto/widgets/kernel/qapplication/heart.svg create mode 100644 tests/auto/widgets/kernel/qapplication/modal/base.cpp create mode 100644 tests/auto/widgets/kernel/qapplication/modal/base.h create mode 100644 tests/auto/widgets/kernel/qapplication/modal/main.cpp create mode 100644 tests/auto/widgets/kernel/qapplication/modal/modal.pro create mode 100644 tests/auto/widgets/kernel/qapplication/qapplication.pro create mode 100644 tests/auto/widgets/kernel/qapplication/test/test.pro create mode 100644 tests/auto/widgets/kernel/qapplication/tmp/README create mode 100644 tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp create mode 100644 tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp create mode 100644 tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro create mode 100644 tests/auto/widgets/kernel/qboxlayout/.gitignore create mode 100644 tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro create mode 100644 tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp create mode 100644 tests/auto/widgets/kernel/qdesktopwidget/.gitignore create mode 100644 tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro create mode 100644 tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp create mode 100644 tests/auto/widgets/kernel/qformlayout/.gitignore create mode 100644 tests/auto/widgets/kernel/qformlayout/qformlayout.pro create mode 100644 tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp create mode 100644 tests/auto/widgets/kernel/qgridlayout/.gitignore create mode 100644 tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro create mode 100644 tests/auto/widgets/kernel/qgridlayout/sortdialog.ui create mode 100644 tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp create mode 100644 tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro create mode 100644 tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp create mode 100644 tests/auto/widgets/kernel/qlayout/.gitignore create mode 100644 tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize create mode 100644 tests/auto/widgets/kernel/qlayout/qlayout.pro create mode 100644 tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp create mode 100644 tests/auto/widgets/kernel/qsound/.gitignore create mode 100644 tests/auto/widgets/kernel/qsound/4.wav create mode 100644 tests/auto/widgets/kernel/qsound/qsound.pro create mode 100644 tests/auto/widgets/kernel/qsound/tst_qsound.cpp create mode 100644 tests/auto/widgets/kernel/qstackedlayout/.gitignore create mode 100644 tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro create mode 100644 tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp create mode 100644 tests/auto/widgets/kernel/qtooltip/.gitignore create mode 100644 tests/auto/widgets/kernel/qtooltip/qtooltip.pro create mode 100644 tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp create mode 100644 tests/auto/widgets/kernel/qwidget/.gitignore create mode 100644 tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat create mode 100644 tests/auto/widgets/kernel/qwidget/geometry-maximized.dat create mode 100644 tests/auto/widgets/kernel/qwidget/geometry.dat create mode 100644 tests/auto/widgets/kernel/qwidget/qwidget.pro create mode 100644 tests/auto/widgets/kernel/qwidget/qwidget.qrc create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap create mode 100644 tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp create mode 100644 tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h create mode 100644 tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm create mode 100644 tests/auto/widgets/kernel/qwidget_window/.gitignore create mode 100644 tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro create mode 100644 tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp create mode 100644 tests/auto/widgets/kernel/qwidgetaction/.gitignore create mode 100644 tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro create mode 100644 tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp create mode 100644 tests/auto/widgets/styles/qmacstyle/.gitignore create mode 100644 tests/auto/widgets/styles/qmacstyle/qmacstyle.pro create mode 100644 tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp create mode 100644 tests/auto/widgets/styles/qstyle/.gitignore create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/button.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/combobox.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/lineedit.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/mdi.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/menu.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/slider.png create mode 100644 tests/auto/widgets/styles/qstyle/images/mac/spinbox.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/button.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/combobox.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/lineedit.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/menu.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/slider.png create mode 100644 tests/auto/widgets/styles/qstyle/images/vista/spinbox.png create mode 100644 tests/auto/widgets/styles/qstyle/qstyle.pro create mode 100644 tests/auto/widgets/styles/qstyle/task_25863.png create mode 100644 tests/auto/widgets/styles/qstyle/tst_qstyle.cpp create mode 100644 tests/auto/widgets/styles/qstyleoption/.gitignore create mode 100644 tests/auto/widgets/styles/qstyleoption/qstyleoption.pro create mode 100644 tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp create mode 100644 tests/auto/widgets/styles/qstylesheetstyle/.gitignore create mode 100644 tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png create mode 100644 tests/auto/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro create mode 100644 tests/auto/widgets/styles/qstylesheetstyle/resources.qrc create mode 100644 tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp create mode 100644 tests/auto/widgets/styles/styles.pro create mode 100644 tests/auto/widgets/util/qcompleter/.gitignore create mode 100644 tests/auto/widgets/util/qcompleter/qcompleter.pro create mode 100644 tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp create mode 100644 tests/auto/widgets/util/qscroller/qscroller.pro create mode 100644 tests/auto/widgets/util/qscroller/tst_qscroller.cpp create mode 100644 tests/auto/widgets/util/qsystemtrayicon/.gitignore create mode 100644 tests/auto/widgets/util/qsystemtrayicon/icons/icon.png create mode 100644 tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro create mode 100644 tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp create mode 100644 tests/auto/widgets/util/qundogroup/.gitignore create mode 100644 tests/auto/widgets/util/qundogroup/qundogroup.pro create mode 100644 tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts create mode 100644 tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp create mode 100644 tests/auto/widgets/util/qundostack/.gitignore create mode 100644 tests/auto/widgets/util/qundostack/qundostack.pro create mode 100644 tests/auto/widgets/util/qundostack/testdata/qundostack.ts create mode 100644 tests/auto/widgets/util/qundostack/tst_qundostack.cpp create mode 100644 tests/auto/widgets/util/util.pro create mode 100644 tests/auto/widgets/widgets.pro create mode 100644 tests/auto/widgets/widgets/qabstractbutton/.gitignore create mode 100644 tests/auto/widgets/widgets/qabstractbutton/qabstractbutton.pro create mode 100644 tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp create mode 100644 tests/auto/widgets/widgets/qabstractscrollarea/.gitignore create mode 100644 tests/auto/widgets/widgets/qabstractscrollarea/qabstractscrollarea.pro create mode 100644 tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp create mode 100644 tests/auto/widgets/widgets/qabstractslider/.gitignore create mode 100644 tests/auto/widgets/widgets/qabstractslider/qabstractslider.pro create mode 100644 tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp create mode 100644 tests/auto/widgets/widgets/qabstractspinbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qabstractspinbox/qabstractspinbox.pro create mode 100644 tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp create mode 100644 tests/auto/widgets/widgets/qbuttongroup/.gitignore create mode 100644 tests/auto/widgets/widgets/qbuttongroup/qbuttongroup.pro create mode 100644 tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp create mode 100644 tests/auto/widgets/widgets/qcalendarwidget/.gitignore create mode 100644 tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro create mode 100644 tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp create mode 100644 tests/auto/widgets/widgets/qcheckbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qcheckbox/qcheckbox.pro create mode 100644 tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp create mode 100644 tests/auto/widgets/widgets/qcombobox/.gitignore create mode 100644 tests/auto/widgets/widgets/qcombobox/qcombobox.pro create mode 100644 tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp create mode 100644 tests/auto/widgets/widgets/qcommandlinkbutton/.gitignore create mode 100644 tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro create mode 100644 tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp create mode 100644 tests/auto/widgets/widgets/qdatetimeedit/.gitignore create mode 100644 tests/auto/widgets/widgets/qdatetimeedit/qdatetimeedit.pro create mode 100644 tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp create mode 100644 tests/auto/widgets/widgets/qdial/.gitignore create mode 100644 tests/auto/widgets/widgets/qdial/qdial.pro create mode 100644 tests/auto/widgets/widgets/qdial/tst_qdial.cpp create mode 100644 tests/auto/widgets/widgets/qdialogbuttonbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qdialogbuttonbox/qdialogbuttonbox.pro create mode 100644 tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp create mode 100644 tests/auto/widgets/widgets/qdockwidget/.gitignore create mode 100644 tests/auto/widgets/widgets/qdockwidget/qdockwidget.pro create mode 100644 tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp create mode 100644 tests/auto/widgets/widgets/qdoublespinbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qdoublespinbox/qdoublespinbox.pro create mode 100644 tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp create mode 100644 tests/auto/widgets/widgets/qdoublevalidator/.gitignore create mode 100644 tests/auto/widgets/widgets/qdoublevalidator/qdoublevalidator.pro create mode 100644 tests/auto/widgets/widgets/qdoublevalidator/tst_qdoublevalidator.cpp create mode 100644 tests/auto/widgets/widgets/qfocusframe/.gitignore create mode 100644 tests/auto/widgets/widgets/qfocusframe/qfocusframe.pro create mode 100644 tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp create mode 100644 tests/auto/widgets/widgets/qfontcombobox/.gitignore create mode 100644 tests/auto/widgets/widgets/qfontcombobox/qfontcombobox.pro create mode 100644 tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp create mode 100644 tests/auto/widgets/widgets/qgroupbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro create mode 100644 tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp create mode 100644 tests/auto/widgets/widgets/qintvalidator/.gitignore create mode 100644 tests/auto/widgets/widgets/qintvalidator/qintvalidator.pro create mode 100644 tests/auto/widgets/widgets/qintvalidator/tst_qintvalidator.cpp create mode 100644 tests/auto/widgets/widgets/qlabel/.gitignore create mode 100644 tests/auto/widgets/widgets/qlabel/green.png create mode 100644 tests/auto/widgets/widgets/qlabel/qlabel.pro create mode 100644 tests/auto/widgets/widgets/qlabel/red.png create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data3.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data3.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data1.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data2.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data3.qsnap create mode 100644 tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp create mode 100644 tests/auto/widgets/widgets/qlcdnumber/.gitignore create mode 100644 tests/auto/widgets/widgets/qlcdnumber/qlcdnumber.pro create mode 100644 tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp create mode 100644 tests/auto/widgets/widgets/qlineedit/.gitignore create mode 100644 tests/auto/widgets/widgets/qlineedit/qlineedit.pro create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png create mode 100644 tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp create mode 100644 tests/auto/widgets/widgets/qmainwindow/.gitignore create mode 100644 tests/auto/widgets/widgets/qmainwindow/qmainwindow.pro create mode 100644 tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp create mode 100644 tests/auto/widgets/widgets/qmdiarea/.gitignore create mode 100644 tests/auto/widgets/widgets/qmdiarea/qmdiarea.pro create mode 100644 tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp create mode 100644 tests/auto/widgets/widgets/qmdisubwindow/.gitignore create mode 100644 tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro create mode 100644 tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp create mode 100644 tests/auto/widgets/widgets/qmenu/.gitignore create mode 100644 tests/auto/widgets/widgets/qmenu/qmenu.pro create mode 100644 tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp create mode 100644 tests/auto/widgets/widgets/qmenubar/.gitignore create mode 100644 tests/auto/widgets/widgets/qmenubar/qmenubar.pro create mode 100644 tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp create mode 100644 tests/auto/widgets/widgets/qplaintextedit/.gitignore create mode 100644 tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro create mode 100644 tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp create mode 100644 tests/auto/widgets/widgets/qprogressbar/.gitignore create mode 100644 tests/auto/widgets/widgets/qprogressbar/qprogressbar.pro create mode 100644 tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp create mode 100644 tests/auto/widgets/widgets/qpushbutton/.gitignore create mode 100644 tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Motif_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap create mode 100644 tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp create mode 100644 tests/auto/widgets/widgets/qradiobutton/.gitignore create mode 100644 tests/auto/widgets/widgets/qradiobutton/qradiobutton.pro create mode 100644 tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp create mode 100644 tests/auto/widgets/widgets/qregexpvalidator/.gitignore create mode 100644 tests/auto/widgets/widgets/qregexpvalidator/qregexpvalidator.pro create mode 100644 tests/auto/widgets/widgets/qregexpvalidator/tst_qregexpvalidator.cpp create mode 100644 tests/auto/widgets/widgets/qscrollarea/.gitignore create mode 100644 tests/auto/widgets/widgets/qscrollarea/qscrollarea.pro create mode 100644 tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp create mode 100644 tests/auto/widgets/widgets/qscrollbar/.gitignore create mode 100644 tests/auto/widgets/widgets/qscrollbar/qscrollbar.pro create mode 100644 tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp create mode 100644 tests/auto/widgets/widgets/qsizegrip/.gitignore create mode 100644 tests/auto/widgets/widgets/qsizegrip/qsizegrip.pro create mode 100644 tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp create mode 100644 tests/auto/widgets/widgets/qslider/.gitignore create mode 100644 tests/auto/widgets/widgets/qslider/qslider.pro create mode 100644 tests/auto/widgets/widgets/qslider/tst_qslider.cpp create mode 100644 tests/auto/widgets/widgets/qspinbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qspinbox/qspinbox.pro create mode 100644 tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp create mode 100644 tests/auto/widgets/widgets/qsplitter/.gitignore create mode 100644 tests/auto/widgets/widgets/qsplitter/extradata.txt create mode 100644 tests/auto/widgets/widgets/qsplitter/qsplitter.pro create mode 100644 tests/auto/widgets/widgets/qsplitter/setSizes3.dat create mode 100644 tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp create mode 100644 tests/auto/widgets/widgets/qstackedwidget/.gitignore create mode 100644 tests/auto/widgets/widgets/qstackedwidget/qstackedwidget.pro create mode 100644 tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp create mode 100644 tests/auto/widgets/widgets/qstatusbar/.gitignore create mode 100644 tests/auto/widgets/widgets/qstatusbar/qstatusbar.pro create mode 100644 tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp create mode 100644 tests/auto/widgets/widgets/qtabbar/.gitignore create mode 100644 tests/auto/widgets/widgets/qtabbar/qtabbar.pro create mode 100644 tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp create mode 100644 tests/auto/widgets/widgets/qtabwidget/.gitignore create mode 100644 tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro create mode 100644 tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp create mode 100644 tests/auto/widgets/widgets/qtextbrowser/.gitignore create mode 100644 tests/auto/widgets/widgets/qtextbrowser/anchor.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/bigpage.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/firstpage.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/pagewithbg.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/pagewithimage.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/pagewithoutbg.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro create mode 100644 tests/auto/widgets/widgets/qtextbrowser/secondpage.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/subdir/index.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/thirdpage.html create mode 100644 tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp create mode 100644 tests/auto/widgets/widgets/qtextedit/.gitignore create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-fully-selected.png create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-partly-selected.png create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-line.png create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-parag.png create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/multiple-full-width-lines.png create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/nowrap_long.png create mode 100644 tests/auto/widgets/widgets/qtextedit/fullWidthSelection/single-full-width-line.png create mode 100644 tests/auto/widgets/widgets/qtextedit/qtextedit.pro create mode 100644 tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp create mode 100644 tests/auto/widgets/widgets/qtoolbar/.gitignore create mode 100644 tests/auto/widgets/widgets/qtoolbar/qtoolbar.pro create mode 100644 tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp create mode 100644 tests/auto/widgets/widgets/qtoolbox/.gitignore create mode 100644 tests/auto/widgets/widgets/qtoolbox/qtoolbox.pro create mode 100644 tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp create mode 100644 tests/auto/widgets/widgets/qtoolbutton/.gitignore create mode 100644 tests/auto/widgets/widgets/qtoolbutton/qtoolbutton.pro create mode 100644 tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp create mode 100644 tests/auto/widgets/widgets/qworkspace/.gitignore create mode 100644 tests/auto/widgets/widgets/qworkspace/qworkspace.pro create mode 100644 tests/auto/widgets/widgets/qworkspace/tst_qworkspace.cpp create mode 100644 tests/auto/widgets/widgets/widgets.pro delete mode 100644 tests/auto/windowsmobile/test/ddhelper.cpp delete mode 100644 tests/auto/windowsmobile/test/ddhelper.h delete mode 100644 tests/auto/windowsmobile/test/test.pro delete mode 100644 tests/auto/windowsmobile/test/testQMenuBar_current.png delete mode 100644 tests/auto/windowsmobile/test/testSimpleWidget_current.png delete mode 100644 tests/auto/windowsmobile/test/tst_windowsmobile.cpp delete mode 100644 tests/auto/windowsmobile/test/windowsmobile.qrc delete mode 100644 tests/auto/windowsmobile/testQMenuBar/main.cpp delete mode 100644 tests/auto/windowsmobile/testQMenuBar/testQMenuBar.pro delete mode 100644 tests/auto/windowsmobile/windowsmobile.pro (limited to 'tests/auto') diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 86fe037887..ded314d9ba 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -5,6 +5,7 @@ SUBDIRS += \ dbus \ host.pro \ gui.pro \ + integrationtests \ network.pro \ opengl \ sql \ @@ -13,6 +14,7 @@ SUBDIRS += \ v8.pro \ xml \ other.pro \ + widgets \ cross_compile: SUBDIRS -= host.pro cross_compile: SUBDIRS -= tools diff --git a/tests/auto/collections/.gitignore b/tests/auto/collections/.gitignore deleted file mode 100644 index dcd9d49ec0..0000000000 --- a/tests/auto/collections/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_collections diff --git a/tests/auto/collections/collections.pro b/tests/auto/collections/collections.pro deleted file mode 100644 index 8601ff877d..0000000000 --- a/tests/auto/collections/collections.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_collections.cpp -QT = core -CONFIG += parallel_test diff --git a/tests/auto/collections/tst_collections.cpp b/tests/auto/collections/tst_collections.cpp deleted file mode 100644 index f09ff06234..0000000000 --- a/tests/auto/collections/tst_collections.cpp +++ /dev/null @@ -1,3846 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - - -// test the container forwards -#include - -static QCache *cacheX; -static QHash *hashX; -static QLinkedList *linkedListX; -static QList *listX; -static QMap *mapX; -static QMultiHash *multiHashX; -static QMultiMap *multiMapX; -static QPair *pairX; -static QQueue *queueX; -static QSet *setX; -static QStack *stackX; -static QVarLengthArray *varLengthArrayX; -static QVarLengthArray *varLengthArrayY; -static QVector *vectorX; - -void foo() -{ - cacheX = 0; - hashX = 0; - linkedListX = 0; - listX = 0; - mapX = 0; - multiHashX = 0; - multiMapX = 0; - pairX = 0; - queueX = 0; - setX = 0; - stackX = 0; - varLengthArrayX = 0; - varLengthArrayY = 0; - vectorX = 0; -} - -#include - -#ifndef QT_NO_STL -# include -#endif - -#include "qalgorithms.h" -#include "qbitarray.h" -#include "qbytearray.h" -#include "qcache.h" -#include "qhash.h" -#include "qlinkedlist.h" -#include "qlist.h" -#include "qmap.h" -#include "qpair.h" -#include "qregexp.h" -#include "qset.h" -#include "qstack.h" -#include "qstring.h" -#include "qstringlist.h" -#include "qvarlengtharray.h" -#include "qvector.h" -#include "qqueue.h" - -template class QList; - -//TESTED_FILES= - -class tst_Collections : public QObject -{ - Q_OBJECT - -public: - tst_Collections(); - ~tst_Collections(); - -public slots: - void init(); - void cleanup(); -private slots: - void typeinfo(); - void qstring(); - void list(); - void linkedList(); - void vector(); - void byteArray(); - void stack(); - void hash(); - void map(); - void bitArray(); - void cache(); - void regexp(); - void pair(); - void sharableQList(); - void sharableQLinkedList(); - void sharableQVector(); - void sharableQMap(); - void sharableQHash(); - void q_foreach(); - void conversions(); - void javaStyleIterators(); - void constAndNonConstStlIterators(); -#ifndef QT_NO_STL - void vector_stl_data(); - void vector_stl(); - void list_stl_data(); - void list_stl(); - void linkedlist_stl_data(); - void linkedlist_stl(); -#endif - void q_init(); - void pointersize(); - void containerInstantiation(); - void qtimerList(); - void containerTypedefs(); - void forwardDeclared(); -#if defined(Q_ALIGNOF) && defined(Q_DECL_ALIGN) - void alignment(); -#endif - void QTBUG13079_collectionInsideCollection(); - - void foreach_2(); - void insert_remove_loop(); -}; - -struct LargeStatic { - static int count; - LargeStatic():c(count) { ++count; } - LargeStatic(const LargeStatic& o):c(o.c) { ++count; } - ~LargeStatic() { --count; } - int c; - int data[8]; -}; - -int LargeStatic::count = 0; - -struct Movable { - static int count; - Movable():c(count) { ++count; } - Movable(const Movable& o):c(o.c) { ++count; } - ~Movable() { --count; } - int c; -}; - -int Movable::count = 0; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); -QT_END_NAMESPACE - - -struct Pod { - int i1, i2; -}; - -tst_Collections::tst_Collections() -{ -} - -tst_Collections::~tst_Collections() -{ - -} - -void tst_Collections::init() -{ -} - -void tst_Collections::cleanup() -{ -} - -void tst_Collections::typeinfo() -{ - QVERIFY(QTypeInfo::isPointer); - QVERIFY(!QTypeInfo::isPointer); - QVERIFY(QTypeInfo::isComplex); - QVERIFY(!QTypeInfo::isComplex); -} - -void tst_Collections::list() -{ - { - QList list; - QVERIFY(list.isEmpty()); - list.append(1); - QVERIFY(list.size() == 1); - - QVERIFY(*list.begin() == 1); - - list.push_back(2); - list += (3); - list << 4 << 5 << 6; - QVERIFY(!list.isEmpty()); - QVERIFY(list.size() == 6); - QVERIFY(list.end() - list.begin() == list.size()); - -#if !defined(QT_NO_STL) && !defined(Q_CC_MSVC) && !defined(Q_CC_SUN) - QVERIFY(std::binary_search(list.begin(), list.end(), 2) == true); - QVERIFY(std::binary_search(list.begin(), list.end(), 9) == false); -#endif - QVERIFY(qBinaryFind(list.begin(), list.end(), 2) == list.begin() + 1); - QVERIFY(qLowerBound(list.begin(), list.end(), 2) == list.begin() + 1); - QVERIFY(qUpperBound(list.begin(), list.end(), 2) == list.begin() + 2); - QVERIFY(qBinaryFind(list.begin(), list.end(), 9) == list.end()); - QVERIFY(qLowerBound(list.begin(), list.end(), 9) == list.end()); - QVERIFY(qUpperBound(list.begin(), list.end(), 9) == list.end()); - { - int sum = 0; - QListIterator i(list); - while (i.hasNext()) - sum += i.next(); - QVERIFY(sum == 21); - } - - { - QList list1; - list1 << 1 << 2 << 3 << 5 << 7 << 8 << 9; - QList list2 = list1; - - QMutableListIterator i1(list1); - while (i1.hasNext()) { - if (i1.next() % 2 != 0) - i1.remove(); - } - - QMutableListIterator i2(list2); - i2.toBack(); - while (i2.hasPrevious()) { - if (i2.previous() % 2 != 0) - i2.remove(); - } - QVERIFY(list1.size() == 2); - QVERIFY(list2.size() == 2); - QVERIFY(list1 == list2); - } - - { - int sum = 0; - for (int i = 0; i < list.size(); ++i) - sum += list[i]; - QVERIFY(sum == 21); - } - { - int sum = 0; - QList::const_iterator i = list.begin(); - while (i != list.end()) - sum += *i++; - QVERIFY(sum == 21); - } - { - int sum = 0; - QList::ConstIterator i = list.begin(); - while (i != list.end()) - sum += *i++; - QVERIFY(sum == 21); - } - { - QList::Iterator i = list.begin(); - i += 2; - QCOMPARE(*i, 3); - i -= 1; - QCOMPARE(*i, 2); - } - { - QList::ConstIterator i = list.begin(); - i += 2; - QCOMPARE(*i, 3); - i -= 1; - QCOMPARE(*i, 2); - } - { - int sum = 0; - int i; - for (i = 0; i < list.size(); ++i) - list[i] = list[i] +1; - for (i = 0; i < list.size(); ++i) - sum += list[i]; - QVERIFY(sum == 21 + list.size()); - } - { - int sum = 0; - int i; - for (i = 0; i < list.size(); ++i) - --list[i]; - for (i = 0; i < list.size(); ++i) - sum += list[i]; - QVERIFY(sum == 21); - } - { - QMutableListIterator i(list); - while (i.hasNext()) - i.setValue(2*i.next()); - } - { - int sum = 0; - QListIterator i(list); - i.toBack(); - while (i.hasPrevious()) - sum += i.previous(); - QVERIFY(sum == 2*21); - } - { - QMutableListIterator i(list); - i.toBack(); - while (i.hasPrevious()) - i.setValue(2*i.previous()); - } - { - int sum = 0; - QListIterator i(list); - i.toBack(); - while (i.hasPrevious()) - sum += i.previous(); - QVERIFY(sum == 2*2*21); - } - { - QMutableListIterator i(list); - while (i.hasNext()) { - int a = i.next(); - i.insert(a); - } - } - { - int sum = 0; - QList::iterator i = list.begin(); - while (i != list.end()) - sum += *i++; - QVERIFY(sum == 2*2*2*21); - } - { - int duplicates = 0; - QListIterator i(list); - while (i.hasNext()) { - int a = i.next(); - if (i.hasNext() && a == i.peekNext()) - duplicates++; - } - QVERIFY(duplicates == 6); - } - { - int duplicates = 0; - QListIterator i(list); - i.toBack(); - while (i.hasPrevious()) { - int a = i.previous(); - if (i.hasPrevious() && a == i.peekPrevious()) - duplicates++; - } - QVERIFY(duplicates == 6); - } - { - QMutableListIterator i(list); - while (i.hasNext()) { - int a = i.next(); - if (i.hasNext() && - i.peekNext() == a) - i.remove(); - } - } - { - int duplicates = 0; - QMutableListIterator i = list; - i.toBack(); - while (i.hasPrevious()) { - int a = i.previous(); - if (i.hasPrevious() && a == i.peekPrevious()) - duplicates++; - } - QVERIFY(duplicates == 0); - } - { - QVERIFY(list.size() == 6); - QMutableListIterator i = list; - while (i.hasNext()) { - int a = i.peekNext(); - i.insert(42); - QVERIFY(i.peekPrevious() == 42 && i.peekNext() == a); - i.next(); - } - QVERIFY(list.size() == 12); - i.toFront(); - while (i.findNext(42)) - i.remove(); - } - { - QList l; - l << 4 << 8 << 12 << 16 << 20 << 24; - QVERIFY(l == list); - QList copy = list; - list += list; - QVERIFY(l != list && l.size() == list.size()/2 && l == copy); - l += copy; - QVERIFY(l == list); - list = copy; - } - { - QList copy = list; - list << 8; - QVERIFY(list.indexOf(8) == 1); - QVERIFY(list.indexOf(8, list.indexOf(8)+1) == 6); - int a = list.indexOf(8); - QVERIFY(list.count(8) == 2); - int r = list.removeAll(8); - QVERIFY(r == 2); - list.insert(a, 8); - QVERIFY(list == copy); - } - { - QList list; - list << "one" << "two" << "three" << "four" << "five" << "six"; - while (!list.isEmpty()) - list.removeAll(list.first()); - } - { - QList list; - list << "one" << "two" << "one" << "two"; - QVERIFY(!list.removeOne("three")); - QVERIFY(list.removeOne("two")); - QCOMPARE(list, QList() << "one" << "one" << "two");; - QVERIFY(list.removeOne("two")); - QCOMPARE(list, QList() << "one" << "one"); - QVERIFY(!list.removeOne("two")); - QCOMPARE(list, QList() << "one" << "one"); - QVERIFY(list.removeOne("one")); - QCOMPARE(list, QList() << "one"); - QVERIFY(list.removeOne("one")); - QVERIFY(list.isEmpty()); - QVERIFY(!list.removeOne("one")); - QVERIFY(list.isEmpty()); - } - { - QList copy = list; - list << 8; - QVERIFY(list.lastIndexOf(8) == 6); - QVERIFY(list.lastIndexOf(8, list.lastIndexOf(8)-1) == 1); - list = copy; - } - { - QList copy = list; - list.insert(3, 999); - QVERIFY(list[3] == 999); - list.replace(3, 222); - QVERIFY(list[3] == 222); - QVERIFY(list.contains(222) && ! list.contains(999)); - list.removeAt(3); - list = copy; - QVERIFY(list == copy); - } - { - list.clear(); - QVERIFY(list.isEmpty()); - QVERIFY(list.begin() == list.end()); - QListIterator i(list); - QVERIFY(!i.hasNext() && !i.hasPrevious()); - } - { - QList l1; - QList l2; - l1 << 1 << 2 << 3; - l2 << 4 << 5 << 6; - QList l3 = l1 + l2; - l1 += l2; - QVERIFY(l3 == l1); - } - { - QList list; - QVERIFY(list.isEmpty()); - list.append(1); - QList list2; - list2 = list; - list2.clear(); - QVERIFY(list2.size() == 0); - QVERIFY(list.size() == 1); - } - { - QList list; - list.append(1); - list = list; - QVERIFY(list.size() == 1); - } - } - { - QList list; - list.append(0); - list.append((void*)42); - QCOMPARE(list.size(), 2); - QCOMPARE(list.at(0), (void*)0); - QCOMPARE(list.at(1), (void*)42); - } - - { - QVector vector(5); - vector[0] = "99"; - vector[4] ="100"; - QList list = vector.toList(); - - QVERIFY(list.size() == 5); - QVERIFY(list.at(0) == "99"); - QVERIFY(list.at(4) == "100"); - list[0] = "10"; - QVERIFY(list.at(0) == "10"); - QVERIFY(vector.at(0) == "99"); - - } - - { - QList list; - list.append("Hello"); - - QList::iterator it = list.begin(); - QVERIFY((*it)[0] == QChar('H')); - QVERIFY(it->constData()[0] == QChar('H')); - it->replace(QChar('H'), QChar('X')); - QVERIFY(list.first() == "Xello"); - - QList::const_iterator cit = list.constBegin(); - QVERIFY((*cit).toLower() == "xello"); - QVERIFY(cit->toUpper() == "XELLO"); - } - - { - QList list; - QVERIFY(list.value(0) == 0); - int i; - list.append(&i); - QVERIFY(list.value(0) == &i); - } - { - QList list; - QVERIFY(list.value(0) == 0); - int i; - list.append(&i); - QVERIFY(list.value(0) == &i); - } - { - QList list; - QVERIFY(list.value(0) == 0); - list.append(10); - QVERIFY(list.value(0) == 10); - } - { - QList list; - QCOMPARE(list.value(0).i1, 0); - QCOMPARE(list.value(0).i2, 0); - } - - { - QList list; - list << "alpha" << "beta"; - list += list; - QVERIFY(list.size() == 4); - QVERIFY(list.at(0) == "alpha"); - QVERIFY(list.at(1) == "beta"); - QVERIFY(list.at(2) == "alpha"); - QVERIFY(list.at(3) == "beta"); - } - - // test endcases for inserting into a qlist - { - QList list; - list << "foo" << "bar"; - QVERIFY(!list.isEmpty()); - - list.insert(-1, "lessthanzero"); - QCOMPARE(list.at(0), QString("lessthanzero")); - - list.insert(0, "atzero"); - QCOMPARE(list.at(0), QString("atzero")); - - int listCount = list.count(); - list.insert(listCount, "atcount"); - QCOMPARE(list.at(listCount), QString("atcount")); - - listCount = list.count(); - list.insert(listCount + 1, "beyondcount"); - QCOMPARE(list.at(listCount), QString("beyondcount")); - } - - { - QList list1; - list1 << 0 << 1 << 2 << 3; - list1.removeFirst(); - - list1.swap(0, 0); - QVERIFY(list1 == QList() << 1 << 2 << 3); - - list1.swap(1, 1); - QVERIFY(list1 == QList() << 1 << 2 << 3); - - list1.swap(2, 2); - QVERIFY(list1 == QList() << 1 << 2 << 3); - - list1.swap(0, 1); - QVERIFY(list1 == QList() << 2 << 1 << 3); - - list1.swap(0, 2); - QVERIFY(list1 == QList() << 3 << 1 << 2); - - list1.swap(1, 2); - QVERIFY(list1 == QList() << 3 << 2 << 1); - - list1.swap(1, 2); - QVERIFY(list1 == QList() << 3 << 1 << 2); - - QList list2; - list2 << "1" << "2" << "3"; - - list2.swap(0, 0); - QVERIFY(list2 == QList() << "1" << "2" << "3"); - - list2.swap(1, 1); - QVERIFY(list2 == QList() << "1" << "2" << "3"); - - list2.swap(2, 2); - QVERIFY(list2 == QList() << "1" << "2" << "3"); - - list2.swap(0, 1); - QVERIFY(list2 == QList() << "2" << "1" << "3"); - - list2.swap(0, 2); - QVERIFY(list2 == QList() << "3" << "1" << "2"); - - list2.swap(1, 2); - QVERIFY(list2 == QList() << "3" << "2" << "1"); - - list2.swap(1, 2); - QVERIFY(list2 == QList() << "3" << "1" << "2"); - - QList list3; - list3 << 1.0 << 2.0 << 3.0; - - list3.swap(0, 0); - QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); - - list3.swap(1, 1); - QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); - - list3.swap(2, 2); - QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); - - list3.swap(0, 1); - QVERIFY(list3 == QList() << 2.0 << 1.0 << 3.0); - - list3.swap(0, 2); - QVERIFY(list3 == QList() << 3.0 << 1.0 << 2.0); - - list3.swap(1, 2); - QVERIFY(list3 == QList() << 3.0 << 2.0 << 1.0); - - list3.swap(1, 2); - QVERIFY(list3 == QList() << 3.0 << 1.0 << 2.0); - } - - // Check what happens when using references to own items. - // Ideally we should run valgrind on this. - { - int i; - - QList list1; - list1.append(reinterpret_cast(50)); - - for (i = 1; i < 100; ++i) { - list1.append(list1.at(i - 1)); - list1.prepend(list1.at(i)); - list1.insert(i, list1.at(i - 1)); - list1.insert(i, list1.at(i)); - list1.insert(i, list1.at(i + 1)); - list1.replace(i, list1.at(i - 1)); - list1.replace(i, list1.at(i)); - list1.replace(i, list1.at(i + 1)); - } - QCOMPARE(list1.size(), 496); - for (i = 0; i < list1.size(); ++i) { - QCOMPARE(list1.at(i), reinterpret_cast(50)); - } - - QList list2; - list2.append("50"); - - for (i = 1; i < 100; ++i) { - list2.append(list2.at(i - 1)); - list2.prepend(list2.at(i)); - list2.insert(i, list2.at(i - 1)); - list2.insert(i, list2.at(i)); - list2.insert(i, list2.at(i + 1)); - list2.replace(i, list2.at(i - 1)); - list2.replace(i, list2.at(i)); - list2.replace(i, list2.at(i + 1)); - } - QCOMPARE(list2.size(), 496); - for (i = 0; i < list2.size(); ++i) { - QCOMPARE(list2.at(i), QString::fromLatin1("50")); - } - - QList list3; - list3.append(50.0); - - for (i = 1; i < 100; ++i) { - list3.append(list3.at(i - 1)); - list3.prepend(list3.at(i)); - list3.insert(i, list3.at(i - 1)); - list3.insert(i, list3.at(i)); - list3.insert(i, list3.at(i + 1)); - list3.replace(i, list3.at(i - 1)); - list3.replace(i, list3.at(i)); - list3.replace(i, list3.at(i + 1)); - } - QCOMPARE(list3.size(), 496); - for (i = 0; i < list3.size(); ++i) { - QCOMPARE(list3.at(i), 50.0); - } - - QList list4; - list4.append(QTime(12, 34, 56)); - - for (i = 1; i < 100; ++i) { - list4.append(list4.at(i - 1)); - list4.prepend(list4.at(i)); - list4.insert(i, list4.at(i - 1)); - list4.insert(i, list4.at(i)); - list4.insert(i, list4.at(i + 1)); - list4.replace(i, list4.at(i - 1)); - list4.replace(i, list4.at(i)); - list4.replace(i, list4.at(i + 1)); - } - QCOMPARE(list4.size(), 496); - for (i = 0; i < list4.size(); ++i) { - QVERIFY(list4.at(i) == QTime(12, 34, 56)); - } - - } - { - QList a; - QCOMPARE(a.startsWith(1), false); - QCOMPARE(a.endsWith(1), false); - a.append(1); - QCOMPARE(a.startsWith(1), true); - QCOMPARE(a.startsWith(2), false); - QCOMPARE(a.endsWith(1), true); - QCOMPARE(a.endsWith(2), false); - a.append(2); - QCOMPARE(a.startsWith(1), true); - QCOMPARE(a.startsWith(2), false); - QCOMPARE(a.endsWith(1), false); - QCOMPARE(a.endsWith(2), true); - } -} - -void tst_Collections::linkedList() -{ - { - QLinkedList list; - QVERIFY(list.isEmpty()); - list.append(1); - list.push_back(2); - list += (3); - list << 4 << 5 << 6; - QVERIFY(!list.isEmpty()); - QVERIFY(list.size() == 6); - { - int sum = 0; - QLinkedListIterator i = list; - while (i.hasNext()) { - sum += i.next(); - } - QVERIFY(sum == 21); - } - { - int sum = 0; - QLinkedList::const_iterator i = list.begin(); - while (i != list.end()) - sum += *i++; - QVERIFY(sum == 21); - } - { - QMutableLinkedListIterator i = list; - while (i.hasNext()) - i.setValue(2*i.next()); - } - { - int sum = 0; - QLinkedListIterator i = list; - i.toBack(); - while (i.hasPrevious()) - sum += i.previous(); - QVERIFY(sum == 2*21); - } - { - QMutableLinkedListIterator i = list; - i.toBack(); - while (i.hasPrevious()) - i.setValue(2*i.previous()); - } - { - int sum = 0; - QLinkedListIterator i = list; - i.toBack(); - while (i.hasPrevious()) - sum += i.previous(); - QVERIFY(sum == 2*2*21); - } - { - QMutableLinkedListIterator i = list; - while (i.hasNext()) { - int a = i.next(); - i.insert(a); - } - } - { - int sum = 0; - QLinkedList::iterator i = list.begin(); - while (i != list.end()) - sum += *i++; - QVERIFY(sum == 2*2*2*21); - } - { - int duplicates = 0; - QLinkedListIterator i = list; - while (i.hasNext()) { - int a = i.next(); - if (i.hasNext() && a == i.peekNext()) - duplicates++; - } - QVERIFY(duplicates == 6); - } - { - int duplicates = 0; - QLinkedListIterator i = list; - i.toBack(); - while (i.hasPrevious()) { - int a = i.previous(); - if (i.hasPrevious() && a == i.peekPrevious()) - duplicates++; - } - QVERIFY(duplicates == 6); - } - { - QMutableLinkedListIterator i = list; - while (i.hasNext()) { - int a = i.next(); - if (i.hasNext() && - i.peekNext() == a) - i.remove(); - } - } - { - int duplicates = 0; - QMutableLinkedListIterator i = list; - i.toBack(); - while (i.hasPrevious()) { - int a = i.previous(); - if (i.hasPrevious() && a == i.peekPrevious()) - duplicates++; - } - QVERIFY(duplicates == 0); - } - { - QVERIFY(list.size() == 6); - QMutableLinkedListIterator i = list; - while (i.hasNext()) { - int a = i.peekNext(); - i.insert(42); - QVERIFY(i.peekPrevious() == 42 && i.peekNext() == a); - i.next(); - } - QVERIFY(list.size() == 12); - i.toFront(); - while (i.findNext(42)) - i.remove(); - } - { - QLinkedList l; - l << 4 << 8 << 12 << 16 << 20 << 24; - QVERIFY(l == list); - QLinkedList copy = list; - list += list; - QVERIFY(l != list && l.size() == list.size()/2 && l == copy); - l += copy; - QVERIFY(l == list); - list = copy; - } - { - QLinkedList copy = list; - list.prepend(999); - list.append(999); - QVERIFY(list.contains(999)); - QVERIFY(list.count(999) == 2); - list.removeAll(999); - QVERIFY(list == copy); - } - { - QLinkedList list; - list << "one" << "two" << "three" << "four" << "five" << "six"; - while (!list.isEmpty()) - list.removeAll(list.first()); - } - { - QLinkedList list; - list << "one" << "two" << "one" << "two"; - QVERIFY(!list.removeOne("three")); - QVERIFY(list.removeOne("two")); - QCOMPARE(list, QLinkedList() << "one" << "one" << "two");; - QVERIFY(list.removeOne("two")); - QCOMPARE(list, QLinkedList() << "one" << "one"); - QVERIFY(!list.removeOne("two")); - QCOMPARE(list, QLinkedList() << "one" << "one"); - QVERIFY(list.removeOne("one")); - QCOMPARE(list, QLinkedList() << "one"); - QVERIFY(list.removeOne("one")); - QVERIFY(list.isEmpty()); - QVERIFY(!list.removeOne("one")); - QVERIFY(list.isEmpty()); - } - { - list.clear(); - QVERIFY(list.isEmpty()); - QVERIFY(list.begin() == list.end()); - QLinkedListIterator i(list); - QVERIFY(!i.hasNext() && !i.hasPrevious()); - } - } - - { - QLinkedList list; - list.append("Hello"); - - QLinkedList::iterator it = list.begin(); - QVERIFY((*it)[0] == QChar('H')); - QVERIFY(it->constData()[0] == QChar('H')); - it->replace(QChar('H'), QChar('X')); - QVERIFY(list.first() == "Xello"); - - QLinkedList::const_iterator cit = list.constBegin(); - QVERIFY((*cit).toLower() == "xello"); - QVERIFY(cit->toUpper() == "XELLO"); - } - - { - QLinkedList list; - list << "alpha" << "beta"; - list += list; - QVERIFY(list.size() == 4); - QVERIFY(*list.begin() == "alpha"); - QVERIFY(*(list.begin() + 1) == "beta"); - QVERIFY(*(list.begin() + 2) == "alpha"); - QVERIFY(*(list.begin() + 3) == "beta"); - } - - { - QLinkedList a; - QCOMPARE(a.startsWith(1), false); - QCOMPARE(a.endsWith(1), false); - a.append(1); - QCOMPARE(a.startsWith(1), true); - QCOMPARE(a.startsWith(2), false); - QCOMPARE(a.endsWith(1), true); - QCOMPARE(a.endsWith(2), false); - a.append(2); - QCOMPARE(a.startsWith(1), true); - QCOMPARE(a.startsWith(2), false); - QCOMPARE(a.endsWith(1), false); - QCOMPARE(a.endsWith(2), true); - } -}; - - -void tst_Collections::vector() -{ - QVector v1; - v1 << 1 << 2 << 3; - QVector v2; - v2 << 4 << 5; - QVector v3; - v3 << 1 << 2 << 3 << 4 << 5; - QVERIFY(v1 + v2 == v3); - - QVector emptyVector; - QCOMPARE(emptyVector.size(), 0); -#if 0 - // this should trigger an assert - emptyVector.remove(3, -3); - QCOMPARE(emptyVector.size(), 0); -#endif - emptyVector.remove(0, 0); - QCOMPARE(emptyVector.size(), 0); - - QVector v4; - v4 << 1 << 2 << 3; - QCOMPARE(v4.size(), 3); - v4.remove(1, 0); - QCOMPARE(v4.size(), 3); - - QVector v; - v.append(2); - QVERIFY(*v.begin() == 2); - v.prepend(1); - - v << 3 << 4 << 5 << 6; -#if !defined(QT_NO_STL) - QVERIFY(std::binary_search(v.begin(), v.end(), 2) == true); - QVERIFY(std::binary_search(v.begin(), v.end(), 9) == false); -#endif - QVERIFY(qBinaryFind(v.begin(), v.end(), 2) == v.begin() + 1); - QVERIFY(qLowerBound(v.begin(), v.end(), 2) == v.begin() + 1); - QVERIFY(qUpperBound(v.begin(), v.end(), 2) == v.begin() + 2); - QVERIFY(qBinaryFind(v.begin(), v.end(), 9) == v.end()); - QVERIFY(qLowerBound(v.begin(), v.end(), 9) == v.end()); - QVERIFY(qUpperBound(v.begin(), v.end(), 9) == v.end()); - - v.clear(); - v << 1 << 2 << 3; - v.insert(v.begin(), 0); - v.insert(v.end(), 4); - v.insert(v.begin()+2, 9); - - QVector result; - result << 0 << 1 << 9 << 2 << 3 << 4; - - QVERIFY( v == result ); - - v.clear(); - v << 1 << 2 << 3; - v.insert(0, 0); - v.insert(4, 4); - v.insert(2, 9); - - QVERIFY( v == result ); - - QVector vec; - vec << "foo" << "bar"; - vec.reserve( 512 ); - QVERIFY(vec[0] == "foo"); - QVERIFY(vec[1] == "bar"); - - int initialLargeStaticCount = LargeStatic::count; - { - QVector vector; - vector.append(LargeStatic()); - vector.resize(0); - } - QCOMPARE(LargeStatic::count, initialLargeStaticCount); - - { - QVector vector; - vector << "alpha" << "beta"; - vector += vector; - QVERIFY(vector.size() == 4); - QVERIFY(vector.at(0) == "alpha"); - QVERIFY(vector.at(1) == "beta"); - QVERIFY(vector.at(2) == "alpha"); - QVERIFY(vector.at(3) == "beta"); - } - - int originalLargeStaticCount = LargeStatic::count; - { - QVector vector(5); - } - QVERIFY(LargeStatic::count == originalLargeStaticCount); - { - QVector vector(5); - QList list = vector.toList(); - } - QVERIFY(LargeStatic::count == originalLargeStaticCount); - { - QVector vector; - LargeStatic *dummy = 0; - for (int i = 0; i < 10000; ++i) { - delete dummy; - dummy = new LargeStatic; - vector.append(LargeStatic()); - } - delete dummy; - } - QVERIFY(LargeStatic::count == originalLargeStaticCount); - - int originalMovableCount = Movable::count; - { - QVector vector(5); - } - QVERIFY(Movable::count == originalMovableCount); - { - QVector vector(5); - QList list = vector.toList(); - } - QVERIFY(Movable::count == originalMovableCount); - { - QVector vector; - Movable *dummy = 0; - for (int i = 0; i < 10000; ++i) { - delete dummy; - dummy = new Movable; - vector.append(Movable()); - } - delete dummy; - } - QVERIFY(Movable::count == originalMovableCount); - - // Check what happens when using references to own items. - // Ideally we should run valgrind on this. - { - int i; - - QVector vect1; - vect1.append(reinterpret_cast(50)); - - for (i = 1; i < 100; ++i) { - vect1.append(vect1.at(i - 1)); - vect1.prepend(vect1.at(i)); - vect1.insert(i, vect1.at(i - 1)); - vect1.insert(i, vect1.at(i)); - vect1.insert(i, vect1.at(i + 1)); - vect1.replace(i, vect1.at(i - 1)); - vect1.replace(i, vect1.at(i)); - vect1.replace(i, vect1.at(i + 1)); - } - QCOMPARE(vect1.size(), 496); - for (i = 0; i < vect1.size(); ++i) { - QCOMPARE(vect1.at(i), reinterpret_cast(50)); - } - - QVector vect2; - vect2.append("50"); - - for (i = 1; i < 100; ++i) { - vect2.append(vect2.at(i - 1)); - vect2.prepend(vect2.at(i)); - vect2.insert(i, vect2.at(i - 1)); - vect2.insert(i, vect2.at(i)); - vect2.insert(i, vect2.at(i + 1)); - vect2.replace(i, vect2.at(i - 1)); - vect2.replace(i, vect2.at(i)); - vect2.replace(i, vect2.at(i + 1)); - } - QCOMPARE(vect2.size(), 496); - for (i = 0; i < vect2.size(); ++i) { - QCOMPARE(vect2.at(i), QString::fromLatin1("50")); - } - - QVector vect3; - vect3.append(50.0); - - for (i = 1; i < 100; ++i) { - vect3.append(vect3.at(i - 1)); - vect3.prepend(vect3.at(i)); - vect3.insert(i, vect3.at(i - 1)); - vect3.insert(i, vect3.at(i)); - vect3.insert(i, vect3.at(i + 1)); - vect3.replace(i, vect3.at(i - 1)); - vect3.replace(i, vect3.at(i)); - vect3.replace(i, vect3.at(i + 1)); - } - QCOMPARE(vect3.size(), 496); - for (i = 0; i < vect3.size(); ++i) { - QCOMPARE(vect3.at(i), 50.0); - } - - QVector vect4; - vect4.append(QTime(12, 34, 56)); - - for (i = 1; i < 100; ++i) { - vect4.append(vect4.at(i - 1)); - vect4.prepend(vect4.at(i)); - vect4.insert(i, vect4.at(i - 1)); - vect4.insert(i, vect4.at(i)); - vect4.insert(i, vect4.at(i + 1)); - vect4.replace(i, vect4.at(i - 1)); - vect4.replace(i, vect4.at(i)); - vect4.replace(i, vect4.at(i + 1)); - } - QCOMPARE(vect4.size(), 496); - for (i = 0; i < vect4.size(); ++i) { - QVERIFY(vect4.at(i) == QTime(12, 34, 56)); - } - } - - // this used to trigger an uninitialized read in valgrind - QVector foo; - foo.resize(144); - - { - QVector a; - QCOMPARE(a.startsWith(1), false); - QCOMPARE(a.endsWith(1), false); - a.append(1); - QCOMPARE(a.startsWith(1), true); - QCOMPARE(a.startsWith(2), false); - QCOMPARE(a.endsWith(1), true); - QCOMPARE(a.endsWith(2), false); - a.append(2); - QCOMPARE(a.startsWith(1), true); - QCOMPARE(a.startsWith(2), false); - QCOMPARE(a.endsWith(1), false); - QCOMPARE(a.endsWith(2), true); - } -} - -void tst_Collections::byteArray() -{ - QByteArray hello = "hello"; - QByteArray ello = "ello"; - QByteArray World = "World"; - QByteArray Wor = "Wor"; - QByteArray helloWorld = "helloWorld"; - QVERIFY(hello + World == helloWorld); - QVERIFY(hello + "World" == helloWorld); - QVERIFY("hello" + World == helloWorld); - - - QByteArray l; - QVERIFY('h' + ello == hello); - QVERIFY(Wor + 'l' + 'd' == "World"); - QVERIFY(hello + World == "helloWorld"); - QVERIFY(hello + "World" == "helloWorld"); - QVERIFY("hello" + World == "helloWorld"); - QVERIFY('h' + ello == "hello"); - QVERIFY(Wor + 'l' + 'd' == "World"); - QVERIFY("helloWorld" == hello + World); - QVERIFY("helloWorld" == hello + "World"); - QVERIFY("helloWorld" == "hello" + World); - QVERIFY("hello" == 'h' + ello); - QVERIFY("World" == Wor + 'l' + 'd'); - - QVERIFY(hello.contains('e')); - QVERIFY (true == hello.contains('e')); - QVERIFY (hello.contains('e') != false); - - QVERIFY(hello.indexOf('e') == 1); - QVERIFY(hello.indexOf('e', -10) == 1); - QVERIFY(hello.indexOf('l') == 2); - QVERIFY(hello.indexOf('l',2) == 2); - QVERIFY(hello.indexOf('l',3) == 3); - - QByteArray large = "000 100 200 300 400 500 600 700 800 900"; - - QVERIFY(large.indexOf("700") == 28); - QVERIFY(large.indexOf("700", 28) == 28); - QVERIFY(large.indexOf("700", 29) == -1); - QVERIFY(large.lastIndexOf("700") == 28); - QVERIFY(large.lastIndexOf("700", 28) == 28); - QVERIFY(large.lastIndexOf("700", 27) == -1); - - QVERIFY(large.contains("200")); - QVERIFY(!large.contains("201")); - QVERIFY(large.contains('3')); - QVERIFY(!large.contains('a')); - - QVERIFY(large.count("00") == 11); - QVERIFY(large.count('3') == 1); - QVERIFY(large.count('0') == 21); - QVERIFY(large.count("0") == 21); - QVERIFY(large.count("200") == 1); - QVERIFY(large.count("201") == 0); - - QVERIFY(hello.left(0) == ""); - QVERIFY(!hello.left(0).isNull()); - QVERIFY(hello.left(1) == "h"); - QVERIFY(hello.left(2) == "he"); - QVERIFY(hello.left(200) == "hello"); - QVERIFY(hello.left(hello.size()) == hello); - QVERIFY(hello.left(hello.size()+1) == hello); - - QVERIFY(hello.right(0) == ""); - QVERIFY(!hello.right(0).isNull()); - QVERIFY(hello.right(1) == "o"); - QVERIFY(hello.right(2) == "lo"); - QVERIFY(hello.right(200) == "hello"); - QVERIFY(hello.right(hello.size()) == hello); - QVERIFY(hello.right(hello.size()+1) == hello); - - QVERIFY(!hello.mid(0, 0).isNull()); - QVERIFY(hello.mid(0, 1) == "h"); - QVERIFY(hello.mid(0, 2) == "he"); - QVERIFY(hello.mid(0, 200) == "hello"); - QVERIFY(hello.mid(0) == "hello"); - QVERIFY(hello.mid(0, hello.size()) == hello); - QVERIFY(hello.mid(0, hello.size()+1) == hello); - - QVERIFY(hello.mid(hello.size()-0) == ""); - - QVERIFY(hello.mid(hello.size()-0).isNull()); // weird but valid 3.x semantics - QVERIFY(hello.mid(hello.size()-1) == "o"); - QVERIFY(hello.mid(hello.size()-2) == "lo"); - QVERIFY(hello.mid(hello.size()-200) == "hello"); - - QByteArray null; - QByteArray nonNull = ""; - QVERIFY(null.left(10).isNull()); - QVERIFY(null.mid(0).isNull()); - -#if 0 - QVERIFY(null == QByteArray::null); - QVERIFY(QByteArray::null == null); - QVERIFY(nonNull != QByteArray::null); - QVERIFY(QByteArray::null != nonNull); - QVERIFY(null == nonNull); - QVERIFY(QByteArray::null == QByteArray::null); -#endif - - QByteArray str = "Hello"; - QByteArray cstr(str.data(), str.size()); - QVERIFY(str == "Hello"); - QVERIFY(cstr == "Hello"); - cstr.clear(); - QVERIFY(str == "Hello"); - QVERIFY(cstr.isEmpty()); - - { - QByteArray ba1("Foo"); - ba1.prepend(ba1); - QCOMPARE(ba1, QByteArray("FooFoo")); - ba1.append(ba1); - QCOMPARE(ba1, QByteArray("FooFooFooFoo")); - ba1.insert(2, ba1); - QCOMPARE(ba1, QByteArray("FoFooFooFooFoooFooFooFoo")); - ba1.replace(3, 3, ba1); - QCOMPARE(ba1, QByteArray("FoFFoFooFooFooFoooFooFooFooooFooFoooFooFooFoo")); - ba1 = "FooFoo"; - ba1.replace(char('F'), ba1); - QCOMPARE(ba1, QByteArray("FooFooooFooFoooo")); - ba1 = "FooFoo"; - ba1.replace(char('o'), ba1); - QCOMPARE(ba1, QByteArray("FFooFooFooFooFFooFooFooFoo")); - - ba1.replace(ba1, "xxx"); - QCOMPARE(ba1, QByteArray("xxx")); - ba1.replace(ba1, QByteArray("yyy")); - QCOMPARE(ba1, QByteArray("yyy")); - ba1 += ba1; - QCOMPARE(ba1, QByteArray("yyyyyy")); - - ba1.remove(1, -1); // do nothing - QCOMPARE(ba1, QByteArray("yyyyyy")); - - ba1.replace(0, -1, "ZZZ"); - QCOMPARE(ba1, QByteArray("ZZZyyyyyy")); - } -}; - -void tst_Collections::stack() -{ - QStack stack; - stack.push(1); - stack.push(2); - stack.push(3); - QVectorIterator i = stack; - i.toBack(); - int sum = 0; - while (i.hasPrevious()) - sum += i.previous(); - QVERIFY(sum == 6); - - sum = 0; - for (QStack::iterator i = stack.begin(); i != stack.end(); ++i) - sum += *i; - QVERIFY(sum == 6); - - while (!stack.isEmpty()) - sum -= stack.pop(); - QVERIFY(sum == 0); -} - -void tst_Collections::hash() -{ - const char *hello = "hello"; - const char *world = "world"; - const char *allo = "allo"; - const char *monde = "monde"; - - { - typedef QHash Hash; - Hash hash; - QString key; - for (int i = 0; i < 10; ++i) { - key[0] = i + '0'; - for (int j = 0; j < 10; ++j) { - key[1] = j + '0'; - hash.insert(key, "V" + key); - } - } - - for (int i = 0; i < 10; ++i) { - key[0] = i + '0'; - for (int j = 0; j < 10; ++j) { - key[1] = j + '0'; - hash.remove(key); - } - } - } - - { - typedef QHash Hash; - Hash hash; - hash.insert(1, hello); - hash.insert(2, world); - - QVERIFY(hash.size() == 2); - QVERIFY(!hash.isEmpty()); - - { - Hash hash2 = hash; - hash2 = hash; - hash = hash2; - hash2 = hash2; - hash = hash; - hash2.clear(); - hash2 = hash2; - QVERIFY(hash2.size() == 0); - QVERIFY(hash2.isEmpty()); - } - QVERIFY(hash.size() == 2); - - { - Hash hash2 = hash; - hash2[1] = allo; - hash2[2] = monde; - - QVERIFY(hash2[1] == allo); - QVERIFY(hash2[2] == monde); - QVERIFY(hash[1] == hello); - QVERIFY(hash[2] == world); - - hash2[1] = hash[1]; - hash2[2] = hash[2]; - - QVERIFY(hash2[1] == hello); - QVERIFY(hash2[2] == world); - - hash[1] = hash[1]; - QVERIFY(hash[1] == hello); - } - - { - Hash hash2 = hash; - hash2.detach(); - hash2.remove(1); - QVERIFY(hash2.size() == 1); - hash2.remove(1); - QVERIFY(hash2.size() == 1); - hash2.remove(0); - QVERIFY(hash2.size() == 1); - hash2.remove(2); - QVERIFY(hash2.size() == 0); - QVERIFY(hash.size() == 2); - } - - hash.detach(); - - { - Hash::iterator it1 = hash.find(1); - QVERIFY(it1 != hash.end()); - - Hash::iterator it2 = hash.find(0); - QVERIFY(it2 != hash.begin()); - QVERIFY(it2 == hash.end()); - - *it1 = monde; - QVERIFY(*it1 == monde); - QVERIFY(hash[1] == monde); - - *it1 = hello; - QVERIFY(*it1 == hello); - QVERIFY(hash[1] == hello); - - hash[1] = monde; - QVERIFY(it1.key() == 1); - QVERIFY(it1.value() == monde); - QVERIFY(*it1 == monde); - QVERIFY(hash[1] == monde); - - hash[1] = hello; - QVERIFY(*it1 == hello); - QVERIFY(hash[1] == hello); - } - - { - const Hash hash2 = hash; - - Hash::const_iterator it1 = hash2.find(1); - QVERIFY(it1 != hash2.end()); - QVERIFY(it1.key() == 1); - QVERIFY(it1.value() == hello); - QVERIFY(*it1 == hello); - - Hash::const_iterator it2 = hash2.find(2); - QVERIFY(it1 != it2); - QVERIFY(it1 != hash2.end()); - QVERIFY(it2 != hash2.end()); - - int count = 0; - it1 = hash2.begin(); - while (it1 != hash2.end()) { - count++; - ++it1; - } - QVERIFY(count == 2); - - count = 0; - it1 = hash.begin(); - while (it1 != hash.end()) { - count++; - ++it1; - } - QVERIFY(count == 2); - } - - { - QVERIFY(hash.contains(1)); - QVERIFY(hash.contains(2)); - QVERIFY(!hash.contains(0)); - QVERIFY(!hash.contains(3)); - } - - { - QVERIFY(hash.value(1) == hello); - QVERIFY(hash.value(2) == world); - QVERIFY(hash.value(3) == 0); - QVERIFY(hash.value(1, allo) == hello); - QVERIFY(hash.value(2, allo) == world); - QVERIFY(hash.value(3, allo) == allo); - QVERIFY(hash.value(0, monde) == monde); - } - - { - QHash hash; - for (int i = 0; i < 10; i++) - hash.insert(i, LargeStatic()); - QVERIFY(LargeStatic::count == 10); - hash.remove(7); - QVERIFY(LargeStatic::count == 9); - - } - QVERIFY(LargeStatic::count == 0); - { - QHash hash; - QVERIFY(((const QHash*) &hash)->operator[](7) == 0); - } - - { - /* - This test relies on a certain implementation of - QHash. If you change the way QHash works internally, - change this test as well. - */ - QHash hash; - for (int i = 0; i < 1000; ++i) - hash.insert(i, i); - QVERIFY(hash.capacity() == 1031); - hash.squeeze(); - QVERIFY(hash.capacity() == 521); - - hash.insert(12345, 12345); - QVERIFY(hash.capacity() == 1031); - - for (int j = 0; j < 900; ++j) - hash.remove(j); - QVERIFY(hash.capacity() == 257); - hash.squeeze(); - QVERIFY(hash.capacity() == 67); - hash.reserve(0); - } - } - - { - QHash hash; - hash.insert(0, "Hello"); - - QHash::iterator it = hash.begin(); - QVERIFY((*it)[0] == QChar('H')); - QVERIFY(it->constData()[0] == QChar('H')); - it->replace(QChar('H'), QChar('X')); - QVERIFY(*hash.begin() == "Xello"); - - QHash::const_iterator cit = hash.constBegin(); - QVERIFY((*cit).toLower() == "xello"); - QVERIFY(cit->toUpper() == "XELLO"); - } - - { - QHash hash1, hash2; - hash1.insertMulti(1, "Alpha"); - hash1.insertMulti(1, "Gamma"); - hash2.insertMulti(1, "Beta"); - hash2.insertMulti(1, "Gamma"); - hash2.insertMulti(1, "Gamma"); - - hash1.unite(hash2); - QCOMPARE(hash1.size(), 5); - QCOMPARE(hash1.values(), - (QList() << "Gamma" << "Gamma" << "Beta" << "Gamma" << "Alpha")); - - hash2 = hash1; - hash2.unite(hash2); - QCOMPARE(hash2.size(), 10); - QCOMPARE(hash2.values(), hash1.values() + hash1.values()); - } - -#if 0 - { - QMultiHash hash1; - hash1.insert("1", 2); - hash1.insert("1", 1); - hash1.insert("a", 3); - hash1.insert("a", 2); - hash1.insert("a", 1); - hash1.insert("b", 2); - hash1.insert("b", 1); - - // hash1: [ "1" -> 1, "1" -> 2, "a" -> 1, "a" -> 2, "a" -> 3, "b" -> 1, "b" -> 2 ] - - QHashIterator i1(hash1); - i1.toBack(); - - bool found; - - found = i1.findPreviousKey("1"); - QVERIFY(found && i1.value() == 2); - - found = i1.findPreviousKey("1"); - QVERIFY(found && i1.value() == 1); - - found = i1.findPreviousKey("1"); - QVERIFY(!found); - - i1.toFront(); - found = i1.findNextKey("1"); - QVERIFY(found && i1.value() == 1); - - found = i1.findNextKey("1"); - QVERIFY(found && i1.value() == 2); - - found = i1.findNextKey("1"); - QVERIFY(!found); - - i1.toBack(); - found = i1.findPreviousKey("b"); - QVERIFY(found && i1.value() == 2); - - found = i1.findPreviousKey("b"); - QVERIFY(found && i1.value() == 1); - - found = i1.findPreviousKey("b"); - QVERIFY(!found); - - i1.toFront(); - found = i1.findNextKey("b"); - QVERIFY(found && i1.value() == 1); - - found = i1.findNextKey("b"); - QVERIFY(found && i1.value() == 2); - - found = i1.findNextKey("b"); - QVERIFY(!found); - } -#endif -} - -void tst_Collections::map() -{ - const char *hello = "hello"; - const char *world = "world"; - const char *allo = "allo"; - const char *monde = "monde"; - - { - typedef QMap Map; - Map map; - map.insert(1, hello); - map.insert(2, world); - - QVERIFY(*map.begin() == hello); - - QVERIFY(map.size() == 2); - QVERIFY(!map.isEmpty()); - - { - Map map2 = map; - map2 = map; - map = map2; - map2 = map2; - map = map; - map2.clear(); - map2 = map2; - QVERIFY(map2.size() == 0); - QVERIFY(map2.isEmpty()); - } - QVERIFY(map.size() == 2); - - { - Map map2 = map; - map2[1] = allo; - map2[2] = monde; - - QVERIFY(map2[1] == allo); - QVERIFY(map2[2] == monde); - QVERIFY(map[1] == hello); - QVERIFY(map[2] == world); - - map2[1] = map[1]; - map2[2] = map[2]; - - QVERIFY(map2[1] == hello); - QVERIFY(map2[2] == world); - - map[1] = map[1]; - QVERIFY(map[1] == hello); - } - - { - Map map2 = map; - map2.detach(); - map2.remove(1); - QVERIFY(map2.size() == 1); - map2.remove(1); - QVERIFY(map2.size() == 1); - map2.remove(0); - QVERIFY(map2.size() == 1); - map2.remove(2); - QVERIFY(map2.size() == 0); - QVERIFY(map.size() == 2); - } - - map.detach(); - - { - Map::iterator it1 = map.find(1); - QVERIFY(it1 == map.begin()); - QVERIFY(it1 != map.end()); - - Map::iterator it2 = map.find(0); - QVERIFY(it2 != map.begin()); - QVERIFY(it2 == map.end()); - - *it1 = monde; - QVERIFY(*it1 == monde); - QVERIFY(map[1] == monde); - - *it1 = hello; - QVERIFY(*it1 == hello); - QVERIFY(map[1] == hello); - - map[1] = monde; - QVERIFY(it1.key() == 1); - QVERIFY(it1.value() == monde); - QVERIFY(*it1 == monde); - QVERIFY(map[1] == monde); - - map[1] = hello; - QVERIFY(*it1 == hello); - QVERIFY(map[1] == hello); - - *++it1 = allo; - QVERIFY(*it1 == allo); - QVERIFY(map[2] == allo); - *it1 = world; - - ++it1; - QVERIFY(it1 == map.end()); - - int count = 0; - it1 = map.begin(); - while (it1 != map.end()) { - count++; - ++it1; - } - QVERIFY(count == 2); - } - - { - const Map map2 = map; - - Map::const_iterator it1 = map2.find(1); - QVERIFY(it1 != map2.end()); - QVERIFY(it1.key() == 1); - QVERIFY(it1.value() == hello); - QVERIFY(*it1 == hello); - ++it1; - - Map::const_iterator it2 = map2.find(2); - QVERIFY(it1 == it2); - ++it1; - QVERIFY(it1 == map2.end()); - QVERIFY(it2 != map2.end()); - QVERIFY(it1 != it2); - - int count = 0; - it1 = map2.begin(); - while (it1 != map2.end()) { - count++; - ++it1; - } - QVERIFY(count == 2); - - count = 0; - it1 = map.begin(); - while (it1 != map.end()) { - count++; - ++it1; - } - QVERIFY(count == 2); - } - - { - QVERIFY(map.contains(1)); - QVERIFY(map.contains(2)); - QVERIFY(!map.contains(0)); - QVERIFY(!map.contains(3)); - } - - { - QVERIFY(map.value(1) == hello); - QVERIFY(map.value(2) == world); - QVERIFY(map.value(3) == 0); - QVERIFY(map.value(1, allo) == hello); - QVERIFY(map.value(2, allo) == world); - QVERIFY(map.value(3, allo) == allo); - QVERIFY(map.value(0, monde) == monde); - } - int originalLargeStaticCount = LargeStatic::count; - { - QMap map; - for (int i = 0; i < 10; i++) - map.insert(i, LargeStatic()); - QVERIFY(LargeStatic::count == (originalLargeStaticCount + 10)); - map.remove(7); - QVERIFY(LargeStatic::count == (originalLargeStaticCount + 9)); - - } - QVERIFY(LargeStatic::count == originalLargeStaticCount); - { - QMap map; - QVERIFY(((const QMap*) &map)->operator[](7) == 0); - } - - { - QMap map; - map[0] = 1; - map[1] = 2; - map[2] = 4; - map[3] = 8; - int sum = 0; - int sumkey = 0; - QMapIterator i = map; - while (i.hasNext()) { - sum += i.next().value(); - sumkey += i.key(); - } - QVERIFY(sum == 15); - QVERIFY(sumkey == 6); - } - { - QMap map; - map[0] = 1; - map[1] = 2; - map[2] = 4; - map[3] = 8; - int sum = 0; - QMutableMapIterator i = map; - while(i.hasNext()) - if (i.next().key() == 2) - i.remove(); - i.toFront(); - while(i.hasNext()) { - sum += i.next().value(); - i.setValue(10); - i.value() += 22; - QVERIFY(i.value() == 32); - } - QVERIFY(sum == 11); - } - { - QMap map; - map[0] = 1; - QMutableMapIterator i(map); - i.toBack(); - while (i.hasPrevious()) { - i.previous(); - QCOMPARE(i.key(), 0); - QCOMPARE(i.value(), 1); - } - } - } - - { - QMultiMap map1; - map1.insert("1", 2); - map1.insert("1", 1); - map1.insert("a", 3); - map1.insert("a", 2); - map1.insert("a", 1); - map1.insert("b", 2); - map1.insert("b", 1); - - // map1: [ "1" -> 1, "1" -> 2, "a" -> 1, "a" -> 2, "a" -> 3, "b" -> 1, "b" -> 2 ] - -#if 0 - QMapIterator i1(map1); - i1.toBack(); - - bool found; - found = i1.findPreviousKey("1"); - QVERIFY(found && i1.value() == 2); - - found = i1.findPreviousKey("1"); - QVERIFY(found && i1.value() == 1); - - found = i1.findPreviousKey("1"); - QVERIFY(!found); - - i1.toFront(); - found = i1.findNextKey("1"); - QVERIFY(found && i1.value() == 1); - - found = i1.findNextKey("1"); - QVERIFY(found && i1.value() == 2); - - found = i1.findNextKey("1"); - QVERIFY(!found); - - i1.toBack(); - found = i1.findPreviousKey("b"); - QVERIFY(found && i1.value() == 2); - - found = i1.findPreviousKey("b"); - QVERIFY(found && i1.value() == 1); - - found = i1.findPreviousKey("b"); - QVERIFY(!found); - - i1.toFront(); - found = i1.findNextKey("b"); - QVERIFY(found && i1.value() == 1); - - found = i1.findNextKey("b"); - QVERIFY(found && i1.value() == 2); - - found = i1.findNextKey("b"); - QVERIFY(!found); -#endif - - QMultiMap::iterator j1, k1; - - j1 = map1.lowerBound("0"); k1 = map1.upperBound("0"); - QVERIFY(j1 == map1.begin() && k1 == j1); - j1 = map1.lowerBound("00"); k1 = map1.upperBound("00"); - QVERIFY(j1 == map1.find("1") && k1 == j1); - j1 = map1.lowerBound("1"); k1 = map1.upperBound("1"); - QVERIFY(j1 == map1.find("1") && --(--k1) == j1); - j1 = map1.lowerBound("11"); k1 = map1.upperBound("11"); - QVERIFY(j1 == map1.find("a") && k1 == j1); - j1 = map1.lowerBound("a"); k1 = map1.upperBound("a"); - QVERIFY(j1 == map1.find("a") && k1 == map1.find("b")); - QVERIFY(j1.value() == 1 && j1.value() == 1); - j1 = map1.lowerBound("aa"); k1 = map1.upperBound("aa"); - QVERIFY(j1 == map1.find("b") && k1 == j1); - QVERIFY(j1.value() == 1); - j1 = map1.lowerBound("b"); k1 = map1.upperBound("b"); - QVERIFY(j1 == map1.find("b") && k1 == map1.end()); - QVERIFY(j1.value() == 1); - j1 = map1.lowerBound("bb"); k1 = map1.upperBound("bb"); - QVERIFY(j1 == map1.end() && k1 == j1); - - const QMultiMap map2 = map1; - QMultiMap::const_iterator j2, k2; - - j2 = map2.lowerBound("0"); k2 = map2.upperBound("0"); - QVERIFY(j2 == map2.begin() && k2 == j2); - j2 = map2.lowerBound("00"); k2 = map2.upperBound("00"); - QVERIFY(j2 == map2.find("1") && k2 == j2); - j2 = map2.lowerBound("1"); k2 = map2.upperBound("1"); - QVERIFY(j2 == map2.find("1") && --(--k2) == j2); - j2 = map2.lowerBound("11"); k2 = map2.upperBound("11"); - QVERIFY(j2 == map2.find("a") && k2 == j2); - j2 = map2.lowerBound("a"); k2 = map2.upperBound("a"); - QVERIFY(j2 == map2.find("a") && k2 == map2.find("b")); - QVERIFY(j2.value() == 1 && j2.value() == 1); - j2 = map2.lowerBound("aa"); k2 = map2.upperBound("aa"); - QVERIFY(j2 == map2.find("b") && k2 == j2); - QVERIFY(j2.value() == 1); - j2 = map2.lowerBound("b"); k2 = map2.upperBound("b"); - QVERIFY(j2 == map2.find("b") && k2 == map2.end()); - QVERIFY(j2.value() == 1); - j2 = map2.lowerBound("bb"); k2 = map2.upperBound("bb"); - QVERIFY(j2 == map2.end() && k2 == j2); - } - - { - QMap map; - map.insert(0, "Hello"); - - QMap::iterator it = map.begin(); - QVERIFY((*it)[0] == QChar('H')); - QVERIFY(it->constData()[0] == QChar('H')); - it->replace(QChar('H'), QChar('X')); - QVERIFY(*map.begin() == "Xello"); - - QMap::const_iterator cit = map.constBegin(); - QVERIFY((*cit).toLower() == "xello"); - QVERIFY(cit->toUpper() == "XELLO"); - } - - { - QMap map1, map2; - map1.insertMulti(1, "Alpha"); - map1.insertMulti(1, "Gamma"); - map2.insertMulti(1, "Beta"); - map2.insertMulti(1, "Gamma"); - map2.insertMulti(1, "Gamma"); - - map1.unite(map2); - QCOMPARE(map1.size(), 5); - QCOMPARE(static_cast(map1.values()), - (QStringList() << "Gamma" << "Gamma" << "Beta" << "Gamma" << "Alpha")); - - map2 = map1; - map2.unite(map2); - QCOMPARE(map2.size(), 10); - QCOMPARE(map2.values(), map1.values() + map1.values()); - } -} - -void tst_Collections::qstring() -{ - QString hello = "hello"; - QString ello = "ello"; - QString World = "World"; - QString Wor = "Wor"; - QString helloWorld = "helloWorld"; - - QString s = hello + "World"; - QVERIFY(hello + World == helloWorld); - QVERIFY(hello + "World" == helloWorld); - QVERIFY("hello" + World == helloWorld); - - - QString l; - QVERIFY('h' + ello == hello); - QVERIFY(Wor + 'l' + 'd' == "World"); - QVERIFY(hello + World == "helloWorld"); - QVERIFY(hello + "World" == "helloWorld"); - QVERIFY("hello" + World == "helloWorld"); - QVERIFY('h' + ello == "hello"); - QVERIFY(Wor + 'l' + 'd' == "World"); - QVERIFY("helloWorld" == hello + World); - QVERIFY("helloWorld" == hello + "World"); - QVERIFY("helloWorld" == "hello" + World); - QVERIFY("hello" == 'h' + ello); - QVERIFY("World" == Wor + 'l' + 'd'); - - QVERIFY(hello.contains('e')); - QVERIFY (true == hello.contains('e')); - QVERIFY (hello.contains('e') != false); - - QVERIFY(hello.indexOf('e') == 1); - QVERIFY(hello.indexOf('e', -10) == 1); - QVERIFY(hello.indexOf('l') == 2); - QVERIFY(hello.indexOf('l',2) == 2); - QVERIFY(hello.indexOf('l',3) == 3); - - QString large = "000 100 200 300 400 500 600 700 800 900"; - - QVERIFY(large.indexOf("700") == 28); - QVERIFY(large.indexOf("700", 28) == 28); - QVERIFY(large.indexOf("700", 29) == -1); - QVERIFY(large.lastIndexOf("700") == 28); - QVERIFY(large.lastIndexOf("700", 28) == 28); - QVERIFY(large.lastIndexOf("700", 27) == -1); - - QVERIFY(large.contains("200")); - QVERIFY(!large.contains("201")); - QVERIFY(large.contains('3')); - QVERIFY(!large.contains('a')); - - QVERIFY(large.count("00") == 11); - QVERIFY(large.count('3') == 1); - QVERIFY(large.count('0') == 21); - QVERIFY(large.count("0") == 21); - QVERIFY(large.count("200") == 1); - QVERIFY(large.count("201") == 0); - - QVERIFY(hello.left(0) == ""); - QVERIFY(!hello.left(0).isNull()); - QVERIFY(hello.left(1) == "h"); - QVERIFY(hello.left(2) == "he"); - QVERIFY(hello.left(200) == "hello"); - QVERIFY(hello.left(hello.size()) == hello); - QVERIFY(hello.left(hello.size()+1) == hello); - - QVERIFY(hello.right(0) == ""); - QVERIFY(!hello.right(0).isNull()); - QVERIFY(hello.right(1) == "o"); - QVERIFY(hello.right(2) == "lo"); - QVERIFY(hello.right(200) == "hello"); - QVERIFY(hello.right(hello.size()) == hello); - QVERIFY(hello.right(hello.size()+1) == hello); - - QVERIFY(!hello.mid(0, 0).isNull()); - QVERIFY(hello.mid(0, 1) == "h"); - QVERIFY(hello.mid(0, 2) == "he"); - QVERIFY(hello.mid(0, 200) == "hello"); - QVERIFY(hello.mid(0) == "hello"); - QVERIFY(hello.mid(0, hello.size()) == hello); - QVERIFY(hello.mid(0, hello.size()+1) == hello); - - QVERIFY(hello.mid(hello.size()-0) == ""); - - QVERIFY(hello.mid(hello.size()-0).isNull()); - QVERIFY(hello.mid(hello.size()-1) == "o"); - QVERIFY(hello.mid(hello.size()-2) == "lo"); - QVERIFY(hello.mid(hello.size()-200) == "hello"); - - QString null; - QString nonNull = ""; - QVERIFY(null.left(10).isNull()); - QVERIFY(null.mid(0).isNull()); - - QVERIFY(null == QString::null); - QVERIFY(QString::null == null); - QVERIFY(nonNull != QString::null); - QVERIFY(QString::null != nonNull); - QVERIFY(null == nonNull); - QVERIFY(QString::null == QString::null); - - QString fill = "123"; - fill.fill('a'); - QVERIFY(fill == "aaa"); - - s.clear(); - s = hello; - s.append(World); - QVERIFY(s == helloWorld); - s.clear(); - s = World; - s.insert(0,hello); - QVERIFY(s == helloWorld); - s = "012345"; - s.insert(3, 'E'); - QVERIFY(s == "012E345"); - s.insert(3, "INSID"); - QVERIFY(s == "012INSIDE345"); - s = "short"; - s.insert(7, 'E'); - QVERIFY(s == "short E"); - s = "short"; - s.insert(7, "END"); - QVERIFY(s == "short END"); - - QVERIFY(QString::fromLatin1("hello") == "hello"); - - s = "first"; - QVERIFY(s.toLatin1() == "first"); - s = "second"; - QVERIFY(s.toLatin1() == "second"); - s.clear(); - QVERIFY(s.isNull()); - QVERIFY(s.toLatin1().size() == 0); - QVERIFY(s.toLatin1().isEmpty()); - QVERIFY(s.toLatin1().isNull()); - - s = "first-utf8"; - QVERIFY(s.toUtf8() == "first-utf8"); - s = "second-utf8"; - QVERIFY(s.toUtf8() == "second-utf8"); - s.clear(); - QVERIFY(s.isNull()); - QVERIFY(s.toUtf8().size() == 0); - QVERIFY(s.toUtf8().isEmpty()); - QVERIFY(s.toUtf8().isNull()); - - s = "first-utf8"; - QVERIFY(s.toUtf8() == "first-utf8"); - s = "second-utf8"; - QVERIFY(s.toUtf8() == "second-utf8"); - s.clear(); - QVERIFY(s.isNull()); - QVERIFY(s.toUtf8().size() == 0); - QVERIFY(s.toUtf8().isEmpty()); - QVERIFY(s.toUtf8().isNull()); - - s = "first-local8Bit"; - QVERIFY(s.toLocal8Bit() == "first-local8Bit"); - s = "second-local8Bit"; - QVERIFY(s.toLocal8Bit() == "second-local8Bit"); - s.clear(); - QVERIFY(s.isNull()); - QVERIFY(s.toLocal8Bit().size() == 0); - QVERIFY(s.toLocal8Bit().isEmpty()); - - s = "first-ascii"; - QVERIFY(s.toAscii() == "first-ascii"); - s = "second-ascii"; - QVERIFY(s.toAscii() == "second-ascii"); - s.clear(); - QVERIFY(s.isNull()); - QVERIFY(s.toAscii().size() == 0); - QVERIFY(s.toAscii().isEmpty()); - QVERIFY(s.toAscii().isNull()); - - s = "ascii"; - s += (uchar) 0xb0; - QVERIFY(s.toUtf8() != s.toLatin1()); - QString sa = s.toLatin1().constData(); - QVERIFY(sa[sa.length()-1] == (ushort) 0xb0); - QVERIFY(sa.left(sa.length()-1) == "ascii"); - - QVERIFY(s == QString::fromUtf8(s.toUtf8().constData())); - - s = "12"; - s.append('3'); - s += '4'; - QVERIFY(s == "1234"); - - s = "repend"; - s.prepend('p'); - QVERIFY(s == "prepend"); - s.prepend("abc "); - QVERIFY(s == "abc prepend"); - - s = " whitespace "; - QVERIFY(s.trimmed() == "whitespace"); - s = " lots of stuff "; - QVERIFY(s.simplified() == "lots of stuff"); - - s = "a hat, a stick, a ski"; - QVERIFY(s[2] == 'h'); - QVERIFY(s[1] < 'b'); - - - s = "12223"; - s.remove(1, 2); - QVERIFY(s == "123"); - - s = "(%1)(%2)"; - s = s.arg("foo").arg(7); - QVERIFY(s == "(foo)(7)"); - - -#if 0 - s = "stl rocks"; - std::string stl_string = s; - s = stl_string; - QVERIFY(s == "stl rocks"); -#endif - - { - QString str("Bananas"); - QVERIFY(str.startsWith("Ban")); - QVERIFY(false == str.startsWith("Car")); - } - { - QString str("Bananas"); - QVERIFY(str.endsWith("anas")); - QVERIFY(false == str.endsWith("pple")); - } - - - QString str = "Hello"; - QString cstr = QString::fromRawData(str.unicode(), str.length()); - QVERIFY(str == "Hello"); - QVERIFY(cstr == "Hello"); - cstr.clear(); - QVERIFY(str == "Hello"); - QVERIFY(cstr.isEmpty()); - - { - QString str1("Foo"); - str1.prepend(str1); - QCOMPARE(str1, QString("FooFoo")); - str1.append(str1); - QCOMPARE(str1, QString("FooFooFooFoo")); - str1.insert(2, str1); - QCOMPARE(str1, QString("FoFooFooFooFoooFooFooFoo")); - str1.replace(3, 3, str1); - QCOMPARE(str1, QString("FoFFoFooFooFooFoooFooFooFooooFooFoooFooFooFoo")); - str1 = "FooFoo"; - str1.replace(char('F'), str1); - QCOMPARE(str1, QString("FooFooooFooFoooo")); - str1 = "FooFoo"; - str1.replace(char('o'), str1); - QCOMPARE(str1, QString("FFooFooFooFooFFooFooFooFoo")); - - str1 = "Foo"; - str1.replace("Foo", str1); - QCOMPARE(str1, QString("Foo")); - str1.replace(str1, str1); - QCOMPARE(str1, QString("Foo")); - - str1 = "Foo"; - str1.replace("Foo", str1, Qt::CaseInsensitive); - QCOMPARE(str1, QString("Foo")); - str1.replace(str1, str1); - QCOMPARE(str1, QString("Foo")); - - str1 = "FooFoo"; - str1.reserve(100); - str1.replace("oo", str1); - QCOMPARE(str1, QString("FFooFooFFooFoo")); - - str1 = "Bar"; - str1.replace("FooFoo", str1); - QCOMPARE(str1, QString("Bar")); - - str1.replace(str1, "xxx"); - QCOMPARE(str1, QString("xxx")); - str1.replace(str1, QString("yyy")); - QCOMPARE(str1, QString("yyy")); - str1 += str1; - QCOMPARE(str1, QString("yyyyyy")); - } -} - - -void tst_Collections::bitArray() -{ - QBitArray ba(20); - QVERIFY(ba.testBit(17) == false); - ba.setBit(17); - QVERIFY(ba.size() == 20); - QVERIFY(ba.testBit(17)==true); - QVERIFY(!ba.testBit(16)); - ba[4] = true; - QVERIFY(ba.testBit(4)); - QVERIFY(ba[4]); - int sum = 0; - for(int i = 0; i < 20; i++) - sum += ba.testBit(i) ? 1 : 0; - QVERIFY(sum == 2); - - ba = QBitArray(7, true); - QVERIFY(ba.size() == 7); - QVERIFY(ba[5]); - - ba = QBitArray(3); - ba[0] = ba[2] = true; - - QBitArray nba(3); - nba[1] = true; - - QVERIFY(~ba == nba); - -}; - -struct CacheFoo -{ - CacheFoo(int v):val(v) { counter++; } - ~CacheFoo() { counter--; } - int val; - static int counter; - bool isDetached() const { return val != 2; } -}; - -int CacheFoo::counter = 0; - -void tst_Collections::cache() -{ - { - CacheFoo* cf; - QCache cache(120); - int i; - for (i = 0; i < 30; i++) { - cf = cache.object(10); - cache.insert(i, new CacheFoo(i), i); - } - - QVERIFY(cache.contains(10)); - QVERIFY(!cache.contains(1)); - QVERIFY(!cache.contains(2)); - delete cache.take(10); - } - { - QCache cache(120); - int i; - QString two; - for (i = 0; i < 30; i++) { - QString s = QString::number(i); - cache.insert(i, new QString(s), i); - if (i == 2) - two = s; - } - QVERIFY(!cache.contains(3)); - QVERIFY(!cache.contains(2)); - } - { - QCache cache(100); - cache.insert(2, new int(2)); - *cache[2] = 3; - QVERIFY(*cache.object(2) == 3); - } - - QVERIFY(CacheFoo::counter == 0); - -} - -void tst_Collections::regexp() -{ - QRegExp rx("^\\d\\d?$"); - QVERIFY(rx.indexIn("123") == -1); - QVERIFY(rx.indexIn("-6") == -1); - QVERIFY(rx.indexIn("6") == 0) ; -} - -void tst_Collections::pair() -{ - QPair p; - QVERIFY(p.first == 0.0); - QVERIFY(p.second == 0); - - QPair a(1, "Zebra"), b(2, "Ying"), c(3, "Yang"), d(3, "Ying"), e(5, "Alabama"); - QVERIFY(a.first == 1); - QVERIFY(a.second == "Zebra"); - QVERIFY(a == qMakePair(1, QString("Zebra"))); - - QVERIFY(a == a && b == b && c == c && d == d && e == e); - QVERIFY(a != b && a != c && a != d && a != e && b != c && b != d && b != e && c != d && c != e - && d != e); - - QVERIFY(a < b && b < c && c < d && d < e); - QVERIFY(a <= b && b <= c && c <= d && d <= e); - - QVERIFY(e > d && d > c && c > b && b > a); - QVERIFY(e >= d && d >= c && c >= b && b >= a); - - QVERIFY(!(a > b || b > c || c > d || d > e)); - QVERIFY(!(a >= b || b >= c || c >= d || d >= e)); - - QVERIFY(!(e < d || d < c || c < b || b < a)); - QVERIFY(!(e <= d || d <= c || c <= b || b <= a)); - - QVERIFY(a <= a && b <= b && c <= c && d <= d && e <= e); - QVERIFY(!(a < a || b < b || c < c || d < d || e < e)); - - QVERIFY(a >= a && b >= b && c >= c && d >= d && e >= e); - QVERIFY(!(a > a || b > b || c > c || d > d || e > e)); -} - -/* - These test that Java-style mutable iterators don't trash shared - copy (the setSharable() mechanism). -*/ - -template -void populate(Container &); - -template <> -void populate(QList &container) -{ - container << 1 << 2 << 4 << 8; -} - -template <> -void populate(QLinkedList &container) -{ - container << 1 << 2 << 4 << 8; -} - -template <> -void populate(QVector &container) -{ - container << 1 << 2 << 4 << 8; -} - -template <> -void populate(QMap &container) -{ - container.insert(1, 1); - container.insert(2, 2); - container.insert(4, 4); - container.insert(8, 8); -} - -template <> -void populate(QHash &container) -{ - container.insert(1, 1); - container.insert(2, 2); - container.insert(4, 4); - container.insert(8, 8); -} - -template -bool isSharable(const Container &container) -{ - Container copy = container; - return !container.isDetached(); -} - -template -void testContainer() -{ - /* - Verify that shared_null's 'sharable' flag is set to true. - */ - { - Container c1; - QVERIFY(!c1.isDetached()); - - Container c2 = c1; - QVERIFY(!c1.isDetached()); - QVERIFY(!c2.isDetached()); - } - - /* - Verify that the 'sharable' flag is true while no mutable - iterator is active. - */ - { - Container c1; - populate(c1); - QVERIFY(c1.size() == 4); - QVERIFY(c1.isDetached()); - - Container c2 = c1; - QVERIFY(c1.size() == 4); - QVERIFY(c2.size() == 4); - QVERIFY(!c1.isDetached()); - QVERIFY(!c2.isDetached()); - } - - /* - Verify that the 'sharable' flag is set to false by the - mutable iterator. - */ - { - Container c1; - populate(c1); - QVERIFY(c1.size() == 4); - QVERIFY(c1.isDetached()); - - ContainerMutableIterator i(c1); - i.next(); - - Container c2 = c1; - QVERIFY(c1.size() == 4); - QVERIFY(c2.size() == 4); - QVERIFY(c1.isDetached()); - QVERIFY(c2.isDetached()); - - i.remove(); - QVERIFY(c1.size() == 3); - QVERIFY(c2.size() == 4); - } - - /* - Verify that the 'sharable' flag is reset to true by the - mutable iterator's destructor. - */ - { - Container c1; - populate(c1); - QVERIFY(c1.size() == 4); - QVERIFY(c1.isDetached()); - - { - ContainerMutableIterator i(c1); - i.next(); - } - - Container c2 = c1; - QVERIFY(c1.size() == 4); - QVERIFY(c2.size() == 4); - QVERIFY(!c1.isDetached()); - QVERIFY(!c2.isDetached()); - } - - /* - Verify that the 'sharable' flag only affects the original - object, not the copies. - */ - { - Container c1; - populate(c1); - QVERIFY(c1.size() == 4); - QVERIFY(c1.isDetached()); - - Container c2 = c1; - QVERIFY(isSharable(c2)); - - ContainerMutableIterator i(c1); - QVERIFY(!isSharable(c1)); - QVERIFY(isSharable(c2)); - - Container c3 = c1; - QVERIFY(!isSharable(c1)); - QVERIFY(isSharable(c2)); - QVERIFY(isSharable(c3)); - QVERIFY(c1.isDetached()); - QVERIFY(c2.isDetached()); - QVERIFY(c3.isDetached()); - - Container c4; - c4 = c1; - QVERIFY(!isSharable(c1)); - QVERIFY(isSharable(c2)); - QVERIFY(isSharable(c4)); - QVERIFY(c1.isDetached()); - QVERIFY(c2.isDetached()); - QVERIFY(c4.isDetached()); - - c3 = c2; - QVERIFY(!isSharable(c1)); - QVERIFY(isSharable(c2)); - QVERIFY(isSharable(c3)); - QVERIFY(c1.isDetached()); - QVERIFY(!c2.isDetached()); - QVERIFY(!c3.isDetached()); - } -} - -#define TEST_SEQUENTIAL_CONTAINER(Container) \ - testContainer, QMutable##Container##Iterator >() - -#define TEST_ASSOCIATIVE_CONTAINER(Container) \ - testContainer, QMutable##Container##Iterator >() - -void tst_Collections::sharableQList() -{ - TEST_SEQUENTIAL_CONTAINER(List); -} - -void tst_Collections::sharableQLinkedList() -{ - TEST_SEQUENTIAL_CONTAINER(LinkedList); -} - -void tst_Collections::sharableQVector() -{ - TEST_SEQUENTIAL_CONTAINER(Vector); -} - -void tst_Collections::sharableQMap() -{ - TEST_ASSOCIATIVE_CONTAINER(Map); -} - -void tst_Collections::sharableQHash() -{ - TEST_ASSOCIATIVE_CONTAINER(Hash); -} - -static int getList_calls = 0; -QList getList() -{ - ++getList_calls; - QList list; - list << 1 << 2 << 3 << 4 << 5 << 6; - return list; -} - - -void tst_Collections::q_foreach() -{ - QList list; - list << -2 << -1 << 0 << 1 << 2; - - int sum = 0; - int j = 0; - foreach(int i, list) { - QCOMPARE(i, list.at(j)); - sum += i; - ++j; - } - QCOMPARE(sum, 0); - - // again, but without scope - foreach(int i, list) - sum += i; - QCOMPARE(sum, 0); - - foreach(int i, list) { - sum += i; - if (i == 0) - break; - } - QCOMPARE(sum, -3); - - sum = 0; - foreach(int i, list) { - if (i < 0) - continue; - sum += i; - } - QCOMPARE(sum, 3); - - sum = 0; - getList_calls = 0; - foreach(int i, getList()) - sum += i; - QCOMPARE(sum, 21); - QCOMPARE(getList_calls, 1); -} - - -void tst_Collections::conversions() -{ -#define STUFF "A" << "C" << "B" << "A" - - { - QList list1; - list1 << STUFF; - - QVector vect1 = list1.toVector(); - QCOMPARE(list1.size(), 4); - QVERIFY(vect1 == (QVector() << STUFF)); - - QList list2 = vect1.toList(); - QCOMPARE(list2.size(), 4); - QVERIFY(list2 == (QList() << STUFF)); - - QSet set1 = list1.toSet(); - QCOMPARE(set1.size(), 3); - QVERIFY(set1.contains("A")); - QVERIFY(set1.contains("B")); - QVERIFY(set1.contains("C")); - QVERIFY(!set1.contains("D")); - - QList list3 = set1.toList(); - QCOMPARE(list3.size(), 3); - QVERIFY(list3.contains("A")); - QVERIFY(list3.contains("B")); - QVERIFY(list3.contains("C")); - QVERIFY(!list3.contains("D")); - - QVERIFY(QList().toVector().isEmpty()); - QVERIFY(QList().toSet().isEmpty()); - QVERIFY(QVector().toList().isEmpty()); - QVERIFY(QSet().toList().isEmpty()); - } - - { - QList list1; - list1 << STUFF; - - QVector vect1 = QVector::fromList(list1); - QCOMPARE(list1.size(), 4); - QVERIFY(vect1 == (QVector() << STUFF)); - - QList list2 = QList::fromVector(vect1); - QCOMPARE(list2.size(), 4); - QVERIFY(list2 == (QList() << STUFF)); - - QSet set1 = QSet::fromList(list1); - QCOMPARE(set1.size(), 3); - QVERIFY(set1.contains("A")); - QVERIFY(set1.contains("B")); - QVERIFY(set1.contains("C")); - QVERIFY(!set1.contains("D")); - - QList list3 = QList::fromSet(set1); - QCOMPARE(list3.size(), 3); - QVERIFY(list3.contains("A")); - QVERIFY(list3.contains("B")); - QVERIFY(list3.contains("C")); - QVERIFY(!list3.contains("D")); - - QVERIFY(QVector::fromList(QList()).isEmpty()); - QVERIFY(QSet::fromList(QList()).isEmpty()); - QVERIFY(QList::fromVector(QVector()).isEmpty()); - QVERIFY(QList::fromSet(QSet()).isEmpty()); - } -#undef STUFF -} - -void tst_Collections::javaStyleIterators() -{ - QStringList list; - list << "a" << "b" << "c"; - QMutableStringListIterator i(list); - while (i.hasNext()) { - i.next(); - i.setValue(""); - } - while (i.hasPrevious()) { - i.previous(); - QVERIFY(i.value().isEmpty()); - i.value() = "x"; - QCOMPARE(i.value(), QString("x")); - } -} - -template -void testLinkedListLikeStlIterators() -{ - Container fake; - typename Container::value_type t; - fake << t; - - typename Container::iterator i1 = fake.begin(), i2 = i1 + 1; - typename Container::const_iterator c1 = i1, c2 = c1 + 1; - - QVERIFY(i1 == i1); - QVERIFY(i1 == c1); - QVERIFY(c1 == i1); - QVERIFY(c1 == c1); - QVERIFY(i2 == i2); - QVERIFY(i2 == c2); - QVERIFY(c2 == i2); - QVERIFY(c2 == c2); - - QVERIFY(i1 != i2); - QVERIFY(i1 != c2); - QVERIFY(c1 != i2); - QVERIFY(c1 != c2); - QVERIFY(i2 != i1); - QVERIFY(i2 != c1); - QVERIFY(c2 != i1); - QVERIFY(c2 != c1); -} - -template -void testListLikeStlIterators() -{ - testLinkedListLikeStlIterators(); - - Container fake; - typename Container::value_type t; - fake << t; - - typename Container::iterator i1 = fake.begin(), i2 = i1 + 1; - typename Container::const_iterator c1 = i1, c2 = c1 + 1; - - QVERIFY(i1 < i2); - QVERIFY(i1 < c2); - QVERIFY(c1 < i2); - QVERIFY(c1 < c2); - QVERIFY(!(i2 < i1)); - QVERIFY(!(i2 < c1)); - QVERIFY(!(c2 < i1)); - QVERIFY(!(c2 < c1)); - QVERIFY(!(i1 < i1)); - QVERIFY(!(i1 < c1)); - QVERIFY(!(c1 < i1)); - QVERIFY(!(c1 < c1)); - QVERIFY(!(i2 < i2)); - QVERIFY(!(i2 < c2)); - QVERIFY(!(c2 < i2)); - QVERIFY(!(c2 < c2)); - - QVERIFY(i2 > i1); - QVERIFY(i2 > c1); - QVERIFY(c2 > i1); - QVERIFY(c2 > c1); - QVERIFY(!(i1 > i2)); - QVERIFY(!(i1 > c2)); - QVERIFY(!(c1 > i2)); - QVERIFY(!(c1 > c2)); - QVERIFY(!(i1 > i1)); - QVERIFY(!(i1 > c1)); - QVERIFY(!(c1 > i1)); - QVERIFY(!(c1 > c1)); - QVERIFY(!(i2 > i2)); - QVERIFY(!(i2 > c2)); - QVERIFY(!(c2 > i2)); - QVERIFY(!(c2 > c2)); - - QVERIFY(!(i1 >= i2)); - QVERIFY(!(i1 >= c2)); - QVERIFY(!(c1 >= i2)); - QVERIFY(!(c1 >= c2)); - QVERIFY(i2 >= i1); - QVERIFY(i2 >= c1); - QVERIFY(c2 >= i1); - QVERIFY(c2 >= c1); - QVERIFY(i1 >= i1); - QVERIFY(i1 >= c1); - QVERIFY(c1 >= i1); - QVERIFY(c1 >= c1); - QVERIFY(i2 >= i2); - QVERIFY(i2 >= c2); - QVERIFY(c2 >= i2); - QVERIFY(c2 >= c2); - - QVERIFY(!(i2 <= i1)); - QVERIFY(!(i2 <= c1)); - QVERIFY(!(c2 <= i1)); - QVERIFY(!(c2 <= c1)); - QVERIFY(i1 <= i2); - QVERIFY(i1 <= c2); - QVERIFY(c1 <= i2); - QVERIFY(c1 <= c2); - QVERIFY(i1 <= i1); - QVERIFY(i1 <= c1); - QVERIFY(c1 <= i1); - QVERIFY(c1 <= c1); - QVERIFY(i2 <= i2); - QVERIFY(i2 <= c2); - QVERIFY(c2 <= i2); - QVERIFY(c2 <= c2); -} - -template -void testMapLikeStlIterators() -{ - Container fake; - QString k; - QString t; - fake.insert(k, t); - - typename Container::iterator i1 = fake.begin(), i2 = i1 + 1; - typename Container::const_iterator c1 = i1, c2 = c1 + 1; - - QVERIFY(i1 == i1); - QVERIFY(i1 == c1); - QVERIFY(c1 == i1); - QVERIFY(c1 == c1); - QVERIFY(i2 == i2); - QVERIFY(i2 == c2); - QVERIFY(c2 == i2); - QVERIFY(c2 == c2); - - QVERIFY(i1 != i2); - QVERIFY(i1 != c2); - QVERIFY(c1 != i2); - QVERIFY(c1 != c2); - QVERIFY(i2 != i1); - QVERIFY(i2 != c1); - QVERIFY(c2 != i1); - QVERIFY(c2 != c1); -} - -void tst_Collections::constAndNonConstStlIterators() -{ - testListLikeStlIterators >(); - testListLikeStlIterators(); - testLinkedListLikeStlIterators >(); - testListLikeStlIterators >(); - testMapLikeStlIterators >(); - testMapLikeStlIterators >(); - testMapLikeStlIterators >(); - testMapLikeStlIterators >(); -} - -#ifndef QT_NO_STL -void tst_Collections::vector_stl_data() -{ - QTest::addColumn("elements"); - - QTest::newRow("empty") << QStringList(); - QTest::newRow("one") << (QStringList() << "Hei"); - QTest::newRow("two") << (QStringList() << "Hei" << "Hopp"); - QTest::newRow("three") << (QStringList() << "Hei" << "Hopp" << "Sann"); -} - -void tst_Collections::vector_stl() -{ - QFETCH(QStringList, elements); - - QVector vector; - for (int i = 0; i < elements.count(); ++i) - vector << elements.at(i); - - std::vector stdVector = vector.toStdVector(); - - QCOMPARE(int(stdVector.size()), elements.size()); - - std::vector::const_iterator it = stdVector.begin(); - for (uint j = 0; j < stdVector.size() && it != stdVector.end(); ++j, ++it) - QCOMPARE(*it, vector[j]); - - QCOMPARE(QVector::fromStdVector(stdVector), vector); -} - -void tst_Collections::linkedlist_stl_data() -{ - list_stl_data(); -} - -void tst_Collections::linkedlist_stl() -{ - QFETCH(QStringList, elements); - - QLinkedList list; - for (int i = 0; i < elements.count(); ++i) - list << elements.at(i); - - std::list stdList = list.toStdList(); - - QCOMPARE(int(stdList.size()), elements.size()); - - std::list::const_iterator it = stdList.begin(); - QLinkedList::const_iterator it2 = list.constBegin(); - for (uint j = 0; j < stdList.size(); ++j, ++it, ++it2) - QCOMPARE(*it, *it2); - - QCOMPARE(QLinkedList::fromStdList(stdList), list); -} - -void tst_Collections::list_stl_data() -{ - QTest::addColumn("elements"); - - QTest::newRow("empty") << QStringList(); - QTest::newRow("one") << (QStringList() << "Hei"); - QTest::newRow("two") << (QStringList() << "Hei" << "Hopp"); - QTest::newRow("three") << (QStringList() << "Hei" << "Hopp" << "Sann"); -} - -void tst_Collections::list_stl() -{ - QFETCH(QStringList, elements); - - QList list; - for (int i = 0; i < elements.count(); ++i) - list << elements.at(i); - - std::list stdList = list.toStdList(); - - QCOMPARE(int(stdList.size()), elements.size()); - - std::list::const_iterator it = stdList.begin(); - for (uint j = 0; j < stdList.size() && it != stdList.end(); ++j, ++it) - QCOMPARE(*it, list[j]); - - QCOMPARE(QList::fromStdList(stdList), list); -} -#endif - -template -T qtInit(T * = 0) -{ - return T(); -} - -void tst_Collections::q_init() -{ - QCOMPARE(qtInit(), 0); - QCOMPARE(qtInit(), 0.0); - QCOMPARE(qtInit(), QString()); - QCOMPARE(qtInit(), static_cast(0)); - QCOMPARE(qtInit(), static_cast(0)); - QCOMPARE(qtInit(), static_cast(0)); - QCOMPARE(qtInit().i1, 0); - QCOMPARE(qtInit().i2, 0); -} - -void tst_Collections::pointersize() -{ - QCOMPARE(int(sizeof(void *)), QT_POINTER_SIZE); -} - -class LessThanComparable -{ -public: - bool operator<(const LessThanComparable &) const { return true; } -}; - -class EqualsComparable -{ -public: - bool operator==(const EqualsComparable &) const { return true; } -}; - -uint qHash(const EqualsComparable &) -{ - return 0; -} - -/* - The following functions instatiates every member functions in the - Qt containers that requires either operator== or operator<. - They are ordered in a concept inheritance tree: - - Container - MutableIterationContainer - Sequence (QLinkedList) - Random Access (QVector, QList, QQueue, QStack) - Pair Associative (QHash, QMap) - Associative (QSet) -*/ -template -void instantiateContainer() -{ - const ValueType value = ValueType(); - ContainerType container; - const ContainerType constContainer(container); - -#ifndef QT_NO_STL - typename ContainerType::const_iterator constIt; - constIt = constContainer.begin(); - container.constBegin(); - - constIt = constContainer.end(); - container.constEnd(); -#endif - container.clear(); - container.contains(value); - container.count(); - container.empty(); - container.isEmpty(); - container.size(); - - container != constContainer; - container == constContainer; - container = constContainer; -} - -template -void instantiateMutableIterationContainer() -{ - instantiateContainer(); - ContainerType container; - -#ifndef QT_NO_STL - typename ContainerType::iterator it; - it = container.begin(); - it = container.end(); -#endif - - // QSet lacks count(T). - const ValueType value = ValueType(); - container.count(value); -} - -template -void instantiateSequence() -{ - instantiateMutableIterationContainer(); - -// QVector lacks removeAll(T) -// ValueType value = ValueType(); -// ContainerType container; -// container.removeAll(value); -} - -template -void instantiateRandomAccess() -{ - instantiateSequence(); - - ValueType value = ValueType(); - ContainerType container; - container.indexOf(value); - container.lastIndexOf(value); -} - -template -void instantiateAssociative() -{ - instantiateContainer(); - - const ValueType value = ValueType(); - ContainerType container; - const ContainerType constContainer(container); - - container.reserve(1); - container.capacity(); - container.squeeze(); - - container.remove(value); - container.values(); - - container.unite(constContainer); - container.intersect(constContainer); - container.subtract(constContainer); - - container != constContainer; - container == constContainer; - container & constContainer; - container &= constContainer; - container &= value; - container + constContainer; - container += constContainer; - container += value; - container - constContainer; - container -= constContainer; - container -= value; - container | constContainer; - container |= constContainer; - container |= value; -} - -template -void instantiatePairAssociative() -{ - instantiateMutableIterationContainer(); - - typename ContainerType::iterator it; - typename ContainerType::const_iterator constIt; - const KeyType key = KeyType(); - const ValueType value = ValueType(); - ContainerType container; - const ContainerType constContainer(container); - - it = container.insert(key, value); - container.erase(it); - container.find(key); - container.constFind(key); - constContainer.find(key); - - container.key(value); - container.keys(); - constContainer.keys(); - container.remove(key); - container.take(key); - container.unite(constContainer); - container.value(key); - container.value(key, value); - container.values(); - container.values(key); - container[key]; - const int foo = constContainer[key]; - Q_UNUSED(foo); -} - -/* - Instantiate all Qt containers using a datatype that - defines the minimum amount of operators. -*/ -void tst_Collections::containerInstantiation() -{ - // Instantiate QHash member functions. - typedef QHash Hash; - instantiatePairAssociative(); - - Hash hash; - hash.reserve(1); - hash.capacity(); - hash.squeeze(); - - // Instantiate QMap member functions. - typedef QMap Map; - instantiatePairAssociative(); - - // Instantiate QSet member functions. - typedef QSet Set; - instantiateAssociative(); - - //Instantiate QLinkedList member functions. - typedef QLinkedList LinkedList; - instantiateSequence (); - { - EqualsComparable value; - LinkedList list; - list.removeAll(value); - } - - //Instantiate QList member functions. - typedef QList List; - instantiateRandomAccess(); - { - EqualsComparable value; - List list; - list.removeAll(value); - } - - //Instantiate QVector member functions. - typedef QVector Vector; - instantiateRandomAccess(); - - //Instantiate QQueue member functions. - typedef QQueue Queue; - instantiateRandomAccess(); - - //Instantiate QStack member functions. - typedef QStack Stack; - instantiateRandomAccess(); -} - -void tst_Collections::qtimerList() -{ - QList foo; - const int N = 10000; - - foo.append(99.9); - foo.append(99.9); - foo.append(99.9); - - for(int i = 0; i < N; i++) { - foo.removeFirst(); - foo.insert(1, 99.9); - } - - QList::Iterator end = foo.end(); - for (int i = 0; i < (N / 2) - 10; ++i) { - foo.prepend(99.9); - if (foo.end() != end) - return; - } - QFAIL("QList preallocates too much memory"); -} - -template -void testContainerTypedefs(Container container) -{ - Q_UNUSED(container) - { typedef typename Container::value_type Foo; } - { typedef typename Container::iterator Foo; } - { typedef typename Container::const_iterator Foo; } - { typedef typename Container::reference Foo; } - { typedef typename Container::const_reference Foo; } - { typedef typename Container::pointer Foo; } - { typedef typename Container::difference_type Foo; } - { typedef typename Container::size_type Foo; } -} - -template -void testPairAssociativeContainerTypedefs(Container container) -{ - Q_UNUSED(container) - -// TODO: Not sure how to define value_type for our associative containers -// { typedef typename Container::value_type Foo; } -// { typedef typename Container::const_iterator Foo; } -// { typedef typename Container::reference Foo; } -// { typedef typename Container::const_reference Foo; } -// { typedef typename Container::pointer Foo; } - - { typedef typename Container::difference_type Foo; } - { typedef typename Container::size_type Foo; } - { typedef typename Container::iterator Foo; } - { typedef typename Container::key_type Foo; } - { typedef typename Container::mapped_type Foo; } -// TODO -// { typedef typename Container::key_compare Foo; } -// { typedef typename Container::value_comare Foo; } -} - -template -void testSetContainerTypedefs(Container container) -{ - Q_UNUSED(container) - { typedef typename Container::iterator Foo; } - { typedef typename Container::const_iterator Foo; } - { typedef typename Container::reference Foo; } - { typedef typename Container::const_reference Foo; } - { typedef typename Container::pointer Foo; } - { typedef typename Container::difference_type Foo; } - { typedef typename Container::size_type Foo; } - { typedef typename Container::key_type Foo; } -} - -/* - Compile-time test that verifies that the Qt containers - have STL-compatable typedefs. -*/ -void tst_Collections::containerTypedefs() -{ - testContainerTypedefs(QVector()); - testContainerTypedefs(QStack()); - testContainerTypedefs(QList()); - testContainerTypedefs(QLinkedList()); - testContainerTypedefs(QQueue()); - - testPairAssociativeContainerTypedefs(QMap()); - testPairAssociativeContainerTypedefs(QMultiMap()); - testPairAssociativeContainerTypedefs(QHash()); - - testSetContainerTypedefs(QSet()); -} - -class Key1; -class T1; -class T2; - -void tst_Collections::forwardDeclared() -{ - { typedef QHash C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QMultiHash C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QMap C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QMultiMap C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QPair C; C *x = 0; Q_UNUSED(x) } - { typedef QList C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QLinkedList C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QVector C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) Q_UNUSED(i) Q_UNUSED(j) } - { typedef QStack C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) Q_UNUSED(i) Q_UNUSED(j) } - { typedef QQueue C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } - { typedef QSet C; C *x = 0; /* C::iterator i; */ C::const_iterator j; Q_UNUSED(x) } -} - -#if defined(Q_ALIGNOF) && defined(Q_DECL_ALIGN) - -class Q_DECL_ALIGN(4) Aligned4 -{ - char i; -public: - Aligned4(int i = 0) : i(i) {} - bool checkAligned() const - { - return (quintptr(this) & 3) == 0; - } - - inline bool operator==(const Aligned4 &other) const { return i == other.i; } - inline bool operator<(const Aligned4 &other) const { return i < other.i; } - friend inline int qHash(const Aligned4 &a) { return qHash(a.i); } -}; - -class Q_DECL_ALIGN(128) Aligned128 -{ - char i; -public: - Aligned128(int i = 0) : i(i) {} - bool checkAligned() const - { - return (quintptr(this) & 127) == 0; - } - - inline bool operator==(const Aligned128 &other) const { return i == other.i; } - inline bool operator<(const Aligned128 &other) const { return i < other.i; } - friend inline int qHash(const Aligned128 &a) { return qHash(a.i); } -}; - -template -void testVectorAlignment() -{ - typedef typename C::value_type Aligned; - C container; - container.append(Aligned()); - QVERIFY(container[0].checkAligned()); - - for (int i = 0; i < 200; ++i) - container.append(Aligned()); - - for (int i = 0; i < container.size(); ++i) - QVERIFY(container.at(i).checkAligned()); -} - -template -void testContiguousCacheAlignment() -{ - typedef typename C::value_type Aligned; - C container(150); - container.append(Aligned()); - QVERIFY(container[container.firstIndex()].checkAligned()); - - for (int i = 0; i < 200; ++i) - container.append(Aligned()); - - for (int i = container.firstIndex(); i < container.lastIndex(); ++i) - QVERIFY(container.at(i).checkAligned()); -} - -template -void testAssociativeContainerAlignment() -{ - typedef typename C::key_type Key; - typedef typename C::mapped_type Value; - C container; - container.insert(Key(), Value()); - - typename C::const_iterator it = container.constBegin(); - QVERIFY(it.key().checkAligned()); - QVERIFY(it.value().checkAligned()); - - // add some more elements - for (int i = 0; i < 200; ++i) - container.insert(Key(i), Value(i)); - - it = container.constBegin(); - for ( ; it != container.constEnd(); ++it) { - QVERIFY(it.key().checkAligned()); - QVERIFY(it.value().checkAligned()); - } -} - -void tst_Collections::alignment() -{ - testVectorAlignment >(); - testVectorAlignment >(); - testContiguousCacheAlignment >(); - testContiguousCacheAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); - testAssociativeContainerAlignment >(); -} -#endif - -#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS - -template class C> -struct QTBUG13079_Node { - C children; - QString s; - - ~QTBUG13079_Node() { - children.begin(); //play with memory - } -}; -template class C> void QTBUG13079_collectionInsideCollectionImpl() -{ - C > nodeList; - nodeList << QTBUG13079_Node(); - nodeList.first().s = "parent"; - nodeList.first().children << QTBUG13079_Node(); - nodeList.first().children.first().s = "child"; - - nodeList = nodeList.first().children; - QCOMPARE(nodeList.first().s, QString::fromLatin1("child")); - - nodeList = nodeList.first().children; - QCOMPARE(nodeList.count(), 0); - nodeList << QTBUG13079_Node(); -} - -template class C> -struct QTBUG13079_NodeAssoc { - C children; - QString s; - - ~QTBUG13079_NodeAssoc() { - children.begin(); //play with memory - } -}; -template class C> void QTBUG13079_collectionInsideCollectionAssocImpl() -{ - C > nodeMap; - nodeMap[18] = QTBUG13079_NodeAssoc(); - nodeMap[18].s = "parent"; - nodeMap[18].children[12] = QTBUG13079_NodeAssoc(); - nodeMap[18].children[12].s = "child"; - - nodeMap = nodeMap[18].children; - QCOMPARE(nodeMap[12].s, QString::fromLatin1("child")); - - nodeMap = nodeMap[12].children; - QCOMPARE(nodeMap.count(), 0); - nodeMap[42] = QTBUG13079_NodeAssoc(); -} - - -quint32 qHash(const QTBUG13079_Node &) -{ - return 0; -} - -bool operator==(const QTBUG13079_Node &a, const QTBUG13079_Node &b) -{ - return a.s == b.s && a.children == b.children; -} - -template class C> -struct QTBUG13079_NodePtr : QSharedData { - C child; - QTBUG13079_NodePtr *next; - QString s; - - QTBUG13079_NodePtr() : next(0) {} - ~QTBUG13079_NodePtr() { - next = child.data(); //play with memory - } -}; -template class C> void QTBUG13079_collectionInsidePtrImpl() -{ - typedef C > Ptr; - { - Ptr nodePtr; - nodePtr = Ptr(new QTBUG13079_NodePtr()); - nodePtr->s = "parent"; - nodePtr->child = Ptr(new QTBUG13079_NodePtr()); - nodePtr->child->s = "child"; - nodePtr = nodePtr->child; - QCOMPARE(nodePtr->s, QString::fromLatin1("child")); - nodePtr = nodePtr->child; - QVERIFY(!nodePtr); - } - { - Ptr nodePtr; - nodePtr = Ptr(new QTBUG13079_NodePtr()); - nodePtr->s = "parent"; - nodePtr->next = new QTBUG13079_NodePtr(); - nodePtr->next->s = "next"; - nodePtr = Ptr(nodePtr->next); - QCOMPARE(nodePtr->s, QString::fromLatin1("next")); - nodePtr = Ptr(nodePtr->next); - QVERIFY(!nodePtr); - } -} - -#endif - -void tst_Collections::QTBUG13079_collectionInsideCollection() -{ -#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS - QTBUG13079_collectionInsideCollectionImpl(); - QTBUG13079_collectionInsideCollectionImpl(); - QTBUG13079_collectionInsideCollectionImpl(); - QTBUG13079_collectionInsideCollectionImpl(); - QTBUG13079_collectionInsideCollectionImpl(); - - { - QSet > nodeSet; - nodeSet << QTBUG13079_Node(); - nodeSet = nodeSet.begin()->children; - QCOMPARE(nodeSet.count(), 0); - } - - QTBUG13079_collectionInsideCollectionAssocImpl(); - QTBUG13079_collectionInsideCollectionAssocImpl(); - - QTBUG13079_collectionInsidePtrImpl(); - QTBUG13079_collectionInsidePtrImpl(); - QTBUG13079_collectionInsidePtrImpl(); -#endif -} - -template void foreach_test_arrays(const Container &container) -{ - typedef typename Container::value_type T; - int i = 0; - QSet set; - foreach(const T & val, container) { - QVERIFY( val == container[i] ); - set << val; - i++; - } - QCOMPARE(set.count(), container.count()); - - //modify the container while iterating. - Container c2 = container; - Container c3; - i = 0; - foreach (T val, c2) { - c3 << val; - c2.insert((i * 89) % c2.size(), T() ); - QVERIFY( val == container.at(i) ); - val = T(); - i++; - } - QVERIFY(c3 == container); -} - - -void tst_Collections::foreach_2() -{ - QStringList strlist = QString::fromLatin1("a,b,c,d,e,f,g,h,ih,kl,mn,op,qr,st,uvw,xyz").split(","); - foreach_test_arrays(strlist); - foreach_test_arrays(QList(strlist)); - foreach_test_arrays(strlist.toVector()); - - QList intlist; - intlist << 1 << 2 << 3 << 4 <<5 << 6 << 7 << 8 << 9; - foreach_test_arrays(intlist); - foreach_test_arrays(intlist.toVector()); - - QVarLengthArray varl1; - QVarLengthArray varl2; - QVarLengthArray varl3; - foreach(int i, intlist) { - varl1 << i; - varl2 << i; - varl3 << i; - } - QCOMPARE(varl1.count(), intlist.count()); - QCOMPARE(varl2.count(), intlist.count()); - QCOMPARE(varl3.count(), intlist.count()); - foreach_test_arrays(varl1); - foreach_test_arrays(varl2); - foreach_test_arrays(varl3); - - QVarLengthArray varl4; - QVarLengthArray varl5; - QVarLengthArray varl6; - foreach(const QString &str, strlist) { - varl4 << str; - varl5 << str; - varl6 << str; - } - QCOMPARE(varl4.count(), strlist.count()); - QCOMPARE(varl5.count(), strlist.count()); - QCOMPARE(varl6.count(), strlist.count()); - foreach_test_arrays(varl4); - foreach_test_arrays(varl5); - foreach_test_arrays(varl6); -} - -struct IntOrString -{ - int val; - IntOrString(int v) : val(v) { } - IntOrString(const QString &v) : val(v.toInt()) { } - operator int() { return val; } - operator QString() { return QString::number(val); } -#ifndef QT_NO_STL - operator std::string() { return QString::number(val).toStdString(); } - IntOrString(const std::string &v) : val(QString::fromStdString(v).toInt()) { } -#endif -}; - -template void insert_remove_loop_impl() -{ - typedef typename Container::value_type T; - Container t; - t.append(T(IntOrString(1))); - t << (T(IntOrString(2))); - t += (T(IntOrString(3))); - t.prepend(T(IntOrString(4))); - t.insert(2, 3 , T(IntOrString(5))); - t.insert(4, T(IntOrString(6))); - t.insert(t.begin() + 2, T(IntOrString(7))); - t.insert(t.begin() + 5, 3, T(IntOrString(8))); - int expect1[] = { 4 , 1 , 7, 5 , 5 , 8, 8, 8, 6, 5, 2 , 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect1)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { - QCOMPARE(t[i], T(IntOrString(expect1[i]))); - } - - Container compare_test1 = t; - t.replace(5, T(IntOrString(9))); - Container compare_test2 = t; - QVERIFY(!(compare_test1 == t)); - QVERIFY( (compare_test1 != t)); - QVERIFY( (compare_test2 == t)); - QVERIFY(!(compare_test2 != t)); - t.remove(7); - t.remove(2, 3); - int expect2[] = { 4 , 1 , 9, 8, 6, 5, 2 , 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect2)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { - QCOMPARE(t[i], T(IntOrString(expect2[i]))); - } - - for (typename Container::iterator it = t.begin(); it != t.end(); ) { - if ( int(IntOrString(*it)) % 2 ) - ++it; - else - it = t.erase(it); - } - - int expect3[] = { 1 , 9, 5, 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect3)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { - QCOMPARE(t[i], T(IntOrString(expect3[i]))); - } - - t.erase(t.begin() + 1, t.end() - 1); - - int expect4[] = { 1 , 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect4)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { - QCOMPARE(t[i], T(IntOrString(expect4[i]))); - } - - t << T(IntOrString(10)) << T(IntOrString(11)) << T(IntOrString(12)) << T(IntOrString(13)); - t << T(IntOrString(14)) << T(IntOrString(15)) << T(IntOrString(16)) << T(IntOrString(17)); - t << T(IntOrString(18)) << T(IntOrString(19)) << T(IntOrString(20)) << T(IntOrString(21)); - for (typename Container::iterator it = t.begin(); it != t.end(); ++it) { - int iv = int(IntOrString(*it)); - if ( iv % 2 ) { - it = t.insert(it, T(IntOrString(iv * iv))); - it = t.insert(it + 2, T(IntOrString(iv * iv + 1))); - } - } - - int expect5[] = { 1, 1, 2, 3*3, 3, 3*3+1, 10, 11*11, 11, 11*11+1, 12 , 13*13, 13, 13*13+1, 14, - 15*15, 15, 15*15+1, 16 , 17*17, 17, 17*17+1 ,18 , 19*19, 19, 19*19+1, 20, 21*21, 21, 21*21+1 }; - QCOMPARE(size_t(t.count()), sizeof(expect5)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { - QCOMPARE(t[i], T(IntOrString(expect5[i]))); - } -} - - -//Add insert(int, int, T) so it has the same interface as QVector and QVarLengthArray for the test. -template -struct ExtList : QList { - using QList::insert; - void insert(int before, int n, const T&x) { - while (n--) { - this->insert(before, x ); - } - } - void insert(typename QList::iterator before, int n, const T&x) { - while (n--) { - before = this->insert(before, x); - } - } - - void remove(int i) { - this->removeAt(i); - } - void remove(int i, int n) { - while (n--) { - this->removeAt(i); - } - } -}; - -void tst_Collections::insert_remove_loop() -{ - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - -#ifndef QT_NO_STL - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); - insert_remove_loop_impl >(); -#endif -} - - - -QTEST_APPLESS_MAIN(tst_Collections) -#include "tst_collections.moc" diff --git a/tests/auto/corelib.pro b/tests/auto/corelib.pro index 7269f890a7..ebdc1cd8c5 100644 --- a/tests/auto/corelib.pro +++ b/tests/auto/corelib.pro @@ -1,7 +1,5 @@ TEMPLATE=subdirs SUBDIRS=\ corelib \ - collections \ - exceptionsafety \ qobjectrace \ utf8 diff --git a/tests/auto/corelib/kernel/kernel.pro b/tests/auto/corelib/kernel/kernel.pro index 42fda6f300..552c94d35f 100644 --- a/tests/auto/corelib/kernel/kernel.pro +++ b/tests/auto/corelib/kernel/kernel.pro @@ -13,7 +13,7 @@ SUBDIRS=\ qsignalmapper \ qsocketnotifier \ qtimer \ - # qtipc \ # needs to be moved to qtscript + # qtipc \ # needs to be moved to qtscript (and note that it uses private API) qtranslator \ qvariant \ qwineventnotifier diff --git a/tests/auto/corelib/kernel/qabstractitemmodel/qabstractitemmodel.pro b/tests/auto/corelib/kernel/qabstractitemmodel/qabstractitemmodel.pro index 50730b371f..eee2222cda 100644 --- a/tests/auto/corelib/kernel/qabstractitemmodel/qabstractitemmodel.pro +++ b/tests/auto/corelib/kernel/qabstractitemmodel/qabstractitemmodel.pro @@ -1,9 +1,7 @@ load(qttest_p4) -INCLUDEPATH += $$PWD/../../../modeltest +mtdir = ../../../integrationtests/modeltest +INCLUDEPATH += $$PWD/$${mtdir} QT += widgets -SOURCES += tst_qabstractitemmodel.cpp ../../../modeltest/dynamictreemodel.cpp ../../../modeltest/modeltest.cpp -HEADERS += ../../../modeltest/dynamictreemodel.h ../../../modeltest/modeltest.h - - - +SOURCES += tst_qabstractitemmodel.cpp $${mtdir}/dynamictreemodel.cpp $${mtdir}/modeltest.cpp +HEADERS += $${mtdir}/dynamictreemodel.h $${mtdir}/modeltest.h diff --git a/tests/auto/exceptionsafety/.gitignore b/tests/auto/exceptionsafety/.gitignore deleted file mode 100644 index 9a854c4c26..0000000000 --- a/tests/auto/exceptionsafety/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_exceptionsafety diff --git a/tests/auto/exceptionsafety/exceptionsafety.pro b/tests/auto/exceptionsafety/exceptionsafety.pro deleted file mode 100644 index 52ba9e27bd..0000000000 --- a/tests/auto/exceptionsafety/exceptionsafety.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_exceptionsafety.cpp -QT = core -CONFIG += parallel_test diff --git a/tests/auto/exceptionsafety/tst_exceptionsafety.cpp b/tests/auto/exceptionsafety/tst_exceptionsafety.cpp deleted file mode 100644 index 27db9ea7f7..0000000000 --- a/tests/auto/exceptionsafety/tst_exceptionsafety.cpp +++ /dev/null @@ -1,734 +0,0 @@ -/**************************************************************************** -** -** 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 - -QT_USE_NAMESPACE - -class tst_ExceptionSafety: public QObject -{ - Q_OBJECT -private slots: -#ifdef QT_NO_EXCEPTIONS - void initTestCase(); -#else - void exceptionInSlot(); - void exceptionVector(); - void exceptionHash(); - void exceptionMap(); - void exceptionList(); - void exceptionLinkedList(); -// void exceptionEventLoop(); -// void exceptionSignalSlot(); -#endif -}; - -#ifdef QT_NO_EXCEPTIONS -void tst_ExceptionSafety::initTestCase() -{ - QSKIP("This test requires exception support", SkipAll); -} - -#else - -class Emitter : public QObject -{ - Q_OBJECT -public: - inline void emitTestSignal() { emit testSignal(); } -signals: - void testSignal(); -}; - -class ExceptionThrower : public QObject -{ - Q_OBJECT -public slots: - void thrower() { throw 5; } -}; - -class Receiver : public QObject -{ - Q_OBJECT -public: - Receiver() - : received(0) {} - int received; - -public slots: - void receiver() { ++received; } -}; - -enum ThrowType { ThrowNot = 0, ThrowAtCreate = 1, ThrowAtCopy = 2, ThrowLater = 3, ThrowAtComparison = 4 }; - -ThrowType throwType = ThrowNot; // global flag to indicate when an exception should be throw. Will be reset when the exception has been generated. - -int objCounter = 0; - -/*! Class that does not throw any exceptions. Used as baseclass for all the other ones. - */ -template -class FlexibleThrower -{ - public: - FlexibleThrower() : _value(-1) { - if( throwType == ThrowAtCreate ) { - throwType = ThrowNot; - throw ThrowAtCreate; - } - objCounter++; - } - - FlexibleThrower( short value ) : _value(value) { - if( throwType == ThrowAtCreate ) { - throwType = ThrowNot; - throw ThrowAtCreate; - } - objCounter++; - } - - FlexibleThrower(FlexibleThrower const& other ) { - // qDebug("cc"); - - if( throwType == ThrowAtCopy ) { - throwType = ThrowNot; - throw ThrowAtCopy; - - } else if( throwType == ThrowLater ) { - throwType = ThrowAtCopy; - } - - objCounter++; - _value = other.value(); - } - - ~FlexibleThrower() { objCounter--; } - - bool operator==(const FlexibleThrower &t) const - { - // qDebug("vv == %d %d", value(), t.value()); - if( throwType == ThrowAtComparison ) { - throwType = ThrowNot; - throw ThrowAtComparison; - } - return value()==t.value(); - } - - bool operator<(const FlexibleThrower &t) const - { - // qDebug("vv < %d %d", value(), t.value()); - if( throwType == ThrowAtComparison ) { - throwType = ThrowNot; - throw ThrowAtComparison; - } - return value()& t) -{ - // qDebug("ha"); - if( throwType == ThrowAtComparison ) { - throwType = ThrowNot; - throw ThrowAtComparison; - } - return (uint)t.value(); -} - -typedef FlexibleThrower<2> FlexibleThrowerSmall; -typedef QMap MyMap; -typedef QHash MyHash; - -// connect a signal to a slot that throws an exception -// run this through valgrind to make sure it doesn't corrupt -void tst_ExceptionSafety::exceptionInSlot() -{ - Emitter emitter; - ExceptionThrower thrower; - - connect(&emitter, SIGNAL(testSignal()), &thrower, SLOT(thrower())); - - try { - emitter.emitTestSignal(); - } catch (int i) { - QCOMPARE(i, 5); - } -} - -void tst_ExceptionSafety::exceptionList() { - - { - QList list; - QList list2; - QList list3; - - for( int i = 0; i<10; i++ ) - list.append( FlexibleThrowerSmall(i) ); - - try { - throwType = ThrowAtCopy; - list.append( FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( list.size(), 10 ); - - try { - throwType = ThrowAtCopy; - list.prepend( FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( list.at(0).value(), 0 ); - QCOMPARE( list.size(), 10 ); - - try { - throwType = ThrowAtCopy; - list.insert( 8, FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( list.at(7).value(), 7 ); - QCOMPARE( list.at(8).value(), 8 ); - QCOMPARE( list.size(), 10 ); - - try { - throwType = ThrowAtCopy; - FlexibleThrowerSmall t = list.takeAt( 6 ); - } catch (...) { - } - QCOMPARE( list.at(6).value(), 6 ); - QCOMPARE( list.at(7).value(), 7 ); - QCOMPARE( list.size(), 10 ); - - try { - throwType = ThrowAtCopy; - list3 = list; - } catch (...) { - } - QCOMPARE( list.at(0).value(), 0 ); - QCOMPARE( list.at(7).value(), 7 ); - QCOMPARE( list.size(), 10 ); - QCOMPARE( list3.at(0).value(), 0 ); - QCOMPARE( list3.at(7).value(), 7 ); - QCOMPARE( list3.size(), 10 ); - - try { - throwType = ThrowAtCopy; - list3.append( FlexibleThrowerSmall(11) ); - } catch (...) { - } - QCOMPARE( list.at(0).value(), 0 ); - QCOMPARE( list.at(7).value(), 7 ); - QCOMPARE( list.size(), 10 ); - QCOMPARE( list3.at(0).value(), 0 ); - QCOMPARE( list3.at(7).value(), 7 ); - QCOMPARE( list3.size(), 10 ); - - try { - list2.clear(); - list2.append( FlexibleThrowerSmall(11)); - throwType = ThrowAtCopy; - list3 = list+list2; - } catch (...) { - } - QCOMPARE( list.at(0).value(), 0 ); - QCOMPARE( list.at(7).value(), 7 ); - QCOMPARE( list.size(), 10 ); - - // check that copy on write works atomar - list2.clear(); - list2.append( FlexibleThrowerSmall(11)); - list3 = list+list2; - try { - throwType = ThrowAtCreate; - list3[7]=FlexibleThrowerSmall(12); - } catch (...) { - } - QCOMPARE( list.at(7).value(), 7 ); - QCOMPARE( list.size(), 10 ); - QCOMPARE( list3.at(7).value(), 7 ); - QCOMPARE( list3.size(), 11 ); - - } - QCOMPARE(objCounter, 0 ); // check that every object has been freed -} - -void tst_ExceptionSafety::exceptionLinkedList() { - - { - QLinkedList list; - QLinkedList list2; - QLinkedList list3; - - for( int i = 0; i<10; i++ ) - list.append( FlexibleThrowerSmall(i) ); - - try { - throwType = ThrowAtCopy; - list.append( FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( list.size(), 10 ); - - try { - throwType = ThrowAtCopy; - list.prepend( FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( list.first().value(), 0 ); - QCOMPARE( list.size(), 10 ); - - try { - throwType = ThrowAtCopy; - list3 = list; - list3.append( FlexibleThrowerSmall(11) ); - } catch (...) { - } - QCOMPARE( list.first().value(), 0 ); - QCOMPARE( list.size(), 10 ); - QCOMPARE( list3.size(), 10 ); - } - QCOMPARE(objCounter, 0 ); // check that every object has been freed -} - -void tst_ExceptionSafety::exceptionVector() { - - { - QVector vector; - QVector vector2; - QVector vector3; - - for (int i = 0; i<10; i++) - vector.append( FlexibleThrowerSmall(i) ); - - try { - throwType = ThrowAtCopy; - vector.append( FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( vector.size(), 10 ); - - try { - throwType = ThrowAtCopy; - vector.prepend( FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( vector.at(0).value(), 0 ); - QCOMPARE( vector.size(), 10 ); - - try { - throwType = ThrowAtCopy; - vector.insert( 8, FlexibleThrowerSmall(10)); - } catch (...) { - } - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.at(8).value(), 8 ); - QCOMPARE( vector.size(), 10 ); - - try { - throwType = ThrowAtCopy; - vector3 = vector; - } catch (...) { - } - QCOMPARE( vector.at(0).value(), 0 ); - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.size(), 10 ); - QCOMPARE( vector3.at(0).value(), 0 ); - QCOMPARE( vector3.at(7).value(), 7 ); - QCOMPARE( vector3.size(), 10 ); - - try { - throwType = ThrowAtCopy; - vector3.append( FlexibleThrowerSmall(11) ); - } catch (...) { - } - QCOMPARE( vector.at(0).value(), 0 ); - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.size(), 10 ); - QCOMPARE( vector3.at(0).value(), 0 ); - QCOMPARE( vector3.at(7).value(), 7 ); - - try { - vector2.clear(); - vector2.append( FlexibleThrowerSmall(11)); - throwType = ThrowAtCopy; - vector3 = vector+vector2; - } catch (...) { - } - QCOMPARE( vector.at(0).value(), 0 ); - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.size(), 10 ); - - // check that copy on write works atomar - vector2.clear(); - vector2.append( FlexibleThrowerSmall(11)); - vector3 = vector+vector2; - try { - throwType = ThrowAtCreate; - vector3[7]=FlexibleThrowerSmall(12); - } catch (...) { - } - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.size(), 10 ); - QCOMPARE( vector3.at(7).value(), 7 ); - QCOMPARE( vector3.size(), 11 ); - - try { - throwType = ThrowAtCreate; - vector.resize(15); - } catch (...) { - } - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.size(), 10 ); - - try { - throwType = ThrowAtCreate; - vector.resize(15); - } catch (...) { - } - QCOMPARE( vector.at(7).value(), 7 ); - QCOMPARE( vector.size(), 10 ); - - try { - throwType = ThrowLater; - vector.fill(FlexibleThrowerSmall(1), 15); - } catch (...) { - } - QCOMPARE( vector.at(0).value(), 0 ); - QCOMPARE( vector.size(), 10 ); - - - } - QCOMPARE(objCounter, 0 ); // check that every object has been freed -} - - -void tst_ExceptionSafety::exceptionMap() { - - { - MyMap map; - MyMap map2; - MyMap map3; - - throwType = ThrowNot; - for (int i = 0; i<10; i++) - map[ FlexibleThrowerSmall(i) ] = FlexibleThrowerSmall(i); - - return; // further test are deactivated until Map is fixed. - - for( int i = ThrowAtCopy; i<=ThrowAtComparison; i++ ) { - try { - throwType = (ThrowType)i; - map[ FlexibleThrowerSmall(10) ] = FlexibleThrowerSmall(10); - } catch(...) { - } - QCOMPARE( map.size(), 10 ); - QCOMPARE( map[ FlexibleThrowerSmall(1) ], FlexibleThrowerSmall(1) ); - } - - map2 = map; - try { - throwType = ThrowLater; - map2[ FlexibleThrowerSmall(10) ] = FlexibleThrowerSmall(10); - } catch(...) { - } - /* qDebug("%d %d", map.size(), map2.size() ); - for( int i=0; i(ThrowEventId)) - { - } -}; - -class NoThrowEvent : public QEvent -{ -public: - NoThrowEvent() - : QEvent(static_cast(NoThrowEventId)) - {} -}; - -struct IntEx : public std::exception -{ - IntEx(int aEx) : ex(aEx) {} - int ex; -}; - -class TestObject : public QObject -{ -public: - TestObject() - : throwEventCount(0), noThrowEventCount(0) {} - - int throwEventCount; - int noThrowEventCount; - -protected: - bool event(QEvent *event) - { - if (int(event->type()) == ThrowEventId) { - throw IntEx(++throwEventCount); - } else if (int(event->type()) == NoThrowEventId) { - ++noThrowEventCount; - } - return QObject::event(event); - } -}; - -void tst_ExceptionSafety::exceptionEventLoop() -{ - // send an event that throws - TestObject obj; - ThrowEvent throwEvent; - try { - qApp->sendEvent(&obj, &throwEvent); - } catch (IntEx code) { - QCOMPARE(code.ex, 1); - } - QCOMPARE(obj.throwEventCount, 1); - - // post an event that throws - qApp->postEvent(&obj, new ThrowEvent); - - try { - qApp->processEvents(); - } catch (IntEx code) { - QCOMPARE(code.ex, 2); - } - QCOMPARE(obj.throwEventCount, 2); - - // post a normal event, then a throwing event, then a normal event - // run this in valgrind to ensure that it doesn't leak. - - qApp->postEvent(&obj, new NoThrowEvent); - qApp->postEvent(&obj, new ThrowEvent); - qApp->postEvent(&obj, new NoThrowEvent); - - try { - qApp->processEvents(); - } catch (IntEx code) { - QCOMPARE(code.ex, 3); - } - // here, we should have received on non-throwing event and one throwing one - QCOMPARE(obj.throwEventCount, 3); - QCOMPARE(obj.noThrowEventCount, 1); - - // spin the event loop again - qApp->processEvents(); - - // now, we should have received the second non-throwing event - QCOMPARE(obj.noThrowEventCount, 2); -} - -void tst_ExceptionSafety::exceptionSignalSlot() -{ - Emitter e; - ExceptionThrower thrower; - Receiver r1; - Receiver r2; - - // connect a signal to a normal object, a thrower and a normal object again - connect(&e, SIGNAL(testSignal()), &r1, SLOT(receiver())); - connect(&e, SIGNAL(testSignal()), &thrower, SLOT(thrower())); - connect(&e, SIGNAL(testSignal()), &r2, SLOT(receiver())); - - int code = 0; - try { - e.emitTestSignal(); - } catch (int c) { - code = c; - } - - // 5 is the magic number that's thrown by thrower - QCOMPARE(code, 5); - - // assumption: slots are called in the connection order - QCOMPARE(r1.received, 1); - QCOMPARE(r2.received, 0); -} -#endif - -#endif - -QTEST_MAIN(tst_ExceptionSafety) -#include "tst_exceptionsafety.moc" diff --git a/tests/auto/exceptionsafety_objects/3rdparty/memcheck.h b/tests/auto/exceptionsafety_objects/3rdparty/memcheck.h deleted file mode 100644 index 72a02ca9ba..0000000000 --- a/tests/auto/exceptionsafety_objects/3rdparty/memcheck.h +++ /dev/null @@ -1,319 +0,0 @@ - -/* - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (memcheck.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of MemCheck, a heavyweight Valgrind tool for - detecting memory errors. - - Copyright (C) 2000-2008 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (memcheck.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - - -#ifndef __MEMCHECK_H -#define __MEMCHECK_H - - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query memory permissions - inside your own programs. - - See comment near the top of valgrind.h on how to use them. -*/ - -#include "valgrind.h" - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef - enum { - VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'), - VG_USERREQ__MAKE_MEM_UNDEFINED, - VG_USERREQ__MAKE_MEM_DEFINED, - VG_USERREQ__DISCARD, - VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE, - VG_USERREQ__CHECK_MEM_IS_DEFINED, - VG_USERREQ__DO_LEAK_CHECK, - VG_USERREQ__COUNT_LEAKS, - - VG_USERREQ__GET_VBITS, - VG_USERREQ__SET_VBITS, - - VG_USERREQ__CREATE_BLOCK, - - VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, - - VG_USERREQ__ENABLE_OOM, - VG_USERREQ__GET_ALLOC_INDEX, - - /* This is just for memcheck's internal use - don't use it */ - _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR - = VG_USERREQ_TOOL_BASE('M','C') + 256, - - /* This is just for memcheck's internal use - don't use it */ - _VG_USERREQ__EXCEPTION - = VG_USERREQ_TOOL_BASE('M','C') + 512, - } Vg_MemCheckClientRequest; - - - -/* Client-code macros to manipulate the state of memory. */ - -/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */ -#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_NOACCESS, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Similarly, mark memory at _qzz_addr as addressable but undefined - for _qzz_len bytes. */ -#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_UNDEFINED, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Similarly, mark memory at _qzz_addr as addressable and defined - for _qzz_len bytes. */ -#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_DEFINED, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is - not altered: bytes which are addressable are marked as defined, - but those which are not addressable are left unchanged. */ -#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Create a block-description handle. The description is an ascii - string which is included in any messages pertaining to addresses - within the specified memory range. Has no other effect on the - properties of the memory range. */ -#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__CREATE_BLOCK, \ - _qzz_addr, _qzz_len, _qzz_desc, \ - 0, 0); \ - _qzz_res; \ - })) - -/* Discard a block-description-handle. Returns 1 for an - invalid handle, 0 for a valid handle. */ -#define VALGRIND_DISCARD(_qzz_blkindex) \ - (__extension__ ({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__DISCARD, \ - 0, _qzz_blkindex, 0, 0, 0); \ - _qzz_res; \ - })) - - -/* Client-code macros to check the state of memory. */ - -/* Check that memory at _qzz_addr is addressable for _qzz_len bytes. - If suitable addressibility is not established, Valgrind prints an - error message and returns the address of the first offending byte. - Otherwise it returns zero. */ -#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,\ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Check that memory at _qzz_addr is addressable and defined for - _qzz_len bytes. If suitable addressibility and definedness are not - established, Valgrind prints an error message and returns the - address of the first offending byte. Otherwise it returns zero. */ -#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CHECK_MEM_IS_DEFINED, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Use this macro to force the definedness and addressibility of an - lvalue to be checked. If suitable addressibility and definedness - are not established, Valgrind prints an error message and returns - the address of the first offending byte. Otherwise it returns - zero. */ -#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \ - VALGRIND_CHECK_MEM_IS_DEFINED( \ - (volatile unsigned char *)&(__lvalue), \ - (unsigned long)(sizeof (__lvalue))) - - -/* Do a memory leak check mid-execution. */ -#define VALGRIND_DO_LEAK_CHECK \ - {unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DO_LEAK_CHECK, \ - 0, 0, 0, 0, 0); \ - } - -/* Just display summaries of leaked memory, rather than all the - details */ -#define VALGRIND_DO_QUICK_LEAK_CHECK \ - {unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DO_LEAK_CHECK, \ - 1, 0, 0, 0, 0); \ - } - -/* Return number of leaked, dubious, reachable and suppressed bytes found by - all previous leak checks. They must be lvalues. */ -#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \ - /* For safety on 64-bit platforms we assign the results to private - unsigned long variables, then assign these to the lvalues the user - specified, which works no matter what type 'leaked', 'dubious', etc - are. We also initialise '_qzz_leaked', etc because - VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as - initialised. */ \ - {unsigned long _qzz_res; \ - unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \ - unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__COUNT_LEAKS, \ - &_qzz_leaked, &_qzz_dubious, \ - &_qzz_reachable, &_qzz_suppressed, 0); \ - leaked = _qzz_leaked; \ - dubious = _qzz_dubious; \ - reachable = _qzz_reachable; \ - suppressed = _qzz_suppressed; \ - } - - -/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it - into the provided zzvbits array. Return values: - 0 if not running on valgrind - 1 success - 2 [previously indicated unaligned arrays; these are now allowed] - 3 if any parts of zzsrc/zzvbits are not addressable. - The metadata is not copied in cases 0, 2 or 3 so it should be - impossible to segfault your system by using this call. -*/ -#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \ - (__extension__({unsigned long _qzz_res; \ - char* czza = (char*)zza; \ - char* czzvbits = (char*)zzvbits; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__GET_VBITS, \ - czza, czzvbits, zznbytes, 0, 0 ); \ - _qzz_res; \ - })) - -/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it - from the provided zzvbits array. Return values: - 0 if not running on valgrind - 1 success - 2 [previously indicated unaligned arrays; these are now allowed] - 3 if any parts of zza/zzvbits are not addressable. - The metadata is not copied in cases 0, 2 or 3 so it should be - impossible to segfault your system by using this call. -*/ -#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \ - (__extension__({unsigned int _qzz_res; \ - char* czza = (char*)zza; \ - char* czzvbits = (char*)zzvbits; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__SET_VBITS, \ - czza, czzvbits, zznbytes, 0, 0 ); \ - _qzz_res; \ - })) - -/* Enable or disable OOM simulation. */ -#define VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(index) \ - (__extension__ ({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__ENABLE_OOM, \ - 1, index, 0, 0, 0); \ - _qzz_res; \ - })) - -#define VALGRIND_DISABLE_OOM_AT_ALLOC_INDEX(index) \ - (__extension__ ({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__ENABLE_OOM, \ - 0, index, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Get the current allocation index. */ -#define VALGRIND_GET_ALLOC_INDEX \ - (__extension__ ({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, -1 /* default return */, \ - VG_USERREQ__GET_ALLOC_INDEX, \ - 0, 0, 0, 0, 0); \ - _qzz_res; \ - })) - - -#endif - diff --git a/tests/auto/exceptionsafety_objects/3rdparty/valgrind.h b/tests/auto/exceptionsafety_objects/3rdparty/valgrind.h deleted file mode 100644 index 577c59ab0c..0000000000 --- a/tests/auto/exceptionsafety_objects/3rdparty/valgrind.h +++ /dev/null @@ -1,3924 +0,0 @@ -/* -*- c -*- - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (valgrind.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2008 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (valgrind.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query Valgrind's - execution inside your own programs. - - The resulting executables will still run without Valgrind, just a - little bit more slowly than they otherwise would, but otherwise - unchanged. When not running on valgrind, each client request - consumes very few (eg. 7) instructions, so the resulting performance - loss is negligible unless you plan to execute client requests - millions of times per second. Nevertheless, if that is still a - problem, you can compile with the NVALGRIND symbol defined (gcc - -DNVALGRIND) so that client requests are not even compiled in. */ - -#ifndef __VALGRIND_H -#define __VALGRIND_H - -#include - -/* Nb: this file might be included in a file compiled with -ansi. So - we can't use C++ style "//" comments nor the "asm" keyword (instead - use "__asm__"). */ - -/* Derive some tags indicating what the target platform is. Note - that in this file we're using the compiler's CPP symbols for - identifying architectures, which are different to the ones we use - within the rest of Valgrind. Note, __powerpc__ is active for both - 32 and 64-bit PPC, whereas __powerpc64__ is only active for the - latter (on Linux, that is). */ -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#if !defined(_AIX) && defined(__i386__) -# define PLAT_x86_linux 1 -#elif !defined(_AIX) && defined(__x86_64__) -# define PLAT_amd64_linux 1 -#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) -# define PLAT_ppc32_linux 1 -#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) -# define PLAT_ppc64_linux 1 -#elif defined(_AIX) && defined(__64BIT__) -# define PLAT_ppc64_aix5 1 -#elif defined(_AIX) && !defined(__64BIT__) -# define PLAT_ppc32_aix5 1 -#endif - - -/* If we're not compiling for our target platform, don't generate - any inline asms. */ -#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \ - && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \ - && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) -# if !defined(NVALGRIND) -# define NVALGRIND 1 -# endif -#endif - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ -/* in here of use to end-users -- skip to the next section. */ -/* ------------------------------------------------------------------ */ - -#if defined(NVALGRIND) - -/* Define NVALGRIND to completely remove the Valgrind magic sequence - from the compiled code (analogous to NDEBUG's effects on - assert()) */ -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { \ - (_zzq_rlval) = (_zzq_default); \ - } - -#else /* ! NVALGRIND */ - -/* The following defines the magic code sequences which the JITter - spots and handles magically. Don't look too closely at them as - they will rot your brain. - - The assembly code sequences for all architectures is in this one - file. This is because this file must be stand-alone, and we don't - want to have multiple files. - - For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default - value gets put in the return slot, so that everything works when - this is executed not under Valgrind. Args are passed in a memory - block, and so there's no intrinsic limit to the number that could - be passed, but it's currently five. - - The macro args are: - _zzq_rlval result lvalue - _zzq_default default value (result returned when running on real CPU) - _zzq_request request code - _zzq_arg1..5 request params - - The other two macros are used to support function wrapping, and are - a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the - guest's NRADDR pseudo-register and whatever other information is - needed to safely run the call original from the wrapper: on - ppc64-linux, the R2 value at the divert point is also needed. This - information is abstracted into a user-visible type, OrigFn. - - VALGRIND_CALL_NOREDIR_* behaves the same as the following on the - guest, but guarantees that the branch instruction will not be - redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: - branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a - complete inline asm, since it needs to be combined with more magic - inline asm stuff to be useful. -*/ - -/* ------------------------- x86-linux ------------------------- */ - -#if defined(PLAT_x86_linux) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "roll $3, %%edi ; roll $13, %%edi\n\t" \ - "roll $29, %%edi ; roll $19, %%edi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EDX = client_request ( %EAX ) */ \ - "xchgl %%ebx,%%ebx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EAX = guest_NRADDR */ \ - "xchgl %%ecx,%%ecx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_EAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%EAX */ \ - "xchgl %%edx,%%edx\n\t" -#endif /* PLAT_x86_linux */ - -/* ------------------------ amd64-linux ------------------------ */ - -#if defined(PLAT_amd64_linux) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ - "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned long long int _zzq_args[6]; \ - volatile unsigned long long int _zzq_result; \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RDX = client_request ( %RAX ) */ \ - "xchgq %%rbx,%%rbx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RAX = guest_NRADDR */ \ - "xchgq %%rcx,%%rcx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_RAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%RAX */ \ - "xchgq %%rdx,%%rdx\n\t" -#endif /* PLAT_amd64_linux */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[6]; \ - unsigned int _zzq_result; \ - unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 3,%1\n\t" /*default*/ \ - "mr 4,%2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" /*result*/ \ - : "=b" (_zzq_result) \ - : "b" (_zzq_default), "b" (_zzq_ptr) \ - : "cc", "memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "cc", "memory", "r3" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[6]; \ - register unsigned long long int _zzq_result __asm__("r3"); \ - register unsigned long long int* _zzq_ptr __asm__("r4"); \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1" \ - : "=r" (_zzq_result) \ - : "0" (_zzq_default), "r" (_zzq_ptr) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr __asm__("r3"); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - unsigned int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[7]; \ - register unsigned int _zzq_result; \ - register unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "lwz 3, 24(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[7]; \ - register unsigned long long int _zzq_result; \ - register unsigned long long int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int long long)(_zzq_request); \ - _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int long long)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "ld 3, 48(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_aix5 */ - -/* Insert assembly code for other platforms here... */ - -#endif /* NVALGRIND */ - - -/* ------------------------------------------------------------------ */ -/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ -/* ugly. It's the least-worst tradeoff I can think of. */ -/* ------------------------------------------------------------------ */ - -/* This section defines magic (a.k.a appalling-hack) macros for doing - guaranteed-no-redirection macros, so as to get from function - wrappers to the functions they are wrapping. The whole point is to - construct standard call sequences, but to do the call itself with a - special no-redirect call pseudo-instruction that the JIT - understands and handles specially. This section is long and - repetitious, and I can't see a way to make it shorter. - - The naming scheme is as follows: - - CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} - - 'W' stands for "word" and 'v' for "void". Hence there are - different macros for calling arity 0, 1, 2, 3, 4, etc, functions, - and for each, the possibility of returning a word-typed result, or - no result. -*/ - -/* Use these to write the name of your wrapper. NOTE: duplicates - VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ - -#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ - _vgwZU_##soname##_##fnname - -#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ - _vgwZZ_##soname##_##fnname - -/* Use this macro from within a wrapper function to collect the - context (address and possibly other info) of the original function. - Once you have that you can then use it in one of the CALL_FN_ - macros. The type of the argument _lval is OrigFn. */ -#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) - -/* Derivatives of the main macros below, for calling functions - returning void. */ - -#define CALL_FN_v_v(fnptr) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_v(_junk,fnptr); } while (0) - -#define CALL_FN_v_W(fnptr, arg1) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_W(_junk,fnptr,arg1); } while (0) - -#define CALL_FN_v_WW(fnptr, arg1,arg2) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) - -#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) - -/* ------------------------- x86-linux ------------------------- */ - -#if defined(PLAT_x86_linux) - -/* These regs are trashed by the hidden call. No need to mention eax - as gcc can already see that, plus causes gcc to bomb. */ -#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" - -/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $4, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $8, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $12, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $20, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $24, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $28, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $36, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $40, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $44, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "pushl 48(%%eax)\n\t" \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_x86_linux */ - -/* ------------------------ amd64-linux ------------------------ */ - -#if defined(PLAT_amd64_linux) - -/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ - "rdi", "r8", "r9", "r10", "r11" - -/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned - long) == 8. */ - -/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ - macros. In order not to trash the stack redzone, we need to drop - %rsp by 128 before the hidden call, and restore afterwards. The - nastyness is that it is only by luck that the stack still appears - to be unwindable during the hidden call - since then the behaviour - of any routine using this macro does not match what the CFI data - says. Sigh. - - Why is this important? Imagine that a wrapper has a stack - allocated local, and passes to the hidden call, a pointer to it. - Because gcc does not know about the hidden call, it may allocate - that local in the redzone. Unfortunately the hidden call may then - trash it before it comes to use it. So we must step clear of the - redzone, for the duration of the hidden call, to make it safe. - - Probably the same problem afflicts the other redzone-style ABIs too - (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is - self describing (none of this CFI nonsense) so at least messing - with the stack pointer doesn't give a danger of non-unwindable - stack. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CALL_NOREDIR_RAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $8, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $16, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $24, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $32, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $40, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 96(%%rax)\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $48, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_amd64_linux */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -/* This is useful for finding out about the on-stack stuff: - - extern int f9 ( int,int,int,int,int,int,int,int,int ); - extern int f10 ( int,int,int,int,int,int,int,int,int,int ); - extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); - extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); - - int g9 ( void ) { - return f9(11,22,33,44,55,66,77,88,99); - } - int g10 ( void ) { - return f10(11,22,33,44,55,66,77,88,99,110); - } - int g11 ( void ) { - return f11(11,22,33,44,55,66,77,88,99,110,121); - } - int g12 ( void ) { - return f12(11,22,33,44,55,66,77,88,99,110,121,132); - } -*/ - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc32-linux, - sizeof(unsigned long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - _argvec[12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,20(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "lwz 3," #_n_fr "(1)\n\t" \ - "stw 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,68(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "ld 3," #_n_fr "(1)\n\t" \ - "std 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_aix5 */ - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ -/* */ -/* ------------------------------------------------------------------ */ - -/* Some request codes. There are many more of these, but most are not - exposed to end-user view. These are the public ones, all of the - form 0x1000 + small_number. - - Core ones are in the range 0x00000000--0x0000ffff. The non-public - ones start at 0x2000. -*/ - -/* These macros are used by tools -- they must be public, but don't - embed them into other programs. */ -#define VG_USERREQ_TOOL_BASE(a,b) \ - ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) -#define VG_IS_TOOL_USERREQ(a, b, v) \ - (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef - enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, - VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, - - /* These allow any function to be called from the simulated - CPU but run on the real CPU. Nb: the first arg passed to - the function is always the ThreadId of the running - thread! So CLIENT_CALL0 actually requires a 1 arg - function, etc. */ - VG_USERREQ__CLIENT_CALL0 = 0x1101, - VG_USERREQ__CLIENT_CALL1 = 0x1102, - VG_USERREQ__CLIENT_CALL2 = 0x1103, - VG_USERREQ__CLIENT_CALL3 = 0x1104, - - /* Can be useful in regression testing suites -- eg. can - send Valgrind's output to /dev/null and still count - errors. */ - VG_USERREQ__COUNT_ERRORS = 0x1201, - - /* These are useful and can be interpreted by any tool that - tracks malloc() et al, by using vg_replace_malloc.c. */ - VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, - VG_USERREQ__FREELIKE_BLOCK = 0x1302, - /* Memory pool support. */ - VG_USERREQ__CREATE_MEMPOOL = 0x1303, - VG_USERREQ__DESTROY_MEMPOOL = 0x1304, - VG_USERREQ__MEMPOOL_ALLOC = 0x1305, - VG_USERREQ__MEMPOOL_FREE = 0x1306, - VG_USERREQ__MEMPOOL_TRIM = 0x1307, - VG_USERREQ__MOVE_MEMPOOL = 0x1308, - VG_USERREQ__MEMPOOL_CHANGE = 0x1309, - VG_USERREQ__MEMPOOL_EXISTS = 0x130a, - - /* Allow printfs to valgrind log. */ - VG_USERREQ__PRINTF = 0x1401, - VG_USERREQ__PRINTF_BACKTRACE = 0x1402, - - /* Stack support. */ - VG_USERREQ__STACK_REGISTER = 0x1501, - VG_USERREQ__STACK_DEREGISTER = 0x1502, - VG_USERREQ__STACK_CHANGE = 0x1503 - } Vg_ClientRequest; - -#if !defined(__GNUC__) -# define __extension__ /* */ -#endif - -/* Returns the number of Valgrinds this code is running under. That - is, 0 if running natively, 1 if running under Valgrind, 2 if - running under Valgrind which is running under another Valgrind, - etc. */ -#define RUNNING_ON_VALGRIND __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ - VG_USERREQ__RUNNING_ON_VALGRIND, \ - 0, 0, 0, 0, 0); \ - _qzz_res; \ - }) - - -/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + - _qzz_len - 1]. Useful if you are debugging a JITter or some such, - since it provides a way to make sure valgrind will retranslate the - invalidated area. Returns no value. */ -#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DISCARD_TRANSLATIONS, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - } - - -/* These requests are for getting Valgrind itself to print something. - Possibly with a backtrace. This is a really ugly hack. */ - -#if defined(NVALGRIND) - -# define VALGRIND_PRINTF(...) -# define VALGRIND_PRINTF_BACKTRACE(...) - -#else /* NVALGRIND */ - -/* Modern GCC will optimize the static routine out if unused, - and unused attribute will shut down warnings about it. */ -static int VALGRIND_PRINTF(const char *format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -static int -VALGRIND_PRINTF(const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, - (unsigned long)format, (unsigned long)vargs, - 0, 0, 0); - va_end(vargs); - return (int)_qzz_res; -} - -static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -static int -VALGRIND_PRINTF_BACKTRACE(const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, - (unsigned long)format, (unsigned long)vargs, - 0, 0, 0); - va_end(vargs); - return (int)_qzz_res; -} - -#endif /* NVALGRIND */ - - -/* These requests allow control to move from the simulated CPU to the - real CPU, calling an arbitary function. - - Note that the current ThreadId is inserted as the first argument. - So this call: - - VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) - - requires f to have this signature: - - Word f(Word tid, Word arg1, Word arg2) - - where "Word" is a word-sized type. - - Note that these client requests are not entirely reliable. For example, - if you call a function with them that subsequently calls printf(), - there's a high chance Valgrind will crash. Generally, your prospects of - these working are made higher if the called function does not refer to - any global variables, and does not refer to any libc or other functions - (printf et al). Any kind of entanglement with libc or dynamic linking is - likely to have a bad outcome, for tricky reasons which we've grappled - with a lot in the past. -*/ -#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL0, \ - _qyy_fn, \ - 0, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL1, \ - _qyy_fn, \ - _qyy_arg1, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL2, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL3, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, \ - _qyy_arg3, 0); \ - _qyy_res; \ - }) - - -/* Counts the number of errors that have been recorded by a tool. Nb: - the tool must record the errors with VG_(maybe_record_error)() or - VG_(unique_error)() for them to be counted. */ -#define VALGRIND_COUNT_ERRORS \ - __extension__ \ - ({unsigned int _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__COUNT_ERRORS, \ - 0, 0, 0, 0, 0); \ - _qyy_res; \ - }) - -/* Mark a block of memory as having been allocated by a malloc()-like - function. `addr' is the start of the usable block (ie. after any - redzone) `rzB' is redzone size if the allocator can apply redzones; - use '0' if not. Adding redzones makes it more likely Valgrind will spot - block overruns. `is_zeroed' indicates if the memory is zeroed, as it is - for calloc(). Put it immediately after the point where a block is - allocated. - - If you're using Memcheck: If you're allocating memory via superblocks, - and then handing out small chunks of each superblock, if you don't have - redzones on your small blocks, it's worth marking the superblock with - VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are - detected. But if you can put redzones on, it's probably better to not do - this, so that messages for small overruns are described in terms of the - small block rather than the superblock (but if you have a big overrun - that skips over a redzone, you could miss an error this way). See - memcheck/tests/custom_alloc.c for an example. - - WARNING: if your allocator uses malloc() or 'new' to allocate - superblocks, rather than mmap() or brk(), this will not work properly -- - you'll likely get assertion failures during leak detection. This is - because Valgrind doesn't like seeing overlapping heap blocks. Sorry. - - Nb: block must be freed via a free()-like function specified - with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MALLOCLIKE_BLOCK, \ - addr, sizeB, rzB, is_zeroed, 0); \ - } - -/* Mark a block of memory as having been freed by a free()-like function. - `rzB' is redzone size; it must match that given to - VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak - checker. Put it immediately after the point where the block is freed. */ -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__FREELIKE_BLOCK, \ - addr, rzB, 0, 0, 0); \ - } - -/* Create a memory pool. */ -#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CREATE_MEMPOOL, \ - pool, rzB, is_zeroed, 0, 0); \ - } - -/* Destroy a memory pool. */ -#define VALGRIND_DESTROY_MEMPOOL(pool) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DESTROY_MEMPOOL, \ - pool, 0, 0, 0, 0); \ - } - -/* Associate a piece of memory with a memory pool. */ -#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_ALLOC, \ - pool, addr, size, 0, 0); \ - } - -/* Disassociate a piece of memory from a memory pool. */ -#define VALGRIND_MEMPOOL_FREE(pool, addr) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_FREE, \ - pool, addr, 0, 0, 0); \ - } - -/* Disassociate any pieces outside a particular range. */ -#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_TRIM, \ - pool, addr, size, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MOVE_MEMPOOL, \ - poolA, poolB, 0, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_CHANGE, \ - pool, addrA, addrB, size, 0); \ - } - -/* Return 1 if a mempool exists, else 0. */ -#define VALGRIND_MEMPOOL_EXISTS(pool) \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_EXISTS, \ - pool, 0, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Mark a piece of memory as being a stack. Returns a stack id. */ -#define VALGRIND_STACK_REGISTER(start, end) \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_REGISTER, \ - start, end, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Unmark the piece of memory associated with a stack id as being a - stack. */ -#define VALGRIND_STACK_DEREGISTER(id) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_DEREGISTER, \ - id, 0, 0, 0, 0); \ - } - -/* Change the start and end address of the stack id. */ -#define VALGRIND_STACK_CHANGE(id, start, end) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_CHANGE, \ - id, start, end, 0, 0); \ - } - - -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#endif /* __VALGRIND_H */ diff --git a/tests/auto/exceptionsafety_objects/exceptionsafety_objects.pro b/tests/auto/exceptionsafety_objects/exceptionsafety_objects.pro deleted file mode 100644 index d09c349215..0000000000 --- a/tests/auto/exceptionsafety_objects/exceptionsafety_objects.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -HEADERS += oomsimulator.h 3rdparty/valgrind.h 3rdparty/memcheck.h -SOURCES += tst_exceptionsafety_objects.cpp - -CONFIG+=insignificant_test diff --git a/tests/auto/exceptionsafety_objects/oomsimulator.h b/tests/auto/exceptionsafety_objects/oomsimulator.h deleted file mode 100644 index ed4bb53922..0000000000 --- a/tests/auto/exceptionsafety_objects/oomsimulator.h +++ /dev/null @@ -1,283 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#if !defined(Q_OS_WIN) -# include "3rdparty/memcheck.h" -#endif - -static bool mallocFailActive = false; -static int mallocFailIndex = 0; -static int mallocCount = 0; - -static void my_terminate_handler() -{ - // set a breakpoint here to get a backtrace for your uncaught exceptions - fprintf(stderr, "Uncaught Exception Detected. Set a breakpoint in my_terminate_handler()\n"); - exit(1); -} - -#ifdef __GLIBC__ -/* Use glibc's memory allocation hooks */ - -// From glibc 2.14, the malloc hook variables are declared volatile. -// Note: The malloc hook implementation is marked as deprecated. - -#if !defined(__MALLOC_HOOK_VOLATILE) -# define __MALLOC_HOOK_VOLATILE -#endif - -/* our hooks */ -static void *my_malloc_hook(size_t, const void *); -static void *my_realloc_hook(void *, size_t, const void *); -static void *my_memalign_hook(size_t, size_t, const void *); -static void my_free_hook(void *, const void *); - -/* original hooks. */ -static void *(*__MALLOC_HOOK_VOLATILE old_malloc_hook)(size_t, const void *); -static void *(*__MALLOC_HOOK_VOLATILE old_realloc_hook)(void *, size_t, const void *); -static void *(*__MALLOC_HOOK_VOLATILE old_memalign_hook)(size_t, size_t, const void *); -static void (*__MALLOC_HOOK_VOLATILE old_free_hook)(void *, const void *); - -/* initializer function */ -static void my_init_hook(); - -/* Override initialising hook from the C library. */ - -void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook; - -static void disableHooks() -{ - __malloc_hook = old_malloc_hook; - __realloc_hook = old_realloc_hook; - __memalign_hook = old_memalign_hook; - __free_hook = old_free_hook; -} - -static void enableHooks() -{ - __malloc_hook = my_malloc_hook; - __realloc_hook = my_realloc_hook; - __memalign_hook = my_memalign_hook; - __free_hook = my_free_hook; -} - -void my_init_hook() -{ - old_malloc_hook = __malloc_hook; - old_realloc_hook = __realloc_hook; - old_memalign_hook = __memalign_hook; - old_free_hook = __free_hook; - enableHooks(); -} - -void *my_malloc_hook(size_t size, const void *) -{ - ++mallocCount; - - if (mallocFailActive && --mallocFailIndex < 0) - return 0; // simulate OOM - - __malloc_hook = old_malloc_hook; - void *result = ::malloc (size); - __malloc_hook = my_malloc_hook; - - return result; -} - -void *my_memalign_hook(size_t alignment, size_t size, const void *) -{ - ++mallocCount; - - if (mallocFailActive && --mallocFailIndex < 0) - return 0; // simulate OOM - - __memalign_hook = old_memalign_hook; - void *result = ::memalign(alignment, size); - __memalign_hook = my_memalign_hook; - - return result; -} - -void *my_realloc_hook(void *ptr, size_t size, const void *) -{ - ++mallocCount; - - if (mallocFailActive && --mallocFailIndex < 0) - return 0; // simulate OOM - - __realloc_hook = old_realloc_hook; - __malloc_hook = old_malloc_hook; - void *result = ::realloc(ptr, size); - __malloc_hook = my_malloc_hook; - __realloc_hook = my_realloc_hook; - - return result; -} - -void my_free_hook(void *ptr, const void *) -{ - __free_hook = old_free_hook; - ::free(ptr); - __free_hook = my_free_hook; -} - -#elif defined(Q_CC_MSVC) - -#include "crtdbg.h" - -static int qCrtAllocHook(int allocType, void * /*userData*/, size_t /*size*/, - int blockType, long /*requestNumber*/, - const unsigned char * /*filename*/, int /*lineNumber*/) -{ - if (blockType == _CRT_BLOCK) - return TRUE; // ignore allocations from the C library - - switch (allocType) { - case _HOOK_ALLOC: - case _HOOK_REALLOC: - ++mallocCount; - if (mallocFailActive && --mallocFailIndex < 0) - return FALSE; // simulate OOM - } - - return TRUE; -} - -static struct QCrtDebugRegistrator -{ - QCrtDebugRegistrator() - { - _CrtSetAllocHook(qCrtAllocHook); - } - -} crtDebugRegistrator; - -#endif - -struct AllocFailer -{ - inline AllocFailer(int index) { reactivateAt(index); } - inline ~AllocFailer() { deactivate(); } - - inline void reactivateAt(int index) - { -#ifdef RUNNING_ON_VALGRIND - if (RUNNING_ON_VALGRIND) - VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(VALGRIND_GET_ALLOC_INDEX + index + 1); -#endif - mallocFailIndex = index; - mallocFailActive = true; - } - - inline void deactivate() - { - mallocFailActive = false; -#ifdef RUNNING_ON_VALGRIND - VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(0); -#endif - } - - inline int currentAllocIndex() const - { -#ifdef RUNNING_ON_VALGRIND - if (RUNNING_ON_VALGRIND) - return VALGRIND_GET_ALLOC_INDEX; -#endif - return mallocCount; - } - - static bool initialize() - { - std::set_terminate(my_terminate_handler); -#ifdef RUNNING_ON_VALGRIND - if (RUNNING_ON_VALGRIND) { - if (VALGRIND_GET_ALLOC_INDEX == -1u) { - qWarning("You must use a valgrind with oom simulation support"); - return false; - } - // running in valgrind - don't use glibc hooks - disableHooks(); - - // never stop simulating OOM - VALGRIND_DISABLE_OOM_AT_ALLOC_INDEX(-1u); - } -#endif - return true; - } -}; - -static void *new_helper(std::size_t size) -{ - void *ptr = malloc(size); - if (!ptr) - throw std::bad_alloc(); - return ptr; -} - -#ifdef Q_CC_MSVC -# pragma warning(push) -# pragma warning(disable: 4290) -#endif - -// overload operator new -void* operator new(size_t size) throw (std::bad_alloc) { return new_helper(size); } -void* operator new[](size_t size) throw (std::bad_alloc) { return new_helper(size); } -void* operator new(size_t size, const std::nothrow_t&) throw() { return malloc(size); } -void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc(size); } - -// overload operator delete -void operator delete(void *ptr) throw() { if (ptr) free(ptr); } -void operator delete[](void *ptr) throw() { if (ptr) free(ptr); } -void operator delete(void *ptr, const std::nothrow_t&) throw() { if (ptr) free(ptr); } -void operator delete[](void *ptr, const std::nothrow_t&) throw() { if (ptr) free (ptr); } - -#ifdef Q_CC_MSVC -# pragma warning(pop) -#endif - -// ignore placement new and placement delete - those don't allocate. - - diff --git a/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp b/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp deleted file mode 100644 index 0d410a79a2..0000000000 --- a/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#include -#include - -QT_USE_NAMESPACE - -// this test only works with GLIBC - -#include "oomsimulator.h" -#include "3rdparty/memcheck.h" - -class tst_ExceptionSafety_Objects: public QObject -{ - Q_OBJECT - -public slots: - void initTestCase(); -#ifndef QT_NO_EXCEPTIONS - void cleanupTestCase(); - -private slots: - void objects_data(); - void objects(); - - void widgets_data(); - void widgets(); - - void vector_data(); - void vector(); - - void list_data(); - void list(); - - void linkedList_data(); - void linkedList(); - -private: - static QtMsgHandler testMessageHandler; - static void safeMessageHandler(QtMsgType, const char *); -#endif -}; - -#ifdef QT_NO_EXCEPTIONS -void tst_ExceptionSafety_Objects::initTestCase() -{ - QSKIP("This test requires exception support", SkipAll); -} - -#else -// helper structs to create an arbitrary widget -struct AbstractTester -{ - virtual void operator()(QObject *parent) = 0; -}; -Q_DECLARE_METATYPE(AbstractTester *) - -typedef void (*TestFunction)(QObject*); -Q_DECLARE_METATYPE(TestFunction) - -template -struct ObjectCreator : public AbstractTester -{ - void operator()(QObject *) - { - QScopedPointer ptr(new T); - } -}; - -struct BitArrayCreator : public AbstractTester -{ - void operator()(QObject *) - { QScopedPointer bitArray(new QBitArray(100, true)); } -}; - -struct ByteArrayMatcherCreator : public AbstractTester -{ - void operator()(QObject *) - { QScopedPointer ptr(new QByteArrayMatcher("ralf test",8)); } -}; - -struct CryptographicHashCreator : public AbstractTester -{ - void operator()(QObject *) - { - QScopedPointer ptr(new QCryptographicHash(QCryptographicHash::Sha1)); - ptr->addData("ralf test",8); - } -}; - -struct DataStreamCreator : public AbstractTester -{ - void operator()(QObject *) - { - QScopedPointer arr(new QByteArray("hallo, test")); - QScopedPointer ptr(new QDataStream(arr.data(), QIODevice::ReadWrite)); - ptr->writeBytes("ralf test",8); - } -}; - -struct DirCreator : public AbstractTester -{ - void operator()(QObject *) - { - QDir::cleanPath("../////././"); - QScopedPointer ptr(new QDir(".")); - while( ptr->cdUp() ) - ; // just going up - ptr->count(); - ptr->exists(ptr->path()); - - QStringList filters; - filters << "*.cpp" << "*.cxx" << "*.cc"; - ptr->setNameFilters(filters); - } -}; - -void tst_ExceptionSafety_Objects::objects_data() -{ - QTest::addColumn("objectCreator"); - -#define NEWROW(T) QTest::newRow(#T) << static_cast(new ObjectCreator) - NEWROW(QObject); - NEWROW(QBuffer); - NEWROW(QFile); - NEWROW(QFSFileEngine); - NEWROW(QProcess); - NEWROW(QSettings); - NEWROW(QThread); - NEWROW(QThreadPool); - NEWROW(QTranslator); - -#define NEWROW2(T, CREATOR) QTest::newRow(#T) << static_cast(new CREATOR) - NEWROW2(QBitArray, BitArrayCreator); - NEWROW2(QByteArrayMatcher, ByteArrayMatcherCreator); - NEWROW2(QCryptographicHash, CryptographicHashCreator); - NEWROW2(QDataStream, DataStreamCreator); - NEWROW2(QDir, DirCreator); -} - -// create and destructs an object, and lets each and every allocation -// during construction and destruction fail. -template -static void doOOMTest(T &testFunc, QObject *parent, int start=0) -{ - int currentOOMIndex = start; - bool caught = false; - bool done = false; - - AllocFailer allocFailer(0); - int allocCountBefore = allocFailer.currentAllocIndex(); - - do { - allocFailer.reactivateAt(++currentOOMIndex); - - caught = false; - - try { - testFunc(parent); - } catch (const std::bad_alloc &) { - caught = true; - } catch (const std::exception &ex) { - if (strcmp(ex.what(), "autotest swallow") != 0) - throw; - caught = true; - } - - if (!caught) { - void *buf = malloc(42); - if (buf) { - // we got memory here - oom test is over. - free(buf); - done = true; - } - } - - // if we get a FAIL, stop executing now - if (QTest::currentTestFailed()) - done = true; - -//#define REALLY_VERBOSE -#ifdef REALLY_VERBOSE - fprintf(stderr, " OOM Index: %d\n", currentOOMIndex); -#endif - - - } while (caught || !done); - - allocFailer.deactivate(); - -//#define VERBOSE -#ifdef VERBOSE - fprintf(stderr, "OOM Test done, checked allocs: %d (range %d - %d)\n", currentOOMIndex, - allocCountBefore, allocFailer.currentAllocIndex()); -#else - Q_UNUSED(allocCountBefore); -#endif -} - -static int alloc1Failed = 0; -static int alloc2Failed = 0; -static int alloc3Failed = 0; -static int alloc4Failed = 0; -static int malloc1Failed = 0; -static int malloc2Failed = 0; - -// Tests that new, new[] and malloc() fail at least once during OOM testing. -class SelfTestObject : public QObject -{ -public: - SelfTestObject(QObject *parent = 0) - : QObject(parent) - { - try { delete new int; } catch (const std::bad_alloc &) { ++alloc1Failed; throw; } - try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc2Failed; throw ;} - void *buf = malloc(42); - if (buf) - free(buf); - else - ++malloc1Failed; - } - - ~SelfTestObject() - { - try { delete new int; } catch (const std::bad_alloc &) { ++alloc3Failed; } - try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc4Failed; } - void *buf = malloc(42); - if (buf) - free(buf); - else - ++malloc2Failed = true; - } -}; - -QtMsgHandler tst_ExceptionSafety_Objects::testMessageHandler; - -void tst_ExceptionSafety_Objects::safeMessageHandler(QtMsgType type, const char *msg) -{ - // this temporarily suspends OOM testing while handling a message - int currentIndex = mallocFailIndex; - AllocFailer allocFailer(0); - allocFailer.deactivate(); - (*testMessageHandler)(type, msg); - allocFailer.reactivateAt(currentIndex); -} - -typedef void (*PVF)(); -PVF defaultTerminate; -void debugTerminate() -{ - // you can detect uncaught exceptions with a breakpoint in here - (*defaultTerminate)(); -} - -PVF defaultUnexpected; -void debugUnexpected() -{ - // you can detect unexpected exceptions with a breakpoint in here - (*defaultUnexpected)(); -} - -void tst_ExceptionSafety_Objects::initTestCase() -{ - // set handlers for bad exception cases, you might want to step in and breakpoint the default handlers too - defaultTerminate = std::set_terminate(&debugTerminate); - defaultUnexpected = std::set_unexpected(&debugUnexpected); - testMessageHandler = qInstallMsgHandler(safeMessageHandler); - - QVERIFY(AllocFailer::initialize()); - - // sanity check whether OOM simulation works - AllocFailer allocFailer(0); - - // malloc fail index is 0 -> this malloc should fail. - void *buf = malloc(42); - allocFailer.deactivate(); - QVERIFY(!buf); - - // malloc fail index is 1 - second malloc should fail. - allocFailer.reactivateAt(1); - buf = malloc(42); - void *buf2 = malloc(42); - allocFailer.deactivate(); - - QVERIFY(buf); - free(buf); - QVERIFY(!buf2); - - ObjectCreator *selfTest = new ObjectCreator; - doOOMTest(*selfTest, 0); - delete selfTest; - QCOMPARE(alloc1Failed, 1); - QCOMPARE(alloc2Failed, 1); - QCOMPARE(alloc3Failed, 2); - QCOMPARE(alloc4Failed, 3); - QCOMPARE(malloc1Failed, 1); - QCOMPARE(malloc2Failed, 1); -} - -void tst_ExceptionSafety_Objects::cleanupTestCase() -{ - qInstallMsgHandler(testMessageHandler); -} - -void tst_ExceptionSafety_Objects::objects() -{ - QLatin1String tag = QLatin1String(QTest::currentDataTag()); - if (tag == QLatin1String("QFile") - || tag == QLatin1String("QProcess") - || tag == QLatin1String("QSettings") - || tag == QLatin1String("QThread") - || tag == QLatin1String("QThreadPool")) - QSKIP("This type of object is not currently strongly exception safe", SkipSingle); - - QFETCH(AbstractTester *, objectCreator); - - doOOMTest(*objectCreator, 0); - - delete objectCreator; -} - -template -struct WidgetCreator : public AbstractTester -{ - void operator()(QObject *parent) - { - if (parent && !parent->isWidgetType()) - qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO); - QScopedPointer ptr(parent ? new T(static_cast(parent)) : new T); - } -}; - -// QSizeGrip doesn't have a default constructor - always pass parent (even though it might be 0) -template <> struct WidgetCreator : public AbstractTester -{ - void operator()(QObject *parent) - { - if (parent && !parent->isWidgetType()) - qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO); - QScopedPointer ptr(new QSizeGrip(static_cast(parent))); - } -}; - -// QDesktopWidget doesn't need a parent. -template <> struct WidgetCreator : public AbstractTester -{ - void operator()(QObject *parent) - { - if (parent && !parent->isWidgetType()) - qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO); - QScopedPointer ptr(new QDesktopWidget()); - } -}; -void tst_ExceptionSafety_Objects::widgets_data() -{ - QTest::addColumn("widgetCreator"); - -#undef NEWROW -#define NEWROW(T) QTest::newRow(#T) << static_cast(new WidgetCreator) - - NEWROW(QWidget); - - NEWROW(QButtonGroup); - NEWROW(QCheckBox); - NEWROW(QColumnView); - NEWROW(QComboBox); - NEWROW(QCommandLinkButton); - NEWROW(QDateEdit); - NEWROW(QDateTimeEdit); - NEWROW(QDesktopWidget); - NEWROW(QDial); - NEWROW(QDoubleSpinBox); - NEWROW(QFocusFrame); - NEWROW(QFontComboBox); - NEWROW(QFrame); - NEWROW(QGroupBox); - NEWROW(QLabel); - NEWROW(QLCDNumber); - NEWROW(QLineEdit); - NEWROW(QListView); - NEWROW(QListWidget); - NEWROW(QMainWindow); - NEWROW(QMenu); - NEWROW(QMenuBar); - NEWROW(QPlainTextEdit); - NEWROW(QProgressBar); - NEWROW(QPushButton); - NEWROW(QRadioButton); - NEWROW(QScrollArea); - NEWROW(QScrollBar); - NEWROW(QSizeGrip); - NEWROW(QSlider); - NEWROW(QSpinBox); - NEWROW(QSplitter); - NEWROW(QStackedWidget); - NEWROW(QStatusBar); - NEWROW(QTabBar); - NEWROW(QTableView); - NEWROW(QTableWidget); - NEWROW(QTabWidget); - NEWROW(QTextBrowser); - NEWROW(QTextEdit); - NEWROW(QTimeEdit); - NEWROW(QToolBar); - NEWROW(QToolBox); - NEWROW(QToolButton); - NEWROW(QTreeView); - NEWROW(QTreeWidget); - NEWROW(QWorkspace); -} - -void tst_ExceptionSafety_Objects::widgets() -{ - QLatin1String tag = QLatin1String(QTest::currentDataTag()); - if (tag == QLatin1String("QColumnView") - || tag == QLatin1String("QComboBox") - || tag == QLatin1String("QCommandLinkButton") - || tag == QLatin1String("QDateEdit") - || tag == QLatin1String("QDateTimeEdit") - || tag == QLatin1String("QDesktopWidget") - || tag == QLatin1String("QDoubleSpinBox") - || tag == QLatin1String("QFontComboBox") - || tag == QLatin1String("QGroupBox") - || tag == QLatin1String("QLineEdit") - || tag == QLatin1String("QListView") - || tag == QLatin1String("QListWidget") - || tag == QLatin1String("QMainWindow") - || tag == QLatin1String("QMenu") - || tag == QLatin1String("QMenuBar") - || tag == QLatin1String("QPlainTextEdit") - || tag == QLatin1String("QProgressBar") - || tag == QLatin1String("QPushButton") - || tag == QLatin1String("QScrollArea") - || tag == QLatin1String("QSpinBox") - || tag == QLatin1String("QStackedWidget") - || tag == QLatin1String("QStatusBar") - || tag == QLatin1String("QTableView") - || tag == QLatin1String("QTableWidget") - || tag == QLatin1String("QTabWidget") - || tag == QLatin1String("QTextBrowser") - || tag == QLatin1String("QTextEdit") - || tag == QLatin1String("QTimeEdit") - || tag == QLatin1String("QToolBar") - || tag == QLatin1String("QToolBox") - || tag == QLatin1String("QTreeView") - || tag == QLatin1String("QTreeWidget") - || tag == QLatin1String("QWorkspace")) - QSKIP("This type of widget is not currently strongly exception safe", SkipSingle); - - QFETCH(AbstractTester *, widgetCreator); - - doOOMTest(*widgetCreator, 0, 00000); - - QWidget parent; - doOOMTest(*widgetCreator, &parent, 00000); - - delete widgetCreator; - - // if the test reaches here without crashing, we passed :) - QVERIFY(true); -} - -struct Integer -{ - Integer(int value = 42) - : ptr(new int(value)) - { - ++instanceCount; - } - - Integer(const Integer &other) - : ptr(new int(*other.ptr)) - { - ++instanceCount; - } - - Integer &operator=(const Integer &other) - { - int *newPtr = new int(*other.ptr); - delete ptr; - ptr = newPtr; - return *this; - } - - ~Integer() - { - --instanceCount; - delete ptr; - } - - int value() const - { - return *ptr; - } - - int *ptr; - static int instanceCount; -}; - -int Integer::instanceCount = 0; - -struct IntegerMoveable - { - IntegerMoveable(int value = 42) - : val(value) - { - delete new int; - ++instanceCount; - } - - IntegerMoveable(const IntegerMoveable &other) - : val(other.val) - { - delete new int; - ++instanceCount; - } - - IntegerMoveable &operator=(const IntegerMoveable &other) - { - delete new int; - val = other.val; - return *this; - } - - ~IntegerMoveable() - { - --instanceCount; - } - - int value() const - { - return val; - } - - int val; - static int instanceCount; - }; - -int IntegerMoveable::instanceCount = 0; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(IntegerMoveable, Q_MOVABLE_TYPE); -QT_END_NAMESPACE - -template class Container> -void containerInsertTest(QObject*) -{ - Container container; - - // insert an item in an empty container - try { - container.insert(container.begin(), 41); - } catch (...) { - QVERIFY(container.isEmpty()); - QCOMPARE(T::instanceCount, 0); - return; - } - - QCOMPARE(container.size(), 1); - QCOMPARE(T::instanceCount, 1); - - // insert an item before another item - try { - container.insert(container.begin(), 42); - } catch (...) { - QCOMPARE(container.size(), 1); - QCOMPARE(container.first().value(), 41); - QCOMPARE(T::instanceCount, 1); - return; - } - - QCOMPARE(T::instanceCount, 2); - - // insert an item in between - try { - container.insert(container.begin() + 1, 43); - } catch (...) { - QCOMPARE(container.size(), 2); - QCOMPARE(container.first().value(), 41); - QCOMPARE((container.begin() + 1)->value(), 42); - QCOMPARE(T::instanceCount, 2); - return; - } - - QCOMPARE(T::instanceCount, 3); -} - -template class Container> -void containerAppendTest(QObject*) -{ - Container container; - - // append to an empty container - try { - container.append(42); - } catch (...) { - QCOMPARE(container.size(), 0); - QCOMPARE(T::instanceCount, 0); - return; - } - - // append to a container with one item - try { - container.append(43); - } catch (...) { - QCOMPARE(container.size(), 1); - QCOMPARE(container.first().value(), 42); - QCOMPARE(T::instanceCount, 1); - return; - } - - Container container2; - - try { - container2.append(44); - } catch (...) { - // don't care - return; - } - QCOMPARE(T::instanceCount, 3); - - // append another container with one item - try { - container += container2; - } catch (...) { - QCOMPARE(container.size(), 2); - QCOMPARE(container.first().value(), 42); - QCOMPARE((container.begin() + 1)->value(), 43); - QCOMPARE(T::instanceCount, 3); - return; - } - - QCOMPARE(T::instanceCount, 4); -} - -template class Container> -void containerEraseTest(QObject*) -{ - Container container; - - try { - container.append(42); - container.append(43); - container.append(44); - container.append(45); - container.append(46); - } catch (...) { - // don't care - return; - } - - // sanity checks - QCOMPARE(container.size(), 5); - QCOMPARE(T::instanceCount, 5); - - // delete the first one - try { - container.erase(container.begin()); - } catch (...) { - QCOMPARE(container.size(), 5); - QCOMPARE(container.first().value(), 42); - QCOMPARE(T::instanceCount, 5); - return; - } - - QCOMPARE(container.size(), 4); - QCOMPARE(container.first().value(), 43); - QCOMPARE(T::instanceCount, 4); - - // delete the last one - try { - container.erase(container.end() - 1); - } catch (...) { - QCOMPARE(container.size(), 4); - QCOMPARE(T::instanceCount, 4); - return; - } - - QCOMPARE(container.size(), 3); - QCOMPARE(container.first().value(), 43); - QCOMPARE((container.begin() + 1)->value(), 44); - QCOMPARE((container.begin() + 2)->value(), 45); - QCOMPARE(T::instanceCount, 3); - - // delete the middle one - try { - container.erase(container.begin() + 1); - } catch (...) { - QCOMPARE(container.size(), 3); - QCOMPARE(container.first().value(), 43); - QCOMPARE((container.begin() + 1)->value(), 44); - QCOMPARE((container.begin() + 2)->value(), 45); - QCOMPARE(T::instanceCount, 3); - return; - } - - QCOMPARE(container.size(), 2); - QCOMPARE(container.first().value(), 43); - QCOMPARE((container.begin() + 1)->value(), 45); - QCOMPARE(T::instanceCount, 2); -} - -template class Container> -static void containerData() -{ - QTest::addColumn("testFunction"); - - QTest::newRow("insert static") << static_cast(containerInsertTest); - QTest::newRow("append static") << static_cast(containerAppendTest); - QTest::newRow("erase static") << static_cast(containerEraseTest); - QTest::newRow("insert moveable") << static_cast(containerInsertTest); - QTest::newRow("append moveable") << static_cast(containerAppendTest); - QTest::newRow("erase moveable") << static_cast(containerEraseTest); -} - -void tst_ExceptionSafety_Objects::vector_data() -{ - containerData(); -} - -void tst_ExceptionSafety_Objects::vector() -{ - QFETCH(TestFunction, testFunction); - - if (QLatin1String(QTest::currentDataTag()) == QLatin1String("insert static") - || QLatin1String(QTest::currentDataTag()) == QLatin1String("insert moveable")) - QSKIP("QVector::insert is currently not strongly exception safe", SkipSingle); - - doOOMTest(testFunction, 0); -} - -void tst_ExceptionSafety_Objects::list_data() -{ - containerData(); -} - -void tst_ExceptionSafety_Objects::list() -{ - QFETCH(TestFunction, testFunction); - - doOOMTest(testFunction, 0); -} - -void tst_ExceptionSafety_Objects::linkedList_data() -{ - containerData(); -} - -void tst_ExceptionSafety_Objects::linkedList() -{ - QFETCH(TestFunction, testFunction); - - doOOMTest(testFunction, 0); -} - -#endif - -QTEST_MAIN(tst_ExceptionSafety_Objects) -#include "tst_exceptionsafety_objects.moc" diff --git a/tests/auto/gestures/gestures.pro b/tests/auto/gestures/gestures.pro deleted file mode 100644 index 43ae4a3fa1..0000000000 --- a/tests/auto/gestures/gestures.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_gestures.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp deleted file mode 100644 index 63345fbe88..0000000000 --- a/tests/auto/gestures/tst_gestures.cpp +++ /dev/null @@ -1,2345 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -//TESTED_CLASS= -//TESTED_FILES= - -static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view) -{ - return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt))); -} - -class CustomGesture : public QGesture -{ - Q_OBJECT -public: - static Qt::GestureType GestureType; - - CustomGesture(QObject *parent = 0) - : QGesture(parent), serial(0) - { - } - - int serial; - - static const int SerialMaybeThreshold; - static const int SerialStartedThreshold; - static const int SerialFinishedThreshold; -}; -Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture; -const int CustomGesture::SerialMaybeThreshold = 1; -const int CustomGesture::SerialStartedThreshold = 3; -const int CustomGesture::SerialFinishedThreshold = 6; - -class CustomEvent : public QEvent -{ -public: - static int EventType; - - CustomEvent(int serial_ = 0) - : QEvent(QEvent::Type(CustomEvent::EventType)), - serial(serial_), hasHotSpot(false) - { - } - - int serial; - QPointF hotSpot; - bool hasHotSpot; -}; -int CustomEvent::EventType = 0; - -class CustomGestureRecognizer : public QGestureRecognizer -{ -public: - static bool ConsumeEvents; - - CustomGestureRecognizer() - { - if (!CustomEvent::EventType) - CustomEvent::EventType = QEvent::registerEventType(); - } - - QGesture* create(QObject *) - { - return new CustomGesture; - } - - QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event) - { - if (event->type() == CustomEvent::EventType) { - QGestureRecognizer::Result result = 0; - if (CustomGestureRecognizer::ConsumeEvents) - result |= QGestureRecognizer::ConsumeEventHint; - CustomGesture *g = static_cast(state); - CustomEvent *e = static_cast(event); - g->serial = e->serial; - if (e->hasHotSpot) - g->setHotSpot(e->hotSpot); - if (g->serial >= CustomGesture::SerialFinishedThreshold) - result |= QGestureRecognizer::FinishGesture; - else if (g->serial >= CustomGesture::SerialStartedThreshold) - result |= QGestureRecognizer::TriggerGesture; - else if (g->serial >= CustomGesture::SerialMaybeThreshold) - result |= QGestureRecognizer::MayBeGesture; - else - result = QGestureRecognizer::CancelGesture; - return result; - } - return QGestureRecognizer::Ignore; - } - - void reset(QGesture *state) - { - CustomGesture *g = static_cast(state); - g->serial = 0; - QGestureRecognizer::reset(state); - } -}; -bool CustomGestureRecognizer::ConsumeEvents = false; - -// same as CustomGestureRecognizer but triggers early without the maybe state -class CustomContinuousGestureRecognizer : public QGestureRecognizer -{ -public: - CustomContinuousGestureRecognizer() - { - if (!CustomEvent::EventType) - CustomEvent::EventType = QEvent::registerEventType(); - } - - QGesture* create(QObject *) - { - return new CustomGesture; - } - - QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event) - { - if (event->type() == CustomEvent::EventType) { - QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint; - CustomGesture *g = static_cast(state); - CustomEvent *e = static_cast(event); - g->serial = e->serial; - if (e->hasHotSpot) - g->setHotSpot(e->hotSpot); - if (g->serial >= CustomGesture::SerialFinishedThreshold) - result |= QGestureRecognizer::FinishGesture; - else if (g->serial >= CustomGesture::SerialMaybeThreshold) - result |= QGestureRecognizer::TriggerGesture; - else - result = QGestureRecognizer::CancelGesture; - return result; - } - return QGestureRecognizer::Ignore; - } - - void reset(QGesture *state) - { - CustomGesture *g = static_cast(state); - g->serial = 0; - QGestureRecognizer::reset(state); - } -}; - -class GestureWidget : public QWidget -{ - Q_OBJECT -public: - GestureWidget(const char *name = 0, QWidget *parent = 0) - : QWidget(parent) - { - if (name) - setObjectName(QLatin1String(name)); - reset(); - acceptGestureOverride = false; - } - void reset() - { - customEventsReceived = 0; - gestureEventsReceived = 0; - gestureOverrideEventsReceived = 0; - events.clear(); - overrideEvents.clear(); - ignoredGestures.clear(); - } - - int customEventsReceived; - int gestureEventsReceived; - int gestureOverrideEventsReceived; - struct Events - { - QList all; - QList started; - QList updated; - QList finished; - QList canceled; - - void clear() - { - all.clear(); - started.clear(); - updated.clear(); - finished.clear(); - canceled.clear(); - } - } events, overrideEvents; - - bool acceptGestureOverride; - QSet ignoredGestures; - -protected: - bool event(QEvent *event) - { - Events *eventsPtr = 0; - if (event->type() == QEvent::Gesture) { - QGestureEvent *e = static_cast(event); - ++gestureEventsReceived; - eventsPtr = &events; - foreach(Qt::GestureType type, ignoredGestures) - e->ignore(e->gesture(type)); - } else if (event->type() == QEvent::GestureOverride) { - ++gestureOverrideEventsReceived; - eventsPtr = &overrideEvents; - if (acceptGestureOverride) - event->accept(); - } - if (eventsPtr) { - QGestureEvent *e = static_cast(event); - QList gestures = e->gestures(); - foreach(QGesture *g, gestures) { - eventsPtr->all << g->gestureType(); - switch(g->state()) { - case Qt::GestureStarted: - emit gestureStarted(e->type(), g); - eventsPtr->started << g->gestureType(); - break; - case Qt::GestureUpdated: - emit gestureUpdated(e->type(), g); - eventsPtr->updated << g->gestureType(); - break; - case Qt::GestureFinished: - emit gestureFinished(e->type(), g); - eventsPtr->finished << g->gestureType(); - break; - case Qt::GestureCanceled: - emit gestureCanceled(e->type(), g); - eventsPtr->canceled << g->gestureType(); - break; - default: - qWarning() << "Unknown GestureState enum value:" << static_cast(g->state()); - } - } - } else if (event->type() == CustomEvent::EventType) { - ++customEventsReceived; - } else { - return QWidget::event(event); - } - return true; - } - -Q_SIGNALS: - void gestureStarted(QEvent::Type, QGesture *); - void gestureUpdated(QEvent::Type, QGesture *); - void gestureFinished(QEvent::Type, QGesture *); - void gestureCanceled(QEvent::Type, QGesture *); - -public Q_SLOTS: - void deleteThis() { delete this; } -}; - -// TODO rename to sendGestureSequence -static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0) -{ - QWeakPointer receiver(object); - for (int i = CustomGesture::SerialMaybeThreshold; - i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) { - event->serial = i; - if (scene) - scene->sendEvent(qobject_cast(object), event); - else - QApplication::sendEvent(object, event); - } -} - -class tst_Gestures : public QObject -{ -Q_OBJECT - -public: - tst_Gestures(); - virtual ~tst_Gestures(); - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); - -private slots: - void customGesture(); - void autoCancelingGestures(); - void gestureOverChild(); - void multipleWidgetOnlyGestureInTree(); - void conflictingGestures(); - void conflictingGesturesInGraphicsView(); - void finishedWithoutStarted(); - void unknownGesture(); - void graphicsItemGesture(); - void graphicsView(); - void graphicsItemTreeGesture(); - void explicitGraphicsObjectTarget(); - void gestureOverChildGraphicsItem(); - void twoGesturesOnDifferentLevel(); - void multipleGesturesInTree(); - void multipleGesturesInComplexTree(); - void testMapToScene(); - void ungrabGesture(); - void consumeEventHint(); - void unregisterRecognizer(); - void autoCancelGestures(); - void autoCancelGestures2(); - void graphicsViewParentPropagation(); - void panelPropagation(); - void panelStacksBehindParent(); - void deleteGestureTargetWidget(); - void deleteGestureTargetItem_data(); - void deleteGestureTargetItem(); - void viewportCoordinates(); - void partialGesturePropagation(); - void testQGestureRecognizerCleanup(); - void testReuseCanceledGestures(); - void bug_13501_gesture_not_accepted(); -}; - -tst_Gestures::tst_Gestures() -{ -} - -tst_Gestures::~tst_Gestures() -{ -} - -void tst_Gestures::initTestCase() -{ - CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - QVERIFY(CustomGesture::GestureType != Qt::GestureType(0)); - QVERIFY(CustomGesture::GestureType != Qt::CustomGesture); -} - -void tst_Gestures::cleanupTestCase() -{ - QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType); -} - -void tst_Gestures::init() -{ -} - -void tst_Gestures::cleanup() -{ -} - -void tst_Gestures::customGesture() -{ - GestureWidget widget; - widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - widget.show(); - QTest::qWaitForWindowShown(&widget); - - CustomEvent event; - event.hotSpot = widget.mapToGlobal(QPoint(5,5)); - event.hasHotSpot = true; - sendCustomGesture(&event, &widget); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount); - QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(widget.gestureOverrideEventsReceived, 0); - QCOMPARE(widget.events.all.size(), TotalGestureEventsCount); - for(int i = 0; i < widget.events.all.size(); ++i) - QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType); - QCOMPARE(widget.events.started.size(), 1); - QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2); - QCOMPARE(widget.events.finished.size(), 1); - QCOMPARE(widget.events.canceled.size(), 0); -} - -void tst_Gestures::consumeEventHint() -{ - GestureWidget widget; - widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - - CustomGestureRecognizer::ConsumeEvents = true; - CustomEvent event; - sendCustomGesture(&event, &widget); - CustomGestureRecognizer::ConsumeEvents = false; - - QCOMPARE(widget.customEventsReceived, 0); -} - -void tst_Gestures::autoCancelingGestures() -{ - GestureWidget widget; - widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - // send partial gesture. The gesture will be in the "maybe" state, but will - // never get enough events to fire, so Qt will have to kill it. - CustomEvent ev; - for (int i = CustomGesture::SerialMaybeThreshold; - i < CustomGesture::SerialStartedThreshold; ++i) { - ev.serial = i; - QApplication::sendEvent(&widget, &ev); - } - // wait long enough so the gesture manager will cancel the gesture - QTest::qWait(5000); - QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold); - QCOMPARE(widget.gestureEventsReceived, 0); - QCOMPARE(widget.gestureOverrideEventsReceived, 0); - QCOMPARE(widget.events.all.size(), 0); -} - -void tst_Gestures::gestureOverChild() -{ - GestureWidget widget("widget"); - QVBoxLayout *l = new QVBoxLayout(&widget); - GestureWidget *child = new GestureWidget("child"); - l->addWidget(child); - - widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - - CustomEvent event; - sendCustomGesture(&event, child); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(widget.customEventsReceived, 0); - QCOMPARE(child->gestureEventsReceived, 0); - QCOMPARE(child->gestureOverrideEventsReceived, 0); - QCOMPARE(widget.gestureEventsReceived, 0); - QCOMPARE(widget.gestureOverrideEventsReceived, 0); - - // enable gestures over the children - widget.grabGesture(CustomGesture::GestureType); - - widget.reset(); - child->reset(); - - sendCustomGesture(&event, child); - - QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(widget.customEventsReceived, 0); - - QCOMPARE(child->gestureEventsReceived, 0); - QCOMPARE(child->gestureOverrideEventsReceived, 0); - QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(widget.gestureOverrideEventsReceived, 0); - for(int i = 0; i < widget.events.all.size(); ++i) - QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType); - QCOMPARE(widget.events.started.size(), 1); - QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2); - QCOMPARE(widget.events.finished.size(), 1); - QCOMPARE(widget.events.canceled.size(), 0); -} - -void tst_Gestures::multipleWidgetOnlyGestureInTree() -{ - GestureWidget parent("parent"); - QVBoxLayout *l = new QVBoxLayout(&parent); - GestureWidget *child = new GestureWidget("child"); - l->addWidget(child); - - parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - // sending events to the child and making sure there is no conflict - CustomEvent event; - sendCustomGesture(&event, child); - - QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(parent.customEventsReceived, 0); - QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(child->gestureOverrideEventsReceived, 0); - QCOMPARE(parent.gestureEventsReceived, 0); - QCOMPARE(parent.gestureOverrideEventsReceived, 0); - - parent.reset(); - child->reset(); - - // same for the parent widget - sendCustomGesture(&event, &parent); - - QCOMPARE(child->customEventsReceived, 0); - QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount); - QCOMPARE(child->gestureEventsReceived, 0); - QCOMPARE(child->gestureOverrideEventsReceived, 0); - QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, 0); -} - -void tst_Gestures::conflictingGestures() -{ - GestureWidget parent("parent"); - QVBoxLayout *l = new QVBoxLayout(&parent); - GestureWidget *child = new GestureWidget("child"); - l->addWidget(child); - - parent.grabGesture(CustomGesture::GestureType); - child->grabGesture(CustomGesture::GestureType); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - // child accepts the override, parent will not receive anything - parent.acceptGestureOverride = false; - child->acceptGestureOverride = true; - - // sending events to the child and making sure there is no conflict - CustomEvent event; - sendCustomGesture(&event, child); - - QCOMPARE(child->gestureOverrideEventsReceived, 1); - QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, 0); - QCOMPARE(parent.gestureEventsReceived, 0); - - parent.reset(); - child->reset(); - - // parent accepts the override - parent.acceptGestureOverride = true; - child->acceptGestureOverride = false; - - // sending events to the child and making sure there is no conflict - sendCustomGesture(&event, child); - - QCOMPARE(child->gestureOverrideEventsReceived, 1); - QCOMPARE(child->gestureEventsReceived, 0); - QCOMPARE(parent.gestureOverrideEventsReceived, 1); - QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); - - parent.reset(); - child->reset(); - - // nobody accepts the override, we will send normal events to the closest - // context (i.e. to the child widget) and it will be propagated and - // accepted by the parent widget - parent.acceptGestureOverride = false; - child->acceptGestureOverride = false; - child->ignoredGestures << CustomGesture::GestureType; - - // sending events to the child and making sure there is no conflict - sendCustomGesture(&event, child); - - QCOMPARE(child->gestureOverrideEventsReceived, 1); - QCOMPARE(child->gestureEventsReceived, 1); - QCOMPARE(parent.gestureOverrideEventsReceived, 1); - QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); - - parent.reset(); - child->reset(); - - // nobody accepts the override, and nobody accepts the gesture event - parent.acceptGestureOverride = false; - child->acceptGestureOverride = false; - parent.ignoredGestures << CustomGesture::GestureType; - child->ignoredGestures << CustomGesture::GestureType; - - // sending events to the child and making sure there is no conflict - sendCustomGesture(&event, child); - - QCOMPARE(child->gestureOverrideEventsReceived, 1); - QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, 1); - QCOMPARE(parent.gestureEventsReceived, 1); - - parent.reset(); - child->reset(); - - // we set an attribute to make sure all gesture events are propagated - parent.grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); - parent.acceptGestureOverride = false; - child->acceptGestureOverride = false; - parent.ignoredGestures << CustomGesture::GestureType; - child->ignoredGestures << CustomGesture::GestureType; - - // sending events to the child and making sure there is no conflict - sendCustomGesture(&event, child); - - QCOMPARE(child->gestureOverrideEventsReceived, 1); - QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, 1); - QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); - - parent.reset(); - child->reset(); - - Qt::GestureType ContinuousGesture = QGestureRecognizer::registerRecognizer(new CustomContinuousGestureRecognizer); - static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - child->grabGesture(ContinuousGesture); - // child accepts override. And it also receives another custom gesture. - parent.acceptGestureOverride = false; - child->acceptGestureOverride = true; - sendCustomGesture(&event, child); - - QCOMPARE(child->gestureOverrideEventsReceived, 1); - QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount); - QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, 0); - QCOMPARE(parent.gestureEventsReceived, 0); - - QGestureRecognizer::unregisterRecognizer(ContinuousGesture); -} - -void tst_Gestures::finishedWithoutStarted() -{ - GestureWidget widget; - widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - - // the gesture will claim it finished, but it was never started. - CustomEvent ev; - ev.serial = CustomGesture::SerialFinishedThreshold; - QApplication::sendEvent(&widget, &ev); - - QCOMPARE(widget.customEventsReceived, 1); - QCOMPARE(widget.gestureEventsReceived, 2); - QCOMPARE(widget.gestureOverrideEventsReceived, 0); - QCOMPARE(widget.events.all.size(), 2); - QCOMPARE(widget.events.started.size(), 1); - QCOMPARE(widget.events.updated.size(), 0); - QCOMPARE(widget.events.finished.size(), 1); - QCOMPARE(widget.events.canceled.size(), 0); -} - -void tst_Gestures::unknownGesture() -{ - GestureWidget widget; - widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - widget.grabGesture(Qt::CustomGesture, Qt::DontStartGestureOnChildren); - widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::DontStartGestureOnChildren); - - CustomEvent event; - sendCustomGesture(&event, &widget); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount); -} - -static const QColor InstanceColors[] = { - Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow -}; - -class GestureItem : public QGraphicsObject -{ - Q_OBJECT - static int InstanceCount; -public: - GestureItem(const char *name = 0) - { - instanceNumber = InstanceCount++; - if (name) { - setObjectName(QLatin1String(name)); - setToolTip(name); - } - size = QRectF(0, 0, 100, 100); - customEventsReceived = 0; - gestureEventsReceived = 0; - gestureOverrideEventsReceived = 0; - events.clear(); - overrideEvents.clear(); - acceptGestureOverride = false; - - scene = 0; - } - ~GestureItem() - { - --InstanceCount; - } - - int customEventsReceived; - int gestureEventsReceived; - int gestureOverrideEventsReceived; - struct Events - { - QList all; - QList started; - QList updated; - QList finished; - QList canceled; - - void clear() - { - all.clear(); - started.clear(); - updated.clear(); - finished.clear(); - canceled.clear(); - } - } events, overrideEvents; - - bool acceptGestureOverride; - QSet ignoredGestures; - QSet ignoredStartedGestures; - QSet ignoredUpdatedGestures; - QSet ignoredFinishedGestures; - - QRectF size; - int instanceNumber; - - void reset() - { - customEventsReceived = 0; - gestureEventsReceived = 0; - gestureOverrideEventsReceived = 0; - events.clear(); - overrideEvents.clear(); - ignoredGestures.clear(); - ignoredStartedGestures.clear(); - ignoredUpdatedGestures.clear(); - ignoredFinishedGestures.clear(); - } - - QRectF boundingRect() const - { - return size; - } - void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) - { - QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))]; - p->fillRect(boundingRect(), color); - } - - bool event(QEvent *event) - { - Events *eventsPtr = 0; - if (event->type() == QEvent::Gesture) { - ++gestureEventsReceived; - eventsPtr = &events; - QGestureEvent *e = static_cast(event); - foreach(Qt::GestureType type, ignoredGestures) - e->ignore(e->gesture(type)); - foreach(QGesture *g, e->gestures()) { - switch (g->state()) { - case Qt::GestureStarted: - if (ignoredStartedGestures.contains(g->gestureType())) - e->ignore(g); - break; - case Qt::GestureUpdated: - if (ignoredUpdatedGestures.contains(g->gestureType())) - e->ignore(g); - break; - case Qt::GestureFinished: - if (ignoredFinishedGestures.contains(g->gestureType())) - e->ignore(g); - break; - default: - break; - } - } - } else if (event->type() == QEvent::GestureOverride) { - ++gestureOverrideEventsReceived; - eventsPtr = &overrideEvents; - if (acceptGestureOverride) - event->accept(); - } - if (eventsPtr) { - QGestureEvent *e = static_cast(event); - QList gestures = e->gestures(); - foreach(QGesture *g, gestures) { - eventsPtr->all << g->gestureType(); - switch(g->state()) { - case Qt::GestureStarted: - eventsPtr->started << g->gestureType(); - emit gestureStarted(e->type(), g); - break; - case Qt::GestureUpdated: - eventsPtr->updated << g->gestureType(); - emit gestureUpdated(e->type(), g); - break; - case Qt::GestureFinished: - eventsPtr->finished << g->gestureType(); - emit gestureFinished(e->type(), g); - break; - case Qt::GestureCanceled: - eventsPtr->canceled << g->gestureType(); - emit gestureCanceled(e->type(), g); - break; - default: - qWarning() << "Unknown GestureState enum value:" << static_cast(g->state()); - } - } - } else if (event->type() == CustomEvent::EventType) { - ++customEventsReceived; - } else { - return QGraphicsObject::event(event); - } - return true; - } - -Q_SIGNALS: - void gestureStarted(QEvent::Type, QGesture *); - void gestureUpdated(QEvent::Type, QGesture *); - void gestureFinished(QEvent::Type, QGesture *); - void gestureCanceled(QEvent::Type, QGesture *); - -public: - // some arguments for the slots below: - QGraphicsScene *scene; - -public Q_SLOTS: - void deleteThis() { delete this; } - void addSelfToScene(QEvent::Type eventType, QGesture *) - { - if (eventType == QEvent::Gesture) { - disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*))); - scene->addItem(this); - } - } -}; -int GestureItem::InstanceCount = 0; - -void tst_Gestures::graphicsItemGesture() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item = new GestureItem("item"); - scene.addItem(item); - item->setPos(100, 100); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item->grabGesture(CustomGesture::GestureType); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - CustomEvent event; - // gesture without hotspot should not be delivered to items in the view - QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); - QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); - QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); - QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); - sendCustomGesture(&event, item, &scene); - - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, 0); - QCOMPARE(item->gestureOverrideEventsReceived, 0); - - item->reset(); - - // make sure the event is properly delivered if only the hotspot is set. - event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item, &scene); - - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item->gestureOverrideEventsReceived, 0); - QCOMPARE(item->events.all.size(), TotalGestureEventsCount); - for(int i = 0; i < item->events.all.size(); ++i) - QCOMPARE(item->events.all.at(i), CustomGesture::GestureType); - QCOMPARE(item->events.started.size(), 1); - QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2); - QCOMPARE(item->events.finished.size(), 1); - QCOMPARE(item->events.canceled.size(), 0); - - item->reset(); - - // send gesture to the item which ignores it. - item->ignoredGestures << CustomGesture::GestureType; - - event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item, &scene); - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item->gestureOverrideEventsReceived, 0); -} - -void tst_Gestures::graphicsView() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item = new GestureItem("item"); - scene.addItem(item); - item->setPos(100, 100); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item->grabGesture(CustomGesture::GestureType); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - CustomEvent event; - // make sure the event is properly delivered if only the hotspot is set. - event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item, &scene); - - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item->gestureOverrideEventsReceived, 0); - - // change the viewport and try again - QWidget *newViewport = new QWidget; - view.setViewport(newViewport); - - item->reset(); - sendCustomGesture(&event, item, &scene); - - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item->gestureOverrideEventsReceived, 0); - - // change the scene and try again - QGraphicsScene newScene; - item = new GestureItem("newItem"); - newScene.addItem(item); - item->setPos(100, 100); - view.setScene(&newScene); - - item->reset(); - // first without a gesture - sendCustomGesture(&event, item, &newScene); - - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, 0); - QCOMPARE(item->gestureOverrideEventsReceived, 0); - - // then grab the gesture and try again - item->reset(); - item->grabGesture(CustomGesture::GestureType); - sendCustomGesture(&event, item, &newScene); - - QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item->gestureOverrideEventsReceived, 0); -} - -void tst_Gestures::graphicsItemTreeGesture() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - item1->setPos(100, 100); - item1->size = QRectF(0, 0, 350, 200); - scene.addItem(item1); - - GestureItem *item1_child1 = new GestureItem("item1_child1"); - item1_child1->setPos(50, 50); - item1_child1->size = QRectF(0, 0, 100, 100); - item1_child1->setParentItem(item1); - - GestureItem *item1_child2 = new GestureItem("item1_child2"); - item1_child2->size = QRectF(0, 0, 100, 100); - item1_child2->setPos(200, 50); - item1_child2->setParentItem(item1); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item1->grabGesture(CustomGesture::GestureType); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view); - event.hasHotSpot = true; - - item1->ignoredGestures << CustomGesture::GestureType; - sendCustomGesture(&event, item1_child1, &scene); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child2->gestureEventsReceived, 0); - QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); - - item1->reset(); item1_child1->reset(); item1_child2->reset(); - - item1_child1->grabGesture(CustomGesture::GestureType); - - item1->ignoredGestures << CustomGesture::GestureType; - item1_child1->ignoredGestures << CustomGesture::GestureType; - sendCustomGesture(&event, item1_child1, &scene); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1_child2->gestureEventsReceived, 0); - QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, 1); -} - -void tst_Gestures::explicitGraphicsObjectTarget() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - scene.addItem(item1); - item1->setPos(100, 100); - item1->setZValue(1); - - GestureItem *item2 = new GestureItem("item2"); - scene.addItem(item2); - item2->setPos(100, 100); - item2->setZValue(5); - - GestureItem *item2_child1 = new GestureItem("item2_child1"); - scene.addItem(item2_child1); - item2_child1->setParentItem(item2); - item2_child1->setPos(10, 10); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - // sending events to item1, but the hotSpot is set to item2 - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view); - event.hasHotSpot = true; - - sendCustomGesture(&event, item1, &scene); - - QCOMPARE(item1->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item2_child1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item2_child1->gestureOverrideEventsReceived, 1); - QCOMPARE(item2_child1->events.all.size(), TotalGestureEventsCount); - for(int i = 0; i < item2_child1->events.all.size(); ++i) - QCOMPARE(item2_child1->events.all.at(i), CustomGesture::GestureType); - QCOMPARE(item2_child1->events.started.size(), 1); - QCOMPARE(item2_child1->events.updated.size(), TotalGestureEventsCount - 2); - QCOMPARE(item2_child1->events.finished.size(), 1); - QCOMPARE(item2_child1->events.canceled.size(), 0); - QCOMPARE(item2->gestureEventsReceived, 0); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); -} - -void tst_Gestures::gestureOverChildGraphicsItem() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item0 = new GestureItem("item0"); - scene.addItem(item0); - item0->setPos(0, 0); - item0->grabGesture(CustomGesture::GestureType); - item0->setZValue(1); - - GestureItem *item1 = new GestureItem("item1"); - scene.addItem(item1); - item1->setPos(100, 100); - item1->setZValue(5); - - GestureItem *item2 = new GestureItem("item2"); - scene.addItem(item2); - item2->setPos(100, 100); - item2->setZValue(10); - - GestureItem *item2_child1 = new GestureItem("item2_child1"); - scene.addItem(item2_child1); - item2_child1->setParentItem(item2); - item2_child1->setPos(0, 0); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item1->grabGesture(CustomGesture::GestureType); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item2_child1->gestureEventsReceived, 0); - QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item2->gestureEventsReceived, 0); - QCOMPARE(item2->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - - item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); - item2->grabGesture(CustomGesture::GestureType); - item2->ignoredGestures << CustomGesture::GestureType; - - event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item2_child1->gestureEventsReceived, 0); - QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item2->gestureEventsReceived, 1); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - - item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); - item2->grabGesture(CustomGesture::GestureType); - item2->ignoredGestures << CustomGesture::GestureType; - item1->ignoredGestures << CustomGesture::GestureType; - - event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item2_child1->gestureEventsReceived, 0); - QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, 1); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - - item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); - item2->grabGesture(CustomGesture::GestureType); - item2->ignoredGestures << CustomGesture::GestureType; - item1->ignoredGestures << CustomGesture::GestureType; - item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); - - event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item2_child1->gestureEventsReceived, 0); - QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); -} - -void tst_Gestures::twoGesturesOnDifferentLevel() -{ - GestureWidget parent("parent"); - QVBoxLayout *l = new QVBoxLayout(&parent); - GestureWidget *child = new GestureWidget("child"); - l->addWidget(child); - - Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - - parent.grabGesture(CustomGesture::GestureType); - child->grabGesture(SecondGesture); - - CustomEvent event; - // sending events that form a gesture to one widget, but they will be - // filtered by two different gesture recognizers and will generate two - // QGesture objects. Check that those gesture objects are delivered to - // different widgets properly. - sendCustomGesture(&event, child); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(child->gestureOverrideEventsReceived, 0); - QCOMPARE(child->events.all.size(), TotalGestureEventsCount); - for(int i = 0; i < child->events.all.size(); ++i) - QCOMPARE(child->events.all.at(i), SecondGesture); - - QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, 0); - QCOMPARE(parent.events.all.size(), TotalGestureEventsCount); - for(int i = 0; i < child->events.all.size(); ++i) - QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType); - - QGestureRecognizer::unregisterRecognizer(SecondGesture); -} - -void tst_Gestures::multipleGesturesInTree() -{ - GestureWidget a("A"); - GestureWidget *A = &a; - GestureWidget *B = new GestureWidget("B", A); - GestureWidget *C = new GestureWidget("C", B); - GestureWidget *D = new GestureWidget("D", C); - - Qt::GestureType FirstGesture = CustomGesture::GestureType; - Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - - Qt::GestureFlags flags = Qt::ReceivePartialGestures; - A->grabGesture(FirstGesture, flags); // A [1 3] - A->grabGesture(ThirdGesture, flags); // | - B->grabGesture(SecondGesture, flags); // B [ 2 3] - B->grabGesture(ThirdGesture, flags); // | - C->grabGesture(FirstGesture, flags); // C [1 2 3] - C->grabGesture(SecondGesture, flags); // | - C->grabGesture(ThirdGesture, flags); // D [1 3] - D->grabGesture(FirstGesture, flags); - D->grabGesture(ThirdGesture, flags); - - // make sure all widgets ignore events, so they get propagated. - A->ignoredGestures << FirstGesture << ThirdGesture; - B->ignoredGestures << SecondGesture << ThirdGesture; - C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture; - D->ignoredGestures << FirstGesture << ThirdGesture; - - CustomEvent event; - sendCustomGesture(&event, D); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - // gesture override events - QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1); - QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0); - QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1); - - QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1); - QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1); - QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1); - - QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0); - QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1); - QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1); - - QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1); - QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0); - QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1); - - // normal gesture events - QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount); - QCOMPARE(D->events.all.count(SecondGesture), 0); - QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount); - - QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount); - QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount); - QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount); - - QCOMPARE(B->events.all.count(FirstGesture), 0); - QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount); - QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount); - - QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount); - QCOMPARE(A->events.all.count(SecondGesture), 0); - QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount); - - QGestureRecognizer::unregisterRecognizer(SecondGesture); - QGestureRecognizer::unregisterRecognizer(ThirdGesture); -} - -void tst_Gestures::multipleGesturesInComplexTree() -{ - GestureWidget a("A"); - GestureWidget *A = &a; - GestureWidget *B = new GestureWidget("B", A); - GestureWidget *C = new GestureWidget("C", B); - GestureWidget *D = new GestureWidget("D", C); - - Qt::GestureType FirstGesture = CustomGesture::GestureType; - Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - Qt::GestureType FourthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - Qt::GestureType FifthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - Qt::GestureType SixthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - Qt::GestureType SeventhGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - - Qt::GestureFlags flags = Qt::ReceivePartialGestures; - A->grabGesture(FirstGesture, flags); // A [1,3,4] - A->grabGesture(ThirdGesture, flags); // | - A->grabGesture(FourthGesture, flags); // B [2,3,5] - B->grabGesture(SecondGesture, flags); // | - B->grabGesture(ThirdGesture, flags); // C [1,2,3,6] - B->grabGesture(FifthGesture, flags); // | - C->grabGesture(FirstGesture, flags); // D [1,3,7] - C->grabGesture(SecondGesture, flags); - C->grabGesture(ThirdGesture, flags); - C->grabGesture(SixthGesture, flags); - D->grabGesture(FirstGesture, flags); - D->grabGesture(ThirdGesture, flags); - D->grabGesture(SeventhGesture, flags); - - // make sure all widgets ignore events, so they get propagated. - QSet allGestureTypes; - allGestureTypes << FirstGesture << SecondGesture << ThirdGesture - << FourthGesture << FifthGesture << SixthGesture << SeventhGesture; - A->ignoredGestures = B->ignoredGestures = allGestureTypes; - C->ignoredGestures = D->ignoredGestures = allGestureTypes; - - CustomEvent event; - sendCustomGesture(&event, D); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - // gesture override events - QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1); - QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0); - QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1); - - QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1); - QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1); - QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1); - - QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0); - QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1); - QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1); - - QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1); - QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0); - QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1); - - // normal gesture events - QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount); - QCOMPARE(D->events.all.count(SecondGesture), 0); - QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount); - QCOMPARE(D->events.all.count(FourthGesture), 0); - QCOMPARE(D->events.all.count(FifthGesture), 0); - QCOMPARE(D->events.all.count(SixthGesture), 0); - QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount); - - QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount); - QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount); - QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount); - QCOMPARE(C->events.all.count(FourthGesture), 0); - QCOMPARE(C->events.all.count(FifthGesture), 0); - QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount); - QCOMPARE(C->events.all.count(SeventhGesture), 0); - - QCOMPARE(B->events.all.count(FirstGesture), 0); - QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount); - QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount); - QCOMPARE(B->events.all.count(FourthGesture), 0); - QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount); - QCOMPARE(B->events.all.count(SixthGesture), 0); - QCOMPARE(B->events.all.count(SeventhGesture), 0); - - QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount); - QCOMPARE(A->events.all.count(SecondGesture), 0); - QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount); - QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount); - QCOMPARE(A->events.all.count(FifthGesture), 0); - QCOMPARE(A->events.all.count(SixthGesture), 0); - QCOMPARE(A->events.all.count(SeventhGesture), 0); - - QGestureRecognizer::unregisterRecognizer(SecondGesture); - QGestureRecognizer::unregisterRecognizer(ThirdGesture); - QGestureRecognizer::unregisterRecognizer(FourthGesture); - QGestureRecognizer::unregisterRecognizer(FifthGesture); - QGestureRecognizer::unregisterRecognizer(SixthGesture); - QGestureRecognizer::unregisterRecognizer(SeventhGesture); -} - -void tst_Gestures::testMapToScene() -{ - QGesture gesture; - QList list; - list << &gesture; - QGestureEvent event(list); - QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much - - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item0 = new GestureItem; - scene.addItem(item0); - item0->setPos(14, 16); - - view.show(); // need to show to give it a global coordinate - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - QPoint origin = view.mapToGlobal(QPoint()); - event.setWidget(view.viewport()); - - QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200))); -} - -void tst_Gestures::ungrabGesture() // a method on QWidget -{ - class MockGestureWidget : public GestureWidget { - public: - MockGestureWidget(const char *name = 0, QWidget *parent = 0) - : GestureWidget(name, parent) { } - - - QSet gestures; - protected: - bool event(QEvent *event) - { - if (event->type() == QEvent::Gesture) { - QGestureEvent *gestureEvent = static_cast(event); - if (gestureEvent) - foreach (QGesture *g, gestureEvent->gestures()) - gestures.insert(g); - } - return GestureWidget::event(event); - } - }; - - MockGestureWidget parent("A"); - MockGestureWidget *a = &parent; - MockGestureWidget *b = new MockGestureWidget("B", a); - - a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - b->grabGesture(CustomGesture::GestureType); - b->ignoredGestures << CustomGesture::GestureType; - - CustomEvent event; - // sending an event will cause the QGesture objects to be instantiated for the widgets - sendCustomGesture(&event, b); - - QCOMPARE(a->gestures.count(), 1); - QPointer customGestureA; - customGestureA = *(a->gestures.begin()); - QVERIFY(!customGestureA.isNull()); - QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType); - - QCOMPARE(b->gestures.count(), 1); - QPointer customGestureB; - customGestureB = *(b->gestures.begin()); - QVERIFY(!customGestureB.isNull()); - QVERIFY(customGestureA.data() == customGestureB.data()); - QCOMPARE(customGestureB->gestureType(), CustomGesture::GestureType); - - a->gestures.clear(); - // sending an event will cause the QGesture objects to be instantiated for the widget - sendCustomGesture(&event, a); - - QCOMPARE(a->gestures.count(), 1); - customGestureA = *(a->gestures.begin()); - QVERIFY(!customGestureA.isNull()); - QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType); - QVERIFY(customGestureA.data() != customGestureB.data()); - - a->ungrabGesture(CustomGesture::GestureType); - //We changed the deletion of Gestures to lazy during QT-4022, so we can't ensure the QGesture is deleted until now - QVERIFY(!customGestureB.isNull()); - - a->gestures.clear(); - a->reset(); - // send again to 'b' and make sure a never gets it. - sendCustomGesture(&event, b); - //After all Gestures are processed in the QGestureManager, we can ensure the QGesture is now deleted - QVERIFY(customGestureA.isNull()); - QCOMPARE(a->gestureEventsReceived, 0); - QCOMPARE(a->gestureOverrideEventsReceived, 0); -} - -void tst_Gestures::unregisterRecognizer() // a method on QApplication -{ - /* - The hardest usecase to get right is when we remove a recognizer while several - of the gestures it created are in active state and we immediately add a new recognizer - for the same type (thus replacing the old one). - The expected result is that all old gestures continue till they are finished/cancelled - and the new recognizer starts creating gestures immediately at registration. - - This implies that deleting of the recognizer happens only when there are no more gestures - that it created. (since gestures might have a pointer to the recognizer) - */ - -} - -void tst_Gestures::autoCancelGestures() -{ - class MockWidget : public GestureWidget { - public: - MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { } - - bool event(QEvent *event) - { - if (event->type() == QEvent::Gesture) { - QGestureEvent *ge = static_cast(event); - if (ge->gestures().count() != 1) - ++badGestureEvents; // event should contain exactly one gesture - ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext); - } - return GestureWidget::event(event); - } - - int badGestureEvents; - }; - - const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); - - MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext - parent.resize(300, 100); - parent.setWindowFlags(Qt::X11BypassWindowManagerHint); - GestureWidget *child = new GestureWidget("child", &parent); - child->setGeometry(10, 10, 100, 80); - - parent.grabGesture(CustomGesture::GestureType); - child->grabGesture(secondGesture); - parent.show(); - QTest::qWaitForWindowShown(&parent); - - /* - An event is send to both the child and the parent, when the child gets it a gesture is triggered - and send to the child. - When the parent gets the event a new gesture is triggered and delivered to the parent. When the - parent gets it he accepts it and that causes the cancel policy to activate. - The cause of that is the gesture for the child is cancelled and send to the child as such. - */ - CustomEvent event; - event.serial = CustomGesture::SerialStartedThreshold; - QApplication::sendEvent(child, &event); - QCOMPARE(child->events.all.count(), 2); - QCOMPARE(child->events.started.count(), 1); - QCOMPARE(child->events.canceled.count(), 1); - QCOMPARE(parent.events.all.count(), 1); - - // clean up, make the parent gesture finish - event.serial = CustomGesture::SerialFinishedThreshold; - QApplication::sendEvent(child, &event); - QCOMPARE(parent.events.all.count(), 2); - QCOMPARE(parent.badGestureEvents, 0); -} - -void tst_Gestures::autoCancelGestures2() -{ - class MockItem : public GestureItem { - public: - MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { } - - bool event(QEvent *event) { - if (event->type() == QEvent::Gesture) { - QGestureEvent *ge = static_cast(event); - if (ge->gestures().count() != 1) - ++badGestureEvents; // event should contain exactly one gesture - ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext); - } - return GestureItem::event(event); - } - - int badGestureEvents; - }; - - const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer); - - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - MockItem *parent = new MockItem("parent"); - GestureItem *child = new GestureItem("child"); - child->setParentItem(parent); - parent->setPos(0, 0); - child->setPos(10, 10); - scene.addItem(parent); - parent->grabGesture(CustomGesture::GestureType); - child->grabGesture(secondGesture); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - CustomEvent event; - event.serial = CustomGesture::SerialStartedThreshold; - event.hasHotSpot = true; - event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view); - scene.sendEvent(child, &event); - QCOMPARE(parent->events.all.count(), 1); - QCOMPARE(child->events.started.count(), 1); - QCOMPARE(child->events.canceled.count(), 1); - QCOMPARE(child->events.all.count(), 2); - - // clean up, make the parent gesture finish - event.serial = CustomGesture::SerialFinishedThreshold; - scene.sendEvent(child, &event); - QCOMPARE(parent->events.all.count(), 2); - QCOMPARE(parent->badGestureEvents, 0); -} - -void tst_Gestures::graphicsViewParentPropagation() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item0 = new GestureItem("item0"); - scene.addItem(item0); - item0->setPos(0, 0); - item0->grabGesture(CustomGesture::GestureType); - item0->setZValue(1); - - GestureItem *item1 = new GestureItem("item1"); - scene.addItem(item1); - item1->setPos(0, 0); - item1->setZValue(5); - - GestureItem *item1_c1 = new GestureItem("item1_child1"); - item1_c1->setParentItem(item1); - item1_c1->setPos(0, 0); - - GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1"); - item1_c1_c1->setParentItem(item1_c1); - item1_c1_c1->setPos(0, 0); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); - item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); - item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent); - item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); - - item0->ignoredUpdatedGestures << CustomGesture::GestureType; - item0->ignoredFinishedGestures << CustomGesture::GestureType; - item1->ignoredUpdatedGestures << CustomGesture::GestureType; - item1->ignoredFinishedGestures << CustomGesture::GestureType; - item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType; - item1_c1->ignoredFinishedGestures << CustomGesture::GestureType; - item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType; - item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType; - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1); - QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item0->gestureEventsReceived, 0); - QCOMPARE(item0->gestureOverrideEventsReceived, 1); -} - -void tst_Gestures::panelPropagation() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item0 = new GestureItem("item0"); - scene.addItem(item0); - item0->setPos(0, 0); - item0->size = QRectF(0, 0, 200, 200); - item0->grabGesture(CustomGesture::GestureType); - item0->setZValue(1); - - GestureItem *item1 = new GestureItem("item1"); - item1->grabGesture(CustomGesture::GestureType); - scene.addItem(item1); - item1->setPos(10, 10); - item1->size = QRectF(0, 0, 180, 180); - item1->setZValue(2); - - GestureItem *item1_child1 = new GestureItem("item1_child1[panel]"); - item1_child1->setFlags(QGraphicsItem::ItemIsPanel); - item1_child1->setParentItem(item1); - item1_child1->grabGesture(CustomGesture::GestureType); - item1_child1->setPos(10, 10); - item1_child1->size = QRectF(0, 0, 160, 160); - item1_child1->setZValue(5); - - GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1"); - item1_child1_child1->setParentItem(item1_child1); - item1_child1_child1->grabGesture(CustomGesture::GestureType); - item1_child1_child1->setPos(10, 10); - item1_child1_child1->size = QRectF(0, 0, 140, 140); - item1_child1_child1->setZValue(10); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); - QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(item0->gestureEventsReceived, 0); - QCOMPARE(item0->gestureOverrideEventsReceived, 0); - - item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); - - event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); - - QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item0->gestureEventsReceived, 0); - QCOMPARE(item0->gestureOverrideEventsReceived, 1); - - item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); - // try with a modal panel - item1_child1->setPanelModality(QGraphicsItem::PanelModal); - - event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); - - QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(item0->gestureEventsReceived, 0); - QCOMPARE(item0->gestureOverrideEventsReceived, 0); - - item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); - // try with a modal panel, however set the hotspot to be outside of the - // panel and its parent - item1_child1->setPanelModality(QGraphicsItem::PanelModal); - - event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); - - QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item0->gestureOverrideEventsReceived, 0); - - item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); - // try with a scene modal panel - item1_child1->setPanelModality(QGraphicsItem::SceneModal); - - event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item0, &scene); - - QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); - QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(item0->gestureEventsReceived, 0); - QCOMPARE(item0->gestureOverrideEventsReceived, 0); -} - -void tst_Gestures::panelStacksBehindParent() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - item1->grabGesture(CustomGesture::GestureType); - scene.addItem(item1); - item1->setPos(10, 10); - item1->size = QRectF(0, 0, 180, 180); - item1->setZValue(2); - - GestureItem *panel = new GestureItem("panel"); - panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent); - panel->setPanelModality(QGraphicsItem::PanelModal); - panel->setParentItem(item1); - panel->grabGesture(CustomGesture::GestureType); - panel->setPos(-10, -10); - panel->size = QRectF(0, 0, 200, 200); - panel->setZValue(5); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); - - QCOMPARE(item1->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(panel->gestureOverrideEventsReceived, 0); -} - -void tst_Gestures::deleteGestureTargetWidget() -{ -} - -void tst_Gestures::deleteGestureTargetItem_data() -{ - QTest::addColumn("propagateUpdateGesture"); - QTest::addColumn("emitter"); - QTest::addColumn("receiver"); - QTest::addColumn("signalName"); - QTest::addColumn("slotName"); - - QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*)); - QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*)); - QByteArray deleteThis = SLOT(deleteThis()); - QByteArray deleteLater = SLOT(deleteLater()); - - QTest::newRow("delete1") - << false << "item1" << "item1" << gestureUpdated << deleteThis; - QTest::newRow("delete2") - << false << "item2" << "item2" << gestureUpdated << deleteThis; - QTest::newRow("delete3") - << false << "item1" << "item2" << gestureUpdated << deleteThis; - - QTest::newRow("deleteLater1") - << false << "item1" << "item1" << gestureUpdated << deleteLater; - QTest::newRow("deleteLater2") - << false << "item2" << "item2" << gestureUpdated << deleteLater; - QTest::newRow("deleteLater3") - << false << "item1" << "item2" << gestureUpdated << deleteLater; - QTest::newRow("deleteLater4") - << false << "item2" << "item1" << gestureUpdated << deleteLater; - - QTest::newRow("delete-self-and-propagate") - << true << "item2" << "item2" << gestureUpdated << deleteThis; - QTest::newRow("deleteLater-self-and-propagate") - << true << "item2" << "item2" << gestureUpdated << deleteLater; - QTest::newRow("propagate-to-deletedLater") - << true << "item2" << "item1" << gestureUpdated << deleteLater; -} - -void tst_Gestures::deleteGestureTargetItem() -{ - QFETCH(bool, propagateUpdateGesture); - QFETCH(QString, emitter); - QFETCH(QString, receiver); - QFETCH(QByteArray, signalName); - QFETCH(QByteArray, slotName); - - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - item1->grabGesture(CustomGesture::GestureType); - item1->setZValue(2); - scene.addItem(item1); - - GestureItem *item2 = new GestureItem("item2"); - item2->grabGesture(CustomGesture::GestureType); - item2->setZValue(5); - scene.addItem(item2); - - QMap items; - items.insert(item1->objectName(), item1); - items.insert(item2->objectName(), item2); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - if (propagateUpdateGesture) - item2->ignoredUpdatedGestures << CustomGesture::GestureType; - connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName); - - // some debug output to see the current test data tag, so if we crash - // we know which one caused the crash. - qDebug() << "<-- testing"; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); -} - -class GraphicsView : public QGraphicsView -{ -public: - GraphicsView(QGraphicsScene *scene, QWidget *parent = 0) - : QGraphicsView(scene, parent) - { - } - - using QGraphicsView::setViewportMargins; -}; - -// just making sure that even if the graphicsview has margins hotspot still -// works properly. It should use viewport for converting global coordinates to -// scene coordinates. -void tst_Gestures::viewportCoordinates() -{ - QGraphicsScene scene; - GraphicsView view(&scene); - view.setViewportMargins(10,20,15,25); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - item1->grabGesture(CustomGesture::GestureType); - item1->size = QRectF(0, 0, 3, 3); - item1->setZValue(2); - scene.addItem(item1); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - CustomEvent event; - event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); - QVERIFY(item1->gestureEventsReceived != 0); -} - -void tst_Gestures::partialGesturePropagation() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - item1->grabGesture(CustomGesture::GestureType); - item1->setZValue(8); - scene.addItem(item1); - - GestureItem *item2 = new GestureItem("item2[partial]"); - item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); - item2->setZValue(6); - scene.addItem(item2); - - GestureItem *item3 = new GestureItem("item3"); - item3->grabGesture(CustomGesture::GestureType); - item3->setZValue(4); - scene.addItem(item3); - - GestureItem *item4 = new GestureItem("item4[partial]"); - item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); - item4->setZValue(2); - scene.addItem(item4); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - item1->ignoredUpdatedGestures << CustomGesture::GestureType; - - CustomEvent event; - event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item1, &scene); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item3->gestureOverrideEventsReceived, 1); - QCOMPARE(item4->gestureOverrideEventsReceived, 1); - - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished - QCOMPARE(item3->gestureEventsReceived, 0); - QCOMPARE(item4->gestureEventsReceived, 0); -} - -class WinNativePan : public QPanGesture { -public: - WinNativePan() {} -}; - -class Pan : public QPanGesture { -public: - Pan() {} -}; - -class CustomPan : public QPanGesture { -public: - CustomPan() {} -}; - -// Recognizer for active gesture triggers on mouse press -class PanRecognizer : public QGestureRecognizer { -public: - enum PanType { Platform, Default, Custom }; - - PanRecognizer(int id) : m_id(id) {} - QGesture *create(QObject *) { - switch(m_id) { - case Platform: return new WinNativePan(); - case Default: return new Pan(); - default: return new CustomPan(); - } - } - - Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; } - - const int m_id; -}; - -void tst_Gestures::testQGestureRecognizerCleanup() -{ - // Clean first the current recognizers in QGManager - QGestureRecognizer::unregisterRecognizer(Qt::PanGesture); - - // v-- Qt singleton QGManager initialization - - // Mimic QGestureManager: register both default and "platform" recognizers - // (this is done in windows when QT_NO_NATIVE_GESTURES is not defined) - PanRecognizer *def = new PanRecognizer(PanRecognizer::Default); - QGestureRecognizer::registerRecognizer(def); - PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform); - QGestureRecognizer::registerRecognizer(plt); - qDebug () << "register: default =" << def << "; platform =" << plt; - - // ^-- Qt singleton QGManager initialization - - // Here, application code would start - - // Create QGV (has a QAScrollArea, which uses Qt::PanGesture) - QMainWindow *w = new QMainWindow; - QGraphicsView *v = new QGraphicsView(); - w->setCentralWidget(v); - - // Unregister Qt recognizers - QGestureRecognizer::unregisterRecognizer(Qt::PanGesture); - - // Register a custom Pan recognizer - //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom)); - - w->show(); - QTest::qWaitForWindowShown(w); - delete w; -} - -class ReuseCanceledGesturesRecognizer : public QGestureRecognizer -{ -public: - enum Type { - RmbAndCancelAllType, - LmbType - }; - - ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {} - - QGesture *create(QObject *) { - QGesture *g = new QGesture; - return g; - } - - Result recognize(QGesture *gesture, QObject *, QEvent *event) { - QMouseEvent *me = static_cast(event); - Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton); - - switch(event->type()) { - case QEvent::MouseButtonPress: - if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) { - gesture->setHotSpot(QPointF(me->globalPos())); - if (m_type == RmbAndCancelAllType) - gesture->setGestureCancelPolicy(QGesture::CancelAllInContext); - return QGestureRecognizer::TriggerGesture; - } - break; - case QEvent::MouseButtonRelease: - if (me->button() == mouseButton && gesture->state() > Qt::NoGesture) - return QGestureRecognizer::FinishGesture; - default: - break; - } - return QGestureRecognizer::Ignore; - } -private: - Type m_type; -}; - -class ReuseCanceledGesturesWidget : public QGraphicsWidget -{ - public: - ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0) - : QGraphicsWidget(parent), - m_gestureType(gestureType), - m_started(0), m_updated(0), m_canceled(0), m_finished(0) - { - } - - bool event(QEvent *event) { - if (event->type() == QEvent::Gesture) { - QGesture *gesture = static_cast(event)->gesture(m_gestureType); - if (gesture) { - switch(gesture->state()) { - case Qt::GestureStarted: m_started++; break; - case Qt::GestureUpdated: m_updated++; break; - case Qt::GestureFinished: m_finished++; break; - case Qt::GestureCanceled: m_canceled++; break; - default: break; - } - } - return true; - } - if (event->type() == QEvent::GraphicsSceneMousePress) { - return true; - } - return QGraphicsWidget::event(event); - } - - int started() { return m_started; } - int updated() { return m_updated; } - int finished() { return m_finished; } - int canceled() { return m_canceled; } - - private: - Qt::GestureType m_gestureType; - int m_started; - int m_updated; - int m_canceled; - int m_finished; -}; - -void tst_Gestures::testReuseCanceledGestures() -{ - Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer( - new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType)); - Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer( - new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType)); - - QMainWindow mw; - mw.setWindowFlags(Qt::X11BypassWindowManagerHint); - QGraphicsView *gv = new QGraphicsView(&mw); - QGraphicsScene *scene = new QGraphicsScene; - - gv->setScene(scene); - scene->setSceneRect(0,0,100,100); - - // Create container and add to the scene - ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget; - container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture - - // Create widget and add to the scene - ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container); - target->grabGesture(tapGestureTypeId); - - container->setGeometry(scene->sceneRect()); - - scene->addItem(container); - - mw.setCentralWidget(gv); - - // Viewport needs to grab all gestures that widgets in scene grab - gv->viewport()->grabGesture(cancellingGestureTypeId); - gv->viewport()->grabGesture(tapGestureTypeId); - - mw.show(); - QTest::qWaitForWindowShown(&mw); - - QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center()))); - targetPos = gv->viewport()->mapFromParent(targetPos); - - // "Tap" starts on child widget - QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos); - QCOMPARE(target->started(), 1); - QCOMPARE(target->updated(), 0); - QCOMPARE(target->finished(), 0); - QCOMPARE(target->canceled(), 0); - - // Canceling gesture starts on parent - QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos); - QCOMPARE(target->started(), 1); - QCOMPARE(target->updated(), 0); - QCOMPARE(target->finished(), 0); - QCOMPARE(target->canceled(), 1); // <- child canceled - - // Canceling gesture ends - QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos); - QCOMPARE(target->started(), 1); - QCOMPARE(target->updated(), 0); - QCOMPARE(target->finished(), 0); - QCOMPARE(target->canceled(), 1); - - // Tap would end if not canceled - QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos); - QCOMPARE(target->started(), 1); - QCOMPARE(target->updated(), 0); - QCOMPARE(target->finished(), 0); - QCOMPARE(target->canceled(), 1); - - // New "Tap" starts - QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos); - QCOMPARE(target->started(), 2); - QCOMPARE(target->updated(), 0); - QCOMPARE(target->finished(), 0); - QCOMPARE(target->canceled(), 1); - - QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos); - QCOMPARE(target->started(), 2); - QCOMPARE(target->updated(), 0); - QCOMPARE(target->finished(), 1); - QCOMPARE(target->canceled(), 1); -} - -void tst_Gestures::conflictingGesturesInGraphicsView() -{ - QGraphicsScene scene; - GraphicsView view(&scene); - view.setWindowFlags(Qt::X11BypassWindowManagerHint); - - GestureItem *item1 = new GestureItem("item1"); - item1->grabGesture(CustomGesture::GestureType); - item1->size = QRectF(0, 0, 100, 100); - item1->setZValue(2); - scene.addItem(item1); - - GestureItem *item2 = new GestureItem("item2"); - item2->grabGesture(CustomGesture::GestureType); - item2->size = QRectF(0, 0, 100, 100); - item2->setZValue(5); - scene.addItem(item2); - - view.show(); - QTest::qWaitForWindowShown(&view); - view.ensureVisible(scene.sceneRect()); - - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; - - CustomEvent event; - - // nobody accepts override - item1->acceptGestureOverride = false; - item2->acceptGestureOverride = false; - event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item2, &scene); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, 0); - - item1->reset(); item2->reset(); - - // the original target accepts override - item1->acceptGestureOverride = false; - item2->acceptGestureOverride = true; - event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item2, &scene); - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(item1->gestureOverrideEventsReceived, 0); - QCOMPARE(item1->gestureEventsReceived, 0); - - item1->reset(); item2->reset(); - - // the item behind accepts override - item1->acceptGestureOverride = true; - item2->acceptGestureOverride = false; - event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); - event.hasHotSpot = true; - sendCustomGesture(&event, item2, &scene); - - QCOMPARE(item2->gestureOverrideEventsReceived, 1); - QCOMPARE(item2->gestureEventsReceived, 0); - QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); -} - -class NoConsumeWidgetBug13501 :public QWidget -{ - Q_OBJECT -protected: - bool event(QEvent *e) { - if(e->type() == QEvent::Gesture) { - return false; - } - return QWidget::event(e); - } -}; - -void tst_Gestures::bug_13501_gesture_not_accepted() -{ - // Create a gesture event that is not accepted by any widget - // make sure this does not lead to an assert in QGestureManager - NoConsumeWidgetBug13501 w; - w.grabGesture(Qt::TapGesture); - w.show(); - QTest::qWaitForWindowShown(&w); - //QTest::mousePress(&ignoreEvent, Qt::LeftButton); - QTest::touchEvent(&w).press(0, QPoint(10, 10), &w); -} - -QTEST_MAIN(tst_Gestures) -#include "tst_gestures.moc" diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 7e07df24d8..d876873bd4 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -6,130 +6,9 @@ TEMPLATE=subdirs SUBDIRS=\ gui \ - gestures \ - languagechange \ - modeltest \ - qabstractbutton \ - qabstractitemview \ - qabstractprintdialog \ - qabstractproxymodel \ - qabstractscrollarea \ - qabstractslider \ - qabstractspinbox \ - qaction \ - qactiongroup \ - qapplication \ - qboxlayout \ - qbuttongroup \ - qcalendarwidget \ - qcheckbox \ - qcolordialog \ - qcolumnview \ - qcommandlinkbutton \ - qcompleter \ - qcomplextext \ - qdatawidgetmapper \ - qdatetimeedit \ - qdesktopwidget \ - qdial \ - qdialog \ - qdialogbuttonbox \ - qdirmodel \ - qdockwidget \ - qdoublespinbox \ - qdoublevalidator \ - qerrormessage \ - qfiledialog \ - qfiledialog2 \ - qfileiconprovider \ - qfilesystemmodel \ - qfocusframe \ - qfontcombobox \ - qfontdialog \ - qformlayout \ - qgraphicsanchorlayout \ - qgraphicsanchorlayout1 \ - qgraphicseffect \ - qgraphicseffectsource \ - qgraphicsgridlayout \ - qgraphicsitem \ - qgraphicsitemanimation \ - qgraphicslayout \ - qgraphicslayoutitem \ - qgraphicslinearlayout \ - qgraphicsobject \ - qgraphicspixmapitem \ - qgraphicspolygonitem \ - qgraphicsproxywidget \ - qgraphicsscene \ - qgraphicssceneindex \ - qgraphicstransform \ - qgraphicsview \ - qgraphicswidget \ - qgridlayout \ - qgroupbox \ - qheaderview \ - qidentityproxymodel \ - qinputcontext \ - qinputdialog \ - qintvalidator \ - qitemdelegate \ - qitemeditorfactory \ - qitemselectionmodel \ - qitemview \ - qlabel \ - qlcdnumber \ - qlineedit \ - qlistview \ - qlistwidget \ - qmacstyle \ - qmainwindow \ - qmdisubwindow \ - qmessagebox \ - qnetworkaccessmanager_and_qprogressdialog \ qopengl \ - qplaintextedit \ - qprogressbar \ - qprogressdialog \ - qpushbutton \ - qradiobutton \ - qregexpvalidator \ - qscrollarea \ - qscrollbar \ - qscroller \ - qsharedpointer_and_qwidget \ - qsidebar \ - qsizegrip \ - qslider \ - qsortfilterproxymodel \ - qsound \ - qspinbox \ - qstackedlayout \ - qstackedwidget \ - qstandarditem \ - qstandarditemmodel \ - qstatusbar \ - qstringlistmodel \ - qstyle \ - qstyleoption \ - qstylesheetstyle \ - qsystemtrayicon \ - qtabbar \ - qtableview \ - qtablewidget \ - qtoolbar \ - qtoolbox \ - qtooltip \ qtransformedscreen \ - qtreeview \ - qtreewidget \ - qtreewidgetitemiterator \ - qundogroup \ - qundostack \ - qwidget_window \ - qwidgetaction \ qwindowsurface \ - qwizard \ qwsembedwidget \ qwsinputmethod \ qwswindowsystem \ @@ -139,13 +18,6 @@ SUBDIRS=\ mac*:SUBDIRS -= \ qwindowsurface \ -# This test can only be run on Mac OS -!mac:SUBDIRS -= \ - qmacstyle \ - -# This test takes too long to run on IRIX, so skip it on that platform -irix-*:SUBDIRS -= qitemview - # These tests are only valid for QWS !embedded|wince*:SUBDIRS -= \ qtransformedscreen \ @@ -153,28 +25,3 @@ irix-*:SUBDIRS -= qitemview qwsinputmethod \ qwswindowsystem \ -# These tests require the cleanlooks style -!contains(styles, cleanlooks):SUBDIRS -= \ - qgraphicswidget \ - qgraphicsproxywidget \ - -win32:SUBDIRS -= qtextpiecetable - -!contains(QT_CONFIG, private_tests): SUBDIRS -= \ - qcolumnview \ - qgraphicsanchorlayout \ - qgraphicsanchorlayout1 \ - qgraphicsitem \ - qgraphicsscene \ - qgraphicssceneindex \ - qlistwidget \ - qmainwindow \ - qpathclipper \ - qpixmapcache \ - qsidebar \ - qstylesheetstyle \ - qtextlayout \ - qtextpiecetable \ - qtipc \ - qtoolbar \ - diff --git a/tests/auto/integrationtests/collections/.gitignore b/tests/auto/integrationtests/collections/.gitignore new file mode 100644 index 0000000000..dcd9d49ec0 --- /dev/null +++ b/tests/auto/integrationtests/collections/.gitignore @@ -0,0 +1 @@ +tst_collections diff --git a/tests/auto/integrationtests/collections/collections.pro b/tests/auto/integrationtests/collections/collections.pro new file mode 100644 index 0000000000..8601ff877d --- /dev/null +++ b/tests/auto/integrationtests/collections/collections.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +SOURCES += tst_collections.cpp +QT = core +CONFIG += parallel_test diff --git a/tests/auto/integrationtests/collections/tst_collections.cpp b/tests/auto/integrationtests/collections/tst_collections.cpp new file mode 100644 index 0000000000..f09ff06234 --- /dev/null +++ b/tests/auto/integrationtests/collections/tst_collections.cpp @@ -0,0 +1,3846 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +// test the container forwards +#include + +static QCache *cacheX; +static QHash *hashX; +static QLinkedList *linkedListX; +static QList *listX; +static QMap *mapX; +static QMultiHash *multiHashX; +static QMultiMap *multiMapX; +static QPair *pairX; +static QQueue *queueX; +static QSet *setX; +static QStack *stackX; +static QVarLengthArray *varLengthArrayX; +static QVarLengthArray *varLengthArrayY; +static QVector *vectorX; + +void foo() +{ + cacheX = 0; + hashX = 0; + linkedListX = 0; + listX = 0; + mapX = 0; + multiHashX = 0; + multiMapX = 0; + pairX = 0; + queueX = 0; + setX = 0; + stackX = 0; + varLengthArrayX = 0; + varLengthArrayY = 0; + vectorX = 0; +} + +#include + +#ifndef QT_NO_STL +# include +#endif + +#include "qalgorithms.h" +#include "qbitarray.h" +#include "qbytearray.h" +#include "qcache.h" +#include "qhash.h" +#include "qlinkedlist.h" +#include "qlist.h" +#include "qmap.h" +#include "qpair.h" +#include "qregexp.h" +#include "qset.h" +#include "qstack.h" +#include "qstring.h" +#include "qstringlist.h" +#include "qvarlengtharray.h" +#include "qvector.h" +#include "qqueue.h" + +template class QList; + +//TESTED_FILES= + +class tst_Collections : public QObject +{ + Q_OBJECT + +public: + tst_Collections(); + ~tst_Collections(); + +public slots: + void init(); + void cleanup(); +private slots: + void typeinfo(); + void qstring(); + void list(); + void linkedList(); + void vector(); + void byteArray(); + void stack(); + void hash(); + void map(); + void bitArray(); + void cache(); + void regexp(); + void pair(); + void sharableQList(); + void sharableQLinkedList(); + void sharableQVector(); + void sharableQMap(); + void sharableQHash(); + void q_foreach(); + void conversions(); + void javaStyleIterators(); + void constAndNonConstStlIterators(); +#ifndef QT_NO_STL + void vector_stl_data(); + void vector_stl(); + void list_stl_data(); + void list_stl(); + void linkedlist_stl_data(); + void linkedlist_stl(); +#endif + void q_init(); + void pointersize(); + void containerInstantiation(); + void qtimerList(); + void containerTypedefs(); + void forwardDeclared(); +#if defined(Q_ALIGNOF) && defined(Q_DECL_ALIGN) + void alignment(); +#endif + void QTBUG13079_collectionInsideCollection(); + + void foreach_2(); + void insert_remove_loop(); +}; + +struct LargeStatic { + static int count; + LargeStatic():c(count) { ++count; } + LargeStatic(const LargeStatic& o):c(o.c) { ++count; } + ~LargeStatic() { --count; } + int c; + int data[8]; +}; + +int LargeStatic::count = 0; + +struct Movable { + static int count; + Movable():c(count) { ++count; } + Movable(const Movable& o):c(o.c) { ++count; } + ~Movable() { --count; } + int c; +}; + +int Movable::count = 0; +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + + +struct Pod { + int i1, i2; +}; + +tst_Collections::tst_Collections() +{ +} + +tst_Collections::~tst_Collections() +{ + +} + +void tst_Collections::init() +{ +} + +void tst_Collections::cleanup() +{ +} + +void tst_Collections::typeinfo() +{ + QVERIFY(QTypeInfo::isPointer); + QVERIFY(!QTypeInfo::isPointer); + QVERIFY(QTypeInfo::isComplex); + QVERIFY(!QTypeInfo::isComplex); +} + +void tst_Collections::list() +{ + { + QList list; + QVERIFY(list.isEmpty()); + list.append(1); + QVERIFY(list.size() == 1); + + QVERIFY(*list.begin() == 1); + + list.push_back(2); + list += (3); + list << 4 << 5 << 6; + QVERIFY(!list.isEmpty()); + QVERIFY(list.size() == 6); + QVERIFY(list.end() - list.begin() == list.size()); + +#if !defined(QT_NO_STL) && !defined(Q_CC_MSVC) && !defined(Q_CC_SUN) + QVERIFY(std::binary_search(list.begin(), list.end(), 2) == true); + QVERIFY(std::binary_search(list.begin(), list.end(), 9) == false); +#endif + QVERIFY(qBinaryFind(list.begin(), list.end(), 2) == list.begin() + 1); + QVERIFY(qLowerBound(list.begin(), list.end(), 2) == list.begin() + 1); + QVERIFY(qUpperBound(list.begin(), list.end(), 2) == list.begin() + 2); + QVERIFY(qBinaryFind(list.begin(), list.end(), 9) == list.end()); + QVERIFY(qLowerBound(list.begin(), list.end(), 9) == list.end()); + QVERIFY(qUpperBound(list.begin(), list.end(), 9) == list.end()); + { + int sum = 0; + QListIterator i(list); + while (i.hasNext()) + sum += i.next(); + QVERIFY(sum == 21); + } + + { + QList list1; + list1 << 1 << 2 << 3 << 5 << 7 << 8 << 9; + QList list2 = list1; + + QMutableListIterator i1(list1); + while (i1.hasNext()) { + if (i1.next() % 2 != 0) + i1.remove(); + } + + QMutableListIterator i2(list2); + i2.toBack(); + while (i2.hasPrevious()) { + if (i2.previous() % 2 != 0) + i2.remove(); + } + QVERIFY(list1.size() == 2); + QVERIFY(list2.size() == 2); + QVERIFY(list1 == list2); + } + + { + int sum = 0; + for (int i = 0; i < list.size(); ++i) + sum += list[i]; + QVERIFY(sum == 21); + } + { + int sum = 0; + QList::const_iterator i = list.begin(); + while (i != list.end()) + sum += *i++; + QVERIFY(sum == 21); + } + { + int sum = 0; + QList::ConstIterator i = list.begin(); + while (i != list.end()) + sum += *i++; + QVERIFY(sum == 21); + } + { + QList::Iterator i = list.begin(); + i += 2; + QCOMPARE(*i, 3); + i -= 1; + QCOMPARE(*i, 2); + } + { + QList::ConstIterator i = list.begin(); + i += 2; + QCOMPARE(*i, 3); + i -= 1; + QCOMPARE(*i, 2); + } + { + int sum = 0; + int i; + for (i = 0; i < list.size(); ++i) + list[i] = list[i] +1; + for (i = 0; i < list.size(); ++i) + sum += list[i]; + QVERIFY(sum == 21 + list.size()); + } + { + int sum = 0; + int i; + for (i = 0; i < list.size(); ++i) + --list[i]; + for (i = 0; i < list.size(); ++i) + sum += list[i]; + QVERIFY(sum == 21); + } + { + QMutableListIterator i(list); + while (i.hasNext()) + i.setValue(2*i.next()); + } + { + int sum = 0; + QListIterator i(list); + i.toBack(); + while (i.hasPrevious()) + sum += i.previous(); + QVERIFY(sum == 2*21); + } + { + QMutableListIterator i(list); + i.toBack(); + while (i.hasPrevious()) + i.setValue(2*i.previous()); + } + { + int sum = 0; + QListIterator i(list); + i.toBack(); + while (i.hasPrevious()) + sum += i.previous(); + QVERIFY(sum == 2*2*21); + } + { + QMutableListIterator i(list); + while (i.hasNext()) { + int a = i.next(); + i.insert(a); + } + } + { + int sum = 0; + QList::iterator i = list.begin(); + while (i != list.end()) + sum += *i++; + QVERIFY(sum == 2*2*2*21); + } + { + int duplicates = 0; + QListIterator i(list); + while (i.hasNext()) { + int a = i.next(); + if (i.hasNext() && a == i.peekNext()) + duplicates++; + } + QVERIFY(duplicates == 6); + } + { + int duplicates = 0; + QListIterator i(list); + i.toBack(); + while (i.hasPrevious()) { + int a = i.previous(); + if (i.hasPrevious() && a == i.peekPrevious()) + duplicates++; + } + QVERIFY(duplicates == 6); + } + { + QMutableListIterator i(list); + while (i.hasNext()) { + int a = i.next(); + if (i.hasNext() && + i.peekNext() == a) + i.remove(); + } + } + { + int duplicates = 0; + QMutableListIterator i = list; + i.toBack(); + while (i.hasPrevious()) { + int a = i.previous(); + if (i.hasPrevious() && a == i.peekPrevious()) + duplicates++; + } + QVERIFY(duplicates == 0); + } + { + QVERIFY(list.size() == 6); + QMutableListIterator i = list; + while (i.hasNext()) { + int a = i.peekNext(); + i.insert(42); + QVERIFY(i.peekPrevious() == 42 && i.peekNext() == a); + i.next(); + } + QVERIFY(list.size() == 12); + i.toFront(); + while (i.findNext(42)) + i.remove(); + } + { + QList l; + l << 4 << 8 << 12 << 16 << 20 << 24; + QVERIFY(l == list); + QList copy = list; + list += list; + QVERIFY(l != list && l.size() == list.size()/2 && l == copy); + l += copy; + QVERIFY(l == list); + list = copy; + } + { + QList copy = list; + list << 8; + QVERIFY(list.indexOf(8) == 1); + QVERIFY(list.indexOf(8, list.indexOf(8)+1) == 6); + int a = list.indexOf(8); + QVERIFY(list.count(8) == 2); + int r = list.removeAll(8); + QVERIFY(r == 2); + list.insert(a, 8); + QVERIFY(list == copy); + } + { + QList list; + list << "one" << "two" << "three" << "four" << "five" << "six"; + while (!list.isEmpty()) + list.removeAll(list.first()); + } + { + QList list; + list << "one" << "two" << "one" << "two"; + QVERIFY(!list.removeOne("three")); + QVERIFY(list.removeOne("two")); + QCOMPARE(list, QList() << "one" << "one" << "two");; + QVERIFY(list.removeOne("two")); + QCOMPARE(list, QList() << "one" << "one"); + QVERIFY(!list.removeOne("two")); + QCOMPARE(list, QList() << "one" << "one"); + QVERIFY(list.removeOne("one")); + QCOMPARE(list, QList() << "one"); + QVERIFY(list.removeOne("one")); + QVERIFY(list.isEmpty()); + QVERIFY(!list.removeOne("one")); + QVERIFY(list.isEmpty()); + } + { + QList copy = list; + list << 8; + QVERIFY(list.lastIndexOf(8) == 6); + QVERIFY(list.lastIndexOf(8, list.lastIndexOf(8)-1) == 1); + list = copy; + } + { + QList copy = list; + list.insert(3, 999); + QVERIFY(list[3] == 999); + list.replace(3, 222); + QVERIFY(list[3] == 222); + QVERIFY(list.contains(222) && ! list.contains(999)); + list.removeAt(3); + list = copy; + QVERIFY(list == copy); + } + { + list.clear(); + QVERIFY(list.isEmpty()); + QVERIFY(list.begin() == list.end()); + QListIterator i(list); + QVERIFY(!i.hasNext() && !i.hasPrevious()); + } + { + QList l1; + QList l2; + l1 << 1 << 2 << 3; + l2 << 4 << 5 << 6; + QList l3 = l1 + l2; + l1 += l2; + QVERIFY(l3 == l1); + } + { + QList list; + QVERIFY(list.isEmpty()); + list.append(1); + QList list2; + list2 = list; + list2.clear(); + QVERIFY(list2.size() == 0); + QVERIFY(list.size() == 1); + } + { + QList list; + list.append(1); + list = list; + QVERIFY(list.size() == 1); + } + } + { + QList list; + list.append(0); + list.append((void*)42); + QCOMPARE(list.size(), 2); + QCOMPARE(list.at(0), (void*)0); + QCOMPARE(list.at(1), (void*)42); + } + + { + QVector vector(5); + vector[0] = "99"; + vector[4] ="100"; + QList list = vector.toList(); + + QVERIFY(list.size() == 5); + QVERIFY(list.at(0) == "99"); + QVERIFY(list.at(4) == "100"); + list[0] = "10"; + QVERIFY(list.at(0) == "10"); + QVERIFY(vector.at(0) == "99"); + + } + + { + QList list; + list.append("Hello"); + + QList::iterator it = list.begin(); + QVERIFY((*it)[0] == QChar('H')); + QVERIFY(it->constData()[0] == QChar('H')); + it->replace(QChar('H'), QChar('X')); + QVERIFY(list.first() == "Xello"); + + QList::const_iterator cit = list.constBegin(); + QVERIFY((*cit).toLower() == "xello"); + QVERIFY(cit->toUpper() == "XELLO"); + } + + { + QList list; + QVERIFY(list.value(0) == 0); + int i; + list.append(&i); + QVERIFY(list.value(0) == &i); + } + { + QList list; + QVERIFY(list.value(0) == 0); + int i; + list.append(&i); + QVERIFY(list.value(0) == &i); + } + { + QList list; + QVERIFY(list.value(0) == 0); + list.append(10); + QVERIFY(list.value(0) == 10); + } + { + QList list; + QCOMPARE(list.value(0).i1, 0); + QCOMPARE(list.value(0).i2, 0); + } + + { + QList list; + list << "alpha" << "beta"; + list += list; + QVERIFY(list.size() == 4); + QVERIFY(list.at(0) == "alpha"); + QVERIFY(list.at(1) == "beta"); + QVERIFY(list.at(2) == "alpha"); + QVERIFY(list.at(3) == "beta"); + } + + // test endcases for inserting into a qlist + { + QList list; + list << "foo" << "bar"; + QVERIFY(!list.isEmpty()); + + list.insert(-1, "lessthanzero"); + QCOMPARE(list.at(0), QString("lessthanzero")); + + list.insert(0, "atzero"); + QCOMPARE(list.at(0), QString("atzero")); + + int listCount = list.count(); + list.insert(listCount, "atcount"); + QCOMPARE(list.at(listCount), QString("atcount")); + + listCount = list.count(); + list.insert(listCount + 1, "beyondcount"); + QCOMPARE(list.at(listCount), QString("beyondcount")); + } + + { + QList list1; + list1 << 0 << 1 << 2 << 3; + list1.removeFirst(); + + list1.swap(0, 0); + QVERIFY(list1 == QList() << 1 << 2 << 3); + + list1.swap(1, 1); + QVERIFY(list1 == QList() << 1 << 2 << 3); + + list1.swap(2, 2); + QVERIFY(list1 == QList() << 1 << 2 << 3); + + list1.swap(0, 1); + QVERIFY(list1 == QList() << 2 << 1 << 3); + + list1.swap(0, 2); + QVERIFY(list1 == QList() << 3 << 1 << 2); + + list1.swap(1, 2); + QVERIFY(list1 == QList() << 3 << 2 << 1); + + list1.swap(1, 2); + QVERIFY(list1 == QList() << 3 << 1 << 2); + + QList list2; + list2 << "1" << "2" << "3"; + + list2.swap(0, 0); + QVERIFY(list2 == QList() << "1" << "2" << "3"); + + list2.swap(1, 1); + QVERIFY(list2 == QList() << "1" << "2" << "3"); + + list2.swap(2, 2); + QVERIFY(list2 == QList() << "1" << "2" << "3"); + + list2.swap(0, 1); + QVERIFY(list2 == QList() << "2" << "1" << "3"); + + list2.swap(0, 2); + QVERIFY(list2 == QList() << "3" << "1" << "2"); + + list2.swap(1, 2); + QVERIFY(list2 == QList() << "3" << "2" << "1"); + + list2.swap(1, 2); + QVERIFY(list2 == QList() << "3" << "1" << "2"); + + QList list3; + list3 << 1.0 << 2.0 << 3.0; + + list3.swap(0, 0); + QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); + + list3.swap(1, 1); + QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); + + list3.swap(2, 2); + QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); + + list3.swap(0, 1); + QVERIFY(list3 == QList() << 2.0 << 1.0 << 3.0); + + list3.swap(0, 2); + QVERIFY(list3 == QList() << 3.0 << 1.0 << 2.0); + + list3.swap(1, 2); + QVERIFY(list3 == QList() << 3.0 << 2.0 << 1.0); + + list3.swap(1, 2); + QVERIFY(list3 == QList() << 3.0 << 1.0 << 2.0); + } + + // Check what happens when using references to own items. + // Ideally we should run valgrind on this. + { + int i; + + QList list1; + list1.append(reinterpret_cast(50)); + + for (i = 1; i < 100; ++i) { + list1.append(list1.at(i - 1)); + list1.prepend(list1.at(i)); + list1.insert(i, list1.at(i - 1)); + list1.insert(i, list1.at(i)); + list1.insert(i, list1.at(i + 1)); + list1.replace(i, list1.at(i - 1)); + list1.replace(i, list1.at(i)); + list1.replace(i, list1.at(i + 1)); + } + QCOMPARE(list1.size(), 496); + for (i = 0; i < list1.size(); ++i) { + QCOMPARE(list1.at(i), reinterpret_cast(50)); + } + + QList list2; + list2.append("50"); + + for (i = 1; i < 100; ++i) { + list2.append(list2.at(i - 1)); + list2.prepend(list2.at(i)); + list2.insert(i, list2.at(i - 1)); + list2.insert(i, list2.at(i)); + list2.insert(i, list2.at(i + 1)); + list2.replace(i, list2.at(i - 1)); + list2.replace(i, list2.at(i)); + list2.replace(i, list2.at(i + 1)); + } + QCOMPARE(list2.size(), 496); + for (i = 0; i < list2.size(); ++i) { + QCOMPARE(list2.at(i), QString::fromLatin1("50")); + } + + QList list3; + list3.append(50.0); + + for (i = 1; i < 100; ++i) { + list3.append(list3.at(i - 1)); + list3.prepend(list3.at(i)); + list3.insert(i, list3.at(i - 1)); + list3.insert(i, list3.at(i)); + list3.insert(i, list3.at(i + 1)); + list3.replace(i, list3.at(i - 1)); + list3.replace(i, list3.at(i)); + list3.replace(i, list3.at(i + 1)); + } + QCOMPARE(list3.size(), 496); + for (i = 0; i < list3.size(); ++i) { + QCOMPARE(list3.at(i), 50.0); + } + + QList list4; + list4.append(QTime(12, 34, 56)); + + for (i = 1; i < 100; ++i) { + list4.append(list4.at(i - 1)); + list4.prepend(list4.at(i)); + list4.insert(i, list4.at(i - 1)); + list4.insert(i, list4.at(i)); + list4.insert(i, list4.at(i + 1)); + list4.replace(i, list4.at(i - 1)); + list4.replace(i, list4.at(i)); + list4.replace(i, list4.at(i + 1)); + } + QCOMPARE(list4.size(), 496); + for (i = 0; i < list4.size(); ++i) { + QVERIFY(list4.at(i) == QTime(12, 34, 56)); + } + + } + { + QList a; + QCOMPARE(a.startsWith(1), false); + QCOMPARE(a.endsWith(1), false); + a.append(1); + QCOMPARE(a.startsWith(1), true); + QCOMPARE(a.startsWith(2), false); + QCOMPARE(a.endsWith(1), true); + QCOMPARE(a.endsWith(2), false); + a.append(2); + QCOMPARE(a.startsWith(1), true); + QCOMPARE(a.startsWith(2), false); + QCOMPARE(a.endsWith(1), false); + QCOMPARE(a.endsWith(2), true); + } +} + +void tst_Collections::linkedList() +{ + { + QLinkedList list; + QVERIFY(list.isEmpty()); + list.append(1); + list.push_back(2); + list += (3); + list << 4 << 5 << 6; + QVERIFY(!list.isEmpty()); + QVERIFY(list.size() == 6); + { + int sum = 0; + QLinkedListIterator i = list; + while (i.hasNext()) { + sum += i.next(); + } + QVERIFY(sum == 21); + } + { + int sum = 0; + QLinkedList::const_iterator i = list.begin(); + while (i != list.end()) + sum += *i++; + QVERIFY(sum == 21); + } + { + QMutableLinkedListIterator i = list; + while (i.hasNext()) + i.setValue(2*i.next()); + } + { + int sum = 0; + QLinkedListIterator i = list; + i.toBack(); + while (i.hasPrevious()) + sum += i.previous(); + QVERIFY(sum == 2*21); + } + { + QMutableLinkedListIterator i = list; + i.toBack(); + while (i.hasPrevious()) + i.setValue(2*i.previous()); + } + { + int sum = 0; + QLinkedListIterator i = list; + i.toBack(); + while (i.hasPrevious()) + sum += i.previous(); + QVERIFY(sum == 2*2*21); + } + { + QMutableLinkedListIterator i = list; + while (i.hasNext()) { + int a = i.next(); + i.insert(a); + } + } + { + int sum = 0; + QLinkedList::iterator i = list.begin(); + while (i != list.end()) + sum += *i++; + QVERIFY(sum == 2*2*2*21); + } + { + int duplicates = 0; + QLinkedListIterator i = list; + while (i.hasNext()) { + int a = i.next(); + if (i.hasNext() && a == i.peekNext()) + duplicates++; + } + QVERIFY(duplicates == 6); + } + { + int duplicates = 0; + QLinkedListIterator i = list; + i.toBack(); + while (i.hasPrevious()) { + int a = i.previous(); + if (i.hasPrevious() && a == i.peekPrevious()) + duplicates++; + } + QVERIFY(duplicates == 6); + } + { + QMutableLinkedListIterator i = list; + while (i.hasNext()) { + int a = i.next(); + if (i.hasNext() && + i.peekNext() == a) + i.remove(); + } + } + { + int duplicates = 0; + QMutableLinkedListIterator i = list; + i.toBack(); + while (i.hasPrevious()) { + int a = i.previous(); + if (i.hasPrevious() && a == i.peekPrevious()) + duplicates++; + } + QVERIFY(duplicates == 0); + } + { + QVERIFY(list.size() == 6); + QMutableLinkedListIterator i = list; + while (i.hasNext()) { + int a = i.peekNext(); + i.insert(42); + QVERIFY(i.peekPrevious() == 42 && i.peekNext() == a); + i.next(); + } + QVERIFY(list.size() == 12); + i.toFront(); + while (i.findNext(42)) + i.remove(); + } + { + QLinkedList l; + l << 4 << 8 << 12 << 16 << 20 << 24; + QVERIFY(l == list); + QLinkedList copy = list; + list += list; + QVERIFY(l != list && l.size() == list.size()/2 && l == copy); + l += copy; + QVERIFY(l == list); + list = copy; + } + { + QLinkedList copy = list; + list.prepend(999); + list.append(999); + QVERIFY(list.contains(999)); + QVERIFY(list.count(999) == 2); + list.removeAll(999); + QVERIFY(list == copy); + } + { + QLinkedList list; + list << "one" << "two" << "three" << "four" << "five" << "six"; + while (!list.isEmpty()) + list.removeAll(list.first()); + } + { + QLinkedList list; + list << "one" << "two" << "one" << "two"; + QVERIFY(!list.removeOne("three")); + QVERIFY(list.removeOne("two")); + QCOMPARE(list, QLinkedList() << "one" << "one" << "two");; + QVERIFY(list.removeOne("two")); + QCOMPARE(list, QLinkedList() << "one" << "one"); + QVERIFY(!list.removeOne("two")); + QCOMPARE(list, QLinkedList() << "one" << "one"); + QVERIFY(list.removeOne("one")); + QCOMPARE(list, QLinkedList() << "one"); + QVERIFY(list.removeOne("one")); + QVERIFY(list.isEmpty()); + QVERIFY(!list.removeOne("one")); + QVERIFY(list.isEmpty()); + } + { + list.clear(); + QVERIFY(list.isEmpty()); + QVERIFY(list.begin() == list.end()); + QLinkedListIterator i(list); + QVERIFY(!i.hasNext() && !i.hasPrevious()); + } + } + + { + QLinkedList list; + list.append("Hello"); + + QLinkedList::iterator it = list.begin(); + QVERIFY((*it)[0] == QChar('H')); + QVERIFY(it->constData()[0] == QChar('H')); + it->replace(QChar('H'), QChar('X')); + QVERIFY(list.first() == "Xello"); + + QLinkedList::const_iterator cit = list.constBegin(); + QVERIFY((*cit).toLower() == "xello"); + QVERIFY(cit->toUpper() == "XELLO"); + } + + { + QLinkedList list; + list << "alpha" << "beta"; + list += list; + QVERIFY(list.size() == 4); + QVERIFY(*list.begin() == "alpha"); + QVERIFY(*(list.begin() + 1) == "beta"); + QVERIFY(*(list.begin() + 2) == "alpha"); + QVERIFY(*(list.begin() + 3) == "beta"); + } + + { + QLinkedList a; + QCOMPARE(a.startsWith(1), false); + QCOMPARE(a.endsWith(1), false); + a.append(1); + QCOMPARE(a.startsWith(1), true); + QCOMPARE(a.startsWith(2), false); + QCOMPARE(a.endsWith(1), true); + QCOMPARE(a.endsWith(2), false); + a.append(2); + QCOMPARE(a.startsWith(1), true); + QCOMPARE(a.startsWith(2), false); + QCOMPARE(a.endsWith(1), false); + QCOMPARE(a.endsWith(2), true); + } +}; + + +void tst_Collections::vector() +{ + QVector v1; + v1 << 1 << 2 << 3; + QVector v2; + v2 << 4 << 5; + QVector v3; + v3 << 1 << 2 << 3 << 4 << 5; + QVERIFY(v1 + v2 == v3); + + QVector emptyVector; + QCOMPARE(emptyVector.size(), 0); +#if 0 + // this should trigger an assert + emptyVector.remove(3, -3); + QCOMPARE(emptyVector.size(), 0); +#endif + emptyVector.remove(0, 0); + QCOMPARE(emptyVector.size(), 0); + + QVector v4; + v4 << 1 << 2 << 3; + QCOMPARE(v4.size(), 3); + v4.remove(1, 0); + QCOMPARE(v4.size(), 3); + + QVector v; + v.append(2); + QVERIFY(*v.begin() == 2); + v.prepend(1); + + v << 3 << 4 << 5 << 6; +#if !defined(QT_NO_STL) + QVERIFY(std::binary_search(v.begin(), v.end(), 2) == true); + QVERIFY(std::binary_search(v.begin(), v.end(), 9) == false); +#endif + QVERIFY(qBinaryFind(v.begin(), v.end(), 2) == v.begin() + 1); + QVERIFY(qLowerBound(v.begin(), v.end(), 2) == v.begin() + 1); + QVERIFY(qUpperBound(v.begin(), v.end(), 2) == v.begin() + 2); + QVERIFY(qBinaryFind(v.begin(), v.end(), 9) == v.end()); + QVERIFY(qLowerBound(v.begin(), v.end(), 9) == v.end()); + QVERIFY(qUpperBound(v.begin(), v.end(), 9) == v.end()); + + v.clear(); + v << 1 << 2 << 3; + v.insert(v.begin(), 0); + v.insert(v.end(), 4); + v.insert(v.begin()+2, 9); + + QVector result; + result << 0 << 1 << 9 << 2 << 3 << 4; + + QVERIFY( v == result ); + + v.clear(); + v << 1 << 2 << 3; + v.insert(0, 0); + v.insert(4, 4); + v.insert(2, 9); + + QVERIFY( v == result ); + + QVector vec; + vec << "foo" << "bar"; + vec.reserve( 512 ); + QVERIFY(vec[0] == "foo"); + QVERIFY(vec[1] == "bar"); + + int initialLargeStaticCount = LargeStatic::count; + { + QVector vector; + vector.append(LargeStatic()); + vector.resize(0); + } + QCOMPARE(LargeStatic::count, initialLargeStaticCount); + + { + QVector vector; + vector << "alpha" << "beta"; + vector += vector; + QVERIFY(vector.size() == 4); + QVERIFY(vector.at(0) == "alpha"); + QVERIFY(vector.at(1) == "beta"); + QVERIFY(vector.at(2) == "alpha"); + QVERIFY(vector.at(3) == "beta"); + } + + int originalLargeStaticCount = LargeStatic::count; + { + QVector vector(5); + } + QVERIFY(LargeStatic::count == originalLargeStaticCount); + { + QVector vector(5); + QList list = vector.toList(); + } + QVERIFY(LargeStatic::count == originalLargeStaticCount); + { + QVector vector; + LargeStatic *dummy = 0; + for (int i = 0; i < 10000; ++i) { + delete dummy; + dummy = new LargeStatic; + vector.append(LargeStatic()); + } + delete dummy; + } + QVERIFY(LargeStatic::count == originalLargeStaticCount); + + int originalMovableCount = Movable::count; + { + QVector vector(5); + } + QVERIFY(Movable::count == originalMovableCount); + { + QVector vector(5); + QList list = vector.toList(); + } + QVERIFY(Movable::count == originalMovableCount); + { + QVector vector; + Movable *dummy = 0; + for (int i = 0; i < 10000; ++i) { + delete dummy; + dummy = new Movable; + vector.append(Movable()); + } + delete dummy; + } + QVERIFY(Movable::count == originalMovableCount); + + // Check what happens when using references to own items. + // Ideally we should run valgrind on this. + { + int i; + + QVector vect1; + vect1.append(reinterpret_cast(50)); + + for (i = 1; i < 100; ++i) { + vect1.append(vect1.at(i - 1)); + vect1.prepend(vect1.at(i)); + vect1.insert(i, vect1.at(i - 1)); + vect1.insert(i, vect1.at(i)); + vect1.insert(i, vect1.at(i + 1)); + vect1.replace(i, vect1.at(i - 1)); + vect1.replace(i, vect1.at(i)); + vect1.replace(i, vect1.at(i + 1)); + } + QCOMPARE(vect1.size(), 496); + for (i = 0; i < vect1.size(); ++i) { + QCOMPARE(vect1.at(i), reinterpret_cast(50)); + } + + QVector vect2; + vect2.append("50"); + + for (i = 1; i < 100; ++i) { + vect2.append(vect2.at(i - 1)); + vect2.prepend(vect2.at(i)); + vect2.insert(i, vect2.at(i - 1)); + vect2.insert(i, vect2.at(i)); + vect2.insert(i, vect2.at(i + 1)); + vect2.replace(i, vect2.at(i - 1)); + vect2.replace(i, vect2.at(i)); + vect2.replace(i, vect2.at(i + 1)); + } + QCOMPARE(vect2.size(), 496); + for (i = 0; i < vect2.size(); ++i) { + QCOMPARE(vect2.at(i), QString::fromLatin1("50")); + } + + QVector vect3; + vect3.append(50.0); + + for (i = 1; i < 100; ++i) { + vect3.append(vect3.at(i - 1)); + vect3.prepend(vect3.at(i)); + vect3.insert(i, vect3.at(i - 1)); + vect3.insert(i, vect3.at(i)); + vect3.insert(i, vect3.at(i + 1)); + vect3.replace(i, vect3.at(i - 1)); + vect3.replace(i, vect3.at(i)); + vect3.replace(i, vect3.at(i + 1)); + } + QCOMPARE(vect3.size(), 496); + for (i = 0; i < vect3.size(); ++i) { + QCOMPARE(vect3.at(i), 50.0); + } + + QVector vect4; + vect4.append(QTime(12, 34, 56)); + + for (i = 1; i < 100; ++i) { + vect4.append(vect4.at(i - 1)); + vect4.prepend(vect4.at(i)); + vect4.insert(i, vect4.at(i - 1)); + vect4.insert(i, vect4.at(i)); + vect4.insert(i, vect4.at(i + 1)); + vect4.replace(i, vect4.at(i - 1)); + vect4.replace(i, vect4.at(i)); + vect4.replace(i, vect4.at(i + 1)); + } + QCOMPARE(vect4.size(), 496); + for (i = 0; i < vect4.size(); ++i) { + QVERIFY(vect4.at(i) == QTime(12, 34, 56)); + } + } + + // this used to trigger an uninitialized read in valgrind + QVector foo; + foo.resize(144); + + { + QVector a; + QCOMPARE(a.startsWith(1), false); + QCOMPARE(a.endsWith(1), false); + a.append(1); + QCOMPARE(a.startsWith(1), true); + QCOMPARE(a.startsWith(2), false); + QCOMPARE(a.endsWith(1), true); + QCOMPARE(a.endsWith(2), false); + a.append(2); + QCOMPARE(a.startsWith(1), true); + QCOMPARE(a.startsWith(2), false); + QCOMPARE(a.endsWith(1), false); + QCOMPARE(a.endsWith(2), true); + } +} + +void tst_Collections::byteArray() +{ + QByteArray hello = "hello"; + QByteArray ello = "ello"; + QByteArray World = "World"; + QByteArray Wor = "Wor"; + QByteArray helloWorld = "helloWorld"; + QVERIFY(hello + World == helloWorld); + QVERIFY(hello + "World" == helloWorld); + QVERIFY("hello" + World == helloWorld); + + + QByteArray l; + QVERIFY('h' + ello == hello); + QVERIFY(Wor + 'l' + 'd' == "World"); + QVERIFY(hello + World == "helloWorld"); + QVERIFY(hello + "World" == "helloWorld"); + QVERIFY("hello" + World == "helloWorld"); + QVERIFY('h' + ello == "hello"); + QVERIFY(Wor + 'l' + 'd' == "World"); + QVERIFY("helloWorld" == hello + World); + QVERIFY("helloWorld" == hello + "World"); + QVERIFY("helloWorld" == "hello" + World); + QVERIFY("hello" == 'h' + ello); + QVERIFY("World" == Wor + 'l' + 'd'); + + QVERIFY(hello.contains('e')); + QVERIFY (true == hello.contains('e')); + QVERIFY (hello.contains('e') != false); + + QVERIFY(hello.indexOf('e') == 1); + QVERIFY(hello.indexOf('e', -10) == 1); + QVERIFY(hello.indexOf('l') == 2); + QVERIFY(hello.indexOf('l',2) == 2); + QVERIFY(hello.indexOf('l',3) == 3); + + QByteArray large = "000 100 200 300 400 500 600 700 800 900"; + + QVERIFY(large.indexOf("700") == 28); + QVERIFY(large.indexOf("700", 28) == 28); + QVERIFY(large.indexOf("700", 29) == -1); + QVERIFY(large.lastIndexOf("700") == 28); + QVERIFY(large.lastIndexOf("700", 28) == 28); + QVERIFY(large.lastIndexOf("700", 27) == -1); + + QVERIFY(large.contains("200")); + QVERIFY(!large.contains("201")); + QVERIFY(large.contains('3')); + QVERIFY(!large.contains('a')); + + QVERIFY(large.count("00") == 11); + QVERIFY(large.count('3') == 1); + QVERIFY(large.count('0') == 21); + QVERIFY(large.count("0") == 21); + QVERIFY(large.count("200") == 1); + QVERIFY(large.count("201") == 0); + + QVERIFY(hello.left(0) == ""); + QVERIFY(!hello.left(0).isNull()); + QVERIFY(hello.left(1) == "h"); + QVERIFY(hello.left(2) == "he"); + QVERIFY(hello.left(200) == "hello"); + QVERIFY(hello.left(hello.size()) == hello); + QVERIFY(hello.left(hello.size()+1) == hello); + + QVERIFY(hello.right(0) == ""); + QVERIFY(!hello.right(0).isNull()); + QVERIFY(hello.right(1) == "o"); + QVERIFY(hello.right(2) == "lo"); + QVERIFY(hello.right(200) == "hello"); + QVERIFY(hello.right(hello.size()) == hello); + QVERIFY(hello.right(hello.size()+1) == hello); + + QVERIFY(!hello.mid(0, 0).isNull()); + QVERIFY(hello.mid(0, 1) == "h"); + QVERIFY(hello.mid(0, 2) == "he"); + QVERIFY(hello.mid(0, 200) == "hello"); + QVERIFY(hello.mid(0) == "hello"); + QVERIFY(hello.mid(0, hello.size()) == hello); + QVERIFY(hello.mid(0, hello.size()+1) == hello); + + QVERIFY(hello.mid(hello.size()-0) == ""); + + QVERIFY(hello.mid(hello.size()-0).isNull()); // weird but valid 3.x semantics + QVERIFY(hello.mid(hello.size()-1) == "o"); + QVERIFY(hello.mid(hello.size()-2) == "lo"); + QVERIFY(hello.mid(hello.size()-200) == "hello"); + + QByteArray null; + QByteArray nonNull = ""; + QVERIFY(null.left(10).isNull()); + QVERIFY(null.mid(0).isNull()); + +#if 0 + QVERIFY(null == QByteArray::null); + QVERIFY(QByteArray::null == null); + QVERIFY(nonNull != QByteArray::null); + QVERIFY(QByteArray::null != nonNull); + QVERIFY(null == nonNull); + QVERIFY(QByteArray::null == QByteArray::null); +#endif + + QByteArray str = "Hello"; + QByteArray cstr(str.data(), str.size()); + QVERIFY(str == "Hello"); + QVERIFY(cstr == "Hello"); + cstr.clear(); + QVERIFY(str == "Hello"); + QVERIFY(cstr.isEmpty()); + + { + QByteArray ba1("Foo"); + ba1.prepend(ba1); + QCOMPARE(ba1, QByteArray("FooFoo")); + ba1.append(ba1); + QCOMPARE(ba1, QByteArray("FooFooFooFoo")); + ba1.insert(2, ba1); + QCOMPARE(ba1, QByteArray("FoFooFooFooFoooFooFooFoo")); + ba1.replace(3, 3, ba1); + QCOMPARE(ba1, QByteArray("FoFFoFooFooFooFoooFooFooFooooFooFoooFooFooFoo")); + ba1 = "FooFoo"; + ba1.replace(char('F'), ba1); + QCOMPARE(ba1, QByteArray("FooFooooFooFoooo")); + ba1 = "FooFoo"; + ba1.replace(char('o'), ba1); + QCOMPARE(ba1, QByteArray("FFooFooFooFooFFooFooFooFoo")); + + ba1.replace(ba1, "xxx"); + QCOMPARE(ba1, QByteArray("xxx")); + ba1.replace(ba1, QByteArray("yyy")); + QCOMPARE(ba1, QByteArray("yyy")); + ba1 += ba1; + QCOMPARE(ba1, QByteArray("yyyyyy")); + + ba1.remove(1, -1); // do nothing + QCOMPARE(ba1, QByteArray("yyyyyy")); + + ba1.replace(0, -1, "ZZZ"); + QCOMPARE(ba1, QByteArray("ZZZyyyyyy")); + } +}; + +void tst_Collections::stack() +{ + QStack stack; + stack.push(1); + stack.push(2); + stack.push(3); + QVectorIterator i = stack; + i.toBack(); + int sum = 0; + while (i.hasPrevious()) + sum += i.previous(); + QVERIFY(sum == 6); + + sum = 0; + for (QStack::iterator i = stack.begin(); i != stack.end(); ++i) + sum += *i; + QVERIFY(sum == 6); + + while (!stack.isEmpty()) + sum -= stack.pop(); + QVERIFY(sum == 0); +} + +void tst_Collections::hash() +{ + const char *hello = "hello"; + const char *world = "world"; + const char *allo = "allo"; + const char *monde = "monde"; + + { + typedef QHash Hash; + Hash hash; + QString key; + for (int i = 0; i < 10; ++i) { + key[0] = i + '0'; + for (int j = 0; j < 10; ++j) { + key[1] = j + '0'; + hash.insert(key, "V" + key); + } + } + + for (int i = 0; i < 10; ++i) { + key[0] = i + '0'; + for (int j = 0; j < 10; ++j) { + key[1] = j + '0'; + hash.remove(key); + } + } + } + + { + typedef QHash Hash; + Hash hash; + hash.insert(1, hello); + hash.insert(2, world); + + QVERIFY(hash.size() == 2); + QVERIFY(!hash.isEmpty()); + + { + Hash hash2 = hash; + hash2 = hash; + hash = hash2; + hash2 = hash2; + hash = hash; + hash2.clear(); + hash2 = hash2; + QVERIFY(hash2.size() == 0); + QVERIFY(hash2.isEmpty()); + } + QVERIFY(hash.size() == 2); + + { + Hash hash2 = hash; + hash2[1] = allo; + hash2[2] = monde; + + QVERIFY(hash2[1] == allo); + QVERIFY(hash2[2] == monde); + QVERIFY(hash[1] == hello); + QVERIFY(hash[2] == world); + + hash2[1] = hash[1]; + hash2[2] = hash[2]; + + QVERIFY(hash2[1] == hello); + QVERIFY(hash2[2] == world); + + hash[1] = hash[1]; + QVERIFY(hash[1] == hello); + } + + { + Hash hash2 = hash; + hash2.detach(); + hash2.remove(1); + QVERIFY(hash2.size() == 1); + hash2.remove(1); + QVERIFY(hash2.size() == 1); + hash2.remove(0); + QVERIFY(hash2.size() == 1); + hash2.remove(2); + QVERIFY(hash2.size() == 0); + QVERIFY(hash.size() == 2); + } + + hash.detach(); + + { + Hash::iterator it1 = hash.find(1); + QVERIFY(it1 != hash.end()); + + Hash::iterator it2 = hash.find(0); + QVERIFY(it2 != hash.begin()); + QVERIFY(it2 == hash.end()); + + *it1 = monde; + QVERIFY(*it1 == monde); + QVERIFY(hash[1] == monde); + + *it1 = hello; + QVERIFY(*it1 == hello); + QVERIFY(hash[1] == hello); + + hash[1] = monde; + QVERIFY(it1.key() == 1); + QVERIFY(it1.value() == monde); + QVERIFY(*it1 == monde); + QVERIFY(hash[1] == monde); + + hash[1] = hello; + QVERIFY(*it1 == hello); + QVERIFY(hash[1] == hello); + } + + { + const Hash hash2 = hash; + + Hash::const_iterator it1 = hash2.find(1); + QVERIFY(it1 != hash2.end()); + QVERIFY(it1.key() == 1); + QVERIFY(it1.value() == hello); + QVERIFY(*it1 == hello); + + Hash::const_iterator it2 = hash2.find(2); + QVERIFY(it1 != it2); + QVERIFY(it1 != hash2.end()); + QVERIFY(it2 != hash2.end()); + + int count = 0; + it1 = hash2.begin(); + while (it1 != hash2.end()) { + count++; + ++it1; + } + QVERIFY(count == 2); + + count = 0; + it1 = hash.begin(); + while (it1 != hash.end()) { + count++; + ++it1; + } + QVERIFY(count == 2); + } + + { + QVERIFY(hash.contains(1)); + QVERIFY(hash.contains(2)); + QVERIFY(!hash.contains(0)); + QVERIFY(!hash.contains(3)); + } + + { + QVERIFY(hash.value(1) == hello); + QVERIFY(hash.value(2) == world); + QVERIFY(hash.value(3) == 0); + QVERIFY(hash.value(1, allo) == hello); + QVERIFY(hash.value(2, allo) == world); + QVERIFY(hash.value(3, allo) == allo); + QVERIFY(hash.value(0, monde) == monde); + } + + { + QHash hash; + for (int i = 0; i < 10; i++) + hash.insert(i, LargeStatic()); + QVERIFY(LargeStatic::count == 10); + hash.remove(7); + QVERIFY(LargeStatic::count == 9); + + } + QVERIFY(LargeStatic::count == 0); + { + QHash hash; + QVERIFY(((const QHash*) &hash)->operator[](7) == 0); + } + + { + /* + This test relies on a certain implementation of + QHash. If you change the way QHash works internally, + change this test as well. + */ + QHash hash; + for (int i = 0; i < 1000; ++i) + hash.insert(i, i); + QVERIFY(hash.capacity() == 1031); + hash.squeeze(); + QVERIFY(hash.capacity() == 521); + + hash.insert(12345, 12345); + QVERIFY(hash.capacity() == 1031); + + for (int j = 0; j < 900; ++j) + hash.remove(j); + QVERIFY(hash.capacity() == 257); + hash.squeeze(); + QVERIFY(hash.capacity() == 67); + hash.reserve(0); + } + } + + { + QHash hash; + hash.insert(0, "Hello"); + + QHash::iterator it = hash.begin(); + QVERIFY((*it)[0] == QChar('H')); + QVERIFY(it->constData()[0] == QChar('H')); + it->replace(QChar('H'), QChar('X')); + QVERIFY(*hash.begin() == "Xello"); + + QHash::const_iterator cit = hash.constBegin(); + QVERIFY((*cit).toLower() == "xello"); + QVERIFY(cit->toUpper() == "XELLO"); + } + + { + QHash hash1, hash2; + hash1.insertMulti(1, "Alpha"); + hash1.insertMulti(1, "Gamma"); + hash2.insertMulti(1, "Beta"); + hash2.insertMulti(1, "Gamma"); + hash2.insertMulti(1, "Gamma"); + + hash1.unite(hash2); + QCOMPARE(hash1.size(), 5); + QCOMPARE(hash1.values(), + (QList() << "Gamma" << "Gamma" << "Beta" << "Gamma" << "Alpha")); + + hash2 = hash1; + hash2.unite(hash2); + QCOMPARE(hash2.size(), 10); + QCOMPARE(hash2.values(), hash1.values() + hash1.values()); + } + +#if 0 + { + QMultiHash hash1; + hash1.insert("1", 2); + hash1.insert("1", 1); + hash1.insert("a", 3); + hash1.insert("a", 2); + hash1.insert("a", 1); + hash1.insert("b", 2); + hash1.insert("b", 1); + + // hash1: [ "1" -> 1, "1" -> 2, "a" -> 1, "a" -> 2, "a" -> 3, "b" -> 1, "b" -> 2 ] + + QHashIterator i1(hash1); + i1.toBack(); + + bool found; + + found = i1.findPreviousKey("1"); + QVERIFY(found && i1.value() == 2); + + found = i1.findPreviousKey("1"); + QVERIFY(found && i1.value() == 1); + + found = i1.findPreviousKey("1"); + QVERIFY(!found); + + i1.toFront(); + found = i1.findNextKey("1"); + QVERIFY(found && i1.value() == 1); + + found = i1.findNextKey("1"); + QVERIFY(found && i1.value() == 2); + + found = i1.findNextKey("1"); + QVERIFY(!found); + + i1.toBack(); + found = i1.findPreviousKey("b"); + QVERIFY(found && i1.value() == 2); + + found = i1.findPreviousKey("b"); + QVERIFY(found && i1.value() == 1); + + found = i1.findPreviousKey("b"); + QVERIFY(!found); + + i1.toFront(); + found = i1.findNextKey("b"); + QVERIFY(found && i1.value() == 1); + + found = i1.findNextKey("b"); + QVERIFY(found && i1.value() == 2); + + found = i1.findNextKey("b"); + QVERIFY(!found); + } +#endif +} + +void tst_Collections::map() +{ + const char *hello = "hello"; + const char *world = "world"; + const char *allo = "allo"; + const char *monde = "monde"; + + { + typedef QMap Map; + Map map; + map.insert(1, hello); + map.insert(2, world); + + QVERIFY(*map.begin() == hello); + + QVERIFY(map.size() == 2); + QVERIFY(!map.isEmpty()); + + { + Map map2 = map; + map2 = map; + map = map2; + map2 = map2; + map = map; + map2.clear(); + map2 = map2; + QVERIFY(map2.size() == 0); + QVERIFY(map2.isEmpty()); + } + QVERIFY(map.size() == 2); + + { + Map map2 = map; + map2[1] = allo; + map2[2] = monde; + + QVERIFY(map2[1] == allo); + QVERIFY(map2[2] == monde); + QVERIFY(map[1] == hello); + QVERIFY(map[2] == world); + + map2[1] = map[1]; + map2[2] = map[2]; + + QVERIFY(map2[1] == hello); + QVERIFY(map2[2] == world); + + map[1] = map[1]; + QVERIFY(map[1] == hello); + } + + { + Map map2 = map; + map2.detach(); + map2.remove(1); + QVERIFY(map2.size() == 1); + map2.remove(1); + QVERIFY(map2.size() == 1); + map2.remove(0); + QVERIFY(map2.size() == 1); + map2.remove(2); + QVERIFY(map2.size() == 0); + QVERIFY(map.size() == 2); + } + + map.detach(); + + { + Map::iterator it1 = map.find(1); + QVERIFY(it1 == map.begin()); + QVERIFY(it1 != map.end()); + + Map::iterator it2 = map.find(0); + QVERIFY(it2 != map.begin()); + QVERIFY(it2 == map.end()); + + *it1 = monde; + QVERIFY(*it1 == monde); + QVERIFY(map[1] == monde); + + *it1 = hello; + QVERIFY(*it1 == hello); + QVERIFY(map[1] == hello); + + map[1] = monde; + QVERIFY(it1.key() == 1); + QVERIFY(it1.value() == monde); + QVERIFY(*it1 == monde); + QVERIFY(map[1] == monde); + + map[1] = hello; + QVERIFY(*it1 == hello); + QVERIFY(map[1] == hello); + + *++it1 = allo; + QVERIFY(*it1 == allo); + QVERIFY(map[2] == allo); + *it1 = world; + + ++it1; + QVERIFY(it1 == map.end()); + + int count = 0; + it1 = map.begin(); + while (it1 != map.end()) { + count++; + ++it1; + } + QVERIFY(count == 2); + } + + { + const Map map2 = map; + + Map::const_iterator it1 = map2.find(1); + QVERIFY(it1 != map2.end()); + QVERIFY(it1.key() == 1); + QVERIFY(it1.value() == hello); + QVERIFY(*it1 == hello); + ++it1; + + Map::const_iterator it2 = map2.find(2); + QVERIFY(it1 == it2); + ++it1; + QVERIFY(it1 == map2.end()); + QVERIFY(it2 != map2.end()); + QVERIFY(it1 != it2); + + int count = 0; + it1 = map2.begin(); + while (it1 != map2.end()) { + count++; + ++it1; + } + QVERIFY(count == 2); + + count = 0; + it1 = map.begin(); + while (it1 != map.end()) { + count++; + ++it1; + } + QVERIFY(count == 2); + } + + { + QVERIFY(map.contains(1)); + QVERIFY(map.contains(2)); + QVERIFY(!map.contains(0)); + QVERIFY(!map.contains(3)); + } + + { + QVERIFY(map.value(1) == hello); + QVERIFY(map.value(2) == world); + QVERIFY(map.value(3) == 0); + QVERIFY(map.value(1, allo) == hello); + QVERIFY(map.value(2, allo) == world); + QVERIFY(map.value(3, allo) == allo); + QVERIFY(map.value(0, monde) == monde); + } + int originalLargeStaticCount = LargeStatic::count; + { + QMap map; + for (int i = 0; i < 10; i++) + map.insert(i, LargeStatic()); + QVERIFY(LargeStatic::count == (originalLargeStaticCount + 10)); + map.remove(7); + QVERIFY(LargeStatic::count == (originalLargeStaticCount + 9)); + + } + QVERIFY(LargeStatic::count == originalLargeStaticCount); + { + QMap map; + QVERIFY(((const QMap*) &map)->operator[](7) == 0); + } + + { + QMap map; + map[0] = 1; + map[1] = 2; + map[2] = 4; + map[3] = 8; + int sum = 0; + int sumkey = 0; + QMapIterator i = map; + while (i.hasNext()) { + sum += i.next().value(); + sumkey += i.key(); + } + QVERIFY(sum == 15); + QVERIFY(sumkey == 6); + } + { + QMap map; + map[0] = 1; + map[1] = 2; + map[2] = 4; + map[3] = 8; + int sum = 0; + QMutableMapIterator i = map; + while(i.hasNext()) + if (i.next().key() == 2) + i.remove(); + i.toFront(); + while(i.hasNext()) { + sum += i.next().value(); + i.setValue(10); + i.value() += 22; + QVERIFY(i.value() == 32); + } + QVERIFY(sum == 11); + } + { + QMap map; + map[0] = 1; + QMutableMapIterator i(map); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + QCOMPARE(i.key(), 0); + QCOMPARE(i.value(), 1); + } + } + } + + { + QMultiMap map1; + map1.insert("1", 2); + map1.insert("1", 1); + map1.insert("a", 3); + map1.insert("a", 2); + map1.insert("a", 1); + map1.insert("b", 2); + map1.insert("b", 1); + + // map1: [ "1" -> 1, "1" -> 2, "a" -> 1, "a" -> 2, "a" -> 3, "b" -> 1, "b" -> 2 ] + +#if 0 + QMapIterator i1(map1); + i1.toBack(); + + bool found; + found = i1.findPreviousKey("1"); + QVERIFY(found && i1.value() == 2); + + found = i1.findPreviousKey("1"); + QVERIFY(found && i1.value() == 1); + + found = i1.findPreviousKey("1"); + QVERIFY(!found); + + i1.toFront(); + found = i1.findNextKey("1"); + QVERIFY(found && i1.value() == 1); + + found = i1.findNextKey("1"); + QVERIFY(found && i1.value() == 2); + + found = i1.findNextKey("1"); + QVERIFY(!found); + + i1.toBack(); + found = i1.findPreviousKey("b"); + QVERIFY(found && i1.value() == 2); + + found = i1.findPreviousKey("b"); + QVERIFY(found && i1.value() == 1); + + found = i1.findPreviousKey("b"); + QVERIFY(!found); + + i1.toFront(); + found = i1.findNextKey("b"); + QVERIFY(found && i1.value() == 1); + + found = i1.findNextKey("b"); + QVERIFY(found && i1.value() == 2); + + found = i1.findNextKey("b"); + QVERIFY(!found); +#endif + + QMultiMap::iterator j1, k1; + + j1 = map1.lowerBound("0"); k1 = map1.upperBound("0"); + QVERIFY(j1 == map1.begin() && k1 == j1); + j1 = map1.lowerBound("00"); k1 = map1.upperBound("00"); + QVERIFY(j1 == map1.find("1") && k1 == j1); + j1 = map1.lowerBound("1"); k1 = map1.upperBound("1"); + QVERIFY(j1 == map1.find("1") && --(--k1) == j1); + j1 = map1.lowerBound("11"); k1 = map1.upperBound("11"); + QVERIFY(j1 == map1.find("a") && k1 == j1); + j1 = map1.lowerBound("a"); k1 = map1.upperBound("a"); + QVERIFY(j1 == map1.find("a") && k1 == map1.find("b")); + QVERIFY(j1.value() == 1 && j1.value() == 1); + j1 = map1.lowerBound("aa"); k1 = map1.upperBound("aa"); + QVERIFY(j1 == map1.find("b") && k1 == j1); + QVERIFY(j1.value() == 1); + j1 = map1.lowerBound("b"); k1 = map1.upperBound("b"); + QVERIFY(j1 == map1.find("b") && k1 == map1.end()); + QVERIFY(j1.value() == 1); + j1 = map1.lowerBound("bb"); k1 = map1.upperBound("bb"); + QVERIFY(j1 == map1.end() && k1 == j1); + + const QMultiMap map2 = map1; + QMultiMap::const_iterator j2, k2; + + j2 = map2.lowerBound("0"); k2 = map2.upperBound("0"); + QVERIFY(j2 == map2.begin() && k2 == j2); + j2 = map2.lowerBound("00"); k2 = map2.upperBound("00"); + QVERIFY(j2 == map2.find("1") && k2 == j2); + j2 = map2.lowerBound("1"); k2 = map2.upperBound("1"); + QVERIFY(j2 == map2.find("1") && --(--k2) == j2); + j2 = map2.lowerBound("11"); k2 = map2.upperBound("11"); + QVERIFY(j2 == map2.find("a") && k2 == j2); + j2 = map2.lowerBound("a"); k2 = map2.upperBound("a"); + QVERIFY(j2 == map2.find("a") && k2 == map2.find("b")); + QVERIFY(j2.value() == 1 && j2.value() == 1); + j2 = map2.lowerBound("aa"); k2 = map2.upperBound("aa"); + QVERIFY(j2 == map2.find("b") && k2 == j2); + QVERIFY(j2.value() == 1); + j2 = map2.lowerBound("b"); k2 = map2.upperBound("b"); + QVERIFY(j2 == map2.find("b") && k2 == map2.end()); + QVERIFY(j2.value() == 1); + j2 = map2.lowerBound("bb"); k2 = map2.upperBound("bb"); + QVERIFY(j2 == map2.end() && k2 == j2); + } + + { + QMap map; + map.insert(0, "Hello"); + + QMap::iterator it = map.begin(); + QVERIFY((*it)[0] == QChar('H')); + QVERIFY(it->constData()[0] == QChar('H')); + it->replace(QChar('H'), QChar('X')); + QVERIFY(*map.begin() == "Xello"); + + QMap::const_iterator cit = map.constBegin(); + QVERIFY((*cit).toLower() == "xello"); + QVERIFY(cit->toUpper() == "XELLO"); + } + + { + QMap map1, map2; + map1.insertMulti(1, "Alpha"); + map1.insertMulti(1, "Gamma"); + map2.insertMulti(1, "Beta"); + map2.insertMulti(1, "Gamma"); + map2.insertMulti(1, "Gamma"); + + map1.unite(map2); + QCOMPARE(map1.size(), 5); + QCOMPARE(static_cast(map1.values()), + (QStringList() << "Gamma" << "Gamma" << "Beta" << "Gamma" << "Alpha")); + + map2 = map1; + map2.unite(map2); + QCOMPARE(map2.size(), 10); + QCOMPARE(map2.values(), map1.values() + map1.values()); + } +} + +void tst_Collections::qstring() +{ + QString hello = "hello"; + QString ello = "ello"; + QString World = "World"; + QString Wor = "Wor"; + QString helloWorld = "helloWorld"; + + QString s = hello + "World"; + QVERIFY(hello + World == helloWorld); + QVERIFY(hello + "World" == helloWorld); + QVERIFY("hello" + World == helloWorld); + + + QString l; + QVERIFY('h' + ello == hello); + QVERIFY(Wor + 'l' + 'd' == "World"); + QVERIFY(hello + World == "helloWorld"); + QVERIFY(hello + "World" == "helloWorld"); + QVERIFY("hello" + World == "helloWorld"); + QVERIFY('h' + ello == "hello"); + QVERIFY(Wor + 'l' + 'd' == "World"); + QVERIFY("helloWorld" == hello + World); + QVERIFY("helloWorld" == hello + "World"); + QVERIFY("helloWorld" == "hello" + World); + QVERIFY("hello" == 'h' + ello); + QVERIFY("World" == Wor + 'l' + 'd'); + + QVERIFY(hello.contains('e')); + QVERIFY (true == hello.contains('e')); + QVERIFY (hello.contains('e') != false); + + QVERIFY(hello.indexOf('e') == 1); + QVERIFY(hello.indexOf('e', -10) == 1); + QVERIFY(hello.indexOf('l') == 2); + QVERIFY(hello.indexOf('l',2) == 2); + QVERIFY(hello.indexOf('l',3) == 3); + + QString large = "000 100 200 300 400 500 600 700 800 900"; + + QVERIFY(large.indexOf("700") == 28); + QVERIFY(large.indexOf("700", 28) == 28); + QVERIFY(large.indexOf("700", 29) == -1); + QVERIFY(large.lastIndexOf("700") == 28); + QVERIFY(large.lastIndexOf("700", 28) == 28); + QVERIFY(large.lastIndexOf("700", 27) == -1); + + QVERIFY(large.contains("200")); + QVERIFY(!large.contains("201")); + QVERIFY(large.contains('3')); + QVERIFY(!large.contains('a')); + + QVERIFY(large.count("00") == 11); + QVERIFY(large.count('3') == 1); + QVERIFY(large.count('0') == 21); + QVERIFY(large.count("0") == 21); + QVERIFY(large.count("200") == 1); + QVERIFY(large.count("201") == 0); + + QVERIFY(hello.left(0) == ""); + QVERIFY(!hello.left(0).isNull()); + QVERIFY(hello.left(1) == "h"); + QVERIFY(hello.left(2) == "he"); + QVERIFY(hello.left(200) == "hello"); + QVERIFY(hello.left(hello.size()) == hello); + QVERIFY(hello.left(hello.size()+1) == hello); + + QVERIFY(hello.right(0) == ""); + QVERIFY(!hello.right(0).isNull()); + QVERIFY(hello.right(1) == "o"); + QVERIFY(hello.right(2) == "lo"); + QVERIFY(hello.right(200) == "hello"); + QVERIFY(hello.right(hello.size()) == hello); + QVERIFY(hello.right(hello.size()+1) == hello); + + QVERIFY(!hello.mid(0, 0).isNull()); + QVERIFY(hello.mid(0, 1) == "h"); + QVERIFY(hello.mid(0, 2) == "he"); + QVERIFY(hello.mid(0, 200) == "hello"); + QVERIFY(hello.mid(0) == "hello"); + QVERIFY(hello.mid(0, hello.size()) == hello); + QVERIFY(hello.mid(0, hello.size()+1) == hello); + + QVERIFY(hello.mid(hello.size()-0) == ""); + + QVERIFY(hello.mid(hello.size()-0).isNull()); + QVERIFY(hello.mid(hello.size()-1) == "o"); + QVERIFY(hello.mid(hello.size()-2) == "lo"); + QVERIFY(hello.mid(hello.size()-200) == "hello"); + + QString null; + QString nonNull = ""; + QVERIFY(null.left(10).isNull()); + QVERIFY(null.mid(0).isNull()); + + QVERIFY(null == QString::null); + QVERIFY(QString::null == null); + QVERIFY(nonNull != QString::null); + QVERIFY(QString::null != nonNull); + QVERIFY(null == nonNull); + QVERIFY(QString::null == QString::null); + + QString fill = "123"; + fill.fill('a'); + QVERIFY(fill == "aaa"); + + s.clear(); + s = hello; + s.append(World); + QVERIFY(s == helloWorld); + s.clear(); + s = World; + s.insert(0,hello); + QVERIFY(s == helloWorld); + s = "012345"; + s.insert(3, 'E'); + QVERIFY(s == "012E345"); + s.insert(3, "INSID"); + QVERIFY(s == "012INSIDE345"); + s = "short"; + s.insert(7, 'E'); + QVERIFY(s == "short E"); + s = "short"; + s.insert(7, "END"); + QVERIFY(s == "short END"); + + QVERIFY(QString::fromLatin1("hello") == "hello"); + + s = "first"; + QVERIFY(s.toLatin1() == "first"); + s = "second"; + QVERIFY(s.toLatin1() == "second"); + s.clear(); + QVERIFY(s.isNull()); + QVERIFY(s.toLatin1().size() == 0); + QVERIFY(s.toLatin1().isEmpty()); + QVERIFY(s.toLatin1().isNull()); + + s = "first-utf8"; + QVERIFY(s.toUtf8() == "first-utf8"); + s = "second-utf8"; + QVERIFY(s.toUtf8() == "second-utf8"); + s.clear(); + QVERIFY(s.isNull()); + QVERIFY(s.toUtf8().size() == 0); + QVERIFY(s.toUtf8().isEmpty()); + QVERIFY(s.toUtf8().isNull()); + + s = "first-utf8"; + QVERIFY(s.toUtf8() == "first-utf8"); + s = "second-utf8"; + QVERIFY(s.toUtf8() == "second-utf8"); + s.clear(); + QVERIFY(s.isNull()); + QVERIFY(s.toUtf8().size() == 0); + QVERIFY(s.toUtf8().isEmpty()); + QVERIFY(s.toUtf8().isNull()); + + s = "first-local8Bit"; + QVERIFY(s.toLocal8Bit() == "first-local8Bit"); + s = "second-local8Bit"; + QVERIFY(s.toLocal8Bit() == "second-local8Bit"); + s.clear(); + QVERIFY(s.isNull()); + QVERIFY(s.toLocal8Bit().size() == 0); + QVERIFY(s.toLocal8Bit().isEmpty()); + + s = "first-ascii"; + QVERIFY(s.toAscii() == "first-ascii"); + s = "second-ascii"; + QVERIFY(s.toAscii() == "second-ascii"); + s.clear(); + QVERIFY(s.isNull()); + QVERIFY(s.toAscii().size() == 0); + QVERIFY(s.toAscii().isEmpty()); + QVERIFY(s.toAscii().isNull()); + + s = "ascii"; + s += (uchar) 0xb0; + QVERIFY(s.toUtf8() != s.toLatin1()); + QString sa = s.toLatin1().constData(); + QVERIFY(sa[sa.length()-1] == (ushort) 0xb0); + QVERIFY(sa.left(sa.length()-1) == "ascii"); + + QVERIFY(s == QString::fromUtf8(s.toUtf8().constData())); + + s = "12"; + s.append('3'); + s += '4'; + QVERIFY(s == "1234"); + + s = "repend"; + s.prepend('p'); + QVERIFY(s == "prepend"); + s.prepend("abc "); + QVERIFY(s == "abc prepend"); + + s = " whitespace "; + QVERIFY(s.trimmed() == "whitespace"); + s = " lots of stuff "; + QVERIFY(s.simplified() == "lots of stuff"); + + s = "a hat, a stick, a ski"; + QVERIFY(s[2] == 'h'); + QVERIFY(s[1] < 'b'); + + + s = "12223"; + s.remove(1, 2); + QVERIFY(s == "123"); + + s = "(%1)(%2)"; + s = s.arg("foo").arg(7); + QVERIFY(s == "(foo)(7)"); + + +#if 0 + s = "stl rocks"; + std::string stl_string = s; + s = stl_string; + QVERIFY(s == "stl rocks"); +#endif + + { + QString str("Bananas"); + QVERIFY(str.startsWith("Ban")); + QVERIFY(false == str.startsWith("Car")); + } + { + QString str("Bananas"); + QVERIFY(str.endsWith("anas")); + QVERIFY(false == str.endsWith("pple")); + } + + + QString str = "Hello"; + QString cstr = QString::fromRawData(str.unicode(), str.length()); + QVERIFY(str == "Hello"); + QVERIFY(cstr == "Hello"); + cstr.clear(); + QVERIFY(str == "Hello"); + QVERIFY(cstr.isEmpty()); + + { + QString str1("Foo"); + str1.prepend(str1); + QCOMPARE(str1, QString("FooFoo")); + str1.append(str1); + QCOMPARE(str1, QString("FooFooFooFoo")); + str1.insert(2, str1); + QCOMPARE(str1, QString("FoFooFooFooFoooFooFooFoo")); + str1.replace(3, 3, str1); + QCOMPARE(str1, QString("FoFFoFooFooFooFoooFooFooFooooFooFoooFooFooFoo")); + str1 = "FooFoo"; + str1.replace(char('F'), str1); + QCOMPARE(str1, QString("FooFooooFooFoooo")); + str1 = "FooFoo"; + str1.replace(char('o'), str1); + QCOMPARE(str1, QString("FFooFooFooFooFFooFooFooFoo")); + + str1 = "Foo"; + str1.replace("Foo", str1); + QCOMPARE(str1, QString("Foo")); + str1.replace(str1, str1); + QCOMPARE(str1, QString("Foo")); + + str1 = "Foo"; + str1.replace("Foo", str1, Qt::CaseInsensitive); + QCOMPARE(str1, QString("Foo")); + str1.replace(str1, str1); + QCOMPARE(str1, QString("Foo")); + + str1 = "FooFoo"; + str1.reserve(100); + str1.replace("oo", str1); + QCOMPARE(str1, QString("FFooFooFFooFoo")); + + str1 = "Bar"; + str1.replace("FooFoo", str1); + QCOMPARE(str1, QString("Bar")); + + str1.replace(str1, "xxx"); + QCOMPARE(str1, QString("xxx")); + str1.replace(str1, QString("yyy")); + QCOMPARE(str1, QString("yyy")); + str1 += str1; + QCOMPARE(str1, QString("yyyyyy")); + } +} + + +void tst_Collections::bitArray() +{ + QBitArray ba(20); + QVERIFY(ba.testBit(17) == false); + ba.setBit(17); + QVERIFY(ba.size() == 20); + QVERIFY(ba.testBit(17)==true); + QVERIFY(!ba.testBit(16)); + ba[4] = true; + QVERIFY(ba.testBit(4)); + QVERIFY(ba[4]); + int sum = 0; + for(int i = 0; i < 20; i++) + sum += ba.testBit(i) ? 1 : 0; + QVERIFY(sum == 2); + + ba = QBitArray(7, true); + QVERIFY(ba.size() == 7); + QVERIFY(ba[5]); + + ba = QBitArray(3); + ba[0] = ba[2] = true; + + QBitArray nba(3); + nba[1] = true; + + QVERIFY(~ba == nba); + +}; + +struct CacheFoo +{ + CacheFoo(int v):val(v) { counter++; } + ~CacheFoo() { counter--; } + int val; + static int counter; + bool isDetached() const { return val != 2; } +}; + +int CacheFoo::counter = 0; + +void tst_Collections::cache() +{ + { + CacheFoo* cf; + QCache cache(120); + int i; + for (i = 0; i < 30; i++) { + cf = cache.object(10); + cache.insert(i, new CacheFoo(i), i); + } + + QVERIFY(cache.contains(10)); + QVERIFY(!cache.contains(1)); + QVERIFY(!cache.contains(2)); + delete cache.take(10); + } + { + QCache cache(120); + int i; + QString two; + for (i = 0; i < 30; i++) { + QString s = QString::number(i); + cache.insert(i, new QString(s), i); + if (i == 2) + two = s; + } + QVERIFY(!cache.contains(3)); + QVERIFY(!cache.contains(2)); + } + { + QCache cache(100); + cache.insert(2, new int(2)); + *cache[2] = 3; + QVERIFY(*cache.object(2) == 3); + } + + QVERIFY(CacheFoo::counter == 0); + +} + +void tst_Collections::regexp() +{ + QRegExp rx("^\\d\\d?$"); + QVERIFY(rx.indexIn("123") == -1); + QVERIFY(rx.indexIn("-6") == -1); + QVERIFY(rx.indexIn("6") == 0) ; +} + +void tst_Collections::pair() +{ + QPair p; + QVERIFY(p.first == 0.0); + QVERIFY(p.second == 0); + + QPair a(1, "Zebra"), b(2, "Ying"), c(3, "Yang"), d(3, "Ying"), e(5, "Alabama"); + QVERIFY(a.first == 1); + QVERIFY(a.second == "Zebra"); + QVERIFY(a == qMakePair(1, QString("Zebra"))); + + QVERIFY(a == a && b == b && c == c && d == d && e == e); + QVERIFY(a != b && a != c && a != d && a != e && b != c && b != d && b != e && c != d && c != e + && d != e); + + QVERIFY(a < b && b < c && c < d && d < e); + QVERIFY(a <= b && b <= c && c <= d && d <= e); + + QVERIFY(e > d && d > c && c > b && b > a); + QVERIFY(e >= d && d >= c && c >= b && b >= a); + + QVERIFY(!(a > b || b > c || c > d || d > e)); + QVERIFY(!(a >= b || b >= c || c >= d || d >= e)); + + QVERIFY(!(e < d || d < c || c < b || b < a)); + QVERIFY(!(e <= d || d <= c || c <= b || b <= a)); + + QVERIFY(a <= a && b <= b && c <= c && d <= d && e <= e); + QVERIFY(!(a < a || b < b || c < c || d < d || e < e)); + + QVERIFY(a >= a && b >= b && c >= c && d >= d && e >= e); + QVERIFY(!(a > a || b > b || c > c || d > d || e > e)); +} + +/* + These test that Java-style mutable iterators don't trash shared + copy (the setSharable() mechanism). +*/ + +template +void populate(Container &); + +template <> +void populate(QList &container) +{ + container << 1 << 2 << 4 << 8; +} + +template <> +void populate(QLinkedList &container) +{ + container << 1 << 2 << 4 << 8; +} + +template <> +void populate(QVector &container) +{ + container << 1 << 2 << 4 << 8; +} + +template <> +void populate(QMap &container) +{ + container.insert(1, 1); + container.insert(2, 2); + container.insert(4, 4); + container.insert(8, 8); +} + +template <> +void populate(QHash &container) +{ + container.insert(1, 1); + container.insert(2, 2); + container.insert(4, 4); + container.insert(8, 8); +} + +template +bool isSharable(const Container &container) +{ + Container copy = container; + return !container.isDetached(); +} + +template +void testContainer() +{ + /* + Verify that shared_null's 'sharable' flag is set to true. + */ + { + Container c1; + QVERIFY(!c1.isDetached()); + + Container c2 = c1; + QVERIFY(!c1.isDetached()); + QVERIFY(!c2.isDetached()); + } + + /* + Verify that the 'sharable' flag is true while no mutable + iterator is active. + */ + { + Container c1; + populate(c1); + QVERIFY(c1.size() == 4); + QVERIFY(c1.isDetached()); + + Container c2 = c1; + QVERIFY(c1.size() == 4); + QVERIFY(c2.size() == 4); + QVERIFY(!c1.isDetached()); + QVERIFY(!c2.isDetached()); + } + + /* + Verify that the 'sharable' flag is set to false by the + mutable iterator. + */ + { + Container c1; + populate(c1); + QVERIFY(c1.size() == 4); + QVERIFY(c1.isDetached()); + + ContainerMutableIterator i(c1); + i.next(); + + Container c2 = c1; + QVERIFY(c1.size() == 4); + QVERIFY(c2.size() == 4); + QVERIFY(c1.isDetached()); + QVERIFY(c2.isDetached()); + + i.remove(); + QVERIFY(c1.size() == 3); + QVERIFY(c2.size() == 4); + } + + /* + Verify that the 'sharable' flag is reset to true by the + mutable iterator's destructor. + */ + { + Container c1; + populate(c1); + QVERIFY(c1.size() == 4); + QVERIFY(c1.isDetached()); + + { + ContainerMutableIterator i(c1); + i.next(); + } + + Container c2 = c1; + QVERIFY(c1.size() == 4); + QVERIFY(c2.size() == 4); + QVERIFY(!c1.isDetached()); + QVERIFY(!c2.isDetached()); + } + + /* + Verify that the 'sharable' flag only affects the original + object, not the copies. + */ + { + Container c1; + populate(c1); + QVERIFY(c1.size() == 4); + QVERIFY(c1.isDetached()); + + Container c2 = c1; + QVERIFY(isSharable(c2)); + + ContainerMutableIterator i(c1); + QVERIFY(!isSharable(c1)); + QVERIFY(isSharable(c2)); + + Container c3 = c1; + QVERIFY(!isSharable(c1)); + QVERIFY(isSharable(c2)); + QVERIFY(isSharable(c3)); + QVERIFY(c1.isDetached()); + QVERIFY(c2.isDetached()); + QVERIFY(c3.isDetached()); + + Container c4; + c4 = c1; + QVERIFY(!isSharable(c1)); + QVERIFY(isSharable(c2)); + QVERIFY(isSharable(c4)); + QVERIFY(c1.isDetached()); + QVERIFY(c2.isDetached()); + QVERIFY(c4.isDetached()); + + c3 = c2; + QVERIFY(!isSharable(c1)); + QVERIFY(isSharable(c2)); + QVERIFY(isSharable(c3)); + QVERIFY(c1.isDetached()); + QVERIFY(!c2.isDetached()); + QVERIFY(!c3.isDetached()); + } +} + +#define TEST_SEQUENTIAL_CONTAINER(Container) \ + testContainer, QMutable##Container##Iterator >() + +#define TEST_ASSOCIATIVE_CONTAINER(Container) \ + testContainer, QMutable##Container##Iterator >() + +void tst_Collections::sharableQList() +{ + TEST_SEQUENTIAL_CONTAINER(List); +} + +void tst_Collections::sharableQLinkedList() +{ + TEST_SEQUENTIAL_CONTAINER(LinkedList); +} + +void tst_Collections::sharableQVector() +{ + TEST_SEQUENTIAL_CONTAINER(Vector); +} + +void tst_Collections::sharableQMap() +{ + TEST_ASSOCIATIVE_CONTAINER(Map); +} + +void tst_Collections::sharableQHash() +{ + TEST_ASSOCIATIVE_CONTAINER(Hash); +} + +static int getList_calls = 0; +QList getList() +{ + ++getList_calls; + QList list; + list << 1 << 2 << 3 << 4 << 5 << 6; + return list; +} + + +void tst_Collections::q_foreach() +{ + QList list; + list << -2 << -1 << 0 << 1 << 2; + + int sum = 0; + int j = 0; + foreach(int i, list) { + QCOMPARE(i, list.at(j)); + sum += i; + ++j; + } + QCOMPARE(sum, 0); + + // again, but without scope + foreach(int i, list) + sum += i; + QCOMPARE(sum, 0); + + foreach(int i, list) { + sum += i; + if (i == 0) + break; + } + QCOMPARE(sum, -3); + + sum = 0; + foreach(int i, list) { + if (i < 0) + continue; + sum += i; + } + QCOMPARE(sum, 3); + + sum = 0; + getList_calls = 0; + foreach(int i, getList()) + sum += i; + QCOMPARE(sum, 21); + QCOMPARE(getList_calls, 1); +} + + +void tst_Collections::conversions() +{ +#define STUFF "A" << "C" << "B" << "A" + + { + QList list1; + list1 << STUFF; + + QVector vect1 = list1.toVector(); + QCOMPARE(list1.size(), 4); + QVERIFY(vect1 == (QVector() << STUFF)); + + QList list2 = vect1.toList(); + QCOMPARE(list2.size(), 4); + QVERIFY(list2 == (QList() << STUFF)); + + QSet set1 = list1.toSet(); + QCOMPARE(set1.size(), 3); + QVERIFY(set1.contains("A")); + QVERIFY(set1.contains("B")); + QVERIFY(set1.contains("C")); + QVERIFY(!set1.contains("D")); + + QList list3 = set1.toList(); + QCOMPARE(list3.size(), 3); + QVERIFY(list3.contains("A")); + QVERIFY(list3.contains("B")); + QVERIFY(list3.contains("C")); + QVERIFY(!list3.contains("D")); + + QVERIFY(QList().toVector().isEmpty()); + QVERIFY(QList().toSet().isEmpty()); + QVERIFY(QVector().toList().isEmpty()); + QVERIFY(QSet().toList().isEmpty()); + } + + { + QList list1; + list1 << STUFF; + + QVector vect1 = QVector::fromList(list1); + QCOMPARE(list1.size(), 4); + QVERIFY(vect1 == (QVector() << STUFF)); + + QList list2 = QList::fromVector(vect1); + QCOMPARE(list2.size(), 4); + QVERIFY(list2 == (QList() << STUFF)); + + QSet set1 = QSet::fromList(list1); + QCOMPARE(set1.size(), 3); + QVERIFY(set1.contains("A")); + QVERIFY(set1.contains("B")); + QVERIFY(set1.contains("C")); + QVERIFY(!set1.contains("D")); + + QList list3 = QList::fromSet(set1); + QCOMPARE(list3.size(), 3); + QVERIFY(list3.contains("A")); + QVERIFY(list3.contains("B")); + QVERIFY(list3.contains("C")); + QVERIFY(!list3.contains("D")); + + QVERIFY(QVector::fromList(QList()).isEmpty()); + QVERIFY(QSet::fromList(QList()).isEmpty()); + QVERIFY(QList::fromVector(QVector()).isEmpty()); + QVERIFY(QList::fromSet(QSet()).isEmpty()); + } +#undef STUFF +} + +void tst_Collections::javaStyleIterators() +{ + QStringList list; + list << "a" << "b" << "c"; + QMutableStringListIterator i(list); + while (i.hasNext()) { + i.next(); + i.setValue(""); + } + while (i.hasPrevious()) { + i.previous(); + QVERIFY(i.value().isEmpty()); + i.value() = "x"; + QCOMPARE(i.value(), QString("x")); + } +} + +template +void testLinkedListLikeStlIterators() +{ + Container fake; + typename Container::value_type t; + fake << t; + + typename Container::iterator i1 = fake.begin(), i2 = i1 + 1; + typename Container::const_iterator c1 = i1, c2 = c1 + 1; + + QVERIFY(i1 == i1); + QVERIFY(i1 == c1); + QVERIFY(c1 == i1); + QVERIFY(c1 == c1); + QVERIFY(i2 == i2); + QVERIFY(i2 == c2); + QVERIFY(c2 == i2); + QVERIFY(c2 == c2); + + QVERIFY(i1 != i2); + QVERIFY(i1 != c2); + QVERIFY(c1 != i2); + QVERIFY(c1 != c2); + QVERIFY(i2 != i1); + QVERIFY(i2 != c1); + QVERIFY(c2 != i1); + QVERIFY(c2 != c1); +} + +template +void testListLikeStlIterators() +{ + testLinkedListLikeStlIterators(); + + Container fake; + typename Container::value_type t; + fake << t; + + typename Container::iterator i1 = fake.begin(), i2 = i1 + 1; + typename Container::const_iterator c1 = i1, c2 = c1 + 1; + + QVERIFY(i1 < i2); + QVERIFY(i1 < c2); + QVERIFY(c1 < i2); + QVERIFY(c1 < c2); + QVERIFY(!(i2 < i1)); + QVERIFY(!(i2 < c1)); + QVERIFY(!(c2 < i1)); + QVERIFY(!(c2 < c1)); + QVERIFY(!(i1 < i1)); + QVERIFY(!(i1 < c1)); + QVERIFY(!(c1 < i1)); + QVERIFY(!(c1 < c1)); + QVERIFY(!(i2 < i2)); + QVERIFY(!(i2 < c2)); + QVERIFY(!(c2 < i2)); + QVERIFY(!(c2 < c2)); + + QVERIFY(i2 > i1); + QVERIFY(i2 > c1); + QVERIFY(c2 > i1); + QVERIFY(c2 > c1); + QVERIFY(!(i1 > i2)); + QVERIFY(!(i1 > c2)); + QVERIFY(!(c1 > i2)); + QVERIFY(!(c1 > c2)); + QVERIFY(!(i1 > i1)); + QVERIFY(!(i1 > c1)); + QVERIFY(!(c1 > i1)); + QVERIFY(!(c1 > c1)); + QVERIFY(!(i2 > i2)); + QVERIFY(!(i2 > c2)); + QVERIFY(!(c2 > i2)); + QVERIFY(!(c2 > c2)); + + QVERIFY(!(i1 >= i2)); + QVERIFY(!(i1 >= c2)); + QVERIFY(!(c1 >= i2)); + QVERIFY(!(c1 >= c2)); + QVERIFY(i2 >= i1); + QVERIFY(i2 >= c1); + QVERIFY(c2 >= i1); + QVERIFY(c2 >= c1); + QVERIFY(i1 >= i1); + QVERIFY(i1 >= c1); + QVERIFY(c1 >= i1); + QVERIFY(c1 >= c1); + QVERIFY(i2 >= i2); + QVERIFY(i2 >= c2); + QVERIFY(c2 >= i2); + QVERIFY(c2 >= c2); + + QVERIFY(!(i2 <= i1)); + QVERIFY(!(i2 <= c1)); + QVERIFY(!(c2 <= i1)); + QVERIFY(!(c2 <= c1)); + QVERIFY(i1 <= i2); + QVERIFY(i1 <= c2); + QVERIFY(c1 <= i2); + QVERIFY(c1 <= c2); + QVERIFY(i1 <= i1); + QVERIFY(i1 <= c1); + QVERIFY(c1 <= i1); + QVERIFY(c1 <= c1); + QVERIFY(i2 <= i2); + QVERIFY(i2 <= c2); + QVERIFY(c2 <= i2); + QVERIFY(c2 <= c2); +} + +template +void testMapLikeStlIterators() +{ + Container fake; + QString k; + QString t; + fake.insert(k, t); + + typename Container::iterator i1 = fake.begin(), i2 = i1 + 1; + typename Container::const_iterator c1 = i1, c2 = c1 + 1; + + QVERIFY(i1 == i1); + QVERIFY(i1 == c1); + QVERIFY(c1 == i1); + QVERIFY(c1 == c1); + QVERIFY(i2 == i2); + QVERIFY(i2 == c2); + QVERIFY(c2 == i2); + QVERIFY(c2 == c2); + + QVERIFY(i1 != i2); + QVERIFY(i1 != c2); + QVERIFY(c1 != i2); + QVERIFY(c1 != c2); + QVERIFY(i2 != i1); + QVERIFY(i2 != c1); + QVERIFY(c2 != i1); + QVERIFY(c2 != c1); +} + +void tst_Collections::constAndNonConstStlIterators() +{ + testListLikeStlIterators >(); + testListLikeStlIterators(); + testLinkedListLikeStlIterators >(); + testListLikeStlIterators >(); + testMapLikeStlIterators >(); + testMapLikeStlIterators >(); + testMapLikeStlIterators >(); + testMapLikeStlIterators >(); +} + +#ifndef QT_NO_STL +void tst_Collections::vector_stl_data() +{ + QTest::addColumn("elements"); + + QTest::newRow("empty") << QStringList(); + QTest::newRow("one") << (QStringList() << "Hei"); + QTest::newRow("two") << (QStringList() << "Hei" << "Hopp"); + QTest::newRow("three") << (QStringList() << "Hei" << "Hopp" << "Sann"); +} + +void tst_Collections::vector_stl() +{ + QFETCH(QStringList, elements); + + QVector vector; + for (int i = 0; i < elements.count(); ++i) + vector << elements.at(i); + + std::vector stdVector = vector.toStdVector(); + + QCOMPARE(int(stdVector.size()), elements.size()); + + std::vector::const_iterator it = stdVector.begin(); + for (uint j = 0; j < stdVector.size() && it != stdVector.end(); ++j, ++it) + QCOMPARE(*it, vector[j]); + + QCOMPARE(QVector::fromStdVector(stdVector), vector); +} + +void tst_Collections::linkedlist_stl_data() +{ + list_stl_data(); +} + +void tst_Collections::linkedlist_stl() +{ + QFETCH(QStringList, elements); + + QLinkedList list; + for (int i = 0; i < elements.count(); ++i) + list << elements.at(i); + + std::list stdList = list.toStdList(); + + QCOMPARE(int(stdList.size()), elements.size()); + + std::list::const_iterator it = stdList.begin(); + QLinkedList::const_iterator it2 = list.constBegin(); + for (uint j = 0; j < stdList.size(); ++j, ++it, ++it2) + QCOMPARE(*it, *it2); + + QCOMPARE(QLinkedList::fromStdList(stdList), list); +} + +void tst_Collections::list_stl_data() +{ + QTest::addColumn("elements"); + + QTest::newRow("empty") << QStringList(); + QTest::newRow("one") << (QStringList() << "Hei"); + QTest::newRow("two") << (QStringList() << "Hei" << "Hopp"); + QTest::newRow("three") << (QStringList() << "Hei" << "Hopp" << "Sann"); +} + +void tst_Collections::list_stl() +{ + QFETCH(QStringList, elements); + + QList list; + for (int i = 0; i < elements.count(); ++i) + list << elements.at(i); + + std::list stdList = list.toStdList(); + + QCOMPARE(int(stdList.size()), elements.size()); + + std::list::const_iterator it = stdList.begin(); + for (uint j = 0; j < stdList.size() && it != stdList.end(); ++j, ++it) + QCOMPARE(*it, list[j]); + + QCOMPARE(QList::fromStdList(stdList), list); +} +#endif + +template +T qtInit(T * = 0) +{ + return T(); +} + +void tst_Collections::q_init() +{ + QCOMPARE(qtInit(), 0); + QCOMPARE(qtInit(), 0.0); + QCOMPARE(qtInit(), QString()); + QCOMPARE(qtInit(), static_cast(0)); + QCOMPARE(qtInit(), static_cast(0)); + QCOMPARE(qtInit(), static_cast(0)); + QCOMPARE(qtInit().i1, 0); + QCOMPARE(qtInit().i2, 0); +} + +void tst_Collections::pointersize() +{ + QCOMPARE(int(sizeof(void *)), QT_POINTER_SIZE); +} + +class LessThanComparable +{ +public: + bool operator<(const LessThanComparable &) const { return true; } +}; + +class EqualsComparable +{ +public: + bool operator==(const EqualsComparable &) const { return true; } +}; + +uint qHash(const EqualsComparable &) +{ + return 0; +} + +/* + The following functions instatiates every member functions in the + Qt containers that requires either operator== or operator<. + They are ordered in a concept inheritance tree: + + Container + MutableIterationContainer + Sequence (QLinkedList) + Random Access (QVector, QList, QQueue, QStack) + Pair Associative (QHash, QMap) + Associative (QSet) +*/ +template +void instantiateContainer() +{ + const ValueType value = ValueType(); + ContainerType container; + const ContainerType constContainer(container); + +#ifndef QT_NO_STL + typename ContainerType::const_iterator constIt; + constIt = constContainer.begin(); + container.constBegin(); + + constIt = constContainer.end(); + container.constEnd(); +#endif + container.clear(); + container.contains(value); + container.count(); + container.empty(); + container.isEmpty(); + container.size(); + + container != constContainer; + container == constContainer; + container = constContainer; +} + +template +void instantiateMutableIterationContainer() +{ + instantiateContainer(); + ContainerType container; + +#ifndef QT_NO_STL + typename ContainerType::iterator it; + it = container.begin(); + it = container.end(); +#endif + + // QSet lacks count(T). + const ValueType value = ValueType(); + container.count(value); +} + +template +void instantiateSequence() +{ + instantiateMutableIterationContainer(); + +// QVector lacks removeAll(T) +// ValueType value = ValueType(); +// ContainerType container; +// container.removeAll(value); +} + +template +void instantiateRandomAccess() +{ + instantiateSequence(); + + ValueType value = ValueType(); + ContainerType container; + container.indexOf(value); + container.lastIndexOf(value); +} + +template +void instantiateAssociative() +{ + instantiateContainer(); + + const ValueType value = ValueType(); + ContainerType container; + const ContainerType constContainer(container); + + container.reserve(1); + container.capacity(); + container.squeeze(); + + container.remove(value); + container.values(); + + container.unite(constContainer); + container.intersect(constContainer); + container.subtract(constContainer); + + container != constContainer; + container == constContainer; + container & constContainer; + container &= constContainer; + container &= value; + container + constContainer; + container += constContainer; + container += value; + container - constContainer; + container -= constContainer; + container -= value; + container | constContainer; + container |= constContainer; + container |= value; +} + +template +void instantiatePairAssociative() +{ + instantiateMutableIterationContainer(); + + typename ContainerType::iterator it; + typename ContainerType::const_iterator constIt; + const KeyType key = KeyType(); + const ValueType value = ValueType(); + ContainerType container; + const ContainerType constContainer(container); + + it = container.insert(key, value); + container.erase(it); + container.find(key); + container.constFind(key); + constContainer.find(key); + + container.key(value); + container.keys(); + constContainer.keys(); + container.remove(key); + container.take(key); + container.unite(constContainer); + container.value(key); + container.value(key, value); + container.values(); + container.values(key); + container[key]; + const int foo = constContainer[key]; + Q_UNUSED(foo); +} + +/* + Instantiate all Qt containers using a datatype that + defines the minimum amount of operators. +*/ +void tst_Collections::containerInstantiation() +{ + // Instantiate QHash member functions. + typedef QHash Hash; + instantiatePairAssociative(); + + Hash hash; + hash.reserve(1); + hash.capacity(); + hash.squeeze(); + + // Instantiate QMap member functions. + typedef QMap Map; + instantiatePairAssociative(); + + // Instantiate QSet member functions. + typedef QSet Set; + instantiateAssociative(); + + //Instantiate QLinkedList member functions. + typedef QLinkedList LinkedList; + instantiateSequence (); + { + EqualsComparable value; + LinkedList list; + list.removeAll(value); + } + + //Instantiate QList member functions. + typedef QList List; + instantiateRandomAccess(); + { + EqualsComparable value; + List list; + list.removeAll(value); + } + + //Instantiate QVector member functions. + typedef QVector Vector; + instantiateRandomAccess(); + + //Instantiate QQueue member functions. + typedef QQueue Queue; + instantiateRandomAccess(); + + //Instantiate QStack member functions. + typedef QStack Stack; + instantiateRandomAccess(); +} + +void tst_Collections::qtimerList() +{ + QList foo; + const int N = 10000; + + foo.append(99.9); + foo.append(99.9); + foo.append(99.9); + + for(int i = 0; i < N; i++) { + foo.removeFirst(); + foo.insert(1, 99.9); + } + + QList::Iterator end = foo.end(); + for (int i = 0; i < (N / 2) - 10; ++i) { + foo.prepend(99.9); + if (foo.end() != end) + return; + } + QFAIL("QList preallocates too much memory"); +} + +template +void testContainerTypedefs(Container container) +{ + Q_UNUSED(container) + { typedef typename Container::value_type Foo; } + { typedef typename Container::iterator Foo; } + { typedef typename Container::const_iterator Foo; } + { typedef typename Container::reference Foo; } + { typedef typename Container::const_reference Foo; } + { typedef typename Container::pointer Foo; } + { typedef typename Container::difference_type Foo; } + { typedef typename Container::size_type Foo; } +} + +template +void testPairAssociativeContainerTypedefs(Container container) +{ + Q_UNUSED(container) + +// TODO: Not sure how to define value_type for our associative containers +// { typedef typename Container::value_type Foo; } +// { typedef typename Container::const_iterator Foo; } +// { typedef typename Container::reference Foo; } +// { typedef typename Container::const_reference Foo; } +// { typedef typename Container::pointer Foo; } + + { typedef typename Container::difference_type Foo; } + { typedef typename Container::size_type Foo; } + { typedef typename Container::iterator Foo; } + { typedef typename Container::key_type Foo; } + { typedef typename Container::mapped_type Foo; } +// TODO +// { typedef typename Container::key_compare Foo; } +// { typedef typename Container::value_comare Foo; } +} + +template +void testSetContainerTypedefs(Container container) +{ + Q_UNUSED(container) + { typedef typename Container::iterator Foo; } + { typedef typename Container::const_iterator Foo; } + { typedef typename Container::reference Foo; } + { typedef typename Container::const_reference Foo; } + { typedef typename Container::pointer Foo; } + { typedef typename Container::difference_type Foo; } + { typedef typename Container::size_type Foo; } + { typedef typename Container::key_type Foo; } +} + +/* + Compile-time test that verifies that the Qt containers + have STL-compatable typedefs. +*/ +void tst_Collections::containerTypedefs() +{ + testContainerTypedefs(QVector()); + testContainerTypedefs(QStack()); + testContainerTypedefs(QList()); + testContainerTypedefs(QLinkedList()); + testContainerTypedefs(QQueue()); + + testPairAssociativeContainerTypedefs(QMap()); + testPairAssociativeContainerTypedefs(QMultiMap()); + testPairAssociativeContainerTypedefs(QHash()); + + testSetContainerTypedefs(QSet()); +} + +class Key1; +class T1; +class T2; + +void tst_Collections::forwardDeclared() +{ + { typedef QHash C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QMultiHash C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QMap C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QMultiMap C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QPair C; C *x = 0; Q_UNUSED(x) } + { typedef QList C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QLinkedList C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QVector C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) Q_UNUSED(i) Q_UNUSED(j) } + { typedef QStack C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) Q_UNUSED(i) Q_UNUSED(j) } + { typedef QQueue C; C *x = 0; C::iterator i; C::const_iterator j; Q_UNUSED(x) } + { typedef QSet C; C *x = 0; /* C::iterator i; */ C::const_iterator j; Q_UNUSED(x) } +} + +#if defined(Q_ALIGNOF) && defined(Q_DECL_ALIGN) + +class Q_DECL_ALIGN(4) Aligned4 +{ + char i; +public: + Aligned4(int i = 0) : i(i) {} + bool checkAligned() const + { + return (quintptr(this) & 3) == 0; + } + + inline bool operator==(const Aligned4 &other) const { return i == other.i; } + inline bool operator<(const Aligned4 &other) const { return i < other.i; } + friend inline int qHash(const Aligned4 &a) { return qHash(a.i); } +}; + +class Q_DECL_ALIGN(128) Aligned128 +{ + char i; +public: + Aligned128(int i = 0) : i(i) {} + bool checkAligned() const + { + return (quintptr(this) & 127) == 0; + } + + inline bool operator==(const Aligned128 &other) const { return i == other.i; } + inline bool operator<(const Aligned128 &other) const { return i < other.i; } + friend inline int qHash(const Aligned128 &a) { return qHash(a.i); } +}; + +template +void testVectorAlignment() +{ + typedef typename C::value_type Aligned; + C container; + container.append(Aligned()); + QVERIFY(container[0].checkAligned()); + + for (int i = 0; i < 200; ++i) + container.append(Aligned()); + + for (int i = 0; i < container.size(); ++i) + QVERIFY(container.at(i).checkAligned()); +} + +template +void testContiguousCacheAlignment() +{ + typedef typename C::value_type Aligned; + C container(150); + container.append(Aligned()); + QVERIFY(container[container.firstIndex()].checkAligned()); + + for (int i = 0; i < 200; ++i) + container.append(Aligned()); + + for (int i = container.firstIndex(); i < container.lastIndex(); ++i) + QVERIFY(container.at(i).checkAligned()); +} + +template +void testAssociativeContainerAlignment() +{ + typedef typename C::key_type Key; + typedef typename C::mapped_type Value; + C container; + container.insert(Key(), Value()); + + typename C::const_iterator it = container.constBegin(); + QVERIFY(it.key().checkAligned()); + QVERIFY(it.value().checkAligned()); + + // add some more elements + for (int i = 0; i < 200; ++i) + container.insert(Key(i), Value(i)); + + it = container.constBegin(); + for ( ; it != container.constEnd(); ++it) { + QVERIFY(it.key().checkAligned()); + QVERIFY(it.value().checkAligned()); + } +} + +void tst_Collections::alignment() +{ + testVectorAlignment >(); + testVectorAlignment >(); + testContiguousCacheAlignment >(); + testContiguousCacheAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); + testAssociativeContainerAlignment >(); +} +#endif + +#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS + +template class C> +struct QTBUG13079_Node { + C children; + QString s; + + ~QTBUG13079_Node() { + children.begin(); //play with memory + } +}; +template class C> void QTBUG13079_collectionInsideCollectionImpl() +{ + C > nodeList; + nodeList << QTBUG13079_Node(); + nodeList.first().s = "parent"; + nodeList.first().children << QTBUG13079_Node(); + nodeList.first().children.first().s = "child"; + + nodeList = nodeList.first().children; + QCOMPARE(nodeList.first().s, QString::fromLatin1("child")); + + nodeList = nodeList.first().children; + QCOMPARE(nodeList.count(), 0); + nodeList << QTBUG13079_Node(); +} + +template class C> +struct QTBUG13079_NodeAssoc { + C children; + QString s; + + ~QTBUG13079_NodeAssoc() { + children.begin(); //play with memory + } +}; +template class C> void QTBUG13079_collectionInsideCollectionAssocImpl() +{ + C > nodeMap; + nodeMap[18] = QTBUG13079_NodeAssoc(); + nodeMap[18].s = "parent"; + nodeMap[18].children[12] = QTBUG13079_NodeAssoc(); + nodeMap[18].children[12].s = "child"; + + nodeMap = nodeMap[18].children; + QCOMPARE(nodeMap[12].s, QString::fromLatin1("child")); + + nodeMap = nodeMap[12].children; + QCOMPARE(nodeMap.count(), 0); + nodeMap[42] = QTBUG13079_NodeAssoc(); +} + + +quint32 qHash(const QTBUG13079_Node &) +{ + return 0; +} + +bool operator==(const QTBUG13079_Node &a, const QTBUG13079_Node &b) +{ + return a.s == b.s && a.children == b.children; +} + +template class C> +struct QTBUG13079_NodePtr : QSharedData { + C child; + QTBUG13079_NodePtr *next; + QString s; + + QTBUG13079_NodePtr() : next(0) {} + ~QTBUG13079_NodePtr() { + next = child.data(); //play with memory + } +}; +template class C> void QTBUG13079_collectionInsidePtrImpl() +{ + typedef C > Ptr; + { + Ptr nodePtr; + nodePtr = Ptr(new QTBUG13079_NodePtr()); + nodePtr->s = "parent"; + nodePtr->child = Ptr(new QTBUG13079_NodePtr()); + nodePtr->child->s = "child"; + nodePtr = nodePtr->child; + QCOMPARE(nodePtr->s, QString::fromLatin1("child")); + nodePtr = nodePtr->child; + QVERIFY(!nodePtr); + } + { + Ptr nodePtr; + nodePtr = Ptr(new QTBUG13079_NodePtr()); + nodePtr->s = "parent"; + nodePtr->next = new QTBUG13079_NodePtr(); + nodePtr->next->s = "next"; + nodePtr = Ptr(nodePtr->next); + QCOMPARE(nodePtr->s, QString::fromLatin1("next")); + nodePtr = Ptr(nodePtr->next); + QVERIFY(!nodePtr); + } +} + +#endif + +void tst_Collections::QTBUG13079_collectionInsideCollection() +{ +#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + QTBUG13079_collectionInsideCollectionImpl(); + + { + QSet > nodeSet; + nodeSet << QTBUG13079_Node(); + nodeSet = nodeSet.begin()->children; + QCOMPARE(nodeSet.count(), 0); + } + + QTBUG13079_collectionInsideCollectionAssocImpl(); + QTBUG13079_collectionInsideCollectionAssocImpl(); + + QTBUG13079_collectionInsidePtrImpl(); + QTBUG13079_collectionInsidePtrImpl(); + QTBUG13079_collectionInsidePtrImpl(); +#endif +} + +template void foreach_test_arrays(const Container &container) +{ + typedef typename Container::value_type T; + int i = 0; + QSet set; + foreach(const T & val, container) { + QVERIFY( val == container[i] ); + set << val; + i++; + } + QCOMPARE(set.count(), container.count()); + + //modify the container while iterating. + Container c2 = container; + Container c3; + i = 0; + foreach (T val, c2) { + c3 << val; + c2.insert((i * 89) % c2.size(), T() ); + QVERIFY( val == container.at(i) ); + val = T(); + i++; + } + QVERIFY(c3 == container); +} + + +void tst_Collections::foreach_2() +{ + QStringList strlist = QString::fromLatin1("a,b,c,d,e,f,g,h,ih,kl,mn,op,qr,st,uvw,xyz").split(","); + foreach_test_arrays(strlist); + foreach_test_arrays(QList(strlist)); + foreach_test_arrays(strlist.toVector()); + + QList intlist; + intlist << 1 << 2 << 3 << 4 <<5 << 6 << 7 << 8 << 9; + foreach_test_arrays(intlist); + foreach_test_arrays(intlist.toVector()); + + QVarLengthArray varl1; + QVarLengthArray varl2; + QVarLengthArray varl3; + foreach(int i, intlist) { + varl1 << i; + varl2 << i; + varl3 << i; + } + QCOMPARE(varl1.count(), intlist.count()); + QCOMPARE(varl2.count(), intlist.count()); + QCOMPARE(varl3.count(), intlist.count()); + foreach_test_arrays(varl1); + foreach_test_arrays(varl2); + foreach_test_arrays(varl3); + + QVarLengthArray varl4; + QVarLengthArray varl5; + QVarLengthArray varl6; + foreach(const QString &str, strlist) { + varl4 << str; + varl5 << str; + varl6 << str; + } + QCOMPARE(varl4.count(), strlist.count()); + QCOMPARE(varl5.count(), strlist.count()); + QCOMPARE(varl6.count(), strlist.count()); + foreach_test_arrays(varl4); + foreach_test_arrays(varl5); + foreach_test_arrays(varl6); +} + +struct IntOrString +{ + int val; + IntOrString(int v) : val(v) { } + IntOrString(const QString &v) : val(v.toInt()) { } + operator int() { return val; } + operator QString() { return QString::number(val); } +#ifndef QT_NO_STL + operator std::string() { return QString::number(val).toStdString(); } + IntOrString(const std::string &v) : val(QString::fromStdString(v).toInt()) { } +#endif +}; + +template void insert_remove_loop_impl() +{ + typedef typename Container::value_type T; + Container t; + t.append(T(IntOrString(1))); + t << (T(IntOrString(2))); + t += (T(IntOrString(3))); + t.prepend(T(IntOrString(4))); + t.insert(2, 3 , T(IntOrString(5))); + t.insert(4, T(IntOrString(6))); + t.insert(t.begin() + 2, T(IntOrString(7))); + t.insert(t.begin() + 5, 3, T(IntOrString(8))); + int expect1[] = { 4 , 1 , 7, 5 , 5 , 8, 8, 8, 6, 5, 2 , 3 }; + QCOMPARE(size_t(t.count()), sizeof(expect1)/sizeof(int)); + for (int i = 0; i < t.count(); i++) { + QCOMPARE(t[i], T(IntOrString(expect1[i]))); + } + + Container compare_test1 = t; + t.replace(5, T(IntOrString(9))); + Container compare_test2 = t; + QVERIFY(!(compare_test1 == t)); + QVERIFY( (compare_test1 != t)); + QVERIFY( (compare_test2 == t)); + QVERIFY(!(compare_test2 != t)); + t.remove(7); + t.remove(2, 3); + int expect2[] = { 4 , 1 , 9, 8, 6, 5, 2 , 3 }; + QCOMPARE(size_t(t.count()), sizeof(expect2)/sizeof(int)); + for (int i = 0; i < t.count(); i++) { + QCOMPARE(t[i], T(IntOrString(expect2[i]))); + } + + for (typename Container::iterator it = t.begin(); it != t.end(); ) { + if ( int(IntOrString(*it)) % 2 ) + ++it; + else + it = t.erase(it); + } + + int expect3[] = { 1 , 9, 5, 3 }; + QCOMPARE(size_t(t.count()), sizeof(expect3)/sizeof(int)); + for (int i = 0; i < t.count(); i++) { + QCOMPARE(t[i], T(IntOrString(expect3[i]))); + } + + t.erase(t.begin() + 1, t.end() - 1); + + int expect4[] = { 1 , 3 }; + QCOMPARE(size_t(t.count()), sizeof(expect4)/sizeof(int)); + for (int i = 0; i < t.count(); i++) { + QCOMPARE(t[i], T(IntOrString(expect4[i]))); + } + + t << T(IntOrString(10)) << T(IntOrString(11)) << T(IntOrString(12)) << T(IntOrString(13)); + t << T(IntOrString(14)) << T(IntOrString(15)) << T(IntOrString(16)) << T(IntOrString(17)); + t << T(IntOrString(18)) << T(IntOrString(19)) << T(IntOrString(20)) << T(IntOrString(21)); + for (typename Container::iterator it = t.begin(); it != t.end(); ++it) { + int iv = int(IntOrString(*it)); + if ( iv % 2 ) { + it = t.insert(it, T(IntOrString(iv * iv))); + it = t.insert(it + 2, T(IntOrString(iv * iv + 1))); + } + } + + int expect5[] = { 1, 1, 2, 3*3, 3, 3*3+1, 10, 11*11, 11, 11*11+1, 12 , 13*13, 13, 13*13+1, 14, + 15*15, 15, 15*15+1, 16 , 17*17, 17, 17*17+1 ,18 , 19*19, 19, 19*19+1, 20, 21*21, 21, 21*21+1 }; + QCOMPARE(size_t(t.count()), sizeof(expect5)/sizeof(int)); + for (int i = 0; i < t.count(); i++) { + QCOMPARE(t[i], T(IntOrString(expect5[i]))); + } +} + + +//Add insert(int, int, T) so it has the same interface as QVector and QVarLengthArray for the test. +template +struct ExtList : QList { + using QList::insert; + void insert(int before, int n, const T&x) { + while (n--) { + this->insert(before, x ); + } + } + void insert(typename QList::iterator before, int n, const T&x) { + while (n--) { + before = this->insert(before, x); + } + } + + void remove(int i) { + this->removeAt(i); + } + void remove(int i, int n) { + while (n--) { + this->removeAt(i); + } + } +}; + +void tst_Collections::insert_remove_loop() +{ + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + +#ifndef QT_NO_STL + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); + insert_remove_loop_impl >(); +#endif +} + + + +QTEST_APPLESS_MAIN(tst_Collections) +#include "tst_collections.moc" diff --git a/tests/auto/integrationtests/exceptionsafety/.gitignore b/tests/auto/integrationtests/exceptionsafety/.gitignore new file mode 100644 index 0000000000..9a854c4c26 --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety/.gitignore @@ -0,0 +1 @@ +tst_exceptionsafety diff --git a/tests/auto/integrationtests/exceptionsafety/exceptionsafety.pro b/tests/auto/integrationtests/exceptionsafety/exceptionsafety.pro new file mode 100644 index 0000000000..52ba9e27bd --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety/exceptionsafety.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +SOURCES += tst_exceptionsafety.cpp +QT = core +CONFIG += parallel_test diff --git a/tests/auto/integrationtests/exceptionsafety/tst_exceptionsafety.cpp b/tests/auto/integrationtests/exceptionsafety/tst_exceptionsafety.cpp new file mode 100644 index 0000000000..27db9ea7f7 --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety/tst_exceptionsafety.cpp @@ -0,0 +1,734 @@ +/**************************************************************************** +** +** 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 + +QT_USE_NAMESPACE + +class tst_ExceptionSafety: public QObject +{ + Q_OBJECT +private slots: +#ifdef QT_NO_EXCEPTIONS + void initTestCase(); +#else + void exceptionInSlot(); + void exceptionVector(); + void exceptionHash(); + void exceptionMap(); + void exceptionList(); + void exceptionLinkedList(); +// void exceptionEventLoop(); +// void exceptionSignalSlot(); +#endif +}; + +#ifdef QT_NO_EXCEPTIONS +void tst_ExceptionSafety::initTestCase() +{ + QSKIP("This test requires exception support", SkipAll); +} + +#else + +class Emitter : public QObject +{ + Q_OBJECT +public: + inline void emitTestSignal() { emit testSignal(); } +signals: + void testSignal(); +}; + +class ExceptionThrower : public QObject +{ + Q_OBJECT +public slots: + void thrower() { throw 5; } +}; + +class Receiver : public QObject +{ + Q_OBJECT +public: + Receiver() + : received(0) {} + int received; + +public slots: + void receiver() { ++received; } +}; + +enum ThrowType { ThrowNot = 0, ThrowAtCreate = 1, ThrowAtCopy = 2, ThrowLater = 3, ThrowAtComparison = 4 }; + +ThrowType throwType = ThrowNot; // global flag to indicate when an exception should be throw. Will be reset when the exception has been generated. + +int objCounter = 0; + +/*! Class that does not throw any exceptions. Used as baseclass for all the other ones. + */ +template +class FlexibleThrower +{ + public: + FlexibleThrower() : _value(-1) { + if( throwType == ThrowAtCreate ) { + throwType = ThrowNot; + throw ThrowAtCreate; + } + objCounter++; + } + + FlexibleThrower( short value ) : _value(value) { + if( throwType == ThrowAtCreate ) { + throwType = ThrowNot; + throw ThrowAtCreate; + } + objCounter++; + } + + FlexibleThrower(FlexibleThrower const& other ) { + // qDebug("cc"); + + if( throwType == ThrowAtCopy ) { + throwType = ThrowNot; + throw ThrowAtCopy; + + } else if( throwType == ThrowLater ) { + throwType = ThrowAtCopy; + } + + objCounter++; + _value = other.value(); + } + + ~FlexibleThrower() { objCounter--; } + + bool operator==(const FlexibleThrower &t) const + { + // qDebug("vv == %d %d", value(), t.value()); + if( throwType == ThrowAtComparison ) { + throwType = ThrowNot; + throw ThrowAtComparison; + } + return value()==t.value(); + } + + bool operator<(const FlexibleThrower &t) const + { + // qDebug("vv < %d %d", value(), t.value()); + if( throwType == ThrowAtComparison ) { + throwType = ThrowNot; + throw ThrowAtComparison; + } + return value()& t) +{ + // qDebug("ha"); + if( throwType == ThrowAtComparison ) { + throwType = ThrowNot; + throw ThrowAtComparison; + } + return (uint)t.value(); +} + +typedef FlexibleThrower<2> FlexibleThrowerSmall; +typedef QMap MyMap; +typedef QHash MyHash; + +// connect a signal to a slot that throws an exception +// run this through valgrind to make sure it doesn't corrupt +void tst_ExceptionSafety::exceptionInSlot() +{ + Emitter emitter; + ExceptionThrower thrower; + + connect(&emitter, SIGNAL(testSignal()), &thrower, SLOT(thrower())); + + try { + emitter.emitTestSignal(); + } catch (int i) { + QCOMPARE(i, 5); + } +} + +void tst_ExceptionSafety::exceptionList() { + + { + QList list; + QList list2; + QList list3; + + for( int i = 0; i<10; i++ ) + list.append( FlexibleThrowerSmall(i) ); + + try { + throwType = ThrowAtCopy; + list.append( FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( list.size(), 10 ); + + try { + throwType = ThrowAtCopy; + list.prepend( FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( list.at(0).value(), 0 ); + QCOMPARE( list.size(), 10 ); + + try { + throwType = ThrowAtCopy; + list.insert( 8, FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( list.at(7).value(), 7 ); + QCOMPARE( list.at(8).value(), 8 ); + QCOMPARE( list.size(), 10 ); + + try { + throwType = ThrowAtCopy; + FlexibleThrowerSmall t = list.takeAt( 6 ); + } catch (...) { + } + QCOMPARE( list.at(6).value(), 6 ); + QCOMPARE( list.at(7).value(), 7 ); + QCOMPARE( list.size(), 10 ); + + try { + throwType = ThrowAtCopy; + list3 = list; + } catch (...) { + } + QCOMPARE( list.at(0).value(), 0 ); + QCOMPARE( list.at(7).value(), 7 ); + QCOMPARE( list.size(), 10 ); + QCOMPARE( list3.at(0).value(), 0 ); + QCOMPARE( list3.at(7).value(), 7 ); + QCOMPARE( list3.size(), 10 ); + + try { + throwType = ThrowAtCopy; + list3.append( FlexibleThrowerSmall(11) ); + } catch (...) { + } + QCOMPARE( list.at(0).value(), 0 ); + QCOMPARE( list.at(7).value(), 7 ); + QCOMPARE( list.size(), 10 ); + QCOMPARE( list3.at(0).value(), 0 ); + QCOMPARE( list3.at(7).value(), 7 ); + QCOMPARE( list3.size(), 10 ); + + try { + list2.clear(); + list2.append( FlexibleThrowerSmall(11)); + throwType = ThrowAtCopy; + list3 = list+list2; + } catch (...) { + } + QCOMPARE( list.at(0).value(), 0 ); + QCOMPARE( list.at(7).value(), 7 ); + QCOMPARE( list.size(), 10 ); + + // check that copy on write works atomar + list2.clear(); + list2.append( FlexibleThrowerSmall(11)); + list3 = list+list2; + try { + throwType = ThrowAtCreate; + list3[7]=FlexibleThrowerSmall(12); + } catch (...) { + } + QCOMPARE( list.at(7).value(), 7 ); + QCOMPARE( list.size(), 10 ); + QCOMPARE( list3.at(7).value(), 7 ); + QCOMPARE( list3.size(), 11 ); + + } + QCOMPARE(objCounter, 0 ); // check that every object has been freed +} + +void tst_ExceptionSafety::exceptionLinkedList() { + + { + QLinkedList list; + QLinkedList list2; + QLinkedList list3; + + for( int i = 0; i<10; i++ ) + list.append( FlexibleThrowerSmall(i) ); + + try { + throwType = ThrowAtCopy; + list.append( FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( list.size(), 10 ); + + try { + throwType = ThrowAtCopy; + list.prepend( FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( list.first().value(), 0 ); + QCOMPARE( list.size(), 10 ); + + try { + throwType = ThrowAtCopy; + list3 = list; + list3.append( FlexibleThrowerSmall(11) ); + } catch (...) { + } + QCOMPARE( list.first().value(), 0 ); + QCOMPARE( list.size(), 10 ); + QCOMPARE( list3.size(), 10 ); + } + QCOMPARE(objCounter, 0 ); // check that every object has been freed +} + +void tst_ExceptionSafety::exceptionVector() { + + { + QVector vector; + QVector vector2; + QVector vector3; + + for (int i = 0; i<10; i++) + vector.append( FlexibleThrowerSmall(i) ); + + try { + throwType = ThrowAtCopy; + vector.append( FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( vector.size(), 10 ); + + try { + throwType = ThrowAtCopy; + vector.prepend( FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( vector.at(0).value(), 0 ); + QCOMPARE( vector.size(), 10 ); + + try { + throwType = ThrowAtCopy; + vector.insert( 8, FlexibleThrowerSmall(10)); + } catch (...) { + } + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.at(8).value(), 8 ); + QCOMPARE( vector.size(), 10 ); + + try { + throwType = ThrowAtCopy; + vector3 = vector; + } catch (...) { + } + QCOMPARE( vector.at(0).value(), 0 ); + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.size(), 10 ); + QCOMPARE( vector3.at(0).value(), 0 ); + QCOMPARE( vector3.at(7).value(), 7 ); + QCOMPARE( vector3.size(), 10 ); + + try { + throwType = ThrowAtCopy; + vector3.append( FlexibleThrowerSmall(11) ); + } catch (...) { + } + QCOMPARE( vector.at(0).value(), 0 ); + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.size(), 10 ); + QCOMPARE( vector3.at(0).value(), 0 ); + QCOMPARE( vector3.at(7).value(), 7 ); + + try { + vector2.clear(); + vector2.append( FlexibleThrowerSmall(11)); + throwType = ThrowAtCopy; + vector3 = vector+vector2; + } catch (...) { + } + QCOMPARE( vector.at(0).value(), 0 ); + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.size(), 10 ); + + // check that copy on write works atomar + vector2.clear(); + vector2.append( FlexibleThrowerSmall(11)); + vector3 = vector+vector2; + try { + throwType = ThrowAtCreate; + vector3[7]=FlexibleThrowerSmall(12); + } catch (...) { + } + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.size(), 10 ); + QCOMPARE( vector3.at(7).value(), 7 ); + QCOMPARE( vector3.size(), 11 ); + + try { + throwType = ThrowAtCreate; + vector.resize(15); + } catch (...) { + } + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.size(), 10 ); + + try { + throwType = ThrowAtCreate; + vector.resize(15); + } catch (...) { + } + QCOMPARE( vector.at(7).value(), 7 ); + QCOMPARE( vector.size(), 10 ); + + try { + throwType = ThrowLater; + vector.fill(FlexibleThrowerSmall(1), 15); + } catch (...) { + } + QCOMPARE( vector.at(0).value(), 0 ); + QCOMPARE( vector.size(), 10 ); + + + } + QCOMPARE(objCounter, 0 ); // check that every object has been freed +} + + +void tst_ExceptionSafety::exceptionMap() { + + { + MyMap map; + MyMap map2; + MyMap map3; + + throwType = ThrowNot; + for (int i = 0; i<10; i++) + map[ FlexibleThrowerSmall(i) ] = FlexibleThrowerSmall(i); + + return; // further test are deactivated until Map is fixed. + + for( int i = ThrowAtCopy; i<=ThrowAtComparison; i++ ) { + try { + throwType = (ThrowType)i; + map[ FlexibleThrowerSmall(10) ] = FlexibleThrowerSmall(10); + } catch(...) { + } + QCOMPARE( map.size(), 10 ); + QCOMPARE( map[ FlexibleThrowerSmall(1) ], FlexibleThrowerSmall(1) ); + } + + map2 = map; + try { + throwType = ThrowLater; + map2[ FlexibleThrowerSmall(10) ] = FlexibleThrowerSmall(10); + } catch(...) { + } + /* qDebug("%d %d", map.size(), map2.size() ); + for( int i=0; i(ThrowEventId)) + { + } +}; + +class NoThrowEvent : public QEvent +{ +public: + NoThrowEvent() + : QEvent(static_cast(NoThrowEventId)) + {} +}; + +struct IntEx : public std::exception +{ + IntEx(int aEx) : ex(aEx) {} + int ex; +}; + +class TestObject : public QObject +{ +public: + TestObject() + : throwEventCount(0), noThrowEventCount(0) {} + + int throwEventCount; + int noThrowEventCount; + +protected: + bool event(QEvent *event) + { + if (int(event->type()) == ThrowEventId) { + throw IntEx(++throwEventCount); + } else if (int(event->type()) == NoThrowEventId) { + ++noThrowEventCount; + } + return QObject::event(event); + } +}; + +void tst_ExceptionSafety::exceptionEventLoop() +{ + // send an event that throws + TestObject obj; + ThrowEvent throwEvent; + try { + qApp->sendEvent(&obj, &throwEvent); + } catch (IntEx code) { + QCOMPARE(code.ex, 1); + } + QCOMPARE(obj.throwEventCount, 1); + + // post an event that throws + qApp->postEvent(&obj, new ThrowEvent); + + try { + qApp->processEvents(); + } catch (IntEx code) { + QCOMPARE(code.ex, 2); + } + QCOMPARE(obj.throwEventCount, 2); + + // post a normal event, then a throwing event, then a normal event + // run this in valgrind to ensure that it doesn't leak. + + qApp->postEvent(&obj, new NoThrowEvent); + qApp->postEvent(&obj, new ThrowEvent); + qApp->postEvent(&obj, new NoThrowEvent); + + try { + qApp->processEvents(); + } catch (IntEx code) { + QCOMPARE(code.ex, 3); + } + // here, we should have received on non-throwing event and one throwing one + QCOMPARE(obj.throwEventCount, 3); + QCOMPARE(obj.noThrowEventCount, 1); + + // spin the event loop again + qApp->processEvents(); + + // now, we should have received the second non-throwing event + QCOMPARE(obj.noThrowEventCount, 2); +} + +void tst_ExceptionSafety::exceptionSignalSlot() +{ + Emitter e; + ExceptionThrower thrower; + Receiver r1; + Receiver r2; + + // connect a signal to a normal object, a thrower and a normal object again + connect(&e, SIGNAL(testSignal()), &r1, SLOT(receiver())); + connect(&e, SIGNAL(testSignal()), &thrower, SLOT(thrower())); + connect(&e, SIGNAL(testSignal()), &r2, SLOT(receiver())); + + int code = 0; + try { + e.emitTestSignal(); + } catch (int c) { + code = c; + } + + // 5 is the magic number that's thrown by thrower + QCOMPARE(code, 5); + + // assumption: slots are called in the connection order + QCOMPARE(r1.received, 1); + QCOMPARE(r2.received, 0); +} +#endif + +#endif + +QTEST_MAIN(tst_ExceptionSafety) +#include "tst_exceptionsafety.moc" diff --git a/tests/auto/integrationtests/exceptionsafety_objects/3rdparty/memcheck.h b/tests/auto/integrationtests/exceptionsafety_objects/3rdparty/memcheck.h new file mode 100644 index 0000000000..72a02ca9ba --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety_objects/3rdparty/memcheck.h @@ -0,0 +1,319 @@ + +/* + ---------------------------------------------------------------- + + Notice that the following BSD-style license applies to this one + file (memcheck.h) only. The rest of Valgrind is licensed under the + terms of the GNU General Public License, version 2, unless + otherwise indicated. See the COPYING file in the source + distribution for details. + + ---------------------------------------------------------------- + + This file is part of MemCheck, a heavyweight Valgrind tool for + detecting memory errors. + + Copyright (C) 2000-2008 Julian Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ---------------------------------------------------------------- + + Notice that the above BSD-style license applies to this one file + (memcheck.h) only. The entire rest of Valgrind is licensed under + the terms of the GNU General Public License, version 2. See the + COPYING file in the source distribution for details. + + ---------------------------------------------------------------- +*/ + + +#ifndef __MEMCHECK_H +#define __MEMCHECK_H + + +/* This file is for inclusion into client (your!) code. + + You can use these macros to manipulate and query memory permissions + inside your own programs. + + See comment near the top of valgrind.h on how to use them. +*/ + +#include "valgrind.h" + +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! + This enum comprises an ABI exported by Valgrind to programs + which use client requests. DO NOT CHANGE THE ORDER OF THESE + ENTRIES, NOR DELETE ANY -- add new ones at the end. */ +typedef + enum { + VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'), + VG_USERREQ__MAKE_MEM_UNDEFINED, + VG_USERREQ__MAKE_MEM_DEFINED, + VG_USERREQ__DISCARD, + VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE, + VG_USERREQ__CHECK_MEM_IS_DEFINED, + VG_USERREQ__DO_LEAK_CHECK, + VG_USERREQ__COUNT_LEAKS, + + VG_USERREQ__GET_VBITS, + VG_USERREQ__SET_VBITS, + + VG_USERREQ__CREATE_BLOCK, + + VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, + + VG_USERREQ__ENABLE_OOM, + VG_USERREQ__GET_ALLOC_INDEX, + + /* This is just for memcheck's internal use - don't use it */ + _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR + = VG_USERREQ_TOOL_BASE('M','C') + 256, + + /* This is just for memcheck's internal use - don't use it */ + _VG_USERREQ__EXCEPTION + = VG_USERREQ_TOOL_BASE('M','C') + 512, + } Vg_MemCheckClientRequest; + + + +/* Client-code macros to manipulate the state of memory. */ + +/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */ +#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__MAKE_MEM_NOACCESS, \ + _qzz_addr, _qzz_len, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Similarly, mark memory at _qzz_addr as addressable but undefined + for _qzz_len bytes. */ +#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__MAKE_MEM_UNDEFINED, \ + _qzz_addr, _qzz_len, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Similarly, mark memory at _qzz_addr as addressable and defined + for _qzz_len bytes. */ +#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__MAKE_MEM_DEFINED, \ + _qzz_addr, _qzz_len, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is + not altered: bytes which are addressable are marked as defined, + but those which are not addressable are left unchanged. */ +#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \ + _qzz_addr, _qzz_len, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Create a block-description handle. The description is an ascii + string which is included in any messages pertaining to addresses + within the specified memory range. Has no other effect on the + properties of the memory range. */ +#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__CREATE_BLOCK, \ + _qzz_addr, _qzz_len, _qzz_desc, \ + 0, 0); \ + _qzz_res; \ + })) + +/* Discard a block-description-handle. Returns 1 for an + invalid handle, 0 for a valid handle. */ +#define VALGRIND_DISCARD(_qzz_blkindex) \ + (__extension__ ({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__DISCARD, \ + 0, _qzz_blkindex, 0, 0, 0); \ + _qzz_res; \ + })) + + +/* Client-code macros to check the state of memory. */ + +/* Check that memory at _qzz_addr is addressable for _qzz_len bytes. + If suitable addressibility is not established, Valgrind prints an + error message and returns the address of the first offending byte. + Otherwise it returns zero. */ +#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,\ + _qzz_addr, _qzz_len, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Check that memory at _qzz_addr is addressable and defined for + _qzz_len bytes. If suitable addressibility and definedness are not + established, Valgrind prints an error message and returns the + address of the first offending byte. Otherwise it returns zero. */ +#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \ + (__extension__({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__CHECK_MEM_IS_DEFINED, \ + _qzz_addr, _qzz_len, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Use this macro to force the definedness and addressibility of an + lvalue to be checked. If suitable addressibility and definedness + are not established, Valgrind prints an error message and returns + the address of the first offending byte. Otherwise it returns + zero. */ +#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \ + VALGRIND_CHECK_MEM_IS_DEFINED( \ + (volatile unsigned char *)&(__lvalue), \ + (unsigned long)(sizeof (__lvalue))) + + +/* Do a memory leak check mid-execution. */ +#define VALGRIND_DO_LEAK_CHECK \ + {unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__DO_LEAK_CHECK, \ + 0, 0, 0, 0, 0); \ + } + +/* Just display summaries of leaked memory, rather than all the + details */ +#define VALGRIND_DO_QUICK_LEAK_CHECK \ + {unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__DO_LEAK_CHECK, \ + 1, 0, 0, 0, 0); \ + } + +/* Return number of leaked, dubious, reachable and suppressed bytes found by + all previous leak checks. They must be lvalues. */ +#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \ + /* For safety on 64-bit platforms we assign the results to private + unsigned long variables, then assign these to the lvalues the user + specified, which works no matter what type 'leaked', 'dubious', etc + are. We also initialise '_qzz_leaked', etc because + VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as + initialised. */ \ + {unsigned long _qzz_res; \ + unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \ + unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__COUNT_LEAKS, \ + &_qzz_leaked, &_qzz_dubious, \ + &_qzz_reachable, &_qzz_suppressed, 0); \ + leaked = _qzz_leaked; \ + dubious = _qzz_dubious; \ + reachable = _qzz_reachable; \ + suppressed = _qzz_suppressed; \ + } + + +/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it + into the provided zzvbits array. Return values: + 0 if not running on valgrind + 1 success + 2 [previously indicated unaligned arrays; these are now allowed] + 3 if any parts of zzsrc/zzvbits are not addressable. + The metadata is not copied in cases 0, 2 or 3 so it should be + impossible to segfault your system by using this call. +*/ +#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \ + (__extension__({unsigned long _qzz_res; \ + char* czza = (char*)zza; \ + char* czzvbits = (char*)zzvbits; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__GET_VBITS, \ + czza, czzvbits, zznbytes, 0, 0 ); \ + _qzz_res; \ + })) + +/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it + from the provided zzvbits array. Return values: + 0 if not running on valgrind + 1 success + 2 [previously indicated unaligned arrays; these are now allowed] + 3 if any parts of zza/zzvbits are not addressable. + The metadata is not copied in cases 0, 2 or 3 so it should be + impossible to segfault your system by using this call. +*/ +#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \ + (__extension__({unsigned int _qzz_res; \ + char* czza = (char*)zza; \ + char* czzvbits = (char*)zzvbits; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__SET_VBITS, \ + czza, czzvbits, zznbytes, 0, 0 ); \ + _qzz_res; \ + })) + +/* Enable or disable OOM simulation. */ +#define VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(index) \ + (__extension__ ({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__ENABLE_OOM, \ + 1, index, 0, 0, 0); \ + _qzz_res; \ + })) + +#define VALGRIND_DISABLE_OOM_AT_ALLOC_INDEX(index) \ + (__extension__ ({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ + VG_USERREQ__ENABLE_OOM, \ + 0, index, 0, 0, 0); \ + _qzz_res; \ + })) + +/* Get the current allocation index. */ +#define VALGRIND_GET_ALLOC_INDEX \ + (__extension__ ({unsigned long _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, -1 /* default return */, \ + VG_USERREQ__GET_ALLOC_INDEX, \ + 0, 0, 0, 0, 0); \ + _qzz_res; \ + })) + + +#endif + diff --git a/tests/auto/integrationtests/exceptionsafety_objects/3rdparty/valgrind.h b/tests/auto/integrationtests/exceptionsafety_objects/3rdparty/valgrind.h new file mode 100644 index 0000000000..577c59ab0c --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety_objects/3rdparty/valgrind.h @@ -0,0 +1,3924 @@ +/* -*- c -*- + ---------------------------------------------------------------- + + Notice that the following BSD-style license applies to this one + file (valgrind.h) only. The rest of Valgrind is licensed under the + terms of the GNU General Public License, version 2, unless + otherwise indicated. See the COPYING file in the source + distribution for details. + + ---------------------------------------------------------------- + + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Julian Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ---------------------------------------------------------------- + + Notice that the above BSD-style license applies to this one file + (valgrind.h) only. The entire rest of Valgrind is licensed under + the terms of the GNU General Public License, version 2. See the + COPYING file in the source distribution for details. + + ---------------------------------------------------------------- +*/ + + +/* This file is for inclusion into client (your!) code. + + You can use these macros to manipulate and query Valgrind's + execution inside your own programs. + + The resulting executables will still run without Valgrind, just a + little bit more slowly than they otherwise would, but otherwise + unchanged. When not running on valgrind, each client request + consumes very few (eg. 7) instructions, so the resulting performance + loss is negligible unless you plan to execute client requests + millions of times per second. Nevertheless, if that is still a + problem, you can compile with the NVALGRIND symbol defined (gcc + -DNVALGRIND) so that client requests are not even compiled in. */ + +#ifndef __VALGRIND_H +#define __VALGRIND_H + +#include + +/* Nb: this file might be included in a file compiled with -ansi. So + we can't use C++ style "//" comments nor the "asm" keyword (instead + use "__asm__"). */ + +/* Derive some tags indicating what the target platform is. Note + that in this file we're using the compiler's CPP symbols for + identifying architectures, which are different to the ones we use + within the rest of Valgrind. Note, __powerpc__ is active for both + 32 and 64-bit PPC, whereas __powerpc64__ is only active for the + latter (on Linux, that is). */ +#undef PLAT_x86_linux +#undef PLAT_amd64_linux +#undef PLAT_ppc32_linux +#undef PLAT_ppc64_linux +#undef PLAT_ppc32_aix5 +#undef PLAT_ppc64_aix5 + +#if !defined(_AIX) && defined(__i386__) +# define PLAT_x86_linux 1 +#elif !defined(_AIX) && defined(__x86_64__) +# define PLAT_amd64_linux 1 +#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) +# define PLAT_ppc32_linux 1 +#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) +# define PLAT_ppc64_linux 1 +#elif defined(_AIX) && defined(__64BIT__) +# define PLAT_ppc64_aix5 1 +#elif defined(_AIX) && !defined(__64BIT__) +# define PLAT_ppc32_aix5 1 +#endif + + +/* If we're not compiling for our target platform, don't generate + any inline asms. */ +#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \ + && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \ + && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) +# if !defined(NVALGRIND) +# define NVALGRIND 1 +# endif +#endif + + +/* ------------------------------------------------------------------ */ +/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ +/* in here of use to end-users -- skip to the next section. */ +/* ------------------------------------------------------------------ */ + +#if defined(NVALGRIND) + +/* Define NVALGRIND to completely remove the Valgrind magic sequence + from the compiled code (analogous to NDEBUG's effects on + assert()) */ +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + { \ + (_zzq_rlval) = (_zzq_default); \ + } + +#else /* ! NVALGRIND */ + +/* The following defines the magic code sequences which the JITter + spots and handles magically. Don't look too closely at them as + they will rot your brain. + + The assembly code sequences for all architectures is in this one + file. This is because this file must be stand-alone, and we don't + want to have multiple files. + + For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default + value gets put in the return slot, so that everything works when + this is executed not under Valgrind. Args are passed in a memory + block, and so there's no intrinsic limit to the number that could + be passed, but it's currently five. + + The macro args are: + _zzq_rlval result lvalue + _zzq_default default value (result returned when running on real CPU) + _zzq_request request code + _zzq_arg1..5 request params + + The other two macros are used to support function wrapping, and are + a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the + guest's NRADDR pseudo-register and whatever other information is + needed to safely run the call original from the wrapper: on + ppc64-linux, the R2 value at the divert point is also needed. This + information is abstracted into a user-visible type, OrigFn. + + VALGRIND_CALL_NOREDIR_* behaves the same as the following on the + guest, but guarantees that the branch instruction will not be + redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: + branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a + complete inline asm, since it needs to be combined with more magic + inline asm stuff to be useful. +*/ + +/* ------------------------- x86-linux ------------------------- */ + +#if defined(PLAT_x86_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "roll $3, %%edi ; roll $13, %%edi\n\t" \ + "roll $29, %%edi ; roll $19, %%edi\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + { volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EDX = client_request ( %EAX ) */ \ + "xchgl %%ebx,%%ebx" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "memory" \ + ); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EAX = guest_NRADDR */ \ + "xchgl %%ecx,%%ecx" \ + : "=a" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_EAX \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%EAX */ \ + "xchgl %%edx,%%edx\n\t" +#endif /* PLAT_x86_linux */ + +/* ------------------------ amd64-linux ------------------------ */ + +#if defined(PLAT_amd64_linux) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ + "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + { volatile unsigned long long int _zzq_args[6]; \ + volatile unsigned long long int _zzq_result; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %RDX = client_request ( %RAX ) */ \ + "xchgq %%rbx,%%rbx" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "memory" \ + ); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %RAX = guest_NRADDR */ \ + "xchgq %%rcx,%%rcx" \ + : "=a" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_RAX \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%RAX */ \ + "xchgq %%rdx,%%rdx\n\t" +#endif /* PLAT_amd64_linux */ + +/* ------------------------ ppc32-linux ------------------------ */ + +#if defined(PLAT_ppc32_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ + "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + { unsigned int _zzq_args[6]; \ + unsigned int _zzq_result; \ + unsigned int* _zzq_ptr; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" +#endif /* PLAT_ppc32_linux */ + +/* ------------------------ ppc64-linux ------------------------ */ + +#if defined(PLAT_ppc64_linux) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + unsigned long long int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + { unsigned long long int _zzq_args[6]; \ + register unsigned long long int _zzq_result __asm__("r3"); \ + register unsigned long long int* _zzq_ptr __asm__("r4"); \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1" \ + : "=r" (_zzq_result) \ + : "0" (_zzq_default), "r" (_zzq_ptr) \ + : "cc", "memory"); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + register unsigned long long int __addr __asm__("r3"); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2" \ + : "=r" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4" \ + : "=r" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#endif /* PLAT_ppc64_linux */ + +/* ------------------------ ppc32-aix5 ------------------------- */ + +#if defined(PLAT_ppc32_aix5) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + unsigned int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ + "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + { unsigned int _zzq_args[7]; \ + register unsigned int _zzq_result; \ + register unsigned int* _zzq_ptr; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + _zzq_args[6] = (unsigned int)(_zzq_default); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 4,%1\n\t" \ + "lwz 3, 24(4)\n\t" \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" \ + : "=b" (_zzq_result) \ + : "b" (_zzq_ptr) \ + : "r3", "r4", "cc", "memory"); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + register unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "r3", "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "r3", "cc", "memory" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#endif /* PLAT_ppc32_aix5 */ + +/* ------------------------ ppc64-aix5 ------------------------- */ + +#if defined(PLAT_ppc64_aix5) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + unsigned long long int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST( \ + _zzq_rlval, _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + { unsigned long long int _zzq_args[7]; \ + register unsigned long long int _zzq_result; \ + register unsigned long long int* _zzq_ptr; \ + _zzq_args[0] = (unsigned int long long)(_zzq_request); \ + _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ + _zzq_args[6] = (unsigned int long long)(_zzq_default); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 4,%1\n\t" \ + "ld 3, 48(4)\n\t" \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" \ + : "=b" (_zzq_result) \ + : "b" (_zzq_ptr) \ + : "r3", "r4", "cc", "memory"); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + register unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "r3", "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "r3", "cc", "memory" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#endif /* PLAT_ppc64_aix5 */ + +/* Insert assembly code for other platforms here... */ + +#endif /* NVALGRIND */ + + +/* ------------------------------------------------------------------ */ +/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ +/* ugly. It's the least-worst tradeoff I can think of. */ +/* ------------------------------------------------------------------ */ + +/* This section defines magic (a.k.a appalling-hack) macros for doing + guaranteed-no-redirection macros, so as to get from function + wrappers to the functions they are wrapping. The whole point is to + construct standard call sequences, but to do the call itself with a + special no-redirect call pseudo-instruction that the JIT + understands and handles specially. This section is long and + repetitious, and I can't see a way to make it shorter. + + The naming scheme is as follows: + + CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} + + 'W' stands for "word" and 'v' for "void". Hence there are + different macros for calling arity 0, 1, 2, 3, 4, etc, functions, + and for each, the possibility of returning a word-typed result, or + no result. +*/ + +/* Use these to write the name of your wrapper. NOTE: duplicates + VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ + +#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ + _vgwZU_##soname##_##fnname + +#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ + _vgwZZ_##soname##_##fnname + +/* Use this macro from within a wrapper function to collect the + context (address and possibly other info) of the original function. + Once you have that you can then use it in one of the CALL_FN_ + macros. The type of the argument _lval is OrigFn. */ +#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) + +/* Derivatives of the main macros below, for calling functions + returning void. */ + +#define CALL_FN_v_v(fnptr) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_v(_junk,fnptr); } while (0) + +#define CALL_FN_v_W(fnptr, arg1) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_W(_junk,fnptr,arg1); } while (0) + +#define CALL_FN_v_WW(fnptr, arg1,arg2) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) + +#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) + +/* ------------------------- x86-linux ------------------------- */ + +#if defined(PLAT_x86_linux) + +/* These regs are trashed by the hidden call. No need to mention eax + as gcc can already see that, plus causes gcc to bomb. */ +#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" + +/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $4, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $8, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $12, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $16, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $20, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $24, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $28, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $32, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $36, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $40, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "pushl 44(%%eax)\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $44, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "pushl 48(%%eax)\n\t" \ + "pushl 44(%%eax)\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + "addl $48, %%esp\n" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_x86_linux */ + +/* ------------------------ amd64-linux ------------------------ */ + +#if defined(PLAT_amd64_linux) + +/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ + "rdi", "r8", "r9", "r10", "r11" + +/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned + long) == 8. */ + +/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ + macros. In order not to trash the stack redzone, we need to drop + %rsp by 128 before the hidden call, and restore afterwards. The + nastyness is that it is only by luck that the stack still appears + to be unwindable during the hidden call - since then the behaviour + of any routine using this macro does not match what the CFI data + says. Sigh. + + Why is this important? Imagine that a wrapper has a stack + allocated local, and passes to the hidden call, a pointer to it. + Because gcc does not know about the hidden call, it may allocate + that local in the redzone. Unfortunately the hidden call may then + trash it before it comes to use it. So we must step clear of the + redzone, for the duration of the hidden call, to make it safe. + + Probably the same problem afflicts the other redzone-style ABIs too + (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is + self describing (none of this CFI nonsense) so at least messing + with the stack pointer doesn't give a danger of non-unwindable + stack. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + "addq $128,%%rsp\n\t" \ + VALGRIND_CALL_NOREDIR_RAX \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $8, %%rsp\n" \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $16, %%rsp\n" \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $24, %%rsp\n" \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $32, %%rsp\n" \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "pushq 88(%%rax)\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $40, %%rsp\n" \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "subq $128,%%rsp\n\t" \ + "pushq 96(%%rax)\n\t" \ + "pushq 88(%%rax)\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + "addq $48, %%rsp\n" \ + "addq $128,%%rsp\n\t" \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_amd64_linux */ + +/* ------------------------ ppc32-linux ------------------------ */ + +#if defined(PLAT_ppc32_linux) + +/* This is useful for finding out about the on-stack stuff: + + extern int f9 ( int,int,int,int,int,int,int,int,int ); + extern int f10 ( int,int,int,int,int,int,int,int,int,int ); + extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); + extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); + + int g9 ( void ) { + return f9(11,22,33,44,55,66,77,88,99); + } + int g10 ( void ) { + return f10(11,22,33,44,55,66,77,88,99,110); + } + int g11 ( void ) { + return f11(11,22,33,44,55,66,77,88,99,110,121); + } + int g12 ( void ) { + return f12(11,22,33,44,55,66,77,88,99,110,121,132); + } +*/ + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* These CALL_FN_ macros assume that on ppc32-linux, + sizeof(unsigned long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "addi 1,1,-16\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "addi 1,1,16\n\t" \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "addi 1,1,-16\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "addi 1,1,16\n\t" \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "addi 1,1,-32\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,16(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "addi 1,1,32\n\t" \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + _argvec[12] = (unsigned long)arg12; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "addi 1,1,-32\n\t" \ + /* arg12 */ \ + "lwz 3,48(11)\n\t" \ + "stw 3,20(1)\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,16(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "addi 1,1,32\n\t" \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc32_linux */ + +/* ------------------------ ppc64-linux ------------------------ */ + +#if defined(PLAT_ppc64_linux) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned + long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)" /* restore tocptr */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + "addi 1,1,128" /* restore frame */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + "addi 1,1,128" /* restore frame */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + "addi 1,1,144" /* restore frame */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg12 */ \ + "ld 3,96(11)\n\t" \ + "std 3,136(1)\n\t" \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + "addi 1,1,144" /* restore frame */ \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc64_linux */ + +/* ------------------------ ppc32-aix5 ------------------------- */ + +#if defined(PLAT_ppc32_aix5) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Expand the stack frame, copying enough info that unwinding + still works. Trashes r3. */ + +#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ + "addi 1,1,-" #_n_fr "\n\t" \ + "lwz 3," #_n_fr "(1)\n\t" \ + "stw 3,0(1)\n\t" + +#define VG_CONTRACT_FRAME_BY(_n_fr) \ + "addi 1,1," #_n_fr "\n\t" + +/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(64) \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,56(1)\n\t" \ + /* args1-8 */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(64) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(64) \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,60(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,56(1)\n\t" \ + /* args1-8 */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(64) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(72) \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,64(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,60(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,56(1)\n\t" \ + /* args1-8 */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(72) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "stw 2,-8(11)\n\t" /* save tocptr */ \ + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(72) \ + /* arg12 */ \ + "lwz 3,48(11)\n\t" \ + "stw 3,68(1)\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,64(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,60(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,56(1)\n\t" \ + /* args1-8 */ \ + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ + "lwz 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "lwz 2,-8(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(72) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc32_aix5 */ + +/* ------------------------ ppc64-aix5 ------------------------- */ + +#if defined(PLAT_ppc64_aix5) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Expand the stack frame, copying enough info that unwinding + still works. Trashes r3. */ + +#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ + "addi 1,1,-" #_n_fr "\n\t" \ + "ld 3," #_n_fr "(1)\n\t" \ + "std 3,0(1)\n\t" + +#define VG_CONTRACT_FRAME_BY(_n_fr) \ + "addi 1,1," #_n_fr "\n\t" + +/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned + long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(128) \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(128) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(128) \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(128) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(144) \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(144) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + "mr 11,%1\n\t" \ + VG_EXPAND_FRAME_BY_trashes_r3(512) \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + VG_EXPAND_FRAME_BY_trashes_r3(144) \ + /* arg12 */ \ + "ld 3,96(11)\n\t" \ + "std 3,136(1)\n\t" \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VG_CONTRACT_FRAME_BY(144) \ + VG_CONTRACT_FRAME_BY(512) \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc64_aix5 */ + + +/* ------------------------------------------------------------------ */ +/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ +/* */ +/* ------------------------------------------------------------------ */ + +/* Some request codes. There are many more of these, but most are not + exposed to end-user view. These are the public ones, all of the + form 0x1000 + small_number. + + Core ones are in the range 0x00000000--0x0000ffff. The non-public + ones start at 0x2000. +*/ + +/* These macros are used by tools -- they must be public, but don't + embed them into other programs. */ +#define VG_USERREQ_TOOL_BASE(a,b) \ + ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) +#define VG_IS_TOOL_USERREQ(a, b, v) \ + (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) + +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! + This enum comprises an ABI exported by Valgrind to programs + which use client requests. DO NOT CHANGE THE ORDER OF THESE + ENTRIES, NOR DELETE ANY -- add new ones at the end. */ +typedef + enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, + VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, + + /* These allow any function to be called from the simulated + CPU but run on the real CPU. Nb: the first arg passed to + the function is always the ThreadId of the running + thread! So CLIENT_CALL0 actually requires a 1 arg + function, etc. */ + VG_USERREQ__CLIENT_CALL0 = 0x1101, + VG_USERREQ__CLIENT_CALL1 = 0x1102, + VG_USERREQ__CLIENT_CALL2 = 0x1103, + VG_USERREQ__CLIENT_CALL3 = 0x1104, + + /* Can be useful in regression testing suites -- eg. can + send Valgrind's output to /dev/null and still count + errors. */ + VG_USERREQ__COUNT_ERRORS = 0x1201, + + /* These are useful and can be interpreted by any tool that + tracks malloc() et al, by using vg_replace_malloc.c. */ + VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, + VG_USERREQ__FREELIKE_BLOCK = 0x1302, + /* Memory pool support. */ + VG_USERREQ__CREATE_MEMPOOL = 0x1303, + VG_USERREQ__DESTROY_MEMPOOL = 0x1304, + VG_USERREQ__MEMPOOL_ALLOC = 0x1305, + VG_USERREQ__MEMPOOL_FREE = 0x1306, + VG_USERREQ__MEMPOOL_TRIM = 0x1307, + VG_USERREQ__MOVE_MEMPOOL = 0x1308, + VG_USERREQ__MEMPOOL_CHANGE = 0x1309, + VG_USERREQ__MEMPOOL_EXISTS = 0x130a, + + /* Allow printfs to valgrind log. */ + VG_USERREQ__PRINTF = 0x1401, + VG_USERREQ__PRINTF_BACKTRACE = 0x1402, + + /* Stack support. */ + VG_USERREQ__STACK_REGISTER = 0x1501, + VG_USERREQ__STACK_DEREGISTER = 0x1502, + VG_USERREQ__STACK_CHANGE = 0x1503 + } Vg_ClientRequest; + +#if !defined(__GNUC__) +# define __extension__ /* */ +#endif + +/* Returns the number of Valgrinds this code is running under. That + is, 0 if running natively, 1 if running under Valgrind, 2 if + running under Valgrind which is running under another Valgrind, + etc. */ +#define RUNNING_ON_VALGRIND __extension__ \ + ({unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ + VG_USERREQ__RUNNING_ON_VALGRIND, \ + 0, 0, 0, 0, 0); \ + _qzz_res; \ + }) + + +/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + + _qzz_len - 1]. Useful if you are debugging a JITter or some such, + since it provides a way to make sure valgrind will retranslate the + invalidated area. Returns no value. */ +#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__DISCARD_TRANSLATIONS, \ + _qzz_addr, _qzz_len, 0, 0, 0); \ + } + + +/* These requests are for getting Valgrind itself to print something. + Possibly with a backtrace. This is a really ugly hack. */ + +#if defined(NVALGRIND) + +# define VALGRIND_PRINTF(...) +# define VALGRIND_PRINTF_BACKTRACE(...) + +#else /* NVALGRIND */ + +/* Modern GCC will optimize the static routine out if unused, + and unused attribute will shut down warnings about it. */ +static int VALGRIND_PRINTF(const char *format, ...) + __attribute__((format(__printf__, 1, 2), __unused__)); +static int +VALGRIND_PRINTF(const char *format, ...) +{ + unsigned long _qzz_res; + va_list vargs; + va_start(vargs, format); + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, + (unsigned long)format, (unsigned long)vargs, + 0, 0, 0); + va_end(vargs); + return (int)_qzz_res; +} + +static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) + __attribute__((format(__printf__, 1, 2), __unused__)); +static int +VALGRIND_PRINTF_BACKTRACE(const char *format, ...) +{ + unsigned long _qzz_res; + va_list vargs; + va_start(vargs, format); + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, + (unsigned long)format, (unsigned long)vargs, + 0, 0, 0); + va_end(vargs); + return (int)_qzz_res; +} + +#endif /* NVALGRIND */ + + +/* These requests allow control to move from the simulated CPU to the + real CPU, calling an arbitary function. + + Note that the current ThreadId is inserted as the first argument. + So this call: + + VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) + + requires f to have this signature: + + Word f(Word tid, Word arg1, Word arg2) + + where "Word" is a word-sized type. + + Note that these client requests are not entirely reliable. For example, + if you call a function with them that subsequently calls printf(), + there's a high chance Valgrind will crash. Generally, your prospects of + these working are made higher if the called function does not refer to + any global variables, and does not refer to any libc or other functions + (printf et al). Any kind of entanglement with libc or dynamic linking is + likely to have a bad outcome, for tricky reasons which we've grappled + with a lot in the past. +*/ +#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ + __extension__ \ + ({unsigned long _qyy_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ + VG_USERREQ__CLIENT_CALL0, \ + _qyy_fn, \ + 0, 0, 0, 0); \ + _qyy_res; \ + }) + +#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ + __extension__ \ + ({unsigned long _qyy_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ + VG_USERREQ__CLIENT_CALL1, \ + _qyy_fn, \ + _qyy_arg1, 0, 0, 0); \ + _qyy_res; \ + }) + +#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ + __extension__ \ + ({unsigned long _qyy_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ + VG_USERREQ__CLIENT_CALL2, \ + _qyy_fn, \ + _qyy_arg1, _qyy_arg2, 0, 0); \ + _qyy_res; \ + }) + +#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ + __extension__ \ + ({unsigned long _qyy_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ + VG_USERREQ__CLIENT_CALL3, \ + _qyy_fn, \ + _qyy_arg1, _qyy_arg2, \ + _qyy_arg3, 0); \ + _qyy_res; \ + }) + + +/* Counts the number of errors that have been recorded by a tool. Nb: + the tool must record the errors with VG_(maybe_record_error)() or + VG_(unique_error)() for them to be counted. */ +#define VALGRIND_COUNT_ERRORS \ + __extension__ \ + ({unsigned int _qyy_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ + VG_USERREQ__COUNT_ERRORS, \ + 0, 0, 0, 0, 0); \ + _qyy_res; \ + }) + +/* Mark a block of memory as having been allocated by a malloc()-like + function. `addr' is the start of the usable block (ie. after any + redzone) `rzB' is redzone size if the allocator can apply redzones; + use '0' if not. Adding redzones makes it more likely Valgrind will spot + block overruns. `is_zeroed' indicates if the memory is zeroed, as it is + for calloc(). Put it immediately after the point where a block is + allocated. + + If you're using Memcheck: If you're allocating memory via superblocks, + and then handing out small chunks of each superblock, if you don't have + redzones on your small blocks, it's worth marking the superblock with + VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are + detected. But if you can put redzones on, it's probably better to not do + this, so that messages for small overruns are described in terms of the + small block rather than the superblock (but if you have a big overrun + that skips over a redzone, you could miss an error this way). See + memcheck/tests/custom_alloc.c for an example. + + WARNING: if your allocator uses malloc() or 'new' to allocate + superblocks, rather than mmap() or brk(), this will not work properly -- + you'll likely get assertion failures during leak detection. This is + because Valgrind doesn't like seeing overlapping heap blocks. Sorry. + + Nb: block must be freed via a free()-like function specified + with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ +#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MALLOCLIKE_BLOCK, \ + addr, sizeB, rzB, is_zeroed, 0); \ + } + +/* Mark a block of memory as having been freed by a free()-like function. + `rzB' is redzone size; it must match that given to + VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak + checker. Put it immediately after the point where the block is freed. */ +#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__FREELIKE_BLOCK, \ + addr, rzB, 0, 0, 0); \ + } + +/* Create a memory pool. */ +#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__CREATE_MEMPOOL, \ + pool, rzB, is_zeroed, 0, 0); \ + } + +/* Destroy a memory pool. */ +#define VALGRIND_DESTROY_MEMPOOL(pool) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__DESTROY_MEMPOOL, \ + pool, 0, 0, 0, 0); \ + } + +/* Associate a piece of memory with a memory pool. */ +#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MEMPOOL_ALLOC, \ + pool, addr, size, 0, 0); \ + } + +/* Disassociate a piece of memory from a memory pool. */ +#define VALGRIND_MEMPOOL_FREE(pool, addr) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MEMPOOL_FREE, \ + pool, addr, 0, 0, 0); \ + } + +/* Disassociate any pieces outside a particular range. */ +#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MEMPOOL_TRIM, \ + pool, addr, size, 0, 0); \ + } + +/* Resize and/or move a piece associated with a memory pool. */ +#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MOVE_MEMPOOL, \ + poolA, poolB, 0, 0, 0); \ + } + +/* Resize and/or move a piece associated with a memory pool. */ +#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MEMPOOL_CHANGE, \ + pool, addrA, addrB, size, 0); \ + } + +/* Return 1 if a mempool exists, else 0. */ +#define VALGRIND_MEMPOOL_EXISTS(pool) \ + ({unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MEMPOOL_EXISTS, \ + pool, 0, 0, 0, 0); \ + _qzz_res; \ + }) + +/* Mark a piece of memory as being a stack. Returns a stack id. */ +#define VALGRIND_STACK_REGISTER(start, end) \ + ({unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__STACK_REGISTER, \ + start, end, 0, 0, 0); \ + _qzz_res; \ + }) + +/* Unmark the piece of memory associated with a stack id as being a + stack. */ +#define VALGRIND_STACK_DEREGISTER(id) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__STACK_DEREGISTER, \ + id, 0, 0, 0, 0); \ + } + +/* Change the start and end address of the stack id. */ +#define VALGRIND_STACK_CHANGE(id, start, end) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__STACK_CHANGE, \ + id, start, end, 0, 0); \ + } + + +#undef PLAT_x86_linux +#undef PLAT_amd64_linux +#undef PLAT_ppc32_linux +#undef PLAT_ppc64_linux +#undef PLAT_ppc32_aix5 +#undef PLAT_ppc64_aix5 + +#endif /* __VALGRIND_H */ diff --git a/tests/auto/integrationtests/exceptionsafety_objects/exceptionsafety_objects.pro b/tests/auto/integrationtests/exceptionsafety_objects/exceptionsafety_objects.pro new file mode 100644 index 0000000000..d09c349215 --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety_objects/exceptionsafety_objects.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +QT += widgets +HEADERS += oomsimulator.h 3rdparty/valgrind.h 3rdparty/memcheck.h +SOURCES += tst_exceptionsafety_objects.cpp + +CONFIG+=insignificant_test diff --git a/tests/auto/integrationtests/exceptionsafety_objects/oomsimulator.h b/tests/auto/integrationtests/exceptionsafety_objects/oomsimulator.h new file mode 100644 index 0000000000..ed4bb53922 --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety_objects/oomsimulator.h @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include + +#if !defined(Q_OS_WIN) +# include "3rdparty/memcheck.h" +#endif + +static bool mallocFailActive = false; +static int mallocFailIndex = 0; +static int mallocCount = 0; + +static void my_terminate_handler() +{ + // set a breakpoint here to get a backtrace for your uncaught exceptions + fprintf(stderr, "Uncaught Exception Detected. Set a breakpoint in my_terminate_handler()\n"); + exit(1); +} + +#ifdef __GLIBC__ +/* Use glibc's memory allocation hooks */ + +// From glibc 2.14, the malloc hook variables are declared volatile. +// Note: The malloc hook implementation is marked as deprecated. + +#if !defined(__MALLOC_HOOK_VOLATILE) +# define __MALLOC_HOOK_VOLATILE +#endif + +/* our hooks */ +static void *my_malloc_hook(size_t, const void *); +static void *my_realloc_hook(void *, size_t, const void *); +static void *my_memalign_hook(size_t, size_t, const void *); +static void my_free_hook(void *, const void *); + +/* original hooks. */ +static void *(*__MALLOC_HOOK_VOLATILE old_malloc_hook)(size_t, const void *); +static void *(*__MALLOC_HOOK_VOLATILE old_realloc_hook)(void *, size_t, const void *); +static void *(*__MALLOC_HOOK_VOLATILE old_memalign_hook)(size_t, size_t, const void *); +static void (*__MALLOC_HOOK_VOLATILE old_free_hook)(void *, const void *); + +/* initializer function */ +static void my_init_hook(); + +/* Override initialising hook from the C library. */ + +void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook; + +static void disableHooks() +{ + __malloc_hook = old_malloc_hook; + __realloc_hook = old_realloc_hook; + __memalign_hook = old_memalign_hook; + __free_hook = old_free_hook; +} + +static void enableHooks() +{ + __malloc_hook = my_malloc_hook; + __realloc_hook = my_realloc_hook; + __memalign_hook = my_memalign_hook; + __free_hook = my_free_hook; +} + +void my_init_hook() +{ + old_malloc_hook = __malloc_hook; + old_realloc_hook = __realloc_hook; + old_memalign_hook = __memalign_hook; + old_free_hook = __free_hook; + enableHooks(); +} + +void *my_malloc_hook(size_t size, const void *) +{ + ++mallocCount; + + if (mallocFailActive && --mallocFailIndex < 0) + return 0; // simulate OOM + + __malloc_hook = old_malloc_hook; + void *result = ::malloc (size); + __malloc_hook = my_malloc_hook; + + return result; +} + +void *my_memalign_hook(size_t alignment, size_t size, const void *) +{ + ++mallocCount; + + if (mallocFailActive && --mallocFailIndex < 0) + return 0; // simulate OOM + + __memalign_hook = old_memalign_hook; + void *result = ::memalign(alignment, size); + __memalign_hook = my_memalign_hook; + + return result; +} + +void *my_realloc_hook(void *ptr, size_t size, const void *) +{ + ++mallocCount; + + if (mallocFailActive && --mallocFailIndex < 0) + return 0; // simulate OOM + + __realloc_hook = old_realloc_hook; + __malloc_hook = old_malloc_hook; + void *result = ::realloc(ptr, size); + __malloc_hook = my_malloc_hook; + __realloc_hook = my_realloc_hook; + + return result; +} + +void my_free_hook(void *ptr, const void *) +{ + __free_hook = old_free_hook; + ::free(ptr); + __free_hook = my_free_hook; +} + +#elif defined(Q_CC_MSVC) + +#include "crtdbg.h" + +static int qCrtAllocHook(int allocType, void * /*userData*/, size_t /*size*/, + int blockType, long /*requestNumber*/, + const unsigned char * /*filename*/, int /*lineNumber*/) +{ + if (blockType == _CRT_BLOCK) + return TRUE; // ignore allocations from the C library + + switch (allocType) { + case _HOOK_ALLOC: + case _HOOK_REALLOC: + ++mallocCount; + if (mallocFailActive && --mallocFailIndex < 0) + return FALSE; // simulate OOM + } + + return TRUE; +} + +static struct QCrtDebugRegistrator +{ + QCrtDebugRegistrator() + { + _CrtSetAllocHook(qCrtAllocHook); + } + +} crtDebugRegistrator; + +#endif + +struct AllocFailer +{ + inline AllocFailer(int index) { reactivateAt(index); } + inline ~AllocFailer() { deactivate(); } + + inline void reactivateAt(int index) + { +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) + VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(VALGRIND_GET_ALLOC_INDEX + index + 1); +#endif + mallocFailIndex = index; + mallocFailActive = true; + } + + inline void deactivate() + { + mallocFailActive = false; +#ifdef RUNNING_ON_VALGRIND + VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(0); +#endif + } + + inline int currentAllocIndex() const + { +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) + return VALGRIND_GET_ALLOC_INDEX; +#endif + return mallocCount; + } + + static bool initialize() + { + std::set_terminate(my_terminate_handler); +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) { + if (VALGRIND_GET_ALLOC_INDEX == -1u) { + qWarning("You must use a valgrind with oom simulation support"); + return false; + } + // running in valgrind - don't use glibc hooks + disableHooks(); + + // never stop simulating OOM + VALGRIND_DISABLE_OOM_AT_ALLOC_INDEX(-1u); + } +#endif + return true; + } +}; + +static void *new_helper(std::size_t size) +{ + void *ptr = malloc(size); + if (!ptr) + throw std::bad_alloc(); + return ptr; +} + +#ifdef Q_CC_MSVC +# pragma warning(push) +# pragma warning(disable: 4290) +#endif + +// overload operator new +void* operator new(size_t size) throw (std::bad_alloc) { return new_helper(size); } +void* operator new[](size_t size) throw (std::bad_alloc) { return new_helper(size); } +void* operator new(size_t size, const std::nothrow_t&) throw() { return malloc(size); } +void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc(size); } + +// overload operator delete +void operator delete(void *ptr) throw() { if (ptr) free(ptr); } +void operator delete[](void *ptr) throw() { if (ptr) free(ptr); } +void operator delete(void *ptr, const std::nothrow_t&) throw() { if (ptr) free(ptr); } +void operator delete[](void *ptr, const std::nothrow_t&) throw() { if (ptr) free (ptr); } + +#ifdef Q_CC_MSVC +# pragma warning(pop) +#endif + +// ignore placement new and placement delete - those don't allocate. + + diff --git a/tests/auto/integrationtests/exceptionsafety_objects/tst_exceptionsafety_objects.cpp b/tests/auto/integrationtests/exceptionsafety_objects/tst_exceptionsafety_objects.cpp new file mode 100644 index 0000000000..0d410a79a2 --- /dev/null +++ b/tests/auto/integrationtests/exceptionsafety_objects/tst_exceptionsafety_objects.cpp @@ -0,0 +1,801 @@ +/**************************************************************************** +** +** 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 +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +// this test only works with GLIBC + +#include "oomsimulator.h" +#include "3rdparty/memcheck.h" + +class tst_ExceptionSafety_Objects: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); +#ifndef QT_NO_EXCEPTIONS + void cleanupTestCase(); + +private slots: + void objects_data(); + void objects(); + + void widgets_data(); + void widgets(); + + void vector_data(); + void vector(); + + void list_data(); + void list(); + + void linkedList_data(); + void linkedList(); + +private: + static QtMsgHandler testMessageHandler; + static void safeMessageHandler(QtMsgType, const char *); +#endif +}; + +#ifdef QT_NO_EXCEPTIONS +void tst_ExceptionSafety_Objects::initTestCase() +{ + QSKIP("This test requires exception support", SkipAll); +} + +#else +// helper structs to create an arbitrary widget +struct AbstractTester +{ + virtual void operator()(QObject *parent) = 0; +}; +Q_DECLARE_METATYPE(AbstractTester *) + +typedef void (*TestFunction)(QObject*); +Q_DECLARE_METATYPE(TestFunction) + +template +struct ObjectCreator : public AbstractTester +{ + void operator()(QObject *) + { + QScopedPointer ptr(new T); + } +}; + +struct BitArrayCreator : public AbstractTester +{ + void operator()(QObject *) + { QScopedPointer bitArray(new QBitArray(100, true)); } +}; + +struct ByteArrayMatcherCreator : public AbstractTester +{ + void operator()(QObject *) + { QScopedPointer ptr(new QByteArrayMatcher("ralf test",8)); } +}; + +struct CryptographicHashCreator : public AbstractTester +{ + void operator()(QObject *) + { + QScopedPointer ptr(new QCryptographicHash(QCryptographicHash::Sha1)); + ptr->addData("ralf test",8); + } +}; + +struct DataStreamCreator : public AbstractTester +{ + void operator()(QObject *) + { + QScopedPointer arr(new QByteArray("hallo, test")); + QScopedPointer ptr(new QDataStream(arr.data(), QIODevice::ReadWrite)); + ptr->writeBytes("ralf test",8); + } +}; + +struct DirCreator : public AbstractTester +{ + void operator()(QObject *) + { + QDir::cleanPath("../////././"); + QScopedPointer ptr(new QDir(".")); + while( ptr->cdUp() ) + ; // just going up + ptr->count(); + ptr->exists(ptr->path()); + + QStringList filters; + filters << "*.cpp" << "*.cxx" << "*.cc"; + ptr->setNameFilters(filters); + } +}; + +void tst_ExceptionSafety_Objects::objects_data() +{ + QTest::addColumn("objectCreator"); + +#define NEWROW(T) QTest::newRow(#T) << static_cast(new ObjectCreator) + NEWROW(QObject); + NEWROW(QBuffer); + NEWROW(QFile); + NEWROW(QFSFileEngine); + NEWROW(QProcess); + NEWROW(QSettings); + NEWROW(QThread); + NEWROW(QThreadPool); + NEWROW(QTranslator); + +#define NEWROW2(T, CREATOR) QTest::newRow(#T) << static_cast(new CREATOR) + NEWROW2(QBitArray, BitArrayCreator); + NEWROW2(QByteArrayMatcher, ByteArrayMatcherCreator); + NEWROW2(QCryptographicHash, CryptographicHashCreator); + NEWROW2(QDataStream, DataStreamCreator); + NEWROW2(QDir, DirCreator); +} + +// create and destructs an object, and lets each and every allocation +// during construction and destruction fail. +template +static void doOOMTest(T &testFunc, QObject *parent, int start=0) +{ + int currentOOMIndex = start; + bool caught = false; + bool done = false; + + AllocFailer allocFailer(0); + int allocCountBefore = allocFailer.currentAllocIndex(); + + do { + allocFailer.reactivateAt(++currentOOMIndex); + + caught = false; + + try { + testFunc(parent); + } catch (const std::bad_alloc &) { + caught = true; + } catch (const std::exception &ex) { + if (strcmp(ex.what(), "autotest swallow") != 0) + throw; + caught = true; + } + + if (!caught) { + void *buf = malloc(42); + if (buf) { + // we got memory here - oom test is over. + free(buf); + done = true; + } + } + + // if we get a FAIL, stop executing now + if (QTest::currentTestFailed()) + done = true; + +//#define REALLY_VERBOSE +#ifdef REALLY_VERBOSE + fprintf(stderr, " OOM Index: %d\n", currentOOMIndex); +#endif + + + } while (caught || !done); + + allocFailer.deactivate(); + +//#define VERBOSE +#ifdef VERBOSE + fprintf(stderr, "OOM Test done, checked allocs: %d (range %d - %d)\n", currentOOMIndex, + allocCountBefore, allocFailer.currentAllocIndex()); +#else + Q_UNUSED(allocCountBefore); +#endif +} + +static int alloc1Failed = 0; +static int alloc2Failed = 0; +static int alloc3Failed = 0; +static int alloc4Failed = 0; +static int malloc1Failed = 0; +static int malloc2Failed = 0; + +// Tests that new, new[] and malloc() fail at least once during OOM testing. +class SelfTestObject : public QObject +{ +public: + SelfTestObject(QObject *parent = 0) + : QObject(parent) + { + try { delete new int; } catch (const std::bad_alloc &) { ++alloc1Failed; throw; } + try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc2Failed; throw ;} + void *buf = malloc(42); + if (buf) + free(buf); + else + ++malloc1Failed; + } + + ~SelfTestObject() + { + try { delete new int; } catch (const std::bad_alloc &) { ++alloc3Failed; } + try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc4Failed; } + void *buf = malloc(42); + if (buf) + free(buf); + else + ++malloc2Failed = true; + } +}; + +QtMsgHandler tst_ExceptionSafety_Objects::testMessageHandler; + +void tst_ExceptionSafety_Objects::safeMessageHandler(QtMsgType type, const char *msg) +{ + // this temporarily suspends OOM testing while handling a message + int currentIndex = mallocFailIndex; + AllocFailer allocFailer(0); + allocFailer.deactivate(); + (*testMessageHandler)(type, msg); + allocFailer.reactivateAt(currentIndex); +} + +typedef void (*PVF)(); +PVF defaultTerminate; +void debugTerminate() +{ + // you can detect uncaught exceptions with a breakpoint in here + (*defaultTerminate)(); +} + +PVF defaultUnexpected; +void debugUnexpected() +{ + // you can detect unexpected exceptions with a breakpoint in here + (*defaultUnexpected)(); +} + +void tst_ExceptionSafety_Objects::initTestCase() +{ + // set handlers for bad exception cases, you might want to step in and breakpoint the default handlers too + defaultTerminate = std::set_terminate(&debugTerminate); + defaultUnexpected = std::set_unexpected(&debugUnexpected); + testMessageHandler = qInstallMsgHandler(safeMessageHandler); + + QVERIFY(AllocFailer::initialize()); + + // sanity check whether OOM simulation works + AllocFailer allocFailer(0); + + // malloc fail index is 0 -> this malloc should fail. + void *buf = malloc(42); + allocFailer.deactivate(); + QVERIFY(!buf); + + // malloc fail index is 1 - second malloc should fail. + allocFailer.reactivateAt(1); + buf = malloc(42); + void *buf2 = malloc(42); + allocFailer.deactivate(); + + QVERIFY(buf); + free(buf); + QVERIFY(!buf2); + + ObjectCreator *selfTest = new ObjectCreator; + doOOMTest(*selfTest, 0); + delete selfTest; + QCOMPARE(alloc1Failed, 1); + QCOMPARE(alloc2Failed, 1); + QCOMPARE(alloc3Failed, 2); + QCOMPARE(alloc4Failed, 3); + QCOMPARE(malloc1Failed, 1); + QCOMPARE(malloc2Failed, 1); +} + +void tst_ExceptionSafety_Objects::cleanupTestCase() +{ + qInstallMsgHandler(testMessageHandler); +} + +void tst_ExceptionSafety_Objects::objects() +{ + QLatin1String tag = QLatin1String(QTest::currentDataTag()); + if (tag == QLatin1String("QFile") + || tag == QLatin1String("QProcess") + || tag == QLatin1String("QSettings") + || tag == QLatin1String("QThread") + || tag == QLatin1String("QThreadPool")) + QSKIP("This type of object is not currently strongly exception safe", SkipSingle); + + QFETCH(AbstractTester *, objectCreator); + + doOOMTest(*objectCreator, 0); + + delete objectCreator; +} + +template +struct WidgetCreator : public AbstractTester +{ + void operator()(QObject *parent) + { + if (parent && !parent->isWidgetType()) + qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO); + QScopedPointer ptr(parent ? new T(static_cast(parent)) : new T); + } +}; + +// QSizeGrip doesn't have a default constructor - always pass parent (even though it might be 0) +template <> struct WidgetCreator : public AbstractTester +{ + void operator()(QObject *parent) + { + if (parent && !parent->isWidgetType()) + qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO); + QScopedPointer ptr(new QSizeGrip(static_cast(parent))); + } +}; + +// QDesktopWidget doesn't need a parent. +template <> struct WidgetCreator : public AbstractTester +{ + void operator()(QObject *parent) + { + if (parent && !parent->isWidgetType()) + qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO); + QScopedPointer ptr(new QDesktopWidget()); + } +}; +void tst_ExceptionSafety_Objects::widgets_data() +{ + QTest::addColumn("widgetCreator"); + +#undef NEWROW +#define NEWROW(T) QTest::newRow(#T) << static_cast(new WidgetCreator) + + NEWROW(QWidget); + + NEWROW(QButtonGroup); + NEWROW(QCheckBox); + NEWROW(QColumnView); + NEWROW(QComboBox); + NEWROW(QCommandLinkButton); + NEWROW(QDateEdit); + NEWROW(QDateTimeEdit); + NEWROW(QDesktopWidget); + NEWROW(QDial); + NEWROW(QDoubleSpinBox); + NEWROW(QFocusFrame); + NEWROW(QFontComboBox); + NEWROW(QFrame); + NEWROW(QGroupBox); + NEWROW(QLabel); + NEWROW(QLCDNumber); + NEWROW(QLineEdit); + NEWROW(QListView); + NEWROW(QListWidget); + NEWROW(QMainWindow); + NEWROW(QMenu); + NEWROW(QMenuBar); + NEWROW(QPlainTextEdit); + NEWROW(QProgressBar); + NEWROW(QPushButton); + NEWROW(QRadioButton); + NEWROW(QScrollArea); + NEWROW(QScrollBar); + NEWROW(QSizeGrip); + NEWROW(QSlider); + NEWROW(QSpinBox); + NEWROW(QSplitter); + NEWROW(QStackedWidget); + NEWROW(QStatusBar); + NEWROW(QTabBar); + NEWROW(QTableView); + NEWROW(QTableWidget); + NEWROW(QTabWidget); + NEWROW(QTextBrowser); + NEWROW(QTextEdit); + NEWROW(QTimeEdit); + NEWROW(QToolBar); + NEWROW(QToolBox); + NEWROW(QToolButton); + NEWROW(QTreeView); + NEWROW(QTreeWidget); + NEWROW(QWorkspace); +} + +void tst_ExceptionSafety_Objects::widgets() +{ + QLatin1String tag = QLatin1String(QTest::currentDataTag()); + if (tag == QLatin1String("QColumnView") + || tag == QLatin1String("QComboBox") + || tag == QLatin1String("QCommandLinkButton") + || tag == QLatin1String("QDateEdit") + || tag == QLatin1String("QDateTimeEdit") + || tag == QLatin1String("QDesktopWidget") + || tag == QLatin1String("QDoubleSpinBox") + || tag == QLatin1String("QFontComboBox") + || tag == QLatin1String("QGroupBox") + || tag == QLatin1String("QLineEdit") + || tag == QLatin1String("QListView") + || tag == QLatin1String("QListWidget") + || tag == QLatin1String("QMainWindow") + || tag == QLatin1String("QMenu") + || tag == QLatin1String("QMenuBar") + || tag == QLatin1String("QPlainTextEdit") + || tag == QLatin1String("QProgressBar") + || tag == QLatin1String("QPushButton") + || tag == QLatin1String("QScrollArea") + || tag == QLatin1String("QSpinBox") + || tag == QLatin1String("QStackedWidget") + || tag == QLatin1String("QStatusBar") + || tag == QLatin1String("QTableView") + || tag == QLatin1String("QTableWidget") + || tag == QLatin1String("QTabWidget") + || tag == QLatin1String("QTextBrowser") + || tag == QLatin1String("QTextEdit") + || tag == QLatin1String("QTimeEdit") + || tag == QLatin1String("QToolBar") + || tag == QLatin1String("QToolBox") + || tag == QLatin1String("QTreeView") + || tag == QLatin1String("QTreeWidget") + || tag == QLatin1String("QWorkspace")) + QSKIP("This type of widget is not currently strongly exception safe", SkipSingle); + + QFETCH(AbstractTester *, widgetCreator); + + doOOMTest(*widgetCreator, 0, 00000); + + QWidget parent; + doOOMTest(*widgetCreator, &parent, 00000); + + delete widgetCreator; + + // if the test reaches here without crashing, we passed :) + QVERIFY(true); +} + +struct Integer +{ + Integer(int value = 42) + : ptr(new int(value)) + { + ++instanceCount; + } + + Integer(const Integer &other) + : ptr(new int(*other.ptr)) + { + ++instanceCount; + } + + Integer &operator=(const Integer &other) + { + int *newPtr = new int(*other.ptr); + delete ptr; + ptr = newPtr; + return *this; + } + + ~Integer() + { + --instanceCount; + delete ptr; + } + + int value() const + { + return *ptr; + } + + int *ptr; + static int instanceCount; +}; + +int Integer::instanceCount = 0; + +struct IntegerMoveable + { + IntegerMoveable(int value = 42) + : val(value) + { + delete new int; + ++instanceCount; + } + + IntegerMoveable(const IntegerMoveable &other) + : val(other.val) + { + delete new int; + ++instanceCount; + } + + IntegerMoveable &operator=(const IntegerMoveable &other) + { + delete new int; + val = other.val; + return *this; + } + + ~IntegerMoveable() + { + --instanceCount; + } + + int value() const + { + return val; + } + + int val; + static int instanceCount; + }; + +int IntegerMoveable::instanceCount = 0; +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(IntegerMoveable, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +template class Container> +void containerInsertTest(QObject*) +{ + Container container; + + // insert an item in an empty container + try { + container.insert(container.begin(), 41); + } catch (...) { + QVERIFY(container.isEmpty()); + QCOMPARE(T::instanceCount, 0); + return; + } + + QCOMPARE(container.size(), 1); + QCOMPARE(T::instanceCount, 1); + + // insert an item before another item + try { + container.insert(container.begin(), 42); + } catch (...) { + QCOMPARE(container.size(), 1); + QCOMPARE(container.first().value(), 41); + QCOMPARE(T::instanceCount, 1); + return; + } + + QCOMPARE(T::instanceCount, 2); + + // insert an item in between + try { + container.insert(container.begin() + 1, 43); + } catch (...) { + QCOMPARE(container.size(), 2); + QCOMPARE(container.first().value(), 41); + QCOMPARE((container.begin() + 1)->value(), 42); + QCOMPARE(T::instanceCount, 2); + return; + } + + QCOMPARE(T::instanceCount, 3); +} + +template class Container> +void containerAppendTest(QObject*) +{ + Container container; + + // append to an empty container + try { + container.append(42); + } catch (...) { + QCOMPARE(container.size(), 0); + QCOMPARE(T::instanceCount, 0); + return; + } + + // append to a container with one item + try { + container.append(43); + } catch (...) { + QCOMPARE(container.size(), 1); + QCOMPARE(container.first().value(), 42); + QCOMPARE(T::instanceCount, 1); + return; + } + + Container container2; + + try { + container2.append(44); + } catch (...) { + // don't care + return; + } + QCOMPARE(T::instanceCount, 3); + + // append another container with one item + try { + container += container2; + } catch (...) { + QCOMPARE(container.size(), 2); + QCOMPARE(container.first().value(), 42); + QCOMPARE((container.begin() + 1)->value(), 43); + QCOMPARE(T::instanceCount, 3); + return; + } + + QCOMPARE(T::instanceCount, 4); +} + +template class Container> +void containerEraseTest(QObject*) +{ + Container container; + + try { + container.append(42); + container.append(43); + container.append(44); + container.append(45); + container.append(46); + } catch (...) { + // don't care + return; + } + + // sanity checks + QCOMPARE(container.size(), 5); + QCOMPARE(T::instanceCount, 5); + + // delete the first one + try { + container.erase(container.begin()); + } catch (...) { + QCOMPARE(container.size(), 5); + QCOMPARE(container.first().value(), 42); + QCOMPARE(T::instanceCount, 5); + return; + } + + QCOMPARE(container.size(), 4); + QCOMPARE(container.first().value(), 43); + QCOMPARE(T::instanceCount, 4); + + // delete the last one + try { + container.erase(container.end() - 1); + } catch (...) { + QCOMPARE(container.size(), 4); + QCOMPARE(T::instanceCount, 4); + return; + } + + QCOMPARE(container.size(), 3); + QCOMPARE(container.first().value(), 43); + QCOMPARE((container.begin() + 1)->value(), 44); + QCOMPARE((container.begin() + 2)->value(), 45); + QCOMPARE(T::instanceCount, 3); + + // delete the middle one + try { + container.erase(container.begin() + 1); + } catch (...) { + QCOMPARE(container.size(), 3); + QCOMPARE(container.first().value(), 43); + QCOMPARE((container.begin() + 1)->value(), 44); + QCOMPARE((container.begin() + 2)->value(), 45); + QCOMPARE(T::instanceCount, 3); + return; + } + + QCOMPARE(container.size(), 2); + QCOMPARE(container.first().value(), 43); + QCOMPARE((container.begin() + 1)->value(), 45); + QCOMPARE(T::instanceCount, 2); +} + +template class Container> +static void containerData() +{ + QTest::addColumn("testFunction"); + + QTest::newRow("insert static") << static_cast(containerInsertTest); + QTest::newRow("append static") << static_cast(containerAppendTest); + QTest::newRow("erase static") << static_cast(containerEraseTest); + QTest::newRow("insert moveable") << static_cast(containerInsertTest); + QTest::newRow("append moveable") << static_cast(containerAppendTest); + QTest::newRow("erase moveable") << static_cast(containerEraseTest); +} + +void tst_ExceptionSafety_Objects::vector_data() +{ + containerData(); +} + +void tst_ExceptionSafety_Objects::vector() +{ + QFETCH(TestFunction, testFunction); + + if (QLatin1String(QTest::currentDataTag()) == QLatin1String("insert static") + || QLatin1String(QTest::currentDataTag()) == QLatin1String("insert moveable")) + QSKIP("QVector::insert is currently not strongly exception safe", SkipSingle); + + doOOMTest(testFunction, 0); +} + +void tst_ExceptionSafety_Objects::list_data() +{ + containerData(); +} + +void tst_ExceptionSafety_Objects::list() +{ + QFETCH(TestFunction, testFunction); + + doOOMTest(testFunction, 0); +} + +void tst_ExceptionSafety_Objects::linkedList_data() +{ + containerData(); +} + +void tst_ExceptionSafety_Objects::linkedList() +{ + QFETCH(TestFunction, testFunction); + + doOOMTest(testFunction, 0); +} + +#endif + +QTEST_MAIN(tst_ExceptionSafety_Objects) +#include "tst_exceptionsafety_objects.moc" diff --git a/tests/auto/integrationtests/gestures/gestures.pro b/tests/auto/integrationtests/gestures/gestures.pro new file mode 100644 index 0000000000..43ae4a3fa1 --- /dev/null +++ b/tests/auto/integrationtests/gestures/gestures.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_gestures.cpp + +CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/integrationtests/gestures/tst_gestures.cpp b/tests/auto/integrationtests/gestures/tst_gestures.cpp new file mode 100644 index 0000000000..63345fbe88 --- /dev/null +++ b/tests/auto/integrationtests/gestures/tst_gestures.cpp @@ -0,0 +1,2345 @@ +/**************************************************************************** +** +** 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//TESTED_CLASS= +//TESTED_FILES= + +static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view) +{ + return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt))); +} + +class CustomGesture : public QGesture +{ + Q_OBJECT +public: + static Qt::GestureType GestureType; + + CustomGesture(QObject *parent = 0) + : QGesture(parent), serial(0) + { + } + + int serial; + + static const int SerialMaybeThreshold; + static const int SerialStartedThreshold; + static const int SerialFinishedThreshold; +}; +Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture; +const int CustomGesture::SerialMaybeThreshold = 1; +const int CustomGesture::SerialStartedThreshold = 3; +const int CustomGesture::SerialFinishedThreshold = 6; + +class CustomEvent : public QEvent +{ +public: + static int EventType; + + CustomEvent(int serial_ = 0) + : QEvent(QEvent::Type(CustomEvent::EventType)), + serial(serial_), hasHotSpot(false) + { + } + + int serial; + QPointF hotSpot; + bool hasHotSpot; +}; +int CustomEvent::EventType = 0; + +class CustomGestureRecognizer : public QGestureRecognizer +{ +public: + static bool ConsumeEvents; + + CustomGestureRecognizer() + { + if (!CustomEvent::EventType) + CustomEvent::EventType = QEvent::registerEventType(); + } + + QGesture* create(QObject *) + { + return new CustomGesture; + } + + QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event) + { + if (event->type() == CustomEvent::EventType) { + QGestureRecognizer::Result result = 0; + if (CustomGestureRecognizer::ConsumeEvents) + result |= QGestureRecognizer::ConsumeEventHint; + CustomGesture *g = static_cast(state); + CustomEvent *e = static_cast(event); + g->serial = e->serial; + if (e->hasHotSpot) + g->setHotSpot(e->hotSpot); + if (g->serial >= CustomGesture::SerialFinishedThreshold) + result |= QGestureRecognizer::FinishGesture; + else if (g->serial >= CustomGesture::SerialStartedThreshold) + result |= QGestureRecognizer::TriggerGesture; + else if (g->serial >= CustomGesture::SerialMaybeThreshold) + result |= QGestureRecognizer::MayBeGesture; + else + result = QGestureRecognizer::CancelGesture; + return result; + } + return QGestureRecognizer::Ignore; + } + + void reset(QGesture *state) + { + CustomGesture *g = static_cast(state); + g->serial = 0; + QGestureRecognizer::reset(state); + } +}; +bool CustomGestureRecognizer::ConsumeEvents = false; + +// same as CustomGestureRecognizer but triggers early without the maybe state +class CustomContinuousGestureRecognizer : public QGestureRecognizer +{ +public: + CustomContinuousGestureRecognizer() + { + if (!CustomEvent::EventType) + CustomEvent::EventType = QEvent::registerEventType(); + } + + QGesture* create(QObject *) + { + return new CustomGesture; + } + + QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event) + { + if (event->type() == CustomEvent::EventType) { + QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint; + CustomGesture *g = static_cast(state); + CustomEvent *e = static_cast(event); + g->serial = e->serial; + if (e->hasHotSpot) + g->setHotSpot(e->hotSpot); + if (g->serial >= CustomGesture::SerialFinishedThreshold) + result |= QGestureRecognizer::FinishGesture; + else if (g->serial >= CustomGesture::SerialMaybeThreshold) + result |= QGestureRecognizer::TriggerGesture; + else + result = QGestureRecognizer::CancelGesture; + return result; + } + return QGestureRecognizer::Ignore; + } + + void reset(QGesture *state) + { + CustomGesture *g = static_cast(state); + g->serial = 0; + QGestureRecognizer::reset(state); + } +}; + +class GestureWidget : public QWidget +{ + Q_OBJECT +public: + GestureWidget(const char *name = 0, QWidget *parent = 0) + : QWidget(parent) + { + if (name) + setObjectName(QLatin1String(name)); + reset(); + acceptGestureOverride = false; + } + void reset() + { + customEventsReceived = 0; + gestureEventsReceived = 0; + gestureOverrideEventsReceived = 0; + events.clear(); + overrideEvents.clear(); + ignoredGestures.clear(); + } + + int customEventsReceived; + int gestureEventsReceived; + int gestureOverrideEventsReceived; + struct Events + { + QList all; + QList started; + QList updated; + QList finished; + QList canceled; + + void clear() + { + all.clear(); + started.clear(); + updated.clear(); + finished.clear(); + canceled.clear(); + } + } events, overrideEvents; + + bool acceptGestureOverride; + QSet ignoredGestures; + +protected: + bool event(QEvent *event) + { + Events *eventsPtr = 0; + if (event->type() == QEvent::Gesture) { + QGestureEvent *e = static_cast(event); + ++gestureEventsReceived; + eventsPtr = &events; + foreach(Qt::GestureType type, ignoredGestures) + e->ignore(e->gesture(type)); + } else if (event->type() == QEvent::GestureOverride) { + ++gestureOverrideEventsReceived; + eventsPtr = &overrideEvents; + if (acceptGestureOverride) + event->accept(); + } + if (eventsPtr) { + QGestureEvent *e = static_cast(event); + QList gestures = e->gestures(); + foreach(QGesture *g, gestures) { + eventsPtr->all << g->gestureType(); + switch(g->state()) { + case Qt::GestureStarted: + emit gestureStarted(e->type(), g); + eventsPtr->started << g->gestureType(); + break; + case Qt::GestureUpdated: + emit gestureUpdated(e->type(), g); + eventsPtr->updated << g->gestureType(); + break; + case Qt::GestureFinished: + emit gestureFinished(e->type(), g); + eventsPtr->finished << g->gestureType(); + break; + case Qt::GestureCanceled: + emit gestureCanceled(e->type(), g); + eventsPtr->canceled << g->gestureType(); + break; + default: + qWarning() << "Unknown GestureState enum value:" << static_cast(g->state()); + } + } + } else if (event->type() == CustomEvent::EventType) { + ++customEventsReceived; + } else { + return QWidget::event(event); + } + return true; + } + +Q_SIGNALS: + void gestureStarted(QEvent::Type, QGesture *); + void gestureUpdated(QEvent::Type, QGesture *); + void gestureFinished(QEvent::Type, QGesture *); + void gestureCanceled(QEvent::Type, QGesture *); + +public Q_SLOTS: + void deleteThis() { delete this; } +}; + +// TODO rename to sendGestureSequence +static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0) +{ + QWeakPointer receiver(object); + for (int i = CustomGesture::SerialMaybeThreshold; + i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) { + event->serial = i; + if (scene) + scene->sendEvent(qobject_cast(object), event); + else + QApplication::sendEvent(object, event); + } +} + +class tst_Gestures : public QObject +{ +Q_OBJECT + +public: + tst_Gestures(); + virtual ~tst_Gestures(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void customGesture(); + void autoCancelingGestures(); + void gestureOverChild(); + void multipleWidgetOnlyGestureInTree(); + void conflictingGestures(); + void conflictingGesturesInGraphicsView(); + void finishedWithoutStarted(); + void unknownGesture(); + void graphicsItemGesture(); + void graphicsView(); + void graphicsItemTreeGesture(); + void explicitGraphicsObjectTarget(); + void gestureOverChildGraphicsItem(); + void twoGesturesOnDifferentLevel(); + void multipleGesturesInTree(); + void multipleGesturesInComplexTree(); + void testMapToScene(); + void ungrabGesture(); + void consumeEventHint(); + void unregisterRecognizer(); + void autoCancelGestures(); + void autoCancelGestures2(); + void graphicsViewParentPropagation(); + void panelPropagation(); + void panelStacksBehindParent(); + void deleteGestureTargetWidget(); + void deleteGestureTargetItem_data(); + void deleteGestureTargetItem(); + void viewportCoordinates(); + void partialGesturePropagation(); + void testQGestureRecognizerCleanup(); + void testReuseCanceledGestures(); + void bug_13501_gesture_not_accepted(); +}; + +tst_Gestures::tst_Gestures() +{ +} + +tst_Gestures::~tst_Gestures() +{ +} + +void tst_Gestures::initTestCase() +{ + CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + QVERIFY(CustomGesture::GestureType != Qt::GestureType(0)); + QVERIFY(CustomGesture::GestureType != Qt::CustomGesture); +} + +void tst_Gestures::cleanupTestCase() +{ + QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType); +} + +void tst_Gestures::init() +{ +} + +void tst_Gestures::cleanup() +{ +} + +void tst_Gestures::customGesture() +{ + GestureWidget widget; + widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + CustomEvent event; + event.hotSpot = widget.mapToGlobal(QPoint(5,5)); + event.hasHotSpot = true; + sendCustomGesture(&event, &widget); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount); + QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(widget.gestureOverrideEventsReceived, 0); + QCOMPARE(widget.events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < widget.events.all.size(); ++i) + QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType); + QCOMPARE(widget.events.started.size(), 1); + QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2); + QCOMPARE(widget.events.finished.size(), 1); + QCOMPARE(widget.events.canceled.size(), 0); +} + +void tst_Gestures::consumeEventHint() +{ + GestureWidget widget; + widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + CustomGestureRecognizer::ConsumeEvents = true; + CustomEvent event; + sendCustomGesture(&event, &widget); + CustomGestureRecognizer::ConsumeEvents = false; + + QCOMPARE(widget.customEventsReceived, 0); +} + +void tst_Gestures::autoCancelingGestures() +{ + GestureWidget widget; + widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + // send partial gesture. The gesture will be in the "maybe" state, but will + // never get enough events to fire, so Qt will have to kill it. + CustomEvent ev; + for (int i = CustomGesture::SerialMaybeThreshold; + i < CustomGesture::SerialStartedThreshold; ++i) { + ev.serial = i; + QApplication::sendEvent(&widget, &ev); + } + // wait long enough so the gesture manager will cancel the gesture + QTest::qWait(5000); + QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold); + QCOMPARE(widget.gestureEventsReceived, 0); + QCOMPARE(widget.gestureOverrideEventsReceived, 0); + QCOMPARE(widget.events.all.size(), 0); +} + +void tst_Gestures::gestureOverChild() +{ + GestureWidget widget("widget"); + QVBoxLayout *l = new QVBoxLayout(&widget); + GestureWidget *child = new GestureWidget("child"); + l->addWidget(child); + + widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + CustomEvent event; + sendCustomGesture(&event, child); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(widget.customEventsReceived, 0); + QCOMPARE(child->gestureEventsReceived, 0); + QCOMPARE(child->gestureOverrideEventsReceived, 0); + QCOMPARE(widget.gestureEventsReceived, 0); + QCOMPARE(widget.gestureOverrideEventsReceived, 0); + + // enable gestures over the children + widget.grabGesture(CustomGesture::GestureType); + + widget.reset(); + child->reset(); + + sendCustomGesture(&event, child); + + QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(widget.customEventsReceived, 0); + + QCOMPARE(child->gestureEventsReceived, 0); + QCOMPARE(child->gestureOverrideEventsReceived, 0); + QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(widget.gestureOverrideEventsReceived, 0); + for(int i = 0; i < widget.events.all.size(); ++i) + QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType); + QCOMPARE(widget.events.started.size(), 1); + QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2); + QCOMPARE(widget.events.finished.size(), 1); + QCOMPARE(widget.events.canceled.size(), 0); +} + +void tst_Gestures::multipleWidgetOnlyGestureInTree() +{ + GestureWidget parent("parent"); + QVBoxLayout *l = new QVBoxLayout(&parent); + GestureWidget *child = new GestureWidget("child"); + l->addWidget(child); + + parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + // sending events to the child and making sure there is no conflict + CustomEvent event; + sendCustomGesture(&event, child); + + QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(parent.customEventsReceived, 0); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(child->gestureOverrideEventsReceived, 0); + QCOMPARE(parent.gestureEventsReceived, 0); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); + + parent.reset(); + child->reset(); + + // same for the parent widget + sendCustomGesture(&event, &parent); + + QCOMPARE(child->customEventsReceived, 0); + QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount); + QCOMPARE(child->gestureEventsReceived, 0); + QCOMPARE(child->gestureOverrideEventsReceived, 0); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::conflictingGestures() +{ + GestureWidget parent("parent"); + QVBoxLayout *l = new QVBoxLayout(&parent); + GestureWidget *child = new GestureWidget("child"); + l->addWidget(child); + + parent.grabGesture(CustomGesture::GestureType); + child->grabGesture(CustomGesture::GestureType); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + // child accepts the override, parent will not receive anything + parent.acceptGestureOverride = false; + child->acceptGestureOverride = true; + + // sending events to the child and making sure there is no conflict + CustomEvent event; + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); + QCOMPARE(parent.gestureEventsReceived, 0); + + parent.reset(); + child->reset(); + + // parent accepts the override + parent.acceptGestureOverride = true; + child->acceptGestureOverride = false; + + // sending events to the child and making sure there is no conflict + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, 0); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + + parent.reset(); + child->reset(); + + // nobody accepts the override, we will send normal events to the closest + // context (i.e. to the child widget) and it will be propagated and + // accepted by the parent widget + parent.acceptGestureOverride = false; + child->acceptGestureOverride = false; + child->ignoredGestures << CustomGesture::GestureType; + + // sending events to the child and making sure there is no conflict + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, 1); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + + parent.reset(); + child->reset(); + + // nobody accepts the override, and nobody accepts the gesture event + parent.acceptGestureOverride = false; + child->acceptGestureOverride = false; + parent.ignoredGestures << CustomGesture::GestureType; + child->ignoredGestures << CustomGesture::GestureType; + + // sending events to the child and making sure there is no conflict + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, 1); + + parent.reset(); + child->reset(); + + // we set an attribute to make sure all gesture events are propagated + parent.grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); + parent.acceptGestureOverride = false; + child->acceptGestureOverride = false; + parent.ignoredGestures << CustomGesture::GestureType; + child->ignoredGestures << CustomGesture::GestureType; + + // sending events to the child and making sure there is no conflict + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + + parent.reset(); + child->reset(); + + Qt::GestureType ContinuousGesture = QGestureRecognizer::registerRecognizer(new CustomContinuousGestureRecognizer); + static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + child->grabGesture(ContinuousGesture); + // child accepts override. And it also receives another custom gesture. + parent.acceptGestureOverride = false; + child->acceptGestureOverride = true; + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount); + QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); + QCOMPARE(parent.gestureEventsReceived, 0); + + QGestureRecognizer::unregisterRecognizer(ContinuousGesture); +} + +void tst_Gestures::finishedWithoutStarted() +{ + GestureWidget widget; + widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + // the gesture will claim it finished, but it was never started. + CustomEvent ev; + ev.serial = CustomGesture::SerialFinishedThreshold; + QApplication::sendEvent(&widget, &ev); + + QCOMPARE(widget.customEventsReceived, 1); + QCOMPARE(widget.gestureEventsReceived, 2); + QCOMPARE(widget.gestureOverrideEventsReceived, 0); + QCOMPARE(widget.events.all.size(), 2); + QCOMPARE(widget.events.started.size(), 1); + QCOMPARE(widget.events.updated.size(), 0); + QCOMPARE(widget.events.finished.size(), 1); + QCOMPARE(widget.events.canceled.size(), 0); +} + +void tst_Gestures::unknownGesture() +{ + GestureWidget widget; + widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + widget.grabGesture(Qt::CustomGesture, Qt::DontStartGestureOnChildren); + widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::DontStartGestureOnChildren); + + CustomEvent event; + sendCustomGesture(&event, &widget); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount); +} + +static const QColor InstanceColors[] = { + Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow +}; + +class GestureItem : public QGraphicsObject +{ + Q_OBJECT + static int InstanceCount; +public: + GestureItem(const char *name = 0) + { + instanceNumber = InstanceCount++; + if (name) { + setObjectName(QLatin1String(name)); + setToolTip(name); + } + size = QRectF(0, 0, 100, 100); + customEventsReceived = 0; + gestureEventsReceived = 0; + gestureOverrideEventsReceived = 0; + events.clear(); + overrideEvents.clear(); + acceptGestureOverride = false; + + scene = 0; + } + ~GestureItem() + { + --InstanceCount; + } + + int customEventsReceived; + int gestureEventsReceived; + int gestureOverrideEventsReceived; + struct Events + { + QList all; + QList started; + QList updated; + QList finished; + QList canceled; + + void clear() + { + all.clear(); + started.clear(); + updated.clear(); + finished.clear(); + canceled.clear(); + } + } events, overrideEvents; + + bool acceptGestureOverride; + QSet ignoredGestures; + QSet ignoredStartedGestures; + QSet ignoredUpdatedGestures; + QSet ignoredFinishedGestures; + + QRectF size; + int instanceNumber; + + void reset() + { + customEventsReceived = 0; + gestureEventsReceived = 0; + gestureOverrideEventsReceived = 0; + events.clear(); + overrideEvents.clear(); + ignoredGestures.clear(); + ignoredStartedGestures.clear(); + ignoredUpdatedGestures.clear(); + ignoredFinishedGestures.clear(); + } + + QRectF boundingRect() const + { + return size; + } + void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) + { + QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))]; + p->fillRect(boundingRect(), color); + } + + bool event(QEvent *event) + { + Events *eventsPtr = 0; + if (event->type() == QEvent::Gesture) { + ++gestureEventsReceived; + eventsPtr = &events; + QGestureEvent *e = static_cast(event); + foreach(Qt::GestureType type, ignoredGestures) + e->ignore(e->gesture(type)); + foreach(QGesture *g, e->gestures()) { + switch (g->state()) { + case Qt::GestureStarted: + if (ignoredStartedGestures.contains(g->gestureType())) + e->ignore(g); + break; + case Qt::GestureUpdated: + if (ignoredUpdatedGestures.contains(g->gestureType())) + e->ignore(g); + break; + case Qt::GestureFinished: + if (ignoredFinishedGestures.contains(g->gestureType())) + e->ignore(g); + break; + default: + break; + } + } + } else if (event->type() == QEvent::GestureOverride) { + ++gestureOverrideEventsReceived; + eventsPtr = &overrideEvents; + if (acceptGestureOverride) + event->accept(); + } + if (eventsPtr) { + QGestureEvent *e = static_cast(event); + QList gestures = e->gestures(); + foreach(QGesture *g, gestures) { + eventsPtr->all << g->gestureType(); + switch(g->state()) { + case Qt::GestureStarted: + eventsPtr->started << g->gestureType(); + emit gestureStarted(e->type(), g); + break; + case Qt::GestureUpdated: + eventsPtr->updated << g->gestureType(); + emit gestureUpdated(e->type(), g); + break; + case Qt::GestureFinished: + eventsPtr->finished << g->gestureType(); + emit gestureFinished(e->type(), g); + break; + case Qt::GestureCanceled: + eventsPtr->canceled << g->gestureType(); + emit gestureCanceled(e->type(), g); + break; + default: + qWarning() << "Unknown GestureState enum value:" << static_cast(g->state()); + } + } + } else if (event->type() == CustomEvent::EventType) { + ++customEventsReceived; + } else { + return QGraphicsObject::event(event); + } + return true; + } + +Q_SIGNALS: + void gestureStarted(QEvent::Type, QGesture *); + void gestureUpdated(QEvent::Type, QGesture *); + void gestureFinished(QEvent::Type, QGesture *); + void gestureCanceled(QEvent::Type, QGesture *); + +public: + // some arguments for the slots below: + QGraphicsScene *scene; + +public Q_SLOTS: + void deleteThis() { delete this; } + void addSelfToScene(QEvent::Type eventType, QGesture *) + { + if (eventType == QEvent::Gesture) { + disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*))); + scene->addItem(this); + } + } +}; +int GestureItem::InstanceCount = 0; + +void tst_Gestures::graphicsItemGesture() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item = new GestureItem("item"); + scene.addItem(item); + item->setPos(100, 100); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item->grabGesture(CustomGesture::GestureType); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + CustomEvent event; + // gesture without hotspot should not be delivered to items in the view + QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); + QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); + QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); + QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture"); + sendCustomGesture(&event, item, &scene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, 0); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + item->reset(); + + // make sure the event is properly delivered if only the hotspot is set. + event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item, &scene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + QCOMPARE(item->events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < item->events.all.size(); ++i) + QCOMPARE(item->events.all.at(i), CustomGesture::GestureType); + QCOMPARE(item->events.started.size(), 1); + QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2); + QCOMPARE(item->events.finished.size(), 1); + QCOMPARE(item->events.canceled.size(), 0); + + item->reset(); + + // send gesture to the item which ignores it. + item->ignoredGestures << CustomGesture::GestureType; + + event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item, &scene); + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::graphicsView() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item = new GestureItem("item"); + scene.addItem(item); + item->setPos(100, 100); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item->grabGesture(CustomGesture::GestureType); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + CustomEvent event; + // make sure the event is properly delivered if only the hotspot is set. + event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item, &scene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + // change the viewport and try again + QWidget *newViewport = new QWidget; + view.setViewport(newViewport); + + item->reset(); + sendCustomGesture(&event, item, &scene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + // change the scene and try again + QGraphicsScene newScene; + item = new GestureItem("newItem"); + newScene.addItem(item); + item->setPos(100, 100); + view.setScene(&newScene); + + item->reset(); + // first without a gesture + sendCustomGesture(&event, item, &newScene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, 0); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + // then grab the gesture and try again + item->reset(); + item->grabGesture(CustomGesture::GestureType); + sendCustomGesture(&event, item, &newScene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::graphicsItemTreeGesture() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->setPos(100, 100); + item1->size = QRectF(0, 0, 350, 200); + scene.addItem(item1); + + GestureItem *item1_child1 = new GestureItem("item1_child1"); + item1_child1->setPos(50, 50); + item1_child1->size = QRectF(0, 0, 100, 100); + item1_child1->setParentItem(item1); + + GestureItem *item1_child2 = new GestureItem("item1_child2"); + item1_child2->size = QRectF(0, 0, 100, 100); + item1_child2->setPos(200, 50); + item1_child2->setParentItem(item1); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item1->grabGesture(CustomGesture::GestureType); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view); + event.hasHotSpot = true; + + item1->ignoredGestures << CustomGesture::GestureType; + sendCustomGesture(&event, item1_child1, &scene); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child2->gestureEventsReceived, 0); + QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + + item1->reset(); item1_child1->reset(); item1_child2->reset(); + + item1_child1->grabGesture(CustomGesture::GestureType); + + item1->ignoredGestures << CustomGesture::GestureType; + item1_child1->ignoredGestures << CustomGesture::GestureType; + sendCustomGesture(&event, item1_child1, &scene); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child2->gestureEventsReceived, 0); + QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 1); +} + +void tst_Gestures::explicitGraphicsObjectTarget() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + scene.addItem(item1); + item1->setPos(100, 100); + item1->setZValue(1); + + GestureItem *item2 = new GestureItem("item2"); + scene.addItem(item2); + item2->setPos(100, 100); + item2->setZValue(5); + + GestureItem *item2_child1 = new GestureItem("item2_child1"); + scene.addItem(item2_child1); + item2_child1->setParentItem(item2); + item2_child1->setPos(10, 10); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + // sending events to item1, but the hotSpot is set to item2 + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view); + event.hasHotSpot = true; + + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item2_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item2_child1->events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < item2_child1->events.all.size(); ++i) + QCOMPARE(item2_child1->events.all.at(i), CustomGesture::GestureType); + QCOMPARE(item2_child1->events.started.size(), 1); + QCOMPARE(item2_child1->events.updated.size(), TotalGestureEventsCount - 2); + QCOMPARE(item2_child1->events.finished.size(), 1); + QCOMPARE(item2_child1->events.canceled.size(), 0); + QCOMPARE(item2->gestureEventsReceived, 0); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); +} + +void tst_Gestures::gestureOverChildGraphicsItem() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item0 = new GestureItem("item0"); + scene.addItem(item0); + item0->setPos(0, 0); + item0->grabGesture(CustomGesture::GestureType); + item0->setZValue(1); + + GestureItem *item1 = new GestureItem("item1"); + scene.addItem(item1); + item1->setPos(100, 100); + item1->setZValue(5); + + GestureItem *item2 = new GestureItem("item2"); + scene.addItem(item2); + item2->setPos(100, 100); + item2->setZValue(10); + + GestureItem *item2_child1 = new GestureItem("item2_child1"); + scene.addItem(item2_child1); + item2_child1->setParentItem(item2); + item2_child1->setPos(0, 0); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item1->grabGesture(CustomGesture::GestureType); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item2_child1->gestureEventsReceived, 0); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item2->gestureEventsReceived, 0); + QCOMPARE(item2->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); + item2->grabGesture(CustomGesture::GestureType); + item2->ignoredGestures << CustomGesture::GestureType; + + event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item2_child1->gestureEventsReceived, 0); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item2->gestureEventsReceived, 1); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); + item2->grabGesture(CustomGesture::GestureType); + item2->ignoredGestures << CustomGesture::GestureType; + item1->ignoredGestures << CustomGesture::GestureType; + + event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item2_child1->gestureEventsReceived, 0); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 1); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); + item2->grabGesture(CustomGesture::GestureType); + item2->ignoredGestures << CustomGesture::GestureType; + item1->ignoredGestures << CustomGesture::GestureType; + item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); + + event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item2_child1->gestureEventsReceived, 0); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); +} + +void tst_Gestures::twoGesturesOnDifferentLevel() +{ + GestureWidget parent("parent"); + QVBoxLayout *l = new QVBoxLayout(&parent); + GestureWidget *child = new GestureWidget("child"); + l->addWidget(child); + + Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + + parent.grabGesture(CustomGesture::GestureType); + child->grabGesture(SecondGesture); + + CustomEvent event; + // sending events that form a gesture to one widget, but they will be + // filtered by two different gesture recognizers and will generate two + // QGesture objects. Check that those gesture objects are delivered to + // different widgets properly. + sendCustomGesture(&event, child); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(child->gestureOverrideEventsReceived, 0); + QCOMPARE(child->events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < child->events.all.size(); ++i) + QCOMPARE(child->events.all.at(i), SecondGesture); + + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); + QCOMPARE(parent.events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < child->events.all.size(); ++i) + QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType); + + QGestureRecognizer::unregisterRecognizer(SecondGesture); +} + +void tst_Gestures::multipleGesturesInTree() +{ + GestureWidget a("A"); + GestureWidget *A = &a; + GestureWidget *B = new GestureWidget("B", A); + GestureWidget *C = new GestureWidget("C", B); + GestureWidget *D = new GestureWidget("D", C); + + Qt::GestureType FirstGesture = CustomGesture::GestureType; + Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + + Qt::GestureFlags flags = Qt::ReceivePartialGestures; + A->grabGesture(FirstGesture, flags); // A [1 3] + A->grabGesture(ThirdGesture, flags); // | + B->grabGesture(SecondGesture, flags); // B [ 2 3] + B->grabGesture(ThirdGesture, flags); // | + C->grabGesture(FirstGesture, flags); // C [1 2 3] + C->grabGesture(SecondGesture, flags); // | + C->grabGesture(ThirdGesture, flags); // D [1 3] + D->grabGesture(FirstGesture, flags); + D->grabGesture(ThirdGesture, flags); + + // make sure all widgets ignore events, so they get propagated. + A->ignoredGestures << FirstGesture << ThirdGesture; + B->ignoredGestures << SecondGesture << ThirdGesture; + C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture; + D->ignoredGestures << FirstGesture << ThirdGesture; + + CustomEvent event; + sendCustomGesture(&event, D); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + // gesture override events + QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0); + QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1); + + // normal gesture events + QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(D->events.all.count(SecondGesture), 0); + QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QCOMPARE(B->events.all.count(FirstGesture), 0); + QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(SecondGesture), 0); + QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QGestureRecognizer::unregisterRecognizer(SecondGesture); + QGestureRecognizer::unregisterRecognizer(ThirdGesture); +} + +void tst_Gestures::multipleGesturesInComplexTree() +{ + GestureWidget a("A"); + GestureWidget *A = &a; + GestureWidget *B = new GestureWidget("B", A); + GestureWidget *C = new GestureWidget("C", B); + GestureWidget *D = new GestureWidget("D", C); + + Qt::GestureType FirstGesture = CustomGesture::GestureType; + Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + Qt::GestureType FourthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + Qt::GestureType FifthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + Qt::GestureType SixthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + Qt::GestureType SeventhGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + + Qt::GestureFlags flags = Qt::ReceivePartialGestures; + A->grabGesture(FirstGesture, flags); // A [1,3,4] + A->grabGesture(ThirdGesture, flags); // | + A->grabGesture(FourthGesture, flags); // B [2,3,5] + B->grabGesture(SecondGesture, flags); // | + B->grabGesture(ThirdGesture, flags); // C [1,2,3,6] + B->grabGesture(FifthGesture, flags); // | + C->grabGesture(FirstGesture, flags); // D [1,3,7] + C->grabGesture(SecondGesture, flags); + C->grabGesture(ThirdGesture, flags); + C->grabGesture(SixthGesture, flags); + D->grabGesture(FirstGesture, flags); + D->grabGesture(ThirdGesture, flags); + D->grabGesture(SeventhGesture, flags); + + // make sure all widgets ignore events, so they get propagated. + QSet allGestureTypes; + allGestureTypes << FirstGesture << SecondGesture << ThirdGesture + << FourthGesture << FifthGesture << SixthGesture << SeventhGesture; + A->ignoredGestures = B->ignoredGestures = allGestureTypes; + C->ignoredGestures = D->ignoredGestures = allGestureTypes; + + CustomEvent event; + sendCustomGesture(&event, D); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + // gesture override events + QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0); + QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1); + + // normal gesture events + QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(D->events.all.count(SecondGesture), 0); + QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(D->events.all.count(FourthGesture), 0); + QCOMPARE(D->events.all.count(FifthGesture), 0); + QCOMPARE(D->events.all.count(SixthGesture), 0); + QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount); + + QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(FourthGesture), 0); + QCOMPARE(C->events.all.count(FifthGesture), 0); + QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(SeventhGesture), 0); + + QCOMPARE(B->events.all.count(FirstGesture), 0); + QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(FourthGesture), 0); + QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(SixthGesture), 0); + QCOMPARE(B->events.all.count(SeventhGesture), 0); + + QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(SecondGesture), 0); + QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(FifthGesture), 0); + QCOMPARE(A->events.all.count(SixthGesture), 0); + QCOMPARE(A->events.all.count(SeventhGesture), 0); + + QGestureRecognizer::unregisterRecognizer(SecondGesture); + QGestureRecognizer::unregisterRecognizer(ThirdGesture); + QGestureRecognizer::unregisterRecognizer(FourthGesture); + QGestureRecognizer::unregisterRecognizer(FifthGesture); + QGestureRecognizer::unregisterRecognizer(SixthGesture); + QGestureRecognizer::unregisterRecognizer(SeventhGesture); +} + +void tst_Gestures::testMapToScene() +{ + QGesture gesture; + QList list; + list << &gesture; + QGestureEvent event(list); + QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much + + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item0 = new GestureItem; + scene.addItem(item0); + item0->setPos(14, 16); + + view.show(); // need to show to give it a global coordinate + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + QPoint origin = view.mapToGlobal(QPoint()); + event.setWidget(view.viewport()); + + QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200))); +} + +void tst_Gestures::ungrabGesture() // a method on QWidget +{ + class MockGestureWidget : public GestureWidget { + public: + MockGestureWidget(const char *name = 0, QWidget *parent = 0) + : GestureWidget(name, parent) { } + + + QSet gestures; + protected: + bool event(QEvent *event) + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *gestureEvent = static_cast(event); + if (gestureEvent) + foreach (QGesture *g, gestureEvent->gestures()) + gestures.insert(g); + } + return GestureWidget::event(event); + } + }; + + MockGestureWidget parent("A"); + MockGestureWidget *a = &parent; + MockGestureWidget *b = new MockGestureWidget("B", a); + + a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + b->grabGesture(CustomGesture::GestureType); + b->ignoredGestures << CustomGesture::GestureType; + + CustomEvent event; + // sending an event will cause the QGesture objects to be instantiated for the widgets + sendCustomGesture(&event, b); + + QCOMPARE(a->gestures.count(), 1); + QPointer customGestureA; + customGestureA = *(a->gestures.begin()); + QVERIFY(!customGestureA.isNull()); + QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType); + + QCOMPARE(b->gestures.count(), 1); + QPointer customGestureB; + customGestureB = *(b->gestures.begin()); + QVERIFY(!customGestureB.isNull()); + QVERIFY(customGestureA.data() == customGestureB.data()); + QCOMPARE(customGestureB->gestureType(), CustomGesture::GestureType); + + a->gestures.clear(); + // sending an event will cause the QGesture objects to be instantiated for the widget + sendCustomGesture(&event, a); + + QCOMPARE(a->gestures.count(), 1); + customGestureA = *(a->gestures.begin()); + QVERIFY(!customGestureA.isNull()); + QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType); + QVERIFY(customGestureA.data() != customGestureB.data()); + + a->ungrabGesture(CustomGesture::GestureType); + //We changed the deletion of Gestures to lazy during QT-4022, so we can't ensure the QGesture is deleted until now + QVERIFY(!customGestureB.isNull()); + + a->gestures.clear(); + a->reset(); + // send again to 'b' and make sure a never gets it. + sendCustomGesture(&event, b); + //After all Gestures are processed in the QGestureManager, we can ensure the QGesture is now deleted + QVERIFY(customGestureA.isNull()); + QCOMPARE(a->gestureEventsReceived, 0); + QCOMPARE(a->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::unregisterRecognizer() // a method on QApplication +{ + /* + The hardest usecase to get right is when we remove a recognizer while several + of the gestures it created are in active state and we immediately add a new recognizer + for the same type (thus replacing the old one). + The expected result is that all old gestures continue till they are finished/cancelled + and the new recognizer starts creating gestures immediately at registration. + + This implies that deleting of the recognizer happens only when there are no more gestures + that it created. (since gestures might have a pointer to the recognizer) + */ + +} + +void tst_Gestures::autoCancelGestures() +{ + class MockWidget : public GestureWidget { + public: + MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { } + + bool event(QEvent *event) + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *ge = static_cast(event); + if (ge->gestures().count() != 1) + ++badGestureEvents; // event should contain exactly one gesture + ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext); + } + return GestureWidget::event(event); + } + + int badGestureEvents; + }; + + const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); + + MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext + parent.resize(300, 100); + parent.setWindowFlags(Qt::X11BypassWindowManagerHint); + GestureWidget *child = new GestureWidget("child", &parent); + child->setGeometry(10, 10, 100, 80); + + parent.grabGesture(CustomGesture::GestureType); + child->grabGesture(secondGesture); + parent.show(); + QTest::qWaitForWindowShown(&parent); + + /* + An event is send to both the child and the parent, when the child gets it a gesture is triggered + and send to the child. + When the parent gets the event a new gesture is triggered and delivered to the parent. When the + parent gets it he accepts it and that causes the cancel policy to activate. + The cause of that is the gesture for the child is cancelled and send to the child as such. + */ + CustomEvent event; + event.serial = CustomGesture::SerialStartedThreshold; + QApplication::sendEvent(child, &event); + QCOMPARE(child->events.all.count(), 2); + QCOMPARE(child->events.started.count(), 1); + QCOMPARE(child->events.canceled.count(), 1); + QCOMPARE(parent.events.all.count(), 1); + + // clean up, make the parent gesture finish + event.serial = CustomGesture::SerialFinishedThreshold; + QApplication::sendEvent(child, &event); + QCOMPARE(parent.events.all.count(), 2); + QCOMPARE(parent.badGestureEvents, 0); +} + +void tst_Gestures::autoCancelGestures2() +{ + class MockItem : public GestureItem { + public: + MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { } + + bool event(QEvent *event) { + if (event->type() == QEvent::Gesture) { + QGestureEvent *ge = static_cast(event); + if (ge->gestures().count() != 1) + ++badGestureEvents; // event should contain exactly one gesture + ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext); + } + return GestureItem::event(event); + } + + int badGestureEvents; + }; + + const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer); + + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + MockItem *parent = new MockItem("parent"); + GestureItem *child = new GestureItem("child"); + child->setParentItem(parent); + parent->setPos(0, 0); + child->setPos(10, 10); + scene.addItem(parent); + parent->grabGesture(CustomGesture::GestureType); + child->grabGesture(secondGesture); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + CustomEvent event; + event.serial = CustomGesture::SerialStartedThreshold; + event.hasHotSpot = true; + event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view); + scene.sendEvent(child, &event); + QCOMPARE(parent->events.all.count(), 1); + QCOMPARE(child->events.started.count(), 1); + QCOMPARE(child->events.canceled.count(), 1); + QCOMPARE(child->events.all.count(), 2); + + // clean up, make the parent gesture finish + event.serial = CustomGesture::SerialFinishedThreshold; + scene.sendEvent(child, &event); + QCOMPARE(parent->events.all.count(), 2); + QCOMPARE(parent->badGestureEvents, 0); +} + +void tst_Gestures::graphicsViewParentPropagation() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item0 = new GestureItem("item0"); + scene.addItem(item0); + item0->setPos(0, 0); + item0->grabGesture(CustomGesture::GestureType); + item0->setZValue(1); + + GestureItem *item1 = new GestureItem("item1"); + scene.addItem(item1); + item1->setPos(0, 0); + item1->setZValue(5); + + GestureItem *item1_c1 = new GestureItem("item1_child1"); + item1_c1->setParentItem(item1); + item1_c1->setPos(0, 0); + + GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1"); + item1_c1_c1->setParentItem(item1_c1); + item1_c1_c1->setPos(0, 0); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); + item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); + item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent); + item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); + + item0->ignoredUpdatedGestures << CustomGesture::GestureType; + item0->ignoredFinishedGestures << CustomGesture::GestureType; + item1->ignoredUpdatedGestures << CustomGesture::GestureType; + item1->ignoredFinishedGestures << CustomGesture::GestureType; + item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType; + item1_c1->ignoredFinishedGestures << CustomGesture::GestureType; + item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType; + item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType; + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1); + QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 1); +} + +void tst_Gestures::panelPropagation() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item0 = new GestureItem("item0"); + scene.addItem(item0); + item0->setPos(0, 0); + item0->size = QRectF(0, 0, 200, 200); + item0->grabGesture(CustomGesture::GestureType); + item0->setZValue(1); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + scene.addItem(item1); + item1->setPos(10, 10); + item1->size = QRectF(0, 0, 180, 180); + item1->setZValue(2); + + GestureItem *item1_child1 = new GestureItem("item1_child1[panel]"); + item1_child1->setFlags(QGraphicsItem::ItemIsPanel); + item1_child1->setParentItem(item1); + item1_child1->grabGesture(CustomGesture::GestureType); + item1_child1->setPos(10, 10); + item1_child1->size = QRectF(0, 0, 160, 160); + item1_child1->setZValue(5); + + GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1"); + item1_child1_child1->setParentItem(item1_child1); + item1_child1_child1->grabGesture(CustomGesture::GestureType); + item1_child1_child1->setPos(10, 10); + item1_child1_child1->size = QRectF(0, 0, 140, 140); + item1_child1_child1->setZValue(10); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a modal panel + item1_child1->setPanelModality(QGraphicsItem::PanelModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a modal panel, however set the hotspot to be outside of the + // panel and its parent + item1_child1->setPanelModality(QGraphicsItem::PanelModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a scene modal panel + item1_child1->setPanelModality(QGraphicsItem::SceneModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::panelStacksBehindParent() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + scene.addItem(item1); + item1->setPos(10, 10); + item1->size = QRectF(0, 0, 180, 180); + item1->setZValue(2); + + GestureItem *panel = new GestureItem("panel"); + panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent); + panel->setPanelModality(QGraphicsItem::PanelModal); + panel->setParentItem(item1); + panel->grabGesture(CustomGesture::GestureType); + panel->setPos(-10, -10); + panel->size = QRectF(0, 0, 200, 200); + panel->setZValue(5); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(panel->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::deleteGestureTargetWidget() +{ +} + +void tst_Gestures::deleteGestureTargetItem_data() +{ + QTest::addColumn("propagateUpdateGesture"); + QTest::addColumn("emitter"); + QTest::addColumn("receiver"); + QTest::addColumn("signalName"); + QTest::addColumn("slotName"); + + QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*)); + QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*)); + QByteArray deleteThis = SLOT(deleteThis()); + QByteArray deleteLater = SLOT(deleteLater()); + + QTest::newRow("delete1") + << false << "item1" << "item1" << gestureUpdated << deleteThis; + QTest::newRow("delete2") + << false << "item2" << "item2" << gestureUpdated << deleteThis; + QTest::newRow("delete3") + << false << "item1" << "item2" << gestureUpdated << deleteThis; + + QTest::newRow("deleteLater1") + << false << "item1" << "item1" << gestureUpdated << deleteLater; + QTest::newRow("deleteLater2") + << false << "item2" << "item2" << gestureUpdated << deleteLater; + QTest::newRow("deleteLater3") + << false << "item1" << "item2" << gestureUpdated << deleteLater; + QTest::newRow("deleteLater4") + << false << "item2" << "item1" << gestureUpdated << deleteLater; + + QTest::newRow("delete-self-and-propagate") + << true << "item2" << "item2" << gestureUpdated << deleteThis; + QTest::newRow("deleteLater-self-and-propagate") + << true << "item2" << "item2" << gestureUpdated << deleteLater; + QTest::newRow("propagate-to-deletedLater") + << true << "item2" << "item1" << gestureUpdated << deleteLater; +} + +void tst_Gestures::deleteGestureTargetItem() +{ + QFETCH(bool, propagateUpdateGesture); + QFETCH(QString, emitter); + QFETCH(QString, receiver); + QFETCH(QByteArray, signalName); + QFETCH(QByteArray, slotName); + + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + item1->setZValue(2); + scene.addItem(item1); + + GestureItem *item2 = new GestureItem("item2"); + item2->grabGesture(CustomGesture::GestureType); + item2->setZValue(5); + scene.addItem(item2); + + QMap items; + items.insert(item1->objectName(), item1); + items.insert(item2->objectName(), item2); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + if (propagateUpdateGesture) + item2->ignoredUpdatedGestures << CustomGesture::GestureType; + connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName); + + // some debug output to see the current test data tag, so if we crash + // we know which one caused the crash. + qDebug() << "<-- testing"; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); +} + +class GraphicsView : public QGraphicsView +{ +public: + GraphicsView(QGraphicsScene *scene, QWidget *parent = 0) + : QGraphicsView(scene, parent) + { + } + + using QGraphicsView::setViewportMargins; +}; + +// just making sure that even if the graphicsview has margins hotspot still +// works properly. It should use viewport for converting global coordinates to +// scene coordinates. +void tst_Gestures::viewportCoordinates() +{ + QGraphicsScene scene; + GraphicsView view(&scene); + view.setViewportMargins(10,20,15,25); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + item1->size = QRectF(0, 0, 3, 3); + item1->setZValue(2); + scene.addItem(item1); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + CustomEvent event; + event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + QVERIFY(item1->gestureEventsReceived != 0); +} + +void tst_Gestures::partialGesturePropagation() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + item1->setZValue(8); + scene.addItem(item1); + + GestureItem *item2 = new GestureItem("item2[partial]"); + item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); + item2->setZValue(6); + scene.addItem(item2); + + GestureItem *item3 = new GestureItem("item3"); + item3->grabGesture(CustomGesture::GestureType); + item3->setZValue(4); + scene.addItem(item3); + + GestureItem *item4 = new GestureItem("item4[partial]"); + item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures); + item4->setZValue(2); + scene.addItem(item4); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item1->ignoredUpdatedGestures << CustomGesture::GestureType; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item3->gestureOverrideEventsReceived, 1); + QCOMPARE(item4->gestureOverrideEventsReceived, 1); + + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished + QCOMPARE(item3->gestureEventsReceived, 0); + QCOMPARE(item4->gestureEventsReceived, 0); +} + +class WinNativePan : public QPanGesture { +public: + WinNativePan() {} +}; + +class Pan : public QPanGesture { +public: + Pan() {} +}; + +class CustomPan : public QPanGesture { +public: + CustomPan() {} +}; + +// Recognizer for active gesture triggers on mouse press +class PanRecognizer : public QGestureRecognizer { +public: + enum PanType { Platform, Default, Custom }; + + PanRecognizer(int id) : m_id(id) {} + QGesture *create(QObject *) { + switch(m_id) { + case Platform: return new WinNativePan(); + case Default: return new Pan(); + default: return new CustomPan(); + } + } + + Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; } + + const int m_id; +}; + +void tst_Gestures::testQGestureRecognizerCleanup() +{ + // Clean first the current recognizers in QGManager + QGestureRecognizer::unregisterRecognizer(Qt::PanGesture); + + // v-- Qt singleton QGManager initialization + + // Mimic QGestureManager: register both default and "platform" recognizers + // (this is done in windows when QT_NO_NATIVE_GESTURES is not defined) + PanRecognizer *def = new PanRecognizer(PanRecognizer::Default); + QGestureRecognizer::registerRecognizer(def); + PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform); + QGestureRecognizer::registerRecognizer(plt); + qDebug () << "register: default =" << def << "; platform =" << plt; + + // ^-- Qt singleton QGManager initialization + + // Here, application code would start + + // Create QGV (has a QAScrollArea, which uses Qt::PanGesture) + QMainWindow *w = new QMainWindow; + QGraphicsView *v = new QGraphicsView(); + w->setCentralWidget(v); + + // Unregister Qt recognizers + QGestureRecognizer::unregisterRecognizer(Qt::PanGesture); + + // Register a custom Pan recognizer + //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom)); + + w->show(); + QTest::qWaitForWindowShown(w); + delete w; +} + +class ReuseCanceledGesturesRecognizer : public QGestureRecognizer +{ +public: + enum Type { + RmbAndCancelAllType, + LmbType + }; + + ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {} + + QGesture *create(QObject *) { + QGesture *g = new QGesture; + return g; + } + + Result recognize(QGesture *gesture, QObject *, QEvent *event) { + QMouseEvent *me = static_cast(event); + Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton); + + switch(event->type()) { + case QEvent::MouseButtonPress: + if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) { + gesture->setHotSpot(QPointF(me->globalPos())); + if (m_type == RmbAndCancelAllType) + gesture->setGestureCancelPolicy(QGesture::CancelAllInContext); + return QGestureRecognizer::TriggerGesture; + } + break; + case QEvent::MouseButtonRelease: + if (me->button() == mouseButton && gesture->state() > Qt::NoGesture) + return QGestureRecognizer::FinishGesture; + default: + break; + } + return QGestureRecognizer::Ignore; + } +private: + Type m_type; +}; + +class ReuseCanceledGesturesWidget : public QGraphicsWidget +{ + public: + ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0) + : QGraphicsWidget(parent), + m_gestureType(gestureType), + m_started(0), m_updated(0), m_canceled(0), m_finished(0) + { + } + + bool event(QEvent *event) { + if (event->type() == QEvent::Gesture) { + QGesture *gesture = static_cast(event)->gesture(m_gestureType); + if (gesture) { + switch(gesture->state()) { + case Qt::GestureStarted: m_started++; break; + case Qt::GestureUpdated: m_updated++; break; + case Qt::GestureFinished: m_finished++; break; + case Qt::GestureCanceled: m_canceled++; break; + default: break; + } + } + return true; + } + if (event->type() == QEvent::GraphicsSceneMousePress) { + return true; + } + return QGraphicsWidget::event(event); + } + + int started() { return m_started; } + int updated() { return m_updated; } + int finished() { return m_finished; } + int canceled() { return m_canceled; } + + private: + Qt::GestureType m_gestureType; + int m_started; + int m_updated; + int m_canceled; + int m_finished; +}; + +void tst_Gestures::testReuseCanceledGestures() +{ + Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer( + new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType)); + Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer( + new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType)); + + QMainWindow mw; + mw.setWindowFlags(Qt::X11BypassWindowManagerHint); + QGraphicsView *gv = new QGraphicsView(&mw); + QGraphicsScene *scene = new QGraphicsScene; + + gv->setScene(scene); + scene->setSceneRect(0,0,100,100); + + // Create container and add to the scene + ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget; + container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture + + // Create widget and add to the scene + ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container); + target->grabGesture(tapGestureTypeId); + + container->setGeometry(scene->sceneRect()); + + scene->addItem(container); + + mw.setCentralWidget(gv); + + // Viewport needs to grab all gestures that widgets in scene grab + gv->viewport()->grabGesture(cancellingGestureTypeId); + gv->viewport()->grabGesture(tapGestureTypeId); + + mw.show(); + QTest::qWaitForWindowShown(&mw); + + QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center()))); + targetPos = gv->viewport()->mapFromParent(targetPos); + + // "Tap" starts on child widget + QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos); + QCOMPARE(target->started(), 1); + QCOMPARE(target->updated(), 0); + QCOMPARE(target->finished(), 0); + QCOMPARE(target->canceled(), 0); + + // Canceling gesture starts on parent + QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos); + QCOMPARE(target->started(), 1); + QCOMPARE(target->updated(), 0); + QCOMPARE(target->finished(), 0); + QCOMPARE(target->canceled(), 1); // <- child canceled + + // Canceling gesture ends + QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos); + QCOMPARE(target->started(), 1); + QCOMPARE(target->updated(), 0); + QCOMPARE(target->finished(), 0); + QCOMPARE(target->canceled(), 1); + + // Tap would end if not canceled + QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos); + QCOMPARE(target->started(), 1); + QCOMPARE(target->updated(), 0); + QCOMPARE(target->finished(), 0); + QCOMPARE(target->canceled(), 1); + + // New "Tap" starts + QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos); + QCOMPARE(target->started(), 2); + QCOMPARE(target->updated(), 0); + QCOMPARE(target->finished(), 0); + QCOMPARE(target->canceled(), 1); + + QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos); + QCOMPARE(target->started(), 2); + QCOMPARE(target->updated(), 0); + QCOMPARE(target->finished(), 1); + QCOMPARE(target->canceled(), 1); +} + +void tst_Gestures::conflictingGesturesInGraphicsView() +{ + QGraphicsScene scene; + GraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + item1->size = QRectF(0, 0, 100, 100); + item1->setZValue(2); + scene.addItem(item1); + + GestureItem *item2 = new GestureItem("item2"); + item2->grabGesture(CustomGesture::GestureType); + item2->size = QRectF(0, 0, 100, 100); + item2->setZValue(5); + scene.addItem(item2); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + CustomEvent event; + + // nobody accepts override + item1->acceptGestureOverride = false; + item2->acceptGestureOverride = false; + event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item2, &scene); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 0); + + item1->reset(); item2->reset(); + + // the original target accepts override + item1->acceptGestureOverride = false; + item2->acceptGestureOverride = true; + event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item2, &scene); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + + item1->reset(); item2->reset(); + + // the item behind accepts override + item1->acceptGestureOverride = true; + item2->acceptGestureOverride = false; + event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item2, &scene); + + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item2->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); +} + +class NoConsumeWidgetBug13501 :public QWidget +{ + Q_OBJECT +protected: + bool event(QEvent *e) { + if(e->type() == QEvent::Gesture) { + return false; + } + return QWidget::event(e); + } +}; + +void tst_Gestures::bug_13501_gesture_not_accepted() +{ + // Create a gesture event that is not accepted by any widget + // make sure this does not lead to an assert in QGestureManager + NoConsumeWidgetBug13501 w; + w.grabGesture(Qt::TapGesture); + w.show(); + QTest::qWaitForWindowShown(&w); + //QTest::mousePress(&ignoreEvent, Qt::LeftButton); + QTest::touchEvent(&w).press(0, QPoint(10, 10), &w); +} + +QTEST_MAIN(tst_Gestures) +#include "tst_gestures.moc" diff --git a/tests/auto/integrationtests/integrationtests.pro b/tests/auto/integrationtests/integrationtests.pro new file mode 100644 index 0000000000..1d58f2c665 --- /dev/null +++ b/tests/auto/integrationtests/integrationtests.pro @@ -0,0 +1,35 @@ +TEMPLATE=subdirs +SUBDIRS=\ + collections \ + exceptionsafety \ + exceptionsafety_objects \ + gestures \ + lancelot \ + languagechange \ + macgui \ + macnativeevents \ + macplist \ + modeltest \ + networkselftest \ + qaccessibility \ + qcomplextext \ + qdirectpainter \ + qfocusevent \ + qmultiscreen \ + qnetworkaccessmanager_and_qprogressdialog \ + qsharedpointer_and_qwidget \ + windowsmobile \ + +wince*|!contains(QT_CONFIG, accessibility):SUBDIRS -= qaccessibility + +!mac|qpa: SUBDIRS -= \ + macgui \ + macnativeevents \ + macplist \ + +!embedded|wince*: SUBDIRS -= \ + qdirectpainter \ + qmultiscreen \ + +!linux*-g++*:SUBDIRS -= exceptionsafety_objects + diff --git a/tests/auto/integrationtests/lancelot/.gitignore b/tests/auto/integrationtests/lancelot/.gitignore new file mode 100644 index 0000000000..0a70416d57 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/.gitignore @@ -0,0 +1 @@ +tst_lancelot diff --git a/tests/auto/integrationtests/lancelot/images.qrc b/tests/auto/integrationtests/lancelot/images.qrc new file mode 100644 index 0000000000..060b52c85a --- /dev/null +++ b/tests/auto/integrationtests/lancelot/images.qrc @@ -0,0 +1,34 @@ + + + + images/alpha.png + images/border.png + images/borderimage.png + images/dome_argb32.png + images/dome_indexed.png + images/dome_mono_palette.png + images/dome_rgb32.png + images/face.png + images/gam045.png + images/gam100.png + images/image.png + images/masked.png + images/sign.png + images/struct-image-01.jpg + images/bitmap.png + images/dome_indexed_mask.png + images/dome_mono_128.png + images/dome_mono.png + images/dot.png + images/gam030.png + images/gam056.png + images/gam200.png + images/mask_100.png + images/mask.png + images/solid.png + images/struct-image-01.png + images/zebra.png + images/alpha2x2.png + images/solid2x2.png + + diff --git a/tests/auto/integrationtests/lancelot/images/alpha.png b/tests/auto/integrationtests/lancelot/images/alpha.png new file mode 100644 index 0000000000..e465b2586d Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/alpha.png differ diff --git a/tests/auto/integrationtests/lancelot/images/alpha2x2.png b/tests/auto/integrationtests/lancelot/images/alpha2x2.png new file mode 100644 index 0000000000..67ecc04286 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/alpha2x2.png differ diff --git a/tests/auto/integrationtests/lancelot/images/bitmap.png b/tests/auto/integrationtests/lancelot/images/bitmap.png new file mode 100644 index 0000000000..d21f8f51bb Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/bitmap.png differ diff --git a/tests/auto/integrationtests/lancelot/images/border.png b/tests/auto/integrationtests/lancelot/images/border.png new file mode 100644 index 0000000000..a3d2fed0a3 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/border.png differ diff --git a/tests/auto/integrationtests/lancelot/images/borderimage.png b/tests/auto/integrationtests/lancelot/images/borderimage.png new file mode 100644 index 0000000000..f7f6b66227 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/borderimage.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_argb32.png b/tests/auto/integrationtests/lancelot/images/dome_argb32.png new file mode 100644 index 0000000000..e3ccba0c13 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_argb32.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_indexed.png b/tests/auto/integrationtests/lancelot/images/dome_indexed.png new file mode 100644 index 0000000000..beefcd514e Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_indexed.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_indexed_mask.png b/tests/auto/integrationtests/lancelot/images/dome_indexed_mask.png new file mode 100644 index 0000000000..a62f29f40e Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_indexed_mask.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_mono.png b/tests/auto/integrationtests/lancelot/images/dome_mono.png new file mode 100644 index 0000000000..950c2a7494 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_mono.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_mono_128.png b/tests/auto/integrationtests/lancelot/images/dome_mono_128.png new file mode 100644 index 0000000000..77e48aaab7 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_mono_128.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_mono_palette.png b/tests/auto/integrationtests/lancelot/images/dome_mono_palette.png new file mode 100644 index 0000000000..dca3f59245 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_mono_palette.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dome_rgb32.png b/tests/auto/integrationtests/lancelot/images/dome_rgb32.png new file mode 100644 index 0000000000..27bc02a545 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dome_rgb32.png differ diff --git a/tests/auto/integrationtests/lancelot/images/dot.png b/tests/auto/integrationtests/lancelot/images/dot.png new file mode 100644 index 0000000000..17a7b6a0ba Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/dot.png differ diff --git a/tests/auto/integrationtests/lancelot/images/face.png b/tests/auto/integrationtests/lancelot/images/face.png new file mode 100644 index 0000000000..4f6172d83b Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/face.png differ diff --git a/tests/auto/integrationtests/lancelot/images/gam030.png b/tests/auto/integrationtests/lancelot/images/gam030.png new file mode 100644 index 0000000000..904c9721bd Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/gam030.png differ diff --git a/tests/auto/integrationtests/lancelot/images/gam045.png b/tests/auto/integrationtests/lancelot/images/gam045.png new file mode 100644 index 0000000000..b649a8a54f Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/gam045.png differ diff --git a/tests/auto/integrationtests/lancelot/images/gam056.png b/tests/auto/integrationtests/lancelot/images/gam056.png new file mode 100644 index 0000000000..e5f959dc96 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/gam056.png differ diff --git a/tests/auto/integrationtests/lancelot/images/gam100.png b/tests/auto/integrationtests/lancelot/images/gam100.png new file mode 100644 index 0000000000..6c7ba5f1ed Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/gam100.png differ diff --git a/tests/auto/integrationtests/lancelot/images/gam200.png b/tests/auto/integrationtests/lancelot/images/gam200.png new file mode 100644 index 0000000000..daa20fcbc4 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/gam200.png differ diff --git a/tests/auto/integrationtests/lancelot/images/image.png b/tests/auto/integrationtests/lancelot/images/image.png new file mode 100644 index 0000000000..85d486a790 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/image.png differ diff --git a/tests/auto/integrationtests/lancelot/images/mask.png b/tests/auto/integrationtests/lancelot/images/mask.png new file mode 100644 index 0000000000..c3f3b1b6ca Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/mask.png differ diff --git a/tests/auto/integrationtests/lancelot/images/mask_100.png b/tests/auto/integrationtests/lancelot/images/mask_100.png new file mode 100644 index 0000000000..fc950dc7ed Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/mask_100.png differ diff --git a/tests/auto/integrationtests/lancelot/images/masked.png b/tests/auto/integrationtests/lancelot/images/masked.png new file mode 100644 index 0000000000..6debec534d Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/masked.png differ diff --git a/tests/auto/integrationtests/lancelot/images/sign.png b/tests/auto/integrationtests/lancelot/images/sign.png new file mode 100644 index 0000000000..6aac7e150a Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/sign.png differ diff --git a/tests/auto/integrationtests/lancelot/images/solid.png b/tests/auto/integrationtests/lancelot/images/solid.png new file mode 100644 index 0000000000..371e9c1aee Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/solid.png differ diff --git a/tests/auto/integrationtests/lancelot/images/solid2x2.png b/tests/auto/integrationtests/lancelot/images/solid2x2.png new file mode 100644 index 0000000000..ad67cd3e12 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/solid2x2.png differ diff --git a/tests/auto/integrationtests/lancelot/images/struct-image-01.jpg b/tests/auto/integrationtests/lancelot/images/struct-image-01.jpg new file mode 100644 index 0000000000..a74e07223b Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/struct-image-01.jpg differ diff --git a/tests/auto/integrationtests/lancelot/images/struct-image-01.png b/tests/auto/integrationtests/lancelot/images/struct-image-01.png new file mode 100644 index 0000000000..4ed08406dc Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/struct-image-01.png differ diff --git a/tests/auto/integrationtests/lancelot/images/zebra.png b/tests/auto/integrationtests/lancelot/images/zebra.png new file mode 100644 index 0000000000..ef35f20785 Binary files /dev/null and b/tests/auto/integrationtests/lancelot/images/zebra.png differ diff --git a/tests/auto/integrationtests/lancelot/lancelot.pro b/tests/auto/integrationtests/lancelot/lancelot.pro new file mode 100644 index 0000000000..d34732e06e --- /dev/null +++ b/tests/auto/integrationtests/lancelot/lancelot.pro @@ -0,0 +1,15 @@ +load(qttest_p4) +QT += xml widgets +contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2):QT += opengl + +SOURCES += tst_lancelot.cpp \ + paintcommands.cpp +HEADERS += paintcommands.h +RESOURCES += images.qrc + +include($$PWD/../../../baselineserver/shared/qbaselinetest.pri) + +!wince*:DEFINES += SRCDIR=\\\"$$PWD\\\" +linux-g++-maemo:DEFINES += USE_RUNTIME_DIR + +CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/integrationtests/lancelot/paintcommands.cpp b/tests/auto/integrationtests/lancelot/paintcommands.cpp new file mode 100644 index 0000000000..9659659973 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/paintcommands.cpp @@ -0,0 +1,2590 @@ +/**************************************************************************** +** +** 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 "paintcommands.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_OPENGL +#include +#endif + +/********************************************************************************* +** everything to populate static tables +**********************************************************************************/ +const char *PaintCommands::brushStyleTable[] = { + "NoBrush", + "SolidPattern", + "Dense1Pattern", + "Dense2Pattern", + "Dense3Pattern", + "Dense4Pattern", + "Dense5Pattern", + "Dense6Pattern", + "Dense7Pattern", + "HorPattern", + "VerPattern", + "CrossPattern", + "BDiagPattern", + "FDiagPattern", + "DiagCrossPattern", + "LinearGradientPattern" +}; + +const char *PaintCommands::penStyleTable[] = { + "NoPen", + "SolidLine", + "DashLine", + "DotLine", + "DashDotLine", + "DashDotDotLine" +}; + +const char *PaintCommands::fontWeightTable[] = { + "Light", + "Normal", + "DemiBold", + "Bold", + "Black" +}; + +const char *PaintCommands::fontHintingTable[] = { + "Default", + "None", + "Vertical", + "Full" +}; + +const char *PaintCommands::clipOperationTable[] = { + "NoClip", + "ReplaceClip", + "IntersectClip", + "UniteClip" +}; + +const char *PaintCommands::spreadMethodTable[] = { + "PadSpread", + "ReflectSpread", + "RepeatSpread" +}; + +const char *PaintCommands::coordinateMethodTable[] = { + "LogicalMode", + "StretchToDeviceMode", + "ObjectBoundingMode" +}; + +const char *PaintCommands::sizeModeTable[] = { + "AbsoluteSize", + "RelativeSize" +}; + +const char *PaintCommands::compositionModeTable[] = { + "SourceOver", + "DestinationOver", + "Clear", + "Source", + "Destination", + "SourceIn", + "DestinationIn", + "SourceOut", + "DestinationOut", + "SourceAtop", + "DestinationAtop", + "Xor", + "Plus", + "Multiply", + "Screen", + "Overlay", + "Darken", + "Lighten", + "ColorDodge", + "ColorBurn", + "HardLight", + "SoftLight", + "Difference", + "Exclusion", + "SourceOrDestination", + "SourceAndDestination", + "SourceXorDestination", + "NotSourceAndNotDestination", + "NotSourceOrNotDestination", + "NotSourceXorDestination", + "NotSource", + "NotSourceAndDestination", + "SourceAndNotDestination" +}; + +const char *PaintCommands::imageFormatTable[] = { + "Invalid", + "Mono", + "MonoLSB", + "Indexed8", + "RGB32", + "ARGB32", + "ARGB32_Premultiplied", + "Format_RGB16", + "Format_ARGB8565_Premultiplied", + "Format_RGB666", + "Format_ARGB6666_Premultiplied", + "Format_RGB555", + "Format_ARGB8555_Premultiplied", + "Format_RGB888", + "Format_RGB444", + "Format_ARGB4444_Premultiplied" +}; + +int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit) +{ + QByteArray p = pattern.toLatin1().toLower(); + for (int i=0; i PaintCommands::s_commandInfoTable = QList(); +QList > PaintCommands::s_enumsTable = QList >(); +QMultiHash PaintCommands::s_commandHash; + +#define DECL_PAINTCOMMAND(identifier, method, regexp, syntax, sample) \ + s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegExp(regexp), \ + QLatin1String(syntax), QLatin1String(sample) ); + +#define DECL_PAINTCOMMANDSECTION(title) \ + s_commandInfoTable << PaintCommandInfos(QLatin1String(title)); + +#define ADD_ENUMLIST(listCaption, cStrArray) { \ + QStringList list; \ + for (int i=0; i", + "import \"myfile.qrc\""); + DECL_PAINTCOMMAND("begin_block", command_begin_block, + "^begin_block\\s+(\\w*)$", + "begin_block ", + "begin_block blockName"); + DECL_PAINTCOMMAND("end_block", command_end_block, + "^end_block$", + "end_block", + "end_block"); + DECL_PAINTCOMMAND("repeat_block", command_repeat_block, + "^repeat_block\\s+(\\w*)$", + "repeat_block ", + "repeat_block blockName"); + DECL_PAINTCOMMAND("textlayout_draw", command_textlayout_draw, + "^textlayout_draw\\s+\"(.*)\"\\s+([0-9.]*)$", + "textlayout_draw ", + "textlayout_draw \"your text\" 1.0"); + DECL_PAINTCOMMAND("abort", command_abort, + "^abort$", + "abort", + "abort"); + DECL_PAINTCOMMAND("noop", command_noop, + "^$", + "-", + "\n"); + + DECL_PAINTCOMMANDSECTION("setters"); + DECL_PAINTCOMMAND("setBackgroundMode", command_setBgMode, + "^(setBackgroundMode|setBgMode)\\s+(\\w*)$", + "setBackgroundMode ", + "setBackgroundMode TransparentMode"); + DECL_PAINTCOMMAND("setBackground", command_setBackground, + "^setBackground\\s+#?(\\w*)\\s*(\\w*)?$", + "setBackground [brush style enum]", + "setBackground black SolidPattern"); + DECL_PAINTCOMMAND("setOpacity", command_setOpacity, + "^setOpacity\\s+(-?\\d*\\.?\\d*)$", + "setOpacity \n - opacity is in [0,1]", + "setOpacity 1.0"); + DECL_PAINTCOMMAND("path_setFillRule", command_path_setFillRule, + "^path_setFillRule\\s+(\\w*)\\s+(\\w*)$", + "path_setFillRule [Winding|OddEven]", + "path_setFillRule pathName Winding"); + DECL_PAINTCOMMAND("setBrush", command_setBrush, + "^setBrush\\s+(#?[\\w.:\\/]*)\\s*(\\w*)?$", + "setBrush \nsetBrush noBrush\nsetBrush ", + "setBrush white SolidPattern"); + DECL_PAINTCOMMAND("setBrushOrigin", command_setBrushOrigin, + "^setBrushOrigin\\s*(-?\\w*)\\s+(-?\\w*)$", + "setBrushOrigin ", + "setBrushOrigin 0 0"); + DECL_PAINTCOMMAND("brushTranslate", command_brushTranslate, + "^brushTranslate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "brushTranslate ", + "brushTranslate 0.0 0.0"); + DECL_PAINTCOMMAND("brushScale", command_brushScale, + "^brushScale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "brushScale ", + "brushScale 0.0 0.0"); + DECL_PAINTCOMMAND("brushRotate", command_brushRotate, + "^brushRotate\\s+(-?[\\w.]*)$", + "brushRotate \n - angle in degrees", + "brushRotate 0.0"); + DECL_PAINTCOMMAND("brushShear", command_brushShear, + "^brushShear\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "brushShear ", + "brushShear 0.0 0.0"); + DECL_PAINTCOMMAND("setCompositionMode", command_setCompositionMode, + "^setCompositionMode\\s+([\\w_0-9]*)$", + "setCompositionMode ", + "setCompositionMode SourceOver"); + DECL_PAINTCOMMAND("setFont", command_setFont, + "^setFont\\s+\"([\\w\\s]*)\"\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$", + "setFont [size] [font weight|font weight enum] [italic] [hinting enum]\n - font weight is an integer between 0 and 99", + "setFont \"times\" 12"); + DECL_PAINTCOMMAND("setPen", command_setPen, + "^setPen\\s+#?(\\w*)$", + "setPen \nsetPen \nsetPen brush", + "setPen black"); + DECL_PAINTCOMMAND("setPen", command_setPen2, + "^setPen\\s+(#?\\w*)\\s+([\\w.]+)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$", + "setPen brush| [width] [pen style enum] [FlatCap|SquareCap|RoundCap] [MiterJoin|BevelJoin|RoundJoin]", + "setPen black 1 FlatCap MiterJoin"); + DECL_PAINTCOMMAND("pen_setDashOffset", command_pen_setDashOffset, + "^pen_setDashOffset\\s+(-?[\\w.]+)$", + "pen_setDashOffset \n", + "pen_setDashOffset 1.0"); + DECL_PAINTCOMMAND("pen_setDashPattern", command_pen_setDashPattern, + "^pen_setDashPattern\\s+\\[([\\w\\s.]*)\\]$", + "pen_setDashPattern <[ ... ]>", + "pen_setDashPattern [ 2 1 4 1 3 3 ]"); + DECL_PAINTCOMMAND("pen_setCosmetic", command_pen_setCosmetic, + "^pen_setCosmetic\\s+(\\w*)$", + "pen_setCosmetic ", + "pen_setCosmetic true"); + DECL_PAINTCOMMAND("setRenderHint", command_setRenderHint, + "^setRenderHint\\s+([\\w_0-9]*)\\s*(\\w*)$", + "setRenderHint ", + "setRenderHint Antialiasing true"); + DECL_PAINTCOMMAND("clearRenderHint", command_clearRenderHint, + "^clearRenderHint$", + "clearRenderHint", + "clearRenderHint"); + + DECL_PAINTCOMMANDSECTION("gradients"); + DECL_PAINTCOMMAND("gradient_appendStop", command_gradient_appendStop, + "^gradient_appendStop\\s+([\\w.]*)\\s+#?(\\w*)$", + "gradient_appendStop ", + "gradient_appendStop 1.0 red"); + DECL_PAINTCOMMAND("gradient_clearStops", command_gradient_clearStops, + "^gradient_clearStops$", + "gradient_clearStops", + "gradient_clearStops"); + DECL_PAINTCOMMAND("gradient_setConical", command_gradient_setConical, + "^gradient_setConical\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", + "gradient_setConical \n - angle in degrees", + "gradient_setConical 5.0 5.0 45.0"); + DECL_PAINTCOMMAND("gradient_setLinear", command_gradient_setLinear, + "^gradient_setLinear\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", + "gradient_setLinear ", + "gradient_setLinear 1.0 1.0 2.0 2.0"); + DECL_PAINTCOMMAND("gradient_setRadial", command_gradient_setRadial, + "^gradient_setRadial\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$", + "gradient_setRadial \n - C is the center\n - rad is the radius\n - F is the focal point", + "gradient_setRadial 1.0 1.0 45.0 2.0 2.0"); + DECL_PAINTCOMMAND("gradient_setRadialExtended", command_gradient_setRadialExtended, + "^gradient_setRadialExtended\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$", + "gradient_setRadialExtended \n - C is the center\n - rad is the center radius\n - F is the focal point\n - frad is the focal radius", + "gradient_setRadialExtended 1.0 1.0 45.0 2.0 2.0 45.0"); + DECL_PAINTCOMMAND("gradient_setLinearPen", command_gradient_setLinearPen, + "^gradient_setLinearPen\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", + "gradient_setLinearPen ", + "gradient_setLinearPen 1.0 1.0 2.0 2.0"); + DECL_PAINTCOMMAND("gradient_setSpread", command_gradient_setSpread, + "^gradient_setSpread\\s+(\\w*)$", + "gradient_setSpread ", + "gradient_setSpread PadSpread"); + DECL_PAINTCOMMAND("gradient_setCoordinateMode", command_gradient_setCoordinateMode, + "^gradient_setCoordinateMode\\s+(\\w*)$", + "gradient_setCoordinateMode ", + "gradient_setCoordinateMode ObjectBoundingMode"); + DECL_PAINTCOMMANDSECTION("drawing ops"); + DECL_PAINTCOMMAND("drawPoint", command_drawPoint, + "^drawPoint\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawPoint ", + "drawPoint 10.0 10.0"); + DECL_PAINTCOMMAND("drawLine", command_drawLine, + "^drawLine\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawLine ", + "drawLine 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("drawRect", command_drawRect, + "^drawRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawRect ", + "drawRect 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("drawRoundRect", command_drawRoundRect, + "^drawRoundRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)?\\s*(-?\\w*)?$", + "drawRoundRect [rx] [ry]", + "drawRoundRect 10 10 20 20 3 3"); + DECL_PAINTCOMMAND("drawRoundedRect", command_drawRoundedRect, + "^drawRoundedRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(\\w*)?$", + "drawRoundedRect [SizeMode enum]", + "drawRoundedRect 10 10 20 20 4 4 AbsoluteSize"); + DECL_PAINTCOMMAND("drawArc", command_drawArc, + "^drawArc\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "drawArc \n - angles are expressed in 1/16th of degree", + "drawArc 10 10 20 20 0 5760"); + DECL_PAINTCOMMAND("drawChord", command_drawChord, + "^drawChord\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "drawChord \n - angles are expressed in 1/16th of degree", + "drawChord 10 10 20 20 0 5760"); + DECL_PAINTCOMMAND("drawEllipse", command_drawEllipse, + "^drawEllipse\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "drawEllipse ", + "drawEllipse 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("drawPath", command_drawPath, + "^drawPath\\s+(\\w*)$", + "drawPath ", + "drawPath mypath"); + DECL_PAINTCOMMAND("drawPie", command_drawPie, + "^drawPie\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "drawPie \n - angles are expressed in 1/16th of degree", + "drawPie 10 10 20 20 0 5760"); + DECL_PAINTCOMMAND("drawPixmap", command_drawPixmap, + "^drawPixmap\\s+([\\w.:\\-/]*)" + "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect + "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect + "drawPixmap " + "\n- where t means target and s means source" + "\n- a width or height of -1 means maximum space", + "drawPixmap :/images/face.png 0 0 -1 -1 0 0 -1 -1"); + DECL_PAINTCOMMAND("drawImage", command_drawImage, + "^drawImage\\s+([\\w.:\\/]*)" + "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect + "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect + "drawImage " + "\n- where t means target and s means source" + "\n- a width or height of -1 means maximum space", + "drawImage :/images/face.png 0 0 -1 -1 0 0 -1 -1"); + DECL_PAINTCOMMAND("drawPolygon", command_drawPolygon, + "^drawPolygon\\s+\\[([\\w\\s-.]*)\\]\\s*(\\w*)$", + "drawPolygon <[ ... ]> ", + "drawPolygon [ 1 4 6 8 5 3 ] Winding"); + DECL_PAINTCOMMAND("drawConvexPolygon", command_drawConvexPolygon, + "^drawConvexPolygon\\s+\\[([\\w\\s-.]*)\\]$", + "drawConvexPolygon <[ ... ]>", + "drawConvexPolygon [ 1 4 6 8 5 3 ]"); + DECL_PAINTCOMMAND("drawPolyline", command_drawPolyline, + "^drawPolyline\\s+\\[([\\w\\s]*)\\]$", + "drawPolyline <[ ... ]>", + "drawPolyline [ 1 4 6 8 5 3 ]"); + DECL_PAINTCOMMAND("drawText", command_drawText, + "^drawText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", + "drawText ", + "drawText 10 10 \"my text\""); + DECL_PAINTCOMMAND("drawStaticText", command_drawStaticText, + "^drawStaticText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", + "drawStaticText ", + "drawStaticText 10 10 \"my text\""); + DECL_PAINTCOMMAND("drawTiledPixmap", command_drawTiledPixmap, + "^drawTiledPixmap\\s+([\\w.:\\/]*)" + "\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)\\s*(-?\\w*)" + "\\s*(-?\\w*)\\s*(-?\\w*)$", + "drawTiledPixmap " + "\n - where t means tile" + "\n - and s is an offset in the tile", + "drawTiledPixmap :/images/alpha.png "); + + DECL_PAINTCOMMANDSECTION("painterPaths"); + DECL_PAINTCOMMAND("path_moveTo", command_path_moveTo, + "^path_moveTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_moveTo ", + "path_moveTo mypath 1.0 1.0"); + DECL_PAINTCOMMAND("path_lineTo", command_path_lineTo, + "^path_lineTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_lineTo ", + "path_lineTo mypath 1.0 1.0"); + DECL_PAINTCOMMAND("path_addEllipse", command_path_addEllipse, + "^path_addEllipse\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_addEllipse ", + "path_addEllipse mypath 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("path_addPolygon", command_path_addPolygon, + "^path_addPolygon\\s+(\\w*)\\s+\\[([\\w\\s]*)\\]\\s*(\\w*)$", + "path_addPolygon <[ ... ]>", + "path_addPolygon mypath [ 1 4 6 8 5 3 ]"); + DECL_PAINTCOMMAND("path_addRect", command_path_addRect, + "^path_addRect\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_addRect ", + "path_addRect mypath 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("path_addText", command_path_addText, + "^path_addText\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+\"(.*)\"$", + "path_addText ", + "path_addText mypath 10.0 20.0 \"some text\""); + DECL_PAINTCOMMAND("path_arcTo", command_path_arcTo, + "^path_arcTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_arcTo \n - angles are expressed in degrees", + "path_arcTo mypath 0.0 0.0 10.0 10.0 0.0 360.0"); + DECL_PAINTCOMMAND("path_cubicTo", command_path_cubicTo, + "^path_cubicTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "path_cubicTo ", + "path_cubicTo mypath 0.0 0.0 10.0 10.0 20.0 20.0"); + DECL_PAINTCOMMAND("path_closeSubpath", command_path_closeSubpath, + "^path_closeSubpath\\s+(\\w*)$", + "path_closeSubpath ", + "path_closeSubpath mypath"); + DECL_PAINTCOMMAND("path_createOutline", command_path_createOutline, + "^path_createOutline\\s+(\\w*)\\s+(\\w*)$", + "path_createOutline ", + "path_createOutline mypath myoutline"); + DECL_PAINTCOMMAND("path_debugPrint", command_path_debugPrint, + "^path_debugPrint\\s+(\\w*)$", + "path_debugPrint ", + "path_debugPrint mypath"); + + DECL_PAINTCOMMANDSECTION("regions"); + DECL_PAINTCOMMAND("region_addRect", command_region_addRect, + "^region_addRect\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "region_addRect ", + "region_addRect myregion 0.0 0.0 10.0 10.0"); + DECL_PAINTCOMMAND("region_addEllipse", command_region_addEllipse, + "^region_addEllipse\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", + "region_addEllipse ", + "region_addEllipse myregion 0.0 0.0 10.0 10.0"); + + DECL_PAINTCOMMANDSECTION("clipping"); + DECL_PAINTCOMMAND("region_getClipRegion", command_region_getClipRegion, + "^region_getClipRegion\\s+(\\w*)$", + "region_getClipRegion ", + "region_getClipRegion myregion"); + DECL_PAINTCOMMAND("setClipRegion", command_setClipRegion, + "^setClipRegion\\s+(\\w*)\\s*(\\w*)$", + "setClipRegion ", + "setClipRegion myregion ReplaceClip"); + DECL_PAINTCOMMAND("path_getClipPath", command_path_getClipPath, + "^path_getClipPath\\s+([\\w0-9]*)$", + "path_getClipPath ", + "path_getClipPath mypath"); + DECL_PAINTCOMMAND("setClipPath", command_setClipPath, + "^setClipPath\\s+(\\w*)\\s*(\\w*)$", + "setClipPath ", + "setClipPath mypath ReplaceClip"); + DECL_PAINTCOMMAND("setClipRect", command_setClipRect, + "^setClipRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)$", + "setClipRect ", + "setClipRect 0.0 0.0 10.0 10.0 ReplaceClip"); + DECL_PAINTCOMMAND("setClipping", command_setClipping, + "^setClipping\\s+(\\w*)$", + "setClipping ", + "setClipping true"); + + DECL_PAINTCOMMANDSECTION("surface"); + DECL_PAINTCOMMAND("surface_begin", command_surface_begin, + "^surface_begin\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "surface_begin ", + "surface_begin 0.0 0.0 10.0 10.0"); + DECL_PAINTCOMMAND("surface_end", command_surface_end, + "^surface_end$", + "surface_end", + "surface_end"); + + DECL_PAINTCOMMANDSECTION("painter states"); + DECL_PAINTCOMMAND("restore", command_restore, + "^restore$", + "restore", + "restore"); + DECL_PAINTCOMMAND("save", command_save, + "^save$", + "save", + "save"); + + DECL_PAINTCOMMANDSECTION("pixmaps'n'images"); + DECL_PAINTCOMMAND("pixmap_load", command_pixmap_load, + "^pixmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", + "pixmap_load ", + "pixmap_load :/images/face.png myPixmap"); + DECL_PAINTCOMMAND("pixmap_setMask", command_pixmap_setMask, + "^pixmap_setMask\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]*)$", + "pixmap_setMask ", + "pixmap_setMask myPixmap :/images/bitmap.png"); + DECL_PAINTCOMMAND("bitmap_load", command_bitmap_load, + "^bitmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", + "bitmap_load \n - note that the image is stored as a pixmap", + "bitmap_load :/images/bitmap.png myBitmap"); + DECL_PAINTCOMMAND("image_convertToFormat", command_image_convertToFormat, + "^image_convertToFormat\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]+)\\s+([\\w0-9_]*)$", + "image_convertToFormat ", + "image_convertToFormat myImage myNewImage Indexed8"); + DECL_PAINTCOMMAND("image_load", command_image_load, + "^image_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", + "image_load ", + "image_load :/images/face.png myImage"); + DECL_PAINTCOMMAND("image_setColor", command_image_setColor, + "^image_setColor\\s+([\\w.:\\/]*)\\s+([0-9]*)\\s+#([0-9]*)$", + "image_setColor ", + "image_setColor myImage 0 black"); + DECL_PAINTCOMMAND("image_setColorCount", command_image_setColorCount, + "^image_setColorCount\\s+([\\w.:\\/]*)\\s+([0-9]*)$", + "image_setColorCount ", + "image_setColorCount myImage 128"); + + DECL_PAINTCOMMANDSECTION("transformations"); + DECL_PAINTCOMMAND("resetMatrix", command_resetMatrix, + "^resetMatrix$", + "resetMatrix", + "resetMatrix"); + DECL_PAINTCOMMAND("setMatrix", command_setMatrix, + "^setMatrix\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "setMatrix ", + "setMatrix 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"); + DECL_PAINTCOMMAND("translate", command_translate, + "^translate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "translate ", + "translate 10.0 10.0"); + DECL_PAINTCOMMAND("rotate", command_rotate, + "^rotate\\s+(-?[\\w.]*)$", + "rotate \n - with angle in degrees", + "rotate 30.0"); + DECL_PAINTCOMMAND("rotate_x", command_rotate_x, + "^rotate_x\\s+(-?[\\w.]*)$", + "rotate_x \n - with angle in degrees", + "rotate_x 30.0"); + DECL_PAINTCOMMAND("rotate_y", command_rotate_y, + "^rotate_y\\s+(-?[\\w.]*)$", + "rotate_y \n - with angle in degrees", + "rotate_y 30.0"); + DECL_PAINTCOMMAND("scale", command_scale, + "^scale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", + "scale ", + "scale 2.0 1.0"); + DECL_PAINTCOMMAND("mapQuadToQuad", command_mapQuadToQuad, + "^mapQuadToQuad\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", + "mapQuadToQuad " + "\n - where vertices 1 to 4 defines the source quad and 5 to 8 the destination quad", + "mapQuadToQuad 0.0 0.0 1.0 1.0 0.0 0.0 -1.0 -1.0"); + + // populate the command lookup hash + for (int i=0; i T PaintCommands::image_load(const QString &filepath) +{ + T t(filepath); + + if (t.isNull()) + t = T(":images/" + filepath); + + if (t.isNull()) + t = T("images/" + filepath); + + if (t.isNull()) { + QFileInfo fi(filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(fi.fileName()); + t = T(fileName); + if (t.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + t = T(fileName); + } + } + + return t; +} + +/********************************************************************************* +** setters +**********************************************************************************/ +void PaintCommands::insertAt(int commandIndex, const QStringList &newCommands) +{ + int index = 0; + int left = newCommands.size(); + while (left--) + m_commands.insert(++commandIndex, newCommands.at(index++)); +} + +/********************************************************************************* +** run +**********************************************************************************/ +void PaintCommands::runCommand(const QString &scriptLine) +{ + if (scriptLine.isEmpty()) { + command_noop(QRegExp()); + return; + } + if (scriptLine.startsWith('#')) { + command_comment(QRegExp()); + return; + } + QString firstWord = scriptLine.section(QRegExp("\\s"), 0, 0); + QList indices = s_commandHash.values(firstWord); + foreach(int idx, indices) { + const PaintCommandInfos &command = s_commandInfoTable.at(idx); + if (command.regExp.indexIn(scriptLine) >= 0) { + (this->*(command.paintMethod))(command.regExp); + return; + } + } + qWarning("ERROR: unknown command or argument syntax error in \"%s\"", qPrintable(scriptLine)); +} + +void PaintCommands::runCommands() +{ + staticInit(); + int width = m_painter->window().width(); + int height = m_painter->window().height(); + + if (width <= 0) + width = 800; + if (height <= 0) + height = 800; + + // paint background + if (m_checkers_background) { + QPixmap pm(20, 20); + pm.fill(Qt::white); + QPainter pt(&pm); + pt.fillRect(0, 0, 10, 10, QColor::fromRgba(0xffdfdfdf)); + pt.fillRect(10, 10, 10, 10, QColor::fromRgba(0xffdfdfdf)); + pt.end(); + m_painter->drawTiledPixmap(0, 0, width, height, pm); + } else { + m_painter->fillRect(0, 0, width, height, Qt::white); + } + + // run each command + m_abort = false; + for (int i=0; idevice()->devType() == Qt::Widget) + return m_painter->window().width(); + else + return 800; + } + if (str.toLower() == "height") { + if (m_painter->device()->devType() == Qt::Widget) + return m_painter->window().height(); + else + return 800; + } + if (re.indexIn(str) >= 0) { + int index = re.cap(1).toInt(); + bool is_it_x = re.cap(2) == "x"; + if (index < 0 || index >= m_controlPoints.size()) { + qWarning("ERROR: control point index=%d is out of bounds", index); + return 0; + } + return is_it_x ? m_controlPoints.at(index).x() : m_controlPoints.at(index).y(); + } + return str.toDouble(); +} + +QColor PaintCommands::convertToColor(const QString &str) +{ + static QRegExp alphaColor("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"); + static QRegExp opaqueColor("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"); + + Q_ASSERT(alphaColor.isValid()); + Q_ASSERT(opaqueColor.isValid()); + + if (alphaColor.indexIn(str) >= 0) { + return QColor(alphaColor.cap(2).toInt(0, 16), + alphaColor.cap(3).toInt(0, 16), + alphaColor.cap(4).toInt(0, 16), + alphaColor.cap(1).toInt(0, 16)); + } else if (opaqueColor.indexIn(str) >= 0) { + return QColor(opaqueColor.cap(1).toInt(0, 16), + opaqueColor.cap(2).toInt(0, 16), + opaqueColor.cap(3).toInt(0, 16)); + } + return QColor(str); +} + +/********************************************************************************* +** command implementations +**********************************************************************************/ +void PaintCommands::command_comment(QRegExp) +{ + if (m_verboseMode) + printf(" -(lance) comment: %s\n", qPrintable(m_currentCommand)); +} + +/***************************************************************************************************/ +void PaintCommands::command_import(QRegExp re) +{ + QString importFile(re.cap(1)); + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + QFile *file = new QFile(dir.absolutePath() + QDir::separator() + importFile); + + if (importFile.isEmpty() || !file->exists()) { + dir.cdUp(); + dir.cd("data"); + dir.cd("qps"); + delete file; + file = new QFile(dir.absolutePath() + QDir::separator() + importFile); + } + + if (importFile.isEmpty() || !file->exists()) { + dir.cdUp(); + dir.cd("images"); + delete file; + file = new QFile(dir.absolutePath() + QDir::separator() + importFile); + } + + if (importFile.isEmpty() || !file->exists()) { + printf(" - importing non-existing file at line %d (%s)\n", m_currentCommandIndex, + qPrintable(file->fileName())); + delete file; + return; + } + + if (!file->open(QIODevice::ReadOnly)) { + printf(" - failed to read file: '%s'\n", qPrintable(file->fileName())); + delete file; + return; + } + if (m_verboseMode) + printf(" -(lance) importing file at line %d (%s)\n", m_currentCommandIndex, + qPrintable(fi.fileName())); + + QFileInfo fileinfo(*file); + m_commands[m_currentCommandIndex] = QString("# import file (%1) start").arg(fileinfo.fileName()); + QTextStream textFile(file); + QString rawContent = textFile.readAll(); + QStringList importedData = rawContent.split('\n', QString::SkipEmptyParts); + importedData.append(QString("# import file (%1) end ---").arg(fileinfo.fileName())); + insertAt(m_currentCommandIndex, importedData); + + if (m_verboseMode) { + printf(" -(lance) Command buffer now looks like:\n"); + for (int i = 0; i < m_commands.count(); ++i) + printf(" ---> {%s}\n", qPrintable(m_commands.at(i))); + } + delete file; +} + +/***************************************************************************************************/ +void PaintCommands::command_begin_block(QRegExp re) +{ + const QString &blockName = re.cap(1); + if (m_verboseMode) + printf(" -(lance) begin_block (%s)\n", qPrintable(blockName)); + + m_commands[m_currentCommandIndex] = QString("# begin block (%1)").arg(blockName); + QStringList newBlock; + int i = m_currentCommandIndex + 1; + for (; i < m_commands.count(); ++i) { + const QString &nextCmd = m_commands.at(i); + if (nextCmd.startsWith("end_block")) { + m_commands[i] = QString("# end block (%1)").arg(blockName); + break; + } + newBlock += nextCmd; + } + + if (m_verboseMode) + for (int j = 0; j < newBlock.count(); ++j) + printf(" %d: %s\n", j, qPrintable(newBlock.at(j))); + + if (i >= m_commands.count()) + printf(" - Warning! Block doesn't have an 'end_block' marker!\n"); + + m_blockMap.insert(blockName, newBlock); +} + +/***************************************************************************************************/ +void PaintCommands::command_end_block(QRegExp) +{ + printf(" - end_block should be consumed by begin_block command.\n"); + printf(" You will never see this if your block markers are in sync\n"); + printf(" (noop)\n"); +} + +/***************************************************************************************************/ +void PaintCommands::command_repeat_block(QRegExp re) +{ + QString blockName = re.cap(1); + if (m_verboseMode) + printf(" -(lance) repeating block (%s)\n", qPrintable(blockName)); + + QStringList block = m_blockMap.value(blockName); + if (block.isEmpty()) { + printf(" - repeated block (%s) is empty!\n", qPrintable(blockName)); + return; + } + + m_commands[m_currentCommandIndex] = QString("# repeated block (%1)").arg(blockName); + insertAt(m_currentCommandIndex, block); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawLine(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) drawLine((%.2f, %.2f), (%.2f, %.2f))\n", x1, y1, x2, y2); + + m_painter->drawLine(QLineF(x1, y1, x2, y2)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPath(QRegExp re) +{ + if (m_verboseMode) + printf(" -(lance) drawPath(name=%s)\n", qPrintable(re.cap(1))); + + QPainterPath &path = m_pathMap[re.cap(1)]; + m_painter->drawPath(path); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPixmap(QRegExp re) +{ + QPixmap pm; + pm = m_pixmapMap[re.cap(1)]; // try cache first + if (pm.isNull()) + pm = image_load(re.cap(1)); + if (pm.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(re.cap(1)); + pm = QPixmap(fileName); + if (pm.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + pm = QPixmap(fileName); + } + } + if (pm.isNull()) { + fprintf(stderr, "ERROR(drawPixmap): failed to load pixmap: '%s'\n", + qPrintable(re.cap(1))); + return; + } + + qreal tx = convertToFloat(re.cap(2)); + qreal ty = convertToFloat(re.cap(3)); + qreal tw = convertToFloat(re.cap(4)); + qreal th = convertToFloat(re.cap(5)); + + qreal sx = convertToFloat(re.cap(6)); + qreal sy = convertToFloat(re.cap(7)); + qreal sw = convertToFloat(re.cap(8)); + qreal sh = convertToFloat(re.cap(9)); + + if (tw == 0) tw = -1; + if (th == 0) th = -1; + if (sw == 0) sw = -1; + if (sh == 0) sh = -1; + + if (m_verboseMode) + printf(" -(lance) drawPixmap('%s' dim=(%d, %d), depth=%d, (%f, %f, %f, %f), (%f, %f, %f, %f)\n", + qPrintable(re.cap(1)), pm.width(), pm.height(), pm.depth(), + tx, ty, tw, th, sx, sy, sw, sh); + + m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawImage(QRegExp re) +{ + QImage im; + im = m_imageMap[re.cap(1)]; // try cache first + if (im.isNull()) + im = image_load(re.cap(1)); + + if (im.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(re.cap(1)); + im = QImage(fileName); + if (im.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + im = QImage(fileName); + } + } + if (im.isNull()) { + fprintf(stderr, "ERROR(drawImage): failed to load image: '%s'\n", qPrintable(re.cap(1))); + return; + } + + qreal tx = convertToFloat(re.cap(2)); + qreal ty = convertToFloat(re.cap(3)); + qreal tw = convertToFloat(re.cap(4)); + qreal th = convertToFloat(re.cap(5)); + + qreal sx = convertToFloat(re.cap(6)); + qreal sy = convertToFloat(re.cap(7)); + qreal sw = convertToFloat(re.cap(8)); + qreal sh = convertToFloat(re.cap(9)); + + if (tw == 0) tw = -1; + if (th == 0) th = -1; + if (sw == 0) sw = -1; + if (sh == 0) sh = -1; + + if (m_verboseMode) + printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n", + qPrintable(re.cap(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh); + + m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh), Qt::OrderedDither | Qt::OrderedAlphaDither); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawTiledPixmap(QRegExp re) +{ + QPixmap pm; + pm = m_pixmapMap[re.cap(1)]; // try cache first + if (pm.isNull()) + pm = image_load(re.cap(1)); + if (pm.isNull()) { + QFileInfo fi(m_filepath); + QDir dir = fi.absoluteDir(); + dir.cdUp(); + dir.cd("images"); + QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(re.cap(1)); + pm = QPixmap(fileName); + if (pm.isNull() && !fileName.endsWith(".png")) { + fileName.append(".png"); + pm = QPixmap(fileName); + } + } + if (pm.isNull()) { + fprintf(stderr, "ERROR(drawTiledPixmap): failed to load pixmap: '%s'\n", + qPrintable(re.cap(1))); + return; + } + + int tx = convertToInt(re.cap(2)); + int ty = convertToInt(re.cap(3)); + int tw = convertToInt(re.cap(4)); + int th = convertToInt(re.cap(5)); + + int sx = convertToInt(re.cap(6)); + int sy = convertToInt(re.cap(7)); + + if (tw == 0) tw = -1; + if (th == 0) th = -1; + + if (m_verboseMode) + printf(" -(lance) drawTiledPixmap('%s' dim=(%d, %d), (%d, %d, %d, %d), (%d, %d)\n", + qPrintable(re.cap(1)), pm.width(), pm.height(), tx, ty, tw, th, sx, sy); + + m_painter->drawTiledPixmap(tx, ty, tw, th, pm, sx, sy); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPoint(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) drawPoint(%.2f, %.2f)\n", x, y); + + m_painter->drawPoint(QPointF(x, y)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPolygon(QRegExp re) +{ + static QRegExp separators("\\s"); + QStringList caps = re.capturedTexts(); + QString cap = caps.at(1); + QStringList numbers = cap.split(separators, QString::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1drawPolygon(array, caps.at(2).toLower() == "winding" ? Qt::WindingFill : Qt::OddEvenFill); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPolyline(QRegExp re) +{ + static QRegExp separators("\\s"); + QStringList numbers = re.cap(1).split(separators, QString::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1drawPolyline(array.toPolygon()); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawRect(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + float w = convertToFloat(caps.at(3)); + float h = convertToFloat(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) drawRect(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); + + m_painter->drawRect(QRectF(x, y, w, h)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawRoundedRect(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + float w = convertToFloat(caps.at(3)); + float h = convertToFloat(caps.at(4)); + float xr = convertToFloat(caps.at(5)); + float yr = convertToFloat(caps.at(6)); + + int mode = translateEnum(sizeModeTable, caps.at(7), sizeof(sizeModeTable)/sizeof(char *)); + if (mode < 0) + mode = Qt::AbsoluteSize; + + if (m_verboseMode) + printf(" -(lance) drawRoundRect(%f, %f, %f, %f, %f, %f, %s)\n", x, y, w, h, xr, yr, mode ? "RelativeSize" : "AbsoluteSize"); + + m_painter->drawRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::SizeMode(mode)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawRoundRect(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int xs = caps.at(5).isEmpty() ? 50 : convertToInt(caps.at(5)); + int ys = caps.at(6).isEmpty() ? 50 : convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawRoundRect(%d, %d, %d, %d, [%d, %d])\n", x, y, w, h, xs, ys); + + m_painter->drawRoundRect(x, y, w, h, xs, ys); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawEllipse(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + float x = convertToFloat(caps.at(1)); + float y = convertToFloat(caps.at(2)); + float w = convertToFloat(caps.at(3)); + float h = convertToFloat(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) drawEllipse(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); + + m_painter->drawEllipse(QRectF(x, y, w, h)); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawPie(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int angle = convertToInt(caps.at(5)); + int sweep = convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawPie(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); + + m_painter->drawPie(x, y, w, h, angle, sweep); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawChord(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int angle = convertToInt(caps.at(5)); + int sweep = convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawChord(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); + + m_painter->drawChord(x, y, w, h, angle, sweep); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawArc(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + int angle = convertToInt(caps.at(5)); + int sweep = convertToInt(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) drawArc(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); + + m_painter->drawArc(x, y, w, h, angle, sweep); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawText(QRegExp re) +{ + if (!m_shouldDrawText) + return; + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + QString txt = caps.at(3); + + if (m_verboseMode) + printf(" -(lance) drawText(%d, %d, %s)\n", x, y, qPrintable(txt)); + + m_painter->drawText(x, y, txt); +} + +void PaintCommands::command_drawStaticText(QRegExp re) +{ + if (!m_shouldDrawText) + return; + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + QString txt = caps.at(3); + + if (m_verboseMode) + printf(" -(lance) drawStaticText(%d, %d, %s)\n", x, y, qPrintable(txt)); + + m_painter->drawStaticText(x, y, QStaticText(txt)); +} + +/***************************************************************************************************/ +void PaintCommands::command_noop(QRegExp) +{ + if (m_verboseMode) + printf(" -(lance) noop: %s\n", qPrintable(m_currentCommand)); + + if (!m_currentCommand.trimmed().isEmpty()) { + fprintf(stderr, "unknown command: '%s'\n", qPrintable(m_currentCommand.trimmed())); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addText(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + QString text = caps.at(4); + + if (m_verboseMode) + printf(" -(lance) path_addText(%s, %.2f, %.2f, text=%s\n", qPrintable(name), x, y, qPrintable(text)); + + m_pathMap[name].addText(x, y, m_painter->font(), text); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addEllipse(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + double w = convertToDouble(caps.at(4)); + double h = convertToDouble(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) path_addEllipse(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h); + + m_pathMap[name].addEllipse(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addRect(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x = convertToDouble(caps.at(2)); + double y = convertToDouble(caps.at(3)); + double w = convertToDouble(caps.at(4)); + double h = convertToDouble(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) path_addRect(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h); + + m_pathMap[name].addRect(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_addPolygon(QRegExp re) +{ + static QRegExp separators("\\s"); + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + QString cap = caps.at(2); + QStringList numbers = cap.split(separators, QString::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1pen(); + + if (m_verboseMode) + printf(" -(lance) path_createOutline(%s, name=%s, width=%d)\n", + qPrintable(name), qPrintable(newName), pen.width()); + + if (!m_pathMap.contains(name)) { + fprintf(stderr, "createOutline(), unknown path: %s\n", qPrintable(name)); + return; + } + QPainterPathStroker stroker; + stroker.setWidth(pen.widthF()); + stroker.setDashPattern(pen.style()); + stroker.setCapStyle(pen.capStyle()); + stroker.setJoinStyle(pen.joinStyle()); + m_pathMap[newName] = stroker.createStroke(m_pathMap[name]); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_cubicTo(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x1 = convertToDouble(caps.at(2)); + double y1 = convertToDouble(caps.at(3)); + double x2 = convertToDouble(caps.at(4)); + double y2 = convertToDouble(caps.at(5)); + double x3 = convertToDouble(caps.at(6)); + double y3 = convertToDouble(caps.at(7)); + + if (m_verboseMode) + printf(" -(lance) path_cubicTo(%s, (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f))\n", qPrintable(name), x1, y1, x2, y2, x3, y3); + + m_pathMap[name].cubicTo(x1, y1, x2, y2, x3, y3); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_moveTo(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x1 = convertToDouble(caps.at(2)); + double y1 = convertToDouble(caps.at(3)); + + if (m_verboseMode) + printf(" -(lance) path_moveTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1); + + m_pathMap[name].moveTo(x1, y1); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_lineTo(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + double x1 = convertToDouble(caps.at(2)); + double y1 = convertToDouble(caps.at(3)); + + if (m_verboseMode) + printf(" -(lance) path_lineTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1); + + m_pathMap[name].lineTo(x1, y1); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_setFillRule(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + bool winding = caps.at(2).toLower() == "winding"; + + if (m_verboseMode) + printf(" -(lance) path_setFillRule(name=%s, winding=%d)\n", qPrintable(name), winding); + + m_pathMap[name].setFillRule(winding ? Qt::WindingFill : Qt::OddEvenFill); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_closeSubpath(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + + if (m_verboseMode) + printf(" -(lance) path_closeSubpath(name=%s)\n", qPrintable(name)); + + m_pathMap[name].closeSubpath(); +} + +/***************************************************************************************************/ +void PaintCommands::command_path_getClipPath(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + + if (m_verboseMode) + printf(" -(lance) path_closeSubpath(name=%s)\n", qPrintable(name)); + + m_pathMap[name] = m_painter->clipPath(); +} + +/***************************************************************************************************/ +static void qt_debug_path(const QPainterPath &path, const QString &name) +{ + const char *names[] = { + "MoveTo ", + "LineTo ", + "CurveTo ", + "CurveToData" + }; + + printf("\nQPainterPath (%s): elementCount=%d\n", qPrintable(name), path.elementCount()); + for (int i=0; i= 0 && e.type <= QPainterPath::CurveToDataElement); + printf(" - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_path_debugPrint(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + qt_debug_path(m_pathMap[name], name); +} + +/***************************************************************************************************/ +void PaintCommands::command_region_addRect(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + int x = convertToInt(caps.at(2)); + int y = convertToInt(caps.at(3)); + int w = convertToInt(caps.at(4)); + int h = convertToInt(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) region_addRect(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h); + + m_regionMap[name] += QRect(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_region_addEllipse(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + int x = convertToInt(caps.at(2)); + int y = convertToInt(caps.at(3)); + int w = convertToInt(caps.at(4)); + int h = convertToInt(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) region_addEllipse(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h); + + m_regionMap[name] += QRegion(x, y, w, h, QRegion::Ellipse); +} + +/***************************************************************************************************/ +void PaintCommands::command_region_getClipRegion(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString name = caps.at(1); + QRegion region = m_painter->clipRegion(); + + if (m_verboseMode) + printf(" -(lance) region_getClipRegion(name=%s), bounds=[%d, %d, %d, %d]\n", qPrintable(name), + region.boundingRect().x(), + region.boundingRect().y(), + region.boundingRect().width(), + region.boundingRect().height()); + + m_regionMap[name] = region; +} + +/***************************************************************************************************/ +void PaintCommands::command_resetMatrix(QRegExp) +{ + if (m_verboseMode) + printf(" -(lance) resetMatrix()\n"); + + m_painter->resetTransform(); +} + +/***************************************************************************************************/ +void PaintCommands::command_restore(QRegExp) +{ + if (m_verboseMode) + printf(" -(lance) restore()\n"); + + m_painter->restore(); +} + +/***************************************************************************************************/ +void PaintCommands::command_rotate(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double angle = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) rotate(%.2f)\n", angle); + + m_painter->rotate(angle); +} + +/***************************************************************************************************/ +void PaintCommands::command_rotate_x(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double angle = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) rotate_x(%.2f)\n", angle); + + QTransform transform; + transform.rotate(angle, Qt::XAxis); + m_painter->setTransform(transform, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_rotate_y(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double angle = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) rotate_y(%.2f)\n", angle); + + QTransform transform; + transform.rotate(angle, Qt::YAxis); + m_painter->setTransform(transform, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_save(QRegExp) +{ + if (m_verboseMode) + printf(" -(lance) save()\n"); + + m_painter->save(); +} + +/***************************************************************************************************/ +void PaintCommands::command_mapQuadToQuad(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + double x3 = convertToDouble(caps.at(5)); + double y3 = convertToDouble(caps.at(6)); + double x4 = convertToDouble(caps.at(7)); + double y4 = convertToDouble(caps.at(8)); + QPolygonF poly1(4); + poly1[0] = QPointF(x1, y1); + poly1[1] = QPointF(x2, y2); + poly1[2] = QPointF(x3, y3); + poly1[3] = QPointF(x4, y4); + + double x5 = convertToDouble(caps.at(9)); + double y5 = convertToDouble(caps.at(10)); + double x6 = convertToDouble(caps.at(11)); + double y6 = convertToDouble(caps.at(12)); + double x7 = convertToDouble(caps.at(13)); + double y7 = convertToDouble(caps.at(14)); + double x8 = convertToDouble(caps.at(15)); + double y8 = convertToDouble(caps.at(16)); + QPolygonF poly2(4); + poly2[0] = QPointF(x5, y5); + poly2[1] = QPointF(x6, y6); + poly2[2] = QPointF(x7, y7); + poly2[3] = QPointF(x8, y8); + + if (m_verboseMode) + printf(" -(lance) mapQuadToQuad(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ->\n\t" + ",%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", + x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7, x8, y8); + + QTransform trans; + + if (!QTransform::quadToQuad(poly1, poly2, trans)) { + qWarning("Couldn't perform quad to quad transformation!"); + } + + m_painter->setTransform(trans, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_setMatrix(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double m11 = convertToDouble(caps.at(1)); + double m12 = convertToDouble(caps.at(2)); + double m13 = convertToDouble(caps.at(3)); + double m21 = convertToDouble(caps.at(4)); + double m22 = convertToDouble(caps.at(5)); + double m23 = convertToDouble(caps.at(6)); + double m31 = convertToDouble(caps.at(7)); + double m32 = convertToDouble(caps.at(8)); + double m33 = convertToDouble(caps.at(9)); + + if (m_verboseMode) + printf(" -(lance) setMatrix(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", + m11, m12, m13, m21, m22, m23, m31, m32, m33); + + QTransform trans; + trans.setMatrix(m11, m12, m13, + m21, m22, m23, + m31, m32, m33); + + m_painter->setTransform(trans, true); +} + +/***************************************************************************************************/ +void PaintCommands::command_scale(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double sx = convertToDouble(caps.at(1)); + double sy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) scale(%.2f, %.2f)\n", sx, sy); + + + m_painter->scale(sx, sy); +} + +/***************************************************************************************************/ +void PaintCommands::command_setBackground(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QColor color = convertToColor(caps.at(1)); + QString pattern = caps.at(2); + + int style = translateEnum(brushStyleTable, pattern, Qt::LinearGradientPattern); + if (style < 0) + style = Qt::SolidPattern; + + if (m_verboseMode) + printf(" -(lance) setBackground(%s, %s)\n", qPrintable(color.name()), qPrintable(pattern)); + + m_painter->setBackground(QBrush(color, Qt::BrushStyle(style))); +} + +/***************************************************************************************************/ +void PaintCommands::command_setOpacity(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double opacity = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) setOpacity(%lf)\n", opacity); + + m_painter->setOpacity(opacity); +} + +/***************************************************************************************************/ +void PaintCommands::command_setBgMode(QRegExp re) +{ + QString cap = re.cap(2); + Qt::BGMode mode = Qt::TransparentMode; + if (cap.toLower() == QLatin1String("opaquemode") || cap.toLower() == QLatin1String("opaque")) + mode = Qt::OpaqueMode; + + if (m_verboseMode) + printf(" -(lance) setBackgroundMode(%s)\n", mode == Qt::OpaqueMode ? "OpaqueMode" : "TransparentMode"); + + m_painter->setBackgroundMode(mode); +} + +/***************************************************************************************************/ +void PaintCommands::command_setBrush(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QPixmap pm = image_load(caps.at(1)); + if (!pm.isNull()) { // Assume pixmap + if (m_verboseMode) + printf(" -(lance) setBrush(pixmap=%s, width=%d, height=%d)\n", + qPrintable(caps.at(1)), pm.width(), pm.height()); + + m_painter->setBrush(QBrush(pm)); + } else if (caps.at(1).toLower() == "nobrush") { + m_painter->setBrush(Qt::NoBrush); + if (m_verboseMode) + printf(" -(lance) setBrush(Qt::NoBrush)\n"); + } else { + QColor color = convertToColor(caps.at(1)); + QString pattern = caps.at(2); + + int style = translateEnum(brushStyleTable, pattern, Qt::LinearGradientPattern); + if (style < 0) + style = Qt::SolidPattern; + + if (m_verboseMode) + printf(" -(lance) setBrush(%s, %s (%d))\n", qPrintable(color.name()), qPrintable(pattern), style); + + m_painter->setBrush(QBrush(color, Qt::BrushStyle(style))); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_setBrushOrigin(QRegExp re) +{ + int x = convertToInt(re.cap(1)); + int y = convertToInt(re.cap(2)); + + if (m_verboseMode) + printf(" -(lance) setBrushOrigin(%d, %d)\n", x, y); + + m_painter->setBrushOrigin(x, y); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushTranslate(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double dx = convertToDouble(caps.at(1)); + double dy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) brushTranslate(%f, %f)\n", dx, dy); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.translate(dx, dy); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushScale(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double sx = convertToDouble(caps.at(1)); + double sy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) brushScale(%f, %f)\n", sx, sy); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.scale(sx, sy); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushRotate(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double rot = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) brushScale(%f)\n", rot); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.rotate(rot); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_brushShear(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double sx = convertToDouble(caps.at(1)); + double sy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) brushShear(%f, %f)\n", sx, sy); + + QBrush new_brush = m_painter->brush(); + QTransform brush_matrix = new_brush.transform(); + brush_matrix.shear(sx, sy); + new_brush.setTransform(brush_matrix); + m_painter->setBrush(new_brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipping(QRegExp re) +{ + bool clipping = re.cap(1).toLower() == "true"; + + if (m_verboseMode) + printf(" -(lance) setClipping(%d)\n", clipping); + + m_painter->setClipping(clipping); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipRect(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + int x = convertToInt(caps.at(1)); + int y = convertToInt(caps.at(2)); + int w = convertToInt(caps.at(3)); + int h = convertToInt(caps.at(4)); + + int combine = translateEnum(clipOperationTable, caps.at(5), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + + if (m_verboseMode) + printf(" -(lance) setClipRect(%d, %d, %d, %d), %s\n", x, y, w, h, clipOperationTable[combine]); + + m_painter->setClipRect(x, y, w, h, Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipPath(QRegExp re) +{ + int combine = translateEnum(clipOperationTable, re.cap(2), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + + if (m_verboseMode) + printf(" -(lance) setClipPath(name=%s), %s\n", qPrintable(re.cap(1)), clipOperationTable[combine]); + + if (!m_pathMap.contains(re.cap(1))) + fprintf(stderr, " - setClipPath, no such path"); + m_painter->setClipPath(m_pathMap[re.cap(1)], Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setClipRegion(QRegExp re) +{ + int combine = translateEnum(clipOperationTable, re.cap(2), Qt::IntersectClip + 1); + if (combine == -1) + combine = Qt::ReplaceClip; + QRegion r = m_regionMap[re.cap(1)]; + + if (m_verboseMode) + printf(" -(lance) setClipRegion(name=%s), bounds=[%d, %d, %d, %d], %s\n", + qPrintable(re.cap(1)), + r.boundingRect().x(), + r.boundingRect().y(), + r.boundingRect().width(), + r.boundingRect().height(), + clipOperationTable[combine]); + + m_painter->setClipRegion(m_regionMap[re.cap(1)], Qt::ClipOperation(combine)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setFont(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QString family = caps.at(1); + int size = convertToInt(caps.at(2)); + + int weight = translateEnum(fontWeightTable, re.cap(3).toLower(), 5); + if (weight != -1) { + switch (weight) { + case 0: weight = QFont::Light; break; + case 1: weight = QFont::Normal; break; + case 2: weight = QFont::DemiBold; break; + case 3: weight = QFont::Bold; break; + case 4: weight = QFont::Black; break; + } + } else { + weight = convertToInt(re.cap(3)); + } + + bool italic = caps.at(4).toLower() == "true" || caps.at(4).toLower() == "italic"; + + QFont font(family, size, weight, italic); + +#if QT_VERSION >= 0x040800 + int hinting = translateEnum(fontHintingTable, caps.at(5), 4); + if (hinting == -1) + hinting = 0; + else + font.setHintingPreference(QFont::HintingPreference(hinting)); +#else + int hinting = 1; +#endif + if (m_verboseMode) + printf(" -(lance) setFont(family=%s, size=%d, weight=%d, italic=%d hinting=%s\n", + qPrintable(family), size, weight, italic, fontHintingTable[hinting]); + + m_painter->setFont(font); +} + +/***************************************************************************************************/ +void PaintCommands::command_setPen(QRegExp re) +{ + QString cap = re.cap(1); + int style = translateEnum(penStyleTable, cap, Qt::DashDotDotLine + 1); + if (style >= 0) { + if (m_verboseMode) + printf(" -(lance) setPen(%s)\n", qPrintable(cap)); + + m_painter->setPen(Qt::PenStyle(style)); + } else if (cap.toLower() == "brush") { + QPen pen(m_painter->brush(), 0); + if (m_verboseMode) { + printf(" -(lance) setPen(brush), style=%d, color=%08x\n", + pen.brush().style(), pen.color().rgba()); + } + m_painter->setPen(pen); + } else { + QColor color = convertToColor(cap); + if (m_verboseMode) + printf(" -(lance) setPen(%s)\n", qPrintable(color.name())); + + m_painter->setPen(color); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_setPen2(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QBrush brush; + + if (caps.at(1).toLower() == "brush") + brush = m_painter->brush(); + else + brush = convertToColor(caps.at(1)); + + double width = convertToDouble(caps.at(2)); + int penStyle = translateEnum(penStyleTable, caps.at(3), Qt::DashDotDotLine + 1); + if (penStyle < 0) + penStyle = Qt::SolidLine; + + Qt::PenCapStyle capStyle = Qt::SquareCap; + if (caps.at(4).toLower() == "flatcap") capStyle = Qt::FlatCap; + else if (caps.at(4).toLower() == "squarecap") capStyle = Qt::SquareCap; + else if (caps.at(4).toLower() == "roundcap") capStyle = Qt::RoundCap; + else if (!caps.at(4).isEmpty()) + fprintf(stderr, "ERROR: setPen, unknown capStyle: %s\n", qPrintable(caps.at(4))); + + Qt::PenJoinStyle joinStyle = Qt::BevelJoin; + if (caps.at(5).toLower() == "miterjoin") joinStyle = Qt::MiterJoin; + else if (caps.at(5).toLower() == "beveljoin") joinStyle = Qt::BevelJoin; + else if (caps.at(5).toLower() == "roundjoin") joinStyle = Qt::RoundJoin; + else if (!caps.at(5).isEmpty()) + fprintf(stderr, "ERROR: setPen, unknown joinStyle: %s\n", qPrintable(caps.at(5))); + + if (m_verboseMode) + printf(" -(lance) setPen(%s, width=%f, style=%d, cap=%d, join=%d)\n", + qPrintable(brush.color().name()), width, penStyle, capStyle, joinStyle); + + m_painter->setPen(QPen(brush, width, Qt::PenStyle(penStyle), capStyle, joinStyle)); +} + +/***************************************************************************************************/ +void PaintCommands::command_setRenderHint(QRegExp re) +{ + QString hintString = re.cap(1).toLower(); + bool on = re.cap(2).isEmpty() || re.cap(2).toLower() == "true"; + if (hintString.contains("antialiasing")) { + if (m_verboseMode) + printf(" -(lance) setRenderHint Antialiasing\n"); + + m_painter->setRenderHint(QPainter::Antialiasing, on); + } else if (hintString.contains("smoothpixmaptransform")) { + if (m_verboseMode) + printf(" -(lance) setRenderHint SmoothPixmapTransform\n"); + m_painter->setRenderHint(QPainter::SmoothPixmapTransform, on); + } else { + fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(hintString)); + } +} + +/***************************************************************************************************/ +void PaintCommands::command_clearRenderHint(QRegExp /*re*/) +{ + m_painter->setRenderHint(QPainter::Antialiasing, false); + m_painter->setRenderHint(QPainter::SmoothPixmapTransform, false); + if (m_verboseMode) + printf(" -(lance) clearRenderHint\n"); +} + +/***************************************************************************************************/ +void PaintCommands::command_setCompositionMode(QRegExp re) +{ + QString modeString = re.cap(1).toLower(); + int mode = translateEnum(compositionModeTable, modeString, 33); + + if (mode < 0 || mode > QPainter::RasterOp_SourceAndNotDestination) { + fprintf(stderr, "ERROR: invalid mode: %s\n", qPrintable(modeString)); + return; + } + + if (m_verboseMode) + printf(" -(lance) setCompositionMode: %d: %s\n", mode, qPrintable(modeString)); + + m_painter->setCompositionMode(QPainter::CompositionMode(mode)); +} + +/***************************************************************************************************/ +void PaintCommands::command_translate(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double dx = convertToDouble(caps.at(1)); + double dy = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) translate(%f, %f)\n", dx, dy); + + m_painter->translate(dx, dy); +} + +/***************************************************************************************************/ +void PaintCommands::command_pixmap_load(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString fileName = caps.at(1); + QString name = caps.at(2); + + if (name.isEmpty()) + name = fileName; + + QImage im = image_load(fileName); + QPixmap px = QPixmap::fromImage(im, Qt::OrderedDither | Qt::OrderedAlphaDither); + + if (m_verboseMode) + printf(" -(lance) pixmap_load(%s as %s), size=[%d, %d], depth=%d\n", + qPrintable(fileName), qPrintable(name), + px.width(), px.height(), px.depth()); + + m_pixmapMap[name] = px; +} + +/***************************************************************************************************/ +void PaintCommands::command_bitmap_load(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString fileName = caps.at(1); + QString name = caps.at(2); + + if (name.isEmpty()) + name = fileName; + + QBitmap bm = image_load(fileName); + + if (m_verboseMode) + printf(" -(lance) bitmap_load(%s as %s), size=[%d, %d], depth=%d\n", + qPrintable(fileName), qPrintable(name), + bm.width(), bm.height(), bm.depth()); + + m_pixmapMap[name] = bm; +} + +/***************************************************************************************************/ +void PaintCommands::command_pixmap_setMask(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + QBitmap mask = image_load(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) pixmap_setMask(%s, %s)\n", qPrintable(caps.at(1)), qPrintable(caps.at(2))); + + if (!m_pixmapMap[caps.at(1)].isNull()) + m_pixmapMap[caps.at(1)].setMask(mask); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_load(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString fileName = caps.at(1); + QString name = caps.at(2); + + if (name.isEmpty()) + name = fileName; + + QImage image = image_load(fileName); + + if (m_verboseMode) + printf(" -(lance) image_load(%s as %s), size=[%d, %d], format=%d\n", + qPrintable(fileName), qPrintable(name), + image.width(), image.height(), image.format()); + + m_imageMap[name] = image; +} + +/***************************************************************************************************/ +void PaintCommands::command_image_setColorCount(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString name = caps.at(1); + int count = convertToInt(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) image_setColorCount(%s), %d -> %d\n", + qPrintable(name), m_imageMap[name].colorCount(), count); + + m_imageMap[name].setColorCount(count); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_setColor(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString name = caps.at(1); + int index = convertToInt(caps.at(2)); + QColor color = convertToColor(caps.at(3)); + + if (m_verboseMode) + printf(" -(lance) image_setColor(%s), %d = %08x\n", qPrintable(name), index, color.rgba()); + + m_imageMap[name].setColor(index, color.rgba()); +} + +/***************************************************************************************************/ +void PaintCommands::command_abort(QRegExp) +{ + m_abort = true; +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_clearStops(QRegExp) +{ + if (m_verboseMode) + printf(" -(lance) gradient_clearStops\n"); + m_gradientStops.clear(); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_appendStop(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double pos = convertToDouble(caps.at(1)); + QColor color = convertToColor(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) gradient_appendStop(%.2f, %x)\n", pos, color.rgba()); + + m_gradientStops << QGradientStop(pos, color); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setLinear(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n", + x1, y1, x2, y2, m_gradientSpread); + + QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2)); + lg.setStops(m_gradientStops); + lg.setSpread(m_gradientSpread); + lg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(lg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setLinearPen(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double x1 = convertToDouble(caps.at(1)); + double y1 = convertToDouble(caps.at(2)); + double x2 = convertToDouble(caps.at(3)); + double y2 = convertToDouble(caps.at(4)); + + if (m_verboseMode) + printf(" -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n", + x1, y1, x2, y2, m_gradientSpread); + + QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2)); + lg.setStops(m_gradientStops); + lg.setSpread(m_gradientSpread); + lg.setCoordinateMode(m_gradientCoordinate); + QPen pen = m_painter->pen(); + pen.setBrush(lg); + m_painter->setPen(pen); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setRadial(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double cx = convertToDouble(caps.at(1)); + double cy = convertToDouble(caps.at(2)); + double rad = convertToDouble(caps.at(3)); + double fx = convertToDouble(caps.at(4)); + double fy = convertToDouble(caps.at(5)); + + if (m_verboseMode) + printf(" -(lance) gradient_setRadial center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), " + "spread=%d\n", + cx, cy, rad, fx, fy, m_gradientSpread); + + QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy)); + rg.setStops(m_gradientStops); + rg.setSpread(m_gradientSpread); + rg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(rg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setRadialExtended(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double cx = convertToDouble(caps.at(1)); + double cy = convertToDouble(caps.at(2)); + double rad = convertToDouble(caps.at(3)); + double fx = convertToDouble(caps.at(4)); + double fy = convertToDouble(caps.at(5)); + double frad = convertToDouble(caps.at(6)); + + if (m_verboseMode) + printf(" -(lance) gradient_setRadialExtended center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), " + "focal radius=%.2f, spread=%d\n", + cx, cy, rad, fx, fy, frad, m_gradientSpread); + +#if QT_VERSION >= 0x040800 + QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy), frad); +#else + QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy)); +#endif + rg.setStops(m_gradientStops); + rg.setSpread(m_gradientSpread); + rg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(rg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setConical(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double cx = convertToDouble(caps.at(1)); + double cy = convertToDouble(caps.at(2)); + double angle = convertToDouble(caps.at(3)); + + if (m_verboseMode) { + printf(" -(lance) gradient_setConical center=(%.2f, %.2f), angle=%.2f\n, spread=%d", + cx, cy, angle, m_gradientSpread); + } + + QConicalGradient cg(QPointF(cx, cy), angle); + cg.setStops(m_gradientStops); + cg.setSpread(m_gradientSpread); + cg.setCoordinateMode(m_gradientCoordinate); + QBrush brush(cg); + QTransform brush_matrix = m_painter->brush().transform(); + brush.setTransform(brush_matrix); + m_painter->setBrush(brush); +} + +/***************************************************************************************************/ +void PaintCommands::command_gradient_setSpread(QRegExp re) +{ + int spreadMethod = translateEnum(spreadMethodTable, re.cap(1), 3); + + if (m_verboseMode) + printf(" -(lance) gradient_setSpread %d=[%s]\n", spreadMethod, spreadMethodTable[spreadMethod]); + + m_gradientSpread = QGradient::Spread(spreadMethod); +} + +void PaintCommands::command_gradient_setCoordinateMode(QRegExp re) +{ + int coord = translateEnum(coordinateMethodTable, re.cap(1), 3); + + if (m_verboseMode) + printf(" -(lance) gradient_setCoordinateMode %d=[%s]\n", coord, + coordinateMethodTable[coord]); + + m_gradientCoordinate = QGradient::CoordinateMode(coord); +} + +/***************************************************************************************************/ +void PaintCommands::command_surface_begin(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double x = convertToDouble(caps.at(1)); + double y = convertToDouble(caps.at(2)); + double w = convertToDouble(caps.at(3)); + double h = convertToDouble(caps.at(4)); + + if (m_surface_painter) { + fprintf(stderr, "ERROR: surface already active"); + return; + } + + if (m_verboseMode) + printf(" -(lance) surface_begin, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", x, y, w, h); + + m_surface_painter = m_painter; + + if (m_type == OpenGLType || m_type == OpenGLPBufferType) { +#ifndef QT_NO_OPENGL + m_surface_pbuffer = new QGLPixelBuffer(qRound(w), qRound(h)); + m_painter = new QPainter(m_surface_pbuffer); + m_painter->fillRect(QRect(0, 0, qRound(w), qRound(h)), Qt::transparent); +#endif +#ifdef Q_WS_X11 + } else if (m_type == WidgetType) { + m_surface_pixmap = QPixmap(qRound(w), qRound(h)); + m_surface_pixmap.fill(Qt::transparent); + m_painter = new QPainter(&m_surface_pixmap); +#endif + } else { + m_surface_image = QImage(qRound(w), qRound(h), QImage::Format_ARGB32_Premultiplied); + m_surface_image.fill(0); + m_painter = new QPainter(&m_surface_image); + } + m_surface_rect = QRectF(x, y, w, h); +} + +/***************************************************************************************************/ +void PaintCommands::command_surface_end(QRegExp) +{ + if (!m_surface_painter) { + fprintf(stderr, "ERROR: surface not active"); + return; + } + + if (m_verboseMode) + printf(" -(lance) surface_end, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", + m_surface_rect.x(), + m_surface_rect.y(), + m_surface_rect.width(), + m_surface_rect.height()); + m_painter->end(); + + delete m_painter; + m_painter = m_surface_painter; + m_surface_painter = 0; + + if (m_type == OpenGLType || m_type == OpenGLPBufferType) { +#ifndef QT_NO_OPENGL + QImage image = m_surface_pbuffer->toImage(); + QImage new_image(image.bits(), image.width(), + image.height(), QImage::Format_ARGB32_Premultiplied); + QPaintDevice *pdev = m_painter->device(); + if (pdev->devType() == QInternal::Widget) { + QWidget *w = static_cast(pdev); + static_cast(w)->makeCurrent(); + } else if (pdev->devType() == QInternal::Pbuffer) { + static_cast(pdev)->makeCurrent(); + } + + m_painter->drawImage(m_surface_rect, new_image); + + delete m_surface_pbuffer; + m_surface_pbuffer = 0; +#endif +#ifdef Q_WS_X11 + } else if (m_type == WidgetType) { + m_painter->drawPixmap(m_surface_rect.topLeft(), m_surface_pixmap); + m_surface_pixmap = QPixmap(); +#endif + } else { + m_painter->drawImage(m_surface_rect, m_surface_image); + m_surface_image = QImage(); + } + m_surface_rect = QRectF(); +} + +/***************************************************************************************************/ +void PaintCommands::command_image_convertToFormat(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString srcName = caps.at(1); + QString destName = caps.at(2); + + if (!m_imageMap.contains(srcName)) { + fprintf(stderr, "ERROR(convertToFormat): no such image '%s'\n", qPrintable(srcName)); + return; + } + + int format = translateEnum(imageFormatTable, caps.at(3), QImage::NImageFormats); + if (format < 0 || format >= QImage::NImageFormats) { + fprintf(stderr, "ERROR(convertToFormat): invalid format %d = '%s'\n", + format, qPrintable(caps.at(3))); + return; + } + + QImage src = m_imageMap[srcName]; + QImage dest = src.convertToFormat(QImage::Format(format), + Qt::OrderedAlphaDither | Qt::OrderedDither); + + if (m_verboseMode) { + printf(" -(lance) convertToFormat %s:%d -> %s:%d\n", + qPrintable(srcName), src.format(), + qPrintable(destName), dest.format()); + } + + m_imageMap[destName] = dest; +} + +/***************************************************************************************************/ +void PaintCommands::command_textlayout_draw(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + + QString text = caps.at(1); + double width = convertToDouble(caps.at(2)); + + if (m_verboseMode) + printf(" -(lance) textlayout_draw text='%s', width=%f\n", + qPrintable(text), width); + + QFont copy = m_painter->font(); + copy.setPointSize(10); + + QTextLayout layout(text, copy, m_painter->device()); + layout.beginLayout(); + + double y_offset = 0; + + while (true) { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(width); + line.setPosition(QPointF(0, y_offset)); + + y_offset += line.height(); + } + + layout.draw(m_painter, QPointF(0, 0)); +} + +/***************************************************************************************************/ +void PaintCommands::command_pen_setDashOffset(QRegExp re) +{ + QStringList caps = re.capturedTexts(); + double offset = convertToDouble(caps.at(1)); + + if (m_verboseMode) + printf(" -(lance) setDashOffset(%lf)\n", offset); + + QPen p = m_painter->pen(); + p.setDashOffset(offset); + m_painter->setPen(p); +} + +/***************************************************************************************************/ +void PaintCommands::command_pen_setDashPattern(QRegExp re) +{ + static QRegExp separators("\\s"); + QStringList caps = re.capturedTexts(); + QString cap = caps.at(1); + QStringList numbers = cap.split(separators, QString::SkipEmptyParts); + + QVector pattern; + for (int i=0; ipen(); + p.setDashPattern(pattern); + m_painter->setPen(p); +} + +/***************************************************************************************************/ +void PaintCommands::command_pen_setCosmetic(QRegExp re) +{ + QString hm = re.capturedTexts().at(1); + bool on = hm == "true" || hm == "yes" || hm == "on"; + + if (m_verboseMode) { + printf(" -(lance) pen_setCosmetic(%s)\n", on ? "true" : "false"); + } + + QPen p = m_painter->pen(); + p.setCosmetic(on); + + m_painter->setPen(p); +} + +/***************************************************************************************************/ +void PaintCommands::command_drawConvexPolygon(QRegExp re) +{ + static QRegExp separators("\\s"); + QStringList caps = re.capturedTexts(); + QString cap = caps.at(1); + QStringList numbers = cap.split(separators, QString::SkipEmptyParts); + + QPolygonF array; + for (int i=0; i + 1drawConvexPolygon(array); +} diff --git a/tests/auto/integrationtests/lancelot/paintcommands.h b/tests/auto/integrationtests/lancelot/paintcommands.h new file mode 100644 index 0000000000..925a867f2f --- /dev/null +++ b/tests/auto/integrationtests/lancelot/paintcommands.h @@ -0,0 +1,334 @@ +/**************************************************************************** +** +** 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 PAINTCOMMANDS_H +#define PAINTCOMMANDS_H + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QPainter) +QT_FORWARD_DECLARE_CLASS(QRegExp) +#ifndef QT_NO_OPENGL +QT_FORWARD_DECLARE_CLASS(QGLPixelBuffer) +#endif + +enum DeviceType { + WidgetType, + BitmapType, + PixmapType, + ImageType, + ImageMonoType, + OpenGLType, + OpenGLPBufferType, + PictureType, + PrinterType, + PdfType, + PsType, + GrabType, + CustomDeviceType, + CustomWidgetType, + ImageWidgetType +}; + +/************************************************************************/ +class PaintCommands +{ +public: + // construction / initialization + PaintCommands(const QStringList &cmds, int w, int h) + : m_painter(0) + , m_surface_painter(0) + , m_commands(cmds) + , m_gradientSpread(QGradient::PadSpread) + , m_gradientCoordinate(QGradient::LogicalMode) + , m_width(w) + , m_height(h) + , m_verboseMode(false) + , m_type(WidgetType) + , m_checkers_background(true) + , m_shouldDrawText(true) + { staticInit(); } + +public: + void setCheckersBackground(bool b) { staticInit(); m_checkers_background = b; } + void setContents(const QStringList &cmds) { + staticInit(); + m_blockMap.clear(); + m_pathMap.clear(); + m_pixmapMap.clear(); + m_imageMap.clear(); + m_regionMap.clear(); + m_gradientStops.clear(); + m_controlPoints.clear(); + m_gradientSpread = QGradient::PadSpread; + m_gradientCoordinate = QGradient::LogicalMode; + m_commands = cmds; + + + } + void setPainter(QPainter *pt) { staticInit(); m_painter = pt; } + void setType(DeviceType t) { staticInit(); m_type = t; } + void setFilePath(const QString &path) { staticInit(); m_filepath = path; } + void setControlPoints(const QVector &points) { staticInit(); m_controlPoints = points; } + void setVerboseMode(bool v) { staticInit(); m_verboseMode = v; } + void insertAt(int commandIndex, const QStringList &newCommands); + void setShouldDrawText(bool drawText) { m_shouldDrawText = drawText; } + + // run + void runCommands(); + +private: + // run + void runCommand(const QString &scriptLine); + + // conversion methods + int convertToInt(const QString &str); + double convertToDouble(const QString &str); + float convertToFloat(const QString &str); + QColor convertToColor(const QString &str); + + // commands: comments + void command_comment(QRegExp re); + + // commands: importer + void command_import(QRegExp re); + + // commands: blocks + void command_begin_block(QRegExp re); + void command_end_block(QRegExp re); + void command_repeat_block(QRegExp re); + + // commands: misc + void command_textlayout_draw(QRegExp re); + void command_abort(QRegExp re); + + // commands: noops + void command_noop(QRegExp re); + + // commands: setters + void command_setBgMode(QRegExp re); + void command_setBackground(QRegExp re); + void command_setOpacity(QRegExp re); + void command_path_setFillRule(QRegExp re); + void command_setBrush(QRegExp re); + void command_setBrushOrigin(QRegExp re); + void command_brushTranslate(QRegExp re); + void command_brushRotate(QRegExp re); + void command_brushScale(QRegExp re); + void command_brushShear(QRegExp re); + void command_setClipPath(QRegExp re); + void command_setClipRect(QRegExp re); + void command_setClipRectangle(QRegExp re); + void command_setClipRegion(QRegExp re); + void command_setClipping(QRegExp re); + void command_setCompositionMode(QRegExp re); + void command_setFont(QRegExp re); + void command_setPen(QRegExp re); + void command_setPen2(QRegExp re); + void command_pen_setDashOffset(QRegExp re); + void command_pen_setDashPattern(QRegExp re); + void command_pen_setCosmetic(QRegExp re); + void command_setRenderHint(QRegExp re); + void command_clearRenderHint(QRegExp re); + void command_gradient_appendStop(QRegExp re); + void command_gradient_clearStops(QRegExp re); + void command_gradient_setConical(QRegExp re); + void command_gradient_setLinear(QRegExp re); + void command_gradient_setRadial(QRegExp re); + void command_gradient_setRadialExtended(QRegExp re); + void command_gradient_setLinearPen(QRegExp re); + void command_gradient_setSpread(QRegExp re); + void command_gradient_setCoordinateMode(QRegExp re); + + // commands: drawing ops + void command_drawArc(QRegExp re); + void command_drawChord(QRegExp re); + void command_drawConvexPolygon(QRegExp re); + void command_drawEllipse(QRegExp re); + void command_drawImage(QRegExp re); + void command_drawLine(QRegExp re); + void command_drawPath(QRegExp re); + void command_drawPie(QRegExp re); + void command_drawPixmap(QRegExp re); + void command_drawPoint(QRegExp re); + void command_drawPolygon(QRegExp re); + void command_drawPolyline(QRegExp re); + void command_drawRect(QRegExp re); + void command_drawRoundedRect(QRegExp re); + void command_drawRoundRect(QRegExp re); + void command_drawText(QRegExp re); + void command_drawStaticText(QRegExp re); + void command_drawTiledPixmap(QRegExp re); + void command_path_addEllipse(QRegExp re); + void command_path_addPolygon(QRegExp re); + void command_path_addRect(QRegExp re); + void command_path_addText(QRegExp re); + void command_path_arcTo(QRegExp re); + void command_path_closeSubpath(QRegExp re); + void command_path_createOutline(QRegExp re); + void command_path_cubicTo(QRegExp re); + void command_path_debugPrint(QRegExp re); + void command_path_lineTo(QRegExp re); + void command_path_moveTo(QRegExp re); + void command_region_addEllipse(QRegExp re); + void command_region_addRect(QRegExp re); + + // getters + void command_region_getClipRegion(QRegExp re); + void command_path_getClipPath(QRegExp re); + + // commands: surface begin/end + void command_surface_begin(QRegExp re); + void command_surface_end(QRegExp re); + + // commands: save/restore painter state + void command_restore(QRegExp re); + void command_save(QRegExp re); + + // commands: pixmap/image + void command_pixmap_load(QRegExp re); + void command_pixmap_setMask(QRegExp re); + void command_bitmap_load(QRegExp re); + void command_image_convertToFormat(QRegExp re); + void command_image_load(QRegExp re); + void command_image_setColor(QRegExp re); + void command_image_setColorCount(QRegExp re); + + // commands: transformation + void command_resetMatrix(QRegExp re); + void command_translate(QRegExp re); + void command_rotate(QRegExp re); + void command_rotate_x(QRegExp re); + void command_rotate_y(QRegExp re); + void command_scale(QRegExp re); + void command_mapQuadToQuad(QRegExp re); + void command_setMatrix(QRegExp re); + + // attributes + QPainter *m_painter; + QPainter *m_surface_painter; + QImage m_surface_image; + QPixmap m_surface_pixmap; +#ifndef QT_NO_OPENGL + QGLPixelBuffer *m_surface_pbuffer; +#endif + QRectF m_surface_rect; + QStringList m_commands; + QString m_currentCommand; + int m_currentCommandIndex; + QString m_filepath; + QMap m_blockMap; + QMap m_pathMap; + QMap m_pixmapMap; + QMap m_imageMap; + QMap m_regionMap; + QGradientStops m_gradientStops; + QGradient::Spread m_gradientSpread; + QGradient::CoordinateMode m_gradientCoordinate; + bool m_abort; + int m_width; + int m_height; + + bool m_verboseMode; + DeviceType m_type; + bool m_checkers_background; + bool m_shouldDrawText; + + QVector m_controlPoints; + + // painter functionalities string tables + static const char *brushStyleTable[]; + static const char *penStyleTable[]; + static const char *fontWeightTable[]; + static const char *fontHintingTable[]; + static const char *clipOperationTable[]; + static const char *spreadMethodTable[]; + static const char *coordinateMethodTable[]; + static const char *compositionModeTable[]; + static const char *imageFormatTable[]; + static const char *sizeModeTable[]; + static int translateEnum(const char *table[], const QString &pattern, int limit); + + // utility + template T image_load(const QString &filepath); + + // commands dictionary management + static void staticInit(); + +public: + struct PaintCommandInfos + { + PaintCommandInfos(QString id, void (PaintCommands::*p)(QRegExp), QRegExp r, QString sy, QString sa) + : identifier(id) + , regExp(r) + , syntax(sy) + , sample(sa) + , paintMethod(p) + {} + PaintCommandInfos(QString title) + : identifier(title), paintMethod(0) {} + bool isSectionHeader() const { return paintMethod == 0; } + QString identifier; + QRegExp regExp; + QString syntax; + QString sample; + void (PaintCommands::*paintMethod)(QRegExp); + }; + + static PaintCommandInfos *findCommandById(const QString &identifier) { + for (int i=0; i s_commandInfoTable; + static QList > s_enumsTable; + static QMultiHash s_commandHash; +}; + +#endif // PAINTCOMMANDS_H diff --git a/tests/auto/integrationtests/lancelot/scripts/aliasing.qps b/tests/auto/integrationtests/lancelot/scripts/aliasing.qps new file mode 100644 index 0000000000..59878f9c4d --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/aliasing.qps @@ -0,0 +1,156 @@ + +path_moveTo convexPath 25 0 +path_lineTo convexPath 50 50 +path_lineTo convexPath 25 25 +path_lineTo convexPath 0 50 +path_closeSubpath convexPath + +pixmap_load border.png pixmap + +setRenderHint LineAntialiasing false +translate 10 10 + +begin_block drawing + setPen black 1 + setBrush 7f7fff + drawPath convexPath + + setFont "monospace" 8 + setPen black + drawText 0 68 "QwErTy@" + + + setPen black 1 + setBrush 7f7fff + drawRect 0 80 10 5 + + setPen black 1 + setBrush noBrush + drawRect 20 80 10 5 + + setPen noPen + setBrush 7f7fff + drawRect 40 80 10 5 + + + setPen black 2 + setBrush 7f7fff + drawRect 0 90 10 5 + + setPen black 2 + setBrush noBrush + drawRect 20 90 10 5 + + setPen noPen + setBrush 7f7fff + drawRect 40 90 10 5 + + + setPen black 3 + setBrush 7f7fff + drawRect 0 100 10 5 + + setPen black 3 + setBrush noBrush + drawRect 20 100 10 5 + + setPen noPen + setBrush 7f7fff + drawRect 40 100 10 5 + + + setPen black 1 + setBrush noBrush + drawLine 10 110 20 120 + drawLine 30 120 40 110 + + setPen black 2 + setBrush noBrush + drawLine 10 120 20 130 + drawLine 30 130 40 120 + + setPen black 3 + setBrush noBrush + drawLine 10 130 20 140 + drawLine 30 140 40 130 + + drawPixmap pixmap 0 150 + + setRenderHint SmoothPixmapTransform false + drawPixmap pixmap 20 150 15 15 0 0 10 10 + +end_block + +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +drawText 15 185 "0.0" + +resetMatrix +translate 70.2 10.2 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.2 -0.2 +drawText 15 185 "0.2" + + +resetMatrix +translate 130.4 10.4 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.4 -0.4 +drawText 15 185 "0.4" + + +resetMatrix +translate 190.5 10.5 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.5 -0.5 +drawText 15 185 "0.5" + + +resetMatrix +translate 250.6 10.6 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.6 -0.6 +drawText 15 185 "0.6" + + +resetMatrix +translate 310.8 10.8 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +translate -0.8 -0.8 +drawText 15 185 "0.8" + + +resetMatrix +translate 371 11 +setRenderHint LineAntialiasing false +repeat_block drawing +translate 0 180 +setRenderHint LineAntialiasing true +repeat_block drawing +drawText 15 185 "1.0" + + +resetMatrix +drawText 430 95 "Aliased" +drawText 430 275 "Anti-Aliased" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/arcs.qps b/tests/auto/integrationtests/lancelot/scripts/arcs.qps new file mode 100644 index 0000000000..8a7a468df1 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/arcs.qps @@ -0,0 +1,68 @@ +# Version: 1 +# CheckVsReference: 5 + +setRenderHint LineAntialiasing + +setPen red + +drawEllipse 0 0 600 400 + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 0 10 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 20 30 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 60 45 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 115 60 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 0 0 600 400 180 90 +path_closeSubpath arcs + +path_moveTo arcs 590 200 +path_arcTo arcs 10 10 580 380 0 360 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 0 -10 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -20 -30 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -60 -45 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -115 -60 +path_closeSubpath arcs + +path_moveTo arcs 300 200 +path_arcTo arcs 20 20 560 360 -180 -90 +path_closeSubpath arcs + +setPen black 1 solidline +setBrush #3f00ff00 +drawPath arcs + +# Then again with a matrix set... +translate 200 400 +rotate 10 +scale 0.5 0.5 +setPen red +setBrush nobrush +drawEllipse 0 0 600 400 + +setPen black 1 solidline +setBrush #3f0000ff +drawPath arcs \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/arcs2.qps b/tests/auto/integrationtests/lancelot/scripts/arcs2.qps new file mode 100644 index 0000000000..411ff08014 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/arcs2.qps @@ -0,0 +1,47 @@ +# Version: 1 +# CheckVsReference: 5 + +drawArc 100 100 100 100 0 1440 +drawArc 100 100 100 100 1440 1440 +drawArc 100 100 100 100 2880 1440 +drawArc 100 100 100 100 4320 1440 + +drawArc 100 200 100 100 0 -1440 +drawArc 100 200 100 100 -1440 -1440 +drawArc 100 200 100 100 -2880 -1440 +drawArc 100 200 100 100 -4320 -1440 + +drawArc 200 100 100 100 720 1440 +drawArc 200 100 100 100 2160 1440 +drawArc 200 100 100 100 3600 1440 +drawArc 200 100 100 100 5040 1440 + +drawArc 200 200 100 100 -720 -1440 +drawArc 200 200 100 100 -2160 -1440 +drawArc 200 200 100 100 -3600 -1440 +drawArc 200 200 100 100 -5040 -1440 + + +drawArc 300 100 100 100 3840 480 +drawArc 300 200 100 100 -3840 -480 + +drawArc 300 100 100 100 1600 1340 + +setPen black +drawArc 400 100 200 200 0 5760 +setPen white +drawArc 400 100 200 200 960 960 +drawArc 400 100 200 200 2880 960 +drawArc 400 100 200 200 4800 960 + +setPen black +drawArc 100 350 300 300 160 5760 +drawArc 100 350 300 300 320 5760 +drawArc 100 350 300 300 1920 5760 +drawArc 100 350 300 300 2080 5760 +drawArc 100 350 300 300 3680 5760 +drawArc 100 350 300 300 3840 5760 +drawArc 100 350 300 300 5440 5760 +drawArc 100 350 300 300 5600 5760 +setPen white +drawArc 100 350 300 300 0 5760 diff --git a/tests/auto/integrationtests/lancelot/scripts/background.qps b/tests/auto/integrationtests/lancelot/scripts/background.qps new file mode 100644 index 0000000000..000cfcdd91 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/background.qps @@ -0,0 +1,136 @@ +# Version: 1 +# CheckVsReference: 5% + +translate 10 30 +setBackground 7f7fff +setBackgroundMode Transparent +setPen ff7f7f + +path_moveTo path 0 0 +path_lineTo path 25 0 +path_cubicTo path 50 0 25 25 25 50 +path_lineTo path 0 50 + +bitmap_load bitmap.png bitmap + +begin_block drawing + save + drawRect 0 0 50 50 + + translate 60 0 + drawEllipse 0 0 50 50 + + translate 60 0 + drawPolygon [0 0 50 0 25 50 25 25] + + translate 60 0 + drawPath path + + translate 60 0 + drawPie 0 0 50 50 1440 2000 + + translate 60 0 + drawChord 0 0 50 50 1440 2000 + + translate 60 0 + drawLine 0 0 50 0 + drawLine 0 0 50 50 + drawLine 0 0 0 50 + + translate 60 0 + drawPolyline [0 0 50 0 25 50 25 25] + + translate 60 0 + drawArc 0 0 50 50 1440 2000 + + translate 60 0 + drawText 0 10 "Jambi-Bambi" + + translate 80 0 + drawPixmap bitmap 0 0 + restore + + save + setRenderHint Antialiasing + translate 5 55 + drawRect 0 0 50 50 + + translate 60 0 + drawEllipse 0 0 50 50 + + translate 60 0 + drawPolygon [0 0 50 0 25 50 25 25] + + translate 60 0 + drawPath path + + translate 60 0 + drawPie 0 0 50 50 1440 2000 + + translate 60 0 + drawChord 0 0 50 50 1440 2000 + + translate 60 0 + drawLine 0 0 50 0 + drawLine 0 0 50 50 + drawLine 0 0 0 50 + + translate 60 0 + drawPolyline [0 0 50 0 25 50 25 25] + + translate 60 0 + drawArc 0 0 50 50 1440 2000 + + translate 60 0 + drawText 0 10 "Jambi-Bambi" + + translate 80 0 + drawPixmap bitmap 0 0 + restore +end_block + +translate 0 160 +setBackgroundMode Transparent +setPen ff7f7f 0 dotline flatcap beveljoin +repeat_block drawing + +translate 0 160 +setBackgroundMode Opaque +setPen ff7f7f 0 dotline flatcap beveljoin +repeat_block drawing + +translate 0 160 +setBackgroundMode Transparent +setPen ff7f7f 4 dashline flatcap beveljoin +repeat_block drawing + +translate 0 160 +setBackgroundMode OpaqueMode +setPen ff7f7f 4 dashline flatcap beveljoin +repeat_block drawing + +resetMatrix + +translate 5 5 + +setBrush nobrush +setPen black +setBackgroundMode transparent +drawText 10 15 "TransparentMode with solid 0-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "TransparentMode with dotted 0-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "OpaqueMode with dotted 0-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "TransparentMode with dotted 4-width pen" +drawRect 0 0 685 135 + +translate 0 160 +drawText 10 15 "OpaqueMode with solid 4-width pen" +drawRect 0 0 685 135 diff --git a/tests/auto/integrationtests/lancelot/scripts/background_brush.qps b/tests/auto/integrationtests/lancelot/scripts/background_brush.qps new file mode 100644 index 0000000000..ca1f944964 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/background_brush.qps @@ -0,0 +1,5 @@ +# Version: 1 +# CheckVsReference: 5% + +setBrush #00ff00 crosspattern +import "background.qps" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/beziers.qps b/tests/auto/integrationtests/lancelot/scripts/beziers.qps new file mode 100644 index 0000000000..9b47cd05ac --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/beziers.qps @@ -0,0 +1,147 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint LineAntialiasing + +translate 20 20 +path_moveTo fullSize 0 0 +path_cubicTo fullSize 200 100 -100 100 100 0 + +path_moveTo fullSize 0 200 +path_cubicTo fullSize 0 100 100 100 100 200 + +path_moveTo fullSize 0 250 +path_cubicTo fullSize 50 200 50 200 100 250 +drawPath fullSize + +translate 110 0 +scale 10 10 +path_moveTo medSize 0 0 +path_cubicTo medSize 20 10 -10 10 10 0 + +path_moveTo medSize 0 20 +path_cubicTo medSize 0 10 10 10 10 20 + +path_moveTo medSize 0 25 +path_cubicTo medSize 5 20 5 20 10 25 +drawPath medSize + +resetMatrix +translate 240 20 +scale 100 100 +path_moveTo smallSize 0 0 +path_cubicTo smallSize 2 1 -1 1 1 0 + +path_moveTo smallSize 0 2 +path_cubicTo smallSize 0 1 1 1 1 2 + +path_moveTo smallSize 0 2.5 +path_cubicTo smallSize 0.5 2 0.5 2 1 2.5 +drawPath smallSize + +resetMatrix +translate 20 300 +drawPath medSize + +resetMatrix +translate 250 -100 +path_moveTo maxSize 0 500 +path_cubicTo maxSize 1000 0 -500 0 500 500 +drawPath maxSize + +setRenderHint Antialiasing off +resetMatrix + +path_moveTo path1 0 0 +path_cubicTo path1 10 10 0 10 10 0 + +path_moveTo path2 0 0 +path_cubicTo path2 15 15 -5 15 10 0 + +path_moveTo path3 0 0 +path_cubicTo path3 20 20 -10 20 10 0 + +path_moveTo path4 0 0 +path_cubicTo path4 0 5 10 10 0 15 + +path_moveTo path5 0 10 +path_cubicTo path5 10 10 -10 20 0 0 + +path_moveTo path6 0 0 +path_cubicTo path6 10 5 -10 10 0 15 + +setPen black 2 +setBrush nobrush + +translate 10 500 +scale 3 3 +begin_block paths +save +drawPath path1 +translate 20 0 +drawPath path2 +translate 20 0 +drawPath path3 +translate 20 0 +drawPath path4 +translate 20 0 +drawPath path5 +translate 20 0 +drawPath path6 +restore +end_block + +setPen nopen +setBrush black + +translate 0 20 +repeat_block paths + +setRenderHint Antialiasing + +setPen black 2 +setBrush nobrush + +translate 120 -20 +repeat_block paths + +setPen nopen +setBrush black + +translate 0 20 +repeat_block paths + +resetMatrix +path_moveTo miterPath 20 0 +path_cubicTo miterPath 20 20 0 0 1 0 +path_lineTo miterPath -1 -0.2 + +setBrush nobrush + +translate 50 660 +scale 5 5 + +setPen black 4 solidline flatcap miterjoin +drawPath miterPath +setPen red 0 +drawPath miterPath + +path_moveTo miterPath2 21 0.2 +path_lineTo miterPath2 19 0 +path_cubicTo miterPath2 20 0 0 20 0 0 + +translate 30 0 +setPen black 4 solidline flatcap miterjoin +drawPath miterPath2 +setPen red 0 +drawPath miterPath2 + +path_moveTo wonkyPath 0 0 +path_cubicTo wonkyPath 5 15 20 0 17 0 + +translate 30 0 +setPen black 4 solidline flatcap miterjoin +drawPath wonkyPath +setPen red 0 +drawPath wonkyPath diff --git a/tests/auto/integrationtests/lancelot/scripts/bitmaps.qps b/tests/auto/integrationtests/lancelot/scripts/bitmaps.qps new file mode 100644 index 0000000000..a816b9d497 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/bitmaps.qps @@ -0,0 +1,166 @@ +# Version: 1 +# CheckVsReference: 5% + + +#setRenderHint SmoothPixmapTransform + +translate 10 50 +setBackground ff7f7f +setPen 3f3f9f + +bitmap_load dome_mono.png the_pixmap + +save + # Draw with opaque pen/bg in transparent/opaque mode + setBackgroundMode Transparent + drawPixmap the_pixmap 0 0 + setBackgroundMode Opaque + drawPixmap the_pixmap 110 0 + + translate 220 0 + + # Draw with alpha pen/bg in transparent/opaque mode + save + setBackground 7fff7f7f + setPen 7f3f3f9f + setBackgroundMode Transparent + drawPixmap the_pixmap 0 0 + setBackgroundMode Opaque + drawPixmap the_pixmap 110 0 + restore + + translate 220 0 + + # Draw with rotated opaque pen/bg in transparent/opaque mode + setBackgroundMode Transparent + save + translate 50 50 + rotate 10 + translate -50 -50 + drawPixmap the_pixmap 0 0 + restore + setBackgroundMode Opaque + translate 110 0 + save + translate 50 50 + rotate 10 + translate -50 -50 + drawPixmap the_pixmap 0 0 + restore +restore + +translate 0 150 + +save + setBackgroundMode Transparent + drawTiledPixmap the_pixmap 0 0 200 100 + setBackgroundMode Opaque + drawTiledPixmap the_pixmap 210 0 200 100 + + translate 440 -10 + save + rotate 10 + drawTiledPixmap the_pixmap 0 0 200 100 + restore +restore + +translate 0 150 +save + setBackgroundMode Transparent + drawTiledPixmap the_pixmap 0 0 200 100 10 20 + setBackgroundMode Opaque + drawTiledPixmap the_pixmap 210 0 200 100 10 20 + + translate 440 -10 + save + rotate 10 + drawTiledPixmap the_pixmap 0 0 200 100 10 20 + restore +restore + + +pixmap_setMask the_pixmap mask_100.png +drawPixmap the_pixmap 0 150 +setBackgroundMode Opaque +drawPixmap the_pixmap 110 150 + +translate 220 150 +save + translate 50 50 + rotate 10 + translate -50 -50 + setBackgroundMode Transparent + drawPixmap the_pixmap 0 0 +restore + +translate 110 0 +save + translate 50 50 + rotate 10 + translate -50 -50 + setBackgroundMode Opaque + drawPixmap the_pixmap 0 0 +restore + +resetMatrix +translate 10 650 +bitmap_load dome_mono.png the_bitmap +setBackgroundMode Transparent + +begin_block draw_subrected + drawPixmap the_bitmap 0 0 50 50 0 0 50 50 + drawPixmap the_bitmap 50 0 50 50 50 0 50 50 + drawPixmap the_bitmap 0 50 50 50 0 50 50 50 + drawPixmap the_bitmap 50 50 50 50 50 50 50 50 +end_block + +translate 110 0 +setBackgroundMode Opaque +repeat_block draw_subrected + +translate 110 0 +save + translate 20 -10 + rotate 10 + setBackgroundMode Transparent + repeat_block draw_subrected +restore + +translate 110 0 +save + translate 20 -10 + rotate 10 + setBackgroundMode Opaque + repeat_block draw_subrected +restore + +# Some helpful texts + +resetMatrix +setPen black +drawText 10 40 "Transparent" +drawText 120 40 "Opaque" +drawText 230 40 "Trans w/alpha" +drawText 340 40 "Opaque w/alpha" +drawText 450 40 "Trans w/xform" +drawText 560 40 "Opaque w/xform" + +drawText 10 190 "Transparent tiled" +drawText 220 190 "Opaque tiled" +drawText 440 190 "Opaque w/xform" + +drawText 10 340 "Transparent tiled w/offset" +drawText 220 340 "Opaque tiled w/offset" +drawText 440 340 "Opaque w/xform w/offset" + +drawText 10 490 "Trans masked" +drawText 120 490 "Opaque masked" +drawText 230 490 "masked w/xform" +drawText 340 490 "masked w/xform" + +drawText 10 640 "Subrected" +drawText 110 640 "Subrected opaque" +drawText 220 640 "subrect w/xform" +drawText 330 640 "subrect w/xform opaque" + + diff --git a/tests/auto/integrationtests/lancelot/scripts/borderimage.qps b/tests/auto/integrationtests/lancelot/scripts/borderimage.qps new file mode 100644 index 0000000000..ebd4f4d249 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/borderimage.qps @@ -0,0 +1,120 @@ +# Version: 1 +# CheckVsReference: 10% + +image_load borderimage.png borderimage +translate -128 -128 +begin_block draw_border +# top +drawImage borderimage 0 0 16 16 0 0 16 16 +drawImage borderimage 16 0 36 16 16 0 32 16 +drawImage borderimage 52 0 16 16 48 0 16 16 +# sides +drawImage borderimage 0 16 16 16 0 16 16 32 +drawImage borderimage 52 16 16 16 48 16 16 32 +#bottom +drawImage borderimage 0 32 16 16 0 48 16 16 +drawImage borderimage 16 32 36 16 16 48 32 16 +drawImage borderimage 52 32 16 16 48 48 16 16 +end_block draw_border +resetMatrix +begin_block draw_column +translate 1 1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +translate 0.1 64.1 +repeat_block draw_border +end_block draw_column +setRenderHint Antialiasing +resetMatrix +translate 72 0 +repeat_block draw_column +resetMatrix +scale 1.25 1.25 +translate 144 0 +repeat_block draw_border +resetMatrix +scale 1.25 1.25 +translate 246 0 +rotate 30 +repeat_block draw_border +setRenderHint SmoothPixmapTransform +resetMatrix +scale 1.25 1.25 +translate 144 120 +repeat_block draw_border +resetMatrix +scale 1.25 1.25 +translate 246 120 +rotate 30 +repeat_block draw_border +resetMatrix +translate 215 260 +scale 3.55 3.55 +rotate 30 +repeat_block draw_border +resetMatrix +setRenderHint SmoothPixmapTransform off +setRenderHint Antialiasing off +translate 480 627 +rotate 180 +repeat_block draw_column +resetMatrix +setRenderHint Antialiasing +translate 552 627 +rotate 180 +repeat_block draw_column +resetMatrix +setRenderHint Antialiasing off +translate 200.1 520.1 +begin_block one_pixel_border +drawImage borderimage 0 0 16 16 0 0 16 16 +drawImage borderimage 16 0 64 16 16 0 1 1 +drawImage borderimage 80 0 16 16 48 0 16 16 +drawImage borderimage 0 16 16 64 16 0 1 1 +drawImage borderimage 80 16 16 64 16 0 1 1 +drawImage borderimage 0 80 16 16 0 48 16 16 +drawImage borderimage 16 80 64 16 16 0 1 1 +drawImage borderimage 80 80 16 16 48 48 16 16 +end_block one_pixel_border +resetMatrix +translate 205.1 626.1 +scale 0.4 0.4 +repeat_block one_pixel_border +resetMatrix +translate 255.1 624.1 +scale 0.4 0.4 +rotate 10 +repeat_block one_pixel_border +resetMatrix +setPen red +drawRect 0 0 70 680 +drawText 10 670 "aa off" +drawRect 72 0 70 680 +drawText 80 670 "aa on" +drawRect 409 0 70 680 +drawText 419 650 "rot 180" +drawText 419 670 "aa off" +drawRect 481 0 70 680 +drawText 491 650 "rot 180" +drawText 491 670 "aa on" +drawRect 164 0 224 124 +drawText 174 114 "smoothpixmaptransform off" +drawRect 164 128 224 134 +drawText 174 252 "smoothpixmaptransform on" +drawRect 200 520 97 188 +drawText 210 698 "1x1 edges" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/brush_pens.qps b/tests/auto/integrationtests/lancelot/scripts/brush_pens.qps new file mode 100644 index 0000000000..b9a2bc0ada --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/brush_pens.qps @@ -0,0 +1,104 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect p 0 0 75 75 +path_addEllipse p 25 25 75 75 + +translate 10 10 + +begin_block setup_gradient + gradient_clearStops + gradient_appendStop 0 red + gradient_appendStop 0.1 blue + gradient_appendStop 0.2 yellow + gradient_appendStop 0.3 cyan + gradient_appendStop 0.4 magenta + gradient_appendStop 0.5 green + gradient_appendStop 0.6 black + gradient_appendStop 0.7 indianred + gradient_appendStop 0.8 white + gradient_appendStop 0.9 orange + gradient_appendStop 1 blue + gradient_setLinear 0 0 100 100 +end_block + +setPen brush 0 +setBrush nobrush + +begin_block drawing + save + drawLine 0 0 100 100 + + translate 0 100 + drawPath p + + translate 0 110 + drawRect 0 0 100 100 + + translate 0 110 + drawPolyline [0 0 100 0 50 50] + + drawPoint 40 40 + drawPoint 41 40 + drawPoint 42 40 + drawPoint 43 40 + drawPoint 44 40 + drawPoint 45 40 + drawPoint 46 40 + drawPoint 47 40 + drawPoint 48 40 + drawPoint 49 40 + drawPoint 50 40 + + restore +end_block + +save + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore + + setBrush dome_rgb32.png + setPen brush 0 + setBrush nobrush + + translate 110 0 + repeat_block drawing + + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore +restore + +translate 0 0 + +save + repeat_block setup_gradient + setPen brush 5 + setBrush nobrush + translate 0 350 + repeat_block drawing + + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore + + setBrush dome_rgb32.png + setPen brush 5 + setBrush nobrush + + translate 110 0 + repeat_block drawing + + translate 110 0 + save + setRenderHint Antialiasing + repeat_block drawing + restore +restore \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/brushes.qps b/tests/auto/integrationtests/lancelot/scripts/brushes.qps new file mode 100644 index 0000000000..82cbff48b9 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/brushes.qps @@ -0,0 +1,79 @@ +# Version: 1 +# CheckVsReference: 5% + +# Fill the background +drawRect 0 0 width height + +setRenderHint Antialiasing +setRenderHint SmoothPixmapTransform + +translate 10 10 +# Draw all the pattern types as 40x40 rects using green, transparent background +begin_block drawrects +setBrush green Dense1Pattern +drawRect 0 0 40 40 +setBrush green Dense2Pattern +drawRect 40 0 40 40 +setBrush green Dense3Pattern +drawRect 80 0 40 40 +setBrush green Dense4Pattern +drawRect 120 0 40 40 +setBrush green Dense5Pattern +drawRect 160 0 40 40 +setBrush green Dense6Pattern +drawRect 200 0 40 40 +setBrush green Dense7Pattern +drawRect 240 0 40 40 +setBrush green HorPattern +drawRect 280 0 40 40 +setBrush green VerPattern +drawRect 320 0 40 40 +setBrush green CrossPattern +drawRect 360 0 40 40 +setBrush green BDiagPattern +drawRect 400 0 40 40 +setBrush green FDiagPattern +drawRect 440 0 40 40 +setBrush green DiagCrossPattern +drawRect 480 0 40 40 +setBrush green SolidPattern +drawRect 520 0 40 40 +setBrush green NoBrush +drawRect 560 0 40 40 +gradient_setLinear 0 0 0 40 +drawRect 600 0 40 40 +setBrush face.png +drawRect 640 0 80 40 +end_block + +# Switch to opaque mode +setBackground #7fff7f +setBackgroundMode OpaqueMode +translate 0 50 + +# Draw all the pattern types as 40x40 rects using green, opaque background +repeat_block drawrects + +translate 50 50 +rotate 10 + + +setBackgroundMode TransparentMode +repeat_block drawrects +setBackgroundMode OpaqueMode +translate 0 40 +repeat_block drawrects + + +setBrush dot.png +setPen nopen +resetMatrix +drawRect 0 200 50 50 +drawRect 50 200 50 50 + +setPen red +setBrushOrigin 0 250 +drawRect 0 250 50 50 +setBrushOrigin 50 250 +drawRect 50 250 50 50 + diff --git a/tests/auto/integrationtests/lancelot/scripts/clippaths.qps b/tests/auto/integrationtests/lancelot/scripts/clippaths.qps new file mode 100644 index 0000000000..fba89784df --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/clippaths.qps @@ -0,0 +1,60 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect hor 0 0 50 10 +path_addRect ver 0 0 10 50 + +translate 10 10 +setPen NoPen + +begin_block clipping +save + + setBrush 0x7f7fff + save + setClipPath hor + drawRect 0 0 100 100 + + setClipPath ver IntersectClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipPath hor + drawRect 0 0 100 100 + + setClipPath ver ReplaceClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipPath hor + drawRect 0 0 100 100 + + setClipPath ver UniteClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + +restore +end_block + +translate 300 0 +setRenderHint Antialiasing +repeat_block clipping + +translate -300 100 +setRenderHint Antialiasing false +scale 1.2 1.2 +repeat_block clipping + +translate 300 0 +setRenderHint Antialiasing +setRenderHint SmoothPixmapTransform +repeat_block clipping + + diff --git a/tests/auto/integrationtests/lancelot/scripts/clipping.qps b/tests/auto/integrationtests/lancelot/scripts/clipping.qps new file mode 100644 index 0000000000..3694ff2ba7 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/clipping.qps @@ -0,0 +1,182 @@ +# Version: 1 +# CheckVsReference: 5% + +region_addRect clip 50 0 90 190 +region_addRect clip 0 50 180 90 + +region_addRect clip2 30 30 60 60 + +region_addRect clip3 10 10 60 60 + +path_cubicTo path 90 0 50 50 90 90 +path_cubicTo path 0 90 50 50 0 0 + +path_addRect path2 0 0 90 90 +path_moveTo path2 90 45 +path_arcTo path2 0 0 90 90 0 -360 + +path_addRect emptypath 0 0 0 0 +region_addRect emptyregion 0 0 0 0 + +# Normal clip rect +setClipRect 0 0 50 150 +begin_block repaint +save +setBrush red +setPen nopen +resetMatrix +region_getClipRegion tmpclip +path_getClipPath tmpclippath +drawRect 0 0 width height +setBrush #3f0000ff +setClipRegion tmpclip +drawRect 0 0 width height +setClipPath tmpclippath +setBrush #3f00ff00 +drawRect 0 0 width height +restore +end_block + +# Rotated clip rect +translate 100 0 +rotate 10 +setClipRect 0 0 50 150 +repeat_block repaint + +# simple clip region +resetMatrix +translate 0 200 +setClipRegion clip +repeat_block repaint + +# simle rotated clip region +translate 250 -10 +rotate 10 +setClipRegion clip +repeat_block repaint + +# verify that clip is not xformed with painter +resetMatrix +translate 200 0 +setClipRegion clip +rotate 30 +setBrush red +setPen nopen +drawRect 0 0 width height + +resetMatrix +translate 0 400 +save +setClipRegion clip +setClipRegion clip2 IntersectClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip +setClipRegion clip2 IntersectClip +restore + +translate 100 0 +save +setClipRegion clip3 +setClipRegion clip2 UniteClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip3 +setClipRegion clip2 UniteClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +repeat_block repaint +translate 50 100 +rotate 45 +setClipPath path +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipPath path2 IntersectClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipPath path +setClipPath path2 IntersectClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipPath path2 UniteClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipPath path +setClipPath path2 UniteClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipRegion clip3 IntersectClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip3 +setClipPath path IntersectClip +repeat_block repaint +restore + +translate 100 0 +save +setClipPath path +setClipRegion clip3 UniteClip +repeat_block repaint +translate 0 100 +rotate 10 +setClipRegion clip3 +setClipPath path UniteClip +repeat_block repaint +restore + +# test that an empty region is not drawn. +resetMatrix +setClipRegion emptyregion +setBrush #3f00ff00 +drawRect 0 0 300 300 +drawText 50 50 "Text should be clipped away by region" +setClipping false + +setClipPath emptypath +setBrush #3fffff00 +drawRect 50 50 300 300 +drawText 70 80 "Text should be clipped away by path" + +# Test that we can extract a clipregion when a matrix is set too +resetMatrix +translate 500 10 +scale 2 1 +setBrush blue +setClipping false +rotate 5 +drawRect 0 0 100 100 +setClipRect 0 0 100 100 +resetMatrix +rotate 10 +region_getClipRegion xclip +setClipRegion xclip +resetMatrix +setBrush #7f00ff00 +drawRect 0 0 width height + +# the below used to assert in debug mode +setClipRect 10 10 20 20 +setClipping false +setClipping true \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/clipping_state.qps b/tests/auto/integrationtests/lancelot/scripts/clipping_state.qps new file mode 100644 index 0000000000..a29d3738c8 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/clipping_state.qps @@ -0,0 +1,47 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect path1 10 10 50 50 +path_addRect path2 30 30 50 50 +# enable/disable a clip path +setPen nopen +setBrush red +setClipPath path1 +setClipPath path2 UniteClip +drawRect 0 0 100 100 +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipping true +setBrush #6300ff00 +drawRect 0 0 100 100 +# enable/disable noclip +translate 150 0 +setClipPath path1 NoClip +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipping true +setBrush #6300ff00 +drawRect 25 25 50 50 +# enable/disable full clipping +translate 150 0 +path_addRect path3 0 0 10 10 +path_addRect path4 20 20 10 10 +setClipPath path3 +setClipPath path4 IntersectClip +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipping true +setBrush #6300ff00 +drawRect 25 25 50 50 +# disable clipping followed by setClipRect +translate 150 0 +setClipRect 0 0 50 50 ReplaceClip +setClipping false +setBrush #630000ff +drawRect 0 0 100 100 +setClipRect 25 25 75 75 IntersectClip +setBrush #6300ff00 +drawRect 25 25 50 50 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/cliprects.qps b/tests/auto/integrationtests/lancelot/scripts/cliprects.qps new file mode 100644 index 0000000000..0d28b035b4 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/cliprects.qps @@ -0,0 +1,59 @@ +# Version: 1 +# CheckVsReference: 5% + + + +translate 10 10 +setPen NoPen + +begin_block clipping +save + + setBrush 0x7f7fff + save + setClipRect 0 0 50 10 + drawRect 0 0 100 100 + + setClipRect 0 0 10 50 IntersectClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipRect 0 0 50 10 + drawRect 0 0 100 100 + + setClipRect 0 0 10 50 ReplaceClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + + translate 100 0 + save + setClipRect 0 0 50 10 + drawRect 0 0 100 100 + + setClipRect 0 0 10 50 UniteClip + setBrush black CrossPattern + drawRect 0 0 100 100 + restore + +restore +end_block + +translate 300 0 +setRenderHint Antialiasing +repeat_block clipping + +translate -300 100 +setRenderHint Antialiasing false +scale 1.2 1.2 +repeat_block clipping + +translate 300 0 +setRenderHint Antialiasing +setRenderHint SmoothPixmapTransform +repeat_block clipping + + diff --git a/tests/auto/integrationtests/lancelot/scripts/conical_gradients.qps b/tests/auto/integrationtests/lancelot/scripts/conical_gradients.qps new file mode 100644 index 0000000000..2e897b1813 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/conical_gradients.qps @@ -0,0 +1,85 @@ +# Version: 1 +# CheckVsReference: 5% + +path_addRect path 300 0 80 80 +path_addEllipse path 340 40 60 60 + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setConical 40 40 50 +drawRect 0 0 100 100 + +gradient_setConical 140 40 230 +drawEllipse 100 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setConical 240 40 50 +drawPolygon [200 0 290 0 250 99] + +gradient_setConical 340 40 230 +drawPath path + +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Some helpful info perhaps? +resetMatrix +setPen black + +drawText 410 50 "No XForm" +drawText 410 200 "scale 1x2" +drawText 410 300 "brush transform" +drawText 10 450 "50 deg" +drawText 110 450 "230 deg" +drawText 210 450 "50 deg w/alpha " +drawText 310 450 "230 deg w/alpha" + +setPen 3f000000 +setBrush nobrush + +begin_block ellipse_draw + setClipRect 0 0 100 100 + drawEllipse 35 35 11 11 + save + translate 40 40 + rotate -50 + drawLine -100 0 100 0 + restore + translate 100 0 +end_block + +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw + +resetMatrix +translate 0 100 +scale 1 2 +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/conical_gradients_perspectives.qps b/tests/auto/integrationtests/lancelot/scripts/conical_gradients_perspectives.qps new file mode 100644 index 0000000000..a9c14f1ce7 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/conical_gradients_perspectives.qps @@ -0,0 +1,64 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint Antialiasing + +setPen #00ff00 + +translate 10 10 +# standard draw +begin_block gradient +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 0.9 cyan +gradient_appendStop 1 red + +gradient_setSpread PadSpread +gradient_setConical 140 140 100 +drawRect 0 0 300 300 +end_block gradient + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block gradient +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block gradient +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block gradient +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/dashes.qps b/tests/auto/integrationtests/lancelot/scripts/dashes.qps new file mode 100644 index 0000000000..649f56cf66 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/dashes.qps @@ -0,0 +1,268 @@ +# Version: 1 +# CheckVsReference: 5% + +translate 20 20 + +begin_block draw +save + save + setPen black 1 SolidLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 SolidLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 SolidLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 SolidLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 SolidLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + + translate 100 0 + save + setPen black 1 DotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 DotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + save + setPen black 1 DashLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DashLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 DashLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + + save + setPen black 1 DashDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DashDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 6 DashDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 6 DashDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + + save + setPen black 1 DashDotDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 DashDotDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 DashDotDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 DashDotDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 4 DashDotDotLine FlatCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 DashDotDotLine SquareCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 DashDotDotLine RoundCap BevelJoin + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + + translate 100 0 + + save + setPen black 1 SolidLine FlatCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine SquareCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 1 SolidLine RoundCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 2 SolidLine FlatCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine SquareCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 2 SolidLine RoundCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + + setPen black 4 SolidLine FlatCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 SolidLine SquareCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + setPen black 4 SolidLine RoundCap BevelJoin + pen_setDashPattern [1 4 9 4 27 4] + drawPolyline [0 0 80 0 80 30 40 20 0 30] + translate 0 40 + restore + +restore +end_block + +translate 0 400 +setRenderHint Antialiasing +repeat_block draw + +translate 0 -20 +drawText 30 0 "Solid" + +translate 100 0 +drawText 20 0 "DotLine" + +translate 100 0 +drawText 10 0 "DashLine" + +translate 100 0 +drawText 0 0 "DashDotLine" + +translate 100 0 +drawText 0 0 "DashDotDotLine" + +translate 100 0 +drawText 0 0 "CustomDashLine" + +resetMatrix + +translate 620 40 + +begin_block width_and_caps_texts + drawText 0 0 "Width=1, FlatCap" + translate 0 40 + drawText 0 0 "Width=1, SquareCap" + translate 0 40 + drawText 0 0 "Width=1, RoundCap" + translate 0 40 + drawText 0 0 "Width=2, FlatCap" + translate 0 40 + drawText 0 0 "Width=2, SquareCap" + translate 0 40 + drawText 0 0 "Width=2, RoundCap" + translate 0 40 + drawText 0 0 "Width=6, FlatCap" + translate 0 40 + drawText 0 0 "Width=6, SqareCap" + translate 0 40 + drawText 0 0 "Width=6, RoundCap" +end_block + +translate 0 80 +repeat_block width_and_caps_texts \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/degeneratebeziers.qps b/tests/auto/integrationtests/lancelot/scripts/degeneratebeziers.qps new file mode 100644 index 0000000000..fb223d5b1f --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/degeneratebeziers.qps @@ -0,0 +1,10 @@ +# Version: 1 +# CheckVsReference: 5% + +path_moveTo degenerate 3427.0918499999997948 3872.1318999999998596 +path_cubicTo degenerate 3427.0918499999997948 3872.1318999999994048 4729.4590867905308187 5176.8613451144155988 5389.9325499999995372 5837.8072499999998399 + +scale 0.05 0.05 +translate -2500 -3000 +setPen black 800 +drawPath degenerate \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/deviceclipping.qps b/tests/auto/integrationtests/lancelot/scripts/deviceclipping.qps new file mode 100644 index 0000000000..cedfc1e363 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/deviceclipping.qps @@ -0,0 +1,48 @@ +# Version: 1 +# CheckVsReference: 5% + +setBrush 0xff7f7f +setPen 0x7f0000 + +path_moveTo path -1000000 10000 +path_cubicTo path 100 100 100 150 150 400 +path_closeSubpath path + +begin_block drawing + + drawPath ellipse + + drawLine -1000000 200 200 200 + drawLine 200 -1000000 200 200 + drawLine 200 200 1000000 200 + drawLine 200 200 200 1000000 + drawLine -1000000 -1000000 200 200 + + drawPolygon [-1000000 100 100 -1000000 100 100] + drawRect 300 -500000 1000000 1000000 + + drawPath path + +end_block + +save +translate 20 20 +setBrush #0x7f7f7fff +setPen #0x7f00007f +repeat_block drawing + +translate 20 20 +setRenderHint Antialiasing +setBrush #0x7f7fff7f +setPen #0x7f007f00 +repeat_block drawing +restore + +setPen 0x00007f 2 +setRenderHint Antialiasing + +drawLine 0 -200 200 200 + +setPen 0x007f00 10 + +drawLine 0 -200 200 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/drawpoints.qps b/tests/auto/integrationtests/lancelot/scripts/drawpoints.qps new file mode 100644 index 0000000000..c02cd85737 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/drawpoints.qps @@ -0,0 +1,101 @@ +# Version: 1 +# CheckVsReference: 5% + +#setRenderHint Antialiasing + +setPen red 0 solidline +begin_block points +drawPoint 00 00 +drawPoint 10 00 +drawPoint 20 00 +drawPoint 30 00 +drawPoint 40 00 +drawPoint 50 00 +drawPoint 00 10 +drawPoint 10 10 +drawPoint 20 10 +drawPoint 30 10 +drawPoint 40 10 +drawPoint 50 10 +drawPoint 00 20 +drawPoint 10 20 +drawPoint 20 20 +drawPoint 30 20 +drawPoint 40 20 +drawPoint 50 20 +drawPoint 00 30 +drawPoint 10 30 +drawPoint 20 30 +drawPoint 30 30 +drawPoint 40 30 +drawPoint 50 30 +drawPoint 00 40 +drawPoint 10 40 +drawPoint 20 40 +drawPoint 30 40 +drawPoint 40 40 +drawPoint 50 40 +drawPoint 00 50 +drawPoint 10 50 +drawPoint 20 50 +drawPoint 30 50 +drawPoint 40 50 +drawPoint 50 50 +end_block points + +translate 100 0 +setPen blue 1 solidline +repeat_block points + +translate 100 0 +setPen green 5 solidline roundcap +repeat_block points + +resetMatrix + +translate 0 100 +scale 3 3 +setPen red 0 solidline roundcap +repeat_block points + +translate 60 0 +setPen blue 1 solidline roundcap +repeat_block points + +translate 60 0 +setPen green 5 solidline roundcap +repeat_block points + +resetMatrix + +translate 0 300 +scale 3 3 +setPen red 0 solidline flatcap +repeat_block points + +translate 60 0 +setPen blue 1 solidline flatcap +repeat_block points + +translate 60 0 +setPen green 5 solidline flatcap +repeat_block points + +resetMatrix +translate 10 500 +setPen black 1 solidline flatcap +drawPoint 0 0 +setPen black 2 solidline flatcap +drawPoint 3 0 +setPen black 3 solidline flatcap +drawPoint 8 0 +setPen black 4 solidline flatcap +drawPoint 15 0 +setPen black 5 solidline flatcap +drawPoint 24 0 +setPen black 6 solidline flatcap +drawPoint 35 0 +setPen black 7 solidline flatcap +drawPoint 48 0 +setPen black 8 solidline flatcap +drawPoint 63 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/ellipses.qps b/tests/auto/integrationtests/lancelot/scripts/ellipses.qps new file mode 100644 index 0000000000..e2cffd7f27 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/ellipses.qps @@ -0,0 +1,86 @@ +# Version: 1 +# CheckVsReference: 5% + + +surface_begin 0 0 600 600 +translate 0 50 + +setPen nopen +setBrush 0x7f000000 +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setRadial 20 20 220 200 + +drawEllipse 10 10 80 80 +drawEllipse 50 50 120 90 + +translate 100 0 +brushTranslate 40 20 +brushScale 0.25 0.25 + +setPen black + +drawEllipse 10 10 80 80 +setOpacity 0.5 +setCompositionMode SourceIn +drawEllipse 50 50 120 90 +setOpacity 1.0 +setRenderHint Antialiasing +setCompositionMode Xor +brushTranslate 70 0 +translate 100 0 +drawEllipse 10 10 80 80 + +setPen nopen +drawEllipse 50 50 120 90 + +setOpacity 0.7 +setBrush red +translate 100 0 +setCompositionMode SourceOver + +drawEllipse 10 10 80 80 + +setOpacity 0.6 +setPen black 5.0 +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 20 20 120 100 +drawEllipse 50 50 120 90 + + +translate 100 0 + +setOpacity 1.0 +drawEllipse 10 10 80 80 + +setCompositionMode SourceIn +setOpacity 0.7 +setPen black 3.0 +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 50 50 80 90 +drawEllipse 50 50 120 90 + +surface_end + +drawText 200 220 "Testing Ellipse drawing with varios combinations" +drawText 200 240 "of features such as brushes, pens and composition modes" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/filltest.qps b/tests/auto/integrationtests/lancelot/scripts/filltest.qps new file mode 100644 index 0000000000..2eeba2ecf6 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/filltest.qps @@ -0,0 +1,413 @@ +# Version: 1 +# CheckVsReference: 5% + +setPen nopen +setBrush red +translate 0 4 +begin_block polys +drawPolygon [0 0 2 -2 4 0] +drawPolygon [0 2 2 4 4 2] +end_block polys +translate 6 .5 +repeat_block polys +translate 6.5 0 +repeat_block polys +translate 6 .5 +repeat_block polys + +resetMatrix + +translate 0 12 +setPen black +drawPolygon [0 0 5 0 5 5 0 5] + +translate 10 0 +setPen nopen +drawPolygon [0 0 5 0 5 5 0 5] + +translate 10 0 +drawPolygon [0 0 5 0 5 5 0 5] + +setBrush black +path_addRect stroke -.5 -.5 6 6 +path_addRect stroke .5 .5 4 4 +drawPath stroke + +resetMatrix + +translate 0 65 + +setPen red +drawText 0 0 "path" +drawText 40 0 "rect" +drawText 80 0 "img" +drawText 120 0 "pix" +drawText 160 0 "brush" +setPen nopen + +translate 0 5 + +image_load border.png img +pixmap_load border.png pix + +path_addRect rect 0 0 10 10 +begin_block rects +drawPath rect +drawRect 40 0 10 10 +drawImage img 80 0 +drawPixmap pix 120 0 +setBrush border.png +drawRect 160 0 10 10 +setBrush black +end_block rects + +setPen red +drawText 180 10 "0.0" +setPen nopen + +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.1" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.2" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.3" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.4" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.5" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.6" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.7" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.8" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "0.9" +setPen nopen +translate 0.1 20 +repeat_block rects +setPen red +drawText 180 10 "1.0" +setPen nopen + +resetMatrix + +translate 0 400 + +setPen red +drawText 0 10 "path" +drawText 0 30 "rect" +drawText 0 50 "img" +drawText 0 70 "pix" +drawText 0 90 "brush" +drawText 0 110 "stroke" +drawText 0 130 "scale" +drawText 0 170 "rotate" +setPen nopen + +translate 50 0 + +begin_block rects +drawPath rect +drawRect 0 20 10 10 +drawImage img 0 40 +drawPixmap pix 0 60 +save +setBrush border.png +drawRect 0 80 10 10 +translate 0 100 +setBrush red +setPen black +drawRect 0 0 10 10 +setBrush border.png +setPen nopen +translate 0 20 +scale 2 2 +drawRect 0 0 10 10 +translate 10 20 +rotate 90 +drawRect 0 0 10 10 +restore +end_block rects + +setPen red +drawText -5 -10 "0.0" +setPen nopen + +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.1" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.2" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.3" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.4" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.5" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.6" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.7" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.8" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "0.9" +setPen nopen +translate 40 0.1 +repeat_block rects +setPen red +drawText -5 -10 "1.0" +setPen nopen + +resetMatrix + +translate 0 620 + +setPen red +drawText 0 10 "path" +setPen nopen + +path_addRect rect2 -5 -5 10 10 + +translate 55 5 +drawPath rect2 + +translate 20 0 +rotate 10 +drawPath rect2 +rotate -10 +translate 20 0 +rotate 20 +drawPath rect2 +rotate -20 +translate 20 0 +rotate 30 +drawPath rect2 +rotate -30 +translate 20 0 +rotate 40 +drawPath rect2 +rotate -40 +translate 20 0 +rotate 50 +drawPath rect2 +rotate -50 +translate 20 0 +rotate 60 +drawPath rect2 +rotate -60 +translate 20 0 +rotate 70 +drawPath rect2 +rotate -70 +translate 20 0 +rotate 80 +drawPath rect2 +rotate -80 +translate 20 0 +rotate 90 +drawPath rect2 +rotate -90 + +resetMatrix + +translate 0 600 + +setPen red +drawText 0 10 "rect" +setPen nopen + +translate 55 5 +drawRect -5 -5 10 10 + +translate 20 0 +rotate 10 +drawRect -5 -5 10 10 +rotate -10 +translate 20 0 +rotate 20 +drawRect -5 -5 10 10 +rotate -20 +translate 20 0 +rotate 30 +drawRect -5 -5 10 10 +rotate -30 +translate 20 0 +rotate 40 +drawRect -5 -5 10 10 +rotate -40 +translate 20 0 +rotate 50 +drawRect -5 -5 10 10 +rotate -50 +translate 20 0 +rotate 60 +drawRect -5 -5 10 10 +rotate -60 +translate 20 0 +rotate 70 +drawRect -5 -5 10 10 +rotate -70 +translate 20 0 +rotate 80 +drawRect -5 -5 10 10 +rotate -80 +translate 20 0 +rotate 90 +drawRect -5 -5 10 10 +rotate -90 + +resetMatrix +path_addRect vertical 0.1 0.1 0.2 10 + +translate 0 320 +drawPath vertical +translate 2.2 0 +drawPath vertical +translate 2.2 0 +drawPath vertical +translate 2.2 0 +drawPath vertical +translate 2.2 0 +drawPath vertical + +resetMatrix +path_addRect horizontal 0.1 0.1 10 0.2 + +translate 0 340 +drawPath horizontal +translate 0 2.2 +drawPath horizontal +translate 0 2.2 +drawPath horizontal +translate 0 2.2 +drawPath horizontal +translate 0 2.2 +drawPath horizontal + +setOpacity 0.8 +resetMatrix + +translate 0.1 24.7 +translate 400 0 +#rotate 88.8 +rotate 89.9 +setBrush red +drawPolygon [0 0 300 0 0 173] +setBrush green +drawPolygon [0 173 300 0 300 173] + +resetMatrix + +translate 410 24 +path_lineTo left 0 273 +path_lineTo left 300 273 +path_cubicTo left 50 273 250 0 0 0 + +path_cubicTo right 250 0 50 273 300 273 +path_lineTo right 300 0 + +translate 310 0 +rotate 90 +setBrush red +drawPath left +setBrush green +drawPath right + +resetMatrix +translate 0.1 680.1 +setPen red +setOpacity 1 +drawText 115 -20 "0.1" +drawText 0 0 "pixmap w/ opacity" +setOpacity 0.6 +drawPixmap pix 120 -10 +translate 0 20 +setOpacity 1 +drawText 0 0 "image w/ opacity" +setOpacity 0.6 +drawImage img 120 -10 + +resetMatrix +path_lineTo fillpath 0 50 +path_lineTo fillpath 50 50 +path_moveTo fillpath 70 50 +path_lineTo fillpath 70 100 +path_lineTo fillpath 40 100 +translate 500 400 +drawPath fillpath + +resetMatrix +path_moveTo vectorarne 50 10 +path_lineTo vectorarne 50 50 +path_lineTo vectorarne 100 50 +path_addEllipse vectorarne 350 20 230 230 +path_moveTo vectorarne 500 500 +path_cubicTo vectorarne 20 20 250 30 50 150 +translate 500 550 +scale 0.4 0.4 +setRenderHint antialiasing +drawPath vectorarne + +resetMatrix +translate 200 730 +setRenderHint antialiasing off +setOpacity 1 +setPen red +drawText 0 0 "outline/fill consistency" +setPen red +setBrush green +translate 80 -30 +drawPolygon [13.6965 -99.1837 -71.4767 13.823 32.4596 -33.1847] \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/gradients.qps b/tests/auto/integrationtests/lancelot/scripts/gradients.qps new file mode 100644 index 0000000000..eb3cda9cad --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/gradients.qps @@ -0,0 +1,44 @@ +# Version: 1 +# CheckVsReference: 5% + +drawText 75 20 "Linear" +drawText 176 20 "Radial" +drawText 277 20 "Conical" +translate 0 30 +drawText 0 50 "AA off" +drawText 0 151 "AA on" + +setPen nopen + +gradient_clearStops +gradient_appendStop 0 0x00000000 +gradient_appendStop 0.001 red +gradient_appendStop 0.2 blue +gradient_appendStop 0.4 yellow +gradient_appendStop 0.6 cyan +gradient_appendStop 0.8 green +gradient_appendStop 0.999 red +gradient_appendStop 1 0x00000000 + +gradient_setSpread PadSpread +gradient_setCoordinateMode ObjectBoundingMode + +begin_block row +save +gradient_setLinear 0.1 0.0 0.9 0.0 +drawRect 50 0 100 100 + +gradient_setRadial 0.5 0.5 0.5 0.5 0.5 +translate 101 0 +drawRect 50 0 100 100 + +gradient_setConical 0.5 0.5 45 +translate 101 0 +drawRect 50 0 100 100 +restore +end_block row + +setRenderHint Antialiasing + +translate 0 101 +repeat_block row \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/hinting.qps b/tests/auto/integrationtests/lancelot/scripts/hinting.qps new file mode 100644 index 0000000000..7ce21b287a --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/hinting.qps @@ -0,0 +1,26 @@ +translate 10 50 +setFont "sansserif" 10 +drawText 0 0 "Default hinting:" +setFont "times" 12 normal normal default +drawText 0 20 "The quick brown fox jumps over the lazy dog" + +translate 0 50 +setFont "sansserif" 10 +drawText 0 0 "No hinting:" +setFont "times" 12 normal normal none +drawText 0 20 "The quick brown fox jumps over the lazy dog" + +translate 0 50 +setFont "sansserif" 10 +drawText 0 0 "Vertical hinting:" +setFont "times" 12 normal normal vertical +drawText 0 20 "The quick brown fox jumps over the lazy dog" + +translate 0 50 +setFont "sansserif" 10 +drawText 0 0 "Full hinting:" +setFont "times" 12 normal normal full +drawText 0 20 "The quick brown fox jumps over the lazy dog" + + +# Note: there is also the textlayout_draw command which might be interesting here. diff --git a/tests/auto/integrationtests/lancelot/scripts/image_formats.qps b/tests/auto/integrationtests/lancelot/scripts/image_formats.qps new file mode 100644 index 0000000000..d817d04bf8 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/image_formats.qps @@ -0,0 +1,81 @@ +# Version: 1 +# CheckVsReference: 5% + + +image_load dome_argb32.png the_pixmap +image_convertToFormat the_pixmap the_pixmap ARGB32_Premultiplied + +begin_block draw_stuff + save + image_convertToFormat the_pixmap converted ARGB32_Premultiplied + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted ARGB32 + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted RGB32 + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted Indexed8 + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted MonoLSB + drawImage converted 0 0 + translate 0 110 + + image_convertToFormat the_pixmap converted Mono + drawImage converted 0 0 + translate 0 110 + restore +end_block + + +image_load dome_argb32.png the_pixmap +translate 110 0 +repeat_block draw_stuff + + +image_load dome_rgb32.png the_pixmap +translate 110 0 +repeat_block draw_stuff + +image_load dome_indexed.png the_pixmap +translate 110 0 +repeat_block draw_stuff + + +image_load dome_mono.png the_pixmap +translate 110 0 +repeat_block draw_stuff + +image_load dome_mono_palette.png the_pixmap +translate 110 0 +repeat_block draw_stuff + +image_load dome_indexed_mask.png the_pixmap +translate 110 0 +repeat_block draw_stuff + + +# helpful texts +resetMatrix +setPen black + +drawText 10 670 "ARGB32_PM" +drawText 120 670 "ARGB32" +drawText 230 670 "RGB32" +drawText 340 670 "Indexed" +drawText 450 670 "Mono" +drawText 560 670 "Mono w/lut" +drawText 670 670 "Indexed w/mask" + +drawText 770 50 "ARGB32_PM" +drawText 770 160 "ARGB32" +drawText 770 270 "RGB32" +drawText 770 380 "Indexed" +drawText 770 490 "MonoLSB" +drawText 770 600 "Mono" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/images.qps b/tests/auto/integrationtests/lancelot/scripts/images.qps new file mode 100644 index 0000000000..3f892400e2 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/images.qps @@ -0,0 +1,106 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint Antialiasing + +setPen #00ff00 + +image_load dome_argb32.png the_image +begin_block draw_stuff + +save + + # standard draw + drawImage the_image 0 0 + + # sub recting + translate 120 0 + drawImage the_image 0 0 40 40 0 0 40 40 + drawImage the_image 60 0 40 40 60 0 40 40 + drawImage the_image 0 60 40 40 0 60 40 40 + drawImage the_image 60 60 40 40 60 60 40 40 + drawImage the_image 0 40 40 20 0 40 40 20 + drawImage the_image 60 40 40 20 60 40 40 20 + drawImage the_image 40 0 20 100 40 0 20 100 + + # subrecting w/scale + translate 120 0 + drawImage the_image 0 0 50 50 0 0 25 25 + drawImage the_image 50 0 50 50 25 0 25 25 + drawImage the_image 0 50 50 50 0 25 25 25 + drawImage the_image 50 50 50 50 25 25 25 25 + + # subrecting w/scale & smooth xform + translate 120 0 + setRenderHint SmoothPixmapTransformation + drawImage the_image 0 0 50 50 0 0 25 25 + drawImage the_image 50 0 50 50 25 0 25 25 + drawImage the_image 0 50 50 50 0 25 25 25 + drawImage the_image 50 50 50 50 25 25 25 25 + + + # Rotation w/o smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform off + rotate 10 + drawImage the_image 0 0 + restore + + # Rotation w smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform + rotate 10 + drawImage the_image 0 0 + restore + +restore + +end_block + + +translate 0 120 +image_load dome_rgb32.png the_image +repeat_block draw_stuff + +translate 0 120 +image_load dome_indexed.png the_image +repeat_block draw_stuff + +translate 0 120 +image_load dome_indexed_mask.png the_image +repeat_block draw_stuff + +translate 0 120 +image_load dome_mono.png the_image +repeat_block draw_stuff + + +resetMatrix +translate 700 60 +setPen black +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" +resetMatrix +translate 0 600 +drawText 0 0 "normal" +translate 120 0 +drawText 0 0 "subrect" +translate 120 0 +drawText 0 0 "subrect scale" +translate 120 0 +drawText 0 0 "subrect scale smooth" +translate 120 0 +drawText 0 0 "xform" +translate 120 0 +drawText 0 0 "smooth xform" +translate 120 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/images2.qps b/tests/auto/integrationtests/lancelot/scripts/images2.qps new file mode 100644 index 0000000000..5159abc928 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/images2.qps @@ -0,0 +1,145 @@ +# Version: 1 +# CheckVsReference: 5% + +image_load dome_argb32.png the_image +begin_block draw_stuff + +save + # standard draw + drawImage the_image 0 0 + + # flip x + translate 220 0 + scale -1 1 + drawImage the_image 0 0 + scale -1 1 + + # flip y + translate 20 100 + scale 1 -1 + drawImage the_image 0 0 + scale 1 -1 + + # flip x and y + translate 220 0 + scale -1 -1 + drawImage the_image 0 0 + scale -1 -1 + + # flip y and scale + translate 20 10 + save + scale 1 -1.1 + drawImage the_image 0 0 + restore + + # flip y and scale + translate 220 -110 + save + scale -1.1 0.9 + drawImage the_image 0 0 + restore +restore +end_block + +setRenderHint Antialiasing + +resetMatrix +translate 0 120 +repeat_block draw_stuff + +resetMatrix +translate 720 60 +setPen black +drawText 0 0 "aliased" +translate 0 120 +drawText 0 0 "antialiased" +resetMatrix +translate 0 260 +drawText 0 0 "normal" +translate 120 0 +drawText 0 0 "flip x" +translate 120 0 +drawText 0 0 "flip y" +translate 120 0 +drawText 0 0 "flip x and y" +translate 120 0 +drawText 0 0 "flip y and scale" +translate 120 0 +drawText 0 0 "flip x and scale" +translate 120 0 + +setRenderHint SmoothPixmapTransform + +resetMatrix +translate 20 300 +drawImage border.png 0 0 100 100 1 1 8 8 +drawText 0 -5 "subrect color bleeding" +translate 0 120 +drawImage border.png 0 0 100 100 0 0 10 10 + +image_load sign.png the_image +resetMatrix +drawText 240 300 "drawImage() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawImage the_image 240 300 50 50 20 0 80 80 +drawRect 300 300 50 50 +drawImage the_image 300 300 50 50 -20 0 80 80 +drawRect 240 370 50 50 +drawImage the_image 240 370 50 50 0 20 80 80 +drawRect 300 370 50 50 +drawImage the_image 300 370 50 50 0 -20 80 80 + +pixmap_load sign.png the_pixmap +translate 220 0 +translate 0 -10 +drawText 240 300 "drawPixmap() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawPixmap the_pixmap 240 300 50 50 20 0 80 80 +drawRect 300 300 50 50 +drawPixmap the_pixmap 300 300 50 50 -20 0 80 80 +drawRect 240 370 50 50 +drawPixmap the_pixmap 240 370 50 50 0 20 80 80 +drawRect 300 370 50 50 +drawPixmap the_pixmap 300 370 50 50 0 -20 80 80 + + +resetMatrix +translate 0 170 +drawText 240 300 "drawImage() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawImage the_image 240 300 50 50 50 0 50 50 +drawRect 300 300 50 50 +drawImage the_image 300 300 50 50 -20 0 50 50 +drawRect 240 370 50 50 +drawImage the_image 240 370 50 50 0 50 50 50 +drawRect 300 370 50 50 +drawImage the_image 300 370 50 50 0 -20 50 50 + +resetMatrix +translate 220 170 +drawText 240 300 "drawPixmap() with varying sx/sy offsets" +translate 0 10 +drawRect 240 300 50 50 +drawPixmap the_pixmap 240 300 50 50 50 0 50 50 +drawRect 300 300 50 50 +drawPixmap the_pixmap 300 300 50 50 -20 0 50 50 +drawRect 240 370 50 50 +drawPixmap the_pixmap 240 370 50 50 0 50 50 50 +drawRect 300 370 50 50 +drawPixmap the_pixmap 300 370 50 50 0 -20 50 50 + +resetMatrix +drawText 10 620 "drawImage/Pixmap() with negative x/y and sx/sy" +setPen red + +translate 20 640 +drawImage the_image -10 -10 -1 -1 -10 -10 0 0 +drawRect 0 0 80 80 + +translate 100 0 +drawPixmap the_pixmap -10 -10 -1 -1 -10 -10 0 0 +drawRect 0 0 80 80 diff --git a/tests/auto/integrationtests/lancelot/scripts/join_cap_styles.qps b/tests/auto/integrationtests/lancelot/scripts/join_cap_styles.qps new file mode 100644 index 0000000000..ed823f53f5 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/join_cap_styles.qps @@ -0,0 +1,63 @@ +# Version: 1 +# CheckVsReference: 5% + + +setRenderHint Antialiasing + +path_moveTo p 20 20 +path_cubicTo p 100 20 100 180 180 100 +path_lineTo p 20 180 +path_lineTo p 180 20 + +setPen black 20 solidline roundcap roundjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline roundcap miterjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline roundcap beveljoin +drawPath p +setPen red +drawPath p + +translate -400 200 +setPen black 20 solidline squarecap roundjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline squarecap miterjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline squarecap beveljoin +drawPath p +setPen red +drawPath p + +translate -400 200 +setPen black 20 solidline flatcap roundjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline flatcap miterjoin +drawPath p +setPen red +drawPath p + +translate 200 0 +setPen black 20 solidline flatcap beveljoin +drawPath p +setPen red +drawPath p \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/join_cap_styles_duplicate_control_points.qps b/tests/auto/integrationtests/lancelot/scripts/join_cap_styles_duplicate_control_points.qps new file mode 100644 index 0000000000..b4630148e2 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/join_cap_styles_duplicate_control_points.qps @@ -0,0 +1,68 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 600 650) + + +setRenderHint Antialiasing + +path_moveTo p 40 70 +path_lineTo p 20 70 +path_cubicTo p 20 70 40 20 80 80 + +path_moveTo p 20 120 +path_cubicTo p 50 60 80 110 80 110 +path_lineTo p 60 110 + +scale 2 2 + +setPen black 10 solidline roundcap roundjoin +drawPath p +setPen red +drawPath p + +translate 100 0 +setPen black 10 solidline roundcap miterjoin +drawPath p +setPen red +drawPath p + +translate 100 0 +setPen black 10 solidline roundcap beveljoin +drawPath p +setPen red +drawPath p + +translate -200 100 +setPen black 10 solidline squarecap roundjoin +drawPath p +setPen red +drawPath p + +translate 100 0 +setPen black 10 solidline squarecap miterjoin +drawPath p +setPen red +drawPath p + +translate 100 0 +setPen black 10 solidline squarecap beveljoin +drawPath p +setPen red +drawPath p + +translate -200 100 +setPen black 10 solidline flatcap roundjoin +drawPath p +setPen red +drawPath p + +translate 100 0 +setPen black 10 solidline flatcap miterjoin +drawPath p +setPen red +drawPath p + +translate 100 0 +setPen black 10 solidline flatcap beveljoin +drawPath p +setPen red +drawPath p \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/linear_gradients.qps b/tests/auto/integrationtests/lancelot/scripts/linear_gradients.qps new file mode 100644 index 0000000000..b1b8dd69e7 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/linear_gradients.qps @@ -0,0 +1,144 @@ +# Version: 1 +# CheckVsReference: 2% (0 0 600 750) + +path_addRect path 400 0 80 80 +path_addEllipse path 440 40 60 60 + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 20 20 70 70 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setLinear 120 20 170 70 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setLinear 220 20 270 70 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setLinear 320 20 340 40 +drawPolygon [300 0 390 0 350 99] + +gradient_setSpread ReflectSpread +gradient_setLinear 420 20 440 40 +drawPath path + +gradient_setSpread RepeatSpread +gradient_setLinear 520 20 540 40 +drawPie 500 0 100 100 720 4320 +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Vertical gradient tests +resetMatrix +setBrush noBrush +translate 0 400 + +begin_block vertical_gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 20 20 20 70 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setLinear 120 20 120 70 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setLinear 220 20 220 70 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setLinear 320 20 320 40 +drawPolygon [300 0 390 0 350 99] + +gradient_setSpread ReflectSpread +gradient_setLinear 420 20 420 40 +drawPath path + +gradient_setSpread RepeatSpread +gradient_setLinear 520 20 520 40 +drawPie 500 0 100 100 720 4320 +end_block + +translate 0 100 +scale 1 1.5 +repeat_block vertical_gradients + +resetMatrix +translate 0 650 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block vertical_gradients + +# Some helpful info perhaps? +resetMatrix +setPen black +# gradient line indicators +drawLine 20 20 70 70 +drawLine 120 20 170 70 +drawLine 220 20 270 70 +drawLine 320 20 340 40 +drawLine 420 20 440 40 +drawLine 520 20 540 40 + +drawLine 20 140 70 240 +drawLine 120 140 170 240 +drawLine 220 140 270 240 +drawLine 320 140 340 180 +drawLine 420 140 440 180 +drawLine 520 140 540 180 + +drawText 610 50 "No XForm" +drawText 610 200 "scale 1x2" +drawText 610 350 "brush transform" +drawText 610 450 "vertical brush" +drawText 610 570 "vertical brush scale 1x1.5" +drawText 610 700 "vertical brush transform" + +drawText 10 780 "Pad" +drawText 110 780 "Reflect" +drawText 210 780 "Repeat" +drawText 310 780 "Pad w/alpha" +drawText 410 780 "Reflect w/alpha" +drawText 510 780 "Repeat w/alpha" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/linear_gradients_perspectives.qps b/tests/auto/integrationtests/lancelot/scripts/linear_gradients_perspectives.qps new file mode 100644 index 0000000000..3ea39fbe46 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/linear_gradients_perspectives.qps @@ -0,0 +1,62 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen #00ff00 + +translate 10 10 +# standard draw +begin_block gradient +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setLinear 10 10 290 290 +drawRect 0 0 300 300 +end_block gradient + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block gradient +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block gradient +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block gradient +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/linear_resolving_gradients.qps b/tests/auto/integrationtests/lancelot/scripts/linear_resolving_gradients.qps new file mode 100644 index 0000000000..779760cb9a --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/linear_resolving_gradients.qps @@ -0,0 +1,66 @@ +# Version: 2 +# CheckVsReference: 2% (0 0 500 400) + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setCoordinateMode ObjectBoundingMode +gradient_setLinear 0.2 0.2 0.7 0.7 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setLinear 0.2 0.2 0.7 0.7 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setLinear 0.2 0.2 0.7 0.7 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setLinear 0.2 0.2 0.8 0.4 +drawPolygon [300 0 400 0 350 100] + +gradient_setSpread RepeatSpread +gradient_setLinear 0.2 0.2 0.4 0.4 +drawPie 400 0 100 100 0 4320 +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Some helpful info perhaps? +resetMatrix +setPen black + +drawText 510 50 "No XForm" +drawText 510 200 "scale 1x2" +drawText 510 350 "brush transform" + +drawText 10 450 "Pad" +drawText 110 450 "Reflect" +drawText 210 450 "Repeat" +drawText 310 450 "Pad w/alpha" +drawText 410 450 "Repeat w/alpha" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/lineconsistency.qps b/tests/auto/integrationtests/lancelot/scripts/lineconsistency.qps new file mode 100644 index 0000000000..0b40577659 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/lineconsistency.qps @@ -0,0 +1,72 @@ +# Version: 1 + +begin_block draw +setPen red +drawPolygon [1.1 1 3.3 30.6 23.1 39.2 38.9 6.5] +setPen black +drawLine 1.1 1 3.3 30.6 +drawLine 3.3 30.6 23.1 39.2 +drawLine 23.1 39.2 38.9 6.5 +drawLine 38.9 6.5 1.1 1 +end_block draw +drawText 0 60 "0.0 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.1 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.2 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.3 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.4 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.5 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.6 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.7 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.8 aligned" +translate 0.1 80.1 +repeat_block draw +drawText 0 60 "0.9 aligned" + +resetMatrix +translate 100 0 +setPen black +drawText 0 20 "Line and text, 0.0 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.1 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.2 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.3 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.4 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.5 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.6 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.7 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.8 aligned" +drawLine 0 21 160 21 +translate 0 40.1 +drawText 0 20 "Line and text, 0.9 aligned" +drawLine 0 21 160 21 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/linedashes.qps b/tests/auto/integrationtests/lancelot/scripts/linedashes.qps new file mode 100644 index 0000000000..ee7d18b156 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/linedashes.qps @@ -0,0 +1,94 @@ +# Version: 1 + +translate 10 10 + +setPen 0xffff0000 0 solidline squarecap +translate 50 50 +begin_block draw_lines + save + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + restore +end_block + +setPen 0xffff0000 0 dotline squarecap +translate 100 0 +repeat_block draw_lines +setPen 0xffff0000 0 dashdotline squarecap +translate 100 0 +repeat_block draw_lines +setPen 0xffff0000 0 dashdotdotline squarecap +translate 100 0 +repeat_block draw_lines +setPen 0xffff0000 0 dashline squarecap +translate 100 0 +repeat_block draw_lines \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/linedashes2.qps b/tests/auto/integrationtests/lancelot/scripts/linedashes2.qps new file mode 100644 index 0000000000..1dc4fd310e --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/linedashes2.qps @@ -0,0 +1,154 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 800 800) + +translate -30 10 + +setPen 0xffff0000 0 dashline squarecap +pen_setDashPattern [10 5] + +save +translate 100 100 +begin_block lines +drawLine 100 100 200 100 +drawLine 100 100 200 200 +drawLine 100 100 100 200 +end_block + +setPen 0xffff0000 2 dashline squarecap +translate 150 0 +repeat_block lines +restore + +save +save +begin_block horizontal +drawLine 0 0 50 0 +drawLine 3 10 53 10 +drawLine 6 20 56 20 +drawLine 9 30 59 30 + +translate 0 50 + +drawLine 0 0 50 5 +drawLine 3 10 53 15 +drawLine 6 20 56 25 +drawLine 9 30 59 35 + +translate 0 50 + +drawLine 0 0 50 -5 +drawLine 3 10 53 5 +drawLine 6 20 56 15 +drawLine 9 30 59 25 +end_block +restore + +save +translate 80 0 +repeat_block horizontal +restore +save +translate 800 0 +repeat_block horizontal +restore + +translate 180 -40 +save +begin_block vertical +drawLine 0 0 0 50 +drawLine 10 3 10 53 +drawLine 20 6 20 56 +drawLine 30 9 30 59 + +translate 50 0 + +drawLine 0 0 5 50 +drawLine 10 3 15 53 +drawLine 20 6 25 56 +drawLine 30 9 35 59 + +translate 50 0 + +drawLine 0 0 -5 50 +drawLine 10 3 5 53 +drawLine 20 6 15 56 +drawLine 30 9 25 59 +end_block +restore + +save +translate 0 80 +repeat_block vertical +restore +translate 0 800 +repeat_block vertical +restore + +translate 0 200 + +setPen 0xffff0000 2 dashline squarecap +save +repeat_block horizontal +restore +save +translate 80 0 +repeat_block horizontal +restore +save +translate 780 0 +repeat_block horizontal +restore + +translate 360 -240 +save +repeat_block vertical +restore +save +translate 0 80 +repeat_block vertical +restore +translate 0 780 +repeat_block vertical + +resetMatrix +translate 40 400 +setPen 0xffff0000 5 dashdotline flatcap +pen_setDashPattern [1 1 4 1 1 4] +pen_setDashOffset -4 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset -2 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 0 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 2 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 4 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 6 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 8 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 10 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 12 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 14 +drawLine 0 0 300 0 +translate 0 8 +pen_setDashOffset 16 +drawLine 0 0 300 0 + +resetMatrix +setPen black 3 dashdotline +pen_setCosmetic true +translate 0 -150 +drawLine 500 160 500 410 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/linedashes2_aa.qps b/tests/auto/integrationtests/lancelot/scripts/linedashes2_aa.qps new file mode 100644 index 0000000000..c818ab62fe --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/linedashes2_aa.qps @@ -0,0 +1,5 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 800 800) + +setRenderHint LineAntialiasing +import "linedashes2.qps" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/lines.qps b/tests/auto/integrationtests/lancelot/scripts/lines.qps new file mode 100644 index 0000000000..c0daffb1b0 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/lines.qps @@ -0,0 +1,558 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 310 425) + + +translate 10 10 + +begin_block draw_lines + save + translate 50 50 + + save + setPen 0x7fff0000 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + restore + + # and then draw the lines the other direction + save + setPen 0x7f0000ff + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + rotate 10 + drawLine 50 0 10 0 + restore + + # and now with a clip + save + setClipRect -30 -30 60 60 + setPen 0x7f00ff00 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + rotate 10 + drawLine 10 0 50 0 + restore + + restore +end_block + +save + translate 100 0 + scale 2 2 + repeat_block draw_lines +restore + +translate 0 10 + +save + translate 0 200 + setRenderHint Antialiasing + repeat_block draw_lines +restore + +save + translate 100 200 + scale 2 2 + setRenderHint Antialiasing + repeat_block draw_lines +restore + +translate 320 0 + +setPen black 0 solidline squarecap + +begin_block lines + +# 0 -> 45 degress +drawLine 100 100 200 90 +drawLine 100 100 200 80 +drawLine 100 100 200 70 +drawLine 100 100 200 60 +drawLine 100 100 200 50 +drawLine 100 100 200 40 +drawLine 100 100 200 30 +drawLine 100 100 200 20 +drawLine 100 100 200 10 + +# 45 +drawLine 100 100 200 0 + +# 45 -> 90 +drawLine 100 100 190 0 +drawLine 100 100 180 0 +drawLine 100 100 170 0 +drawLine 100 100 160 0 +drawLine 100 100 150 0 +drawLine 100 100 140 0 +drawLine 100 100 130 0 +drawLine 100 100 120 0 +drawLine 100 100 110 0 + +# 90 +drawLine 100 100 100 0 + +# 90 -> 135 +drawLine 100 100 90 0 +drawLine 100 100 80 0 +drawLine 100 100 70 0 +drawLine 100 100 60 0 +drawLine 100 100 50 0 +drawLine 100 100 40 0 +drawLine 100 100 30 0 +drawLine 100 100 20 0 +drawLine 100 100 10 0 + +# 135 +drawLine 100 100 0 0 + +# 135 -> 180 degress +drawLine 100 100 0 10 +drawLine 100 100 0 20 +drawLine 100 100 0 30 +drawLine 100 100 0 40 +drawLine 100 100 0 50 +drawLine 100 100 0 60 +drawLine 100 100 0 70 +drawLine 100 100 0 80 +drawLine 100 100 0 90 + +# 180 +drawLine 100 100 0 100 + +# 180 -> 225 +drawLine 100 100 0 110 +drawLine 100 100 0 120 +drawLine 100 100 0 130 +drawLine 100 100 0 140 +drawLine 100 100 0 150 +drawLine 100 100 0 160 +drawLine 100 100 0 170 +drawLine 100 100 0 180 +drawLine 100 100 0 190 + +# 225 +drawLine 100 100 0 200 + +# 225 -> 270 +drawLine 100 100 10 200 +drawLine 100 100 20 200 +drawLine 100 100 30 200 +drawLine 100 100 40 200 +drawLine 100 100 50 200 +drawLine 100 100 60 200 +drawLine 100 100 70 200 +drawLine 100 100 80 200 +drawLine 100 100 90 200 + +# 270 +drawLine 100 100 100 200 + +# 270 -> 315 degrees +drawLine 100 100 110 200 +drawLine 100 100 120 200 +drawLine 100 100 130 200 +drawLine 100 100 140 200 +drawLine 100 100 150 200 +drawLine 100 100 160 200 +drawLine 100 100 170 200 +drawLine 100 100 180 200 +drawLine 100 100 190 200 + +# 315 +drawLine 100 100 200 200 + +# 315 -> 360 degress +drawLine 100 100 200 100 +drawLine 100 100 200 110 +drawLine 100 100 200 120 +drawLine 100 100 200 130 +drawLine 100 100 200 140 +drawLine 100 100 200 150 +drawLine 100 100 200 160 +drawLine 100 100 200 170 +drawLine 100 100 200 180 +drawLine 100 100 200 190 + +end_block + + +setRenderHint Antialiasing +setPen 0x7fff0000 +translate 0.5 0.5 +repeat_block lines + +setPen 0x000000 8 +translate 20 240 +drawText 0 0 "Steep slopes:" + +translate 0 10 + +drawLine 0 0 -8 400 +translate 20 0 +drawLine 0 0 -7 400 +translate 20 0 +drawLine 0 0 -6 400 +translate 20 0 +drawLine 0 0 -5 400 +translate 20 0 +drawLine 0 0 -4 400 +translate 20 0 +drawLine 0 0 -3 400 +translate 20 0 +drawLine 0 0 -2 400 +translate 20 0 +drawLine 0 0 -1 400 +translate 20 0 +drawLine 0 0 0 400 +translate 20 0 +drawLine 0 0 1 400 +translate 20 0 +drawLine 0 0 2 400 +translate 20 0 +drawLine 0 0 3 400 +translate 20 0 +drawLine 0 0 4 400 +translate 20 0 +drawLine 0 0 5 400 +translate 20 0 +drawLine 0 0 6 400 +translate 20 0 +drawLine 0 0 7 400 +translate 20 0 +drawLine 0 0 8 400 + +resetMatrix + +translate 20 450 + +drawText 0 0 "Zero length lines:" + +translate 0 20 +drawText 100 10 "Square cap" +save +begin_block points +setPen 0x000000 1 solidline squarecap +drawLine 0 0 0 0 +setPen 0x000000 2 solidline squarecap +drawLine 8 0 8 0 +setPen 0x000000 3 solidline squarecap +drawLine 16 0 16 0 +setPen 0x000000 4 solidline squarecap +drawLine 24 0 24 0 +setPen 0x000000 5 solidline squarecap +drawLine 32 0 32 0 +setPen 0x000000 6 solidline squarecap +drawLine 40 0 40 0 +setPen 0x000000 7 solidline squarecap +drawLine 48 0 48 0 +setPen 0x000000 8 solidline squarecap +drawLine 57 0 57 0 +setPen 0x000000 9 solidline squarecap +drawLine 67 0 67 0 +setPen 0x000000 10 solidline squarecap +drawLine 78 0 78 0 +end_block points +restore + +translate 0 12 +setRenderHint Antialiasing off +repeat_block points +setRenderHint Antialiasing + +translate 0 20 +drawText 100 10 "Round cap" +save +begin_block points2 +setPen 0x000000 1 solidline roundcap +drawLine 0 0 0 0 +setPen 0x000000 2 solidline roundcap +drawLine 8 0 8 0 +setPen 0x000000 3 solidline roundcap +drawLine 16 0 16 0 +setPen 0x000000 4 solidline roundcap +drawLine 24 0 24 0 +setPen 0x000000 5 solidline roundcap +drawLine 32 0 32 0 +setPen 0x000000 6 solidline roundcap +drawLine 40 0 40 0 +setPen 0x000000 7 solidline roundcap +drawLine 48 0 48 0 +setPen 0x000000 8 solidline roundcap +drawLine 57 0 57 0 +setPen 0x000000 9 solidline roundcap +drawLine 67 0 67 0 +setPen 0x000000 10 solidline roundcap +drawLine 78 0 78 0 +end_block points2 +restore + +translate 0 12 +setRenderHint Antialiasing off +repeat_block points2 +setRenderHint Antialiasing + +translate 0 20 +drawText 100 10 "Flat cap" +save +begin_block points3 +setPen 0x000000 1 solidline flatcap +drawLine 0 0 0 0 +setPen 0x000000 2 solidline flatcap +drawLine 8 0 8 0 +setPen 0x000000 3 solidline flatcap +drawLine 16 0 16 0 +setPen 0x000000 4 solidline flatcap +drawLine 24 0 24 0 +setPen 0x000000 5 solidline flatcap +drawLine 32 0 32 0 +setPen 0x000000 6 solidline flatcap +drawLine 40 0 40 0 +setPen 0x000000 7 solidline flatcap +drawLine 48 0 48 0 +setPen 0x000000 8 solidline flatcap +drawLine 57 0 57 0 +setPen 0x000000 9 solidline flatcap +drawLine 67 0 67 0 +setPen 0x000000 10 solidline flatcap +drawLine 78 0 78 0 +end_block points3 +restore + +translate 0 12 +setRenderHint Antialiasing off +repeat_block points3 + +resetMatrix +translate -220 667.226 +drawText 230 -80 "Task 194266 (should see only one line):" +setPen black +drawRect 230.5 -70.5 122 12 +setRenderHint Antialiasing +setPen red +drawLine 236.842105263 -63.775117299 247.368421053 -63.775437504 + +setRenderHint Antialiasing off +resetMatrix +translate 10 640 +setPen black +drawText 0 -10 "Task 207147 (should see two lines):" +drawRect 0.5 0.5 64 64 +setRenderHint Antialiasing +setPen red + +drawLine 4.5 4.5 4.5001 60.5 +drawLine 4.5 4.5 60.5 4.5001 + +setRenderHint Antialiasing off +resetMatrix +translate 10 730 +setPen black +drawText 0 -10 "Task 229459 (should see one diagonal line):" +drawRect 0.5 0.5 64 64 +setPen red 2 solidline flatcap + +setClipRect 2 2 63 63 +drawLine 1.5 1.5 33560000 33560000 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/lines2.qps b/tests/auto/integrationtests/lancelot/scripts/lines2.qps new file mode 100644 index 0000000000..af6ad65939 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/lines2.qps @@ -0,0 +1,179 @@ +# Version: 1 +# CheckVsReference: 5% + +translate 10 20 +drawText 0 0 "Thin lines" + +translate 60 70 + +save +begin_block lines +translate 0 -60 +translate 0 5 +setPen 0x000000 0.05 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.1 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.15 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.3 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.35 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.5 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.55 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.6 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.65 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.7 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.75 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.8 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.85 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.9 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 0.95 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.05 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.1 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.15 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.3 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.35 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.2 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.25 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.5 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.55 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.6 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.65 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.7 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.75 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.8 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.85 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.9 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 1.95 +drawLine -60 -2 60 2 +translate 0 5 +setPen 0x000000 2 +drawLine -60 -2 60 2 +end_block +restore + +save +translate 150 0 +scale -1 1 +repeat_block lines +restore + +save +translate 80 220 +rotate 90 +repeat_block lines +restore + +save +translate 80 370 +rotate 90 +scale -1 1 +repeat_block lines +restore + +setRenderHint Antialiasing + +translate 300 0 + +save +repeat_block lines +restore + +save +translate 150 0 +scale -1 1 +repeat_block lines +restore + +save +translate 80 220 +rotate 90 +repeat_block lines +restore + +save +translate 80 370 +rotate 90 +scale -1 1 +repeat_block lines +restore \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/pathfill.qps b/tests/auto/integrationtests/lancelot/scripts/pathfill.qps new file mode 100644 index 0000000000..821b4684c9 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pathfill.qps @@ -0,0 +1,38 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 850 420) + +setPen afff0000 4 + +setBrush dome_rgb32.png +drawEllipse 10 10 200 200 + +setBrush dome_argb32.png +drawEllipse 220 10 200 200 + +setPen NoPen + +setBrush dome_rgb32.png +drawEllipse 10 220 200 200 + +setBrush dome_argb32.png +drawEllipse 220 220 200 200 + +setBrushOrigin -30 -30 + +setPen afff0000 4 +setBrush dome_rgb32.png +drawEllipse 430 10 200 200 + +setBrush dome_argb32.png +drawEllipse 640 10 200 200 + +setPen NoPen +setBrush dome_rgb32.png +drawEllipse 430 220 200 200 + +setBrush dome_argb32.png +drawEllipse 640 220 200 200 + +setPen black +drawText 150 450 "No offset RGB/ARGB" +drawText 550 450 "-30 offset RGB/ARGB" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/paths.qps b/tests/auto/integrationtests/lancelot/scripts/paths.qps new file mode 100644 index 0000000000..083026ee17 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/paths.qps @@ -0,0 +1,34 @@ +# Version: 1 + +setPen black +setBrush 7f7fff + +path_moveTo star 50 0 +path_lineTo star 30 90 +path_lineTo star 100 60 +path_lineTo star 0 20 +path_lineTo star 80 100 + +setFont "times" 50 +path_addText text 0 50 "ABCD, 1234, abcd, #¤%&" + +path_addRect rectncircle 0 0 75 75 +path_addEllipse rectncircle 25 25 75 75 +path_setFillRule rectncircle winding + +path_moveTo curve 100 0 +path_cubicTo curve 100 100 50 50 0 100 + +begin_block drawing +drawPath star +translate 100 0 +drawPath rectncircle +translate 100 0 +drawPath curve +translate -200 100 +drawPath text +end_block + +translate 50 100 +rotate 10 +repeat_block drawing diff --git a/tests/auto/integrationtests/lancelot/scripts/paths_aa.qps b/tests/auto/integrationtests/lancelot/scripts/paths_aa.qps new file mode 100644 index 0000000000..4812e2fa5f --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/paths_aa.qps @@ -0,0 +1,4 @@ +# Version: 1 + +setRenderHint LineAntialiasing +import "paths.qps" diff --git a/tests/auto/integrationtests/lancelot/scripts/pens.qps b/tests/auto/integrationtests/lancelot/scripts/pens.qps new file mode 100644 index 0000000000..c72636dcef --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pens.qps @@ -0,0 +1,133 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 800 800) + + +translate 10 10 + +begin_block penstyles +setPen black 0 solidline flatcap +drawLine 0 0 100 0 +setPen black 0 dashline flatcap +drawLine 100 0 100 40 +setPen black 0 dotline flatcap +drawLine 100 40 200 0 +setPen black 0 dashdotline flatcap +drawLine 200 0 300 0 +setPen black 0 dashdotdotline flatcap +drawLine 300 0 400 40 + +translate 0 50 +setPen blue 2 solidline flatcap +drawLine 0 0 100 0 +setPen blue 2 dashline flatcap +drawLine 100 0 100 40 +setPen blue 2 dotline flatcap +drawLine 100 40 200 0 +setPen blue 2 dashdotline flatcap +drawLine 200 0 300 0 +setPen blue 2 dashdotdotline flatcap +drawLine 300 0 400 40 + +translate 0 50 +setPen red 5 solidline flatcap +drawLine 0 0 100 0 +setPen red 5 dashline flatcap +drawLine 100 0 100 40 +setPen red 5 dotline flatcap +drawLine 100 40 200 0 +setPen red 5 dashdotline flatcap +drawLine 200 0 300 0 +setPen red 5 dashdotdotline flatcap +drawLine 300 0 400 40 +end_block + +translate 0 50 +scale 1 2 +repeat_block penstyles + + +# Test cap styles +resetMatrix +translate 420 10 +setPen green 5 dashdotline flatcap +drawLine 0 0 200 0 +setPen green 5 dashdotline roundcap +drawLine 0 20 200 20 +setPen green 5 dashdotline squarecap +drawLine 0 40 200 40 + + +# Test join styles +resetMatrix +translate 420 80 +setBrush nobrush +begin_block joinstyles +setPen orange 10 solidline flatcap miterjoin +drawPolyline [ 0 0 80 0 80 80 0 80 ] + +translate 0 100 +setPen aquamarine 10 solidline squarecap beveljoin +drawPolyline [ 0 0 80 0 80 80 0 80 ] + +translate 0 100 +setPen purple 10 solidline roundcap roundjoin +drawPolyline [ 0 0 80 0 80 80 0 80 ] +end_block + +translate 130 -200 +scale 2 1 +rotate 1 +repeat_block joinstyles + +# transparent lines +resetMatrix +translate 10 400 +setPen #7f000000 +drawLine 0 0 50 0 +setPen #7f000000 1 SolidLine +drawLine 0 10 50 10 +setPen #7f000000 5 SolidLine +drawLine 0 20 50 20 +setPen #7f000000 10 SolidLine +drawLine 0 30 50 30 +setPen #7f000000 +drawLine 0 0 0 50 +setPen #7f000000 1 SolidLine +drawLine 10 0 10 50 +setPen #7f000000 5 SolidLine +drawLine 20 0 20 50 +setPen #7f000000 10 SolidLine +drawLine 30 0 30 50 + +# pen styles +resetMatrix +translate 0 500 +setPen black 0 DashLine +drawLine 20 20 100 20 +translate 0 10 +setPen black 0 DotLine +drawLine 20 20 100 20 +translate 0 10 +setPen black 0 DashDotLine +drawLine 20 20 100 20 +translate 0 10 +setPen black 0 DashDotDotLine +drawLine 20 20 100 20 + +# scaling ellipse +resetMatrix +setPen black 0.008 DashLine +translate 250 550 +rotate 30 +scale 250 250 +drawEllipse -0.4 -0.4 0.8 0.8 + +# scaling path +path_addEllipse star -0.3 -0.3 0.6 0.6 + +resetMatrix +setPen black 0.008 DashLine +translate 250 550 +rotate 30 +scale 250 250 +drawPath star diff --git a/tests/auto/integrationtests/lancelot/scripts/pens_aa.qps b/tests/auto/integrationtests/lancelot/scripts/pens_aa.qps new file mode 100644 index 0000000000..066cac365f --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pens_aa.qps @@ -0,0 +1,6 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 800 800) + +setRenderHint LineAntialiasing + +import "pens.qps" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/pens_cosmetic.qps b/tests/auto/integrationtests/lancelot/scripts/pens_cosmetic.qps new file mode 100644 index 0000000000..d1a60d150d --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pens_cosmetic.qps @@ -0,0 +1,110 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 585 470) + +path_addEllipse path 22 0 7 7 +path_addRect path 25 5 4 4 + +translate 20 20 + +begin_block lines + save + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + + translate 100 0 + save + scale 4 1 + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + restore + + translate 200 0 + save + scale 1 4 + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + restore + + translate 100 0 + save + scale 4 4 + drawLine 0 0 10 10 + drawLine 2 0 10 0 + drawLine 0 2 0 10 + drawPolygon [12 0 20 0 15 10] + drawPath path + drawEllipse 32 0 8 8 + drawPoint 36 4 + restore + restore +end_block + +drawText 580 15 "non-cosmetic, 0-width" +translate 0 50 + +setPen black 2 +repeat_block lines +drawText 580 15 "non-cosmetic, 2-width" + +translate 0 20 +translate 0 50 +setPen black 0 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 0-width" + +translate 0 50 +setPen black 2 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 2-width" + + +setRenderHint Antialiasing +translate 0 20 + +translate 0 50 +setPen black 0 +repeat_block lines +drawText 580 15 "non-cosmetic, 0-width" + +translate 0 50 + +setPen black 2 +repeat_block lines +drawText 580 15 "non-cosmetic, 2-width" + +translate 0 20 +translate 0 50 +setPen black 0 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 0-width" + +translate 0 50 +setPen black 2 +pen_setCosmetic true +repeat_block lines +drawText 580 15 "cosmetic, 2-width" + + +translate 0 70 +drawText 0 0 "scale(1, 1)" +drawText 150 0 "scale(4, 1)" +drawText 300 0 "scale(1, 4)" +drawText 450 0 "scale(4, 4)" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/perspectives.qps b/tests/auto/integrationtests/lancelot/scripts/perspectives.qps new file mode 100644 index 0000000000..0b903e5260 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/perspectives.qps @@ -0,0 +1,72 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen #00ff00 + +image_load image.png the_image + +translate 10 10 +# standard draw +drawImage the_image 0 0 + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + drawImage the_image 0 0 +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + drawImage the_image 0 0 +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + drawImage the_image 0 0 +restore +restore + +setRenderHint SmoothPixmapTransform on +setBrush red +setPen black +resetMatrix +translate 100 720 +rotate_y 85 +scale 7 0.01 +drawRect -150 -150 300 300 + +resetMatrix +setBrush gam030.png +setPen black 30 +translate 700 700 +rotate_y -85 +scale 7 0.01 +drawRect -150 -150 300 300 + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0 +resetMatrix +translate 300 760 +drawText 0 0 "Perspective Clipping" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/perspectives2.qps b/tests/auto/integrationtests/lancelot/scripts/perspectives2.qps new file mode 100644 index 0000000000..2f6d1d653c --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/perspectives2.qps @@ -0,0 +1,309 @@ +# Version: 1 + +setRenderHint Antialiasing + +image_load zebra.png zebra_png + +image_convertToFormat zebra_png zebra ARGB32_Premultiplied + +translate 75 100 +# standard draw +begin_block row +drawImage zebra -50 -50 + +translate 90 0 +save +rotate_y 50 +drawImage zebra -50 -50 +restore + +translate 65 0 +save +rotate_y 60 +drawImage zebra -50 -50 +restore + +translate 50 0 +save +rotate_y 70 +drawImage zebra -50 -50 +restore + +translate 30 0 +save +rotate_y 80 +drawImage zebra -50 -50 +restore + +translate 24 0 +save +rotate_y 82 +drawImage zebra -50 -50 +restore + +translate 20 0 +save +rotate_y 84 +drawImage zebra -50 -50 +restore + +translate 16 0 +save +rotate_y 86 +drawImage zebra -50 -50 +restore + +translate 12 0 +save +rotate_y 87 +drawImage zebra -50 -50 +restore + +translate 8 0 +save +rotate_y 88 +drawImage zebra -50 -50 +restore + +translate 6 0 +save +rotate_y 89 +drawImage zebra -50 -50 +restore + +translate 6 0 +save +rotate_y 91 +drawImage zebra -50 -50 +restore + +translate 6 0 +save +rotate_y 92 +drawImage zebra -50 -50 +restore + +translate 8 0 +save +rotate_y 93 +drawImage zebra -50 -50 +restore + +translate 12 0 +save +rotate_y 94 +drawImage zebra -50 -50 +restore + +translate 16 0 +save +rotate_y 96 +drawImage zebra -50 -50 +restore + +translate 20 0 +save +rotate_y 98 +drawImage zebra -50 -50 +restore + +translate 24 0 +save +rotate_y 100 +drawImage zebra -50 -50 +restore + +translate 30 0 +save +rotate_y 110 +drawImage zebra -50 -50 +restore + +translate 50 0 +save +rotate_y 120 +drawImage zebra -50 -50 +restore + +translate 65 0 +save +rotate_y 130 +drawImage zebra -50 -50 +restore + +translate 90 0 +save +rotate_y 180 +drawImage zebra -50 -50 +restore +end_block + +resetMatrix +translate 75 280 +setRenderHint SmoothPixmapTransform +repeat_block row + +resetMatrix +setPen black +translate 300 20 +drawText 0 0 "Fast Pixmap Transform" +resetMatrix +translate 300 210 +drawText 0 0 "Smooth Pixmap Transform" + +resetMatrix +translate 0 400 + +image_load dome_argb32.png the_pixmap + +image_convertToFormat the_pixmap dome ARGB32 + +setRenderHint SmoothPixmapTransform false + +translate 75 100 +# standard draw +begin_block row +drawImage dome -50 -50 + +translate 90 0 +save +rotate_y 50 +drawImage dome -50 -50 +restore + +translate 65 0 +save +rotate_y 60 +drawImage dome -50 -50 +restore + +translate 50 0 +save +rotate_y 70 +drawImage dome -50 -50 +restore + +translate 30 0 +save +rotate_y 80 +drawImage dome -50 -50 +restore + +translate 24 0 +save +rotate_y 82 +drawImage dome -50 -50 +restore + +translate 20 0 +save +rotate_y 84 +drawImage dome -50 -50 +restore + +translate 16 0 +save +rotate_y 86 +drawImage dome -50 -50 +restore + +translate 12 0 +save +rotate_y 87 +drawImage dome -50 -50 +restore + +translate 8 0 +save +rotate_y 88 +drawImage dome -50 -50 +restore + +translate 6 0 +save +rotate_y 89 +drawImage dome -50 -50 +restore + +translate 6 0 +save +rotate_y 91 +drawImage dome -50 -50 +restore + +translate 6 0 +save +rotate_y 92 +drawImage dome -50 -50 +restore + +translate 8 0 +save +rotate_y 93 +drawImage dome -50 -50 +restore + +translate 12 0 +save +rotate_y 94 +drawImage dome -50 -50 +restore + +translate 16 0 +save +rotate_y 96 +drawImage dome -50 -50 +restore + +translate 20 0 +save +rotate_y 98 +drawImage dome -50 -50 +restore + +translate 24 0 +save +rotate_y 100 +drawImage dome -50 -50 +restore + +translate 30 0 +save +rotate_y 110 +drawImage dome -50 -50 +restore + +translate 50 0 +save +rotate_y 120 +drawImage dome -50 -50 +restore + +translate 65 0 +save +rotate_y 130 +drawImage dome -50 -50 +restore + +translate 90 0 +save +rotate_y 180 +drawImage dome -50 -50 +restore +end_block + +resetMatrix +translate 0 400 +translate 75 280 +setRenderHint SmoothPixmapTransform +repeat_block row + +resetMatrix +setPen black +translate 0 400 +translate 300 20 +drawText 0 0 "Fast Pixmap Transform" +resetMatrix +translate 0 400 +translate 300 210 +drawText 0 0 "Smooth Pixmap Transform" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/pixmap_rotation.qps b/tests/auto/integrationtests/lancelot/scripts/pixmap_rotation.qps new file mode 100644 index 0000000000..2f1ffb53e6 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pixmap_rotation.qps @@ -0,0 +1,30 @@ +# Version: 1 +# CheckVsReference: 0% (0 0 440 220) + +translate 120 120 + +begin_block drawing +save + rotate 90 + drawPixmap solid.png 0 0 + + rotate 90 + drawPixmap solid.png 0 0 + + rotate 90 + drawPixmap solid.png 0 0 + + rotate 90 + drawPixmap solid.png 0 0 +restore +end_block + +resetMatrix + +translate 340 120 +repeat_block drawing + +resetMatrix + +drawText 50 240 "Normal X form" +drawText 270 240 "Smooth xform" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/pixmap_scaling.qps b/tests/auto/integrationtests/lancelot/scripts/pixmap_scaling.qps new file mode 100644 index 0000000000..651896f4a3 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pixmap_scaling.qps @@ -0,0 +1,224 @@ +# Version: 1 +# CheckVsReference: 0% (0 30 600 70) +# CheckVsReference: 0% (290 130 280 60) +# CheckVsReference: 0% (0 180 250 90) + +# Hurra! Force line endings (?) + +translate 5 25 +setFont "arial" 8 + +save + drawText 15 0 "opaque image" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawImage solid2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawImage solid2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawImage solid2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawImage solid2x2.png 0 0 + restore + + +restore + +save + translate 150 0 + drawText 15 0 "alpha image" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawImage alpha2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawImage alpha2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawImage alpha2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawImage alpha2x2.png 0 0 + restore +restore + + +save + translate 0 150 + drawText 15 0 "solid pixmap" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawPixmap solid2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawPixmap solid2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawPixmap solid2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawPixmap solid2x2.png 0 0 + restore +restore + + +save + translate 150 150 + drawText 15 0 "alpha pixmap" + translate 50 50 + save + translate 1 1 + scale 20 20 + drawPixmap alpha2x2.png 0 0 + restore + save + translate -1 1 + scale -20 20 + drawPixmap alpha2x2.png 0 0 + restore + save + translate 1 -1 + scale 20 -20 + drawPixmap alpha2x2.png 0 0 + restore + save + translate -1 -1 + scale -20 -20 + drawPixmap alpha2x2.png 0 0 + restore +restore + + +save + translate 300 10 + save + drawText 0 -10 "subrect solid image" + drawImage solid2x2.png 0 0 50 5 0 0.0 2 0.2 + drawImage solid2x2.png 0 5 50 5 0 0.2 2 0.2 + drawImage solid2x2.png 0 10 50 5 0 0.4 2 0.2 + drawImage solid2x2.png 0 15 50 5 0 0.6 2 0.2 + drawImage solid2x2.png 0 20 50 5 0 0.8 2 0.2 + drawImage solid2x2.png 0 25 50 5 0 1.0 2 0.2 + drawImage solid2x2.png 0 30 50 5 0 1.2 2 0.2 + drawImage solid2x2.png 0 35 50 5 0 1.4 2 0.2 + drawImage solid2x2.png 0 40 50 5 0 1.6 2 0.2 + drawImage solid2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawImage solid2x2.png 0 0 5 50 0.0 0 0.2 2 + drawImage solid2x2.png 5 0 5 50 0.2 0 0.2 2 + drawImage solid2x2.png 10 0 5 50 0.4 0 0.2 2 + drawImage solid2x2.png 15 0 5 50 0.6 0 0.2 2 + drawImage solid2x2.png 20 0 5 50 0.8 0 0.2 2 + drawImage solid2x2.png 25 0 5 50 1.0 0 0.2 2 + drawImage solid2x2.png 30 0 5 50 1.2 0 0.2 2 + drawImage solid2x2.png 35 0 5 50 1.4 0 0.2 2 + drawImage solid2x2.png 40 0 5 50 1.6 0 0.2 2 + drawImage solid2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + + save + translate 150 0 + drawText 0 -10 "subrect solid image" + drawImage alpha2x2.png 0 0 50 5 0 0.0 2 0.2 + drawImage alpha2x2.png 0 5 50 5 0 0.2 2 0.2 + drawImage alpha2x2.png 0 10 50 5 0 0.4 2 0.2 + drawImage alpha2x2.png 0 15 50 5 0 0.6 2 0.2 + drawImage alpha2x2.png 0 20 50 5 0 0.8 2 0.2 + drawImage alpha2x2.png 0 25 50 5 0 1.0 2 0.2 + drawImage alpha2x2.png 0 30 50 5 0 1.2 2 0.2 + drawImage alpha2x2.png 0 35 50 5 0 1.4 2 0.2 + drawImage alpha2x2.png 0 40 50 5 0 1.6 2 0.2 + drawImage alpha2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawImage alpha2x2.png 0 0 5 50 0.0 0 0.2 2 + drawImage alpha2x2.png 5 0 5 50 0.2 0 0.2 2 + drawImage alpha2x2.png 10 0 5 50 0.4 0 0.2 2 + drawImage alpha2x2.png 15 0 5 50 0.6 0 0.2 2 + drawImage alpha2x2.png 20 0 5 50 0.8 0 0.2 2 + drawImage alpha2x2.png 25 0 5 50 1.0 0 0.2 2 + drawImage alpha2x2.png 30 0 5 50 1.2 0 0.2 2 + drawImage alpha2x2.png 35 0 5 50 1.4 0 0.2 2 + drawImage alpha2x2.png 40 0 5 50 1.6 0 0.2 2 + drawImage alpha2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + + save + translate 0 100 + drawText 0 -10 "subrect alpha pixmap" + drawPixmap solid2x2.png 0 0 50 5 0 0.0 2 0.2 + drawPixmap solid2x2.png 0 5 50 5 0 0.2 2 0.2 + drawPixmap solid2x2.png 0 10 50 5 0 0.4 2 0.2 + drawPixmap solid2x2.png 0 15 50 5 0 0.6 2 0.2 + drawPixmap solid2x2.png 0 20 50 5 0 0.8 2 0.2 + drawPixmap solid2x2.png 0 25 50 5 0 1.0 2 0.2 + drawPixmap solid2x2.png 0 30 50 5 0 1.2 2 0.2 + drawPixmap solid2x2.png 0 35 50 5 0 1.4 2 0.2 + drawPixmap solid2x2.png 0 40 50 5 0 1.6 2 0.2 + drawPixmap solid2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawPixmap solid2x2.png 0 0 5 50 0.0 0 0.2 2 + drawPixmap solid2x2.png 5 0 5 50 0.2 0 0.2 2 + drawPixmap solid2x2.png 10 0 5 50 0.4 0 0.2 2 + drawPixmap solid2x2.png 15 0 5 50 0.6 0 0.2 2 + drawPixmap solid2x2.png 20 0 5 50 0.8 0 0.2 2 + drawPixmap solid2x2.png 25 0 5 50 1.0 0 0.2 2 + drawPixmap solid2x2.png 30 0 5 50 1.2 0 0.2 2 + drawPixmap solid2x2.png 35 0 5 50 1.4 0 0.2 2 + drawPixmap solid2x2.png 40 0 5 50 1.6 0 0.2 2 + drawPixmap solid2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + + save + translate 150 100 + drawText 0 -10 "subrect alpha pixmap" + drawPixmap alpha2x2.png 0 0 50 5 0 0.0 2 0.2 + drawPixmap alpha2x2.png 0 5 50 5 0 0.2 2 0.2 + drawPixmap alpha2x2.png 0 10 50 5 0 0.4 2 0.2 + drawPixmap alpha2x2.png 0 15 50 5 0 0.6 2 0.2 + drawPixmap alpha2x2.png 0 20 50 5 0 0.8 2 0.2 + drawPixmap alpha2x2.png 0 25 50 5 0 1.0 2 0.2 + drawPixmap alpha2x2.png 0 30 50 5 0 1.2 2 0.2 + drawPixmap alpha2x2.png 0 35 50 5 0 1.4 2 0.2 + drawPixmap alpha2x2.png 0 40 50 5 0 1.6 2 0.2 + drawPixmap alpha2x2.png 0 45 50 5 0 1.8 2 0.2 + translate 60 0 + drawPixmap alpha2x2.png 0 0 5 50 0.0 0 0.2 2 + drawPixmap alpha2x2.png 5 0 5 50 0.2 0 0.2 2 + drawPixmap alpha2x2.png 10 0 5 50 0.4 0 0.2 2 + drawPixmap alpha2x2.png 15 0 5 50 0.6 0 0.2 2 + drawPixmap alpha2x2.png 20 0 5 50 0.8 0 0.2 2 + drawPixmap alpha2x2.png 25 0 5 50 1.0 0 0.2 2 + drawPixmap alpha2x2.png 30 0 5 50 1.2 0 0.2 2 + drawPixmap alpha2x2.png 35 0 5 50 1.4 0 0.2 2 + drawPixmap alpha2x2.png 40 0 5 50 1.6 0 0.2 2 + drawPixmap alpha2x2.png 45 0 5 50 1.8 0 0.2 2 + restore + +restore \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/pixmap_subpixel.qps b/tests/auto/integrationtests/lancelot/scripts/pixmap_subpixel.qps new file mode 100644 index 0000000000..908f7c3465 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pixmap_subpixel.qps @@ -0,0 +1,117 @@ +# Version: 1 +# CheckVsReference: 5% + + +translate 50 50 + +# Pixmaps at 0.1 offset, unclipped +begin_block draw_pixmaps +save + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 + drawPixmap border.png 0 0 + translate 20.1 0.1 +restore +end_block + +# Tiled pixmaps at 0.1 offsets, unclipped +translate 0 50 +begin_block draw_tiled +save + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 + drawTiledPixmap border.png 0 0 16 16 0 0 + translate 20.1 0.1 +restore +end_block + + +path_moveTo clip 0 0 +path_lineTo clip width 0 +path_lineTo clip width 400 +path_lineTo clip 0 height +setClipPath clip + +translate 0 50 +# Pixmaps at 0.1 offset, clipped +repeat_block draw_pixmaps + + +# Tiled pixmaps at 0.1 offsets... +translate 0 50 +repeat_block draw_tiled + diff --git a/tests/auto/integrationtests/lancelot/scripts/pixmaps.qps b/tests/auto/integrationtests/lancelot/scripts/pixmaps.qps new file mode 100644 index 0000000000..8e60997acc --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/pixmaps.qps @@ -0,0 +1,106 @@ +# Version: 1 +# CheckVsReference: 1% (0 0 690 580) + + +setRenderHint Antialiasing + +setPen #00ff00 + +pixmap_load dome_argb32.png the_pixmap +begin_block draw_stuff + +save + + # standard draw + drawPixmap the_pixmap 0 0 + + # sub recting + translate 120 0 + drawPixmap the_pixmap 0 0 40 40 0 0 40 40 + drawPixmap the_pixmap 60 0 40 40 60 0 40 40 + drawPixmap the_pixmap 0 60 40 40 0 60 40 40 + drawPixmap the_pixmap 60 60 40 40 60 60 40 40 + drawPixmap the_pixmap 0 40 40 20 0 40 40 20 + drawPixmap the_pixmap 60 40 40 20 60 40 40 20 + drawPixmap the_pixmap 40 0 20 100 40 0 20 100 + + # subrecting w/scale + translate 120 0 + drawPixmap the_pixmap 0 0 50 50 0 0 25 25 + drawPixmap the_pixmap 50 0 50 50 25 0 25 25 + drawPixmap the_pixmap 0 50 50 50 0 25 25 25 + drawPixmap the_pixmap 50 50 50 50 25 25 25 25 + + # subrecting w/scale & smooth xform + translate 120 0 + setRenderHint SmoothPixmapTransformation + drawPixmap the_pixmap 0 0 50 50 0 0 25 25 + drawPixmap the_pixmap 50 0 50 50 25 0 25 25 + drawPixmap the_pixmap 0 50 50 50 0 25 25 25 + drawPixmap the_pixmap 50 50 50 50 25 25 25 25 + + + # Rotation w/o smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform off + rotate 10 + drawPixmap the_pixmap 0 0 + restore + + # Rotation w smooth xform + translate 120 0 + save + setRenderHint SmoothPixmapTransform + rotate 10 + drawPixmap the_pixmap 0 0 + restore + +restore + +end_block + + +translate 0 120 +pixmap_load dome_rgb32.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_indexed.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_indexed_mask.png the_pixmap +repeat_block draw_stuff + +translate 0 120 +pixmap_load dome_mono.png the_pixmap +repeat_block draw_stuff + + +resetMatrix +translate 700 60 +setPen black +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" +resetMatrix +translate 0 600 +drawText 0 0 "normal" +translate 120 0 +drawText 0 0 "subrect" +translate 120 0 +drawText 0 0 "subrect scale" +translate 120 0 +drawText 0 0 "subrect scale smooth" +translate 120 0 +drawText 0 0 "xform" +translate 120 0 +drawText 0 0 "smooth xform" +translate 120 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/porter_duff.qps b/tests/auto/integrationtests/lancelot/scripts/porter_duff.qps new file mode 100644 index 0000000000..166e48a57f --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/porter_duff.qps @@ -0,0 +1,251 @@ +# Version: 1 +# CheckVsReference: 5% + + +translate 0 50 + +surface_begin 0 0 100 100 + +begin_block predraw +setRenderHint Antialiasing +setPen nopen +setBrush 0x7f000000 +drawEllipse 10 10 80 80 +end_block + +setCompositionMode SourceOver + +begin_block postdraw + + +setBrush 0x1fff0000 +drawRect 0 0 50 50 + +setBrush 0xdf00ff00 +drawRect 50 50 50 50 + +setBrush 0x7f0000ff +drawEllipse 30 30 40 40 + +# a black rectangle around +setCompositionMode SourceOver +setPen black +setBrush nobrush +drawRect 0.5 0.5 99 99 + +end_block +surface_end + + +# Destination over +surface_begin 100 0 100 100 +repeat_block predraw +setCompositionMode DestinationOver +repeat_block postdraw +surface_end + + +# Clear +surface_begin 200 0 100 100 +repeat_block predraw +setCompositionMode Clear +repeat_block postdraw +surface_end + + +# Source +surface_begin 300 0 100 100 +repeat_block predraw +setCompositionMode Source +repeat_block postdraw +surface_end + + +# Destination +surface_begin 400 0 100 100 +repeat_block predraw +setCompositionMode Destination +repeat_block postdraw +surface_end + + +# Source In +surface_begin 500 0 100 100 +repeat_block predraw +setCompositionMode SourceIn +repeat_block postdraw +surface_end + +translate 0 50 + +# Destination In +surface_begin 0 100 100 100 +repeat_block predraw +setCompositionMode DestinationIn +repeat_block postdraw +surface_end + + +# Source Out +surface_begin 100 100 100 100 +repeat_block predraw +setCompositionMode SourceOut +repeat_block postdraw +surface_end + + +# Destination Out +surface_begin 200 100 100 100 +repeat_block predraw +setCompositionMode DestinationOut +repeat_block postdraw +surface_end + + +# SourceAtop +surface_begin 300 100 100 100 +repeat_block predraw +setCompositionMode SourceAtop +repeat_block postdraw +surface_end + + +# DestinationAtop +surface_begin 400 100 100 100 +repeat_block predraw +setCompositionMode DestinationAtop +repeat_block postdraw +surface_end + + +# Xor +surface_begin 500 100 100 100 +repeat_block predraw +setCompositionMode Xor +repeat_block postdraw +surface_end + +translate 0 50 + +# Plus +surface_begin 0 200 100 100 +repeat_block predraw +setCompositionMode Plus +repeat_block postdraw +surface_end + + +# Multiply +surface_begin 100 200 100 100 +repeat_block predraw +setCompositionMode Multiply +repeat_block postdraw +surface_end + + +# Screen +surface_begin 200 200 100 100 +repeat_block predraw +setCompositionMode Screen +repeat_block postdraw +surface_end + + +# Overlay +surface_begin 300 200 100 100 +repeat_block predraw +setCompositionMode Overlay +repeat_block postdraw +surface_end + + +# Darken +surface_begin 400 200 100 100 +repeat_block predraw +setCompositionMode Darken +repeat_block postdraw +surface_end + + +# Lighten +surface_begin 500 200 100 100 +repeat_block predraw +setCompositionMode Lighten +repeat_block postdraw +surface_end + +translate 0 50 + +# ColorDodge +surface_begin 0 300 100 100 +repeat_block predraw +setCompositionMode ColorDodge +repeat_block postdraw +surface_end + + +# Multiply +surface_begin 100 300 100 100 +repeat_block predraw +setCompositionMode ColorBurn +repeat_block postdraw +surface_end + + +# Screen +surface_begin 200 300 100 100 +repeat_block predraw +setCompositionMode HardLight +repeat_block postdraw +surface_end + + +# Overlay +surface_begin 300 300 100 100 +repeat_block predraw +setCompositionMode SoftLight +repeat_block postdraw +surface_end + + +# Darken +surface_begin 400 300 100 100 +repeat_block predraw +setCompositionMode Difference +repeat_block postdraw +surface_end + + +# Lighten +surface_begin 500 300 100 100 +repeat_block predraw +setCompositionMode Exclusion +repeat_block postdraw +surface_end + +resetMatrix + +drawText 0 50 "SourceOver" +drawText 100 50 "DestinationOver" +drawText 200 50 "Clear" +drawText 300 50 "Source" +drawText 400 50 "Destination" +drawText 500 50 "SourceIn" +drawText 0 200 "DestinationIn" +drawText 100 200 "SourceOut" +drawText 200 200 "DestinationOut" +drawText 300 200 "SourceAtop" +drawText 400 200 "DestinationAtop" +drawText 500 200 "Xor" +drawText 0 350 "Plus" +drawText 100 350 "Multiply" +drawText 200 350 "Screen" +drawText 300 350 "Overlay" +drawText 400 350 "Darken" +drawText 500 350 "Lighten" +drawText 0 500 "ColorDodge" +drawText 100 500 "ColorBurn" +drawText 200 500 "HardLight" +drawText 300 500 "SoftLight" +drawText 400 500 "Difference" +drawText 500 500 "Exclusion" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/porter_duff2.qps b/tests/auto/integrationtests/lancelot/scripts/porter_duff2.qps new file mode 100644 index 0000000000..a792d9b278 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/porter_duff2.qps @@ -0,0 +1,261 @@ +# Version: 1 +# CheckVsReference: 1% (0 50 600 100) +# CheckVsReference: 1% (0 200 600 100) +# CheckVsReference: 1% (0 350 600 100) +# CheckVsReference: 1% (0 500 600 100) + +translate 0 50 + +surface_begin 0 0 100 100 + +begin_block predraw +setRenderHint Antialiasing +setPen nopen +gradient_clearStops +gradient_appendStop 0 efff0000 +gradient_appendStop 0.5 dfffff00 +gradient_appendStop 1 ef00ff00 + +gradient_setSpread PadSpread +gradient_setLinear 10 10 90 90 +drawEllipse 10 10 80 80 +end_block + +setCompositionMode SourceOver + +begin_block postdraw + +gradient_clearStops +gradient_appendStop 0 afff0000 +gradient_appendStop 0.5 cf0000ff +gradient_appendStop 1 bf00ff00 + +gradient_setSpread PadSpread +gradient_setLinear 0 0 100 0 +drawEllipse 10 10 30 30 +drawEllipse 10 60 30 30 +drawEllipse 60 60 30 30 +drawEllipse 60 10 30 30 +drawEllipse 35 35 30 30 + +# a black rectangle around +setCompositionMode SourceOver +setPen black +setBrush nobrush +drawRect 0.5 0.5 99 99 + +end_block +surface_end + +# Destination over +surface_begin 100 0 100 100 +repeat_block predraw +setCompositionMode DestinationOver +repeat_block postdraw +surface_end + + +# Clear +surface_begin 200 0 100 100 +repeat_block predraw +setCompositionMode Clear +repeat_block postdraw +surface_end + + +# Source +surface_begin 300 0 100 100 +repeat_block predraw +setCompositionMode Source +repeat_block postdraw +surface_end + + +# Destination +surface_begin 400 0 100 100 +repeat_block predraw +setCompositionMode Destination +repeat_block postdraw +surface_end + + +# Source In +surface_begin 500 0 100 100 +repeat_block predraw +setCompositionMode SourceIn +repeat_block postdraw +surface_end + +translate 0 50 + +# Destination In +surface_begin 0 100 100 100 +repeat_block predraw +setCompositionMode DestinationIn +repeat_block postdraw +surface_end + + +# Source Out +surface_begin 100 100 100 100 +repeat_block predraw +setCompositionMode SourceOut +repeat_block postdraw +surface_end + + +# Destination Out +surface_begin 200 100 100 100 +repeat_block predraw +setCompositionMode DestinationOut +repeat_block postdraw +surface_end + + +# SourceAtop +surface_begin 300 100 100 100 +repeat_block predraw +setCompositionMode SourceAtop +repeat_block postdraw +surface_end + + +# DestinationAtop +surface_begin 400 100 100 100 +repeat_block predraw +setCompositionMode DestinationAtop +repeat_block postdraw +surface_end + + +# Xor +surface_begin 500 100 100 100 +repeat_block predraw +setCompositionMode Xor +repeat_block postdraw +surface_end + +translate 0 50 + +# Plus +surface_begin 0 200 100 100 +repeat_block predraw +setCompositionMode Plus +repeat_block postdraw +surface_end + + +# Multiply +surface_begin 100 200 100 100 +repeat_block predraw +setCompositionMode Multiply +repeat_block postdraw +surface_end + + +# Screen +surface_begin 200 200 100 100 +repeat_block predraw +setCompositionMode Screen +repeat_block postdraw +surface_end + + +# Overlay +surface_begin 300 200 100 100 +repeat_block predraw +setCompositionMode Overlay +repeat_block postdraw +surface_end + + +# Darken +surface_begin 400 200 100 100 +repeat_block predraw +setCompositionMode Darken +repeat_block postdraw +surface_end + + +# Lighten +surface_begin 500 200 100 100 +repeat_block predraw +setCompositionMode Lighten +repeat_block postdraw +surface_end + +translate 0 50 + +# ColorDodge +surface_begin 0 300 100 100 +repeat_block predraw +setCompositionMode ColorDodge +repeat_block postdraw +surface_end + + +# Multiply +surface_begin 100 300 100 100 +repeat_block predraw +setCompositionMode ColorBurn +repeat_block postdraw +surface_end + + +# Screen +surface_begin 200 300 100 100 +repeat_block predraw +setCompositionMode HardLight +repeat_block postdraw +surface_end + + +# Overlay +surface_begin 300 300 100 100 +repeat_block predraw +setCompositionMode SoftLight +repeat_block postdraw +surface_end + + +# Darken +surface_begin 400 300 100 100 +repeat_block predraw +setCompositionMode Difference +repeat_block postdraw +surface_end + + +# Lighten +surface_begin 500 300 100 100 +repeat_block predraw +setCompositionMode Exclusion +repeat_block postdraw +surface_end + +resetMatrix + +drawText 0 50 "SourceOver" +drawText 100 50 "DestinationOver" +drawText 200 50 "Clear" +drawText 300 50 "Source" +drawText 400 50 "Destination" +drawText 500 50 "SourceIn" +drawText 0 200 "DestinationIn" +drawText 100 200 "SourceOut" +drawText 200 200 "DestinationOut" +drawText 300 200 "SourceAtop" +drawText 400 200 "DestinationAtop" +drawText 500 200 "Xor" +drawText 0 350 "Plus" +drawText 100 350 "Multiply" +drawText 200 350 "Screen" +drawText 300 350 "Overlay" +drawText 400 350 "Darken" +drawText 500 350 "Lighten" +drawText 0 500 "ColorDodge" +drawText 100 500 "ColorBurn" +drawText 200 500 "HardLight" +drawText 300 500 "SoftLight" +drawText 400 500 "Difference" +drawText 500 500 "Exclusion" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/primitives.qps b/tests/auto/integrationtests/lancelot/scripts/primitives.qps new file mode 100644 index 0000000000..f44ba27566 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/primitives.qps @@ -0,0 +1,184 @@ +# Version: 1#Version: 1 +# CheckVsReference: 5% + + +# CheckVsReference: 5% + +setBrush #ff7f7fff +setPen black 1 solidline +translate 20 20 +begin_block testblock +save +drawRect 0 0 10 10 +drawRect 20 0 20 10 +drawRect 0 20 10 20 +drawRect 20 20 20 20 +translate 50 0 +setPen NoPen +drawRect 0 0 10 10 +drawRect 20 0 20 10 +drawRect 0 20 10 20 +drawRect 20 20 20 20 +restore +save +translate 0 50 +drawEllipse 0 0 10 10 +drawEllipse 20 0 20 10 +drawEllipse 0 20 10 20 +drawEllipse 20 20 20 20 +translate 50 0 +setPen NoPen +drawEllipse 0 0 10 10 +drawEllipse 20 0 20 10 +drawEllipse 0 20 10 20 +drawEllipse 20 20 20 20 +restore +save +translate 0 100 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] +save +translate 0 50 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] Winding +translate 0 45 +drawPolyline [ 0 0 50 0 25 25 ] +restore +setPen NoPen +translate 50 0 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] +save +translate 0 50 +drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] Winding +restore +save +translate -20 100 +drawPie 0 0 50 50 0 1500 +restore +restore +end_block +setPen black 1 SolidLine FlatCap +translate 200 0 +scale 2 1 +rotate 10 +repeat_block testblock +resetMatrix +translate 0 250 +setBrush 7f7f7fff +translate 20 20 +repeat_block testblock +setPen black 1 SolidLine FlatCap +translate 200 0 +scale 2 1 +rotate 10 +repeat_block testblock +resetMatrix +save +setRenderHint LineAntialiasing +setBrush 7f7fff +translate 20 500 +repeat_block testblock +translate 200 0 +scale 2 1 +rotate 10 +repeat_block testblock +restore +setRenderHint LineAntialiasing false +translate 420 20 +begin_block lines +drawLine 0 0 100 0 +drawLine 0 0 100 10 +drawLine 0 0 100 20 +drawLine 0 0 100 30 +drawLine 0 0 100 40 +drawLine 0 0 100 50 +drawLine 0 0 100 60 +drawLine 0 0 100 70 +drawLine 0 0 100 80 +drawLine 0 0 100 90 +drawLine 0 0 100 100 +drawLine 0 0 90 100 +drawLine 0 0 80 100 +drawLine 0 0 70 100 +drawLine 0 0 60 100 +drawLine 0 0 50 100 +drawLine 0 0 40 100 +drawLine 0 0 30 100 +drawLine 0 0 20 100 +drawLine 0 0 10 100 +drawLine 0 0 0 100 +end_block +setRenderHint LineAntialiasing +translate 0 120 +repeat_block lines +translate 0 120 +scale 5 2 +repeat_block lines +resetMatrix +translate 420 500 +begin_block roundedrects +save +drawRoundedRect 0 0 50 30 5 5 +translate 60 0 +drawRoundedRect 0 0 50 30 7.5 7.5 +translate 60 0 +drawRoundedRect 0 0 50 30 10 10 +translate 60 0 +drawRoundedRect 0 0 50 30 12.5 12.5 +translate 60 0 +drawRoundedRect 0 0 50 30 15 15 +restore +save +translate 0 40 +drawRoundedRect 0 0 50 30 20 20 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 40 40 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 60 60 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 80 80 RelativeSize +translate 60 0 +drawRoundedRect 0 0 50 30 100 100 RelativeSize +restore +end_block +translate 0.5 80.5 +repeat_block roundedrects +translate -0.5 79.5 +setRenderHint Antialiasing off +repeat_block roundedrects +resetMatrix +setRenderHint Antialiasing off +setPen black 1 +begin_block drawShapes +translate 550.5 25 +rotate 45 +setBrush nobrush +drawEllipse -10 -10 20 20 +drawLine 10 0 50 0 +drawRect 50 -7 14 14 +resetMatrix +end_block +setPen black 2 +translate 25 0 +repeat_block drawShapes +setPen black 3 +translate 50 0 +repeat_block drawShapes +setPen black 4 +translate 75 0 +repeat_block drawShapes +resetMatrix +setRenderHint Antialiasing off +setPen nopen +translate 550 100 +setBrush #7f7f7fff +drawRect -0.5 -0.5 21 21 +setBrush red +drawEllipse 0 0 20 20 +setBrush nobrush +setPen black +drawEllipse 0 0 20 20 +translate 25 0 +setPen nopen +setBrush #7f7f7fff +drawRect 0 0 20 20 +setBrush red +drawEllipse 0 0 20 20 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/radial_gradients.qps b/tests/auto/integrationtests/lancelot/scripts/radial_gradients.qps new file mode 100644 index 0000000000..b55df8bde6 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/radial_gradients.qps @@ -0,0 +1,99 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 600 400) + +path_addRect path 400 0 80 80 +path_addEllipse path 440 40 60 60 + +setRenderHint Antialiasing + +setPen black + +begin_block gradients +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setRadial 20 20 50 40 40 +drawRect 0 0 100 100 + +gradient_setSpread ReflectSpread +gradient_setRadial 120 20 50 140 40 +drawEllipse 100 0 100 100 + +gradient_setSpread RepeatSpread +gradient_setRadial 220 20 50 240 40 +drawRoundRect 200 0 100 100 + +gradient_clearStops +gradient_appendStop 0 3f7f7fff +gradient_appendStop 0.5 dfdfffff +gradient_appendStop 1 7f00007f + +gradient_setSpread PadSpread +gradient_setRadial 320 20 50 340 40 +drawPolygon [300 0 390 0 350 99] + +gradient_setSpread ReflectSpread +gradient_setRadial 420 20 50 440 40 +drawPath path + +gradient_setSpread RepeatSpread +gradient_setRadial 520 20 50 540 40 +drawPie 500 0 100 100 720 4320 +end_block + +translate 0 100 +scale 1 2 +repeat_block gradients + +resetMatrix +translate 0 300 +brushTranslate 30 0 +brushScale 0.9 0.9 +brushRotate 20 +repeat_block gradients + +# Some helpful info perhaps? +resetMatrix +setPen black + +drawText 610 50 "No XForm" +drawText 610 200 "scale 1x2" +drawText 610 300 "brush transform" +drawText 10 450 "Pad" +drawText 110 450 "Reflect" +drawText 210 450 "Repeat" +drawText 310 450 "Pad w/alpha" +drawText 410 450 "Reflect w/alpha" +drawText 510 450 "Repeat w/alpha" + +# Radius and focal indicators +setPen 3f000000 +setBrush nobrush + +begin_block ellipse_draw +setClipRect 0 0 100 100 +drawEllipse -30 -30 100 100 +drawEllipse 35 35 11 11 +translate 100 0 +end_block + +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw + +resetMatrix +translate 0 100 +scale 1 2 +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw +repeat_block ellipse_draw \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/radial_gradients_perspectives.qps b/tests/auto/integrationtests/lancelot/scripts/radial_gradients_perspectives.qps new file mode 100644 index 0000000000..4557354dce --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/radial_gradients_perspectives.qps @@ -0,0 +1,62 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen #00ff00 + +translate 10 10 +# standard draw +begin_block gradient +gradient_clearStops +gradient_appendStop 0 red +gradient_appendStop 0.25 orange +gradient_appendStop 0.5 yellow +gradient_appendStop 0.8 green +gradient_appendStop 1 cyan + +gradient_setSpread PadSpread +gradient_setRadial 110 100 230 230 240 +drawRect 0 0 300 300 +end_block gradient + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block gradient +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block gradient +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block gradient +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/rasterops.qps b/tests/auto/integrationtests/lancelot/scripts/rasterops.qps new file mode 100644 index 0000000000..21f943b543 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/rasterops.qps @@ -0,0 +1,87 @@ +# Version: 1 +# CheckVsReference: 5% + +setPen NoPen + +setBrush black +drawRect 10 10 60 500 + +setCompositionMode SourceOrDestination +translate 20 20 + +begin_block drawShape + setBrush 0xffff0000 + drawEllipse 5 5 30 30 + setBrush 0xff00ff00 + drawRect 0 0 20 20 + setBrush 0xff0000ff + drawRect 20 20 20 20 +end_block + +begin_block loop + setCompositionMode SourceAndDestination + translate 0 50 +repeat_block drawShape + +setCompositionMode SourceXorDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceAndNotDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceOrNotDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceXorDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSource +translate 0 50 +repeat_block drawShape + +setCompositionMode NotSourceAndDestination +translate 0 50 +repeat_block drawShape + +setCompositionMode SourceAndNotDestination +translate 0 50 +repeat_block drawShape +end_block + +resetMatrix +setCompositionMode Source +setBrush white +drawRect 100 10 60 500 +translate 110 20 +repeat_block loop + +resetMatrix +setCompositionMode Source +translate 190 20 +repeat_block loop + +resetMatrix +setPen black +setCompositionMode SourceOver +translate 250 45 +drawText 20 0 "Or ROP" +translate 0 50 +drawText 20 0 "And ROP" +translate 0 50 +drawText 20 0 "Xor ROP" +translate 0 50 +drawText 20 0 "Nor ROP" +translate 0 50 +drawText 20 0 "Nand ROP" +translate 0 50 +drawText 0 0 "NSrcXorDst ROP" +translate 0 50 +drawText 20 0 "NSrc ROP" +translate 0 50 +drawText 0 0 "NSrcAndDst ROP" +translate 0 50 +drawText 0 0 "SrcAndNDst ROP" \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/sizes.qps b/tests/auto/integrationtests/lancelot/scripts/sizes.qps new file mode 100644 index 0000000000..68e01c3262 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/sizes.qps @@ -0,0 +1,90 @@ +# Version: 1 +# CheckVsReference: 5% + +setPen NoPen +setBrush black + +translate 10 10 + +begin_block testblock +drawRect 0 0 10 10 +drawRect 20 0 11 11 +drawRect 40 0 12 12 +drawRect 60 0 13 13 +drawRect 80 0 14 14 +drawRect 100 0 15 15 +drawRect 120 0 16 16 +drawRect 140 0 17 17 +drawRect 160 0 18 18 +drawRect 180 0 19 19 + +drawEllipse 0 20 10 10 +drawEllipse 20 20 11 11 +drawEllipse 40 20 12 12 +drawEllipse 60 20 13 13 +drawEllipse 80 20 14 14 +drawEllipse 100 20 15 15 +drawEllipse 120 20 16 16 +drawEllipse 140 20 17 17 +drawEllipse 160 20 18 18 +drawEllipse 180 20 19 19 + +drawRoundRect 0 40 10 10 +drawRoundRect 20 40 11 11 +drawRoundRect 40 40 12 12 +drawRoundRect 60 40 13 13 +drawRoundRect 80 40 14 14 +drawRoundRect 100 40 15 15 +drawRoundRect 120 40 16 16 +drawRoundRect 140 40 17 17 +drawRoundRect 160 40 18 18 +drawRoundRect 180 40 19 19 + +drawPie 0 60 10 10 0 4320 +drawPie 20 60 11 11 0 4320 +drawPie 40 60 12 12 0 4320 +drawPie 60 60 13 13 0 4320 +drawPie 80 60 14 14 0 4320 +drawPie 100 60 15 15 0 4320 +drawPie 120 60 16 16 0 4320 +drawPie 140 60 17 17 0 4320 +drawPie 160 60 18 18 0 4320 +drawPie 180 60 19 19 0 4320 + +drawArc 0 80 10 10 0 4320 +drawArc 20 80 11 11 0 4320 +drawArc 40 80 12 12 0 4320 +drawArc 60 80 13 13 0 4320 +drawArc 80 80 14 14 0 4320 +drawArc 100 80 15 15 0 4320 +drawArc 120 80 16 16 0 4320 +drawArc 140 80 17 17 0 4320 +drawArc 160 80 18 18 0 4320 +drawArc 180 80 19 19 0 4320 + +drawChord 0 100 10 10 0 4320 +drawChord 20 100 11 11 0 4320 +drawChord 40 100 12 12 0 4320 +drawChord 60 100 13 13 0 4320 +drawChord 80 100 14 14 0 4320 +drawChord 100 100 15 15 0 4320 +drawChord 120 100 16 16 0 4320 +drawChord 140 100 17 17 0 4320 +drawChord 160 100 18 18 0 4320 +drawChord 180 100 19 19 0 4320 + +end_block + +setPen red +translate 0 150 +repeat_block testblock + +setRenderHint LineAntialiasing + +setPen nopen +translate 0 150 +repeat_block testblock + +setPen red +translate 0 150 +repeat_block testblock diff --git a/tests/auto/integrationtests/lancelot/scripts/statictext.qps b/tests/auto/integrationtests/lancelot/scripts/statictext.qps new file mode 100644 index 0000000000..b62b623462 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/statictext.qps @@ -0,0 +1,122 @@ +drawStaticText -5 5 "Text that is drawn outside the bounds..." + +translate 20 20 +begin_block text_drawing +save + setFont "sansserif" 10 normal + drawStaticText 0 20 "sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 60 "sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "sansserif 10pt, bold italic" + + + translate 0 100 + setPen #7fff0000 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "alpha sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "alpha sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 60 "alpha sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "alpha sansserif 10pt, bold italic" + + + translate 0 100 + setPen black + save + scale 0.9 0.9 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 0 100 + setPen black + save + translate 200 90 + rotate 185 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 0 100 + gradient_appendStop 0 red + gradient_appendStop 0.5 #00ff00 + gradient_appendStop 1 blue + gradient_setLinear 0 0 200 0 + setPen brush + + setFont "sansserif" 10 normal + drawStaticText 0 0 "gradient sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 20 "gradient sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 40 "gradient sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 60 "gradient sansserif 10pt, bold italic" +restore +end_block + +translate 250 0 +drawStaticText 25 520 "clipped to rectangle" +save + setPen #3f000000 + setBrush nobrush + drawRect 20 0 100 500 + setClipRect 20 0 100 500 + setPen black + repeat_block text_drawing +restore + +translate 150 0 +drawStaticText 25 520 "clipped to path" +save + path_moveTo clip 20 0 + path_cubicTo clip 0 200 40 400 20 400 + path_lineTo clip 30 500 + path_lineTo clip 30 0 + path_lineTo clip 40 0 + path_lineTo clip 40 500 + path_lineTo clip 120 500 + path_lineTo clip 120 0 + path_lineTo clip 20 0 + setPen #3f000000 + setBrush nobrush + drawPath clip + setClipPath clip + setPen black + repeat_block text_drawing +restore diff --git a/tests/auto/integrationtests/lancelot/scripts/text.qps b/tests/auto/integrationtests/lancelot/scripts/text.qps new file mode 100644 index 0000000000..d7ee83290b --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/text.qps @@ -0,0 +1,124 @@ +# Version: 1 + +drawText -5 5 "Text that is drawn outside the bounds..." + +translate 20 20 +begin_block text_drawing +save + setFont "sansserif" 10 normal + drawText 0 20 "sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawText 0 60 "sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "sansserif 10pt, bold italic" + + + translate 0 100 + setPen #7fff0000 + + setFont "sansserif" 10 normal + drawText 0 20 "alpha sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "alpha sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawText 0 60 "alpha sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "alpha sansserif 10pt, bold italic" + + + translate 0 100 + setPen black + save + scale 0.9 0.9 + + setFont "sansserif" 10 normal + drawText 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawText 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 0 100 + setPen black + save + translate 200 90 + rotate 185 + + setFont "sansserif" 10 normal + drawText 0 20 "scaled sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 40 "scaled sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawText 0 60 "scaled sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 80 "scaled sansserif 10pt, bold italic" + restore + + translate 0 100 + gradient_appendStop 0 red + gradient_appendStop 0.5 #00ff00 + gradient_appendStop 1 blue + gradient_setLinear 0 0 200 0 + setPen brush + + setFont "sansserif" 10 normal + drawText 0 0 "gradient sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawText 0 20 "gradient sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawText 0 40 "gradient sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawText 0 60 "gradient sansserif 10pt, bold italic" +restore +end_block + +translate 250 0 +drawText 25 520 "clipped to rectangle" +save + setPen #3f000000 + setBrush nobrush + drawRect 20 0 100 500 + setClipRect 20 0 100 500 + setPen black + repeat_block text_drawing +restore + +translate 150 0 +drawText 25 520 "clipped to path" +save + path_moveTo clip 20 0 + path_cubicTo clip 0 200 40 400 20 400 + path_lineTo clip 30 500 + path_lineTo clip 30 0 + path_lineTo clip 40 0 + path_lineTo clip 40 500 + path_lineTo clip 120 500 + path_lineTo clip 120 0 + path_lineTo clip 20 0 + setPen #3f000000 + setBrush nobrush + drawPath clip + setClipPath clip + setPen black + repeat_block text_drawing +restore \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/text_perspectives.qps b/tests/auto/integrationtests/lancelot/scripts/text_perspectives.qps new file mode 100644 index 0000000000..4c74306265 --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/text_perspectives.qps @@ -0,0 +1,102 @@ +# Version: 1 + + +setRenderHint Antialiasing + +setPen black + +translate 10 10 +# standard draw +begin_block text +setBrush gray +drawRect 0 0 300 300 + +setFont "times" 3 +drawText 10 10 "Hello World...." + +setFont "times" 4 +drawText 10 20 "Hello World...." + +setFont "times" 5 +drawText 10 30 "Hello World...." + +setFont "times" 6 +drawText 10 40 "Hello World...." + +setFont "times" 7 +drawText 10 50 "Hello World...." + +setFont "times" 8 +drawText 10 60 "Hello World...." + +setFont "times" 9 +drawText 10 70 "Hello World...." + +setFont "times" 10 +drawText 10 80 "Hello World...." + +setFont "times" 16 +drawText 10 100 "Hello World...." + +setFont "times" 17 +drawText 10 120 "Hello World...." + +setFont "times" 18 +drawText 10 140 "Hello World...." + +setFont "times" 20 +drawText 10 160 "Hello World...." + +setFont "times" 22 +drawText 10 180 "Hello World...." + +setFont "times" 24 +drawText 10 205 "Hello World...." + +setFont "times" 26 +drawText 10 230 "Hello World...." + +setFont "times" 32 +drawText 10 260 "Hello World...." +end_block text + +# Rotation w/o smooth xform +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 + repeat_block text +restore +restore + +translate 0 320 + +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 + repeat_block text +restore + +save +translate 350 0 +save + setRenderHint SmoothPixmapTransform on + mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 + repeat_block text +restore +restore + + +resetMatrix +setPen black +translate 125 20 +drawText 0 0 "No transform" +translate 350 0 +drawText 0 0 "Left Tilted" +resetMatrix +translate 125 350 +drawText 0 0 "Bottom Tilted" +translate 350 0 +drawText 0 0 "Right Tilted" +translate 120 0 \ No newline at end of file diff --git a/tests/auto/integrationtests/lancelot/scripts/tiled_pixmap.qps b/tests/auto/integrationtests/lancelot/scripts/tiled_pixmap.qps new file mode 100644 index 0000000000..9cb5e0dd1f --- /dev/null +++ b/tests/auto/integrationtests/lancelot/scripts/tiled_pixmap.qps @@ -0,0 +1,84 @@ +# Version: 1 +# CheckVsReference: 5% (0 0 639 638) + + +translate 0 10 +setRenderHint Antialiasing + +pixmap_load dome_argb32 the_pixmap + +begin_block draw_stuff +save + + # Standard draw + drawTiledPixmap the_pixmap 0 0 150 100 0 0 + + # Standard draw with offset + translate 160 0 + drawTiledPixmap the_pixmap 0 0 150 100 25 25 + + # xformed + translate 160 0 + save + translate 10 -10 + rotate 10 + setRenderHint SmoothPixmapTransform false + drawTiledPixmap the_pixmap 0 0 150 100 25 25 + restore + + # xformed with smooth xform + translate 160 0 + save + translate 10 -10 + rotate 10 + setRenderHint SmoothPixmapTransform + drawTiledPixmap the_pixmap 0 0 150 100 25 25 + restore +restore +end_block + +translate 0 120 +pixmap_load dome_rgb32 the_pixmap +repeat_block draw_stuff + + +translate 0 120 +pixmap_load dome_indexed the_pixmap +repeat_block draw_stuff + + +translate 0 120 +pixmap_load dome_indexed_mask the_pixmap +repeat_block draw_stuff + + +translate 0 120 +pixmap_load dome_mono the_pixmap +repeat_block draw_stuff + + +################################################################################ +# Some helpful text... +# + +resetMatrix +translate 650 80 +drawText 0 0 "32 bit w/alpha" +translate 0 120 +drawText 0 0 "32 bit w/o alpha" +translate 0 120 +drawText 0 0 "8 bit indexed" +translate 0 120 +drawText 0 0 "8 bit indexed w/mask" +translate 0 120 +drawText 0 0 "1 bit" + +resetMatrix +translate 10 630 +drawText 0 0 "normal" +translate 160 0 +drawText 0 0 "offset" +translate 160 0 +drawText 0 0 "xformed" +translate 160 0 +drawText 0 0 "smooth xformed" diff --git a/tests/auto/integrationtests/lancelot/tst_lancelot.cpp b/tests/auto/integrationtests/lancelot/tst_lancelot.cpp new file mode 100644 index 0000000000..07ed74ec6a --- /dev/null +++ b/tests/auto/integrationtests/lancelot/tst_lancelot.cpp @@ -0,0 +1,356 @@ +/**************************************************************************** +** +** 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 +#include "paintcommands.h" +#include +#include +#include +#include + +#ifndef QT_NO_OPENGL +#include +#endif + +#ifndef SRCDIR +#define SRCDIR "." +#endif + +class tst_Lancelot : public QObject +{ +Q_OBJECT + +public: + tst_Lancelot(); + + static bool simfail; + static PlatformInfo clientInfo; + +private: + enum GraphicsEngine { + Raster = 0, + OpenGL = 1 + }; + + bool setupTestSuite(const QStringList& blacklist); + void runTestSuite(GraphicsEngine engine, QImage::Format format); + ImageItem render(const ImageItem &item, GraphicsEngine engine, QImage::Format format); + void paint(QPaintDevice *device, const QStringList &script, const QString &filePath); + + BaselineProtocol proto; + ImageItemList baseList; + QHash scripts; + bool dryRunMode; + QString scriptsDir; + +private slots: + void initTestCase(); + void cleanupTestCase() {} + + void testRasterARGB32PM_data(); + void testRasterARGB32PM(); + void testRasterRGB32_data(); + void testRasterRGB32(); + void testRasterRGB16_data(); + void testRasterRGB16(); + +#ifndef QT_NO_OPENGL + void testOpenGL_data(); + void testOpenGL(); +#endif +}; + +bool tst_Lancelot::simfail = false; +PlatformInfo tst_Lancelot::clientInfo; + +tst_Lancelot::tst_Lancelot() +{ +} + +void tst_Lancelot::initTestCase() +{ + // Check and setup the environment. We treat failures because of test environment + // (e.g. script files not found) as just warnings, and not QFAILs, to avoid false negatives + // caused by environment or server instability + + if (!proto.connect(QLatin1String("tst_Lancelot"), &dryRunMode, clientInfo)) + QSKIP(qPrintable(proto.errorMessage()), SkipAll); + +#if defined(USE_RUNTIME_DIR) + scriptsDir = QCoreApplication::applicationDirPath() + "/scripts/"; +#else + scriptsDir = SRCDIR "/scripts/"; +#endif + QDir qpsDir(scriptsDir); + QStringList files = qpsDir.entryList(QStringList() << QLatin1String("*.qps"), QDir::Files | QDir::Readable); + if (files.isEmpty()) { + QWARN("No qps script files found in " + qpsDir.path().toLatin1()); + QSKIP("Aborted due to errors.", SkipAll); + } + + baseList.resize(files.count()); + ImageItemList::iterator it = baseList.begin(); + foreach(const QString& fileName, files) { + QFile file(scriptsDir + fileName); + file.open(QFile::ReadOnly); + QByteArray cont = file.readAll(); + scripts.insert(fileName, QString::fromLatin1(cont).split(QLatin1Char('\n'), QString::SkipEmptyParts)); + it->itemName = fileName; + it->itemChecksum = qChecksum(cont.constData(), cont.size()); + it++; + } +} + + +void tst_Lancelot::testRasterARGB32PM_data() +{ + QStringList localBlacklist; + if (!setupTestSuite(localBlacklist)) + QSKIP("Communication with baseline image server failed.", SkipAll); +} + + +void tst_Lancelot::testRasterARGB32PM() +{ + runTestSuite(Raster, QImage::Format_ARGB32_Premultiplied); +} + + +void tst_Lancelot::testRasterRGB32_data() +{ + QStringList localBlacklist; + if (!setupTestSuite(localBlacklist)) + QSKIP("Communication with baseline image server failed.", SkipAll); +} + + +void tst_Lancelot::testRasterRGB32() +{ + runTestSuite(Raster, QImage::Format_RGB32); +} + + +void tst_Lancelot::testRasterRGB16_data() +{ + QStringList localBlacklist; + if (!setupTestSuite(localBlacklist)) + QSKIP("Communication with baseline image server failed.", SkipAll); +} + + +void tst_Lancelot::testRasterRGB16() +{ + runTestSuite(Raster, QImage::Format_RGB16); +} + + +#ifndef QT_NO_OPENGL +void tst_Lancelot::testOpenGL_data() +{ + QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps"); + if (!setupTestSuite(localBlacklist)) + QSKIP("Communication with baseline image server failed.", SkipAll); +} + + +void tst_Lancelot::testOpenGL() +{ + bool ok = false; + QGLWidget glWidget; + if (glWidget.isValid() && glWidget.format().directRendering() + && ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) + || (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)) + && QGLFramebufferObject::hasOpenGLFramebufferObjects()) + { + glWidget.makeCurrent(); + if (!QByteArray((const char *)glGetString(GL_VERSION)).contains("Mesa")) + ok = true; + } + if (ok) + runTestSuite(OpenGL, QImage::Format_RGB32); + else + QSKIP("System under test does not meet preconditions for GL testing. Skipping.", SkipAll); +} +#endif + + +bool tst_Lancelot::setupTestSuite(const QStringList& blacklist) +{ + QTest::addColumn("baseline"); + + ImageItemList itemList(baseList); + if (!proto.requestBaselineChecksums(QTest::currentTestFunction(), &itemList)) { + QWARN(qPrintable(proto.errorMessage())); + return false; + } + + foreach(const ImageItem& item, itemList) { + if (!blacklist.contains(item.itemName)) + QTest::newRow(item.itemName.toLatin1()) << item; + } + return true; +} + + +void tst_Lancelot::runTestSuite(GraphicsEngine engine, QImage::Format format) +{ + QFETCH(ImageItem, baseline); + + if (baseline.status == ImageItem::IgnoreItem) + QSKIP("Blacklisted by baseline server.", SkipSingle); + + ImageItem rendered = render(baseline, engine, format); + static int consecutiveErrs = 0; + if (rendered.image.isNull()) { // Assume an error in the test environment, not Qt + QWARN("Error: Failed to render image."); + if (++consecutiveErrs < 3) { + QSKIP("Aborted due to errors.", SkipSingle); + } else { + consecutiveErrs = 0; + QSKIP("Too many errors, skipping rest of testfunction.", SkipAll); + } + } else { + consecutiveErrs = 0; + } + + + if (baseline.status == ImageItem::BaselineNotFound) { + if (!proto.submitNewBaseline(rendered, 0)) + QWARN("Failed to submit new baseline: " + proto.errorMessage().toLatin1()); + QSKIP("Baseline not found; new baseline created.", SkipSingle); + } + + if (!baseline.imageChecksums.contains(rendered.imageChecksums.at(0))) { + QByteArray serverMsg; + if (!proto.submitMismatch(rendered, &serverMsg)) + serverMsg = "Failed to submit mismatching image to server."; + if (dryRunMode) + qDebug() << "Dryrun mode, ignoring detected mismatch." << serverMsg; + else + QFAIL("Rendered image differs from baseline. Report:\n " + serverMsg); + } +} + + +ImageItem tst_Lancelot::render(const ImageItem &item, GraphicsEngine engine, QImage::Format format) +{ + ImageItem res = item; + res.imageChecksums.clear(); + res.image = QImage(); + QString filePath = scriptsDir + item.itemName; + QStringList script = scripts.value(item.itemName); + + if (engine == Raster) { + QImage img(800, 800, format); + paint(&img, script, QFileInfo(filePath).absoluteFilePath()); // eh yuck (filePath stuff) + res.image = img; + res.imageChecksums.append(ImageItem::computeChecksum(img)); +#ifndef QT_NO_OPENGL + } else if (engine == OpenGL) { + QGLWidget glWidget; + if (glWidget.isValid()) { + glWidget.makeCurrent(); + QGLFramebufferObjectFormat fboFormat; + fboFormat.setSamples(16); + fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + QGLFramebufferObject fbo(800, 800, fboFormat); + paint(&fbo, script, QFileInfo(filePath).absoluteFilePath()); // eh yuck (filePath stuff) + res.image = fbo.toImage().convertToFormat(format); + res.imageChecksums.append(ImageItem::computeChecksum(res.image)); + } +#endif + } + + return res; +} + +void tst_Lancelot::paint(QPaintDevice *device, const QStringList &script, const QString &filePath) +{ + QPainter p(device); + PaintCommands pcmd(script, 800, 800); + //pcmd.setShouldDrawText(false); + pcmd.setType(ImageType); + pcmd.setPainter(&p); + pcmd.setFilePath(filePath); + pcmd.runCommands(); + p.end(); + + if (simfail) { + QPainter p2(device); + p2.setPen(QPen(QBrush(Qt::cyan), 3, Qt::DashLine)); + p2.drawLine(200, 200, 600, 600); + p2.drawLine(600, 200, 200, 600); + simfail = false; + } +} + +#define main rmain +QTEST_MAIN(tst_Lancelot) +#undef main + +int main(int argc, char *argv[]) +{ + tst_Lancelot::clientInfo = PlatformInfo::localHostInfo(); + + char *fargv[20]; + int fargc = 0; + for (int i = 0; i < qMin(argc, 19); i++) { + if (!qstrcmp(argv[i], "-simfail")) { + tst_Lancelot::simfail = true; + } else if (!qstrcmp(argv[i], "-compareto") && i < argc-1) { + QString arg = QString::fromLocal8Bit(argv[++i]); + int split = arg.indexOf(QLC('=')); + if (split < 0) + continue; + QString key = arg.left(split).trimmed(); + QString value = arg.mid(split+1).trimmed(); + if (key.isEmpty() || value.isEmpty()) + continue; + tst_Lancelot::clientInfo.addOverride(key, value); + } else { + fargv[fargc++] = argv[i]; + } + } + fargv[fargc] = 0; + return rmain(fargc, fargv); +} + +#include "tst_lancelot.moc" diff --git a/tests/auto/integrationtests/languagechange/.gitignore b/tests/auto/integrationtests/languagechange/.gitignore new file mode 100644 index 0000000000..1b14ad1503 --- /dev/null +++ b/tests/auto/integrationtests/languagechange/.gitignore @@ -0,0 +1 @@ +tst_languagechange diff --git a/tests/auto/integrationtests/languagechange/languagechange.pro b/tests/auto/integrationtests/languagechange/languagechange.pro new file mode 100644 index 0000000000..c51c42ebe1 --- /dev/null +++ b/tests/auto/integrationtests/languagechange/languagechange.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +QT += widgets core-private +SOURCES += tst_languagechange.cpp + +CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/integrationtests/languagechange/tst_languagechange.cpp b/tests/auto/integrationtests/languagechange/tst_languagechange.cpp new file mode 100644 index 0000000000..5e97fd709e --- /dev/null +++ b/tests/auto/integrationtests/languagechange/tst_languagechange.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 + +#include +#include +#include +#include +#include +#include +#include +#include + + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_languageChange : public QObject +{ + Q_OBJECT +public: + tst_languageChange(); + +public slots: + void initTestCase(); + void cleanupTestCase(); +private slots: + void retranslatability_data(); + void retranslatability(); + +}; + + +tst_languageChange::tst_languageChange() + +{ +} + +void tst_languageChange::initTestCase() +{ +} + +void tst_languageChange::cleanupTestCase() +{ +} +/** + * Records all calls to translate() + */ +class TransformTranslator : public QTranslator +{ + Q_OBJECT +public: + TransformTranslator() : QTranslator() {} + TransformTranslator(QObject *parent) : QTranslator(parent) {} + virtual QString translate(const char *context, const char *sourceText, const char *comment = 0) const + { + QByteArray total(context); + total.append("::"); + total.append(sourceText); + if (comment) { + total.append("::"); + total.append(comment); + } + m_translations.insert(total); + QString res; + for (int i = 0; i < int(qstrlen(sourceText)); ++i) { + QChar ch = QLatin1Char(sourceText[i]); + if (ch.isLower()) { + res.append(ch.toUpper()); + } else if (ch.isUpper()) { + res.append(ch.toLower()); + } else { + res.append(ch); + } + } + return res; + } + + virtual bool isEmpty() const { return false; } + +public slots: + void install() { + QCoreApplication::installTranslator(this); + QTest::qWait(2500); + QApplication::closeAllWindows(); + } +public: + mutable QSet m_translations; +}; + +enum DialogType { + InputDialog = 1, + ColorDialog, + FileDialog +}; + +typedef QSet TranslationSet; +Q_DECLARE_METATYPE(TranslationSet) + +void tst_languageChange::retranslatability_data() +{ + QTest::addColumn("dialogType"); + QTest::addColumn("expected"); + + //next we fill it with data + QTest::newRow( "QInputDialog" ) + << int(InputDialog) << (QSet() + << "QDialogButtonBox::Cancel"); + + QTest::newRow( "QColorDialog" ) + << int(ColorDialog) << (QSet() + << "QDialogButtonBox::Cancel" + << "QColorDialog::&Sat:" + << "QColorDialog::&Add to Custom Colors" + << "QColorDialog::&Green:" + << "QColorDialog::&Red:" + << "QColorDialog::Bl&ue:" + << "QColorDialog::A&lpha channel:" + << "QColorDialog::&Basic colors" + << "QColorDialog::&Custom colors" + << "QColorDialog::&Val:" + << "QColorDialog::Hu&e:"); + + QTest::newRow( "QFileDialog" ) + << int(FileDialog) << (QSet() + << "QFileDialog::All Files (*)" + << "QFileDialog::Back" + << "QFileDialog::Create New Folder" + << "QFileDialog::Detail View" +#ifndef Q_OS_MAC + << "QFileDialog::File" +#endif + << "QFileDialog::Files of type:" + << "QFileDialog::Forward" + << "QFileDialog::List View" + << "QFileDialog::Look in:" + << "QFileDialog::Open" + << "QFileDialog::Parent Directory" + << "QFileDialog::Show " + << "QFileDialog::Show &hidden files" + << "QFileDialog::&Delete" + << "QFileDialog::&New Folder" + << "QFileDialog::&Rename" + << "QFileSystemModel::Date Modified" +#ifdef Q_OS_WIN + << "QFileSystemModel::My Computer" +#else + << "QFileSystemModel::Computer" +#endif + << "QFileSystemModel::Size" +#ifdef Q_OS_MAC + << "QFileSystemModel::Kind::Match OS X Finder" +#else + << "QFileSystemModel::Type::All other platforms" +#endif +// << "QFileSystemModel::%1 KB" + << "QDialogButtonBox::Cancel" + << "QDialogButtonBox::Open" + << "QFileDialog::File &name:"); +} + +void tst_languageChange::retranslatability() +{ + QFETCH( int, dialogType); + QFETCH( TranslationSet, expected); + + // This will always be queried for when a language changes + expected.insert("QApplication::QT_LAYOUT_DIRECTION::Translate this string to the string 'LTR' in left-to-right " + "languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to " + "get proper widget layout."); + TransformTranslator translator; + QTimer::singleShot(500, &translator, SLOT(install())); + switch (dialogType) { + case InputDialog: + (void)QInputDialog::getInteger(0, QLatin1String("title"), QLatin1String("label")); + break; + + case ColorDialog: +#ifdef Q_WS_MAC + QSKIP("The native color dialog is used on Mac OS", SkipSingle); +#else + (void)QColorDialog::getColor(); +#endif + break; + case FileDialog: { +#ifdef Q_WS_MAC + QSKIP("The native file dialog is used on Mac OS", SkipSingle); +#endif + QFileDialog dlg; + dlg.setOption(QFileDialog::DontUseNativeDialog); + QString tmpParentDir = QDir::tempPath() + "/languagechangetestdir"; + QString tmpDir = tmpParentDir + "/finaldir"; + QString fooName = tmpParentDir + "/foo"; + QDir dir; + QCOMPARE(dir.mkpath(tmpDir), true); + QCOMPARE(QFile::copy(QApplication::applicationFilePath(), fooName), true); + + dlg.setDirectory(tmpParentDir); +#ifdef Q_OS_WINCE + dlg.setDirectory("\\Windows"); +#endif + dlg.setFileMode(QFileDialog::ExistingFiles); + dlg.setViewMode(QFileDialog::Detail); + dlg.exec(); + QTest::qWait(3000); + QCOMPARE(QFile::remove(fooName), true); + QCOMPARE(dir.rmdir(tmpDir), true); + QCOMPARE(dir.rmdir(tmpParentDir), true); + break; } + } +#if 0 + QList list = translator.m_translations.toList(); + qSort(list); + qDebug() << list; +#endif + // In case we use a Color dialog, we do not want to test for + // strings non existing in the dialog and which do not get + // translated. + if ((dialogType == ColorDialog) && +#ifndef Q_OS_WINCE + (qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350) +#else + true // On Qt/WinCE we always use compact mode +#endif + ) { + expected.remove("QColorDialog::&Basic colors"); + expected.remove("QColorDialog::&Custom colors"); + expected.remove("QColorDialog::&Define Custom Colors >>"); + expected.remove("QColorDialog::&Add to Custom Colors"); + } + + // see if all of our *expected* translations was translated. + // (There might be more, but thats not that bad) + QSet commonTranslations = expected; + commonTranslations.intersect(translator.m_translations); + if (!expected.subtract(commonTranslations).isEmpty()) { + qDebug() << "Missing:" << expected; + if (!translator.m_translations.subtract(commonTranslations).isEmpty()) + qDebug() << "Unexpected:" << translator.m_translations; + } + + QVERIFY(expected.isEmpty()); +} + +QTEST_MAIN(tst_languageChange) +#include "tst_languagechange.moc" diff --git a/tests/auto/integrationtests/macgui/.gitignore b/tests/auto/integrationtests/macgui/.gitignore new file mode 100644 index 0000000000..2b13357fac --- /dev/null +++ b/tests/auto/integrationtests/macgui/.gitignore @@ -0,0 +1 @@ +tst_macgui diff --git a/tests/auto/integrationtests/macgui/guitest.cpp b/tests/auto/integrationtests/macgui/guitest.cpp new file mode 100644 index 0000000000..521134f6b8 --- /dev/null +++ b/tests/auto/integrationtests/macgui/guitest.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** 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 "guitest.h" +#include +#include +#include +#include +#include + +#ifdef Q_OS_MAC +# include +#endif + + +/* + Not really a test, just prints interface info. +*/ +class PrintTest : public TestBase +{ +public: + bool operator()(InterfaceChildPair candidate) + { + qDebug() << ""; + qDebug() << "Name" << candidate.iface->text(QAccessible::Name, candidate.possibleChild); + qDebug() << "Pos" << candidate.iface->rect(candidate.possibleChild); + if (candidate.possibleChild == 0) + qDebug() << "Number of children" << candidate.iface->childCount(); + return false; + } +}; + +class NameTest : public TestBase +{ +public: + NameTest(const QString &text, QAccessible::Text textType) : text(text), textType(textType) {} + QString text; + QAccessible::Text textType; + + bool operator()(InterfaceChildPair candidate) + { + return (candidate.iface->text(textType, candidate.possibleChild) == text); + } +}; + +void WidgetNavigator::printAll(QWidget *widget) +{ + QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(widget); + deleteInDestructor(iface); + printAll(InterfaceChildPair(iface, 0)); +} + +void WidgetNavigator::printAll(InterfaceChildPair interface) +{ + PrintTest printTest; + recursiveSearch(&printTest, interface.iface, interface.possibleChild); +} + +InterfaceChildPair WidgetNavigator::find(QAccessible::Text textType, const QString &text, QWidget *start) +{ + QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(start); + deleteInDestructor(iface); + return find(textType, text, iface); +} + +InterfaceChildPair WidgetNavigator::find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start) +{ + NameTest nameTest(text, textType); + return recursiveSearch(&nameTest, start, 0); +} + +/* + Recursiveley navigates the accessible hiearchy looking for an interfafce that + passsed the Test (meaning it returns true). +*/ +InterfaceChildPair WidgetNavigator::recursiveSearch(TestBase *test, QAccessibleInterface *iface, int possibleChild) +{ + QStack todoInterfaces; + todoInterfaces.push(InterfaceChildPair(iface, possibleChild)); + + while (todoInterfaces.isEmpty() == false) { + InterfaceChildPair testInterface = todoInterfaces.pop(); + + if ((*test)(testInterface)) + return testInterface; + + if (testInterface.possibleChild != 0) + continue; + + const int numChildren = testInterface.iface->childCount(); + for (int i = 0; i < numChildren; ++i) { + QAccessibleInterface *childInterface = 0; + int newPossibleChild = testInterface.iface->navigate(QAccessible::Child, i + 1, &childInterface); + if (childInterface) { + todoInterfaces.push(InterfaceChildPair(childInterface, newPossibleChild)); + deleteInDestructor(childInterface); + } else if (newPossibleChild != -1) { + todoInterfaces.push(InterfaceChildPair(testInterface.iface, newPossibleChild)); + } + } + } + return InterfaceChildPair(); +} + +void WidgetNavigator::deleteInDestructor(QAccessibleInterface * interface) +{ + interfaces.insert(interface); +} + +QWidget *WidgetNavigator::getWidget(InterfaceChildPair interface) +{ + return qobject_cast(interface.iface->object()); +} + +WidgetNavigator::~WidgetNavigator() +{ + foreach(QAccessibleInterface *interface, interfaces) { + delete interface; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +namespace NativeEvents { +#ifdef Q_OS_MAC + void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse) + { + CGPoint position; + position.x = globalPos.x(); + position.y = globalPos.y(); + + const bool updateMousePosition = (updateMouse == UpdatePosition); + + // Mouse down. + CGPostMouseEvent(position, updateMousePosition, 3, + (buttons & Qt::LeftButton) ? true : false, + (buttons & Qt::MidButton/* Middlebutton! */) ? true : false, + (buttons & Qt::RightButton) ? true : false); + + // Mouse up. + CGPostMouseEvent(position, updateMousePosition, 3, false, false, false); + } +#else +# error Oops, NativeEvents::mouseClick() is not implemented on this platform. +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// + +GuiTester::GuiTester() +{ + clearSequence(); +} + +GuiTester::~GuiTester() +{ + foreach(DelayedAction *action, actions) + delete action; +} + +bool checkPixel(QColor pixel, QColor expected) +{ + const int allowedDiff = 20; + + return !(qAbs(pixel.red() - expected.red()) > allowedDiff || + qAbs(pixel.green() - expected.green()) > allowedDiff || + qAbs(pixel.blue() - expected.blue()) > allowedDiff); +} + +/* + Tests that the pixels inside rect in image all have the given color. +*/ +bool GuiTester::isFilled(const QImage image, const QRect &rect, const QColor &color) +{ + for (int y = rect.top(); y <= rect.bottom(); ++y) + for (int x = rect.left(); x <= rect.right(); ++x) { + const QColor pixel = image.pixel(x, y); + if (checkPixel(pixel, color) == false) { +// qDebug()<< "Wrong pixel value at" << x << y << pixel.red() << pixel.green() << pixel.blue(); + return false; + } + } + return true; +} + + +/* + Tests that stuff is painted to the pixels inside rect. + This test fails if any lines in the given direction have pixels + of only one color. +*/ +bool GuiTester::isContent(const QImage image, const QRect &rect, Directions directions) +{ + if (directions & Horizontal) { + for (int y = rect.top(); y <= rect.bottom(); ++y) { + QColor currentColor = image.pixel(rect.left(), y); + bool fullRun = true; + for (int x = rect.left() + 1; x <= rect.right(); ++x) { + if (checkPixel(image.pixel(x, y), currentColor) == false) { + fullRun = false; + break; + } + } + if (fullRun) { +// qDebug() << "Single-color line at horizontal line " << y << currentColor; + return false; + } + } + return true; + } + + if (directions & Vertical) { + for (int x = rect.left(); x <= rect.right(); ++x) { + QRgb currentColor = image.pixel(x, rect.top()); + bool fullRun = true; + for (int y = rect.top() + 1; y <= rect.bottom(); ++y) { + if (checkPixel(image.pixel(x, y), currentColor) == false) { + fullRun = false; + break; + } + } + if (fullRun) { +// qDebug() << "Single-color line at vertical line" << x << currentColor; + return false; + } + } + return true; + } + return false; // shut the compiler up. +} + +void DelayedAction::run() +{ + if (next) + QTimer::singleShot(next->delay, next, SLOT(run())); +}; + +/* + Schedules a mouse click at an interface using a singleShot timer. + Only one click can be scheduled at a time. +*/ +ClickLaterAction::ClickLaterAction(InterfaceChildPair interface, Qt::MouseButtons buttons) +{ + this->useInterface = true; + this->interface = interface; + this->buttons = buttons; +} + +/* + Schedules a mouse click at a widget using a singleShot timer. + Only one click can be scheduled at a time. +*/ +ClickLaterAction::ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons) +{ + this->useInterface = false; + this->widget = widget; + this->buttons = buttons; +} + +void ClickLaterAction::run() +{ + if (useInterface) { + const QPoint globalCenter = interface.iface->rect(interface.possibleChild).center(); + NativeEvents::mouseClick(globalCenter, buttons); + } else { // use widget + const QSize halfSize = widget->size() / 2; + const QPoint globalCenter = widget->mapToGlobal(QPoint(halfSize.width(), halfSize.height())); + NativeEvents::mouseClick(globalCenter, buttons); + } + DelayedAction::run(); +} + +void GuiTester::clickLater(InterfaceChildPair interface, Qt::MouseButtons buttons, int delay) +{ + clearSequence(); + addToSequence(new ClickLaterAction(interface, buttons), delay); + runSequence(); +} + +void GuiTester::clickLater(QWidget *widget, Qt::MouseButtons buttons, int delay) +{ + clearSequence(); + addToSequence(new ClickLaterAction(widget, buttons), delay); + runSequence(); +} + +void GuiTester::clearSequence() +{ + startAction = new DelayedAction(); + actions.insert(startAction); + lastAction = startAction; +} + +void GuiTester::addToSequence(DelayedAction *action, int delay) +{ + actions.insert(action); + action->delay = delay; + lastAction->next = action; + lastAction = action; +} + +void GuiTester::runSequence() +{ + QTimer::singleShot(0, startAction, SLOT(run())); +} + +void GuiTester::exitLoopSlot() +{ + QTestEventLoop::instance().exitLoop(); +} + diff --git a/tests/auto/integrationtests/macgui/guitest.h b/tests/auto/integrationtests/macgui/guitest.h new file mode 100644 index 0000000000..432021c54a --- /dev/null +++ b/tests/auto/integrationtests/macgui/guitest.h @@ -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$ +** +****************************************************************************/ +#ifndef GUITEST_H +#define GUITEST_H + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +/* + GuiTest provides tools for: + - navigating the Qt Widget hiearchy using the accessibilty APIs. + - Simulating platform mouse and keybord events. +*/ + +/* + InterfaceChildPair specifies an accessibilty interface item. +*/ +class InterfaceChildPair { +public: + InterfaceChildPair() : iface(0), possibleChild(0) {} + InterfaceChildPair(QAccessibleInterface *iface, int possibleChild) + :iface(iface), possibleChild(possibleChild) + { } + + QAccessibleInterface *iface; + int possibleChild; +}; + +class TestBase { +public: + virtual bool operator()(InterfaceChildPair candidate) = 0; + virtual ~TestBase() {} +}; + +/* + WidgetNavigator navigates a Qt GUI hierarchy using the QAccessibility APIs. +*/ +class WidgetNavigator { +public: + WidgetNavigator() {}; + ~WidgetNavigator(); + + void printAll(QWidget *widget); + void printAll(InterfaceChildPair interface); + + InterfaceChildPair find(QAccessible::Text textType, const QString &text, QWidget *start); + InterfaceChildPair find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start); + + InterfaceChildPair recursiveSearch(TestBase *test, QAccessibleInterface *iface, int possibleChild); + + void deleteInDestructor(QAccessibleInterface * interface); + static QWidget *getWidget(InterfaceChildPair interface); +private: + QSet interfaces; +}; + +/* + NativeEvents contains platform-specific code for simulating mouse and keybord events. + (Implemented so far: mouseClick on Mac) +*/ +namespace NativeEvents { + enum MousePosition { UpdatePosition, DontUpdatePosition }; + /* + Simulates a mouse click with button at globalPos. + */ + void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse = DontUpdatePosition); +}; + +class ColorWidget : public QWidget +{ +public: + ColorWidget(QWidget *parent = 0, QColor color = QColor(Qt::red)) + : QWidget(parent), color(color) {} + + QColor color; + +protected: + void paintEvent(QPaintEvent *) + { + QPainter p(this); + p.fillRect(this->rect(), color); + } +}; + +class DelayedAction : public QObject +{ +Q_OBJECT +public: + DelayedAction() : delay(0), next(0) {} + virtual ~DelayedAction(){} +public slots: + virtual void run(); +public: + int delay; + DelayedAction *next; +}; + +class ClickLaterAction : public DelayedAction +{ +Q_OBJECT +public: + ClickLaterAction(InterfaceChildPair interface, Qt::MouseButtons buttons = Qt::LeftButton); + ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons = Qt::LeftButton); +protected slots: + void run(); +private: + bool useInterface; + InterfaceChildPair interface; + QWidget *widget; + Qt::MouseButtons buttons; +}; + +/* + +*/ +class GuiTester : public QObject +{ +Q_OBJECT +public: + GuiTester(); + ~GuiTester(); + enum Direction {Horizontal = 1, Vertical = 2, HorizontalAndVertical = 3}; + Q_DECLARE_FLAGS(Directions, Direction) + bool isFilled(const QImage image, const QRect &rect, const QColor &color); + bool isContent(const QImage image, const QRect &rect, Directions directions = HorizontalAndVertical); +protected slots: + void exitLoopSlot(); +protected: + void clickLater(InterfaceChildPair interface, Qt::MouseButtons buttons = Qt::LeftButton, int delay = 300); + void clickLater(QWidget *widget, Qt::MouseButtons buttons = Qt::LeftButton, int delay = 300); + + void clearSequence(); + void addToSequence(DelayedAction *action, int delay = 0); + void runSequence(); + WidgetNavigator wn; +private: + QSet actions; + DelayedAction *startAction; + DelayedAction *lastAction; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(GuiTester::Directions) + +#endif diff --git a/tests/auto/integrationtests/macgui/macgui.pro b/tests/auto/integrationtests/macgui/macgui.pro new file mode 100644 index 0000000000..3fbe74f7c8 --- /dev/null +++ b/tests/auto/integrationtests/macgui/macgui.pro @@ -0,0 +1,14 @@ +load(qttest_p4) +TEMPLATE = app +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += tst_macgui.cpp guitest.cpp +HEADERS += guitest.h + +QT = core-private gui-private widgets + +requires(mac) + +CONFIG+=insignificant_test # QTBUG-20984, fails unstably diff --git a/tests/auto/integrationtests/macgui/tst_macgui.cpp b/tests/auto/integrationtests/macgui/tst_macgui.cpp new file mode 100644 index 0000000000..1552db21ab --- /dev/null +++ b/tests/auto/integrationtests/macgui/tst_macgui.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include +#include +#include + +#include + +class tst_MacGui : public GuiTester +{ +Q_OBJECT +private slots: + void scrollbarPainting(); + + void dummy(); + void splashScreenModality(); + void nonModalOrder(); + + void spinBoxArrowButtons(); +}; + + +QPixmap grabWindowContents(QWidget * widget) +{ + return QPixmap::grabWindow(widget->winId()); +} + +/* + Test that vertical and horizontal mac-style scrollbars paint their + entire area. +*/ +void tst_MacGui::scrollbarPainting() +{ + ColorWidget colorWidget; + colorWidget.resize(400, 400); + + QSize scrollBarSize; + + QScrollBar verticalScrollbar(&colorWidget); + verticalScrollbar.move(10, 10); + scrollBarSize = verticalScrollbar.sizeHint(); + scrollBarSize.setHeight(200); + verticalScrollbar.resize(scrollBarSize); + + QScrollBar horizontalScrollbar(&colorWidget); + horizontalScrollbar.move(30, 10); + horizontalScrollbar.setOrientation(Qt::Horizontal); + scrollBarSize = horizontalScrollbar.sizeHint(); + scrollBarSize.setWidth(200); + horizontalScrollbar.resize(scrollBarSize); + + colorWidget.show(); + colorWidget.raise(); + QTest::qWait(100); + + QPixmap pixmap = grabWindowContents(&colorWidget); + + QVERIFY(isContent(pixmap.toImage(), verticalScrollbar.geometry(), GuiTester::Horizontal)); + QVERIFY(isContent(pixmap.toImage(), horizontalScrollbar.geometry(), GuiTester::Vertical)); +} + +// When running the auto-tests on scruffy, the first enter-the-event-loop-and-wait-for-a-click +// test that runs always times out, so we have this dummy test. +void tst_MacGui::dummy() +{ + QPixmap pix(100, 100); + QSplashScreen splash(pix); + splash.show(); + + QMessageBox *box = new QMessageBox(); + box->setText("accessible?"); + box->show(); + + // Find the "OK" button and schedule a press. + InterfaceChildPair interface = wn.find(QAccessible::Name, "OK", box); + QVERIFY(interface.iface); + const int delay = 1000; + clickLater(interface, Qt::LeftButton, delay); + + // Show dialog and and enter event loop. + connect(wn.getWidget(interface), SIGNAL(clicked()), SLOT(exitLoopSlot())); + const int timeout = 4; + QTestEventLoop::instance().enterLoop(timeout); +} + +/* + Test that a message box pops up in front of a QSplashScreen. +*/ +void tst_MacGui::splashScreenModality() +{ + QPixmap pix(300, 300); + QSplashScreen splash(pix); + splash.show(); + + QMessageBox box; + //box.setWindowFlags(box.windowFlags() | Qt::WindowStaysOnTopHint); + box.setText("accessible?"); + box.show(); + + // Find the "OK" button and schedule a press. + InterfaceChildPair interface = wn.find(QAccessible::Name, "OK", &box); + QVERIFY(interface.iface); + const int delay = 1000; + clickLater(interface, Qt::LeftButton, delay); + + // Show dialog and and enter event loop. + connect(wn.getWidget(interface), SIGNAL(clicked()), SLOT(exitLoopSlot())); + const int timeout = 4; + QTestEventLoop::instance().enterLoop(timeout); + QVERIFY(QTestEventLoop::instance().timeout() == false); +} + +class PrimaryWindowDialog : public QDialog +{ +Q_OBJECT +public: + PrimaryWindowDialog(); + QWidget *secondaryWindow; + QWidget *frontWidget; +public slots: + void showSecondaryWindow(); + void test(); +}; + +PrimaryWindowDialog::PrimaryWindowDialog() : QDialog(0) +{ + frontWidget = 0; + secondaryWindow = new ColorWidget(this); + secondaryWindow->setWindowFlags(Qt::Window); + secondaryWindow->resize(400, 400); + secondaryWindow->move(100, 100); + QTimer::singleShot(1000, this, SLOT(showSecondaryWindow())); + QTimer::singleShot(2000, this, SLOT(test())); + QTimer::singleShot(3000, this, SLOT(close())); +} + +void PrimaryWindowDialog::showSecondaryWindow() +{ + secondaryWindow->show(); +} + +void PrimaryWindowDialog::test() +{ + frontWidget = QApplication::widgetAt(secondaryWindow->mapToGlobal(QPoint(100, 100))); +} + +/* + Test that a non-modal child window of a modal dialog is shown in front + of the dialog even if the dialog becomes modal after the child window + is created. +*/ +void tst_MacGui::nonModalOrder() +{ + clearSequence(); + PrimaryWindowDialog primary; + primary.resize(400, 400); + primary.move(100, 100); + primary.exec(); + QCOMPARE(primary.frontWidget, primary.secondaryWindow); +} + +/* + Test that the QSpinBox buttons are correctly positioned with the Mac style. +*/ +void tst_MacGui::spinBoxArrowButtons() +{ + ColorWidget colorWidget; + colorWidget.resize(200, 200); + QSpinBox spinBox(&colorWidget); + QSpinBox spinBox2(&colorWidget); + spinBox2.move(0, 100); + colorWidget.show(); + QTest::qWait(100); + + // Grab an unfocused spin box. + const QImage noFocus = grabWindowContents(&colorWidget).toImage(); + + // Set focus by clicking the less button. + InterfaceChildPair lessInterface = wn.find(QAccessible::Name, "Less", &spinBox); + QVERIFY(lessInterface.iface); + const int delay = 500; + clickLater(lessInterface, Qt::LeftButton, delay); + const int timeout = 1; + QTestEventLoop::instance().enterLoop(timeout); + + // Grab a focused spin box. + const QImage focus = grabWindowContents(&colorWidget).toImage(); + + // Compare the arrow area of the less button to see if it moved. + const QRect lessRect = lessInterface.iface->rect(lessInterface.possibleChild); + const QRect lessLocalRect(colorWidget.mapFromGlobal(lessRect.topLeft()), colorWidget.mapFromGlobal(lessRect.bottomRight())); + const QRect compareRect = lessLocalRect.adjusted(5, 3, -5, -7); + QVERIFY(noFocus.copy(compareRect) == focus.copy(compareRect)); +} + +QTEST_MAIN(tst_MacGui) +#include "tst_macgui.moc" + diff --git a/tests/auto/integrationtests/macnativeevents/expectedeventlist.cpp b/tests/auto/integrationtests/macnativeevents/expectedeventlist.cpp new file mode 100644 index 0000000000..d603f82f27 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/expectedeventlist.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** 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 "expectedeventlist.h" +#include +#include +#include +#include + +ExpectedEventList::ExpectedEventList(QObject *target) + : QObject(target), eventCount(0) +{ + target->installEventFilter(this); + debug = qgetenv("NATIVEDEBUG").toInt(); + if (debug > 0) + qDebug() << "Debug level sat to:" << debug; +} + +ExpectedEventList::~ExpectedEventList() +{ + qDeleteAll(eventList); +} + +void ExpectedEventList::append(QEvent *e) +{ + eventList.append(e); + ++eventCount; +} + +void ExpectedEventList::timerEvent(QTimerEvent *) +{ + timer.stop(); + QAbstractEventDispatcher::instance()->interrupt(); +} + +bool ExpectedEventList::waitForAllEvents(int maxEventWaitTime) +{ + if (eventList.isEmpty()) + return true; + + int eventCount = eventList.size(); + timer.start(maxEventWaitTime, this); + + while (timer.isActive()) { + QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); + if (eventList.isEmpty()) + return true; + + if (eventCount < eventList.size()){ + eventCount = eventList.size(); + timer.start(maxEventWaitTime, this); + } + } + + int eventListNr = eventCount - eventList.size() + 1; + qWarning() << "Stopped waiting for expected event nr" << eventListNr; + return false; +} + +void ExpectedEventList::compareMouseEvents(QEvent *received, QEvent *expected) +{ + QMouseEvent *e1 = static_cast(received); + QMouseEvent *e2 = static_cast(expected); + + // Do a manual check first to be able to write more sensible + // debug output if we know we're going to fail: + if (e1->pos() == e2->pos() + && (e1->globalPos() == e2->globalPos()) + && (e1->button() == e2->button()) + && (e1->buttons() == e2->buttons()) + && (e1->modifiers() == e2->modifiers())) { + if (debug > 0) + qDebug() << " Received (OK):" << e1 << e1->globalPos(); + return; // equal + } + + // INVARIANT: The two events are not equal. So we fail. Depending + // on whether debug mode is no or not, we let QTest fail. Otherwise + // we let the test continue for debugging puposes. + int eventListNr = eventCount - eventList.size(); + if (debug == 0) { + qWarning() << "Expected event" << eventListNr << "differs from received event:"; + QCOMPARE(e1->pos(), e2->pos()); + QCOMPARE(e1->globalPos(), e2->globalPos()); + QCOMPARE(e1->button(), e2->button()); + QCOMPARE(e1->buttons(), e2->buttons()); + QCOMPARE(e1->modifiers(), e2->modifiers()); + } else { + qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:"; + qWarning() << "Received:" << e1 << e1->globalPos(); + qWarning() << "Expected:" << e2 << e2->globalPos(); + } +} + +void ExpectedEventList::compareKeyEvents(QEvent *received, QEvent *expected) +{ + QKeyEvent *e1 = static_cast(received); + QKeyEvent *e2 = static_cast(expected); + + // Do a manual check first to be able to write more sensible + // debug output if we know we're going to fail: + if (e1->key() == e2->key() + && (e1->modifiers() == e2->modifiers()) + && (e1->count() == e2->count()) + && (e1->isAutoRepeat() == e2->isAutoRepeat())) { + if (debug > 0) + qDebug() << " Received (OK):" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText); + return; // equal + } + + // INVARIANT: The two events are not equal. So we fail. Depending + // on whether debug mode is no or not, we let QTest fail. Otherwise + // we let the test continue for debugging puposes. + int eventListNr = eventCount - eventList.size(); + if (debug == 0) { + qWarning() << "Expected event" << eventListNr << "differs from received event:"; + QCOMPARE(e1->key(), e2->key()); + QCOMPARE(e1->modifiers(), e2->modifiers()); + QCOMPARE(e1->count(), e2->count()); + QCOMPARE(e1->isAutoRepeat(), e2->isAutoRepeat()); + } else { + qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:"; + qWarning() << "Received:" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText); + qWarning() << "Expected:" << e2 << QKeySequence(e2->key()).toString(QKeySequence::NativeText); + } +} + +bool ExpectedEventList::eventFilter(QObject *, QEvent *received) +{ + if (debug > 1) + qDebug() << received; + if (eventList.isEmpty()) + return false; + + bool eat = false; + QEvent *expected = eventList.first(); + if (expected->type() == received->type()) { + eventList.removeFirst(); + switch (received->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + case QEvent::MouseButtonDblClick: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseButtonRelease: + case QEvent::NonClientAreaMouseButtonDblClick: + case QEvent::NonClientAreaMouseMove: { + compareMouseEvents(received, expected); + eat = true; + break; + } + case QEvent::KeyPress: + case QEvent::KeyRelease: { + compareKeyEvents(received, expected); + eat = true; + break; + } + case QEvent::Resize: { + break; + } + case QEvent::WindowActivate: { + break; + } + case QEvent::WindowDeactivate: { + break; + } + default: + break; + } + if (eventList.isEmpty()) + QAbstractEventDispatcher::instance()->interrupt(); + } + + return eat; +} + diff --git a/tests/auto/integrationtests/macnativeevents/expectedeventlist.h b/tests/auto/integrationtests/macnativeevents/expectedeventlist.h new file mode 100644 index 0000000000..e3fef2d56d --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/expectedeventlist.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 EVENTFILTER +#define EVENTFILTER + +#include +#include +#include +#include + +class ExpectedEventList : public QObject +{ + QList eventList; + QBasicTimer timer; + int debug; + int eventCount; + void timerEvent(QTimerEvent *); + +public: + ExpectedEventList(QObject *target); + ~ExpectedEventList(); + void append(QEvent *e); + bool waitForAllEvents(int timeoutPerEvent = 2000); + bool eventFilter(QObject *obj, QEvent *event); + +private: + void compareMouseEvents(QEvent *event1, QEvent *event2); + void compareKeyEvents(QEvent *event1, QEvent *event2); +}; + +#endif + diff --git a/tests/auto/integrationtests/macnativeevents/macnativeevents.pro b/tests/auto/integrationtests/macnativeevents/macnativeevents.pro new file mode 100644 index 0000000000..0a0f6c8743 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/macnativeevents.pro @@ -0,0 +1,16 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Wed Nov 29 22:24:47 2006 +###################################################################### + +load(qttest_p4) +TEMPLATE = app +DEPENDPATH += . +INCLUDEPATH += . +LIBS += -framework Carbon +QT += widgets +HEADERS += qnativeevents.h nativeeventlist.h expectedeventlist.h +SOURCES += qnativeevents.cpp qnativeevents_mac.cpp +SOURCES += expectedeventlist.cpp nativeeventlist.cpp +SOURCES += tst_macnativeevents.cpp + +requires(mac) diff --git a/tests/auto/integrationtests/macnativeevents/nativeeventlist.cpp b/tests/auto/integrationtests/macnativeevents/nativeeventlist.cpp new file mode 100644 index 0000000000..8c7f609d9f --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/nativeeventlist.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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 "nativeeventlist.h" + +NativeEventList::NativeEventList(int defaultWaitMs) + : playbackMultiplier(1.0) + , currIndex(-1) + , wait(false) + , defaultWaitMs(defaultWaitMs) +{ + debug = qgetenv("NATIVEDEBUG").toInt(); + QString multiplier = qgetenv("NATIVEDEBUGSPEED"); + if (!multiplier.isEmpty()) + setTimeMultiplier(multiplier.toFloat()); +} + +NativeEventList::~NativeEventList() +{ + for (int i=0; i 0) + qDebug() << "Sending:" << *e; + QNativeInput::sendNativeEvent(*e); + } + waitNextEvent(); +} + +void NativeEventList::waitNextEvent() +{ + if (++currIndex >= eventList.size()){ + emit done(); + stop(); + return; + } + + int interval = eventList.at(currIndex).first; + QTimer::singleShot(interval * playbackMultiplier, this, SLOT(sendNextEvent())); +} + +void NativeEventList::append(QNativeEvent *event) +{ + eventList.append(QPair(defaultWaitMs, event)); +} + +void NativeEventList::append(int waitMs, QNativeEvent *event) +{ + eventList.append(QPair(waitMs, event)); +} + +void NativeEventList::play(Playback playback) +{ + waitNextEvent(); + + wait = (playback == WaitUntilFinished); + while (wait) + QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); +} + +void NativeEventList::stop() +{ + wait = false; + QAbstractEventDispatcher::instance()->interrupt(); +} + +void NativeEventList::setTimeMultiplier(float multiplier) +{ + playbackMultiplier = multiplier; +} + diff --git a/tests/auto/integrationtests/macnativeevents/nativeeventlist.h b/tests/auto/integrationtests/macnativeevents/nativeeventlist.h new file mode 100644 index 0000000000..6bebca1613 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/nativeeventlist.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 Q_NATIVE_PLAYBACK +#define Q_NATIVE_PLAYBACK + +#include +#include "qnativeevents.h" + +class NativeEventList : public QObject +{ + Q_OBJECT; + + public: + enum Playback {ReturnImmediately, WaitUntilFinished}; + + NativeEventList(int defaultWaitMs = 20); + ~NativeEventList(); + + void append(QNativeEvent *event); + void append(int waitMs, QNativeEvent *event = 0); + + void play(Playback playback = WaitUntilFinished); + void stop(); + void setTimeMultiplier(float multiplier); + +signals: + void done(); + +private slots: + void sendNextEvent(); + +private: + void waitNextEvent(); + + QList > eventList; + float playbackMultiplier; + int currIndex; + bool wait; + int defaultWaitMs; + int debug; +}; + +#endif diff --git a/tests/auto/integrationtests/macnativeevents/qnativeevents.cpp b/tests/auto/integrationtests/macnativeevents/qnativeevents.cpp new file mode 100644 index 0000000000..b530d7bbe3 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/qnativeevents.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** 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 "qnativeevents.h" + +QNativeInput::QNativeInput(bool subscribe) +{ + if (subscribe) + subscribeForNativeEvents(); +} + +QNativeInput::~QNativeInput() +{ + unsubscribeForNativeEvents(); +} + +void QNativeInput::notify(QNativeEvent *event) +{ + nativeEvent(event); +} + +void QNativeInput::nativeEvent(QNativeEvent *event) +{ + switch (event->id()){ + case QNativeMouseButtonEvent::eventId:{ + QNativeMouseButtonEvent *e = static_cast(event); + (e->clickCount > 0) ? nativeMousePressEvent(e) : nativeMouseReleaseEvent(e); + break; } + case QNativeMouseMoveEvent::eventId: + nativeMouseMoveEvent(static_cast(event)); + break; + case QNativeMouseDragEvent::eventId: + nativeMouseDragEvent(static_cast(event)); + break; + case QNativeMouseWheelEvent::eventId: + nativeMouseWheelEvent(static_cast(event)); + break; + case QNativeKeyEvent::eventId:{ + QNativeKeyEvent *e = static_cast(event); + e->press ? nativeKeyPressEvent(e) : nativeKeyReleaseEvent(e); + break; } + case QNativeModifierEvent::eventId: + nativeModifierEvent(static_cast(event)); + break; + default: + break; + } +} + +Qt::Native::Status QNativeInput::sendNativeEvent(const QNativeEvent &event, int pid) +{ + switch (event.id()){ + case QNativeMouseMoveEvent::eventId: + return sendNativeMouseMoveEvent(static_cast(event)); + case QNativeMouseButtonEvent::eventId: + return sendNativeMouseButtonEvent(static_cast(event)); + case QNativeMouseDragEvent::eventId: + return sendNativeMouseDragEvent(static_cast(event)); + case QNativeMouseWheelEvent::eventId: + return sendNativeMouseWheelEvent(static_cast(event)); + case QNativeKeyEvent::eventId: + return sendNativeKeyEvent(static_cast(event), pid); + case QNativeModifierEvent::eventId: + return sendNativeModifierEvent(static_cast(event)); + case QNativeEvent::eventId: + qWarning() << "Warning: Cannot send a pure native event. Use a sub class."; + default: + return Qt::Native::Failure; + } +} + +QNativeEvent::QNativeEvent(Qt::KeyboardModifiers modifiers) + : modifiers(modifiers){} + +QNativeMouseEvent::QNativeMouseEvent(QPoint pos, Qt::KeyboardModifiers modifiers) + : QNativeEvent(modifiers), globalPos(pos){} + +QNativeMouseMoveEvent::QNativeMouseMoveEvent(QPoint pos, Qt::KeyboardModifiers modifiers) + : QNativeMouseEvent(pos, modifiers){} + +QNativeMouseButtonEvent::QNativeMouseButtonEvent(QPoint globalPos, Qt::MouseButton button, int clickCount, Qt::KeyboardModifiers modifiers) + : QNativeMouseEvent(globalPos, modifiers), button(button), clickCount(clickCount){} + +QNativeMouseDragEvent::QNativeMouseDragEvent(QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers) + : QNativeMouseButtonEvent(globalPos, button, true, modifiers){} + +QNativeMouseWheelEvent::QNativeMouseWheelEvent(QPoint globalPos, int delta, Qt::KeyboardModifiers modifiers) + : QNativeMouseEvent(globalPos, modifiers), delta(delta){} + +QNativeKeyEvent::QNativeKeyEvent(int nativeKeyCode, bool press, Qt::KeyboardModifiers modifiers) + : QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode), press(press), character(QChar()){} + +QNativeModifierEvent::QNativeModifierEvent(Qt::KeyboardModifiers modifiers, int nativeKeyCode) + : QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode){} + +QNativeKeyEvent::QNativeKeyEvent(int nativeKeyCode, bool press, QChar character, Qt::KeyboardModifiers modifiers) + : QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode), press(press), character(character){} + +static QString getButtonAsString(const QNativeMouseButtonEvent *e) +{ + switch (e->button){ + case Qt::LeftButton: + return "button = LeftButton"; + break; + case Qt::RightButton: + return "button = RightButton"; + break; + case Qt::MidButton: + return "button = MidButton"; + break; + default: + return "button = Other"; + break; + } +} + +static QString getModifiersAsString(const QNativeEvent *e) +{ + if (e->modifiers == 0) + return "modifiers = none"; + + QString tmp = "modifiers = "; + if (e->modifiers.testFlag(Qt::ShiftModifier)) + tmp += "Shift"; + if (e->modifiers.testFlag(Qt::ControlModifier)) + tmp += "Control"; + if (e->modifiers.testFlag(Qt::AltModifier)) + tmp += "Alt"; + if (e->modifiers.testFlag(Qt::MetaModifier)) + tmp += "Meta"; + return tmp; +} + +static QString getPosAsString(QPoint pos) +{ + return QString("QPoint(%1, %2)").arg(pos.x()).arg(pos.y()); +} + +static QString getBoolAsString(bool b) +{ + return b ? QString("true") : QString("false"); +} + +QString QNativeMouseMoveEvent::toString() const +{ + return QString("QNativeMouseMoveEvent(globalPos = %1 %2)").arg(getPosAsString(globalPos)) + .arg(getModifiersAsString(this)); +} + +QString QNativeMouseButtonEvent::toString() const +{ + return QString("QNativeMouseButtonEvent(globalPos = %1, %2, clickCount = %3, %4)").arg(getPosAsString(globalPos)) + .arg(getButtonAsString(this)).arg(clickCount).arg(getModifiersAsString(this)); +} + +QString QNativeMouseDragEvent::toString() const +{ + return QString("QNativeMouseDragEvent(globalPos = %1, %2, clickCount = %3, %4)").arg(getPosAsString(globalPos)) + .arg(getButtonAsString(this)).arg(clickCount).arg(getModifiersAsString(this)); +} + +QString QNativeMouseWheelEvent::toString() const +{ + return QString("QNativeMouseWheelEvent(globalPos = %1, delta = %2, %3)").arg(getPosAsString(globalPos)) + .arg(delta).arg(getModifiersAsString(this)); +} + +QString QNativeKeyEvent::toString() const +{ + return QString("QNativeKeyEvent(press = %1, native key code = %2, character = %3, %4)").arg(getBoolAsString(press)) + .arg(nativeKeyCode).arg(character.isPrint() ? character : QString("")) + .arg(getModifiersAsString(this)); +} + +QString QNativeModifierEvent::toString() const +{ + return QString("QNativeModifierEvent(%1, native key code = %2)").arg(getModifiersAsString(this)) + .arg(nativeKeyCode); +} + +QDebug operator<<(QDebug d, QNativeEvent *e) +{ + Q_UNUSED(e); + return d << e->toString(); +} + +QDebug operator<<(QDebug d, const QNativeEvent &e) +{ + Q_UNUSED(e); + return d << e.toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeEvent *e) +{ + return s << e->eventId << " " << e->modifiers << " QNativeEvent"; +} + +QTextStream &operator<<(QTextStream &s, QNativeMouseEvent *e) +{ + return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->modifiers << " " << e->toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeMouseMoveEvent *e) +{ + return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->modifiers << " " << e->toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeMouseButtonEvent *e) +{ + return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->button + << " " << e->clickCount << " " << e->modifiers << " " << e->toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeMouseDragEvent *e) +{ + return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->button << " " << e->clickCount + << " " << e->modifiers << " " << e->toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeMouseWheelEvent *e) +{ + return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->delta + << " " << e->modifiers << " " << e->toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeKeyEvent *e) +{ + return s << e->eventId << " " << e->press << " " << e->nativeKeyCode << " " << e->character + << " " << e->modifiers << " " << e->toString(); +} + +QTextStream &operator<<(QTextStream &s, QNativeModifierEvent *e) +{ + return s << e->eventId << " " << e->modifiers << " " << e->nativeKeyCode << " " << e->toString(); +} + + + + +QTextStream &operator>>(QTextStream &s, QNativeMouseMoveEvent *e) +{ + // Skip reading eventId. + QString humanReadable; + int x, y, modifiers; + s >> x >> y >> modifiers >> humanReadable; + e->globalPos.setX(x); + e->globalPos.setY(y); + e->modifiers = Qt::KeyboardModifiers(modifiers); + return s; +} + +QTextStream &operator>>(QTextStream &s, QNativeMouseButtonEvent *e) +{ + // Skip reading eventId. + QString humanReadable; + int x, y, button, clickCount, modifiers; + s >> x >> y >> button >> clickCount >> modifiers >> humanReadable; + e->globalPos.setX(x); + e->globalPos.setY(y); + e->clickCount = clickCount; + e->modifiers = Qt::KeyboardModifiers(modifiers); + switch (button){ + case 1: + e->button = Qt::LeftButton; + break; + case 2: + e->button = Qt::RightButton; + break; + case 3: + e->button = Qt::MidButton; + break; + default: + e->button = Qt::NoButton; + break; + } + return s; +} + +QTextStream &operator>>(QTextStream &s, QNativeMouseDragEvent *e) +{ + // Skip reading eventId. + QString humanReadable; + int x, y, button, clickCount, modifiers; + s >> x >> y >> button >> clickCount >> modifiers >> humanReadable; + e->globalPos.setX(x); + e->globalPos.setY(y); + e->clickCount = clickCount; + e->modifiers = Qt::KeyboardModifiers(modifiers); + switch (button){ + case 1: + e->button = Qt::LeftButton; + break; + case 2: + e->button = Qt::RightButton; + break; + case 3: + e->button = Qt::MidButton; + break; + default: + e->button = Qt::NoButton; + break; + } + return s; +} + +QTextStream &operator>>(QTextStream &s, QNativeMouseWheelEvent *e) +{ + // Skip reading eventId. + QString humanReadable; + int x, y, modifiers; + s >> x >> y >> e->delta >> modifiers >> humanReadable; + e->globalPos.setX(x); + e->globalPos.setY(y); + e->modifiers = Qt::KeyboardModifiers(modifiers); + return s; +} + +QTextStream &operator>>(QTextStream &s, QNativeKeyEvent *e) +{ + // Skip reading eventId. + QString humanReadable; + int press, modifiers; + QString character; + s >> press >> e->nativeKeyCode >> character >> modifiers >> humanReadable; + e->press = bool(press); + e->character = character[0]; + e->modifiers = Qt::KeyboardModifiers(modifiers); + return s; +} + +QTextStream &operator>>(QTextStream &s, QNativeModifierEvent *e) +{ + // Skip reading eventId. + QString humanReadable; + int modifiers; + s >> modifiers >> e->nativeKeyCode >> humanReadable; + e->modifiers = Qt::KeyboardModifiers(modifiers); + return s; +} + diff --git a/tests/auto/integrationtests/macnativeevents/qnativeevents.h b/tests/auto/integrationtests/macnativeevents/qnativeevents.h new file mode 100644 index 0000000000..276afc4fb7 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/qnativeevents.h @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** 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 Q_NATIVE_INPUT +#define Q_NATIVE_INPUT + +#include + +namespace Qt { +namespace Native { + enum Status {Success, Failure}; +}} + +// ---------------------------------------------------------------------------- +// Declare a set of native events that can be used to communicate with +// client applications in an platform independent way +// ---------------------------------------------------------------------------- + +class QNativeEvent +{ +public: + static const int eventId = 1; + + QNativeEvent(Qt::KeyboardModifiers modifiers = Qt::NoModifier); + virtual ~QNativeEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const = 0; + Qt::KeyboardModifiers modifiers; // Yields for mouse events too. +}; + +class QNativeMouseEvent : public QNativeEvent { +public: + static const int eventId = 2; + + QNativeMouseEvent(){}; + QNativeMouseEvent(QPoint globalPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + virtual ~QNativeMouseEvent(){}; + virtual int id() const { return eventId; }; + + QPoint globalPos; +}; + +class QNativeMouseMoveEvent : public QNativeMouseEvent { +public: + static const int eventId = 4; + + QNativeMouseMoveEvent(){}; + QNativeMouseMoveEvent(QPoint globalPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + virtual ~QNativeMouseMoveEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const; +}; + +class QNativeMouseButtonEvent : public QNativeMouseEvent { +public: + static const int eventId = 8; + + QNativeMouseButtonEvent(){}; + QNativeMouseButtonEvent(QPoint globalPos, Qt::MouseButton button, int clickCount, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + virtual ~QNativeMouseButtonEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const; + + Qt::MouseButton button; + int clickCount; +}; + +class QNativeMouseDragEvent : public QNativeMouseButtonEvent { +public: + static const int eventId = 16; + + QNativeMouseDragEvent(){}; + QNativeMouseDragEvent(QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + virtual ~QNativeMouseDragEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const; +}; + +class QNativeMouseWheelEvent : public QNativeMouseEvent { +public: + static const int eventId = 32; + + QNativeMouseWheelEvent(){}; + QNativeMouseWheelEvent(QPoint globalPos, int delta, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + virtual ~QNativeMouseWheelEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const; + + int delta; +}; + +class QNativeKeyEvent : public QNativeEvent { + public: + static const int eventId = 64; + + QNativeKeyEvent(){}; + QNativeKeyEvent(int nativeKeyCode, bool press, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + QNativeKeyEvent(int nativeKeyCode, bool press, QChar character, Qt::KeyboardModifiers modifiers); + virtual ~QNativeKeyEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const; + + int nativeKeyCode; + bool press; + QChar character; + + // Some Qt to Native mappings: + static int Key_A; + static int Key_B; + static int Key_C; + static int Key_1; + static int Key_Backspace; + static int Key_Enter; + static int Key_Del; +}; + +class QNativeModifierEvent : public QNativeEvent { +public: + static const int eventId = 128; + + QNativeModifierEvent(Qt::KeyboardModifiers modifiers = Qt::NoModifier, int nativeKeyCode = 0); + virtual ~QNativeModifierEvent(){}; + virtual int id() const { return eventId; }; + virtual QString toString() const; + + int nativeKeyCode; +}; + +// ---------------------------------------------------------------------------- +// Declare a set of related output / input functions for convenience: +// ---------------------------------------------------------------------------- + +QDebug operator<<(QDebug d, QNativeEvent *e); +QDebug operator<<(QDebug d, const QNativeEvent &e); + +QTextStream &operator<<(QTextStream &s, QNativeEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeMouseEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeMouseMoveEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeMouseButtonEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeMouseDragEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeMouseWheelEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeKeyEvent *e); +QTextStream &operator<<(QTextStream &s, QNativeModifierEvent *e); + +QTextStream &operator>>(QTextStream &s, QNativeMouseMoveEvent *e); +QTextStream &operator>>(QTextStream &s, QNativeMouseButtonEvent *e); +QTextStream &operator>>(QTextStream &s, QNativeMouseDragEvent *e); +QTextStream &operator>>(QTextStream &s, QNativeMouseWheelEvent *e); +QTextStream &operator>>(QTextStream &s, QNativeKeyEvent *e); +QTextStream &operator>>(QTextStream &s, QNativeModifierEvent *e); + +// ---------------------------------------------------------------------------- +// Declare the main class that is supposed to be sub-classed by components +// that are to receive native events +// ---------------------------------------------------------------------------- + +class QNativeInput +{ + public: + QNativeInput(bool subscribe = true); + virtual ~QNativeInput(); + + // Callback methods. Should be implemented by interested sub-classes: + void notify(QNativeEvent *event); + virtual void nativeEvent(QNativeEvent *event); + virtual void nativeMousePressEvent(QNativeMouseButtonEvent *){}; + virtual void nativeMouseReleaseEvent(QNativeMouseButtonEvent *){}; + virtual void nativeMouseMoveEvent(QNativeMouseMoveEvent *){}; + virtual void nativeMouseDragEvent(QNativeMouseDragEvent *){}; + virtual void nativeMouseWheelEvent(QNativeMouseWheelEvent *){}; + virtual void nativeKeyPressEvent(QNativeKeyEvent *){}; + virtual void nativeKeyReleaseEvent(QNativeKeyEvent *){}; + virtual void nativeModifierEvent(QNativeModifierEvent *){}; + + // The following methods will differ in implementation from OS to OS: + static Qt::Native::Status sendNativeMouseButtonEvent(const QNativeMouseButtonEvent &event); + static Qt::Native::Status sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event); + static Qt::Native::Status sendNativeMouseDragEvent(const QNativeMouseDragEvent &event); + static Qt::Native::Status sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event); + static Qt::Native::Status sendNativeKeyEvent(const QNativeKeyEvent &event, int pid = 0); + static Qt::Native::Status sendNativeModifierEvent(const QNativeModifierEvent &event); + // sendNativeEvent will NOT differ from OS to OS. + static Qt::Native::Status sendNativeEvent(const QNativeEvent &event, int pid = 0); + + // The following methods will differ in implementation from OS to OS: + Qt::Native::Status subscribeForNativeEvents(); + Qt::Native::Status unsubscribeForNativeEvents(); +}; + +#endif // Q_NATIVE_INPUT diff --git a/tests/auto/integrationtests/macnativeevents/qnativeevents_mac.cpp b/tests/auto/integrationtests/macnativeevents/qnativeevents_mac.cpp new file mode 100644 index 0000000000..8987a8d502 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/qnativeevents_mac.cpp @@ -0,0 +1,382 @@ +/**************************************************************************** +** +** 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 "qnativeevents.h" +#include +#include + +// ************************************************************ +// Quartz +// ************************************************************ + +static Qt::KeyboardModifiers getModifiersFromQuartzEvent(CGEventRef inEvent) +{ + Qt::KeyboardModifiers m; + CGEventFlags flags = CGEventGetFlags(inEvent); + if (flags & kCGEventFlagMaskShift || flags & kCGEventFlagMaskAlphaShift) + m |= Qt::ShiftModifier; + if (flags & kCGEventFlagMaskControl) + m |= Qt::ControlModifier; + if (flags & kCGEventFlagMaskAlternate) + m |= Qt::AltModifier; + if (flags & kCGEventFlagMaskCommand) + m |= Qt::MetaModifier; + return m; +} + +static void setModifiersFromQNativeEvent(CGEventRef inEvent, const QNativeEvent &event) +{ + CGEventFlags flags = 0; + if (event.modifiers.testFlag(Qt::ShiftModifier)) + flags |= kCGEventFlagMaskShift; + if (event.modifiers.testFlag(Qt::ControlModifier)) + flags |= kCGEventFlagMaskControl; + if (event.modifiers.testFlag(Qt::AltModifier)) + flags |= kCGEventFlagMaskAlternate; + if (event.modifiers.testFlag(Qt::MetaModifier)) + flags |= kCGEventFlagMaskCommand; + CGEventSetFlags(inEvent, flags); +} + +static QPoint getMouseLocationFromQuartzEvent(CGEventRef inEvent) +{ + CGPoint pos = CGEventGetLocation(inEvent); + QPoint tmp; + tmp.setX(pos.x); + tmp.setY(pos.y); + return tmp; +} + +static QChar getCharFromQuartzEvent(CGEventRef inEvent) +{ + UniCharCount count = 0; + UniChar c; + CGEventKeyboardGetUnicodeString(inEvent, 1, &count, &c); + return QChar(c); +} + +static CGEventRef EventHandler_Quartz(CGEventTapProxy proxy, CGEventType type, CGEventRef inEvent, void *refCon) +{ + Q_UNUSED(proxy); + QNativeInput *nativeInput = static_cast(refCon); + switch (type){ + case kCGEventKeyDown:{ + QNativeKeyEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode); + e.character = getCharFromQuartzEvent(inEvent); + e.press = true; + nativeInput->notify(&e); + break; + } + case kCGEventKeyUp:{ + QNativeKeyEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode); + e.character = getCharFromQuartzEvent(inEvent); + e.press = false; + nativeInput->notify(&e); + break; + } + case kCGEventLeftMouseDown:{ + QNativeMouseButtonEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState); + e.button = Qt::LeftButton; + nativeInput->notify(&e); + break; + } + case kCGEventLeftMouseUp:{ + QNativeMouseButtonEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + e.clickCount = 0; + e.button = Qt::LeftButton; + nativeInput->notify(&e); + break; + } + case kCGEventRightMouseDown:{ + QNativeMouseButtonEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState); + e.button = Qt::RightButton; + nativeInput->notify(&e); + break; + } + case kCGEventRightMouseUp:{ + QNativeMouseButtonEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + e.clickCount = 0; + e.button = Qt::RightButton; + nativeInput->notify(&e); + break; + } + case kCGEventMouseMoved:{ + QNativeMouseMoveEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + nativeInput->notify(&e); + break; + } + case kCGEventLeftMouseDragged:{ + QNativeMouseDragEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState); + e.button = Qt::LeftButton; + nativeInput->notify(&e); + break; + } + case kCGEventScrollWheel:{ + QNativeMouseWheelEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.delta = CGEventGetIntegerValueField(inEvent, kCGScrollWheelEventDeltaAxis1); + e.globalPos = getMouseLocationFromQuartzEvent(inEvent); + nativeInput->notify(&e); + break; + } + case kCGEventFlagsChanged:{ + QNativeModifierEvent e; + e.modifiers = getModifiersFromQuartzEvent(inEvent); + e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode); + nativeInput->notify(&e); + break; + } + + } + + return inEvent; +} + +Qt::Native::Status insertEventHandler_Quartz(QNativeInput *nativeInput, int pid = 0) +{ + uid_t uid = geteuid(); + if (uid != 0) + qWarning("MacNativeEvents: You must be root to listen for key events!"); + + CFMachPortRef port; + if (!pid){ + port = CGEventTapCreate(kCGHIDEventTap, + kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, + kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput); + } else { + ProcessSerialNumber psn; + GetProcessForPID(pid, &psn); + port = CGEventTapCreateForPSN(&psn, + kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, + kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput); + } + + CFRunLoopSourceRef eventSrc = CFMachPortCreateRunLoopSource(NULL, port, 0); + CFRunLoopAddSource((CFRunLoopRef) GetCFRunLoopFromEventLoop(GetMainEventLoop()), + eventSrc, kCFRunLoopCommonModes); + + return Qt::Native::Success; +} + +Qt::Native::Status removeEventHandler_Quartz() +{ + return Qt::Native::Success; // ToDo: +} + +Qt::Native::Status sendNativeKeyEventToProcess_Quartz(const QNativeKeyEvent &event, int pid) +{ + ProcessSerialNumber psn; + GetProcessForPID(pid, &psn); + + CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press); + setModifiersFromQNativeEvent(e, event); + SetFrontProcess(&psn); + CGEventPostToPSN(&psn, e); + CFRelease(e); + return Qt::Native::Success; +} + +Qt::Native::Status sendNativeKeyEvent_Quartz(const QNativeKeyEvent &event) +{ + CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press); + setModifiersFromQNativeEvent(e, event); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); + return Qt::Native::Success; +} + +Qt::Native::Status sendNativeMouseMoveEvent_Quartz(const QNativeMouseMoveEvent &event) +{ + CGPoint pos; + pos.x = event.globalPos.x(); + pos.y = event.globalPos.y(); + + CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0); + setModifiersFromQNativeEvent(e, event); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); + return Qt::Native::Success; +} + +Qt::Native::Status sendNativeMouseButtonEvent_Quartz(const QNativeMouseButtonEvent &event) +{ + CGPoint pos; + pos.x = event.globalPos.x(); + pos.y = event.globalPos.y(); + + CGEventType type = 0; + if (event.button == Qt::LeftButton) + type = (event.clickCount > 0) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp; + else if (event.button == Qt::RightButton) + type = (event.clickCount > 0) ? kCGEventRightMouseDown : kCGEventRightMouseUp; + else + type = (event.clickCount > 0) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp; + + CGEventRef e = CGEventCreateMouseEvent(0, type, pos, event.button); + setModifiersFromQNativeEvent(e, event); + CGEventSetIntegerValueField(e, kCGMouseEventClickState, event.clickCount); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); + return Qt::Native::Success; +} + +Qt::Native::Status sendNativeMouseDragEvent_Quartz(const QNativeMouseDragEvent &event) +{ + CGPoint pos; + pos.x = event.globalPos.x(); + pos.y = event.globalPos.y(); + + CGEventType type = 0; + if (event.button == Qt::LeftButton) + type = kCGEventLeftMouseDragged; + else if (event.button == Qt::RightButton) + type = kCGEventRightMouseDragged; + else + type = kCGEventOtherMouseDragged; + + CGEventRef e = CGEventCreateMouseEvent(0, type, pos, event.button); + setModifiersFromQNativeEvent(e, event); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); + return Qt::Native::Success; +} + +Qt::Native::Status sendNativeMouseWheelEvent_Quartz(const QNativeMouseWheelEvent &event) +{ + CGPoint pos; + pos.x = event.globalPos.x(); + pos.y = event.globalPos.y(); + + CGEventRef e = CGEventCreateScrollWheelEvent(0, kCGScrollEventUnitPixel, 1, 0); + CGEventSetIntegerValueField(e, kCGScrollWheelEventDeltaAxis1, event.delta); + CGEventSetLocation(e, pos); + setModifiersFromQNativeEvent(e, event); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); + + return Qt::Native::Success; +} + +Qt::Native::Status sendNativeModifierEvent_Quartz(const QNativeModifierEvent &event) +{ + CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, 0); + CGEventSetType(e, kCGEventFlagsChanged); + setModifiersFromQNativeEvent(e, event); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); + return Qt::Native::Success; +} + +// ************************************************************ +// QNativeInput methods: +// ************************************************************ + +Qt::Native::Status QNativeInput::sendNativeMouseButtonEvent(const QNativeMouseButtonEvent &event) +{ + return sendNativeMouseButtonEvent_Quartz(event); +} + +Qt::Native::Status QNativeInput::sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event) +{ + return sendNativeMouseMoveEvent_Quartz(event); +} + +Qt::Native::Status QNativeInput::sendNativeMouseDragEvent(const QNativeMouseDragEvent &event) +{ + return sendNativeMouseDragEvent_Quartz(event); +} + +Qt::Native::Status QNativeInput::sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event) +{ + return sendNativeMouseWheelEvent_Quartz(event); +} + +Qt::Native::Status QNativeInput::sendNativeKeyEvent(const QNativeKeyEvent &event, int pid) +{ + if (!pid) + return sendNativeKeyEvent_Quartz(event); + else + return sendNativeKeyEventToProcess_Quartz(event, pid); +} + +Qt::Native::Status QNativeInput::sendNativeModifierEvent(const QNativeModifierEvent &event) +{ + return sendNativeModifierEvent_Quartz(event); +} + +Qt::Native::Status QNativeInput::subscribeForNativeEvents() +{ + return insertEventHandler_Quartz(this); +} + +Qt::Native::Status QNativeInput::unsubscribeForNativeEvents() +{ + return removeEventHandler_Quartz(); +} + +// Some Qt to Mac mappings: +int QNativeKeyEvent::Key_A = 0; +int QNativeKeyEvent::Key_B = 11; +int QNativeKeyEvent::Key_C = 8; +int QNativeKeyEvent::Key_1 = 18; +int QNativeKeyEvent::Key_Backspace = 51; +int QNativeKeyEvent::Key_Enter = 36; +int QNativeKeyEvent::Key_Del = 117; + diff --git a/tests/auto/integrationtests/macnativeevents/tst_macnativeevents.cpp b/tests/auto/integrationtests/macnativeevents/tst_macnativeevents.cpp new file mode 100644 index 0000000000..ea30b0b5c2 --- /dev/null +++ b/tests/auto/integrationtests/macnativeevents/tst_macnativeevents.cpp @@ -0,0 +1,522 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include + +#include "qnativeevents.h" +#include "nativeeventlist.h" +#include "expectedeventlist.h" +#include + +QT_USE_NAMESPACE + +class tst_MacNativeEvents : public QObject +{ +Q_OBJECT +private slots: + void testMouseMoveLocation(); + void testPushButtonPressRelease(); + void testMouseLeftDoubleClick(); + void stressTestMouseLeftDoubleClick(); + void testMouseDragInside(); + void testMouseDragOutside(); + void testMouseDragToNonClientArea(); + void testDragWindow(); + void testMouseEnter(); + void testChildDialogInFrontOfModalParent(); +// void testChildWindowInFrontOfParentWindow(); +// void testChildToolWindowInFrontOfChildNormalWindow(); + void testChildWindowInFrontOfStaysOnTopParentWindow(); + void testKeyPressOnToplevel(); + void testModifierShift(); + void testModifierAlt(); + void testModifierCtrl(); + void testModifierCtrlWithDontSwapCtrlAndMeta(); +}; + +void tst_MacNativeEvents::testMouseMoveLocation() +{ + QWidget w; + w.setMouseTracking(true); + w.show(); + QPoint p = w.geometry().center(); + + NativeEventList native; + native.append(new QNativeMouseMoveEvent(p, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p), p, Qt::NoButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testPushButtonPressRelease() +{ + // Check that a native mouse press and release generates the + // same qevents on a pushbutton: + QPushButton w("click me"); + w.show(); + QPoint p = w.geometry().center(); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testMouseLeftDoubleClick() +{ + // Check that a native double click makes + // the test widget receive a press-release-click-release: + QWidget w; + w.show(); + QPoint p = w.geometry().center(); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::stressTestMouseLeftDoubleClick() +{ + // Check that multiple, fast, double clicks makes + // the test widget receive correct click events + QWidget w; + w.show(); + QPoint p = w.geometry().center(); + + NativeEventList native; + ExpectedEventList expected(&w); + + for (int i=0; i<10; ++i){ + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); + + expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + } + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testMouseDragInside() +{ + // Check that a mouse drag inside a widget + // will cause press-move-release events to be delivered + QWidget w; + w.show(); + QPoint p1 = w.geometry().center(); + QPoint p2 = p1 - QPoint(10, 0); + QPoint p3 = p1 - QPoint(20, 0); + QPoint p4 = p1 - QPoint(30, 0); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(p1, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(p2, Qt::LeftButton, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(p3, Qt::LeftButton, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(p4, Qt::LeftButton, 0, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p1), p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p2), p2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p3), p3, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p4), p4, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testMouseDragOutside() +{ + // Check that if we drag the mouse from inside the + // widget, and release it outside, we still get mouse move + // and release events when the mouse is outside the widget. + QWidget w; + w.show(); + QPoint inside1 = w.geometry().center(); + QPoint inside2 = inside1 - QPoint(10, 0); + QPoint outside1 = w.geometry().topLeft() - QPoint(50, 0); + QPoint outside2 = outside1 - QPoint(10, 0); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(outside1, Qt::LeftButton, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(outside2, Qt::LeftButton, 0, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(outside1), outside1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(outside2), outside2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testMouseDragToNonClientArea() +{ + // Check that if we drag the mouse from inside the + // widget, and release it on the title bar, we still get mouse move + // and release events when the mouse is on the title bar + QWidget w; + w.show(); + QPoint inside1 = w.geometry().center(); + QPoint inside2 = inside1 - QPoint(10, 0); + QPoint titlebar1 = w.geometry().topLeft() - QPoint(-100, 10); + QPoint titlebar2 = titlebar1 - QPoint(10, 0); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(titlebar1, Qt::LeftButton, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(titlebar2, Qt::LeftButton, 0, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(titlebar1), titlebar1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(titlebar2), titlebar2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testDragWindow() +{ + // Check that if we drag the mouse from inside the + // widgets title bar, we get a move event on the window + QWidget w; + w.show(); + QPoint titlebar = w.geometry().topLeft() - QPoint(-100, 10); + QPoint moveTo = titlebar + QPoint(100, 0); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(titlebar, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseDragEvent(moveTo, Qt::LeftButton, Qt::NoModifier)); + native.append(500, new QNativeMouseButtonEvent(moveTo, Qt::LeftButton, 0, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonPress, w.mapFromGlobal(titlebar), titlebar, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonRelease, w.mapFromGlobal(titlebar), moveTo, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testMouseEnter() +{ + // When a mouse enters a widget, both a mouse enter events and a + // mouse move event should be sendt. Lets test this: + QWidget w; + w.setMouseTracking(true); + w.show(); + QPoint outside = w.geometry().topLeft() - QPoint(50, 0); + QPoint inside = w.geometry().center(); + + NativeEventList native; + native.append(new QNativeMouseMoveEvent(outside, Qt::NoModifier)); + native.append(new QNativeMouseMoveEvent(inside, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QEvent(QEvent::Enter)); + expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside), inside, Qt::NoButton, Qt::NoButton, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testChildDialogInFrontOfModalParent() +{ + // Test that a child dialog of a modal parent dialog is + // in front of the parent, and active: + QDialog parent; + parent.setWindowModality(Qt::ApplicationModal); + QDialog child(&parent); + QPushButton button("close", &child); + connect(&button, SIGNAL(clicked()), &child, SLOT(close())); + parent.show(); + child.show(); + QPoint inside = button.mapToGlobal(button.geometry().center()); + + // Post a click on the button to close the child dialog: + NativeEventList native; + native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier)); + + native.play(); + QTest::qWait(100); + QVERIFY(!child.isVisible()); +} + +#if 0 +// This test is disabled as of Qt-4.7.4 because we cannot do it +// unless we use the Cocoa sub window API. But using that opens up +// a world of side effects that we cannot live with. So we rather +// not support child-on-top-of-parent instead. +void tst_MacNativeEvents::testChildWindowInFrontOfParentWindow() +{ + // Test that a child window always stacks in front of its parent window. + // Do this by first click on the parent, then on the child window button. + QWidget parent; + QPushButton child("a button", &parent); + child.setWindowFlags(Qt::Window); + connect(&child, SIGNAL(clicked()), &child, SLOT(close())); + parent.show(); + child.show(); + + QPoint parent_p = parent.geometry().bottomLeft() + QPoint(20, -20); + QPoint child_p = child.geometry().center(); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 0, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 0, Qt::NoModifier)); + + native.play(); + QTest::qWait(100); + QVERIFY(!child.isVisible()); +} +#endif + +/* This test can be enabled once setStackingOrder has been fixed in qwidget_mac.mm +void tst_MacNativeEvents::testChildToolWindowInFrontOfChildNormalWindow() +{ + // Test that a child tool window always stacks in front of normal sibling windows. + // Do this by first click on the sibling, then on the tool window button. + QWidget parent; + QWidget normalChild(&parent, Qt::Window); + QPushButton toolChild("a button", &parent); + toolChild.setWindowFlags(Qt::Tool); + connect(&toolChild, SIGNAL(clicked()), &toolChild, SLOT(close())); + parent.show(); + normalChild.show(); + toolChild.show(); + + QPoint normalChild_p = normalChild.geometry().bottomLeft() + QPoint(20, -20); + QPoint toolChild_p = toolChild.geometry().center(); + + NativeEventList native; + native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 0, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 0, Qt::NoModifier)); + + native.play(); + QTest::qWait(100); + QVERIFY(!toolChild.isVisible()); +} +*/ +void tst_MacNativeEvents::testChildWindowInFrontOfStaysOnTopParentWindow() +{ + // Test that a child window stacks on top of a stays-on-top parent. + QWidget parent(0, Qt::WindowStaysOnTopHint); + QPushButton button("close", &parent); + button.setWindowFlags(Qt::Window); + connect(&button, SIGNAL(clicked()), &button, SLOT(close())); + parent.show(); + button.show(); + QPoint inside = button.geometry().center(); + + // Post a click on the button to close the child dialog: + NativeEventList native; + native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier)); + native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier)); + + native.play(); + QTest::qWait(100); + QVERIFY(!button.isVisible()); +} + +void tst_MacNativeEvents::testKeyPressOnToplevel() +{ + // Check that we receive keyevents for + // toplevel widgets. For leagacy reasons, and according to Qt on + // other platforms (carbon port + linux), we should get these events + // even when the focus policy is set to Qt::NoFocus when there is no + // other focus widget on screen: + QWidget w; + w.show(); + + NativeEventList native; + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::NoModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierShift() +{ + QWidget w; + w.show(); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::ShiftModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ShiftModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ShiftModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierAlt() +{ + QWidget w; + w.show(); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::AltModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::AltModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::AltModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::AltModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::AltModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Alt, Qt::AltModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierCtrl() +{ + // On Mac, we switch the Command and Control modifier by default, so that Command + // means Meta, and Control means Command. Lets check that this works: + QWidget w; + w.show(); + + QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]); + QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::MetaModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::MetaModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::MetaModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); +} + +void tst_MacNativeEvents::testModifierCtrlWithDontSwapCtrlAndMeta() +{ + // On Mac, we switch the Command and Control modifier by default, so that Command + // means Meta, and Control means Command. Lets check that the flag to swith off + // this behaviour works. While working on this test I realized that we actually + // don't (and never have) respected this flag for raw key events. Only for + // menus, through QKeySequence. I don't want to change this behaviour now, at + // least not until someone complains. So I choose to let the test just stop + // any unintended regressions instead. If we decide to resepect the the flag at one + // point, fix the test. + QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta); + QWidget w; + w.show(); + + QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]); + QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]); + + NativeEventList native; + native.append(new QNativeModifierEvent(Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier)); + native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier)); + native.append(new QNativeModifierEvent(Qt::NoModifier)); + + ExpectedEventList expected(&w); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier)); + expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ControlModifier)); + expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::ControlModifier)); + + native.play(); + QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); + QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, false); +} + +QTEST_MAIN(tst_MacNativeEvents) +#include "tst_macnativeevents.moc" diff --git a/tests/auto/integrationtests/macplist/app/app.pro b/tests/auto/integrationtests/macplist/app/app.pro new file mode 100644 index 0000000000..c1cf52e0ef --- /dev/null +++ b/tests/auto/integrationtests/macplist/app/app.pro @@ -0,0 +1,11 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Wed Jan 7 13:01:11 2009 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/tests/auto/integrationtests/macplist/app/main.cpp b/tests/auto/integrationtests/macplist/app/main.cpp new file mode 100644 index 0000000000..ddc47a9a5f --- /dev/null +++ b/tests/auto/integrationtests/macplist/app/main.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** 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 + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + return 0; +} diff --git a/tests/auto/integrationtests/macplist/macplist.pro b/tests/auto/integrationtests/macplist/macplist.pro new file mode 100644 index 0000000000..3a0e2d43d3 --- /dev/null +++ b/tests/auto/integrationtests/macplist/macplist.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs + +SUBDIRS = app test +CONFIG += ordered + + + diff --git a/tests/auto/integrationtests/macplist/test/test.pro b/tests/auto/integrationtests/macplist/test/test.pro new file mode 100644 index 0000000000..4751b47e00 --- /dev/null +++ b/tests/auto/integrationtests/macplist/test/test.pro @@ -0,0 +1,11 @@ +load(qttest_p4) + +SOURCES += ../tst_macplist.cpp +TARGET = ../tst_macplist +win32 { + CONFIG(debug, debug|release) { + TARGET = ../../debug/tst_macplist + } else { + TARGET = ../../release/tst_macplist + } +} diff --git a/tests/auto/integrationtests/macplist/tst_macplist.cpp b/tests/auto/integrationtests/macplist/tst_macplist.cpp new file mode 100644 index 0000000000..5b48c586b5 --- /dev/null +++ b/tests/auto/integrationtests/macplist/tst_macplist.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include + +class tst_MacPlist : public QObject +{ + Q_OBJECT +public: + tst_MacPlist() {} + +private slots: +#ifdef Q_OS_MAC + void test_plist_data(); + void test_plist(); +#endif +}; + +#ifdef Q_OS_MAC +void tst_MacPlist::test_plist_data() +{ + QTest::addColumn("test_plist"); + + QTest::newRow("control") << QString::fromLatin1( +"" +"\n" +"\n" +"\n" +" CFBundleIconFile\n" +" \n" +" CFBundlePackageType\n" +" APPL\n" +" CFBundleGetInfoString\n" +" Created by Qt/QMake\n" +" CFBundleExecutable\n" +" app\n" +" CFBundleIdentifier\n" +" com.yourcompany.app\n" +"\n" +"\n"); + + QTest::newRow("LSUIElement-as-string") << QString::fromLatin1( +"" +"\n" +"\n" +"\n" +" CFBundleIconFile\n" +" \n" +" CFBundlePackageType\n" +" APPL\n" +" CFBundleGetInfoString\n" +" Created by Qt/QMake\n" +" CFBundleExecutable\n" +" app\n" +" CFBundleIdentifier\n" +" com.yourcompany.app\n" +" LSUIElement\n" +" false\n" +"\n" +"\n"); + + QTest::newRow("LSUIElement-as-bool") << QString::fromLatin1( +"" +"\n" +"\n" +"\n" +" CFBundleIconFile\n" +" \n" +" CFBundlePackageType\n" +" APPL\n" +" CFBundleGetInfoString\n" +" Created by Qt/QMake\n" +" CFBundleExecutable\n" +" app\n" +" CFBundleIdentifier\n" +" com.yourcompany.app\n" +" LSUIElement\n" +" \n" +"\n" +"\n"); + + QTest::newRow("LSUIElement-as-int") << QString::fromLatin1( +"" +"\n" +"\n" +"\n" +" CFBundleIconFile\n" +" \n" +" CFBundlePackageType\n" +" APPL\n" +" CFBundleGetInfoString\n" +" Created by Qt/QMake\n" +" CFBundleExecutable\n" +" app\n" +" CFBundleIdentifier\n" +" com.yourcompany.app\n" +" LSUIElement\n" +" 0\n" +"\n" +"\n"); + + QTest::newRow("LSUIElement-as-garbage") << QString::fromLatin1( +"" +"\n" +"\n" +"\n" +" CFBundleIconFile\n" +" \n" +" CFBundlePackageType\n" +" APPL\n" +" CFBundleGetInfoString\n" +" Created by Qt/QMake\n" +" CFBundleExecutable\n" +" app\n" +" CFBundleIdentifier\n" +" com.yourcompany.app\n" +" LSUIElement\n" +" 0\n" +"\n" +"\n"); +} + +void tst_MacPlist::test_plist() +{ + QFETCH(QString, test_plist); + + QString infoPlist = QLatin1String("Info.plist"); + QDir dir(QCoreApplication::applicationDirPath()); + QVERIFY(dir.cdUp()); + QVERIFY(dir.cdUp()); + QVERIFY(dir.cdUp()); + QVERIFY(dir.cd(QLatin1String("app"))); + QVERIFY(dir.cd(QLatin1String("app.app"))); + QVERIFY(dir.cd(QLatin1String("Contents"))); + QVERIFY(dir.exists(infoPlist)); + { + QFile file(dir.filePath(infoPlist)); + QVERIFY(file.open(QIODevice::WriteOnly)); + QByteArray ba = test_plist.toUtf8(); + QCOMPARE(file.write(ba), qint64(ba.size())); + } + QVERIFY(dir.cd(QLatin1String("MacOS"))); + QVERIFY(dir.exists(QLatin1String("app"))); + QProcess process; + process.start(dir.filePath("app")); + QCOMPARE(process.waitForFinished(), true); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); +} +#endif + +QTEST_MAIN(tst_MacPlist) +#include "tst_macplist.moc" diff --git a/tests/auto/integrationtests/modeltest/dynamictreemodel.cpp b/tests/auto/integrationtests/modeltest/dynamictreemodel.cpp new file mode 100644 index 0000000000..2f8bb0a730 --- /dev/null +++ b/tests/auto/integrationtests/modeltest/dynamictreemodel.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Stephen Kelly +** 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 "dynamictreemodel.h" + +#include +#include +#include +#include + + +DynamicTreeModel::DynamicTreeModel(QObject *parent) + : QAbstractItemModel(parent), + nextId(1) +{ +} + +QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const +{ +// if (column != 0) +// return QModelIndex(); + + + if ( column < 0 || row < 0 ) + return QModelIndex(); + + QList > childIdColumns = m_childItems.value(parent.internalId()); + + const qint64 grandParent = findParentId(parent.internalId()); + if (grandParent >= 0) { + QList > parentTable = m_childItems.value(grandParent); + if (parent.column() >= parentTable.size()) + qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO); + QList parentSiblings = parentTable.at(parent.column()); + if (parent.row() >= parentSiblings.size()) + qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO); + } + + if (childIdColumns.size() == 0) + return QModelIndex(); + + if (column >= childIdColumns.size()) + return QModelIndex(); + + QList rowIds = childIdColumns.at(column); + + if ( row >= rowIds.size()) + return QModelIndex(); + + qint64 id = rowIds.at(row); + + return createIndex(row, column, reinterpret_cast(id)); + +} + +qint64 DynamicTreeModel::findParentId(qint64 searchId) const +{ + if (searchId <= 0) + return -1; + + QHashIterator > > i(m_childItems); + while (i.hasNext()) + { + i.next(); + QListIterator > j(i.value()); + while (j.hasNext()) + { + QList l = j.next(); + if (l.contains(searchId)) + { + return i.key(); + } + } + } + return -1; +} + +QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + qint64 searchId = index.internalId(); + qint64 parentId = findParentId(searchId); + // Will never happen for valid index, but what the hey... + if (parentId <= 0) + return QModelIndex(); + + qint64 grandParentId = findParentId(parentId); + if (grandParentId < 0) + grandParentId = 0; + + int column = 0; + QList childList = m_childItems.value(grandParentId).at(column); + + int row = childList.indexOf(parentId); + + return createIndex(row, column, reinterpret_cast(parentId)); + +} + +int DynamicTreeModel::rowCount(const QModelIndex &index ) const +{ + QList > cols = m_childItems.value(index.internalId()); + + if (cols.size() == 0 ) + return 0; + + if (index.column() > 0) + return 0; + + return cols.at(0).size(); +} + +int DynamicTreeModel::columnCount(const QModelIndex &index ) const +{ +// Q_UNUSED(index); + return m_childItems.value(index.internalId()).size(); +} + +QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (Qt::DisplayRole == role) + { + return m_items.value(index.internalId()); + } + return QVariant(); +} + +void DynamicTreeModel::clear() +{ + beginResetModel(); + m_items.clear(); + m_childItems.clear(); + nextId = 1; + endResetModel(); +} + + +ModelChangeCommand::ModelChangeCommand( DynamicTreeModel *model, QObject *parent ) + : QObject(parent), m_model(model), m_numCols(1), m_startRow(-1), m_endRow(-1) +{ + +} + +QModelIndex ModelChangeCommand::findIndex(QList rows) +{ + const int col = 0; + QModelIndex parent = QModelIndex(); + QListIterator i(rows); + while (i.hasNext()) + { + parent = m_model->index(i.next(), col, parent); + if (!parent.isValid()) + qFatal("%s: parent must be valid", Q_FUNC_INFO); + } + return parent; +} + +ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent ) + : ModelChangeCommand(model, parent) +{ + +} + +void ModelInsertCommand::doCommand() +{ + QModelIndex parent = findIndex(m_rowNumbers); + m_model->beginInsertRows(parent, m_startRow, m_endRow); + qint64 parentId = parent.internalId(); + for (int row = m_startRow; row <= m_endRow; row++) + { + for(int col = 0; col < m_numCols; col++ ) + { + if (m_model->m_childItems[parentId].size() <= col) + { + m_model->m_childItems[parentId].append(QList()); + } +// QString name = QUuid::createUuid().toString(); + qint64 id = m_model->newId(); + QString name = QString::number(id); + + m_model->m_items.insert(id, name); + m_model->m_childItems[parentId][col].insert(row, id); + + } + } + m_model->endInsertRows(); +} + + +ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) + : ModelChangeCommand(model, parent) +{ + +} +bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +{ + return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow); +} + +void ModelMoveCommand::doCommand() +{ + QModelIndex srcParent = findIndex(m_rowNumbers); + QModelIndex destParent = findIndex(m_destRowNumbers); + + if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow)) + { + return; + } + + for (int column = 0; column < m_numCols; ++column) + { + QList l = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1 ); + + for (int i = m_startRow; i <= m_endRow ; i++) + { + m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow); + } + int d; + if (m_destRow < m_startRow) + d = m_destRow; + else + { + if (srcParent == destParent) + d = m_destRow - (m_endRow - m_startRow + 1); + else + d = m_destRow - (m_endRow - m_startRow) + 1; + } + + foreach(const qint64 id, l) + { + m_model->m_childItems[destParent.internalId()][column].insert(d++, id); + } + } + + emitPostSignal(); +} + +void ModelMoveCommand::emitPostSignal() +{ + m_model->endMoveRows(); +} + +ModelResetCommand::ModelResetCommand(DynamicTreeModel* model, QObject* parent) + : ModelMoveCommand(model, parent) +{ + +} + +ModelResetCommand::~ModelResetCommand() +{ + +} + +bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +{ + Q_UNUSED(srcParent); + Q_UNUSED(srcStart); + Q_UNUSED(srcEnd); + Q_UNUSED(destParent); + Q_UNUSED(destRow); + + return true; +} + +void ModelResetCommand::emitPostSignal() +{ + m_model->reset(); +} + +ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent) + : ModelMoveCommand(model, parent) +{ + +} + +ModelResetCommandFixed::~ModelResetCommandFixed() +{ + +} + +bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +{ + Q_UNUSED(srcParent); + Q_UNUSED(srcStart); + Q_UNUSED(srcEnd); + Q_UNUSED(destParent); + Q_UNUSED(destRow); + + m_model->beginResetModel(); + return true; +} + +void ModelResetCommandFixed::emitPostSignal() +{ + m_model->endResetModel(); +} + diff --git a/tests/auto/integrationtests/modeltest/dynamictreemodel.h b/tests/auto/integrationtests/modeltest/dynamictreemodel.h new file mode 100644 index 0000000000..81ef80cc40 --- /dev/null +++ b/tests/auto/integrationtests/modeltest/dynamictreemodel.h @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Stephen Kelly +** 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 DYNAMICTREEMODEL_H +#define DYNAMICTREEMODEL_H + +#include + +#include +#include + + +class DynamicTreeModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + DynamicTreeModel(QObject *parent = 0); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &index = QModelIndex()) const; + int columnCount(const QModelIndex &index = QModelIndex()) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + void clear(); + +protected slots: + + /** + Finds the parent id of the string with id @p searchId. + + Returns -1 if not found. + */ + qint64 findParentId(qint64 searchId) const; + +private: + QHash m_items; + QHash > > m_childItems; + qint64 nextId; + qint64 newId() { return nextId++; }; + + QModelIndex m_nextParentIndex; + int m_nextRow; + + int m_depth; + int maxDepth; + + friend class ModelInsertCommand; + friend class ModelMoveCommand; + friend class ModelResetCommand; + friend class ModelResetCommandFixed; + +}; + + +class ModelChangeCommand : public QObject +{ + Q_OBJECT +public: + + ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 ); + + virtual ~ModelChangeCommand() {} + + void setAncestorRowNumbers(QList rowNumbers) { m_rowNumbers = rowNumbers; } + + QModelIndex findIndex(QList rows); + + void setStartRow(int row) { m_startRow = row; } + + void setEndRow(int row) { m_endRow = row; } + + void setNumCols(int cols) { m_numCols = cols; } + + virtual void doCommand() = 0; + +protected: + DynamicTreeModel* m_model; + QList m_rowNumbers; + int m_numCols; + int m_startRow; + int m_endRow; + +}; + +typedef QList ModelChangeCommandList; + +class ModelInsertCommand : public ModelChangeCommand +{ + Q_OBJECT + +public: + + ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 ); + virtual ~ModelInsertCommand() {} + + virtual void doCommand(); +}; + + +class ModelMoveCommand : public ModelChangeCommand +{ + Q_OBJECT +public: + ModelMoveCommand(DynamicTreeModel *model, QObject *parent); + + virtual ~ModelMoveCommand() {} + + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + + virtual void doCommand(); + + virtual void emitPostSignal(); + + void setDestAncestors( QList rows ) { m_destRowNumbers = rows; } + + void setDestRow(int row) { m_destRow = row; } + +protected: + QList m_destRowNumbers; + int m_destRow; +}; + +/** + A command which does a move and emits a reset signal. +*/ +class ModelResetCommand : public ModelMoveCommand +{ + Q_OBJECT +public: + ModelResetCommand(DynamicTreeModel* model, QObject* parent = 0); + + virtual ~ModelResetCommand(); + + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + virtual void emitPostSignal(); + +}; + +/** + A command which does a move and emits a beginResetModel and endResetModel signals. +*/ +class ModelResetCommandFixed : public ModelMoveCommand +{ + Q_OBJECT +public: + ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent = 0); + + virtual ~ModelResetCommandFixed(); + + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + virtual void emitPostSignal(); + +}; + + +#endif diff --git a/tests/auto/integrationtests/modeltest/modeltest.cpp b/tests/auto/integrationtests/modeltest/modeltest.cpp new file mode 100644 index 0000000000..76803dfbe5 --- /dev/null +++ b/tests/auto/integrationtests/modeltest/modeltest.cpp @@ -0,0 +1,564 @@ +/**************************************************************************** +** +** 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 + +#include "modeltest.h" + +#include + +Q_DECLARE_METATYPE ( QModelIndex ) + +/*! + Connect to all of the models signals. Whenever anything happens recheck everything. +*/ +ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) +{ + if (!model) + qFatal("%s: model must not be null", Q_FUNC_INFO); + + connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), + this, SLOT ( runAllTests() ) ); + + // Special checks for inserting/removing + connect ( model, SIGNAL ( layoutAboutToBeChanged() ), + this, SLOT ( layoutAboutToBeChanged() ) ); + connect ( model, SIGNAL ( layoutChanged() ), + this, SLOT ( layoutChanged() ) ); + + connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), + this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); + connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), + this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); + connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), + this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); + connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), + this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); + + runAllTests(); +} + +void ModelTest::runAllTests() +{ + if ( fetchingMore ) + return; + nonDestructiveBasicTest(); + rowCount(); + columnCount(); + hasIndex(); + index(); + parent(); + data(); +} + +/*! + nonDestructiveBasicTest tries to call a number of the basic functions (not all) + to make sure the model doesn't outright segfault, testing the functions that makes sense. +*/ +void ModelTest::nonDestructiveBasicTest() +{ + QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() ); + model->canFetchMore ( QModelIndex() ); + QVERIFY( model->columnCount ( QModelIndex() ) >= 0 ); + QVERIFY( model->data ( QModelIndex() ) == QVariant() ); + fetchingMore = true; + model->fetchMore ( QModelIndex() ); + fetchingMore = false; + Qt::ItemFlags flags = model->flags ( QModelIndex() ); + QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 ); + model->hasChildren ( QModelIndex() ); + model->hasIndex ( 0, 0 ); + model->headerData ( 0, Qt::Horizontal ); + model->index ( 0, 0 ); + model->itemData ( QModelIndex() ); + QVariant cache; + model->match ( QModelIndex(), -1, cache ); + model->mimeTypes(); + QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); + QVERIFY( model->rowCount() >= 0 ); + QVariant variant; + model->setData ( QModelIndex(), variant, -1 ); + model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); + model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); + QMap roles; + model->sibling ( 0, 0, QModelIndex() ); + model->span ( QModelIndex() ); + model->supportedDropActions(); +} + +/*! + Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() + + Models that are dynamically populated are not as fully tested here. + */ +void ModelTest::rowCount() +{ +// qDebug() << "rc"; + // check top row + QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); + int rows = model->rowCount ( topIndex ); + QVERIFY( rows >= 0 ); + if ( rows > 0 ) + QVERIFY( model->hasChildren ( topIndex ) ); + + QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); + if ( secondLevelIndex.isValid() ) { // not the top level + // check a row count where parent is valid + rows = model->rowCount ( secondLevelIndex ); + QVERIFY( rows >= 0 ); + if ( rows > 0 ) + QVERIFY( model->hasChildren ( secondLevelIndex ) ); + } + + // The models rowCount() is tested more extensively in checkChildren(), + // but this catches the big mistakes +} + +/*! + Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() + */ +void ModelTest::columnCount() +{ + // check top row + QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); + QVERIFY( model->columnCount ( topIndex ) >= 0 ); + + // check a column count where parent is valid + QModelIndex childIndex = model->index ( 0, 0, topIndex ); + if ( childIndex.isValid() ) + QVERIFY( model->columnCount ( childIndex ) >= 0 ); + + // columnCount() is tested more extensively in checkChildren(), + // but this catches the big mistakes +} + +/*! + Tests model's implementation of QAbstractItemModel::hasIndex() + */ +void ModelTest::hasIndex() +{ +// qDebug() << "hi"; + // Make sure that invalid values returns an invalid index + QVERIFY( !model->hasIndex ( -2, -2 ) ); + QVERIFY( !model->hasIndex ( -2, 0 ) ); + QVERIFY( !model->hasIndex ( 0, -2 ) ); + + int rows = model->rowCount(); + int columns = model->columnCount(); + + // check out of bounds + QVERIFY( !model->hasIndex ( rows, columns ) ); + QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) ); + + if ( rows > 0 ) + QVERIFY( model->hasIndex ( 0, 0 ) ); + + // hasIndex() is tested more extensively in checkChildren(), + // but this catches the big mistakes +} + +/*! + Tests model's implementation of QAbstractItemModel::index() + */ +void ModelTest::index() +{ +// qDebug() << "i"; + // Make sure that invalid values returns an invalid index + QVERIFY( model->index ( -2, -2 ) == QModelIndex() ); + QVERIFY( model->index ( -2, 0 ) == QModelIndex() ); + QVERIFY( model->index ( 0, -2 ) == QModelIndex() ); + + int rows = model->rowCount(); + int columns = model->columnCount(); + + if ( rows == 0 ) + return; + + // Catch off by one errors + QVERIFY( model->index ( rows, columns ) == QModelIndex() ); + QVERIFY( model->index ( 0, 0 ).isValid() ); + + // Make sure that the same index is *always* returned + QModelIndex a = model->index ( 0, 0 ); + QModelIndex b = model->index ( 0, 0 ); + QVERIFY( a == b ); + + // index() is tested more extensively in checkChildren(), + // but this catches the big mistakes +} + +/*! + Tests model's implementation of QAbstractItemModel::parent() + */ +void ModelTest::parent() +{ +// qDebug() << "p"; + // Make sure the model wont crash and will return an invalid QModelIndex + // when asked for the parent of an invalid index. + QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); + + if ( model->rowCount() == 0 ) + return; + + // Column 0 | Column 1 | + // QModelIndex() | | + // \- topIndex | topIndex1 | + // \- childIndex | childIndex1 | + + // Common error test #1, make sure that a top level index has a parent + // that is a invalid QModelIndex. + QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); + QVERIFY( model->parent ( topIndex ) == QModelIndex() ); + + // Common error test #2, make sure that a second level index has a parent + // that is the first level index. + if ( model->rowCount ( topIndex ) > 0 ) { + QModelIndex childIndex = model->index ( 0, 0, topIndex ); + QVERIFY( model->parent ( childIndex ) == topIndex ); + } + + // Common error test #3, the second column should NOT have the same children + // as the first column in a row. + // Usually the second column shouldn't have children. + QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); + if ( model->rowCount ( topIndex1 ) > 0 ) { + QModelIndex childIndex = model->index ( 0, 0, topIndex ); + QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); + QVERIFY( childIndex != childIndex1 ); + } + + // Full test, walk n levels deep through the model making sure that all + // parent's children correctly specify their parent. + checkChildren ( QModelIndex() ); +} + +/*! + Called from the parent() test. + + 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() already 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 ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) +{ + // First just try walking back up the tree. + QModelIndex p = parent; + while ( p.isValid() ) + p = p.parent(); + + // For models that are dynamically populated + if ( model->canFetchMore ( parent ) ) { + fetchingMore = true; + model->fetchMore ( parent ); + fetchingMore = false; + } + + int rows = model->rowCount ( parent ); + int columns = model->columnCount ( parent ); + + if ( rows > 0 ) + QVERIFY( model->hasChildren ( parent ) ); + + // Some further testing against rows(), columns(), and hasChildren() + QVERIFY( rows >= 0 ); + QVERIFY( columns >= 0 ); + if ( rows > 0 ) + QVERIFY( model->hasChildren ( parent ) ); + + //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows + // << "columns:" << columns << "parent column:" << parent.column(); + + QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); + for ( int r = 0; r < rows; ++r ) { + if ( model->canFetchMore ( parent ) ) { + fetchingMore = true; + model->fetchMore ( parent ); + fetchingMore = false; + } + QVERIFY( !model->hasIndex ( r, columns + 1, parent ) ); + for ( int c = 0; c < columns; ++c ) { + QVERIFY( model->hasIndex ( r, c, parent ) ); + QModelIndex index = model->index ( r, c, parent ); + // rowCount() and columnCount() said that it existed... + QVERIFY( index.isValid() ); + + // index() should always return the same index when called twice in a row + QModelIndex modifiedIndex = model->index ( r, c, parent ); + QVERIFY( index == modifiedIndex ); + + // Make sure we get the same index if we request it twice in a row + QModelIndex a = model->index ( r, c, parent ); + QModelIndex b = model->index ( r, c, parent ); + QVERIFY( a == b ); + + // Some basic checking on the index that is returned + QVERIFY( index.model() == model ); + QCOMPARE( index.row(), r ); + QCOMPARE( index.column(), c ); + // While you can technically return a QVariant usually this is a sign + // of a bug in data(). Disable if this really is ok in your model. +// QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() ); + + // If the next test fails here is some somewhat useful debug you play with. + + if (model->parent(index) != parent) { + qDebug() << r << c << currentDepth << model->data(index).toString() + << model->data(parent).toString(); + qDebug() << index << parent << model->parent(index); +// And a view that you can even use to show the model. +// QTreeView view; +// view.setModel(model); +// view.show(); + } + + // Check that we can get back our real parent. + QCOMPARE( model->parent ( index ), parent ); + + // recursively go down the children + if ( model->hasChildren ( index ) && currentDepth < 10 ) { + //qDebug() << r << c << "has children" << model->rowCount(index); + checkChildren ( index, ++currentDepth ); + }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ + + // make sure that after testing the children that the index doesn't change. + QModelIndex newerIndex = model->index ( r, c, parent ); + QVERIFY( index == newerIndex ); + } + } +} + +/*! + Tests model's implementation of QAbstractItemModel::data() + */ +void ModelTest::data() +{ + // Invalid index should return an invalid qvariant + QVERIFY( !model->data ( QModelIndex() ).isValid() ); + + if ( model->rowCount() == 0 ) + return; + + // A valid index should have a valid QVariant data + QVERIFY( model->index ( 0, 0 ).isValid() ); + + // shouldn't be able to set data on an invalid index + QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) ); + + // General Purpose roles that should return a QString + QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); + if ( variant.isValid() ) { + QVERIFY( qVariantCanConvert ( variant ) ); + } + variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); + if ( variant.isValid() ) { + QVERIFY( qVariantCanConvert ( variant ) ); + } + variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); + if ( variant.isValid() ) { + QVERIFY( qVariantCanConvert ( variant ) ); + } + + // General Purpose roles that should return a QSize + variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); + if ( variant.isValid() ) { + QVERIFY( qVariantCanConvert ( variant ) ); + } + + // General Purpose roles that should return a QFont + QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); + if ( fontVariant.isValid() ) { + QVERIFY( qVariantCanConvert ( fontVariant ) ); + } + + // Check that the alignment is one we know about + QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); + if ( textAlignmentVariant.isValid() ) { + int alignment = textAlignmentVariant.toInt(); + QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); + } + + // General Purpose roles that should return a QColor + QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); + if ( colorVariant.isValid() ) { + QVERIFY( qVariantCanConvert ( colorVariant ) ); + } + + colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); + if ( colorVariant.isValid() ) { + QVERIFY( qVariantCanConvert ( colorVariant ) ); + } + + // Check that the "check state" is one we know about. + QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); + if ( checkStateVariant.isValid() ) { + int state = checkStateVariant.toInt(); + QVERIFY( state == Qt::Unchecked || + state == Qt::PartiallyChecked || + state == Qt::Checked ); + } +} + +/*! + Store what is about to be inserted to make sure it actually happens + + \sa rowsInserted() + */ +void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */) +{ +// Q_UNUSED(end); +// qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() +// << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); +// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); + Changing c; + c.parent = parent; + c.oldSize = model->rowCount ( parent ); + c.last = model->data ( model->index ( start - 1, 0, parent ) ); + c.next = model->data ( model->index ( start, 0, parent ) ); + insert.push ( c ); +} + +/*! + Confirm that what was said was going to happen actually did + + \sa rowsAboutToBeInserted() + */ +void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) +{ + Changing c = insert.pop(); + QVERIFY( c.parent == parent ); +// qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize +// << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); + +// for (int ii=start; ii <= end; ii++) +// { +// qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); +// } +// qDebug(); + + QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); + QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); + + if (c.next != model->data(model->index(end + 1, 0, c.parent))) { + qDebug() << start << end; + for (int i=0; i < model->rowCount(); ++i) + qDebug() << model->index(i, 0).data().toString(); + qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); + } + + QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); +} + +void ModelTest::layoutAboutToBeChanged() +{ + for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) + changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); +} + +void ModelTest::layoutChanged() +{ + for ( int i = 0; i < changing.count(); ++i ) { + QPersistentModelIndex p = changing[i]; + QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) ); + } + changing.clear(); +} + +/*! + Store what is about to be inserted to make sure it actually happens + + \sa rowsRemoved() + */ +void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) +{ +qDebug() << "ratbr" << parent << start << end; + Changing c; + c.parent = parent; + c.oldSize = model->rowCount ( parent ); + c.last = model->data ( model->index ( start - 1, 0, parent ) ); + c.next = model->data ( model->index ( end + 1, 0, parent ) ); + remove.push ( c ); +} + +/*! + Confirm that what was said was going to happen actually did + + \sa rowsAboutToBeRemoved() + */ +void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) +{ + qDebug() << "rr" << parent << start << end; + Changing c = remove.pop(); + QVERIFY( c.parent == parent ); + QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); + QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); + QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); +} + + diff --git a/tests/auto/integrationtests/modeltest/modeltest.h b/tests/auto/integrationtests/modeltest/modeltest.h new file mode 100644 index 0000000000..e4ef478c5e --- /dev/null +++ b/tests/auto/integrationtests/modeltest/modeltest.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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 MODELTEST_H +#define MODELTEST_H + +#include +#include +#include + +class ModelTest : public QObject +{ + Q_OBJECT + +public: + ModelTest( QAbstractItemModel *model, QObject *parent = 0 ); + +private Q_SLOTS: + void nonDestructiveBasicTest(); + void rowCount(); + void columnCount(); + void hasIndex(); + void index(); + void parent(); + void data(); + +protected Q_SLOTS: + void runAllTests(); + void layoutAboutToBeChanged(); + void layoutChanged(); + void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end ); + void rowsInserted( const QModelIndex & parent, int start, int end ); + void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end ); + void rowsRemoved( const QModelIndex & parent, int start, int end ); + +private: + void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); + + QAbstractItemModel *model; + + struct Changing { + QModelIndex parent; + int oldSize; + QVariant last; + QVariant next; + }; + QStack insert; + QStack remove; + + bool fetchingMore; + + QList changing; +}; + +#endif diff --git a/tests/auto/integrationtests/modeltest/modeltest.pro b/tests/auto/integrationtests/modeltest/modeltest.pro new file mode 100644 index 0000000000..d4a8ba971d --- /dev/null +++ b/tests/auto/integrationtests/modeltest/modeltest.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_modeltest.cpp modeltest.cpp dynamictreemodel.cpp +HEADERS += modeltest.h dynamictreemodel.h + + + diff --git a/tests/auto/integrationtests/modeltest/tst_modeltest.cpp b/tests/auto/integrationtests/modeltest/tst_modeltest.cpp new file mode 100644 index 0000000000..434537a81f --- /dev/null +++ b/tests/auto/integrationtests/modeltest/tst_modeltest.cpp @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** 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 +#include +#include + +#include "modeltest.h" +#include "dynamictreemodel.h" + + +class tst_ModelTest : public QObject +{ + Q_OBJECT + +public: + tst_ModelTest() {} + virtual ~tst_ModelTest() {} + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void stringListModel(); + void treeWidgetModel(); + void standardItemModel(); + void testInsertThroughProxy(); + void moveSourceItems(); + void testResetThroughProxy(); +}; + + + +void tst_ModelTest::initTestCase() +{ +} + +void tst_ModelTest::cleanupTestCase() +{ +} + +void tst_ModelTest::init() +{ + +} + +void tst_ModelTest::cleanup() +{ +} +/* + tests +*/ + +void tst_ModelTest::stringListModel() +{ + QStringListModel model; + QSortFilterProxyModel proxy; + + ModelTest t1(&model); + ModelTest t2(&proxy); + + proxy.setSourceModel(&model); + + model.setStringList(QStringList() << "2" << "3" << "1"); + model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c" ); + + proxy.setDynamicSortFilter(true); + proxy.setFilterRegExp(QRegExp("[^b]")); +} + +void tst_ModelTest::treeWidgetModel() +{ + QTreeWidget widget; + + ModelTest t1(widget.model()); + + QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root")); + for (int i = 0; i < 20; ++i) { + new QTreeWidgetItem(root, QStringList(QString::number(i))); + } + QTreeWidgetItem *remove = root->child(2); + root->removeChild(remove); + QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent")); + new QTreeWidgetItem(parent, QStringList("child")); + widget.setItemHidden(parent, true); + + widget.sortByColumn(0); +} + +void tst_ModelTest::standardItemModel() +{ + QStandardItemModel model(10,10); + QSortFilterProxyModel proxy; + + + ModelTest t1(&model); + ModelTest t2(&proxy); + + proxy.setSourceModel(&model); + + model.insertRows(2, 5); + model.removeRows(4, 5); + + model.insertColumns(2, 5); + model.removeColumns(4, 5); + + model.insertRows(0,5, model.index(1,1)); + model.insertColumns(0,5, model.index(1,3)); +} + +void tst_ModelTest::testInsertThroughProxy() +{ + DynamicTreeModel *model = new DynamicTreeModel(this); + + QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); + proxy->setSourceModel(model); + + new ModelTest(proxy, this); + + ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); + insertCommand->setNumCols(4); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + // Parent is QModelIndex() + insertCommand->doCommand(); + + insertCommand = new ModelInsertCommand(model, this); + insertCommand->setNumCols(4); + insertCommand->setAncestorRowNumbers(QList() << 5); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + insertCommand->doCommand(); + + ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this); + moveCommand->setNumCols(4); + moveCommand->setStartRow(0); + moveCommand->setEndRow(0); + moveCommand->setDestRow(9); + moveCommand->setDestAncestors(QList() << 5); + moveCommand->doCommand(); +} + +/** + Makes the persistent index list publicly accessible +*/ +class AccessibleProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {} + + QModelIndexList persistent() + { + return persistentIndexList(); + } +}; + +class ObservingObject : public QObject +{ + Q_OBJECT +public: + ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0) + : QObject(parent) + , m_proxy(proxy) + , storePersistentFailureCount(0) + , checkPersistentFailureCount(0) + { + connect(m_proxy, SIGNAL(layoutAboutToBeChanged()), SLOT(storePersistent())); + connect(m_proxy, SIGNAL(layoutChanged()), SLOT(checkPersistent())); + } + +public slots: + + void storePersistent(const QModelIndex &parent) + { + for (int row = 0; row < m_proxy->rowCount(parent); ++row) { + QModelIndex proxyIndex = m_proxy->index(row, 0, parent); + QModelIndex sourceIndex = m_proxy->mapToSource(proxyIndex); + if (!proxyIndex.isValid()) { + qWarning("%s: Invalid proxy index", Q_FUNC_INFO); + ++storePersistentFailureCount; + } + if (!sourceIndex.isValid()) { + qWarning("%s: invalid source index", Q_FUNC_INFO); + ++storePersistentFailureCount; + } + m_persistentSourceIndexes.append(sourceIndex); + m_persistentProxyIndexes.append(proxyIndex); + if (m_proxy->hasChildren(proxyIndex)) + storePersistent(proxyIndex); + } + } + + void storePersistent() + { + // This method is called from layoutAboutToBeChanged. Persistent indexes should be valid + foreach(const QModelIndex &idx, m_persistentProxyIndexes) + if (!idx.isValid()) { + qWarning("%s: persistentProxyIndexes contains invalid index", Q_FUNC_INFO); + ++storePersistentFailureCount; + } + + if (!m_proxy->persistent().isEmpty()) { + qWarning("%s: proxy should have no persistent indexes when storePersistent called", + Q_FUNC_INFO); + ++storePersistentFailureCount; + } + storePersistent(QModelIndex()); + if (m_proxy->persistent().isEmpty()) { + qWarning("%s: proxy should have persistent index after storePersistent called", + Q_FUNC_INFO); + ++storePersistentFailureCount; + } + } + + void checkPersistent() + { + for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) { + QModelIndex updatedProxy = m_persistentProxyIndexes.at(row); + QModelIndex updatedSource = m_persistentSourceIndexes.at(row); + } + for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) { + QModelIndex updatedProxy = m_persistentProxyIndexes.at(row); + QModelIndex updatedSource = m_persistentSourceIndexes.at(row); + if (m_proxy->mapToSource(updatedProxy) != updatedSource) { + qWarning("%s: check failed at row %d", Q_FUNC_INFO, row); + ++checkPersistentFailureCount; + } + } + m_persistentSourceIndexes.clear(); + m_persistentProxyIndexes.clear(); + } + +private: + AccessibleProxyModel *m_proxy; + QList m_persistentSourceIndexes; + QList m_persistentProxyIndexes; +public: + int storePersistentFailureCount; + int checkPersistentFailureCount; +}; + +void tst_ModelTest::moveSourceItems() +{ + DynamicTreeModel *model = new DynamicTreeModel(this); + AccessibleProxyModel *proxy = new AccessibleProxyModel(this); + proxy->setSourceModel(model); + + ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); + insertCommand->setStartRow(0); + insertCommand->setEndRow(2); + insertCommand->doCommand(); + + insertCommand = new ModelInsertCommand(model, this); + insertCommand->setAncestorRowNumbers(QList() << 1); + insertCommand->setStartRow(0); + insertCommand->setEndRow(2); + insertCommand->doCommand(); + + ObservingObject observer(proxy); + + ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this); + moveCommand->setStartRow(0); + moveCommand->setEndRow(0); + moveCommand->setDestAncestors(QList() << 1); + moveCommand->setDestRow(0); + moveCommand->doCommand(); + + QCOMPARE(observer.storePersistentFailureCount, 0); + QCOMPARE(observer.checkPersistentFailureCount, 0); +} + +void tst_ModelTest::testResetThroughProxy() +{ + DynamicTreeModel *model = new DynamicTreeModel(this); + + ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); + insertCommand->setStartRow(0); + insertCommand->setEndRow(2); + insertCommand->doCommand(); + + QPersistentModelIndex persistent = model->index(0, 0); + + AccessibleProxyModel *proxy = new AccessibleProxyModel(this); + proxy->setSourceModel(model); + + ObservingObject observer(proxy); + observer.storePersistent(); + + ModelResetCommand *resetCommand = new ModelResetCommand(model, this); + resetCommand->setNumCols(0); + resetCommand->doCommand(); + + QCOMPARE(observer.storePersistentFailureCount, 0); + QCOMPARE(observer.checkPersistentFailureCount, 0); +} + + +QTEST_MAIN(tst_ModelTest) +#include "tst_modeltest.moc" diff --git a/tests/auto/integrationtests/networkselftest/networkselftest.pro b/tests/auto/integrationtests/networkselftest/networkselftest.pro new file mode 100644 index 0000000000..4440dc6cfd --- /dev/null +++ b/tests/auto/integrationtests/networkselftest/networkselftest.pro @@ -0,0 +1,16 @@ +load(qttest_p4) + +SOURCES += tst_networkselftest.cpp +QT = core network + +wince*: { + addFiles.files = rfc3252.txt + addFiles.path = . + DEPLOYMENT += addFiles + DEFINES += SRCDIR=\\\"\\\" +} else:vxworks*: { + DEFINES += SRCDIR=\\\"\\\" +} else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +} + diff --git a/tests/auto/integrationtests/networkselftest/rfc3252.txt b/tests/auto/integrationtests/networkselftest/rfc3252.txt new file mode 100644 index 0000000000..b80c61bf0a --- /dev/null +++ b/tests/auto/integrationtests/networkselftest/rfc3252.txt @@ -0,0 +1,899 @@ + + + + + + +Network Working Group H. Kennedy +Request for Comments: 3252 Mimezine +Category: Informational 1 April 2002 + + + Binary Lexical Octet Ad-hoc Transport + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2002). All Rights Reserved. + +Abstract + + This document defines a reformulation of IP and two transport layer + protocols (TCP and UDP) as XML applications. + +1. Introduction + +1.1. Overview + + This document describes the Binary Lexical Octet Ad-hoc Transport + (BLOAT): a reformulation of a widely-deployed network-layer protocol + (IP [RFC791]), and two associated transport layer protocols (TCP + [RFC793] and UDP [RFC768]) as XML [XML] applications. It also + describes methods for transporting BLOAT over Ethernet and IEEE 802 + networks as well as encapsulating BLOAT in IP for gatewaying BLOAT + across the public Internet. + +1.2. Motivation + + The wild popularity of XML as a basis for application-level protocols + such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple + Object Access Protocol [SOAP], and Jabber [JABBER] prompted + investigation into the possibility of extending the use of XML in the + protocol stack. Using XML at both the transport and network layer in + addition to the application layer would provide for an amazing amount + of power and flexibility while removing dependencies on proprietary + and hard-to-understand binary protocols. This protocol unification + would also allow applications to use a single XML parser for all + aspects of their operation, eliminating developer time spent figuring + out the intricacies of each new protocol, and moving the hard work of + + + + +Kennedy Informational [Page 1] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + parsing to the XML toolset. The use of XML also mitigates concerns + over "network vs. host" byte ordering which is at the root of many + network application bugs. + +1.3. Relation to Existing Protocols + + The reformulations specified in this RFC follow as closely as + possible the spirit of the RFCs on which they are based, and so MAY + contain elements or attributes that would not be needed in a pure + reworking (e.g. length attributes, which are implicit in XML.) + + The layering of network and transport protocols are maintained in + this RFC despite the optimizations that could be made if the line + were somewhat blurred (i.e. merging TCP and IP into a single, larger + element in the DTD) in order to foster future use of this protocol as + a basis for reformulating other protocols (such as ICMP.) + + Other than the encoding, the behavioral aspects of each of the + existing protocols remain unchanged. Routing, address spaces, TCP + congestion control, etc. behave as specified in the extant standards. + Adapting to new standards and experimental algorithm heuristics for + improving performance will become much easier once the move to BLOAT + has been completed. + +1.4. Requirement Levels + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in BCP 14, RFC 2119 + [RFC2119]. + +2. IPoXML + + This protocol MUST be implemented to be compliant with this RFC. + IPoXML is the root protocol REQUIRED for effective use of TCPoXML + (section 3.) and higher-level application protocols. + + The DTD for this document type can be found in section 7.1. + + The routing of IPoXML can be easily implemented on hosts with an XML + parser, as the regular structure lends itself handily to parsing and + validation of the document/datagram and then processing the + destination address, TTL, and checksum before sending it on to its + next-hop. + + The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the + wider deployment of IPv4 and the fact that implementing IPv6 as XML + would have exceeded the 1500 byte Ethernet MTU. + + + +Kennedy Informational [Page 2] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + All BLOAT implementations MUST use - and specify - the UTF-8 encoding + of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well- + formed and include the XMLDecl. + +2.1. IP Description + + A number of items have changed (for the better) from the original IP + specification. Bit-masks, where present have been converted into + human-readable values. IP addresses are listed in their dotted- + decimal notation [RFC1123]. Length and checksum values are present + as decimal integers. + + To calculate the length and checksum fields of the IP element, a + canonicalized form of the element MUST be used. The canonical form + SHALL have no whitespace (including newline characters) between + elements and only one space character between attributes. There + SHALL NOT be a space following the last attribute in an element. + + An iterative method SHOULD be used to calculate checksums, as the + length field will vary based on the size of the checksum. + + The payload element bears special attention. Due to the character + set restrictions of XML, the payload of IP datagrams (which MAY + contain arbitrary data) MUST be encoded for transport. This RFC + REQUIRES the contents of the payload to be encoded in the base-64 + encoding of RFC 2045 [RFC2045], but removes the requirement that the + encoded output MUST be wrapped on 76-character lines. + + + + + + + + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 3] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + +2.2. Example Datagram + + The following is an example IPoXML datagram with an empty payload: + + + + +
+ + + + + + + + + + + + + + + +
+ + +
+ +3. TCPoXML + + This protocol MUST be implemented to be compliant with this RFC. The + DTD for this document type can be found in section 7.2. + +3.1. TCP Description + + A number of items have changed from the original TCP specification. + Bit-masks, where present have been converted into human-readable + values. Length and checksum and port values are present as decimal + integers. + + To calculate the length and checksum fields of the TCP element, a + canonicalized form of the element MUST be used as in section 2.1. + + An iterative method SHOULD be used to calculate checksums as in + section 2.1. + + The payload element MUST be encoded as in section 2.1. + + + +Kennedy Informational [Page 4] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + The TCP offset element was expanded to a maximum of 255 from 16 to + allow for the increased size of the header in XML. + + TCPoXML datagrams encapsulated by IPoXML MAY omit the header + as well as the declaration. + +3.2. Example Datagram + + The following is an example TCPoXML datagram with an empty payload: + + + + + + + + + + + + + + + + + + + + + + + + +4. UDPoXML + + This protocol MUST be implemented to be compliant with this RFC. The + DTD for this document type can be found in section 7.3. + +4.1. UDP Description + + A number of items have changed from the original UDP specification. + Bit-masks, where present have been converted into human-readable + values. Length and checksum and port values are present as decimal + integers. + + + + + + + +Kennedy Informational [Page 5] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + To calculate the length and checksum fields of the UDP element, a + canonicalized form of the element MUST be used as in section 2.1. An + iterative method SHOULD be used to calculate checksums as in section + 2.1. + + The payload element MUST be encoded as in section 2.1. + + UDPoXML datagrams encapsulated by IPoXML MAY omit the header + as well as the declaration. + +4.2. Example Datagram + + The following is an example UDPoXML datagram with an empty payload: + + + + + + + + + + + + + + +5. Network Transport + + This document provides for the transmission of BLOAT datagrams over + two common families of physical layer transport. Future RFCs will + address additional transports as routing vendors catch up to the + specification, and we begin to see BLOAT routed across the Internet + backbone. + +5.1. Ethernet + + BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the + exception that the type field of the Ethernet frame MUST contain the + value 0xBEEF. The first 5 octets of the Ethernet frame payload will + be 0x3c 3f 78 6d 6c (" + --> + + + + +Kennedy Informational [Page 7] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 9] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + + + + + + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 10] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + + + + + + + + + + + +7.2. TCPoXML DTD + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 11] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 12] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + + + + + + + + + + + + + + + + + + +7.3. UDPoXML DTD + + + + + + + + + + + + + + + +Kennedy Informational [Page 13] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + +8. Security Considerations + + XML, as a subset of SGML, has the same security considerations as + specified in SGML Media Types [RFC1874]. Security considerations + that apply to IP, TCP and UDP also likely apply to BLOAT as it does + not attempt to correct for issues not related to message format. + +9. References + + [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt, + February 2002. (Work in Progress) + + [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, + August 1980. + + [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791, + September 1981. + + [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC + 793, September 1981. + + [RFC894] Hornig, C., "Standard for the Transmission of IP + Datagrams over Ethernet Networks.", RFC 894, April 1984. + + [RFC1042] Postel, J. and J. Reynolds, "Standard for the + Transmission of IP Datagrams Over IEEE 802 Networks", STD + 43, RFC 1042, February 1988. + + [RFC1123] Braden, R., "Requirements for Internet Hosts - + Application and Support", RFC 1123, October 1989. + + [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December + 1995. + + [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003, + October 1996. + + [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message + Bodies", RFC 2045, November 1996. + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO + 10646", RFC 2279, January 1998. + + + + + +Kennedy Informational [Page 14] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + + [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6 + (IPv6) Specification", RFC 2460, December 1998. + + [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core", + RFC 3080, March 2001. + + [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A., + Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D., + "Simple Object Access Protocol (SOAP) 1.1" World Wide Web + Consortium Note, May 2000 http://www.w3.org/TR/SOAP/ + + [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible + Markup Language (XML)" World Wide Web Consortium + Recommendation REC- xml-19980210. + http://www.w3.org/TR/1998/REC-xml-19980210 + +10. Author's Address + + Hugh Kennedy + Mimezine + 1060 West Addison + Chicago, IL 60613 + USA + + EMail: kennedyh@engin.umich.edu + + + + + + + + + + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 15] + +RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 + + +11. Full Copyright Statement + + Copyright (C) The Internet Society (2002). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Kennedy Informational [Page 16] + diff --git a/tests/auto/integrationtests/networkselftest/tst_networkselftest.cpp b/tests/auto/integrationtests/networkselftest/tst_networkselftest.cpp new file mode 100644 index 0000000000..341054c533 --- /dev/null +++ b/tests/auto/integrationtests/networkselftest/tst_networkselftest.cpp @@ -0,0 +1,1029 @@ +/**************************************************************************** +** +** 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 +#include + +#include + +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif + +#include "../../network-settings.h" + +class tst_NetworkSelfTest: public QObject +{ + Q_OBJECT + QHostAddress cachedIpAddress; +public: + tst_NetworkSelfTest(); + virtual ~tst_NetworkSelfTest(); + + QHostAddress serverIpAddress(); + +private slots: + void initTestCase(); + void hostTest(); + void dnsResolution_data(); + void dnsResolution(); + void serverReachability(); + void remotePortsOpen_data(); + void remotePortsOpen(); + void fileLineEndingTest(); + + // specific protocol tests + void ftpServer(); + void ftpProxyServer(); + void imapServer(); + void httpServer(); + void httpServerFiles_data(); + void httpServerFiles(); + void httpServerCGI_data(); + void httpServerCGI(); +#ifndef QT_NO_OPENSSL + void httpsServer(); +#endif + void httpProxy(); + void httpProxyBasicAuth(); + void httpProxyNtlmAuth(); + void socks5Proxy(); + void socks5ProxyAuth(); + void smbServer(); + + // ssl supported test + void supportsSsl(); +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif +}; + +class Chat +{ +public: + enum Type { + Reconnect, + Send, + Expect, + SkipBytes, + DiscardUntil, + DiscardUntilDisconnect, + Disconnect, + RemoteDisconnect, + StartEncryption + }; + Chat(Type t, const QByteArray &d) + : data(d), type(t) + { + } + Chat(Type t, int val = 0) + : value(val), type(t) + { + } + + static inline Chat send(const QByteArray &data) + { return Chat(Send, data); } + static inline Chat expect(const QByteArray &data) + { return Chat(Expect, data); } + static inline Chat discardUntil(const QByteArray &data) + { return Chat(DiscardUntil, data); } + static inline Chat skipBytes(int count) + { return Chat(SkipBytes, count); } + + QByteArray data; + int value; + Type type; +}; + +static QString prettyByteArray(const QByteArray &array) +{ + // any control chars? + QString result; + result.reserve(array.length() + array.length() / 3); + for (int i = 0; i < array.length(); ++i) { + char c = array.at(i); + switch (c) { + case '\n': + result += "\\n"; + continue; + case '\r': + result += "\\r"; + continue; + case '\t': + result += "\\t"; + continue; + case '"': + result += "\\\""; + continue; + default: + break; + } + + if (c < 0x20 || uchar(c) >= 0x7f) { + result += '\\'; + result += QString::number(uchar(c), 8); + } else { + result += c; + } + } + return result; +} + +static bool doSocketRead(QTcpSocket *socket, int minBytesAvailable, int timeout = 4000) +{ + QElapsedTimer timer; + timer.start(); + forever { + if (socket->bytesAvailable() >= minBytesAvailable) + return true; + if (socket->state() == QAbstractSocket::UnconnectedState + || timer.elapsed() >= timeout) + return false; + if (!socket->waitForReadyRead(timeout - timer.elapsed())) + return false; + } +} + +static bool doSocketFlush(QTcpSocket *socket, int timeout = 4000) +{ +#ifndef QT_NO_OPENSSL + QSslSocket *sslSocket = qobject_cast(socket); +#endif + QTime timer; + timer.start(); + forever { + if (socket->bytesToWrite() == 0 +#ifndef QT_NO_OPENSSL + && sslSocket->encryptedBytesToWrite() == 0 +#endif + ) + return true; + if (socket->state() == QAbstractSocket::UnconnectedState + || timer.elapsed() >= timeout) + return false; + if (!socket->waitForBytesWritten(timeout - timer.elapsed())) + return false; + } +} + +static void netChat(int port, const QList &chat) +{ +#ifndef QT_NO_OPENSSL + QSslSocket socket; +#else + QTcpSocket socket; +#endif + + socket.connectToHost(QtNetworkSettings::serverName(), port); + qDebug() << 0 << "Connecting to server on port" << port; + QVERIFY2(socket.waitForConnected(10000), + QString("Failed to connect to server in step 0: %1").arg(socket.errorString()).toLocal8Bit()); + + // now start the chat + QList::ConstIterator it = chat.constBegin(); + for (int i = 1; it != chat.constEnd(); ++it, ++i) { + switch (it->type) { + case Chat::Expect: { + qDebug() << i << "Expecting" << prettyByteArray(it->data); + if (!doSocketRead(&socket, it->data.length())) + QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit()); + + // pop that many bytes off the socket + QByteArray received = socket.read(it->data.length()); + + // is it what we expected? + QVERIFY2(received == it->data, + QString("Did not receive expected data in step %1: data received was:\n%2") + .arg(i).arg(prettyByteArray(received)).toLocal8Bit()); + + break; + } + + case Chat::DiscardUntil: + qDebug() << i << "Discarding until" << prettyByteArray(it->data); + while (true) { + // scan the buffer until we have our string + if (!doSocketRead(&socket, it->data.length())) + QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit()); + + QByteArray buffer; + buffer.resize(socket.bytesAvailable()); + socket.peek(buffer.data(), socket.bytesAvailable()); + + int pos = buffer.indexOf(it->data); + if (pos == -1) { + // data not found, keep trying + continue; + } + + buffer = socket.read(pos + it->data.length()); + qDebug() << i << "Discarded" << prettyByteArray(buffer); + break; + } + break; + + case Chat::SkipBytes: { + qDebug() << i << "Skipping" << it->value << "bytes"; + if (!doSocketRead(&socket, it->value)) + QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit()); + + // now discard the bytes + QByteArray buffer = socket.read(it->value); + qDebug() << i << "Skipped" << prettyByteArray(buffer); + break; + } + + case Chat::Send: { + qDebug() << i << "Sending" << prettyByteArray(it->data); + socket.write(it->data); + if (!doSocketFlush(&socket)) { + QVERIFY2(socket.state() == QAbstractSocket::ConnectedState, + QString("Socket disconnected while sending data in step %1").arg(i).toLocal8Bit()); + QFAIL(QString("Failed to send data in step %1: timeout").arg(i).toLocal8Bit()); + } + break; + } + + case Chat::Disconnect: + qDebug() << i << "Disconnecting from host"; + socket.disconnectFromHost(); + + // is this the last command? + if (it + 1 != chat.constEnd()) + break; + + // fall through: + case Chat::RemoteDisconnect: + case Chat::DiscardUntilDisconnect: + qDebug() << i << "Waiting for remote disconnect"; + if (socket.state() != QAbstractSocket::UnconnectedState) + socket.waitForDisconnected(10000); + QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, + QString("Socket did not disconnect as expected in step %1").arg(i).toLocal8Bit()); + + // any data left? + if (it->type == Chat::DiscardUntilDisconnect) { + QByteArray buffer = socket.readAll(); + qDebug() << i << "Discarded in the process:" << prettyByteArray(buffer); + } + + if (socket.bytesAvailable() != 0) + QFAIL(QString("Unexpected bytes still on buffer when disconnecting in step %1:\n%2") + .arg(i).arg(prettyByteArray(socket.readAll())).toLocal8Bit()); + break; + + case Chat::Reconnect: + qDebug() << i << "Reconnecting to server on port" << port; + socket.connectToHost(QtNetworkSettings::serverName(), port); + QVERIFY2(socket.waitForConnected(10000), + QString("Failed to reconnect to server in step %1: %2").arg(i).arg(socket.errorString()).toLocal8Bit()); + break; + + case Chat::StartEncryption: +#ifdef QT_NO_OPENSSL + QFAIL("Internal error: SSL required for this test"); +#else + qDebug() << i << "Starting client encryption"; + socket.ignoreSslErrors(); + socket.startClientEncryption(); + QVERIFY2(socket.waitForEncrypted(5000), + QString("Failed to start client encryption in step %1: %2").arg(i) + .arg(socket.errorString()).toLocal8Bit()); + break; +#endif + } + } +} + +tst_NetworkSelfTest::tst_NetworkSelfTest() +{ +} + +tst_NetworkSelfTest::~tst_NetworkSelfTest() +{ +} + +QHostAddress tst_NetworkSelfTest::serverIpAddress() +{ + if (cachedIpAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { + // need resolving + QHostInfo resolved = QHostInfo::fromName(QtNetworkSettings::serverName()); + if(resolved.error() != QHostInfo::NoError || + resolved.addresses().isEmpty()) { + qWarning("QHostInfo::fromName failed (%d).", resolved.error()); + return QHostAddress(QHostAddress::Null); + } + cachedIpAddress = resolved.addresses().first(); + } + return cachedIpAddress; +} + +void tst_NetworkSelfTest::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif +} + +void tst_NetworkSelfTest::hostTest() +{ + // this is a localhost self-test + QHostInfo localhost = QHostInfo::fromName("localhost"); + QCOMPARE(localhost.error(), QHostInfo::NoError); + QVERIFY(!localhost.addresses().isEmpty()); + + QTcpServer server; + QVERIFY(server.listen()); + + QTcpSocket socket; + socket.connectToHost("127.0.0.1", server.serverPort()); + QVERIFY(socket.waitForConnected(10000)); +} + +void tst_NetworkSelfTest::dnsResolution_data() +{ + QTest::addColumn("hostName"); + QTest::newRow("local-name") << QtNetworkSettings::serverLocalName(); + QTest::newRow("fqdn") << QtNetworkSettings::serverName(); +} + +void tst_NetworkSelfTest::dnsResolution() +{ + QFETCH(QString, hostName); + QHostInfo resolved = QHostInfo::fromName(hostName); + QVERIFY2(resolved.error() == QHostInfo::NoError, + QString("Failed to resolve hostname %1: %2").arg(hostName, resolved.errorString()).toLocal8Bit()); + QVERIFY2(resolved.addresses().size() > 0, "Got 0 addresses for server IP"); + + cachedIpAddress = resolved.addresses().first(); +} + +void tst_NetworkSelfTest::serverReachability() +{ + // check that we get a proper error connecting to port 12346 + QTcpSocket socket; + socket.connectToHost(QtNetworkSettings::serverName(), 12346); + + QTime timer; + timer.start(); + socket.waitForConnected(10000); + QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong"); + + QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!"); + QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError, + QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit()); +} + +void tst_NetworkSelfTest::remotePortsOpen_data() +{ + QTest::addColumn("portNumber"); + QTest::newRow("echo") << 7; + QTest::newRow("daytime") << 13; + QTest::newRow("ftp") << 21; + QTest::newRow("ssh") << 22; + QTest::newRow("imap") << 143; + QTest::newRow("http") << 80; + QTest::newRow("https") << 443; + QTest::newRow("http-proxy") << 3128; + QTest::newRow("http-proxy-auth-basic") << 3129; + QTest::newRow("http-proxy-auth-ntlm") << 3130; + QTest::newRow("socks5-proxy") << 1080; + QTest::newRow("socks5-proxy-auth") << 1081; + QTest::newRow("ftp-proxy") << 2121; + QTest::newRow("smb") << 139; +} + +void tst_NetworkSelfTest::remotePortsOpen() +{ + QFETCH(int, portNumber); + QTcpSocket socket; + socket.connectToHost(QtNetworkSettings::serverName(), portNumber); + + if (!socket.waitForConnected(10000)) { + if (socket.error() == QAbstractSocket::SocketTimeoutError) + QFAIL(QString("Network timeout connecting to the server on port %1").arg(portNumber).toLocal8Bit()); + else + QFAIL(QString("Error connecting to server on port %1: %2").arg(portNumber).arg(socket.errorString()).toLocal8Bit()); + } + QVERIFY(socket.state() == QAbstractSocket::ConnectedState); +} + + +void tst_NetworkSelfTest::fileLineEndingTest() +{ + QString referenceName = SRCDIR "/rfc3252.txt"; + long long expectedReferenceSize = 25962; + + QString lineEndingType("LF"); + + QFile reference(referenceName); + QVERIFY(reference.open(QIODevice::ReadOnly)); + QByteArray byteLine = reference.readLine(); + if(byteLine.endsWith("\r\n")) + lineEndingType = "CRLF"; + else if(byteLine.endsWith("\r")) + lineEndingType = "CR"; + + QString referenceAsTextData; + QFile referenceAsText(referenceName); + QVERIFY(referenceAsText.open(QIODevice::ReadOnly)); + referenceAsTextData = referenceAsText.readAll(); + + QVERIFY2(expectedReferenceSize == referenceAsTextData.length(), QString("Reference file %1 has %2 as line ending and file size not matching - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit()); + QVERIFY2(!lineEndingType.compare("LF"), QString("Reference file %1 has %2 as line ending - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit()); +} + +static QList ftpChat(const QByteArray &userSuffix = QByteArray()) +{ + QList rv; + rv << Chat::expect("220") + << Chat::discardUntil("\r\n") + << Chat::send("USER anonymous" + userSuffix + "\r\n") + << Chat::expect("331") + << Chat::discardUntil("\r\n") + << Chat::send("PASS user@hostname\r\n") + << Chat::expect("230") + << Chat::discardUntil("\r\n") + + << Chat::send("CWD pub\r\n") + << Chat::expect("250") + << Chat::discardUntil("\r\n") + << Chat::send("CWD dir-not-readable\r\n") + << Chat::expect("550") + << Chat::discardUntil("\r\n") + << Chat::send("PWD\r\n") + << Chat::expect("257 \"/pub\"\r\n") + << Chat::send("SIZE file-not-readable.txt\r\n") + << Chat::expect("213 41\r\n") + << Chat::send("CWD qxmlquery\r\n") + << Chat::expect("250") + << Chat::discardUntil("\r\n") + + << Chat::send("CWD /qtest\r\n") + << Chat::expect("250") + << Chat::discardUntil("\r\n") + << Chat::send("SIZE bigfile\r\n") + << Chat::expect("213 519240\r\n") + << Chat::send("SIZE rfc3252\r\n") + << Chat::expect("213 25962\r\n") + << Chat::send("SIZE rfc3252.txt\r\n") + << Chat::expect("213 25962\r\n") +// << Chat::send("SIZE nonASCII/german_\344\366\374\304\326\334\337\r\n") +// << Chat::expect("213 40\r\n") + + << Chat::send("QUIT\r\n"); + rv << Chat::expect("221") + << Chat::discardUntil("\r\n"); + + rv << Chat::RemoteDisconnect; + return rv; +} + +void tst_NetworkSelfTest::ftpServer() +{ + netChat(21, ftpChat()); +} + +void tst_NetworkSelfTest::ftpProxyServer() +{ + netChat(2121, ftpChat("@" + QtNetworkSettings::serverName().toLatin1())); +} + +void tst_NetworkSelfTest::imapServer() +{ + netChat(143, QList() + << Chat::expect("* OK ") + << Chat::discardUntil("\r\n") + << Chat::send("1 CAPABILITY\r\n") + << Chat::expect("* CAPABILITY ") + << Chat::discardUntil("1 OK") + << Chat::discardUntil("\r\n") + << Chat::send("2 LOGOUT\r\n") + << Chat::discardUntil("2 OK") + << Chat::discardUntil("\r\n") + << Chat::RemoteDisconnect); +} + +void tst_NetworkSelfTest::httpServer() +{ + QString uniqueExtension; + qsrand(time(0)); +#ifndef Q_OS_WINCE + uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(qrand()).arg((qulonglong)time(0)); +#else + uniqueExtension = QString("%1%2").arg((qulonglong)this).arg(qrand()); +#endif + + netChat(80, QList() + // HTTP/0.9 chat: + << Chat::send("GET /\r\n") + << Chat::DiscardUntilDisconnect + + // HTTP/1.0 chat: + << Chat::Reconnect + << Chat::send("GET / HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // HTTP/1.0 POST: + << Chat::Reconnect + << Chat::send("POST / HTTP/1.0\r\n" + "Content-Length: 5\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n" + "Hello") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // HTTP protected area + << Chat::Reconnect + << Chat::send("GET /qtest/protected/rfc3252.txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("401 ") + << Chat::DiscardUntilDisconnect + + << Chat::Reconnect + << Chat::send("HEAD /qtest/protected/rfc3252.txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // DAV area + << Chat::Reconnect + << Chat::send("HEAD /dav/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // HTTP/1.0 PUT + << Chat::Reconnect + << Chat::send("PUT /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" + "Content-Length: 5\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n" + "Hello") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("201 ") + << Chat::DiscardUntilDisconnect + + // check that the file did get uploaded + << Chat::Reconnect + << Chat::send("HEAD /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::discardUntil("\r\nContent-Length: 5\r\n") + << Chat::DiscardUntilDisconnect + + // HTTP/1.0 DELETE + << Chat::Reconnect + << Chat::send("DELETE /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("204 ") + << Chat::DiscardUntilDisconnect + ); +} + +void tst_NetworkSelfTest::httpServerFiles_data() +{ + QTest::addColumn("uri"); + QTest::addColumn("size"); + + QTest::newRow("fluke.gif") << "/qtest/fluke.gif" << -1; + QTest::newRow("bigfile") << "/qtest/bigfile" << 519240; + QTest::newRow("rfc3252.txt") << "/qtest/rfc3252.txt" << 25962; + QTest::newRow("protected/rfc3252.txt") << "/qtest/protected/rfc3252.txt" << 25962; + QTest::newRow("completelyEmptyQuery.xq") << "/qtest/qxmlquery/completelyEmptyQuery.xq" << -1; + QTest::newRow("notWellformedViaHttps.xml") << "/qtest/qxmlquery/notWellformedViaHttps.xml" << -1; + QTest::newRow("notWellformed.xml") << "/qtest/qxmlquery/notWellformed.xml" << -1; + QTest::newRow("viaHttp.xq") << "/qtest/qxmlquery/viaHttp.xq" << -1; + QTest::newRow("wellFormedViaHttps.xml") << "/qtest/qxmlquery/wellFormedViaHttps.xml" << -1; + QTest::newRow("wellFormed.xml") << "/qtest/qxmlquery/wellFormed.xml" << -1; +} + +void tst_NetworkSelfTest::httpServerFiles() +{ + QFETCH(QString, uri); + QFETCH(int, size); + + QList chat; + chat << Chat::send("HEAD " + QUrl::toPercentEncoding(uri, "/") + " HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::skipBytes(1) // HTTP/1.0 or 1.1 reply + << Chat::expect(" 200 "); + if (size != -1) + chat << Chat::discardUntil("\r\nContent-Length: " + QByteArray::number(size) + "\r\n"); + chat << Chat::DiscardUntilDisconnect; + netChat(80, chat); +} + +void tst_NetworkSelfTest::httpServerCGI_data() +{ + QTest::addColumn("request"); + QTest::addColumn("result"); + QTest::addColumn("additionalHeader"); + + QTest::newRow("echo.cgi") + << QByteArray("GET /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n" + "Connection: close\r\n" + "\r\n") + << QByteArray("Hello+World") + << QByteArray(); + + QTest::newRow("echo.cgi(POST)") + << QByteArray("POST /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n" + "Connection: close\r\n" + "Content-Length: 15\r\n" + "\r\n" + "Hello, World!\r\n") + << QByteArray("Hello, World!\r\n") + << QByteArray(); + + QTest::newRow("md5sum.cgi") + << QByteArray("POST /qtest/cgi-bin/md5sum.cgi HTTP/1.0\r\n" + "Connection: close\r\n" + "Content-Length: 15\r\n" + "\r\n" + "Hello, World!\r\n") + << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n") + << QByteArray(); + + QTest::newRow("protected/md5sum.cgi") + << QByteArray("POST /qtest/protected/cgi-bin/md5sum.cgi HTTP/1.0\r\n" + "Connection: close\r\n" + "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "Content-Length: 15\r\n" + "\r\n" + "Hello, World!\r\n") + << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n") + << QByteArray(); + + QTest::newRow("set-cookie.cgi") + << QByteArray("POST /qtest/cgi-bin/set-cookie.cgi HTTP/1.0\r\n" + "Connection: close\r\n" + "Content-Length: 8\r\n" + "\r\n" + "foo=bar\n") + << QByteArray("Success\n") + << QByteArray("\r\nSet-Cookie: foo=bar\r\n"); +} + +void tst_NetworkSelfTest::httpServerCGI() +{ + QFETCH(QByteArray, request); + QFETCH(QByteArray, result); + QFETCH(QByteArray, additionalHeader); + QList chat; + chat << Chat::send(request) + << Chat::expect("HTTP/1.") << Chat::skipBytes(1) + << Chat::expect(" 200 "); + + if (!additionalHeader.isEmpty()) + chat << Chat::discardUntil(additionalHeader); + + chat << Chat::discardUntil("\r\n\r\n") + << Chat::expect(result) + << Chat::RemoteDisconnect; + netChat(80, chat); +} + +#ifndef QT_NO_OPENSSL +void tst_NetworkSelfTest::httpsServer() +{ + netChat(443, QList() + << Chat::StartEncryption + << Chat::send("GET / HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect); +} +#endif + +void tst_NetworkSelfTest::httpProxy() +{ + netChat(3128, QList() + // proxy GET by IP + << Chat::send("GET http://" + serverIpAddress().toString().toLatin1() + "/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Proxy-connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // proxy GET by hostname + << Chat::Reconnect + << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Proxy-connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect + + // proxy CONNECT by IP + << Chat::Reconnect + << Chat::send("CONNECT " + serverIpAddress().toString().toLatin1() + ":21 HTTP/1.0\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::discardUntil("\r\n\r\n") + << ftpChat() + + // proxy CONNECT by hostname + << Chat::Reconnect + << Chat::send("CONNECT " + QtNetworkSettings::serverName().toLatin1() + ":21 HTTP/1.0\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::discardUntil("\r\n\r\n") + << ftpChat() + ); +} + +void tst_NetworkSelfTest::httpProxyBasicAuth() +{ + netChat(3129, QList() + // test auth required response + << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Proxy-connection: close\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("407 ") + << Chat::discardUntil("\r\nProxy-Authenticate: Basic realm=\"") + << Chat::DiscardUntilDisconnect + + // now try sending our credentials + << Chat::Reconnect + << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Proxy-connection: close\r\n" + "Proxy-Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("200 ") + << Chat::DiscardUntilDisconnect); +} + +void tst_NetworkSelfTest::httpProxyNtlmAuth() +{ + netChat(3130, QList() + // test auth required response + << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" + "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" + "Proxy-connection: keep-alive\r\n" // NTLM auth will disconnect + "\r\n") + << Chat::expect("HTTP/1.") + << Chat::discardUntil(" ") + << Chat::expect("407 ") + << Chat::discardUntil("\r\nProxy-Authenticate: NTLM\r\n") + << Chat::DiscardUntilDisconnect + ); +} + +// SOCKSv5 is a binary protocol +static const char handshakeNoAuth[] = "\5\1\0"; +static const char handshakeOkNoAuth[] = "\5\0"; +static const char handshakeAuthPassword[] = "\5\1\2\1\12qsockstest\10password"; +static const char handshakeOkPasswdAuth[] = "\5\2\1\0"; +static const char handshakeAuthNotOk[] = "\5\377"; +static const char connect1[] = "\5\1\0\1\177\0\0\1\0\25"; // Connect IPv4 127.0.0.1 port 21 +static const char connect1a[] = "\5\1\0\1"; // just "Connect to IPv4" +static const char connect1b[] = "\0\25"; // just "port 21" +static const char connect2[] = "\5\1\0\3\11localhost\0\25"; // Connect hostname localhost 21 +static const char connect2a[] = "\5\1\0\3"; // just "Connect to hostname" +static const char connected[] = "\5\0\0"; + +#define QBA(x) (QByteArray::fromRawData(x, -1 + sizeof(x))) + +void tst_NetworkSelfTest::socks5Proxy() +{ + union { + char buf[4]; + quint32 data; + } ip4Address; + ip4Address.data = qToBigEndian(serverIpAddress().toIPv4Address()); + + netChat(1080, QList() + // IP address connection + << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) + << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) + << Chat::send(QByteArray(connect1, -1 + sizeof connect1)) + << Chat::expect(QByteArray(connected, -1 + sizeof connected)) + << Chat::expect("\1") // IPv4 address following + << Chat::skipBytes(6) // the server's local address and port + << ftpChat() + + // connect by IP + << Chat::Reconnect + << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) + << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) + << Chat::send(QBA(connect1a) + QByteArray::fromRawData(ip4Address.buf, 4) + QBA(connect1b)) + << Chat::expect(QByteArray(connected, -1 + sizeof connected)) + << Chat::expect("\1") // IPv4 address following + << Chat::skipBytes(6) // the server's local address and port + << ftpChat() + + // connect to "localhost" by hostname + << Chat::Reconnect + << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) + << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) + << Chat::send(QByteArray(connect2, -1 + sizeof connect2)) + << Chat::expect(QByteArray(connected, -1 + sizeof connected)) + << Chat::expect("\1") // IPv4 address following + << Chat::skipBytes(6) // the server's local address and port + << ftpChat() + + // connect to server by its official name + << Chat::Reconnect + << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) + << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) + << Chat::send(QBA(connect2a) + char(QtNetworkSettings::serverName().size()) + QtNetworkSettings::serverName().toLatin1() + QBA(connect1b)) + << Chat::expect(QByteArray(connected, -1 + sizeof connected)) + << Chat::expect("\1") // IPv4 address following + << Chat::skipBytes(6) // the server's local address and port + << ftpChat() + ); +} + +void tst_NetworkSelfTest::socks5ProxyAuth() +{ + netChat(1081, QList() + // unauthenticated connect -- will get error + << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) + << Chat::expect(QByteArray(handshakeAuthNotOk, -1 + sizeof handshakeAuthNotOk)) + << Chat::RemoteDisconnect + + // now try to connect with authentication + << Chat::Reconnect + << Chat::send(QByteArray(handshakeAuthPassword, -1 + sizeof handshakeAuthPassword)) + << Chat::expect(QByteArray(handshakeOkPasswdAuth, -1 + sizeof handshakeOkPasswdAuth)) + << Chat::send(QByteArray(connect1, -1 + sizeof connect1)) + << Chat::expect(QByteArray(connected, -1 + sizeof connected)) + << Chat::expect("\1") // IPv4 address following + << Chat::skipBytes(6) // the server's local address and port + << ftpChat() + ); +} + +void tst_NetworkSelfTest::supportsSsl() +{ +#ifdef QT_NO_OPENSSL + QFAIL("SSL not compiled in"); +#else + QVERIFY2(QSslSocket::supportsSsl(), "Could not load SSL libraries"); +#endif +} + +void tst_NetworkSelfTest::smbServer() +{ + static const char contents[] = "This is 34 bytes. Do not change..."; +#ifdef Q_OS_WIN + // use Windows's native UNC support to try and open a file on the server + QString filepath = QString("\\\\%1\\testshare\\test.pri").arg(QtNetworkSettings::winServerName()); + FILE *f = fopen(filepath.toLatin1(), "rb"); + QVERIFY2(f, qt_error_string().toLocal8Bit()); + + char buf[128]; + size_t ret = fread(buf, 1, sizeof buf, f); + fclose(f); + + QCOMPARE(ret, strlen(contents)); + QVERIFY(memcmp(buf, contents, strlen(contents)) == 0); +#else + // try to use Samba + QString progname = "smbclient"; + QProcess smbclient; + smbclient.start(progname, QIODevice::ReadOnly); + if (!smbclient.waitForStarted(2000)) + QSKIP("Could not find smbclient (from Samba), cannot continue testing", SkipAll); + if (!smbclient.waitForFinished(2000) || smbclient.exitStatus() != QProcess::NormalExit) + QSKIP("smbclient isn't working, cannot continue testing", SkipAll); + smbclient.close(); + + // try listing the server + smbclient.start(progname, QStringList() << "-g" << "-N" << "-L" << QtNetworkSettings::winServerName(), QIODevice::ReadOnly); + QVERIFY(smbclient.waitForFinished(5000)); + if (smbclient.exitStatus() != QProcess::NormalExit) + QSKIP("smbclient crashed", SkipAll); + QVERIFY2(smbclient.exitCode() == 0, "Test server not found"); + + QByteArray output = smbclient.readAll(); + QVERIFY(output.contains("Disk|testshare|")); + QVERIFY(output.contains("Disk|testsharewritable|")); + QVERIFY(output.contains("Disk|testsharelargefile|")); + qDebug() << "Test server found and shares are correct"; + + // try getting a file + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("PAGER", "/bin/cat"); // just in case + smbclient.setProcessEnvironment(env); + smbclient.start(progname, QStringList() << "-N" << "-c" << "more test.pri" + << QString("\\\\%1\\testshare").arg(QtNetworkSettings::winServerName()), QIODevice::ReadOnly); + QVERIFY(smbclient.waitForFinished(5000)); + if (smbclient.exitStatus() != QProcess::NormalExit) + QSKIP("smbclient crashed", SkipAll); + QVERIFY2(smbclient.exitCode() == 0, "File //qt-test-server/testshare/test.pri not found"); + + output = smbclient.readAll(); + QCOMPARE(output.constData(), contents); + qDebug() << "Test file is correct"; +#endif +} + +QTEST_MAIN(tst_NetworkSelfTest) +#include "tst_networkselftest.moc" diff --git a/tests/auto/integrationtests/qaccessibility/.gitignore b/tests/auto/integrationtests/qaccessibility/.gitignore new file mode 100644 index 0000000000..6fd6ae2d48 --- /dev/null +++ b/tests/auto/integrationtests/qaccessibility/.gitignore @@ -0,0 +1 @@ +tst_qaccessibility diff --git a/tests/auto/integrationtests/qaccessibility/qaccessibility.pro b/tests/auto/integrationtests/qaccessibility/qaccessibility.pro new file mode 100644 index 0000000000..ae046cc3c3 --- /dev/null +++ b/tests/auto/integrationtests/qaccessibility/qaccessibility.pro @@ -0,0 +1,12 @@ +load(qttest_p4) +requires(contains(QT_CONFIG,accessibility)) +QT += widgets +SOURCES += tst_qaccessibility.cpp + +unix:!mac:LIBS+=-lm + +wince*: { + accessneeded.files = $$QT_BUILD_TREE\\plugins\\accessible\\*.dll + accessneeded.path = accessible + DEPLOYMENT += accessneeded +} diff --git a/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp b/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp new file mode 100644 index 0000000000..e1bd968534 --- /dev/null +++ b/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp @@ -0,0 +1,3372 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include + +#if defined(Q_OS_WIN) && defined(interface) +# undef interface +#endif + + +#include "QtTest/qtestaccessible.h" + +#if defined(Q_OS_WINCE) +extern "C" bool SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); +#define SPI_GETPLATFORMTYPE 257 +inline bool IsValidCEPlatform() { + wchar_t tszPlatform[64]; + if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(*tszPlatform), tszPlatform, 0)) { + QString platform = QString::fromWCharArray(tszPlatform); + if ((platform == QLatin1String("PocketPC")) || (platform == QLatin1String("Smartphone"))) + return false; + } + return true; +} +#endif + +static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface, + int index, const QRect &domain) +{ + if (!child) { + qWarning("tst_QAccessibility::verifyChild: null pointer to child."); + return false; + } + + if (!interface) { + qWarning("tst_QAccessibility::verifyChild: null pointer to interface."); + return false; + } + + // Verify that we get a valid QAccessibleInterface for the child. + QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(child); + if (!childInterface) { + qWarning("tst_QAccessibility::verifyChild: Failed to retrieve interface for child."); + return false; + } + + // QAccessibleInterface::indexOfChild(): + // Verify that indexOfChild() returns an index equal to the index passed in + int indexFromIndexOfChild = interface->indexOfChild(childInterface); + delete childInterface; + if (indexFromIndexOfChild != index) { + qWarning("tst_QAccessibility::verifyChild (indexOfChild()):"); + qWarning() << "Expected:" << index; + qWarning() << "Actual: " << indexFromIndexOfChild; + return false; + } + + // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child). + QAccessibleInterface *navigatedChildInterface = interface->child(index - 1); + if (navigatedChildInterface == 0) + return false; + + const QRect rectFromInterface = navigatedChildInterface->rect(); + delete navigatedChildInterface; + + // QAccessibleInterface::childAt(): + // Calculate global child position and check that the interface + // returns the correct index for that position. + QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0)); + int indexFromChildAt = interface->childAt(globalChildPos.x(), globalChildPos.y()); + if (indexFromChildAt != index) { + qWarning("tst_QAccessibility::verifyChild (childAt()):"); + qWarning() << "Expected:" << index; + qWarning() << "Actual: " << indexFromChildAt; + return false; + } + + // QAccessibleInterface::rect(): + // Calculate global child geometry and check that the interface + // returns a QRect which is equal to the calculated QRect. + const QRect expectedGlobalRect = QRect(globalChildPos, child->size()); + if (expectedGlobalRect != rectFromInterface) { + qWarning("tst_QAccessibility::verifyChild (rect()):"); + qWarning() << "Expected:" << expectedGlobalRect; + qWarning() << "Actual: " << rectFromInterface; + return false; + } + + // Verify that the child is within its domain. + if (!domain.contains(rectFromInterface)) { + qWarning("tst_QAccessibility::verifyChild: Child is not within its domain."); + return false; + } + + return true; +} + +static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget) +{ + if (!parentInterface || !childWidget) + return -1; + QAccessibleInterface *childInterface = QAccessibleInterface::queryAccessibleInterface(childWidget); + if (!childInterface) + return -1; + int index = parentInterface->indexOfChild(childInterface); + delete childInterface; + return index; +} + +#define EXPECT(cond) \ + do { \ + if (!errorAt && !(cond)) { \ + errorAt = __LINE__; \ + qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \ + } \ + } while (0) + +static int verifyHierarchy(QAccessibleInterface *iface) +{ + int errorAt = 0; + static int treelevel = 0; // for error diagnostics + QAccessibleInterface *middleChild, *if2; + middleChild = 0; + ++treelevel; + int middle = iface->childCount()/2 + 1; + if (iface->childCount() >= 2) { + middleChild = iface->child(middle - 1); + } + for (int i = 0; i < iface->childCount() && !errorAt; ++i) { + if2 = iface->child(i); + EXPECT(if2 != 0); + // navigate Ancestor... + QAccessibleInterface *parent = 0; + parent = if2->parent(); + EXPECT(iface->object() == parent->object()); + delete parent; + + // navigate Sibling... +// if (middleChild) { +// entry = if2->navigate(QAccessible::Sibling, middle, &if3); +// EXPECT(entry == 0 && if3->object() == middleChild->object()); +// if (entry == 0) +// delete if3; +// EXPECT(iface->indexOfChild(middleChild) == middle); +// } + + // verify children... + if (!errorAt) + errorAt = verifyHierarchy(if2); + delete if2; + } + delete middleChild; + + --treelevel; + return errorAt; +} + + +//TESTED_FILES= + +class tst_QAccessibility : public QObject +{ + Q_OBJECT +public: + tst_QAccessibility(); + virtual ~tst_QAccessibility(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); +private slots: + void eventTest(); + void customWidget(); + void deletedWidget(); + + void navigateGeometric(); + void navigateHierarchy(); + void sliderTest(); + void navigateCovered(); + void textAttributes(); + void hideShowTest(); + + void actionTest(); + + void applicationTest(); + void mainWindowTest(); + void buttonTest(); + void scrollBarTest(); + void tabTest(); + void tabWidgetTest(); + void menuTest(); + void spinBoxTest(); + void doubleSpinBoxTest(); + void textEditTest(); + void textBrowserTest(); + void mdiAreaTest(); + void mdiSubWindowTest(); + void lineEditTest(); + void workspaceTest(); + void dialogButtonBoxTest(); + void dialTest(); + void rubberBandTest(); + void abstractScrollAreaTest(); + void scrollAreaTest(); + + // Accessible table1 interface is no longer supported on X11, + // where it has been replaced by table2 interface. +#ifndef Q_OS_UNIX + void listViewTest(); + void treeWidgetTest(); + void tableWidgetTest(); + void tableViewTest(); +#else + void table2ListTest(); + void table2TreeTest(); + void table2TableTest(); +#endif + + void calendarWidgetTest(); + void dockWidgetTest(); + void comboBoxTest(); + void accessibleName(); + void labelTest(); + void accelerators(); +}; + +const double Q_PI = 3.14159265358979323846; + +QString eventName(const int ev) +{ + switch(ev) { + case 0x0001: return "SoundPlayed"; + case 0x0002: return "Alert"; + case 0x0003: return "ForegroundChanged"; + case 0x0004: return "MenuStart"; + case 0x0005: return "MenuEnd"; + case 0x0006: return "PopupMenuStart"; + case 0x0007: return "PopupMenuEnd"; + case 0x000C: return "ContextHelpStart"; + case 0x000D: return "ContextHelpEnd"; + case 0x000E: return "DragDropStart"; + case 0x000F: return "DragDropEnd"; + case 0x0010: return "DialogStart"; + case 0x0011: return "DialogEnd"; + case 0x0012: return "ScrollingStart"; + case 0x0013: return "ScrollingEnd"; + case 0x0018: return "MenuCommand"; + + case 0x0116: return "TableModelChanged"; + case 0x011B: return "TextCaretMoved"; + + case 0x8000: return "ObjectCreated"; + case 0x8001: return "ObjectDestroyed"; + case 0x8002: return "ObjectShow"; + case 0x8003: return "ObjectHide"; + case 0x8004: return "ObjectReorder"; + case 0x8005: return "Focus"; + case 0x8006: return "Selection"; + case 0x8007: return "SelectionAdd"; + case 0x8008: return "SelectionRemove"; + case 0x8009: return "SelectionWithin"; + case 0x800A: return "StateChanged"; + case 0x800B: return "LocationChanged"; + case 0x800C: return "NameChanged"; + case 0x800D: return "DescriptionChanged"; + case 0x800E: return "ValueChanged"; + case 0x800F: return "ParentChanged"; + case 0x80A0: return "HelpChanged"; + case 0x80B0: return "DefaultActionChanged"; + case 0x80C0: return "AcceleratorChanged"; + default: return "Unknown Event"; + } +} + +QAccessible::State state(QWidget * const widget) +{ + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); + if (!iface) + qWarning() << "Cannot get QAccessibleInterface for widget"; + QAccessible::State state = (iface ? iface->state() : static_cast(0)); + delete iface; + return state; +} + +class QtTestAccessibleWidget: public QWidget +{ + Q_OBJECT +public: + QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent) + { + setObjectName(name); + QPalette pal; + pal.setColor(backgroundRole(), Qt::black);//black is beautiful + setPalette(pal); + setFixedSize(5, 5); + } +}; + +class QtTestAccessibleWidgetIface: public QAccessibleWidget +{ +public: + QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {} + QString text(Text t, int control = 0) const + { + if (t == Help) + return QString::fromLatin1("Help yourself"); + return QAccessibleWidget::text(t, control); + } + static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o) + { + if (key == "QtTestAccessibleWidget") + return new QtTestAccessibleWidgetIface(static_cast(o)); + return 0; + } +}; + +tst_QAccessibility::tst_QAccessibility() +{ +} + +tst_QAccessibility::~tst_QAccessibility() +{ +} + +void tst_QAccessibility::initTestCase() +{ + QTestAccessibility::initialize(); + QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory); +} + +void tst_QAccessibility::cleanupTestCase() +{ + QTestAccessibility::cleanup(); +} + +void tst_QAccessibility::init() +{ + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::cleanup() +{ + const EventList list = QTestAccessibility::events(); + if (!list.isEmpty()) { + qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(), + QString(QTest::currentTestFunction()).toAscii().constData()); + for (int i = 0; i < list.count(); ++i) + qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object, + eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child); + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::eventTest() +{ + QPushButton* button = new QPushButton(0); + button->setObjectName(QString("Olaf")); + + button->show(); + QVERIFY_EVENT(button, 0, QAccessible::ObjectShow); + button->setFocus(Qt::MouseFocusReason); + QTestAccessibility::clearEvents(); + QTest::mouseClick(button, Qt::LeftButton, 0); + QVERIFY_EVENT(button, 0, QAccessible::StateChanged); + QVERIFY_EVENT(button, 0, QAccessible::StateChanged); + + button->setAccessibleName("Olaf the second"); + QVERIFY_EVENT(button, 0, QAccessible::NameChanged); + button->setAccessibleDescription("This is a button labeled Olaf"); + QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged); + + button->hide(); + QVERIFY_EVENT(button, 0, QAccessible::ObjectHide); + + delete button; +} + +void tst_QAccessibility::customWidget() +{ + QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz"); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + QCOMPARE(iface->object(), (QObject*)widget); + QCOMPARE(iface->object()->objectName(), QString("Heinz")); + QCOMPARE(iface->text(QAccessible::Help, 0), QString("Help yourself")); + + delete iface; + delete widget; +} + +void tst_QAccessibility::deletedWidget() +{ + QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf"); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + QCOMPARE(iface->object(), (QObject*)widget); + + delete widget; + widget = 0; + QVERIFY(!iface->isValid()); + delete iface; +} + +void tst_QAccessibility::navigateGeometric() +{ + { + static const int skip = 20; //speed the test up significantly + static const double step = Q_PI / 180; + QWidget *w = new QWidget(0); + w->setObjectName(QString("Josef")); + w->setFixedSize(400, 400); + + // center widget + QtTestAccessibleWidget *center = new QtTestAccessibleWidget(w, "Sol"); + center->move(200, 200); + + // arrange 360 widgets around it in a circle + QtTestAccessibleWidget *aw = 0; + for (int i = 0; i < 360; i += skip) { + aw = new QtTestAccessibleWidget(w, QString::number(i).toLatin1()); + aw->move( int(200.0 + 100.0 * sin(step * (double)i)), int(200.0 + 100.0 * cos(step * (double)i)) ); + } + + aw = new QtTestAccessibleWidget(w, "Earth"); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(center); + QAccessibleInterface *target = 0; + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + + w->show(); + QCoreApplication::processEvents(); + QTest::qWait(100); + + // let one widget rotate around center + for (int i = 0; i < 360; i+=skip) { + aw->move( int(200.0 + 75.0 * sin(step * (double)i)), int(200.0 + 75.0 * cos(step * (double)i)) ); + + if (i < 45 || i > 315) { + QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0); + } else if ( i < 135 ) { + QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0); + } else if ( i < 225 ) { + QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0); + } else { + QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0); + } + + QVERIFY(target); + QVERIFY(target->isValid()); + QVERIFY(target->object()); + QCOMPARE(target->object()->objectName(), aw->objectName()); + delete target; target = 0; + } + + // test invisible widget + target = QAccessible::queryAccessibleInterface(aw); + QVERIFY(!(target->state() & QAccessible::Invisible)); + aw->hide(); + QVERIFY(target->state() & QAccessible::Invisible); + delete target; target = 0; + + aw->move(center->x() + 10, center->y()); + QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0); + QVERIFY(target); + QVERIFY(target->isValid()); + QVERIFY(target->object()); + QVERIFY(QString(target->object()->objectName()) != "Earth"); + delete target; target = 0; + + aw->move(center->x() - 10, center->y()); + QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0); + QVERIFY(target); + QVERIFY(target->isValid()); + QVERIFY(target->object()); + QVERIFY(QString(target->object()->objectName()) != "Earth"); + delete target; target = 0; + + aw->move(center->x(), center->y() + 10); + QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0); + QVERIFY(target); + QVERIFY(target->isValid()); + QVERIFY(target->object()); + QVERIFY(QString(target->object()->objectName()) != "Earth"); + delete target; target = 0; + + aw->move(center->x(), center->y() - 10); + QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0); + QVERIFY(target); + QVERIFY(target->isValid()); + QVERIFY(target->object()); + QVERIFY(QString(target->object()->objectName()) != "Earth"); + delete target; target = 0; + + delete iface; + delete w; + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::sliderTest() +{ + { + QSlider *slider = new QSlider(0); + slider->setObjectName(QString("Slidy")); + slider->show(); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + + QCOMPARE(iface->childCount(), 0); + QCOMPARE(iface->role(), QAccessible::Slider); + + QAccessibleValueInterface *valueIface = iface->valueInterface(); + QVERIFY(valueIface != 0); + QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum()); + QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum()); + slider->setValue(50); + QCOMPARE(valueIface->currentValue().toInt(), slider->value()); + slider->setValue(0); + QCOMPARE(valueIface->currentValue().toInt(), slider->value()); + slider->setValue(100); + QCOMPARE(valueIface->currentValue().toInt(), slider->value()); + valueIface->setCurrentValue(77); + QCOMPARE(77, slider->value()); + + delete iface; + delete slider; + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::navigateCovered() +{ + { + QWidget *w = new QWidget(0); + w->setObjectName(QString("Harry")); + QWidget *w1 = new QWidget(w); + w1->setObjectName(QString("1")); + QWidget *w2 = new QWidget(w); + w2->setObjectName(QString("2")); + w->show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + + w->setFixedSize(6, 6); + w1->setFixedSize(5, 5); + w2->setFixedSize(5, 5); + w2->move(0, 0); + w1->raise(); + + QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1); + QVERIFY(iface1 != 0); + QVERIFY(iface1->isValid()); + QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2); + QVERIFY(iface2 != 0); + QVERIFY(iface2->isValid()); + QAccessibleInterface *iface3 = 0; + + QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1); + QVERIFY(iface3 == 0); + QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1); + QVERIFY(iface3 == 0); + QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1); + QVERIFY(iface3 == 0); + + for (int loop = 0; loop < 2; ++loop) { + for (int x = 0; x < w->width(); ++x) { + for (int y = 0; y < w->height(); ++y) { + w1->move(x, y); + if (w1->geometry().intersects(w2->geometry())) { + QVERIFY(iface1->relationTo(0, iface2, 0) & QAccessible::Covers); + QVERIFY(iface2->relationTo(0, iface1, 0) & QAccessible::Covered); + QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0); + QVERIFY(iface3 != 0); + QVERIFY(iface3->isValid()); + QCOMPARE(iface3->object(), iface2->object()); + delete iface3; iface3 = 0; + QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0); + QVERIFY(iface3 != 0); + QVERIFY(iface3->isValid()); + QCOMPARE(iface3->object(), iface1->object()); + delete iface3; iface3 = 0; + } else { + QVERIFY(!(iface1->relationTo(0, iface2, 0) & QAccessible::Covers)); + QVERIFY(!(iface2->relationTo(0, iface1, 0) & QAccessible::Covered)); + QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1); + QVERIFY(iface3 == 0); + QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1); + QVERIFY(iface3 == 0); + QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1); + QVERIFY(iface3 == 0); + QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1); + QVERIFY(iface3 == 0); + } + } + } + if (!loop) { + // switch children for second loop + w2->raise(); + QAccessibleInterface *temp = iface1; + iface1 = iface2; + iface2 = temp; + } + } + delete iface1; iface1 = 0; + delete iface2; iface2 = 0; + iface1 = QAccessible::queryAccessibleInterface(w1); + QVERIFY(iface1 != 0); + QVERIFY(iface1->isValid()); + iface2 = QAccessible::queryAccessibleInterface(w2); + QVERIFY(iface2 != 0); + QVERIFY(iface2->isValid()); + + w1->move(0,0); + w2->move(0,0); + w1->raise(); + QVERIFY(iface1->relationTo(0, iface2, 0) & QAccessible::Covers); + QVERIFY(iface2->relationTo(0, iface1, 0) & QAccessible::Covered); + QVERIFY(!(iface1->state() & QAccessible::Invisible)); + w1->hide(); + QVERIFY(iface1->state() & QAccessible::Invisible); + QVERIFY(!(iface1->relationTo(0, iface2, 0) & QAccessible::Covers)); + QVERIFY(!(iface2->relationTo(0, iface1, 0) & QAccessible::Covered)); + QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1); + QVERIFY(iface3 == 0); + QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1); + QVERIFY(iface3 == 0); + + delete iface1; iface1 = 0; + delete iface2; iface2 = 0; + delete w; + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::navigateHierarchy() +{ + { + QWidget *w = new QWidget(0); + w->setObjectName(QString("Hans")); + w->show(); + QWidget *w1 = new QWidget(w); + w1->setObjectName(QString("1")); + w1->show(); + QWidget *w2 = new QWidget(w); + w2->setObjectName(QString("2")); + w2->show(); + QWidget *w3 = new QWidget(w); + w3->setObjectName(QString("3")); + w3->show(); + QWidget *w31 = new QWidget(w3); + w31->setObjectName(QString("31")); + w31->show(); + + QAccessibleInterface *target = 0; + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + + QCOMPARE(iface->navigate(QAccessible::Sibling, -42, &target), -1); + QVERIFY(target == 0); + QCOMPARE(iface->navigate(QAccessible::Sibling, 42, &target), -1); + QVERIFY(target == 0); + + target = iface->child(14); + QVERIFY(target == 0); + target = iface->child(-1); + QVERIFY(target == 0); + target = iface->child(0); + QAccessibleInterface *interfaceW1 = iface->child(0); + QVERIFY(target); + QVERIFY(target->isValid()); + QCOMPARE(target->object(), (QObject*)w1); + QVERIFY(interfaceW1 != 0); + QVERIFY(interfaceW1->isValid()); + QCOMPARE(interfaceW1->object(), (QObject*)w1); + delete interfaceW1; + delete iface; iface = 0; + + QCOMPARE(target->navigate(QAccessible::Sibling, 0, &iface), -1); + QVERIFY(iface == 0); + QCOMPARE(target->navigate(QAccessible::Sibling, 42, &iface), -1); + QVERIFY(iface == 0); + QCOMPARE(target->navigate(QAccessible::Sibling, -42, &iface), -1); + QVERIFY(iface == 0); + QCOMPARE(target->navigate(QAccessible::Sibling, 2, &iface), 0); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + QCOMPARE(iface->object(), (QObject*)w2); + delete target; target = 0; + QCOMPARE(iface->navigate(QAccessible::Sibling, 3, &target), 0); + QVERIFY(target != 0); + QVERIFY(target->isValid()); + QCOMPARE(target->object(), (QObject*)w3); + delete iface; iface = 0; + + iface = target->child(0); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + QCOMPARE(iface->object(), (QObject*)w31); + delete target; target = 0; + + QCOMPARE(iface->navigate(QAccessible::Sibling, -1, &target), -1); + QVERIFY(target == 0); + QCOMPARE(iface->navigate(QAccessible::Sibling, 0, &target), -1); + QVERIFY(target == 0); + QCOMPARE(iface->navigate(QAccessible::Sibling, 1, &target), 0); + QVERIFY(target != 0); + QVERIFY(target->isValid()); + QCOMPARE(target->object(), (QObject*)w31); + delete iface; iface = 0; + + iface = target->parent(); + QVERIFY(iface != 0); + QVERIFY(iface->isValid()); + QCOMPARE(iface->object(), (QObject*)w3); + delete iface; iface = 0; + delete target; target = 0; + + delete w; + } + QTestAccessibility::clearEvents(); +} + +#define QSETCOMPARE(thetypename, elements, otherelements) \ + QCOMPARE((QSet() << elements), (QSet() << otherelements)) + +static QWidget *createWidgets() +{ + QWidget *w = new QWidget(); + + QHBoxLayout *box = new QHBoxLayout(w); + + int i = 0; + box->addWidget(new QComboBox(w)); + box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QHeaderView(Qt::Vertical, w)); + box->addWidget(new QTreeView(w)); + box->addWidget(new QTreeWidget(w)); + box->addWidget(new QListView(w)); + box->addWidget(new QListWidget(w)); + box->addWidget(new QTableView(w)); + box->addWidget(new QTableWidget(w)); + box->addWidget(new QCalendarWidget(w)); + box->addWidget(new QDialogButtonBox(w)); + box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QFrame(w)); + box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QProgressBar(w)); + box->addWidget(new QTabWidget(w)); + box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QDial(w)); + box->addWidget(new QScrollBar(w)); + box->addWidget(new QSlider(w)); + box->addWidget(new QDateTimeEdit(w)); + box->addWidget(new QDoubleSpinBox(w)); + box->addWidget(new QSpinBox(w)); + box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QLCDNumber(w)); + box->addWidget(new QStackedWidget(w)); + box->addWidget(new QToolBox(w)); + box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w)); + box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w)); + + /* Not in the list + * QAbstractItemView, QGraphicsView, QScrollArea, + * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle, + * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter + */ + return w; +} + +void tst_QAccessibility::accessibleName() +{ + QWidget *toplevel = createWidgets(); + toplevel->show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + QLayout *lout = toplevel->layout(); + for (int i = 0; i < lout->count(); i++) { + QLayoutItem *item = lout->itemAt(i); + QWidget *child = item->widget(); + + QString name = tr("Widget Name %1").arg(i); + child->setAccessibleName(name); + QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child); + QCOMPARE(acc->text(QAccessible::Name), name); + + QString desc = tr("Widget Description %1").arg(i); + child->setAccessibleDescription(desc); + QCOMPARE(acc->text(QAccessible::Description), desc); + + } + + delete toplevel; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::textAttributes() +{ + QTextEdit textEdit; + int startOffset; + int endOffset; + QString attributes; + QString text("" + "Hello, this is an example text." + "Multiple fonts are used." + "Multiple text sizes are used." + "Let's give some color to Qt." + ""); + + textEdit.setText(text); + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit); + + QAccessibleTextInterface *textInterface=interface->textInterface(); + + QVERIFY(textInterface); + QCOMPARE(textInterface->characterCount(), 112); + + attributes = textInterface->attributes(10, &startOffset, &endOffset); + QCOMPARE(startOffset, 7); + QCOMPARE(endOffset, 11); + attributes.prepend(';'); + QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;"))); + + attributes = textInterface->attributes(18, &startOffset, &endOffset); + QCOMPARE(startOffset, 18); + QCOMPARE(endOffset, 25); + attributes.prepend(';'); + QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;"))); + QVERIFY(attributes.contains(QLatin1String(";font-style:italic;"))); + + attributes = textInterface->attributes(34, &startOffset, &endOffset); + QCOMPARE(startOffset, 31); + QCOMPARE(endOffset, 55); + attributes.prepend(';'); + QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";"))); + + attributes = textInterface->attributes(65, &startOffset, &endOffset); + QCOMPARE(startOffset, 64); + QCOMPARE(endOffset, 74); + attributes.prepend(';'); + QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;"))); + + attributes = textInterface->attributes(110, &startOffset, &endOffset); + QCOMPARE(startOffset, 109); + QCOMPARE(endOffset, 111); + attributes.prepend(';'); + QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);"))); + QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);"))); +} + +void tst_QAccessibility::hideShowTest() +{ + QWidget * const window = new QWidget(); + QWidget * const child = new QWidget(window); + + QVERIFY(state(window) & QAccessible::Invisible); + QVERIFY(state(child) & QAccessible::Invisible); + + QTestAccessibility::clearEvents(); + + // show() and veryfy that both window and child are not invisible and get ObjectShow events. + window->show(); + QVERIFY(state(window) ^ QAccessible::Invisible); + QVERIFY(state(child) ^ QAccessible::Invisible); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow))); + QTestAccessibility::clearEvents(); + + // hide() and veryfy that both window and child are invisible and get ObjectHide events. + window->hide(); + QVERIFY(state(window) & QAccessible::Invisible); + QVERIFY(state(child) & QAccessible::Invisible); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide))); + QTestAccessibility::clearEvents(); + + delete window; + QTestAccessibility::clearEvents(); +} + + +void tst_QAccessibility::actionTest() +{ + QCOMPARE(QAccessibleActionInterface::PressAction, QString("Press")); + + QWidget *widget = new QWidget; + widget->show(); + + QAccessibleInterface *test = QAccessible::queryAccessibleInterface(widget); + QVERIFY(test); + QVERIFY(test->isValid()); + +// QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString()); +// QCOMPARE(test->actionText(0, QAccessible::Name, 1), QString()); +// QCOMPARE(test->actionText(1, QAccessible::Name, 1), QString()); +// QCOMPARE(test->actionText(QAccessible::SetFocus, QAccessible::Name, -1), QString()); + +// QCOMPARE(test->actionText(QAccessible::DefaultAction, QAccessible::Name, 0), QString("SetFocus")); +// QCOMPARE(test->actionText(QAccessible::SetFocus, QAccessible::Name, 0), QString("SetFocus")); + + delete test; + delete widget; + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::applicationTest() +{ + QLatin1String name = QLatin1String("My Name"); + qApp->setApplicationName(name); + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp); + QCOMPARE(interface->text(QAccessible::Name, 0), name); + QCOMPARE(interface->role(), QAccessible::Application); + delete interface; +} + +void tst_QAccessibility::mainWindowTest() +{ + QMainWindow *mw = new QMainWindow; + mw->resize(300, 200); + mw->show(); // triggers layout + + QLatin1String name = QLatin1String("I am the main window"); + mw->setWindowTitle(name); + QTest::qWaitForWindowShown(mw); + QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow); + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw); + QCOMPARE(interface->text(QAccessible::Name, 0), name); + QCOMPARE(interface->role(), QAccessible::Window); + delete interface; + delete mw; + QTestAccessibility::clearEvents(); +} + +class CounterButton : public QPushButton { + Q_OBJECT +public: + CounterButton(const QString& name, QWidget* parent) + : QPushButton(name, parent), clickCount(0) + { + connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount())); + } + int clickCount; +public Q_SLOTS: + void incClickCount() { + ++clickCount; + } +}; + +void tst_QAccessibility::buttonTest() +{ + QWidget window; + window.setLayout(new QVBoxLayout); + + // Standard push button + CounterButton pushButton("Ok", &window); + + // toggle button + QPushButton toggleButton("Toggle", &window); + toggleButton.setCheckable(true); + + // standard checkbox + QCheckBox checkBox("Check me!", &window); + + // tristate checkbox + QCheckBox tristate("Tristate!", &window); + tristate.setTristate(TRUE); + + // radiobutton + QRadioButton radio("Radio me!", &window); + + // standard toolbutton + QToolButton toolbutton(&window); + toolbutton.setText("Tool"); + toolbutton.setMinimumSize(20,20); + + // standard toolbutton + QToolButton toggletool(&window); + toggletool.setCheckable(true); + toggletool.setText("Toggle"); + toggletool.setMinimumSize(20,20); + + // test push button + QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton); + QAccessibleActionInterface* actionInterface = interface->actionInterface(); + QVERIFY(actionInterface != 0); + QCOMPARE(interface->role(), QAccessible::PushButton); + + // currently our buttons only have click as action, press and release are missing + QCOMPARE(actionInterface->actionNames().size(), 1); + QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); + QCOMPARE(pushButton.clickCount, 0); + actionInterface->doAction(QAccessibleActionInterface::PressAction); + QTest::qWait(500); + QCOMPARE(pushButton.clickCount, 1); + delete interface; + + // test toggle button + interface = QAccessible::queryAccessibleInterface(&toggleButton); + actionInterface = interface->actionInterface(); + QCOMPARE(interface->role(), QAccessible::CheckBox); + QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); + QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::CheckAction), QString("Checks the checkbox")); + QVERIFY(!toggleButton.isChecked()); + QVERIFY((interface->state() & QAccessible::Checked) == 0); + actionInterface->doAction(QAccessibleActionInterface::CheckAction); + QTest::qWait(500); + QVERIFY(toggleButton.isChecked()); + QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::UncheckAction); + QVERIFY(interface->state() & QAccessible::Checked); + delete interface; + + { + // test menu push button + QAction *foo = new QAction("Foo", 0); + foo->setShortcut(QKeySequence("Ctrl+F")); + QMenu *menu = new QMenu(); + menu->addAction(foo); + QPushButton menuButton; + menuButton.setMenu(menu); + menuButton.show(); + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton); + QCOMPARE(interface->role(), QAccessible::ButtonMenu); + QVERIFY(interface->state() & QAccessible::HasPopup); + QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); + // showing the menu enters a new event loop... +// interface->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); +// QTest::qWait(500); + delete interface; + delete menu; + } + + // test check box + interface = QAccessible::queryAccessibleInterface(&checkBox); + actionInterface = interface->actionInterface(); + QCOMPARE(interface->role(), QAccessible::CheckBox); + QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); + QVERIFY((interface->state() & QAccessible::Checked) == 0); + actionInterface->doAction(QAccessibleActionInterface::CheckAction); + QTest::qWait(500); + QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::UncheckAction); + QVERIFY(interface->state() & QAccessible::Checked); + QVERIFY(checkBox.isChecked()); + delete interface; + + // test radiobutton + interface = QAccessible::queryAccessibleInterface(&radio); + actionInterface = interface->actionInterface(); + QCOMPARE(interface->role(), QAccessible::RadioButton); + QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); + QVERIFY((interface->state() & QAccessible::Checked) == 0); + actionInterface->doAction(QAccessibleActionInterface::CheckAction); + QTest::qWait(500); + QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); + QVERIFY(interface->state() & QAccessible::Checked); + QVERIFY(checkBox.isChecked()); + delete interface; + +// // test standard toolbutton +// QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test)); +// QCOMPARE(test->role(), QAccessible::PushButton); +// QCOMPARE(test->defaultAction(0), QAccessible::Press); +// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press")); +// QCOMPARE(test->state(), (int)QAccessible::Normal); +// test->release(); + +// // toggle tool button +// QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test)); +// QCOMPARE(test->role(), QAccessible::CheckBox); +// QCOMPARE(test->defaultAction(0), QAccessible::Press); +// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check")); +// QCOMPARE(test->state(), (int)QAccessible::Normal); +// QVERIFY(test->doAction(QAccessible::Press, 0)); +// QTest::qWait(500); +// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck")); +// QCOMPARE(test->state(), (int)QAccessible::Checked); +// test->release(); + +// // test menu toolbutton +// QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test)); +// QCOMPARE(test->role(), QAccessible::ButtonMenu); +// QCOMPARE(test->defaultAction(0), 1); +// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open")); +// QCOMPARE(test->state(), (int)QAccessible::HasPopup); +// QCOMPARE(test->actionCount(0), 1); +// QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press")); +// test->release(); + +// // test split menu toolbutton +// QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test)); +// QCOMPARE(test->childCount(), 2); +// QCOMPARE(test->role(), QAccessible::ButtonDropDown); +// QCOMPARE(test->role(1), QAccessible::PushButton); +// QCOMPARE(test->role(2), QAccessible::ButtonMenu); +// QCOMPARE(test->defaultAction(0), QAccessible::Press); +// QCOMPARE(test->defaultAction(1), QAccessible::Press); +// QCOMPARE(test->defaultAction(2), QAccessible::Press); +// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press")); +// QCOMPARE(test->state(), (int)QAccessible::HasPopup); +// QCOMPARE(test->actionCount(0), 1); +// QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open")); +// QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press")); +// QCOMPARE(test->state(1), (int)QAccessible::Normal); +// QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open")); +// QCOMPARE(test->state(2), (int)QAccessible::HasPopup); +// test->release(); + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::scrollBarTest() +{ + QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal); + QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar); + QVERIFY(scrollBarInterface); + QVERIFY(scrollBarInterface->state() & QAccessible::Invisible); + scrollBar->resize(200, 50); + scrollBar->show(); + QVERIFY(scrollBarInterface->state() ^ QAccessible::Invisible); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow))); + QTestAccessibility::clearEvents(); + + scrollBar->hide(); + QVERIFY(scrollBarInterface->state() & QAccessible::Invisible); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide))); + QTestAccessibility::clearEvents(); + + // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum. + scrollBar->show(); + scrollBar->setMinimum(11); + scrollBar->setMaximum(111); + + QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface(); + QVERIFY(valueIface != 0); + QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum()); + QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum()); + scrollBar->setValue(50); + QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value()); + scrollBar->setValue(0); + QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value()); + scrollBar->setValue(100); + QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value()); + valueIface->setCurrentValue(77); + QCOMPARE(77, scrollBar->value()); + + const QRect scrollBarRect = scrollBarInterface->rect(); + QVERIFY(scrollBarRect.isValid()); + + delete scrollBarInterface; + delete scrollBar; + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::tabTest() +{ + QTabBar *tabBar = new QTabBar(); + tabBar->show(); + + QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar); + QVERIFY(interface); + QCOMPARE(interface->childCount(), 2); + + // Test that the Invisible bit for the navigation buttons gets set + // and cleared correctly. + QAccessibleInterface *leftButton = interface->child(0); + QCOMPARE(leftButton->role(), QAccessible::PushButton); + QVERIFY(leftButton->state() & QAccessible::Invisible); + delete leftButton; + + const int lots = 5; + for (int i = 0; i < lots; ++i) + tabBar->addTab("Foo"); + + QAccessibleInterface *child1 = interface->child(0); + QAccessibleInterface *child2 = interface->child(1); + QVERIFY(child1); + QCOMPARE(child1->role(), QAccessible::PageTab); + QVERIFY(child2); + QCOMPARE(child2->role(), QAccessible::PageTab); + + QVERIFY((child1->state() & QAccessible::Invisible) == false); + tabBar->hide(); + + QCoreApplication::processEvents(); + QTest::qWait(100); + + QVERIFY(child1->state() & QAccessible::Invisible); + + tabBar->show(); + tabBar->setCurrentIndex(0); + + // Test that sending a focus action to a tab does not select it. +// child2->doAction(QAccessible::Focus, 2, QVariantList()); + QCOMPARE(tabBar->currentIndex(), 0); + + // Test that sending a press action to a tab selects it. + QVERIFY(child2->actionInterface()); + QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); + QCOMPARE(tabBar->currentIndex(), 0); + child2->actionInterface()->doAction(QAccessibleActionInterface::PressAction); + QCOMPARE(tabBar->currentIndex(), 1); + + delete tabBar; + delete interface; + delete child1; + delete child2; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::tabWidgetTest() +{ + QTabWidget *tabWidget = new QTabWidget(); + tabWidget->show(); + + // the interface for the tab is just a container for tabbar and stacked widget + QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget); + QVERIFY(interface); + QCOMPARE(interface->childCount(), 2); + QCOMPARE(interface->role(), QAccessible::Client); + + // Create pages, check navigation + QLabel *label1 = new QLabel("Page 1", tabWidget); + tabWidget->addTab(label1, "Tab 1"); + QLabel *label2 = new QLabel("Page 2", tabWidget); + tabWidget->addTab(label2, "Tab 2"); + + QCOMPARE(interface->childCount(), 2); + + QAccessibleInterface* tabBarInterface = 0; + // there is no special logic to sort the children, so the contents will be 1, the tab bar 2 + tabBarInterface = interface->child(1); + QVERIFY(tabBarInterface); + QCOMPARE(tabBarInterface->childCount(), 4); + QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList); + + QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0); + QVERIFY(tabButton1Interface); + QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab); + QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1")); + + QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1); + QVERIFY(tabButton1Interface); + QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab); + QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2")); + + QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2); + QVERIFY(tabButtonLeft); + QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton); + QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left")); + + QAccessibleInterface* tabButtonRight = tabBarInterface->child(3); + QVERIFY(tabButtonRight); + QCOMPARE(tabButtonRight->role(), QAccessible::PushButton); + QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right")); + delete tabButton1Interface; + delete tabButton2Interface; + delete tabButtonLeft; + delete tabButtonRight; + + QAccessibleInterface* stackWidgetInterface = interface->child(0); + QVERIFY(stackWidgetInterface); + QCOMPARE(stackWidgetInterface->childCount(), 2); + QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane); + + QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0); + QVERIFY(stackChild1Interface); +#ifndef Q_CC_INTEL + QCOMPARE(stackChild1Interface->childCount(), 0); +#endif + QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText); + QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1")); + QCOMPARE(label1, stackChild1Interface->object()); + + // Navigation in stack widgets should be consistent + QAccessibleInterface* parent = stackChild1Interface->parent(); + QVERIFY(parent); +#ifndef Q_CC_INTEL + QCOMPARE(parent->childCount(), 2); +#endif + QCOMPARE(parent->role(), QAccessible::LayeredPane); + delete parent; + + QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1); + QVERIFY(stackChild2Interface); + QCOMPARE(stackChild2Interface->childCount(), 0); + QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText); + QCOMPARE(label2, stackChild2Interface->object()); + QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name)); + + parent = stackChild2Interface->parent(); + QVERIFY(parent); +#ifndef Q_CC_INTEL + QCOMPARE(parent->childCount(), 2); +#endif + QCOMPARE(parent->role(), QAccessible::LayeredPane); + delete parent; + + delete tabBarInterface; + delete stackChild1Interface; + delete stackChild2Interface; + delete stackWidgetInterface; + delete interface; + delete tabWidget; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::menuTest() +{ + { + QMainWindow mw; + mw.resize(300, 200); + QMenu *file = mw.menuBar()->addMenu("&File"); + QMenu *fileNew = file->addMenu("&New..."); + fileNew->menuAction()->setShortcut(tr("Ctrl+N")); + fileNew->addAction("Text file"); + fileNew->addAction("Image file"); + file->addAction("&Open")->setShortcut(tr("Ctrl+O")); + file->addAction("&Save")->setShortcut(tr("Ctrl+S")); + file->addSeparator(); + file->addAction("E&xit")->setShortcut(tr("Alt+F4")); + + QMenu *edit = mw.menuBar()->addMenu("&Edit"); + edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z")); + edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y")); + edit->addSeparator(); + edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X")); + edit->addAction("&Copy")->setShortcut(tr("Ctrl+C")); + edit->addAction("&Paste")->setShortcut(tr("Ctrl+V")); + edit->addAction("&Delete")->setShortcut(tr("Del")); + edit->addSeparator(); + edit->addAction("Pr&operties"); + + mw.menuBar()->addSeparator(); + + QMenu *help = mw.menuBar()->addMenu("&Help"); + help->addAction("&Contents"); + help->addAction("&About"); + + mw.menuBar()->addAction("Action!"); + + mw.show(); // triggers layout + QTest::qWait(100); + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar()); + QCOMPARE(verifyHierarchy(interface), 0); + + QVERIFY(interface); + QCOMPARE(interface->childCount(), 5); + QCOMPARE(interface->role(), QAccessible::MenuBar); + + QAccessibleInterface *iFile = interface->child(0); + QAccessibleInterface *iEdit = interface->child(1); + QAccessibleInterface *iSeparator = interface->child(2); + QAccessibleInterface *iHelp = interface->child(3); + QAccessibleInterface *iAction = interface->child(4); + + QCOMPARE(iFile->role(), QAccessible::MenuItem); + QCOMPARE(iEdit->role(), QAccessible::MenuItem); + QCOMPARE(iSeparator->role(), QAccessible::Separator); + QCOMPARE(iHelp->role(), QAccessible::MenuItem); + QCOMPARE(iAction->role(), QAccessible::MenuItem); +#ifndef Q_WS_MAC +#ifdef Q_OS_WINCE + if (!IsValidCEPlatform()) { + QSKIP("Tests do not work on Mobile platforms due to native menus", SkipAll); + } +#endif + QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft()); + QCOMPARE(interface->rect().size(), mw.menuBar()->size()); + + QVERIFY(interface->rect().contains(iFile->rect())); + QVERIFY(interface->rect().contains(iEdit->rect())); + // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible + QVERIFY(interface->rect().contains(iHelp->rect())); + QVERIFY(interface->rect().contains(iAction->rect())); +#endif + + QCOMPARE(iFile->text(QAccessible::Name, 0), QString("File")); + QCOMPARE(iEdit->text(QAccessible::Name, 0), QString("Edit")); + QCOMPARE(iSeparator->text(QAccessible::Name, 0), QString()); + QCOMPARE(iHelp->text(QAccessible::Name, 0), QString("Help")); + QCOMPARE(iAction->text(QAccessible::Name, 0), QString("Action!")); + +// TODO: Currently not working, task to fix is #100019. +#ifndef Q_OS_MAC + QCOMPARE(iFile->text(QAccessible::Accelerator, 0), tr("Alt+F")); + QCOMPARE(iEdit->text(QAccessible::Accelerator, 0), tr("Alt+E")); + QCOMPARE(iSeparator->text(QAccessible::Accelerator, 0), QString()); + QCOMPARE(iHelp->text(QAccessible::Accelerator, 0), tr("Alt+H")); + QCOMPARE(iAction->text(QAccessible::Accelerator, 0), QString()); +#endif + + QVERIFY(iFile->actionInterface()); + + QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); + QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList()); + QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); + QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); + + bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu); + int menuFadeDelay = 300; + iFile->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + if(menuFade) + QTest::qWait(menuFadeDelay); + QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible()); + iEdit->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + if(menuFade) + QTest::qWait(menuFadeDelay); + QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible()); + iHelp->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + if(menuFade) + QTest::qWait(menuFadeDelay); + QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible()); + iAction->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + if(menuFade) + QTest::qWait(menuFadeDelay); + QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible()); + + QVERIFY(!interface->actionInterface()); + delete interface; + interface = QAccessible::queryAccessibleInterface(file); + QCOMPARE(interface->childCount(), 5); + QCOMPARE(interface->role(), QAccessible::PopupMenu); + + QAccessibleInterface *iFileNew = interface->child(0); + QAccessibleInterface *iFileOpen = interface->child(1); + QAccessibleInterface *iFileSave = interface->child(2); + QAccessibleInterface *iFileSeparator = interface->child(3); + QAccessibleInterface *iFileExit = interface->child(4); + + QCOMPARE(iFileNew->role(), QAccessible::MenuItem); + QCOMPARE(iFileOpen->role(), QAccessible::MenuItem); + QCOMPARE(iFileSave->role(), QAccessible::MenuItem); + QCOMPARE(iFileSeparator->role(), QAccessible::Separator); + QCOMPARE(iFileExit->role(), QAccessible::MenuItem); + QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); + QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); + QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); + QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList()); + QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); + + QAccessibleInterface *iface = 0; + QAccessibleInterface *iface2 = 0; + + // traverse siblings with navigate(Sibling, ...) + int entry = interface->navigate(QAccessible::Child, 1, &iface); + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::MenuItem); + + QAccessible::Role fileRoles[5] = { + QAccessible::MenuItem, + QAccessible::MenuItem, + QAccessible::MenuItem, + QAccessible::Separator, + QAccessible::MenuItem + }; + for (int child = 0; child < 5; ++child) { + entry = iface->navigate(QAccessible::Sibling, child + 1, &iface2); + QCOMPARE(entry, 0); + QVERIFY(iface2); + QCOMPARE(iface2->role(), fileRoles[child]); + delete iface2; + } + delete iface; + + // traverse menu items with navigate(Down, ...) + entry = interface->navigate(QAccessible::Child, 1, &iface); + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::MenuItem); + + for (int child = 0; child < 4; ++child) { + entry = iface->navigate(QAccessible::Down, 1, &iface2); + delete iface; + iface = iface2; + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), fileRoles[child + 1]); + } + delete iface; + + // traverse menu items with navigate(Up, ...) + entry = interface->navigate(QAccessible::Child, interface->childCount(), &iface); + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::MenuItem); + + for (int child = 3; child >= 0; --child) { + entry = iface->navigate(QAccessible::Up, 1, &iface2); + delete iface; + iface = iface2; + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), fileRoles[child]); + } + delete iface; + + // "New" item + entry = interface->navigate(QAccessible::Child, 1, &iface); + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::MenuItem); + + // "New" menu + entry = iface->navigate(QAccessible::Child, 1, &iface2); + delete iface; + iface = iface2; + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::PopupMenu); + + // "Text file" menu item + entry = iface->navigate(QAccessible::Child, 1, &iface2); + delete iface; + iface = iface2; + QCOMPARE(entry, 0); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::MenuItem); + + delete iface; + + // move mouse pointer away, since that might influence the + // subsequent tests + QTest::mouseMove(&mw, QPoint(-1, -1)); + QTest::qWait(100); + if (menuFade) + QTest::qWait(menuFadeDelay); + + iFile->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + iFileNew->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + + QVERIFY(file->isVisible()); + QVERIFY(fileNew->isVisible()); + QVERIFY(!edit->isVisible()); + QVERIFY(!help->isVisible()); + + QTestAccessibility::clearEvents(); + mw.hide(); + + delete iFile; + delete iFileNew; + delete iFileOpen; + delete iFileSave; + delete iFileSeparator; + delete iFileExit; + + // Do not crash if the menu don't have a parent + QMenu *menu = new QMenu; + menu->addAction(QLatin1String("one")); + menu->addAction(QLatin1String("two")); + menu->addAction(QLatin1String("three")); + iface = QAccessible::queryAccessibleInterface(menu); + iface2 = iface->parent(); + QVERIFY(iface2); + QCOMPARE(iface2->role(), QAccessible::Application); + // caused a *crash* + iface2->state(); + delete iface2; + delete iface; + delete menu; + + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::spinBoxTest() +{ + QSpinBox * const spinBox = new QSpinBox(); + spinBox->setValue(3); + spinBox->show(); + + QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox); + QVERIFY(interface); + QCOMPARE(interface->role(), QAccessible::SpinBox); + + const QRect widgetRect = spinBox->geometry(); + const QRect accessibleRect = interface->rect(); + QCOMPARE(accessibleRect, widgetRect); + QCOMPARE(interface->text(QAccessible::Value, 0), QLatin1String("3")); + + // one child, the line edit + const int numChildren = interface->childCount(); + QCOMPARE(numChildren, 1); + QAccessibleInterface *lineEdit = interface->child(0); + + QCOMPARE(lineEdit->role(), QAccessible::EditableText); + QCOMPARE(lineEdit->text(QAccessible::Value, 0), QLatin1String("3")); + delete lineEdit; + + QVERIFY(interface->valueInterface()); + QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3); + interface->valueInterface()->setCurrentValue(23); + QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23); + QCOMPARE(spinBox->value(), 23); + + spinBox->setFocus(); + QTestAccessibility::clearEvents(); + QTest::keyPress(spinBox, Qt::Key_Up); + QTest::qWait(200); + EventList events = QTestAccessibility::events(); + QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged); + QVERIFY(events.contains(expectedEvent)); + delete spinBox; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::doubleSpinBoxTest() +{ + QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox; + doubleSpinBox->show(); + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox); + QVERIFY(interface); + + const QRect widgetRect = doubleSpinBox->geometry(); + const QRect accessibleRect = interface->rect(); + QCOMPARE(accessibleRect, widgetRect); + + // Test that we get valid rects for all the spinbox child interfaces. + const int numChildren = interface->childCount(); + for (int i = 1; i <= numChildren; ++i) { + const QRect childRect = interface->rect(i); + QVERIFY(childRect.isValid()); + } + + delete doubleSpinBox; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::textEditTest() +{ + { + QTextEdit edit; + int startOffset; + int endOffset; + QString text = "hello world\nhow are you today?\n"; + edit.setText(text); + edit.show(); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit); + QCOMPARE(iface->text(QAccessible::Value, 0), text); + QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world")); + QCOMPARE(startOffset, 6); + QCOMPARE(endOffset, 11); + QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?")); + QCOMPARE(startOffset, 12); + QCOMPARE(endOffset, 30); + QCOMPARE(iface->textInterface()->characterCount(), 31); + QFontMetrics fm(edit.font()); + QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height())); + QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height())); + QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height())); + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::textBrowserTest() +{ + { + QTextBrowser textBrowser; + QString text = QLatin1String("Hello world\nhow are you today?\n"); + textBrowser.setText(text); + textBrowser.show(); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::StaticText); + QCOMPARE(iface->text(QAccessible::Value, 0), text); + int startOffset; + int endOffset; + QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world")); + QCOMPARE(startOffset, 6); + QCOMPARE(endOffset, 11); + QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?")); + QCOMPARE(startOffset, 12); + QCOMPARE(endOffset, 30); + QCOMPARE(iface->textInterface()->characterCount(), 31); + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::mdiAreaTest() +{ + { + QMdiArea mdiArea; + mdiArea.resize(400,300); + mdiArea.show(); + const int subWindowCount = 3; + for (int i = 0; i < subWindowCount; ++i) + mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show(); + + QList subWindows = mdiArea.subWindowList(); + QCOMPARE(subWindows.count(), subWindowCount); + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea); + QVERIFY(interface); + QCOMPARE(interface->childCount(), subWindowCount); + + // Right, right, right, ... + for (int i = 0; i < subWindowCount; ++i) { + QAccessibleInterface *destination = 0; + int index = interface->navigate(QAccessible::Right, i + 1, &destination); + if (i == subWindowCount - 1) { + QVERIFY(!destination); + QCOMPARE(index, -1); + } else { + QVERIFY(destination); + QCOMPARE(index, 0); + QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1)); + delete destination; + } + } + + // Left, left, left, ... + for (int i = subWindowCount; i > 0; --i) { + QAccessibleInterface *destination = 0; + int index = interface->navigate(QAccessible::Left, i, &destination); + if (i == 1) { + QVERIFY(!destination); + QCOMPARE(index, -1); + } else { + QVERIFY(destination); + QCOMPARE(index, 0); + QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2)); + delete destination; + } + } + // ### Add test for Up and Down. + + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::mdiSubWindowTest() +{ + { + QMdiArea mdiArea; + mdiArea.show(); + qApp->setActiveWindow(&mdiArea); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(150); +#endif + + bool isSubWindowsPlacedNextToEachOther = false; + const int subWindowCount = 5; + for (int i = 0; i < subWindowCount; ++i) { + QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest")); + window->show(); + // Parts of this test requires that the sub windows are placed next + // to each other. In order to achieve that QMdiArea must have + // a width which is larger than subWindow->width() * subWindowCount. + if (i == 0) { + int minimumWidth = window->width() * subWindowCount + 20; + mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0))); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + if (mdiArea.width() >= minimumWidth) + isSubWindowsPlacedNextToEachOther = true; + } + } + + QList subWindows = mdiArea.subWindowList(); + QCOMPARE(subWindows.count(), subWindowCount); + + QMdiSubWindow *testWindow = subWindows.at(3); + QVERIFY(testWindow); + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow); + + // childCount + QVERIFY(interface); + QCOMPARE(interface->childCount(), 1); + + // setText / text + QCOMPARE(interface->text(QAccessible::Name, 0), QString()); + QCOMPARE(interface->text(QAccessible::Name, 1), QString()); + testWindow->setWindowTitle(QLatin1String("ReplaceMe")); + QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("ReplaceMe")); + QCOMPARE(interface->text(QAccessible::Name, 1), QLatin1String("ReplaceMe")); + interface->setText(QAccessible::Name, 0, QLatin1String("TitleSetOnWindow")); + QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("TitleSetOnWindow")); + interface->setText(QAccessible::Name, 1, QLatin1String("TitleSetOnChild")); + QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("TitleSetOnChild")); + + mdiArea.setActiveSubWindow(testWindow); + + // state + QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused + | QAccessible::Movable | QAccessible::Sizeable; + QCOMPARE(interface->state(), state); + const QRect originalGeometry = testWindow->geometry(); + testWindow->showMaximized(); + state &= ~QAccessible::Sizeable; + state &= ~QAccessible::Movable; + QCOMPARE(interface->state(), state); + testWindow->showNormal(); + testWindow->move(-10, 0); + QVERIFY(interface->state() & QAccessible::Offscreen); + testWindow->setVisible(false); + QVERIFY(interface->state() & QAccessible::Invisible); + testWindow->setVisible(true); + testWindow->setEnabled(false); + QVERIFY(interface->state() & QAccessible::Unavailable); + testWindow->setEnabled(true); + qApp->setActiveWindow(&mdiArea); + mdiArea.setActiveSubWindow(testWindow); + testWindow->setFocus(); + QVERIFY(testWindow->isAncestorOf(qApp->focusWidget())); + QVERIFY(interface->state() & QAccessible::Focused); + testWindow->setGeometry(originalGeometry); + + if (isSubWindowsPlacedNextToEachOther) { + // This part of the test can only be run if the sub windows are + // placed next to each other. + QAccessibleInterface *destination = 0; + QCOMPARE(interface->navigate(QAccessible::Child, 1, &destination), 0); + QVERIFY(destination); + QCOMPARE(destination->object(), (QObject*)testWindow->widget()); + delete destination; + QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0); + QVERIFY(destination); + QCOMPARE(destination->object(), (QObject*)subWindows.at(2)); + delete destination; + QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0); + QVERIFY(destination); + QCOMPARE(destination->object(), (QObject*)subWindows.at(4)); + delete destination; + } + + // rect + const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0)); + QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size())); + testWindow->hide(); + QCOMPARE(interface->rect(), QRect()); + QCOMPARE(interface->rect(1), QRect()); + testWindow->showMinimized(); + QCOMPARE(interface->rect(1), QRect()); + testWindow->showNormal(); + testWindow->widget()->hide(); + QCOMPARE(interface->rect(1), QRect()); + testWindow->widget()->show(); + const QRect widgetGeometry = testWindow->contentsRect(); + const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(), + globalPos.y() + widgetGeometry.y()); + QCOMPARE(interface->rect(1), QRect(globalWidgetPos, widgetGeometry.size())); + + // childAt + QCOMPARE(interface->childAt(-10, 0), -1); + QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), 0); + QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 1); + testWindow->widget()->hide(); + QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 0); + + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::lineEditTest() +{ + QLineEdit *le = new QLineEdit; + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le); + QVERIFY(iface); + le->show(); + + QApplication::processEvents(); + QCOMPARE(iface->childCount(), 0); + QVERIFY(iface->state() & QAccessible::Sizeable); + QVERIFY(iface->state() & QAccessible::Movable); + QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow()); + QVERIFY(iface->state() & QAccessible::Selectable); + QVERIFY(iface->state() & QAccessible::HasPopup); + QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus()); + + QString secret(QLatin1String("secret")); + le->setText(secret); + le->setEchoMode(QLineEdit::Normal); + QVERIFY(!(iface->state() & QAccessible::Protected)); + QCOMPARE(iface->text(QAccessible::Value, 0), secret); + le->setEchoMode(QLineEdit::NoEcho); + QVERIFY(iface->state() & QAccessible::Protected); + QVERIFY(iface->text(QAccessible::Value, 0).isEmpty()); + le->setEchoMode(QLineEdit::Password); + QVERIFY(iface->state() & QAccessible::Protected); + QVERIFY(iface->text(QAccessible::Value, 0).isEmpty()); + le->setEchoMode(QLineEdit::PasswordEchoOnEdit); + QVERIFY(iface->state() & QAccessible::Protected); + QVERIFY(iface->text(QAccessible::Value, 0).isEmpty()); + le->setEchoMode(QLineEdit::Normal); + QVERIFY(!(iface->state() & QAccessible::Protected)); + QCOMPARE(iface->text(QAccessible::Value, 0), secret); + + QWidget *toplevel = new QWidget; + le->setParent(toplevel); + toplevel->show(); + QApplication::processEvents(); + QVERIFY(!(iface->state() & QAccessible::Sizeable)); + QVERIFY(!(iface->state() & QAccessible::Movable)); + QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow()); + QVERIFY(iface->state() & QAccessible::Selectable); + QVERIFY(iface->state() & QAccessible::HasPopup); + QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus()); + + QLineEdit *le2 = new QLineEdit(toplevel); + le2->show(); + QTest::qWait(100); + le2->activateWindow(); + QTest::qWait(100); + le->setFocus(Qt::TabFocusReason); + QTestAccessibility::clearEvents(); + le2->setFocus(Qt::TabFocusReason); + QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus))); + + le->setText(QLatin1String("500")); + le->setValidator(new QIntValidator()); + iface->setText(QAccessible::Value, 0, QLatin1String("This text is not a number")); + QCOMPARE(le->text(), QLatin1String("500")); + + delete iface; + delete le; + delete le2; + QTestAccessibility::clearEvents(); + + // IA2 + QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde"; + QLineEdit *le3 = new QLineEdit(cite, toplevel); + iface = QAccessible::queryAccessibleInterface(le3); + QAccessibleTextInterface* textIface = iface->textInterface(); + le3->deselect(); + le3->setCursorPosition(3); + QCOMPARE(textIface->cursorPosition(), 3); + QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved))); + QCOMPARE(textIface->selectionCount(), 0); + QTestAccessibility::clearEvents(); + + int start, end; + QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always")); + QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I")); + QCOMPARE(start, 0); + QCOMPARE(end, 1); + QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString()); + QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(start, 1); + QCOMPARE(end, 2); + + QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a")); + QCOMPARE(start, 5); + QCOMPARE(end, 6); + QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w")); + QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y")); + + QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); + QCOMPARE(start, 2); + QCOMPARE(end, 8); + + QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); + QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); + QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice")); + QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself")); + + QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. ")); + QCOMPARE(start, 0); + QCOMPARE(end, 30); + + QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. ")); + QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. ")); + + QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite); + QCOMPARE(start, 0); + QCOMPARE(end, cite.length()); + QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite); + QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite); + + delete iface; + delete toplevel; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::workspaceTest() +{ + { + QWorkspace workspace; + workspace.resize(400,300); + workspace.show(); + const int subWindowCount = 3; + for (int i = 0; i < subWindowCount; ++i) { + QWidget *window = workspace.addWindow(new QWidget); + if (i > 0) + window->move(window->x() + 1, window->y()); + window->show(); + window->resize(70, window->height()); + } + + QWidgetList subWindows = workspace.windowList(); + QCOMPARE(subWindows.count(), subWindowCount); + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace); + QVERIFY(interface); + QCOMPARE(interface->childCount(), subWindowCount); + + // Right, right, right, ... + for (int i = 0; i < subWindowCount; ++i) { + QAccessibleInterface *destination = 0; + int index = interface->navigate(QAccessible::Right, i + 1, &destination); + if (i == subWindowCount - 1) { + QVERIFY(!destination); + QCOMPARE(index, -1); + } else { + QVERIFY(destination); + QCOMPARE(index, 0); + QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1)); + delete destination; + } + } + + // Left, left, left, ... + for (int i = subWindowCount; i > 0; --i) { + QAccessibleInterface *destination = 0; + int index = interface->navigate(QAccessible::Left, i, &destination); + if (i == 1) { + QVERIFY(!destination); + QCOMPARE(index, -1); + } else { + QVERIFY(destination); + QCOMPARE(index, 0); + QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2)); + delete destination; + } + } + // ### Add test for Up and Down. + + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::dialogButtonBoxTest() +{ + { + QDialogButtonBox box(QDialogButtonBox::Reset | + QDialogButtonBox::Help | + QDialogButtonBox::Ok, Qt::Horizontal); + + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box); + QVERIFY(iface); + box.show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + + QApplication::processEvents(); + QCOMPARE(iface->childCount(), 3); + QCOMPARE(iface->role(), QAccessible::Grouping); + QCOMPARE(iface->role(1), QAccessible::PushButton); + QCOMPARE(iface->role(2), QAccessible::PushButton); + QCOMPARE(iface->role(3), QAccessible::PushButton); + QStringList actualOrder; + QAccessibleInterface *child; + QAccessibleInterface *leftmost; + child = iface->child(0); + // first find the leftmost button + while (child->navigate(QAccessible::Left, 1, &leftmost) != -1) { + delete child; + child = leftmost; + } + leftmost = child; + + // then traverse from left to right to find the correct order of the buttons + int right = 0; + while (right != -1) { + actualOrder << leftmost->text(QAccessible::Name, 0); + right = leftmost->navigate(QAccessible::Right, 1, &child); + delete leftmost; + leftmost = child; + } + + QStringList expectedOrder; + QDialogButtonBox::ButtonLayout btnlout = + QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout)); + switch (btnlout) { + case QDialogButtonBox::WinLayout: + expectedOrder << QDialogButtonBox::tr("Reset") + << QDialogButtonBox::tr("OK") + << QDialogButtonBox::tr("Help"); + break; + case QDialogButtonBox::GnomeLayout: + case QDialogButtonBox::KdeLayout: + case QDialogButtonBox::MacLayout: + expectedOrder << QDialogButtonBox::tr("Help") + << QDialogButtonBox::tr("Reset") + << QDialogButtonBox::tr("OK"); + break; + } + QCOMPARE(actualOrder, expectedOrder); + delete iface; + QApplication::processEvents(); + QTestAccessibility::clearEvents(); + } + + { + QDialogButtonBox box(QDialogButtonBox::Reset | + QDialogButtonBox::Help | + QDialogButtonBox::Ok, Qt::Horizontal); + + + // Test up and down navigation + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box); + QVERIFY(iface); + box.setOrientation(Qt::Vertical); + box.show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + + QApplication::processEvents(); + QAccessibleInterface *child; + QStringList actualOrder; + child = iface->child(0); + // first find the topmost button + QAccessibleInterface *other; + while (child->navigate(QAccessible::Up, 1, &other) != -1) { + delete child; + child = other; + } + other = child; + + // then traverse from top to bottom to find the correct order of the buttons + actualOrder.clear(); + int right = 0; + while (right != -1) { + actualOrder << other->text(QAccessible::Name, 0); + right = other->navigate(QAccessible::Down, 1, &child); + delete other; + other = child; + } + + QStringList expectedOrder; + expectedOrder << QDialogButtonBox::tr("OK") + << QDialogButtonBox::tr("Reset") + << QDialogButtonBox::tr("Help"); + + QCOMPARE(actualOrder, expectedOrder); + delete iface; + QApplication::processEvents(); + + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::dialTest() +{ + { + QDial dial; + dial.setMinimum(23); + dial.setMaximum(121); + dial.setValue(42); + QCOMPARE(dial.value(), 42); + dial.show(); + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial); + QVERIFY(interface); + QCOMPARE(interface->childCount(), 0); + + QCOMPARE(interface->text(QAccessible::Value, 0), QString::number(dial.value())); + QCOMPARE(interface->rect(), dial.geometry()); + + QAccessibleValueInterface *valueIface = interface->valueInterface(); + QVERIFY(valueIface != 0); + QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum()); + QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum()); + QCOMPARE(valueIface->currentValue().toInt(), 42); + dial.setValue(50); + QCOMPARE(valueIface->currentValue().toInt(), dial.value()); + dial.setValue(0); + QCOMPARE(valueIface->currentValue().toInt(), dial.value()); + dial.setValue(100); + QCOMPARE(valueIface->currentValue().toInt(), dial.value()); + valueIface->setCurrentValue(77); + QCOMPARE(77, dial.value()); + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::rubberBandTest() +{ + QRubberBand rubberBand(QRubberBand::Rectangle); + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand); + QVERIFY(interface); + QCOMPARE(interface->role(), QAccessible::Border); + delete interface; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::abstractScrollAreaTest() +{ + { + QAbstractScrollArea abstractScrollArea; + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea); + QVERIFY(interface); + QVERIFY(!interface->rect().isValid()); + QCOMPARE(interface->childAt(200, 200), -1); + + abstractScrollArea.resize(400, 400); + abstractScrollArea.show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)), + abstractScrollArea.size()); + + // Viewport. + QCOMPARE(interface->childCount(), 1); + QWidget *viewport = abstractScrollArea.viewport(); + QVERIFY(viewport); + QVERIFY(verifyChild(viewport, interface, 1, globalGeometry)); + + // Horizontal scrollBar. + abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + QCOMPARE(interface->childCount(), 2); + QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar(); + QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget(); + QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry)); + + // Horizontal scrollBar widgets. + QLabel *secondLeftLabel = new QLabel(QLatin1String("L2")); + abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft); + QCOMPARE(interface->childCount(), 2); + + QLabel *firstLeftLabel = new QLabel(QLatin1String("L1")); + abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft); + QCOMPARE(interface->childCount(), 2); + + QLabel *secondRightLabel = new QLabel(QLatin1String("R2")); + abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight); + QCOMPARE(interface->childCount(), 2); + + QLabel *firstRightLabel = new QLabel(QLatin1String("R1")); + abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight); + QCOMPARE(interface->childCount(), 2); + + // Vertical scrollBar. + abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + QCOMPARE(interface->childCount(), 3); + QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar(); + QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget(); + QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry)); + + // Vertical scrollBar widgets. + QLabel *secondTopLabel = new QLabel(QLatin1String("T2")); + abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop); + QCOMPARE(interface->childCount(), 3); + + QLabel *firstTopLabel = new QLabel(QLatin1String("T1")); + abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop); + QCOMPARE(interface->childCount(), 3); + + QLabel *secondBottomLabel = new QLabel(QLatin1String("B2")); + abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom); + QCOMPARE(interface->childCount(), 3); + + QLabel *firstBottomLabel = new QLabel(QLatin1String("B1")); + abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom); + QCOMPARE(interface->childCount(), 3); + + // CornerWidget. + abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C"))); + QCOMPARE(interface->childCount(), 4); + QWidget *cornerWidget = abstractScrollArea.cornerWidget(); + QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry)); + + // Test navigate. + QAccessibleInterface *target = 0; + + // viewport -> Up -> NOTHING + const int viewportIndex = indexOfChild(interface, viewport); + QVERIFY(viewportIndex != -1); + QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1); + QVERIFY(!target); + + // viewport -> Left -> NOTHING + QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1); + QVERIFY(!target); + + // viewport -> Down -> horizontalScrollBarContainer + const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer); + QVERIFY(horizontalScrollBarContainerIndex != -1); + QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0); + QVERIFY(target); + QCOMPARE(target->object(), static_cast(horizontalScrollBarContainer)); + delete target; + target = 0; + + // horizontalScrollBarContainer -> Left -> NOTHING + QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1); + QVERIFY(!target); + + // horizontalScrollBarContainer -> Down -> NOTHING + QVERIFY(horizontalScrollBarContainerIndex != -1); + QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1); + QVERIFY(!target); + + // horizontalScrollBarContainer -> Right -> cornerWidget + const int cornerWidgetIndex = indexOfChild(interface, cornerWidget); + QVERIFY(cornerWidgetIndex != -1); + QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0); + QVERIFY(target); + QCOMPARE(target->object(), static_cast(cornerWidget)); + delete target; + target = 0; + + // cornerWidget -> Down -> NOTHING + QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1); + QVERIFY(!target); + + // cornerWidget -> Right -> NOTHING + QVERIFY(cornerWidgetIndex != -1); + QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1); + QVERIFY(!target); + + // cornerWidget -> Up -> verticalScrollBarContainer + const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer); + QVERIFY(verticalScrollBarContainerIndex != -1); + QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0); + QVERIFY(target); + QCOMPARE(target->object(), static_cast(verticalScrollBarContainer)); + delete target; + target = 0; + + // verticalScrollBarContainer -> Right -> NOTHING + QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1); + QVERIFY(!target); + + // verticalScrollBarContainer -> Up -> NOTHING + QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1); + QVERIFY(!target); + + // verticalScrollBarContainer -> Left -> viewport + QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0); + QVERIFY(target); + QCOMPARE(target->object(), static_cast(viewport)); + delete target; + target = 0; + + QCOMPARE(verifyHierarchy(interface), 0); + + delete interface; + } + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::scrollAreaTest() +{ + { + QScrollArea scrollArea; + scrollArea.show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea); + QVERIFY(interface); + QCOMPARE(interface->childCount(), 1); // The viewport. + delete interface; + } + QTestAccessibility::clearEvents(); +} + +// Accessible table1 interface is no longer supported on X11, +// where it has been replaced by table2 interface. +#ifndef Q_OS_UNIX + +void tst_QAccessibility::listViewTest() +{ + { + QListView listView; + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QVERIFY(iface); + QCOMPARE(iface->childCount(), 1); + delete iface; + } + { + QListWidget listView; + listView.addItem(tr("A")); + listView.addItem(tr("B")); + listView.addItem(tr("C")); + listView.resize(400,400); + listView.show(); + QTest::qWait(1); // Need this for indexOfchild to work. + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QCOMPARE((int)iface->role(), (int)QAccessible::Client); + QCOMPARE((int)iface->role(1), (int)QAccessible::List); + QCOMPARE(iface->childCount(), 1); + QAccessibleInterface *child; + iface->navigate(QAccessible::Child, 1, &child); + delete iface; + iface = child; + QCOMPARE(iface->text(QAccessible::Name, 1), QString("A")); + QCOMPARE(iface->text(QAccessible::Name, 2), QString("B")); + QCOMPARE(iface->text(QAccessible::Name, 3), QString("C")); + + QCOMPARE(iface->childCount(), 3); + + QAccessibleInterface *childA = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 1, &childA), 0); + QVERIFY(childA); + QCOMPARE(iface->indexOfChild(childA), 1); + QCOMPARE(childA->text(QAccessible::Name, 1), QString("A")); + delete childA; + + QAccessibleInterface *childB = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 2, &childB), 0); + QVERIFY(childB); + QCOMPARE(iface->indexOfChild(childB), 2); + QCOMPARE(childB->text(QAccessible::Name, 1), QString("B")); + delete childB; + + QAccessibleInterface *childC = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 3, &childC), 0); + QVERIFY(childC); + QCOMPARE(iface->indexOfChild(childC), 3); + QCOMPARE(childC->text(QAccessible::Name, 1), QString("C")); + delete childC; + QTestAccessibility::clearEvents(); + + // Check for events + QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(1)).center()); + QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(2)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView.viewport(), 2, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView.viewport(), 3, QAccessible::Selection))); + delete iface; + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::treeWidgetTest() +{ + QWidget *w = new QWidget; + QTreeWidget *tree = new QTreeWidget(w); + QHBoxLayout *l = new QHBoxLayout(w); + l->addWidget(tree); + for (int i = 0; i < 10; ++i) { + QStringList strings = QStringList() << QString::fromAscii("row: %1").arg(i) + << QString("column 1") << QString("column 2"); + + tree->addTopLevelItem(new QTreeWidgetItem(strings)); + } + w->show(); + + QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(tree); + QAccessibleInterface *accViewport = 0; + int entry = acc->navigate(QAccessible::Child, 1, &accViewport); + QVERIFY(accViewport); + QCOMPARE(entry, 0); + QAccessibleInterface *accTreeItem = 0; + entry = accViewport->navigate(QAccessible::Child, 1, &accTreeItem); + QCOMPARE(entry, 0); + + QAccessibleInterface *accTreeItem2 = 0; + entry = accTreeItem->navigate(QAccessible::Sibling, 3, &accTreeItem2); + QCOMPARE(entry, 0); + QCOMPARE(accTreeItem2->text(QAccessible::Name, 0), QLatin1String("row: 1")); + + // test selected/focused state + QItemSelectionModel *selModel = tree->selectionModel(); + QVERIFY(selModel); + selModel->select(QItemSelection(tree->model()->index(0, 0), tree->model()->index(3, 0)), QItemSelectionModel::Select); + selModel->setCurrentIndex(tree->model()->index(1, 0), QItemSelectionModel::Current); + + for (int i = 1; i < 10 ; ++i) { + QAccessible::State expected; + if (i <= 5 && i >= 2) + expected = QAccessible::Selected; + if (i == 3) + expected |= QAccessible::Focused; + + QCOMPARE(accViewport->state(i) & (QAccessible::Focused | QAccessible::Selected), expected); + } + + // Test sanity of its navigation functions + QCOMPARE(verifyHierarchy(acc), 0); + + delete accTreeItem2; + delete accTreeItem; + delete accViewport; + delete acc; + delete w; + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::tableWidgetTest() +{ + { + QWidget *topLevel = new QWidget; + QTableWidget *w = new QTableWidget(8,4,topLevel); + for (int r = 0; r < 8; ++r) { + for (int c = 0; c < 4; ++c) { + w->setItem(r, c, new QTableWidgetItem(tr("%1,%2").arg(c).arg(r))); + } + } + w->resize(100, 100); + topLevel->show(); + + QAccessibleInterface *client = QAccessible::queryAccessibleInterface(w); + QCOMPARE(client->role(), QAccessible::Client); + QCOMPARE(client->childCount(), 3); + QAccessibleInterface *view = 0; + view = client->child(0); + QCOMPARE(view->role(), QAccessible::Table); + QAccessibleInterface *ifRow; + ifRow = view->child(1); + QCOMPARE(ifRow->role(), QAccessible::Row); + QAccessibleInterface *item; + int entry = ifRow->navigate(QAccessible::Child, 1, &item); + QCOMPARE(entry, 1); + QCOMPARE(item , (QAccessibleInterface*)0); + QCOMPARE(ifRow->text(QAccessible::Name, 2), QLatin1String("0,0")); + QCOMPARE(ifRow->text(QAccessible::Name, 3), QLatin1String("1,0")); + + QCOMPARE(verifyHierarchy(client), 0); + + delete ifRow; + delete view; + delete client; + delete w; + delete topLevel; + } + QTestAccessibility::clearEvents(); +} + +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) {} + + int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; } + int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; } + + 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(); + } + + 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(); + } + + 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(); + } + + void reset() + { + QAbstractTableModel::reset(); + } + + int row_count; + int column_count; +}; + +class QtTestDelegate : public QItemDelegate +{ +public: + QtTestDelegate(QWidget *parent = 0) : QItemDelegate(parent) {} + + virtual QSize sizeHint(const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/) const + { + return QSize(100,50); + } +}; + +void tst_QAccessibility::tableViewTest() +{ + { + QtTestTableModel *model = new QtTestTableModel(3, 4); + QTableView *w = new QTableView(); + w->setModel(model); + w->setItemDelegate(new QtTestDelegate(w)); + w->resize(450,200); + w->resizeColumnsToContents(); + w->resizeRowsToContents(); + w->show(); + + QAccessibleInterface *client = QAccessible::queryAccessibleInterface(w); + QAccessibleInterface *table2; + client->navigate(QAccessible::Child, 1, &table2); + QVERIFY(table2); + QCOMPARE(table2->role(1), QAccessible::Row); + QAccessibleInterface *toprow = 0; + table2->navigate(QAccessible::Child, 1, &toprow); + QVERIFY(toprow); + QCOMPARE(toprow->role(1), QAccessible::RowHeader); + QCOMPARE(toprow->role(2), QAccessible::ColumnHeader); + delete toprow; + + // call childAt() for each child until we reach the bottom, + // and do it for each row in the table + for (int y = 1; y < 5; ++y) { // this includes the special header + for (int x = 1; x < 6; ++x) { + QCOMPARE(client->role(), QAccessible::Client); + QRect globalRect = client->rect(); + QVERIFY(globalRect.isValid()); + // make sure we don't hit the vertical header ##### + QPoint p = globalRect.topLeft() + QPoint(8, 8); + p.ry() += 50 * (y - 1); + p.rx() += 100 * (x - 1); + int index = client->childAt(p.x(), p.y()); + QCOMPARE(index, 1); + QCOMPARE(client->role(index), QAccessible::Table); + + // navigate to table/viewport + QAccessibleInterface *table; + client->navigate(QAccessible::Child, index, &table); + QVERIFY(table); + index = table->childAt(p.x(), p.y()); + QCOMPARE(index, y); + QCOMPARE(table->role(index), QAccessible::Row); + QAccessibleInterface *row; + QCOMPARE(table->role(1), QAccessible::Row); + + // navigate to the row + table->navigate(QAccessible::Child, index, &row); + QVERIFY(row); + QCOMPARE(row->role(1), QAccessible::RowHeader); + index = row->childAt(p.x(), p.y()); + QVERIFY(index > 0); + if (x == 1 && y == 1) { + QCOMPARE(row->role(index), QAccessible::RowHeader); + QCOMPARE(row->text(QAccessible::Name, index), QLatin1String("")); + } else if (x > 1 && y > 1) { + QCOMPARE(row->role(index), QAccessible::Cell); + QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("[%1,%2,0]").arg(y - 2).arg(x - 2)); + } else if (x == 1) { + QCOMPARE(row->role(index), QAccessible::RowHeader); + QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("%1").arg(y - 1)); + } else if (y == 1) { + QCOMPARE(row->role(index), QAccessible::ColumnHeader); + QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("%1").arg(x - 1)); + } + delete table; + delete row; + } + } + delete table2; + delete client; + delete w; + delete model; + } + QTestAccessibility::clearEvents(); +} + +#else +// Test accessible table2 interface on unix + +void tst_QAccessibility::table2ListTest() +{ + QListWidget *listView = new QListWidget; + listView->addItem("Oslo"); + listView->addItem("Berlin"); + listView->addItem("Brisbane"); + listView->resize(400,400); + listView->show(); + QTest::qWait(1); // Need this for indexOfchild to work. + QCoreApplication::processEvents(); + QTest::qWait(100); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QCOMPARE(verifyHierarchy(iface), 0); + + QCOMPARE((int)iface->role(), (int)QAccessible::List); + QCOMPARE(iface->childCount(), 3); + + QAccessibleInterface *child1 = 0; + child1 = iface->child(0); + QVERIFY(child1); + QCOMPARE(iface->indexOfChild(child1), 1); + QCOMPARE(child1->text(QAccessible::Name, 0), QString("Oslo")); + QCOMPARE(child1->role(), QAccessible::ListItem); + delete child1; + + QAccessibleInterface *child2 = 0; + child2 = iface->child(1); + QVERIFY(child2); + QCOMPARE(iface->indexOfChild(child2), 2); + QCOMPARE(child2->text(QAccessible::Name, 0), QString("Berlin")); + delete child2; + + QAccessibleInterface *child3 = 0; + child3 = iface->child(2); + QVERIFY(child3); + QCOMPARE(iface->indexOfChild(child3), 3); + QCOMPARE(child3->text(QAccessible::Name, 0), QString("Brisbane")); + delete child3; + QTestAccessibility::clearEvents(); + + // Check for events + QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus))); + QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus))); + + listView->addItem("Munich"); + QCOMPARE(iface->childCount(), 4); + + // table 2 + QAccessibleTable2Interface *table2 = iface->table2Interface(); + QVERIFY(table2); + QCOMPARE(table2->columnCount(), 1); + QCOMPARE(table2->rowCount(), 4); + QAccessibleTable2CellInterface *cell1; + QVERIFY(cell1 = table2->cellAt(0,0)); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Oslo")); + QAccessibleTable2CellInterface *cell4; + QVERIFY(cell4 = table2->cellAt(3,0)); + QCOMPARE(cell4->text(QAccessible::Name, 0), QString("Munich")); + QCOMPARE(cell4->role(), QAccessible::ListItem); + QCOMPARE(cell4->rowIndex(), 3); + QCOMPARE(cell4->columnIndex(), 0); + QVERIFY(!cell4->isExpandable()); + + delete cell4; + delete cell1; + delete iface; + delete listView; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::table2TreeTest() +{ + QTreeWidget *treeView = new QTreeWidget; + treeView->setColumnCount(2); + QTreeWidgetItem *header = new QTreeWidgetItem; + header->setText(0, "Artist"); + header->setText(1, "Work"); + treeView->setHeaderItem(header); + + QTreeWidgetItem *root1 = new QTreeWidgetItem; + root1->setText(0, "Spain"); + treeView->addTopLevelItem(root1); + + QTreeWidgetItem *item1 = new QTreeWidgetItem; + item1->setText(0, "Picasso"); + item1->setText(1, "Guernica"); + root1->addChild(item1); + + QTreeWidgetItem *item2 = new QTreeWidgetItem; + item2->setText(0, "Tapies"); + item2->setText(1, "Ambrosia"); + root1->addChild(item2); + + QTreeWidgetItem *root2 = new QTreeWidgetItem; + root2->setText(0, "Austria"); + treeView->addTopLevelItem(root2); + + QTreeWidgetItem *item3 = new QTreeWidgetItem; + item3->setText(0, "Klimt"); + item3->setText(1, "The Kiss"); + root2->addChild(item3); + + treeView->resize(400,400); + treeView->show(); + + QCoreApplication::processEvents(); + QTest::qWait(100); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView); + QCOMPARE(verifyHierarchy(iface), 0); + + QCOMPARE((int)iface->role(), (int)QAccessible::Tree); + // header and 2 rows (the others are not expanded, thus not visible) + QCOMPARE(iface->childCount(), 6); + + QAccessibleInterface *header1 = 0; + header1 = iface->child(0); + QVERIFY(header1); + QCOMPARE(iface->indexOfChild(header1), 1); + QCOMPARE(header1->text(QAccessible::Name, 0), QString("Artist")); + QCOMPARE(header1->role(), QAccessible::ColumnHeader); + delete header1; + + QAccessibleInterface *child1 = 0; + child1 = iface->child(2); + QVERIFY(child1); + QCOMPARE(iface->indexOfChild(child1), 3); + QCOMPARE(child1->text(QAccessible::Name, 0), QString("Spain")); + QCOMPARE(child1->role(), QAccessible::TreeItem); + QVERIFY(!(child1->state() & QAccessible::Expanded)); + delete child1; + + QAccessibleInterface *child2 = 0; + child2 = iface->child(4); + QVERIFY(child2); + QCOMPARE(iface->indexOfChild(child2), 5); + QCOMPARE(child2->text(QAccessible::Name, 0), QString("Austria")); + delete child2; + + QTestAccessibility::clearEvents(); + + // table 2 + QAccessibleTable2Interface *table2 = iface->table2Interface(); + QVERIFY(table2); + QCOMPARE(table2->columnCount(), 2); + QCOMPARE(table2->rowCount(), 2); + QAccessibleTable2CellInterface *cell1; + QVERIFY(cell1 = table2->cellAt(0,0)); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Spain")); + QAccessibleTable2CellInterface *cell2; + QVERIFY(cell2 = table2->cellAt(1,0)); + QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Austria")); + QCOMPARE(cell2->role(), QAccessible::TreeItem); + QCOMPARE(cell2->rowIndex(), 1); + QCOMPARE(cell2->columnIndex(), 0); + QVERIFY(cell2->isExpandable()); + QCOMPARE(iface->indexOfChild(cell2), 5); + QVERIFY(!(cell2->state() & QAccessible::Expanded)); + QCOMPARE(table2->columnDescription(1), QString("Work")); + delete cell2; + delete cell1; + + treeView->expandAll(); + + // Need this for indexOfchild to work. + QCoreApplication::processEvents(); + QTest::qWait(100); + + QCOMPARE(table2->columnCount(), 2); + QCOMPARE(table2->rowCount(), 5); + cell1 = table2->cellAt(1,0); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Picasso")); + QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item + + cell2 = table2->cellAt(4,0); + QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Klimt")); + QCOMPARE(cell2->role(), QAccessible::TreeItem); + QCOMPARE(cell2->rowIndex(), 4); + QCOMPARE(cell2->columnIndex(), 0); + QVERIFY(!cell2->isExpandable()); + QCOMPARE(iface->indexOfChild(cell2), 11); + + QCOMPARE(table2->columnDescription(0), QString("Artist")); + QCOMPARE(table2->columnDescription(1), QString("Work")); + + delete iface; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::table2TableTest() +{ + QTableWidget *tableView = new QTableWidget(3, 3); + tableView->setColumnCount(3); + QStringList hHeader; + hHeader << "h1" << "h2" << "h3"; + tableView->setHorizontalHeaderLabels(hHeader); + + QStringList vHeader; + vHeader << "v1" << "v2" << "v3"; + tableView->setVerticalHeaderLabels(vHeader); + + for (int i = 0; i<9; ++i) { + QTableWidgetItem *item = new QTableWidgetItem; + item->setText(QString::number(i/3) + QString(".") + QString::number(i%3)); + tableView->setItem(i/3, i%3, item); + } + + tableView->resize(600,600); + tableView->show(); + QTest::qWait(1); // Need this for indexOfchild to work. + QCoreApplication::processEvents(); + QTest::qWait(100); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView); + QCOMPARE(verifyHierarchy(iface), 0); + + QCOMPARE((int)iface->role(), (int)QAccessible::Table); + // header and 2 rows (the others are not expanded, thus not visible) + QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button + + QAccessibleInterface *cornerButton = iface->child(0); + QVERIFY(cornerButton); + QCOMPARE(iface->indexOfChild(cornerButton), 1); + QCOMPARE(cornerButton->role(), QAccessible::Pane); + delete cornerButton; + + QAccessibleInterface *child1 = iface->child(2); + QVERIFY(child1); + QCOMPARE(iface->indexOfChild(child1), 3); + QCOMPARE(child1->text(QAccessible::Name, 0), QString("h2")); + QCOMPARE(child1->role(), QAccessible::ColumnHeader); + QVERIFY(!(child1->state() & QAccessible::Expanded)); + delete child1; + + QAccessibleInterface *child2 = iface->child(10); + QVERIFY(child2); + QCOMPARE(iface->indexOfChild(child2), 11); + QCOMPARE(child2->text(QAccessible::Name, 0), QString("1.1")); + QAccessibleTable2CellInterface *cell2Iface = static_cast(child2); + QCOMPARE(cell2Iface->rowIndex(), 1); + QCOMPARE(cell2Iface->columnIndex(), 1); + delete child2; + + QAccessibleInterface *child3 = iface->child(11); + QCOMPARE(iface->indexOfChild(child3), 12); + QCOMPARE(child3->text(QAccessible::Name, 0), QString("1.2")); + delete child3; + + QTestAccessibility::clearEvents(); + + // table 2 + QAccessibleTable2Interface *table2 = iface->table2Interface(); + QVERIFY(table2); + QCOMPARE(table2->columnCount(), 3); + QCOMPARE(table2->rowCount(), 3); + QAccessibleTable2CellInterface *cell1; + QVERIFY(cell1 = table2->cellAt(0,0)); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("0.0")); + QCOMPARE(iface->indexOfChild(cell1), 6); + + QAccessibleTable2CellInterface *cell2; + QVERIFY(cell2 = table2->cellAt(0,1)); + QCOMPARE(cell2->text(QAccessible::Name, 0), QString("0.1")); + QCOMPARE(cell2->role(), QAccessible::Cell); + QCOMPARE(cell2->rowIndex(), 0); + QCOMPARE(cell2->columnIndex(), 1); + QCOMPARE(iface->indexOfChild(cell2), 7); + delete cell2; + + QAccessibleTable2CellInterface *cell3; + QVERIFY(cell3 = table2->cellAt(1,2)); + QCOMPARE(cell3->text(QAccessible::Name, 0), QString("1.2")); + QCOMPARE(cell3->role(), QAccessible::Cell); + QCOMPARE(cell3->rowIndex(), 1); + QCOMPARE(cell3->columnIndex(), 2); + QCOMPARE(iface->indexOfChild(cell3), 12); + delete cell3; + + QCOMPARE(table2->columnDescription(0), QString("h1")); + QCOMPARE(table2->columnDescription(1), QString("h2")); + QCOMPARE(table2->columnDescription(2), QString("h3")); + QCOMPARE(table2->rowDescription(0), QString("v1")); + QCOMPARE(table2->rowDescription(1), QString("v2")); + QCOMPARE(table2->rowDescription(2), QString("v3")); + + delete iface; + + delete tableView; + + QTestAccessibility::clearEvents(); +} +#endif + +void tst_QAccessibility::calendarWidgetTest() +{ +#ifndef QT_NO_CALENDARWIDGET + { + QCalendarWidget calendarWidget; + + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget); + QVERIFY(interface); + QCOMPARE(interface->role(), QAccessible::Table); + QVERIFY(!interface->rect().isValid()); + QVERIFY(!interface->rect(1).isValid()); + QCOMPARE(interface->childAt(200, 200), -1); + + calendarWidget.resize(400, 300); + calendarWidget.show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + + // 1 = navigationBar, 2 = view. + QCOMPARE(interface->childCount(), 2); + + const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)), + calendarWidget.size()); + QCOMPARE(interface->rect(), globalGeometry); + + QWidget *navigationBar = 0; + foreach (QObject *child, calendarWidget.children()) { + if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) { + navigationBar = static_cast(child); + break; + } + } + QVERIFY(navigationBar); + QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry)); + + QAbstractItemView *calendarView = 0; + foreach (QObject *child, calendarWidget.children()) { + if (child->objectName() == QLatin1String("qt_calendar_calendarview")) { + calendarView = static_cast(child); + break; + } + } + QVERIFY(calendarView); + QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry)); + + // Hide navigation bar. + calendarWidget.setNavigationBarVisible(false); + QCOMPARE(interface->childCount(), 1); + QVERIFY(!navigationBar->isVisible()); + + QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry)); + + // Show navigation bar. + calendarWidget.setNavigationBarVisible(true); + QCOMPARE(interface->childCount(), 2); + QVERIFY(navigationBar->isVisible()); + + // Navigate to the navigation bar via Child. + QAccessibleInterface *navigationBarInterface = interface->child(0); + QVERIFY(navigationBarInterface); + QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar); + delete navigationBarInterface; + navigationBarInterface = 0; + + // Navigate to the view via Child. + QAccessibleInterface *calendarViewInterface = interface->child(1); + QVERIFY(calendarViewInterface); + QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView); + delete calendarViewInterface; + calendarViewInterface = 0; + + QVERIFY(!interface->child(-1)); + + // Navigate from navigation bar -> view (Down). + QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0); + QVERIFY(calendarViewInterface); + QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView); + delete calendarViewInterface; + calendarViewInterface = 0; + + // Navigate from view -> navigation bar (Up). + QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0); + QVERIFY(navigationBarInterface); + QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar); + delete navigationBarInterface; + navigationBarInterface = 0; + + } + QTestAccessibility::clearEvents(); +#endif // QT_NO_CALENDARWIDGET +} + +void tst_QAccessibility::dockWidgetTest() +{ +#ifndef QT_NO_DOCKWIDGET + // Set up a proper main window with two dock widgets + QMainWindow *mw = new QMainWindow(); + QFrame *central = new QFrame(mw); + mw->setCentralWidget(central); + QMenuBar *mb = new QMenuBar(mw); + mb->addAction(tr("&File")); + mw->setMenuBar(mb); + + QDockWidget *dock1 = new QDockWidget(mw); + mw->addDockWidget(Qt::LeftDockWidgetArea, dock1); + QPushButton *pb1 = new QPushButton(tr("Push me"), dock1); + dock1->setWidget(pb1); + + QDockWidget *dock2 = new QDockWidget(mw); + mw->addDockWidget(Qt::BottomDockWidgetArea, dock2); + QPushButton *pb2 = new QPushButton(tr("Push me"), dock2); + dock2->setWidget(pb2); + + mw->resize(600,400); + mw->show(); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); + QTest::qWait(100); +#endif + + QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw); + // 4 children: menu bar, dock1, dock2, and central widget + QCOMPARE(accMainWindow->childCount(), 4); + QAccessibleInterface *accDock1 = 0; + for (int i = 1; i <= 4; ++i) { + if (accMainWindow->role(i) == QAccessible::Window) { + accDock1 = accMainWindow->child(i-1); + if (accDock1 && qobject_cast(accDock1->object()) == dock1) { + break; + } else { + delete accDock1; + } + } + } + QVERIFY(accDock1); + QCOMPARE(accDock1->role(), QAccessible::Window); + QCOMPARE(accDock1->role(1), QAccessible::TitleBar); + QVERIFY(accDock1->rect().contains(accDock1->rect(1))); + + QPoint globalPos = dock1->mapToGlobal(QPoint(0,0)); + globalPos.rx()+=5; //### query style + globalPos.ry()+=5; + int entry = accDock1->childAt(globalPos.x(), globalPos.y()); //### + QCOMPARE(entry, 1); + QAccessibleInterface *accTitleBar = accDock1->child(entry - 1); + + QCOMPARE(accTitleBar->role(), QAccessible::TitleBar); + QCOMPARE(accDock1->indexOfChild(accTitleBar), 1); + QAccessibleInterface *acc; + acc = accTitleBar->parent(); + QVERIFY(acc); + QCOMPARE(acc->role(), QAccessible::Window); + + + delete accTitleBar; + delete accDock1; + delete pb1; + delete pb2; + delete dock1; + delete dock2; + delete mw; + QTestAccessibility::clearEvents(); +#endif // QT_NO_DOCKWIDGET +} + +void tst_QAccessibility::comboBoxTest() +{ +#if defined(Q_OS_WINCE) + if (!IsValidCEPlatform()) { + QSKIP("Test skipped on Windows Mobile test hardware", SkipAll); + } +#endif + { // not editable combobox + QComboBox combo; + combo.addItems(QStringList() << "one" << "two" << "three"); + combo.show(); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo); + QCOMPARE(verifyHierarchy(iface), 0); + + QCOMPARE(iface->role(), QAccessible::ComboBox); + QCOMPARE(iface->childCount(), 1); + +#ifdef Q_OS_UNIX + QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one")); +#endif + QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one")); + combo.setCurrentIndex(2); +#ifdef Q_OS_UNIX + QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three")); +#endif + QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three")); + + QAccessibleInterface *listIface = iface->child(0); + QCOMPARE(listIface->role(), QAccessible::List); + QCOMPARE(listIface->childCount(), 3); + + QVERIFY(!combo.view()->isVisible()); + QVERIFY(iface->actionInterface()); + QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); + iface->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); + QVERIFY(combo.view()->isVisible()); + + delete iface; + } + + { // editable combobox + QComboBox editableCombo; + editableCombo.show(); + editableCombo.setEditable(true); + editableCombo.addItems(QStringList() << "foo" << "bar" << "baz"); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo); + QCOMPARE(verifyHierarchy(iface), 0); + + QCOMPARE(iface->role(), QAccessible::ComboBox); + QCOMPARE(iface->childCount(), 2); + + QAccessibleInterface *listIface = iface->child(0); + QCOMPARE(listIface->role(), QAccessible::List); + QAccessibleInterface *editIface = iface->child(1); + QCOMPARE(editIface->role(), QAccessible::EditableText); + + delete listIface; + delete editIface; + delete iface; + } + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::labelTest() +{ + QString text = "Hello World"; + QLabel *label = new QLabel(text); + label->show(); + +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); +#endif + QTest::qWait(100); + + QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label); + QVERIFY(acc_label); + + QCOMPARE(acc_label->text(QAccessible::Name, 0), text); + + delete acc_label; + delete label; + QTestAccessibility::clearEvents(); + + QPixmap testPixmap(50, 50); + testPixmap.fill(); + + QLabel imageLabel; + imageLabel.setPixmap(testPixmap); + imageLabel.setToolTip("Test Description"); + + acc_label = QAccessible::queryAccessibleInterface(&imageLabel); + QVERIFY(acc_label); + + QAccessibleImageInterface *imageInterface = acc_label->imageInterface(); + QVERIFY(imageInterface); + + QCOMPARE(imageInterface->imageSize(), testPixmap.size()); + QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description")); + QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry()); + + delete acc_label; + + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::accelerators() +{ + QWidget *window = new QWidget; + QHBoxLayout *lay = new QHBoxLayout(window); + QLabel *label = new QLabel(tr("&Line edit"), window); + QLineEdit *le = new QLineEdit(window); + lay->addWidget(label); + lay->addWidget(le); + label->setBuddy(le); + + window->show(); + + QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L")); + label->setText(tr("Q &")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); + label->setText(tr("Q &&")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); + label->setText(tr("Q && A")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); + label->setText(tr("Q &&&A")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A")); + label->setText(tr("Q &&A")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); + +#if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC) + QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'"); +#endif + label->setText(tr("Q &A&B")); + QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A")); + +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); +#endif + QTest::qWait(100); + delete window; + QTestAccessibility::clearEvents(); +} + +QTEST_MAIN(tst_QAccessibility) +#include "tst_qaccessibility.moc" diff --git a/tests/auto/integrationtests/qcomplextext/.gitignore b/tests/auto/integrationtests/qcomplextext/.gitignore new file mode 100644 index 0000000000..8929cd2f89 --- /dev/null +++ b/tests/auto/integrationtests/qcomplextext/.gitignore @@ -0,0 +1 @@ +tst_qcomplextext diff --git a/tests/auto/integrationtests/qcomplextext/bidireorderstring.h b/tests/auto/integrationtests/qcomplextext/bidireorderstring.h new file mode 100644 index 0000000000..e0bbf6e80b --- /dev/null +++ b/tests/auto/integrationtests/qcomplextext/bidireorderstring.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +struct LV { + const char *name; + const char *logical; + const char *visual; + int basicDir; +}; + +const LV logical_visual[] = { + { "data0", "Hello", "Hello", QChar::DirL }, + { "data1", "\327\251\327\234\327\225\327\235", "\327\235\327\225\327\234\327\251", QChar::DirR }, + { "data2", "Hello \327\251\327\234\327\225\327\235", "Hello \327\235\327\225\327\234\327\251", QChar::DirL }, + { "data3", "car is \327\236\327\233\327\225\327\240\327\231\327\252 \327\220\327\225\327\230\327\225 in hebrew", "car is \327\225\327\230\327\225\327\220 \327\252\327\231\327\240\327\225\327\233\327\236 in hebrew", QChar::DirL }, + { "data4", "\327\236\327\233\327\225\327\240\327\231\327\252 \327\224\327\231\327\220 the car \327\221\327\251\327\244\327\224 \327\224\327\220\327\240\327\222\327\234\327\231\327\252", "\327\252\327\231\327\234\327\222\327\240\327\220\327\224 \327\224\327\244\327\251\327\221 the car \327\220\327\231\327\224 \327\252\327\231\327\240\327\225\327\233\327\236", QChar::DirR }, + { "data5", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 123, 456, \327\221\327\241\327\223\327\250\" ", "he said \"\327\250\327\223\327\241\327\221 ,456 ,123 \327\224\327\225\327\225\327\251 \327\224\327\226\" ", QChar::DirL }, + { "data6", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 (123, 456), \327\221\327\241\327\223\327\250\"", "he said \"\327\250\327\223\327\241\327\221 ,(456 ,123) \327\224\327\225\327\225\327\251 \327\224\327\226\"", QChar::DirL }, + { "data7", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 123,456, \327\221\327\241\327\223\327\250\"", "he said \"\327\250\327\223\327\241\327\221 ,123,456 \327\224\327\225\327\225\327\251 \327\224\327\226\"", QChar::DirL }, + { "data8", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 ,(123,456) \327\221\327\241\327\223\327\250\"", "he said \"\327\250\327\223\327\241\327\221 (123,456), \327\224\327\225\327\225\327\251 \327\224\327\226\"", QChar::DirL }, + { "data9", "\327\224\327\225\327\220 \327\220\327\236\327\250 \"it is 123, 456, ok\"", "\"it is 123, 456, ok\" \327\250\327\236\327\220 \327\220\327\225\327\224", QChar::DirR }, + { "data10", "<\327\233123>shalom", "<123\327\233/>shalom<123\327\233>", QChar::DirR }, + { "data11", "\327\251\327\234\327\225\327\235", "\327\235\327\225\327\234\327\251", QChar::DirL }, + { "data12", "\327\224\327\225\327\220 \327\220\327\236\327\250 \"it is a car!\" \327\225\327\220\327\226 \327\250\327\245", "\327\245\327\250 \327\226\327\220\327\225 \"!it is a car\" \327\250\327\236\327\220 \327\220\327\225\327\224", QChar::DirR }, + { "data13", "\327\224\327\225\327\220 \327\220\327\236\327\250 \"it is a car!x\" \327\225\327\220\327\226 \327\250\327\245", "\327\245\327\250 \327\226\327\220\327\225 \"it is a car!x\" \327\250\327\236\327\220 \327\220\327\225\327\224", QChar::DirR }, + { "data14", "-2 \327\236\327\242\327\234\327\225\327\252 \327\226\327\224 \327\247\327\250", "\327\250\327\247 \327\224\327\226 \327\252\327\225\327\234\327\242\327\236 2-", QChar::DirR }, + { "data15", "-10% \327\251\327\231\327\240\327\225\327\231", "\327\231\327\225\327\240\327\231\327\251 10%-", QChar::DirR }, + { "data16", "\327\224\327\230\327\225\327\225\327\227 \327\224\327\231\327\240\327\225 2.5..5", "5..2.5 \327\225\327\240\327\231\327\224 \327\227\327\225\327\225\327\230\327\224", QChar::DirR }, + { "data17", "he said \"\327\226\327\225 \327\236\327\233\327\225\327\240\327\231\327\252!\"", "he said \"\327\252\327\231\327\240\327\225\327\233\327\236 \327\225\327\226!\"", QChar::DirL }, + { "data18", "he said \"\327\226\327\225 \327\236\327\233\327\225\327\240\327\231\327\252!\327\251\"", "he said \"\327\251!\327\252\327\231\327\240\327\225\327\233\327\236 \327\225\327\226\"", QChar::DirL }, + { "data19", "(\327\240\327\231\327\241\327\225\327\231) abc", "abc (\327\231\327\225\327\241\327\231\327\240)", QChar::DirR }, + { "data20", "abc (\327\240\327\231\327\241\327\225\327\231)", "abc (\327\231\327\225\327\241\327\231\327\240)", QChar::DirL }, + { "data21", "\327\240\327\231\327\241\327\225\327\231 23 \327\231\327\227\327\231\327\223 abc", "abc \327\223\327\231\327\227\327\231 23 \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, + { "data22", "#@$ \327\240\327\231\327\241\327\225\327\231", "\327\231\327\225\327\241\327\231\327\240 $@#", QChar::DirR }, + { "data23", "\327\240\327\231\327\241\327\225\327\231 ~~~23%%% \327\231\327\227\327\231\327\223 abc ", " abc \327\223\327\231\327\227\327\231 23%%%~~~ \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, + { "data24", "\327\240\327\231\327\241\327\225\327\231 abc ~~~23%%% \327\231\327\227\327\231\327\223 abc", "abc \327\223\327\231\327\227\327\231 abc ~~~23%%% \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, + { "data25", "\327\240\327\231\327\241\327\225\327\231 abc@23@cde \327\231\327\227\327\231\327\223", "\327\223\327\231\327\227\327\231 abc@23@cde \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, + { "data26", "\327\240\327\231\327\241\327\225\327\231 abc 23 cde \327\231\327\227\327\231\327\223", "\327\223\327\231\327\227\327\231 abc 23 cde \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, + { "data27", "\327\240\327\231\327\241\327\225\327\231 abc 23 \327\231\327\227\327\231\327\223 cde", "cde \327\223\327\231\327\227\327\231 abc 23 \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, + { "data28", "\327\222a 2 \327\251", "\327\251 a 2\327\222", QChar::DirR }, + { "data29", "\327\244\327\252\327\225\327\250 1*5 1-5 1/5 1+5", "1+5 1/5 1-5 5*1 \327\250\327\225\327\252\327\244", QChar::DirR }, + { "data30", "\330\272 1*5 1-5 1/5 1+5", "5+1 1/5 5-1 5*1 \330\272", QChar::DirR }, + { "data31", "\330\250 \333\261\333\262.\333\263", "\333\261\333\262.\333\263 \330\250", QChar::DirR }, + { "data32", "\330\250 12.3", "12.3 \330\250", QChar::DirR }, + { "data33", "\330\250 1.23", "1.23 \330\250", QChar::DirR }, + { "data34", "\331\276 \333\261.\333\262\333\263", "\333\261.\333\262\333\263 \331\276", QChar::DirR }, + { "data35", "\331\276\333\261.\333\262\333\263", "\333\261.\333\262\333\263\331\276", QChar::DirR }, + { "data36", "1) \327\251", "\327\251 (1", QChar::DirR }, + { "data37", "1) \327\251", "1) \327\251", QChar::DirL }, + { "data38", "\327\224-w3c", "w3c-\327\224", QChar::DirR }, + { "data39", "\327\224-w3c", "\327\224-w3c", QChar::DirL }, + { "data40", "17:25, foo", "17:25, foo", QChar::DirL }, + { "data41", "5, foo", "foo ,5", QChar::DirR }, + { "data42", "foo\nfoo", "foo\nfoo", QChar::DirL }, + { "data43", "\327\251\327\234\327\225\327\235\n\327\251\327\234\327\225\327\235", "\327\235\327\225\327\234\327\251\n\327\235\327\225\327\234\327\251", QChar::DirR }, + { "data44", "foo\n\327\251\327\234\327\225\327\235", "foo\n\327\235\327\225\327\234\327\251", QChar::DirL }, + { "data45", "\327\251\327\234\327\225\327\235\nfoo", "\327\235\327\225\327\234\327\251\nfoo", QChar::DirR }, + { "data46", "\330\250 1.23 \330\250", "\330\250 1.23 \330\250", QChar::DirR }, + { "data47", "\331\204\330\250 1.23 \331\202\330\250", "\330\250\331\202 1.23 \330\250\331\204", QChar::DirR }, + { "data48", "\330\250 1.2 \330\250", "\330\250 1.2 \330\250", QChar::DirR }, + { "data49", "\331\204\330\250 1.2 \331\202\330\250", "\330\250\331\202 1.2 \330\250\331\204", QChar::DirR }, + { "data50", "a\331\204\330\250 1.2 \331\202\330\250", "a\330\250\331\202 1.2 \330\250\331\204", QChar::DirL }, + + { "data51", "ab(\327\240\327\231)cd", "ab(\327\231\327\240)cd", QChar::DirL }, + { "data52", "ab(\327\240\327\231)cd", "cd(\327\231\327\240)ab", QChar::DirR }, + { "data53", "a(\327\231)c", "a(\327\231)c", QChar::DirL }, + { "data54", "a(\327\231)c", "c(\327\231)a", QChar::DirR }, + { "data55", "\"[\327\220]\"", "\"[\327\220]\"", QChar::DirR }, + { "data56", "\"[\327\220]\"", "\"[\327\220]\"", QChar::DirL }, + { "data57", "\331\204\330\250 \331\202\330\250", "\330\250\331\202 \330\250\331\204", QChar::DirR }, + { "data58", "\331\204\330\250 \331\202\330\250", "\330\250\331\202 \330\250\331\204", QChar::DirL }, + { "data59", "3layout", "3layout", QChar::DirL }, + { "data60", "3layout", "3layout", QChar::DirR }, + { "data61", "3l", "3l", QChar::DirR }, + { "data62", "3la", "3la", QChar::DirR }, + { "data63", "3lay", "3lay", QChar::DirR }, + +// explicit levels +// LRE: \342\200\252 +// RLE: \342\200\253 +// PDF: \342\200\254 +// LRO: \342\200\255 +// RLO: \342\200\256 + + { "override1", "\342\200\256hello\342\200\254", "\342\200\254olleh\342\200\256", QChar::DirL }, + { "override2", "\342\200\255hello\342\200\254", "\342\200\255hello\342\200\254", QChar::DirL }, + { "override3", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", QChar::DirL }, + { "override4", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\256", QChar::DirL }, + { "override5", "\342\200\256hello\342\200\254", "\342\200\254olleh\342\200\256", QChar::DirR }, + { "override6", "\342\200\255hello\342\200\254", "\342\200\255hello\342\200\254", QChar::DirR }, + { "override7", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", QChar::DirR }, + { "override8", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\256", QChar::DirR }, + + { "override9", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\342\200\254olleh\342\200\256\327\225\327\235\342\200\254\327\224", QChar::DirL }, + { "override10", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\342\200\254olleh\342\200\256\327\225\327\235\342\200\254\327\224", QChar::DirR }, + + + { "embed1", "\342\200\252hello\342\200\254", "\342\200\252hello\342\200\254", QChar::DirL }, + { "embed2", "\342\200\253hello\342\200\254", "\342\200\254hello\342\200\253", QChar::DirL }, + { "embed3", "\342\200\252hello\342\200\254", "\342\200\252hello\342\200\254", QChar::DirR }, + { "embed4", "\342\200\253hello\342\200\254", "\342\200\254hello\342\200\253", QChar::DirR }, + { "embed5", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\252\327\235\327\225\327\234\327\251\342\200\254", QChar::DirL }, + { "embed6", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\253", QChar::DirL }, + { "embed7", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\252\327\235\327\225\327\234\327\251\342\200\254", QChar::DirR }, + { "embed8", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\253", QChar::DirR }, + + { "embed9", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirL }, + { "embed10", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirL }, + { "embed11", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirR }, + { "embed12", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirR }, + { "zwsp", "+0\342\200\213f-1", "+0\342\200\213f-1", QChar::DirL }, + + { 0, 0, 0, QChar::DirON } +}; diff --git a/tests/auto/integrationtests/qcomplextext/qcomplextext.pro b/tests/auto/integrationtests/qcomplextext/qcomplextext.pro new file mode 100644 index 0000000000..e04ebcbc69 --- /dev/null +++ b/tests/auto/integrationtests/qcomplextext/qcomplextext.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +QT += widgets widgets-private +QT += core-private gui-private +SOURCES += tst_qcomplextext.cpp +INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src diff --git a/tests/auto/integrationtests/qcomplextext/tst_qcomplextext.cpp b/tests/auto/integrationtests/qcomplextext/tst_qcomplextext.cpp new file mode 100644 index 0000000000..c72393cfe6 --- /dev/null +++ b/tests/auto/integrationtests/qcomplextext/tst_qcomplextext.cpp @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +// Horrible hack, but this get this out of the way for now +// Carlos Duclos, 2007-12-11 +#if !defined(Q_WS_MAC) + +#include +#include +#include + +#include "bidireorderstring.h" + + +//TESTED_CLASS= +//TESTED_FILES=gui/widgets/qcombobox.h gui/widgets/qcombobox.cpp + +class tst_QComplexText : public QObject +{ +Q_OBJECT + +public: + tst_QComplexText(); + virtual ~tst_QComplexText(); + + +public slots: + void init(); + void cleanup(); +private slots: + void bidiReorderString_data(); + void bidiReorderString(); + void bidiCursor_qtbug2795(); + void bidiCursor_PDF(); + void bidiCursorMovement_data(); + void bidiCursorMovement(); + void bidiCursorLogicalMovement_data(); + void bidiCursorLogicalMovement(); +}; + +tst_QComplexText::tst_QComplexText() +{ +} + +tst_QComplexText::~tst_QComplexText() +{ + +} + +void tst_QComplexText::init() +{ +// This will be executed immediately before each test is run. +// TODO: Add initialization code here. +} + +void tst_QComplexText::cleanup() +{ +// This will be executed immediately after each test is run. +// TODO: Add cleanup code here. +} + +void tst_QComplexText::bidiReorderString_data() +{ + QTest::addColumn("logical"); + QTest::addColumn("VISUAL"); + QTest::addColumn("basicDir"); + + const LV *data = logical_visual; + while ( data->name ) { + //next we fill it with data + QTest::newRow( data->name ) + << QString::fromUtf8( data->logical ) + << QString::fromUtf8( data->visual ) + << (int) data->basicDir; + data++; + } +} + +void tst_QComplexText::bidiReorderString() +{ + QFETCH( QString, logical ); + QFETCH( int, basicDir ); + + // replace \n with Unicode newline. The new algorithm ignores \n + logical.replace(QChar('\n'), QChar(0x2028)); + + QTextEngine e(logical, QFont()); + e.option.setTextDirection((QChar::Direction)basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); + e.itemize(); + quint8 levels[256]; + int visualOrder[256]; + int nitems = e.layoutData->items.size(); + int i; + for (i = 0; i < nitems; ++i) { + //qDebug("item %d bidiLevel=%d", i, e.items[i].analysis.bidiLevel); + levels[i] = e.layoutData->items[i].analysis.bidiLevel; + } + e.bidiReorder(nitems, levels, visualOrder); + + QString visual; + for (i = 0; i < nitems; ++i) { + QScriptItem &si = e.layoutData->items[visualOrder[i]]; + QString sub = logical.mid(si.position, e.length(visualOrder[i])); + if (si.analysis.bidiLevel % 2) { + // reverse sub + QChar *a = (QChar *)sub.unicode(); + QChar *b = a + sub.length() - 1; + while (a < b) { + QChar tmp = *a; + *a = *b; + *b = tmp; + ++a; + --b; + } + a = (QChar *)sub.unicode(); + b = a + sub.length(); + while (amirroredChar(); + ++a; + } + } + visual += sub; + } + // replace Unicode newline back with \n to compare. + visual.replace(QChar(0x2028), QChar('\n')); + + QTEST(visual, "VISUAL"); +} + +void tst_QComplexText::bidiCursor_qtbug2795() +{ + QString str = QString::fromUtf8("الجزيرة نت"); + QTextLayout l1(str); + + l1.beginLayout(); + QTextLine line1 = l1.createLine(); + l1.endLayout(); + + qreal x1 = line1.cursorToX(0) - line1.cursorToX(str.size()); + + str.append("1"); + QTextLayout l2(str); + l2.beginLayout(); + QTextLine line2 = l2.createLine(); + l2.endLayout(); + + qreal x2 = line2.cursorToX(0) - line2.cursorToX(str.size()); + + // The cursor should remain at the same position after a digit is appended + QVERIFY(x1 == x2); +} + +void tst_QComplexText::bidiCursorMovement_data() +{ + QTest::addColumn("logical"); + QTest::addColumn("basicDir"); + + const LV *data = logical_visual; + while ( data->name ) { + //next we fill it with data + QTest::newRow( data->name ) + << QString::fromUtf8( data->logical ) + << (int) data->basicDir; + data++; + } +} + +void tst_QComplexText::bidiCursorMovement() +{ + QFETCH(QString, logical); + QFETCH(int, basicDir); + + QTextLayout layout(logical); + + QTextOption option = layout.textOption(); + option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); + layout.setTextOption(option); + layout.setCursorMoveStyle(Qt::VisualMoveStyle); + bool moved; + int oldPos, newPos = 0; + qreal x, newX; + + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + newX = line.cursorToX(0); + do { + oldPos = newPos; + x = newX; + newX = line.cursorToX(oldPos); + if (basicDir == QChar::DirL) { + QVERIFY(newX >= x); + newPos = layout.rightCursorPosition(oldPos); + } else + { + QVERIFY(newX <= x); + newPos = layout.leftCursorPosition(oldPos); + } + moved = (oldPos != newPos); + } while (moved); +} + +void tst_QComplexText::bidiCursorLogicalMovement_data() +{ + bidiCursorMovement_data(); +} + +void tst_QComplexText::bidiCursorLogicalMovement() +{ + QFETCH(QString, logical); + QFETCH(int, basicDir); + + QTextLayout layout(logical); + + QTextOption option = layout.textOption(); + option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); + layout.setTextOption(option); + bool moved; + int oldPos, newPos = 0; + + do { + oldPos = newPos; + newPos = layout.nextCursorPosition(oldPos); + QVERIFY(newPos >= oldPos); + moved = (oldPos != newPos); + } while (moved); + + do { + oldPos = newPos; + newPos = layout.previousCursorPosition(oldPos); + QVERIFY(newPos <= oldPos); + moved = (oldPos != newPos); + } while (moved); +} + +void tst_QComplexText::bidiCursor_PDF() +{ + QString str = QString::fromUtf8("\342\200\252hello\342\200\254"); + QTextLayout layout(str); + + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + int size = str.size(); + + QVERIFY(line.cursorToX(size) == line.cursorToX(size - 1)); +} + +QTEST_MAIN(tst_QComplexText) +#include "tst_qcomplextext.moc" + +#endif // Q_WS_MAC + diff --git a/tests/auto/integrationtests/qdirectpainter/.gitignore b/tests/auto/integrationtests/qdirectpainter/.gitignore new file mode 100644 index 0000000000..615dfa8ddc --- /dev/null +++ b/tests/auto/integrationtests/qdirectpainter/.gitignore @@ -0,0 +1,2 @@ +tst_qdirectpainter +runDirectPainter/runDirectPainter diff --git a/tests/auto/integrationtests/qdirectpainter/qdirectpainter.pro b/tests/auto/integrationtests/qdirectpainter/qdirectpainter.pro new file mode 100644 index 0000000000..e86b3427eb --- /dev/null +++ b/tests/auto/integrationtests/qdirectpainter/qdirectpainter.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs +SUBDIRS = test runDirectPainter + +requires(embedded) + diff --git a/tests/auto/integrationtests/qdirectpainter/runDirectPainter/main.cpp b/tests/auto/integrationtests/qdirectpainter/runDirectPainter/main.cpp new file mode 100644 index 0000000000..af3dd90beb --- /dev/null +++ b/tests/auto/integrationtests/qdirectpainter/runDirectPainter/main.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ +#ifdef Q_WS_QWS + QApplication app(argc, argv); + QDirectPainter dp; + QImage screenImage(dp.frameBuffer(), dp.screenWidth(), dp.screenHeight(), + dp.linestep(), QScreen::instance()->pixelFormat()); + QPainter p; + + QStringList args = app.arguments(); + + dp.setRegion(QRect(args.at(1).toInt(), + args.at(2).toInt(), + args.at(3).toInt(), + args.at(4).toInt())); + + for (;;) { + dp.startPainting(); + p.begin(&screenImage); + p.setPen(Qt::NoPen); + p.setBrush(Qt::blue); + p.drawRects(dp.allocatedRegion().rects()); + p.end(); + dp.endPainting(dp.allocatedRegion()); + app.processEvents(); + } +#else + Q_UNUSED(argc); + Q_UNUSED(argv); +#endif + + return 0; +} + diff --git a/tests/auto/integrationtests/qdirectpainter/runDirectPainter/runDirectPainter.pro b/tests/auto/integrationtests/qdirectpainter/runDirectPainter/runDirectPainter.pro new file mode 100644 index 0000000000..09524e90c3 --- /dev/null +++ b/tests/auto/integrationtests/qdirectpainter/runDirectPainter/runDirectPainter.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES = main.cpp +TARGET = runDirectPainter + +requires(embedded) + diff --git a/tests/auto/integrationtests/qdirectpainter/test/test.pro b/tests/auto/integrationtests/qdirectpainter/test/test.pro new file mode 100644 index 0000000000..3621e11fa9 --- /dev/null +++ b/tests/auto/integrationtests/qdirectpainter/test/test.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +QT += widgets +SOURCES += ../tst_qdirectpainter.cpp +TARGET = ../tst_qdirectpainter + +requires(embedded) + diff --git a/tests/auto/integrationtests/qdirectpainter/tst_qdirectpainter.cpp b/tests/auto/integrationtests/qdirectpainter/tst_qdirectpainter.cpp new file mode 100644 index 0000000000..550c2e96c0 --- /dev/null +++ b/tests/auto/integrationtests/qdirectpainter/tst_qdirectpainter.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** 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 + +//TESTED_CLASS= +//TESTED_FILES= + +#include +#include +#include +#include +#include +#include + +class tst_QDirectPainter : public QObject +{ + Q_OBJECT + +public: + tst_QDirectPainter() {} + ~tst_QDirectPainter() {} + +private slots: + void initTestCase(); + void setGeometry_data(); + void setGeometry(); +#ifndef QT_NO_PROCESS + void regionSynchronization(); +#endif + void reservedSynchronous(); + +private: + QWSWindow* getWindow(int windId); + QColor bgColor; +}; + +class ColorPainter : public QDirectPainter +{ +public: + ColorPainter(SurfaceFlag flag = NonReserved, + const QColor &color = QColor(Qt::red)) + : QDirectPainter(0, flag), c(color) {} + + QColor color() { return c; } + +protected: + void regionChanged(const QRegion ®ion) { + QScreen::instance()->solidFill(c, region); + } + +private: + QColor c; + QRegion r; +}; + +Q_DECLARE_METATYPE(QDirectPainter::SurfaceFlag) + +void tst_QDirectPainter::initTestCase() +{ + bgColor = QColor(Qt::green); + + QWSServer *server = QWSServer::instance(); + server->setBackground(bgColor); +} + +QWSWindow* tst_QDirectPainter::getWindow(int winId) +{ + QWSServer *server = QWSServer::instance(); + foreach (QWSWindow *w, server->clientWindows()) { + if (w->winId() == winId) + return w; + } + return 0; +} + +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(rect, color) { \ + 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.fill(color); \ + QCOMPARE(pixmap, expectedPixmap); \ +} + +void tst_QDirectPainter::setGeometry_data() +{ + QTest::addColumn("flag"); + + QTest::newRow("NonReserved") << QDirectPainter::NonReserved; + QTest::newRow("Reserved") << QDirectPainter::Reserved; + QTest::newRow("ReservedSynchronous") << QDirectPainter::ReservedSynchronous; +} + +void tst_QDirectPainter::setGeometry() +{ + QFETCH(QDirectPainter::SurfaceFlag, flag); + + const QRect rect(100, 100, 100, 100); + { + ColorPainter w(flag); + + w.setGeometry(rect); + QApplication::processEvents(); + QCOMPARE(w.geometry(), rect); + VERIFY_COLOR(rect, w.color()); + } + QApplication::processEvents(); + VERIFY_COLOR(rect, bgColor); +} + +#ifndef QT_NO_PROCESS +void tst_QDirectPainter::regionSynchronization() +{ + QRect dpRect(10, 10, 50, 50); + + // Start the direct painter in a different process + QProcess proc; + QStringList args; + args << QString::number(dpRect.x()) + << QString::number(dpRect.y()) + << QString::number(dpRect.width()) + << QString::number(dpRect.height()); + + proc.start("runDirectPainter/runDirectPainter", args); + QVERIFY(proc.waitForStarted(5 * 1000)); + QTest::qWait(1000); + QApplication::processEvents(); + VERIFY_COLOR(dpRect, Qt::blue); // blue hardcoded in runDirectPainter + + QTime t; + t.start(); + static int i = 0; + while (t.elapsed() < 10 * 1000) { + QApplication::processEvents(); + + ColorWidget w; + w.setGeometry(10, 10, 50, 50); + const QRect wRect = dpRect.translated(10, 0); + w.setGeometry(wRect); + w.show(); + + QApplication::processEvents(); + QApplication::processEvents(); //glib event loop workaround + VERIFY_COLOR(wRect, w.color); + ++i; + } + QVERIFY(i > 100); // sanity check + + proc.kill(); +} +#endif + +class MyObject : public QObject +{ +public: + MyObject(QObject *p = 0) : QObject(p), lastEvent(0) {} + + bool event(QEvent *e) { + lastEvent = e; + return true; + } + + QEvent *lastEvent; +}; + +void tst_QDirectPainter::reservedSynchronous() +{ + MyObject o; + QCoreApplication::postEvent(&o, new QEvent(QEvent::None)); + QDirectPainter p(0, QDirectPainter::ReservedSynchronous); + p.setRegion(QRect(5, 5, 50, 50)); + + // The event loop should not have been executed + QVERIFY(o.lastEvent == 0); + QCOMPARE(p.allocatedRegion(), QRegion(QRect(5, 5, 50, 50))); +} + +QTEST_MAIN(tst_QDirectPainter) + +#include "tst_qdirectpainter.moc" diff --git a/tests/auto/integrationtests/qfocusevent/.gitignore b/tests/auto/integrationtests/qfocusevent/.gitignore new file mode 100644 index 0000000000..f189d8aeb9 --- /dev/null +++ b/tests/auto/integrationtests/qfocusevent/.gitignore @@ -0,0 +1 @@ +tst_qfocusevent diff --git a/tests/auto/integrationtests/qfocusevent/qfocusevent.pro b/tests/auto/integrationtests/qfocusevent/qfocusevent.pro new file mode 100644 index 0000000000..d904a0b0bf --- /dev/null +++ b/tests/auto/integrationtests/qfocusevent/qfocusevent.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_qfocusevent.cpp diff --git a/tests/auto/integrationtests/qfocusevent/tst_qfocusevent.cpp b/tests/auto/integrationtests/qfocusevent/tst_qfocusevent.cpp new file mode 100644 index 0000000000..931059b211 --- /dev/null +++ b/tests/auto/integrationtests/qfocusevent/tst_qfocusevent.cpp @@ -0,0 +1,395 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QWidget) + +//TESTED_CLASS= +//TESTED_FILES=gui/kernel/qevent.h gui/kernel/qevent.cpp + +class FocusLineEdit : public QLineEdit +{ +public: + FocusLineEdit( QWidget* parent = 0, const char* name = 0 ) : QLineEdit(name, parent) {} + int focusInEventReason; + int focusOutEventReason; + bool focusInEventRecieved; + bool focusInEventGotFocus; + bool focusOutEventRecieved; + bool focusOutEventLostFocus; +protected: + virtual void keyPressEvent( QKeyEvent *e ) + { +// qDebug( QString("keyPressEvent: %1").arg(e->key()) ); + QLineEdit::keyPressEvent( e ); + } + void focusInEvent( QFocusEvent* e ) + { + QLineEdit::focusInEvent( e ); + focusInEventReason = e->reason(); + focusInEventGotFocus = e->gotFocus(); + focusInEventRecieved = TRUE; + } + void focusOutEvent( QFocusEvent* e ) + { + QLineEdit::focusOutEvent( e ); + focusOutEventReason = e->reason(); + focusOutEventLostFocus = !e->gotFocus(); + focusOutEventRecieved = TRUE; + } +}; + +class tst_QFocusEvent : public QObject +{ + Q_OBJECT + +public: + tst_QFocusEvent(); + virtual ~tst_QFocusEvent(); + + + void initWidget(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); +private slots: + void checkReason_Tab(); + void checkReason_ShiftTab(); +#ifndef Q_OS_WIN32 + void checkReason_BackTab(); +#endif + void checkReason_Popup(); + void checkReason_focusWidget(); + void checkReason_Shortcut(); + void checkReason_ActiveWindow(); + +private: + QWidget* testFocusWidget; + FocusLineEdit* childFocusWidgetOne; + FocusLineEdit* childFocusWidgetTwo; +}; + +tst_QFocusEvent::tst_QFocusEvent() +{ +} + +tst_QFocusEvent::~tst_QFocusEvent() +{ + +} + +void tst_QFocusEvent::initTestCase() +{ + testFocusWidget = new QWidget( 0 ); + childFocusWidgetOne = new FocusLineEdit( testFocusWidget ); + childFocusWidgetOne->setGeometry( 10, 10, 180, 20 ); + childFocusWidgetTwo = new FocusLineEdit( testFocusWidget ); + childFocusWidgetTwo->setGeometry( 10, 50, 180, 20 ); + + //qApp->setMainWidget( testFocusWidget ); Qt4 + testFocusWidget->resize( 200,100 ); + testFocusWidget->show(); +// Applications don't get focus when launched from the command line on Mac. +#ifdef Q_WS_MAC + testFocusWidget->raise(); +#endif +} + +void tst_QFocusEvent::cleanupTestCase() +{ + delete testFocusWidget; +} + +void tst_QFocusEvent::init() +{ +} + +void tst_QFocusEvent::cleanup() +{ + childFocusWidgetTwo->setGeometry( 10, 50, 180, 20 ); +} + +void tst_QFocusEvent::initWidget() +{ + // On X11 we have to ensure the event was processed before doing any checking, on Windows + // this is processed straight away. + QApplication::setActiveWindow(childFocusWidgetOne); + + for (int i = 0; i < 1000; ++i) { + if (childFocusWidgetOne->isActiveWindow() && childFocusWidgetOne->hasFocus()) + break; + childFocusWidgetOne->activateWindow(); + childFocusWidgetOne->setFocus(); + qApp->processEvents(); + QTest::qWait(100); + } + + // The first lineedit should have focus + QVERIFY( childFocusWidgetOne->hasFocus() ); + + childFocusWidgetOne->focusInEventRecieved = FALSE; + childFocusWidgetOne->focusInEventGotFocus = FALSE; + childFocusWidgetOne->focusInEventReason = -1; + childFocusWidgetOne->focusOutEventRecieved = FALSE; + childFocusWidgetOne->focusOutEventLostFocus = FALSE; + childFocusWidgetOne->focusOutEventReason = -1; + childFocusWidgetTwo->focusInEventRecieved = FALSE; + childFocusWidgetTwo->focusInEventGotFocus = FALSE; + childFocusWidgetTwo->focusInEventReason = -1; + childFocusWidgetTwo->focusOutEventRecieved = FALSE; + childFocusWidgetTwo->focusOutEventLostFocus = FALSE; + childFocusWidgetTwo->focusOutEventReason = -1; +} + +void tst_QFocusEvent::checkReason_Tab() +{ + initWidget(); + + // Now test the tab key + QTest::keyClick( childFocusWidgetOne, Qt::Key_Tab ); + + QVERIFY(childFocusWidgetOne->focusOutEventRecieved); + QVERIFY(childFocusWidgetTwo->focusInEventRecieved); + QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); + QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); + + QVERIFY( childFocusWidgetTwo->hasFocus() ); + QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int) Qt::TabFocusReason ); + QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int) Qt::TabFocusReason ); +} + +void tst_QFocusEvent::checkReason_ShiftTab() +{ + initWidget(); + + // Now test the shift + tab key + QTest::keyClick( childFocusWidgetOne, Qt::Key_Tab, Qt::ShiftModifier ); + + QVERIFY(childFocusWidgetOne->focusOutEventRecieved); + QVERIFY(childFocusWidgetTwo->focusInEventRecieved); + QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); + QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); + + QVERIFY( childFocusWidgetTwo->hasFocus() ); + QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::BacktabFocusReason ); + QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int)Qt::BacktabFocusReason ); + +} + +/*! + In this test we verify that the Qt::KeyBacktab key is handled in a qfocusevent +*/ +// Backtab is not supported on Windows. +#ifndef Q_OS_WIN32 +void tst_QFocusEvent::checkReason_BackTab() +{ + initWidget(); + QVERIFY( childFocusWidgetOne->hasFocus() ); + + // Now test the backtab key + QTest::keyClick( childFocusWidgetOne, Qt::Key_Backtab ); + QTest::qWait(200); + + QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved); + QVERIFY(childFocusWidgetTwo->focusInEventRecieved); + QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); + QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); + + QVERIFY( childFocusWidgetTwo->hasFocus() ); + QCOMPARE( childFocusWidgetOne->focusOutEventReason, int(Qt::BacktabFocusReason) ); + QCOMPARE( childFocusWidgetTwo->focusInEventReason, int(Qt::BacktabFocusReason) ); +} +#endif + +void tst_QFocusEvent::checkReason_Popup() +{ + initWidget(); + + // Now test the popup reason + QMenu* popupMenu = new QMenu( testFocusWidget ); + popupMenu->addMenu( "Test" ); + popupMenu->popup( QPoint(0,0) ); + QTest::qWait(50); + + QTRY_VERIFY(childFocusWidgetOne->focusOutEventLostFocus); + + QTRY_VERIFY( childFocusWidgetOne->hasFocus() ); + QVERIFY( !childFocusWidgetOne->focusInEventRecieved ); + QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); + QVERIFY( !childFocusWidgetTwo->focusInEventRecieved ); + QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved ); + QCOMPARE( childFocusWidgetOne->focusOutEventReason, int(Qt::PopupFocusReason)); + + popupMenu->hide(); + + QVERIFY(childFocusWidgetOne->focusInEventRecieved); + QVERIFY(childFocusWidgetOne->focusInEventGotFocus); + + QVERIFY( childFocusWidgetOne->hasFocus() ); + QVERIFY( childFocusWidgetOne->focusInEventRecieved ); + QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); + QVERIFY( !childFocusWidgetTwo->focusInEventRecieved ); + QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved ); +} + +#ifdef Q_WS_MAC +QT_BEGIN_NAMESPACE + extern void qt_set_sequence_auto_mnemonic(bool); +QT_END_NAMESPACE +#endif + +void tst_QFocusEvent::checkReason_Shortcut() +{ + initWidget(); +#ifdef Q_WS_MAC + qt_set_sequence_auto_mnemonic(true); +#endif + QLabel* label = new QLabel( "&Test", testFocusWidget ); + label->setBuddy( childFocusWidgetTwo ); + label->setGeometry( 10, 50, 90, 20 ); + childFocusWidgetTwo->setGeometry( 105, 50, 95, 20 ); + label->show(); + + QVERIFY( childFocusWidgetOne->hasFocus() ); + QVERIFY( !childFocusWidgetTwo->hasFocus() ); + + QTest::keyClick( label, Qt::Key_T, Qt::AltModifier ); + + QVERIFY(childFocusWidgetOne->focusOutEventRecieved); + QVERIFY(childFocusWidgetTwo->focusInEventRecieved); + QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); + QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); + + QVERIFY( childFocusWidgetTwo->hasFocus() ); + QVERIFY( !childFocusWidgetOne->focusInEventRecieved ); + QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); + QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::ShortcutFocusReason ); + QVERIFY( childFocusWidgetTwo->focusInEventRecieved ); + QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int)Qt::ShortcutFocusReason ); + QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved ); + + label->hide(); + QVERIFY( childFocusWidgetTwo->hasFocus() ); + QVERIFY( !childFocusWidgetOne->hasFocus() ); +#ifdef Q_WS_MAC + qt_set_sequence_auto_mnemonic(false); +#endif +} + +void tst_QFocusEvent::checkReason_focusWidget() +{ + // This test checks that a widget doesn't loose + // its focuswidget just because the focuswidget looses focus. + QWidget window1; + QWidget frame1; + QWidget frame2; + QLineEdit edit1; + QLineEdit edit2; + + QVBoxLayout outerLayout; + outerLayout.addWidget(&frame1); + outerLayout.addWidget(&frame2); + window1.setLayout(&outerLayout); + + QVBoxLayout leftLayout; + QVBoxLayout rightLayout; + leftLayout.addWidget(&edit1); + rightLayout.addWidget(&edit2); + frame1.setLayout(&leftLayout); + frame2.setLayout(&rightLayout); + window1.show(); + + edit1.setFocus(); + QTest::qWait(100); + edit2.setFocus(); + + QVERIFY(frame1.focusWidget() != 0); + QVERIFY(frame2.focusWidget() != 0); +} + +void tst_QFocusEvent::checkReason_ActiveWindow() +{ + initWidget(); + + QDialog* d = new QDialog( testFocusWidget ); + d->show(); + d->activateWindow(); // ### CDE + QApplication::setActiveWindow(d); + QTest::qWaitForWindowShown(d); + + QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved); + QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); + + QVERIFY( !childFocusWidgetOne->focusInEventRecieved ); + QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); + QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::ActiveWindowFocusReason); + QVERIFY( !childFocusWidgetOne->hasFocus() ); + + d->hide(); + QTest::qWait(100); + +#if defined(Q_OS_IRIX) + QEXPECT_FAIL("", "IRIX requires explicit activateWindow(), so this test does not make any sense.", Abort); +#endif + QTRY_VERIFY(childFocusWidgetOne->focusInEventRecieved); + QVERIFY(childFocusWidgetOne->focusInEventGotFocus); + + QVERIFY( childFocusWidgetOne->hasFocus() ); + QVERIFY( childFocusWidgetOne->focusInEventRecieved ); + QCOMPARE( childFocusWidgetOne->focusInEventReason, (int)Qt::ActiveWindowFocusReason); +} + + +QTEST_MAIN(tst_QFocusEvent) +#include "tst_qfocusevent.moc" diff --git a/tests/auto/integrationtests/qmultiscreen/.gitignore b/tests/auto/integrationtests/qmultiscreen/.gitignore new file mode 100644 index 0000000000..82e8d449ad --- /dev/null +++ b/tests/auto/integrationtests/qmultiscreen/.gitignore @@ -0,0 +1 @@ +tst_qmultiscreen diff --git a/tests/auto/integrationtests/qmultiscreen/qmultiscreen.pro b/tests/auto/integrationtests/qmultiscreen/qmultiscreen.pro new file mode 100644 index 0000000000..c4a983c5be --- /dev/null +++ b/tests/auto/integrationtests/qmultiscreen/qmultiscreen.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_qmultiscreen.cpp + +requires(embedded) + diff --git a/tests/auto/integrationtests/qmultiscreen/tst_qmultiscreen.cpp b/tests/auto/integrationtests/qmultiscreen/tst_qmultiscreen.cpp new file mode 100644 index 0000000000..9d74d59f85 --- /dev/null +++ b/tests/auto/integrationtests/qmultiscreen/tst_qmultiscreen.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** 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 + +//TESTED_CLASS= +//TESTED_FILES= + +#include +#include +#include +#include + +class tst_QMultiScreen : public QObject +{ + Q_OBJECT + +public: + tst_QMultiScreen() : screen(0), oldScreen(0) {} + ~tst_QMultiScreen() {} + +private slots: + void initTestCase(); + void cleanupTestCase(); + void widgetSetFixedSize(); + void grabWindow(); + +private: + QScreen *screen; + QScreen *oldScreen; +}; + +void tst_QMultiScreen::cleanupTestCase() +{ + screen->shutdownDevice(); + screen->disconnect(); + delete screen; + screen = 0; + + qt_screen = oldScreen; +} + +void tst_QMultiScreen::initTestCase() +{ + oldScreen = qt_screen; + + QVERIFY(QScreenDriverFactory::keys().contains(QLatin1String("Multi"))); + QVERIFY(QScreenDriverFactory::keys().contains(QLatin1String("VNC"))); + + const int id = 10; + screen = QScreenDriverFactory::create("Multi", id); + QVERIFY(screen); + QVERIFY(screen->connect(QString("Multi: " + "VNC:size=640x480:depth=32:offset=0,0:%1 " + "VNC:size=640x480:depth=32:offset=640,0:%2 " + "VNC:size=640x480:depth=16:offset=0,480:%3 " + ":%4") + .arg(id+1).arg(id+2).arg(id+3).arg(id))); + QVERIFY(screen->initDevice()); + + QDesktopWidget desktop; + QCOMPARE(desktop.numScreens(), 3); +} + +void tst_QMultiScreen::widgetSetFixedSize() +{ + QDesktopWidget desktop; + QRect maxRect; + for (int i = 0; i < desktop.numScreens(); ++i) + maxRect |= desktop.availableGeometry(i); + + maxRect = maxRect.adjusted(50, 50, -50, -50); + + // make sure we can set a size larger than a single screen (task 166368) + QWidget w; + w.setFixedSize(maxRect.size()); + w.show(); + QApplication::processEvents(); + QCOMPARE(w.geometry().size(), maxRect.size()); +} + +void tst_QMultiScreen::grabWindow() +{ + QDesktopWidget desktop; + + QVERIFY(desktop.numScreens() >= 2); + + const QRect r0 = desktop.availableGeometry(0).adjusted(50, 50, -50, -50); + const QRect r1 = desktop.availableGeometry(1).adjusted(60, 60, -60, -60); + + QWidget w; + w.setGeometry(r0); + w.show(); + + QLabel l("hi there"); + l.setGeometry(r1); + l.show(); + + QApplication::processEvents(); + QApplication::sendPostedEvents(); // workaround for glib event loop + QVERIFY(desktop.screenNumber(&w) == 0); + QVERIFY(desktop.screenNumber(&l) == 1); + + const QPixmap p0 = QPixmap::grabWindow(w.winId()); + const QPixmap p1 = QPixmap::grabWindow(l.winId()); + +// p0.save("w.png", "PNG"); +// p1.save("l.png", "PNG"); + QCOMPARE(p0.size(), w.size()); + QCOMPARE(p1.size(), l.size()); + + const QImage img0 = p0.toImage(); + const QImage img1 = p1.toImage(); + +// QPixmap::grabWidget(&w).toImage().convertToFormat(img0.format()).save("w_img.png", "PNG"); +// QPixmap::grabWidget(&l).toImage().convertToFormat(img1.format()).save("l_img.png", "PNG"); + + QImage::Format format = QImage::Format_RGB16; + QCOMPARE(img0.convertToFormat(format), + QPixmap::grabWidget(&w).toImage().convertToFormat(format)); + QCOMPARE(img1.convertToFormat(format), + QPixmap::grabWidget(&l).toImage().convertToFormat(format)); +} + +QTEST_MAIN(tst_QMultiScreen) + +#include "tst_qmultiscreen.moc" diff --git a/tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro b/tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro new file mode 100644 index 0000000000..9e3fcf28ba --- /dev/null +++ b/tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +SOURCES += tst_qnetworkaccessmanager_and_qprogressdialog.cpp +QT += network widgets diff --git a/tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp b/tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp new file mode 100644 index 0000000000..abf5aa528c --- /dev/null +++ b/tests/auto/integrationtests/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include +#include +#include +#include + +#include "../../network-settings.h" + + +class tst_QNetworkAccessManager_And_QProgressDialog : public QObject +{ + Q_OBJECT +public: + tst_QNetworkAccessManager_And_QProgressDialog(); +private slots: + void downloadCheck(); + void downloadCheck_data(); +}; + +class DownloadCheckWidget : public QWidget +{ + Q_OBJECT +public: + DownloadCheckWidget(QWidget *parent = 0) : + QWidget(parent), lateReadyRead(true), zeroCopy(false), + progressDlg(this), netmanager(this) + { + progressDlg.setRange(1, 100); + QMetaObject::invokeMethod(this, "go", Qt::QueuedConnection); + } + bool lateReadyRead; + bool zeroCopy; +public slots: + void go() + { + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile")); + if (zeroCopy) + request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 10*1024*1024); + + QNetworkReply *reply = netmanager.get( + QNetworkRequest( + QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") + )); + connect(reply, SIGNAL(downloadProgress(qint64, qint64)), + this, SLOT(dataReadProgress(qint64, qint64))); + connect(reply, SIGNAL(readyRead()), + this, SLOT(dataReadyRead())); + connect(reply, SIGNAL(finished()), this, SLOT(finishedFromReply())); + + progressDlg.exec(); + } + void dataReadProgress(qint64 done, qint64 total) + { + QNetworkReply *reply = qobject_cast(sender()); + Q_UNUSED(reply); + progressDlg.setMaximum(total); + progressDlg.setValue(done); + } + void dataReadyRead() + { + QNetworkReply *reply = qobject_cast(sender()); + Q_UNUSED(reply); + lateReadyRead = true; + } + void finishedFromReply() + { + QNetworkReply *reply = qobject_cast(sender()); + lateReadyRead = false; + reply->deleteLater(); + QTestEventLoop::instance().exitLoop(); + } + +private: + QProgressDialog progressDlg; + QNetworkAccessManager netmanager; +}; + + +tst_QNetworkAccessManager_And_QProgressDialog::tst_QNetworkAccessManager_And_QProgressDialog() +{ +} + +void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck_data() +{ + QTest::addColumn("useZeroCopy"); + QTest::newRow("with-zeroCopy") << true; + QTest::newRow("without-zeroCopy") << false; +} + +void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck() +{ + QFETCH(bool, useZeroCopy); + + DownloadCheckWidget widget; + widget.zeroCopy = useZeroCopy; + widget.show(); + // run and exit on finished() + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + // run some more to catch the late readyRead() (or: to not catch it) + QTestEventLoop::instance().enterLoop(1); + QVERIFY(QTestEventLoop::instance().timeout()); + // the following fails when a readyRead() was received after finished() + QVERIFY(!widget.lateReadyRead); +} + + + +QTEST_MAIN(tst_QNetworkAccessManager_And_QProgressDialog) +#include "tst_qnetworkaccessmanager_and_qprogressdialog.moc" diff --git a/tests/auto/integrationtests/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro b/tests/auto/integrationtests/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro new file mode 100644 index 0000000000..c947e7a246 --- /dev/null +++ b/tests/auto/integrationtests/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_qsharedpointer_and_qwidget.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/integrationtests/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp b/tests/auto/integrationtests/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp new file mode 100644 index 0000000000..90b71c517c --- /dev/null +++ b/tests/auto/integrationtests/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.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 +#include +#include + +QT_BEGIN_NAMESPACE +namespace QtSharedPointer { + Q_CORE_EXPORT void internalSafetyCheckCleanCheck(); +} +QT_END_NAMESPACE + +class tst_QSharedPointer_and_QWidget: public QObject +{ + Q_OBJECT +private slots: + void weak_externalDelete(); + void weak_parentDelete(); + void weak_parentDelete_setParent(); + + void strong_weak(); + + void strong_sharedptrDelete(); + +public slots: + void cleanup() { check(); } + +public: + inline void check() + { +#ifdef QT_BUILD_INTERNAL + QtSharedPointer::internalSafetyCheckCleanCheck(); +#endif + } +}; + +void tst_QSharedPointer_and_QWidget::weak_externalDelete() +{ + QWidget *w = new QWidget; + QWeakPointer ptr = w; + + QVERIFY(!ptr.isNull()); + + delete w; + QVERIFY(ptr.isNull()); +} + +void tst_QSharedPointer_and_QWidget::weak_parentDelete() +{ + QWidget *parent = new QWidget; + QWidget *w = new QWidget(parent); + QWeakPointer ptr = w; + + QVERIFY(!ptr.isNull()); + + delete parent; + QVERIFY(ptr.isNull()); +} + +void tst_QSharedPointer_and_QWidget::weak_parentDelete_setParent() +{ + QWidget *parent = new QWidget; + QWidget *w = new QWidget; + QWeakPointer ptr = w; + w->setParent(parent); + + QVERIFY(!ptr.isNull()); + + delete parent; + QVERIFY(ptr.isNull()); +} + +// -- mixed -- + +void tst_QSharedPointer_and_QWidget::strong_weak() +{ + QSharedPointer ptr(new QWidget); + QWeakPointer weak = ptr.data(); + QWeakPointer weak2 = ptr; + + QVERIFY(!weak.isNull()); + QVERIFY(!weak2.isNull()); + + ptr.clear(); // deletes + + QVERIFY(weak.isNull()); + QVERIFY(weak2.isNull()); +} + + +// ---- strong management ---- + +void tst_QSharedPointer_and_QWidget::strong_sharedptrDelete() +{ + QWidget *parent = new QWidget; + QSharedPointer ptr(new QWidget(parent)); + QWeakPointer weak = ptr; + QPointer check = ptr.data(); + + QVERIFY(!check.isNull()); + QVERIFY(!weak.isNull()); + + ptr.clear(); // deletes + + QVERIFY(check.isNull()); + QVERIFY(weak.isNull()); + + delete parent; // mustn't crash +} + +QTEST_MAIN(tst_QSharedPointer_and_QWidget) + +#include "tst_qsharedpointer_and_qwidget.moc" diff --git a/tests/auto/integrationtests/windowsmobile/test/ddhelper.cpp b/tests/auto/integrationtests/windowsmobile/test/ddhelper.cpp new file mode 100644 index 0000000000..55469f5901 --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/test/ddhelper.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$ +** +****************************************************************************/ + +#ifdef Q_OS_WINCE_WM + +#include +#include + +static LPDIRECTDRAW g_pDD = NULL; // DirectDraw object +static LPDIRECTDRAWSURFACE g_pDDSSurface = NULL; // DirectDraw primary surface + +static DDSCAPS ddsCaps; +static DDSURFACEDESC ddsSurfaceDesc; +static void *buffer = NULL; + +static int width = 0; +static int height = 0; +static int pitch = 0; +static int bitCount = 0; +static int windowId = 0; + +static bool initialized = false; +static bool locked = false; + +void q_lock() +{ + if (locked) { + qWarning("Direct Painter already locked (QDirectPainter::lock())"); + return; + } + locked = true; + + + memset(&ddsSurfaceDesc, 0, sizeof(ddsSurfaceDesc)); + ddsSurfaceDesc.dwSize = sizeof(ddsSurfaceDesc); + + HRESULT h = g_pDDSSurface->Lock(0, &ddsSurfaceDesc, DDLOCK_WRITEONLY, 0); + if (h != DD_OK) + qDebug() << "GetSurfaceDesc failed!"; + + width = ddsSurfaceDesc.dwWidth; + height = ddsSurfaceDesc.dwHeight; + bitCount = ddsSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; + pitch = ddsSurfaceDesc.lPitch; + buffer = ddsSurfaceDesc.lpSurface; +} + +void q_unlock() +{ + if( !locked) { + qWarning("Direct Painter not locked (QDirectPainter::unlock()"); + return; + } + g_pDDSSurface->Unlock(0); + locked = false; +} + +void q_initDD() +{ + if (initialized) + return; + + DirectDrawCreate(NULL, &g_pDD, NULL); + + HRESULT h; + h = g_pDD->SetCooperativeLevel(0, DDSCL_NORMAL); + + if (h != DD_OK) + qDebug() << "cooperation level failed"; + + h = g_pDD->TestCooperativeLevel(); + if (h != DD_OK) + qDebug() << "cooperation level failed test"; + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS; + + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + h = g_pDD->CreateSurface(&ddsd, &g_pDDSSurface, NULL); + + if (h != DD_OK) + qDebug() << "CreateSurface failed!"; + + if (g_pDDSSurface->GetCaps(&ddsCaps) != DD_OK) + qDebug() << "GetCaps failed"; + + q_lock(); + q_unlock(); + initialized = true; +} + +uchar* q_frameBuffer() +{ + return (uchar*) buffer; +} + +int q_screenDepth() +{ + return bitCount; +} + +int q_screenWidth() +{ + return width; +} + +int q_screenHeight() +{ + return height; +} + +int q_linestep() +{ + return pitch; +} + +#endif //Q_OS_WINCE_WM + + diff --git a/tests/auto/integrationtests/windowsmobile/test/ddhelper.h b/tests/auto/integrationtests/windowsmobile/test/ddhelper.h new file mode 100644 index 0000000000..3d2f06aa36 --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/test/ddhelper.h @@ -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$ +** +****************************************************************************/ + +#ifndef __DDHELPER__ +#define __DDHELPER__ + +extern uchar* q_frameBuffer(); + +extern int q_screenDepth(); + +extern int q_screenWidth(); + +extern int q_screenHeight(); + +extern int q_linestep(); + +extern void q_initDD(); + +extern void q_unlock(); + +extern void q_lock(); + +#endif //__DDHELPER__ + diff --git a/tests/auto/integrationtests/windowsmobile/test/test.pro b/tests/auto/integrationtests/windowsmobile/test/test.pro new file mode 100644 index 0000000000..595a619d2a --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/test/test.pro @@ -0,0 +1,23 @@ + +load(qttest_p4) +QT += widgets +HEADERS += ddhelper.h +SOURCES += tst_windowsmobile.cpp ddhelper.cpp +RESOURCES += windowsmobile.qrc + +TARGET = ../tst_windowsmobile + +wincewm*: { + addFiles.files = $$OUT_PWD/../testQMenuBar/*.exe + + + addFiles.path = "\\Program Files\\tst_windowsmobile" + DEPLOYMENT += addFiles +} + +wincewm*: { + LIBS += Ddraw.lib +} + + + diff --git a/tests/auto/integrationtests/windowsmobile/test/testQMenuBar_current.png b/tests/auto/integrationtests/windowsmobile/test/testQMenuBar_current.png new file mode 100644 index 0000000000..f0042b8fe0 Binary files /dev/null and b/tests/auto/integrationtests/windowsmobile/test/testQMenuBar_current.png differ diff --git a/tests/auto/integrationtests/windowsmobile/test/testSimpleWidget_current.png b/tests/auto/integrationtests/windowsmobile/test/testSimpleWidget_current.png new file mode 100644 index 0000000000..8086c41ce9 Binary files /dev/null and b/tests/auto/integrationtests/windowsmobile/test/testSimpleWidget_current.png differ diff --git a/tests/auto/integrationtests/windowsmobile/test/tst_windowsmobile.cpp b/tests/auto/integrationtests/windowsmobile/test/tst_windowsmobile.cpp new file mode 100644 index 0000000000..0dc7f578c1 --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/test/tst_windowsmobile.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include +#ifdef Q_OS_WINCE_WM +#include +#include "ddhelper.h" +#endif + + + +class tst_WindowsMobile : public QObject +{ + Q_OBJECT +public: + tst_WindowsMobile() + { + qApp->setCursorFlashTime (24 * 3600 * 1000); // once a day + // qApp->setCursorFlashTime (INT_MAX); +#ifdef Q_OS_WINCE_WM + q_initDD(); +#endif + } + +#if defined(Q_OS_WINCE_WM) && defined(_WIN32_WCE) && _WIN32_WCE <= 0x501 + private slots: + void testMainWindowAndMenuBar(); + void testSimpleWidget(); +#endif +}; + +#if defined(Q_OS_WINCE_WM) && defined(_WIN32_WCE) && _WIN32_WCE <= 0x501 + +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 (platformString.utf16()), tszPlatform)) + return true; + return false; +} + +bool qt_wince_is_smartphone() { + return qt_wince_is_platform(QString::fromLatin1("Smartphone")); +} + +void openMenu() +{ + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,450,630,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,450,630,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,55535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,55535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,58535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,58535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,40535,55535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,40535,55535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,32535,55535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,32535,55535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,50535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,50535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,40535,0,0); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,40535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,48535,45535,0,0); + QTest::qWait(2000); + ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,48535,45535,0,0); +} + +void compareScreenshots(const QString &image1, const QString &image2) +{ + QImage screenShot(image1); + QImage original(image2); + + // cut away the title bar before comparing + QDesktopWidget desktop; + QRect desktopFrameRect = desktop.frameGeometry(); + QRect desktopClientRect = desktop.availableGeometry(); + + QPainter p1(&screenShot); + QPainter p2(&original); + + //screenShot.save("scr1.png", "PNG"); + p1.fillRect(0, 0, desktopFrameRect.width(), desktopClientRect.y(), Qt::black); + p2.fillRect(0, 0, desktopFrameRect.width(), desktopClientRect.y(), Qt::black); + + //screenShot.save("scr2.png", "PNG"); + //original.save("orig1.png", "PNG"); + + QVERIFY(original == screenShot); +} + +void takeScreenShot(const QString filename) +{ + q_lock(); + QImage image = QImage(( uchar *) q_frameBuffer(), q_screenWidth(), + q_screenHeight(), q_screenWidth() * q_screenDepth() / 8, QImage::Format_RGB16); + image.save(filename, "PNG"); + q_unlock(); +} + +void tst_WindowsMobile::testMainWindowAndMenuBar() +{ + if (qt_wince_is_smartphone()) + QSKIP("This test is only for Windows Mobile", SkipAll); + + QProcess process; + process.start("testQMenuBar.exe"); + QCOMPARE(process.state(), QProcess::Running); + QTest::qWait(6000); + openMenu(); + QTest::qWait(1000); + takeScreenShot("testQMenuBar_current.png"); + process.close(); + compareScreenshots("testQMenuBar_current.png", ":/testQMenuBar_current.png"); +} + +void tst_WindowsMobile::testSimpleWidget() +{ + if (qt_wince_is_smartphone()) + QSKIP("This test is only for Windows Mobile", SkipAll); + + QMenuBar menubar; + menubar.show(); + QWidget maximized; + QPalette pal = maximized.palette(); + pal.setColor(QPalette::Background, Qt::red); + maximized.setPalette(pal); + maximized.showMaximized(); + QWidget widget; + widget.setGeometry(100, 100, 200, 200); + widget.setWindowTitle("Widget"); + widget.show(); + qApp->processEvents(); + QTest::qWait(1000); + + QWidget widget2; + widget2.setGeometry(100, 380, 300, 200); + widget2.setWindowTitle("Widget 2"); + widget2.setWindowFlags(Qt::Popup); + widget2.show(); + + qApp->processEvents(); + QTest::qWait(1000); + takeScreenShot("testSimpleWidget_current.png"); + compareScreenshots("testSimpleWidget_current.png", ":/testSimpleWidget_current.png"); +} + + +#endif //Q_OS_WINCE_WM + + +QTEST_MAIN(tst_WindowsMobile) +#include "tst_windowsmobile.moc" + diff --git a/tests/auto/integrationtests/windowsmobile/test/windowsmobile.qrc b/tests/auto/integrationtests/windowsmobile/test/windowsmobile.qrc new file mode 100644 index 0000000000..5d6f61459e --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/test/windowsmobile.qrc @@ -0,0 +1,6 @@ + + + testQMenuBar_current.png + testSimpleWidget_current.png + + diff --git a/tests/auto/integrationtests/windowsmobile/testQMenuBar/main.cpp b/tests/auto/integrationtests/windowsmobile/testQMenuBar/main.cpp new file mode 100644 index 0000000000..c2099a648b --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/testQMenuBar/main.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include +#include + +int main(int argc, char * argv[]) +{ + QList widgets; + QApplication app(argc, argv); + + QMainWindow mainWindow; + mainWindow.setWindowTitle("Test"); + QMenu *fileMenu = mainWindow.menuBar()->addMenu("File"); + QMenu *editMenu = mainWindow.menuBar()->addMenu("Edit"); + QMenu *viewMenu = mainWindow.menuBar()->addMenu("View"); + QMenu *toolsMenu = mainWindow.menuBar()->addMenu("Tools"); + QMenu *optionsMenu = mainWindow.menuBar()->addMenu("Options"); + QMenu *helpMenu = mainWindow.menuBar()->addMenu("Help"); + + qApp->processEvents(); + + fileMenu->addAction("Open"); + QAction *close = fileMenu->addAction("Close"); + fileMenu->addSeparator(); + fileMenu->addAction("Exit"); + + close->setEnabled(false); + + editMenu->addAction("Cut"); + editMenu->addAction("Pase"); + editMenu->addAction("Copy"); + editMenu->addSeparator(); + editMenu->addAction("Find"); + + viewMenu->addAction("Hide"); + viewMenu->addAction("Show"); + viewMenu->addAction("Explore"); + QAction *visible = viewMenu->addAction("Visible"); + visible->setCheckable(true); + visible->setChecked(true); + + toolsMenu->addMenu("Hammer"); + toolsMenu->addMenu("Caliper"); + toolsMenu->addMenu("Helm"); + + optionsMenu->addMenu("Settings"); + optionsMenu->addMenu("Standard"); + optionsMenu->addMenu("Extended"); + + QMenu *subMenu = helpMenu->addMenu("Help"); + subMenu->addAction("Index"); + subMenu->addSeparator(); + subMenu->addAction("Vodoo Help"); + helpMenu->addAction("Contens"); + helpMenu->addSeparator(); + helpMenu->addAction("About"); + + QToolBar toolbar; + mainWindow.addToolBar(&toolbar); + toolbar.addAction(QIcon(qApp->style()->standardPixmap(QStyle::SP_FileIcon)), QString("textAction")); + + QTextEdit textEdit; + mainWindow.setCentralWidget(&textEdit); + + mainWindow.showMaximized(); + + app.exec(); +} diff --git a/tests/auto/integrationtests/windowsmobile/testQMenuBar/testQMenuBar.pro b/tests/auto/integrationtests/windowsmobile/testQMenuBar/testQMenuBar.pro new file mode 100644 index 0000000000..6b84ae937c --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/testQMenuBar/testQMenuBar.pro @@ -0,0 +1,4 @@ +SOURCES += main.cpp +QT += widgets +TARGET = ../testQMenuBar + diff --git a/tests/auto/integrationtests/windowsmobile/windowsmobile.pro b/tests/auto/integrationtests/windowsmobile/windowsmobile.pro new file mode 100644 index 0000000000..2e6b444d7b --- /dev/null +++ b/tests/auto/integrationtests/windowsmobile/windowsmobile.pro @@ -0,0 +1,9 @@ + +TEMPLATE = subdirs + +wincewm* { + SUBDIRS = testQMenuBar +} + SUBDIRS += test + + diff --git a/tests/auto/lancelot/.gitignore b/tests/auto/lancelot/.gitignore deleted file mode 100644 index 0a70416d57..0000000000 --- a/tests/auto/lancelot/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_lancelot diff --git a/tests/auto/lancelot/images.qrc b/tests/auto/lancelot/images.qrc deleted file mode 100644 index 060b52c85a..0000000000 --- a/tests/auto/lancelot/images.qrc +++ /dev/null @@ -1,34 +0,0 @@ - - - - images/alpha.png - images/border.png - images/borderimage.png - images/dome_argb32.png - images/dome_indexed.png - images/dome_mono_palette.png - images/dome_rgb32.png - images/face.png - images/gam045.png - images/gam100.png - images/image.png - images/masked.png - images/sign.png - images/struct-image-01.jpg - images/bitmap.png - images/dome_indexed_mask.png - images/dome_mono_128.png - images/dome_mono.png - images/dot.png - images/gam030.png - images/gam056.png - images/gam200.png - images/mask_100.png - images/mask.png - images/solid.png - images/struct-image-01.png - images/zebra.png - images/alpha2x2.png - images/solid2x2.png - - diff --git a/tests/auto/lancelot/images/alpha.png b/tests/auto/lancelot/images/alpha.png deleted file mode 100644 index e465b2586d..0000000000 Binary files a/tests/auto/lancelot/images/alpha.png and /dev/null differ diff --git a/tests/auto/lancelot/images/alpha2x2.png b/tests/auto/lancelot/images/alpha2x2.png deleted file mode 100644 index 67ecc04286..0000000000 Binary files a/tests/auto/lancelot/images/alpha2x2.png and /dev/null differ diff --git a/tests/auto/lancelot/images/bitmap.png b/tests/auto/lancelot/images/bitmap.png deleted file mode 100644 index d21f8f51bb..0000000000 Binary files a/tests/auto/lancelot/images/bitmap.png and /dev/null differ diff --git a/tests/auto/lancelot/images/border.png b/tests/auto/lancelot/images/border.png deleted file mode 100644 index a3d2fed0a3..0000000000 Binary files a/tests/auto/lancelot/images/border.png and /dev/null differ diff --git a/tests/auto/lancelot/images/borderimage.png b/tests/auto/lancelot/images/borderimage.png deleted file mode 100644 index f7f6b66227..0000000000 Binary files a/tests/auto/lancelot/images/borderimage.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_argb32.png b/tests/auto/lancelot/images/dome_argb32.png deleted file mode 100644 index e3ccba0c13..0000000000 Binary files a/tests/auto/lancelot/images/dome_argb32.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_indexed.png b/tests/auto/lancelot/images/dome_indexed.png deleted file mode 100644 index beefcd514e..0000000000 Binary files a/tests/auto/lancelot/images/dome_indexed.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_indexed_mask.png b/tests/auto/lancelot/images/dome_indexed_mask.png deleted file mode 100644 index a62f29f40e..0000000000 Binary files a/tests/auto/lancelot/images/dome_indexed_mask.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_mono.png b/tests/auto/lancelot/images/dome_mono.png deleted file mode 100644 index 950c2a7494..0000000000 Binary files a/tests/auto/lancelot/images/dome_mono.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_mono_128.png b/tests/auto/lancelot/images/dome_mono_128.png deleted file mode 100644 index 77e48aaab7..0000000000 Binary files a/tests/auto/lancelot/images/dome_mono_128.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_mono_palette.png b/tests/auto/lancelot/images/dome_mono_palette.png deleted file mode 100644 index dca3f59245..0000000000 Binary files a/tests/auto/lancelot/images/dome_mono_palette.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dome_rgb32.png b/tests/auto/lancelot/images/dome_rgb32.png deleted file mode 100644 index 27bc02a545..0000000000 Binary files a/tests/auto/lancelot/images/dome_rgb32.png and /dev/null differ diff --git a/tests/auto/lancelot/images/dot.png b/tests/auto/lancelot/images/dot.png deleted file mode 100644 index 17a7b6a0ba..0000000000 Binary files a/tests/auto/lancelot/images/dot.png and /dev/null differ diff --git a/tests/auto/lancelot/images/face.png b/tests/auto/lancelot/images/face.png deleted file mode 100644 index 4f6172d83b..0000000000 Binary files a/tests/auto/lancelot/images/face.png and /dev/null differ diff --git a/tests/auto/lancelot/images/gam030.png b/tests/auto/lancelot/images/gam030.png deleted file mode 100644 index 904c9721bd..0000000000 Binary files a/tests/auto/lancelot/images/gam030.png and /dev/null differ diff --git a/tests/auto/lancelot/images/gam045.png b/tests/auto/lancelot/images/gam045.png deleted file mode 100644 index b649a8a54f..0000000000 Binary files a/tests/auto/lancelot/images/gam045.png and /dev/null differ diff --git a/tests/auto/lancelot/images/gam056.png b/tests/auto/lancelot/images/gam056.png deleted file mode 100644 index e5f959dc96..0000000000 Binary files a/tests/auto/lancelot/images/gam056.png and /dev/null differ diff --git a/tests/auto/lancelot/images/gam100.png b/tests/auto/lancelot/images/gam100.png deleted file mode 100644 index 6c7ba5f1ed..0000000000 Binary files a/tests/auto/lancelot/images/gam100.png and /dev/null differ diff --git a/tests/auto/lancelot/images/gam200.png b/tests/auto/lancelot/images/gam200.png deleted file mode 100644 index daa20fcbc4..0000000000 Binary files a/tests/auto/lancelot/images/gam200.png and /dev/null differ diff --git a/tests/auto/lancelot/images/image.png b/tests/auto/lancelot/images/image.png deleted file mode 100644 index 85d486a790..0000000000 Binary files a/tests/auto/lancelot/images/image.png and /dev/null differ diff --git a/tests/auto/lancelot/images/mask.png b/tests/auto/lancelot/images/mask.png deleted file mode 100644 index c3f3b1b6ca..0000000000 Binary files a/tests/auto/lancelot/images/mask.png and /dev/null differ diff --git a/tests/auto/lancelot/images/mask_100.png b/tests/auto/lancelot/images/mask_100.png deleted file mode 100644 index fc950dc7ed..0000000000 Binary files a/tests/auto/lancelot/images/mask_100.png and /dev/null differ diff --git a/tests/auto/lancelot/images/masked.png b/tests/auto/lancelot/images/masked.png deleted file mode 100644 index 6debec534d..0000000000 Binary files a/tests/auto/lancelot/images/masked.png and /dev/null differ diff --git a/tests/auto/lancelot/images/sign.png b/tests/auto/lancelot/images/sign.png deleted file mode 100644 index 6aac7e150a..0000000000 Binary files a/tests/auto/lancelot/images/sign.png and /dev/null differ diff --git a/tests/auto/lancelot/images/solid.png b/tests/auto/lancelot/images/solid.png deleted file mode 100644 index 371e9c1aee..0000000000 Binary files a/tests/auto/lancelot/images/solid.png and /dev/null differ diff --git a/tests/auto/lancelot/images/solid2x2.png b/tests/auto/lancelot/images/solid2x2.png deleted file mode 100644 index ad67cd3e12..0000000000 Binary files a/tests/auto/lancelot/images/solid2x2.png and /dev/null differ diff --git a/tests/auto/lancelot/images/struct-image-01.jpg b/tests/auto/lancelot/images/struct-image-01.jpg deleted file mode 100644 index a74e07223b..0000000000 Binary files a/tests/auto/lancelot/images/struct-image-01.jpg and /dev/null differ diff --git a/tests/auto/lancelot/images/struct-image-01.png b/tests/auto/lancelot/images/struct-image-01.png deleted file mode 100644 index 4ed08406dc..0000000000 Binary files a/tests/auto/lancelot/images/struct-image-01.png and /dev/null differ diff --git a/tests/auto/lancelot/images/zebra.png b/tests/auto/lancelot/images/zebra.png deleted file mode 100644 index ef35f20785..0000000000 Binary files a/tests/auto/lancelot/images/zebra.png and /dev/null differ diff --git a/tests/auto/lancelot/lancelot.pro b/tests/auto/lancelot/lancelot.pro deleted file mode 100644 index 5b61c32aa5..0000000000 --- a/tests/auto/lancelot/lancelot.pro +++ /dev/null @@ -1,15 +0,0 @@ -load(qttest_p4) -QT += xml widgets -contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2):QT += opengl - -SOURCES += tst_lancelot.cpp \ - paintcommands.cpp -HEADERS += paintcommands.h -RESOURCES += images.qrc - -include($$PWD/../../baselineserver/shared/qbaselinetest.pri) - -!wince*:DEFINES += SRCDIR=\\\"$$PWD\\\" -linux-g++-maemo:DEFINES += USE_RUNTIME_DIR - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/lancelot/paintcommands.cpp b/tests/auto/lancelot/paintcommands.cpp deleted file mode 100644 index 9659659973..0000000000 --- a/tests/auto/lancelot/paintcommands.cpp +++ /dev/null @@ -1,2590 +0,0 @@ -/**************************************************************************** -** -** 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 "paintcommands.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef QT_NO_OPENGL -#include -#endif - -/********************************************************************************* -** everything to populate static tables -**********************************************************************************/ -const char *PaintCommands::brushStyleTable[] = { - "NoBrush", - "SolidPattern", - "Dense1Pattern", - "Dense2Pattern", - "Dense3Pattern", - "Dense4Pattern", - "Dense5Pattern", - "Dense6Pattern", - "Dense7Pattern", - "HorPattern", - "VerPattern", - "CrossPattern", - "BDiagPattern", - "FDiagPattern", - "DiagCrossPattern", - "LinearGradientPattern" -}; - -const char *PaintCommands::penStyleTable[] = { - "NoPen", - "SolidLine", - "DashLine", - "DotLine", - "DashDotLine", - "DashDotDotLine" -}; - -const char *PaintCommands::fontWeightTable[] = { - "Light", - "Normal", - "DemiBold", - "Bold", - "Black" -}; - -const char *PaintCommands::fontHintingTable[] = { - "Default", - "None", - "Vertical", - "Full" -}; - -const char *PaintCommands::clipOperationTable[] = { - "NoClip", - "ReplaceClip", - "IntersectClip", - "UniteClip" -}; - -const char *PaintCommands::spreadMethodTable[] = { - "PadSpread", - "ReflectSpread", - "RepeatSpread" -}; - -const char *PaintCommands::coordinateMethodTable[] = { - "LogicalMode", - "StretchToDeviceMode", - "ObjectBoundingMode" -}; - -const char *PaintCommands::sizeModeTable[] = { - "AbsoluteSize", - "RelativeSize" -}; - -const char *PaintCommands::compositionModeTable[] = { - "SourceOver", - "DestinationOver", - "Clear", - "Source", - "Destination", - "SourceIn", - "DestinationIn", - "SourceOut", - "DestinationOut", - "SourceAtop", - "DestinationAtop", - "Xor", - "Plus", - "Multiply", - "Screen", - "Overlay", - "Darken", - "Lighten", - "ColorDodge", - "ColorBurn", - "HardLight", - "SoftLight", - "Difference", - "Exclusion", - "SourceOrDestination", - "SourceAndDestination", - "SourceXorDestination", - "NotSourceAndNotDestination", - "NotSourceOrNotDestination", - "NotSourceXorDestination", - "NotSource", - "NotSourceAndDestination", - "SourceAndNotDestination" -}; - -const char *PaintCommands::imageFormatTable[] = { - "Invalid", - "Mono", - "MonoLSB", - "Indexed8", - "RGB32", - "ARGB32", - "ARGB32_Premultiplied", - "Format_RGB16", - "Format_ARGB8565_Premultiplied", - "Format_RGB666", - "Format_ARGB6666_Premultiplied", - "Format_RGB555", - "Format_ARGB8555_Premultiplied", - "Format_RGB888", - "Format_RGB444", - "Format_ARGB4444_Premultiplied" -}; - -int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit) -{ - QByteArray p = pattern.toLatin1().toLower(); - for (int i=0; i PaintCommands::s_commandInfoTable = QList(); -QList > PaintCommands::s_enumsTable = QList >(); -QMultiHash PaintCommands::s_commandHash; - -#define DECL_PAINTCOMMAND(identifier, method, regexp, syntax, sample) \ - s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegExp(regexp), \ - QLatin1String(syntax), QLatin1String(sample) ); - -#define DECL_PAINTCOMMANDSECTION(title) \ - s_commandInfoTable << PaintCommandInfos(QLatin1String(title)); - -#define ADD_ENUMLIST(listCaption, cStrArray) { \ - QStringList list; \ - for (int i=0; i", - "import \"myfile.qrc\""); - DECL_PAINTCOMMAND("begin_block", command_begin_block, - "^begin_block\\s+(\\w*)$", - "begin_block ", - "begin_block blockName"); - DECL_PAINTCOMMAND("end_block", command_end_block, - "^end_block$", - "end_block", - "end_block"); - DECL_PAINTCOMMAND("repeat_block", command_repeat_block, - "^repeat_block\\s+(\\w*)$", - "repeat_block ", - "repeat_block blockName"); - DECL_PAINTCOMMAND("textlayout_draw", command_textlayout_draw, - "^textlayout_draw\\s+\"(.*)\"\\s+([0-9.]*)$", - "textlayout_draw ", - "textlayout_draw \"your text\" 1.0"); - DECL_PAINTCOMMAND("abort", command_abort, - "^abort$", - "abort", - "abort"); - DECL_PAINTCOMMAND("noop", command_noop, - "^$", - "-", - "\n"); - - DECL_PAINTCOMMANDSECTION("setters"); - DECL_PAINTCOMMAND("setBackgroundMode", command_setBgMode, - "^(setBackgroundMode|setBgMode)\\s+(\\w*)$", - "setBackgroundMode ", - "setBackgroundMode TransparentMode"); - DECL_PAINTCOMMAND("setBackground", command_setBackground, - "^setBackground\\s+#?(\\w*)\\s*(\\w*)?$", - "setBackground [brush style enum]", - "setBackground black SolidPattern"); - DECL_PAINTCOMMAND("setOpacity", command_setOpacity, - "^setOpacity\\s+(-?\\d*\\.?\\d*)$", - "setOpacity \n - opacity is in [0,1]", - "setOpacity 1.0"); - DECL_PAINTCOMMAND("path_setFillRule", command_path_setFillRule, - "^path_setFillRule\\s+(\\w*)\\s+(\\w*)$", - "path_setFillRule [Winding|OddEven]", - "path_setFillRule pathName Winding"); - DECL_PAINTCOMMAND("setBrush", command_setBrush, - "^setBrush\\s+(#?[\\w.:\\/]*)\\s*(\\w*)?$", - "setBrush \nsetBrush noBrush\nsetBrush ", - "setBrush white SolidPattern"); - DECL_PAINTCOMMAND("setBrushOrigin", command_setBrushOrigin, - "^setBrushOrigin\\s*(-?\\w*)\\s+(-?\\w*)$", - "setBrushOrigin ", - "setBrushOrigin 0 0"); - DECL_PAINTCOMMAND("brushTranslate", command_brushTranslate, - "^brushTranslate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "brushTranslate ", - "brushTranslate 0.0 0.0"); - DECL_PAINTCOMMAND("brushScale", command_brushScale, - "^brushScale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "brushScale ", - "brushScale 0.0 0.0"); - DECL_PAINTCOMMAND("brushRotate", command_brushRotate, - "^brushRotate\\s+(-?[\\w.]*)$", - "brushRotate \n - angle in degrees", - "brushRotate 0.0"); - DECL_PAINTCOMMAND("brushShear", command_brushShear, - "^brushShear\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "brushShear ", - "brushShear 0.0 0.0"); - DECL_PAINTCOMMAND("setCompositionMode", command_setCompositionMode, - "^setCompositionMode\\s+([\\w_0-9]*)$", - "setCompositionMode ", - "setCompositionMode SourceOver"); - DECL_PAINTCOMMAND("setFont", command_setFont, - "^setFont\\s+\"([\\w\\s]*)\"\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$", - "setFont [size] [font weight|font weight enum] [italic] [hinting enum]\n - font weight is an integer between 0 and 99", - "setFont \"times\" 12"); - DECL_PAINTCOMMAND("setPen", command_setPen, - "^setPen\\s+#?(\\w*)$", - "setPen \nsetPen \nsetPen brush", - "setPen black"); - DECL_PAINTCOMMAND("setPen", command_setPen2, - "^setPen\\s+(#?\\w*)\\s+([\\w.]+)\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)$", - "setPen brush| [width] [pen style enum] [FlatCap|SquareCap|RoundCap] [MiterJoin|BevelJoin|RoundJoin]", - "setPen black 1 FlatCap MiterJoin"); - DECL_PAINTCOMMAND("pen_setDashOffset", command_pen_setDashOffset, - "^pen_setDashOffset\\s+(-?[\\w.]+)$", - "pen_setDashOffset \n", - "pen_setDashOffset 1.0"); - DECL_PAINTCOMMAND("pen_setDashPattern", command_pen_setDashPattern, - "^pen_setDashPattern\\s+\\[([\\w\\s.]*)\\]$", - "pen_setDashPattern <[ ... ]>", - "pen_setDashPattern [ 2 1 4 1 3 3 ]"); - DECL_PAINTCOMMAND("pen_setCosmetic", command_pen_setCosmetic, - "^pen_setCosmetic\\s+(\\w*)$", - "pen_setCosmetic ", - "pen_setCosmetic true"); - DECL_PAINTCOMMAND("setRenderHint", command_setRenderHint, - "^setRenderHint\\s+([\\w_0-9]*)\\s*(\\w*)$", - "setRenderHint ", - "setRenderHint Antialiasing true"); - DECL_PAINTCOMMAND("clearRenderHint", command_clearRenderHint, - "^clearRenderHint$", - "clearRenderHint", - "clearRenderHint"); - - DECL_PAINTCOMMANDSECTION("gradients"); - DECL_PAINTCOMMAND("gradient_appendStop", command_gradient_appendStop, - "^gradient_appendStop\\s+([\\w.]*)\\s+#?(\\w*)$", - "gradient_appendStop ", - "gradient_appendStop 1.0 red"); - DECL_PAINTCOMMAND("gradient_clearStops", command_gradient_clearStops, - "^gradient_clearStops$", - "gradient_clearStops", - "gradient_clearStops"); - DECL_PAINTCOMMAND("gradient_setConical", command_gradient_setConical, - "^gradient_setConical\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", - "gradient_setConical \n - angle in degrees", - "gradient_setConical 5.0 5.0 45.0"); - DECL_PAINTCOMMAND("gradient_setLinear", command_gradient_setLinear, - "^gradient_setLinear\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", - "gradient_setLinear ", - "gradient_setLinear 1.0 1.0 2.0 2.0"); - DECL_PAINTCOMMAND("gradient_setRadial", command_gradient_setRadial, - "^gradient_setRadial\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$", - "gradient_setRadial \n - C is the center\n - rad is the radius\n - F is the focal point", - "gradient_setRadial 1.0 1.0 45.0 2.0 2.0"); - DECL_PAINTCOMMAND("gradient_setRadialExtended", command_gradient_setRadialExtended, - "^gradient_setRadialExtended\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)\\s?([\\w.]*)$", - "gradient_setRadialExtended \n - C is the center\n - rad is the center radius\n - F is the focal point\n - frad is the focal radius", - "gradient_setRadialExtended 1.0 1.0 45.0 2.0 2.0 45.0"); - DECL_PAINTCOMMAND("gradient_setLinearPen", command_gradient_setLinearPen, - "^gradient_setLinearPen\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)\\s+([\\w.]*)$", - "gradient_setLinearPen ", - "gradient_setLinearPen 1.0 1.0 2.0 2.0"); - DECL_PAINTCOMMAND("gradient_setSpread", command_gradient_setSpread, - "^gradient_setSpread\\s+(\\w*)$", - "gradient_setSpread ", - "gradient_setSpread PadSpread"); - DECL_PAINTCOMMAND("gradient_setCoordinateMode", command_gradient_setCoordinateMode, - "^gradient_setCoordinateMode\\s+(\\w*)$", - "gradient_setCoordinateMode ", - "gradient_setCoordinateMode ObjectBoundingMode"); - DECL_PAINTCOMMANDSECTION("drawing ops"); - DECL_PAINTCOMMAND("drawPoint", command_drawPoint, - "^drawPoint\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "drawPoint ", - "drawPoint 10.0 10.0"); - DECL_PAINTCOMMAND("drawLine", command_drawLine, - "^drawLine\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "drawLine ", - "drawLine 10.0 10.0 20.0 20.0"); - DECL_PAINTCOMMAND("drawRect", command_drawRect, - "^drawRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "drawRect ", - "drawRect 10.0 10.0 20.0 20.0"); - DECL_PAINTCOMMAND("drawRoundRect", command_drawRoundRect, - "^drawRoundRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)?\\s*(-?\\w*)?$", - "drawRoundRect [rx] [ry]", - "drawRoundRect 10 10 20 20 3 3"); - DECL_PAINTCOMMAND("drawRoundedRect", command_drawRoundedRect, - "^drawRoundedRect\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(\\w*)?$", - "drawRoundedRect [SizeMode enum]", - "drawRoundedRect 10 10 20 20 4 4 AbsoluteSize"); - DECL_PAINTCOMMAND("drawArc", command_drawArc, - "^drawArc\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", - "drawArc \n - angles are expressed in 1/16th of degree", - "drawArc 10 10 20 20 0 5760"); - DECL_PAINTCOMMAND("drawChord", command_drawChord, - "^drawChord\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", - "drawChord \n - angles are expressed in 1/16th of degree", - "drawChord 10 10 20 20 0 5760"); - DECL_PAINTCOMMAND("drawEllipse", command_drawEllipse, - "^drawEllipse\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "drawEllipse ", - "drawEllipse 10.0 10.0 20.0 20.0"); - DECL_PAINTCOMMAND("drawPath", command_drawPath, - "^drawPath\\s+(\\w*)$", - "drawPath ", - "drawPath mypath"); - DECL_PAINTCOMMAND("drawPie", command_drawPie, - "^drawPie\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", - "drawPie \n - angles are expressed in 1/16th of degree", - "drawPie 10 10 20 20 0 5760"); - DECL_PAINTCOMMAND("drawPixmap", command_drawPixmap, - "^drawPixmap\\s+([\\w.:\\-/]*)" - "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect - "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect - "drawPixmap " - "\n- where t means target and s means source" - "\n- a width or height of -1 means maximum space", - "drawPixmap :/images/face.png 0 0 -1 -1 0 0 -1 -1"); - DECL_PAINTCOMMAND("drawImage", command_drawImage, - "^drawImage\\s+([\\w.:\\/]*)" - "\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?" // target rect - "\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?\\s*(-?[\\w.]*)?$", // source rect - "drawImage " - "\n- where t means target and s means source" - "\n- a width or height of -1 means maximum space", - "drawImage :/images/face.png 0 0 -1 -1 0 0 -1 -1"); - DECL_PAINTCOMMAND("drawPolygon", command_drawPolygon, - "^drawPolygon\\s+\\[([\\w\\s-.]*)\\]\\s*(\\w*)$", - "drawPolygon <[ ... ]> ", - "drawPolygon [ 1 4 6 8 5 3 ] Winding"); - DECL_PAINTCOMMAND("drawConvexPolygon", command_drawConvexPolygon, - "^drawConvexPolygon\\s+\\[([\\w\\s-.]*)\\]$", - "drawConvexPolygon <[ ... ]>", - "drawConvexPolygon [ 1 4 6 8 5 3 ]"); - DECL_PAINTCOMMAND("drawPolyline", command_drawPolyline, - "^drawPolyline\\s+\\[([\\w\\s]*)\\]$", - "drawPolyline <[ ... ]>", - "drawPolyline [ 1 4 6 8 5 3 ]"); - DECL_PAINTCOMMAND("drawText", command_drawText, - "^drawText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", - "drawText ", - "drawText 10 10 \"my text\""); - DECL_PAINTCOMMAND("drawStaticText", command_drawStaticText, - "^drawStaticText\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", - "drawStaticText ", - "drawStaticText 10 10 \"my text\""); - DECL_PAINTCOMMAND("drawTiledPixmap", command_drawTiledPixmap, - "^drawTiledPixmap\\s+([\\w.:\\/]*)" - "\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)\\s*(-?\\w*)" - "\\s*(-?\\w*)\\s*(-?\\w*)$", - "drawTiledPixmap " - "\n - where t means tile" - "\n - and s is an offset in the tile", - "drawTiledPixmap :/images/alpha.png "); - - DECL_PAINTCOMMANDSECTION("painterPaths"); - DECL_PAINTCOMMAND("path_moveTo", command_path_moveTo, - "^path_moveTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "path_moveTo ", - "path_moveTo mypath 1.0 1.0"); - DECL_PAINTCOMMAND("path_lineTo", command_path_lineTo, - "^path_lineTo\\s+([.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "path_lineTo ", - "path_lineTo mypath 1.0 1.0"); - DECL_PAINTCOMMAND("path_addEllipse", command_path_addEllipse, - "^path_addEllipse\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "path_addEllipse ", - "path_addEllipse mypath 10.0 10.0 20.0 20.0"); - DECL_PAINTCOMMAND("path_addPolygon", command_path_addPolygon, - "^path_addPolygon\\s+(\\w*)\\s+\\[([\\w\\s]*)\\]\\s*(\\w*)$", - "path_addPolygon <[ ... ]>", - "path_addPolygon mypath [ 1 4 6 8 5 3 ]"); - DECL_PAINTCOMMAND("path_addRect", command_path_addRect, - "^path_addRect\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "path_addRect ", - "path_addRect mypath 10.0 10.0 20.0 20.0"); - DECL_PAINTCOMMAND("path_addText", command_path_addText, - "^path_addText\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+\"(.*)\"$", - "path_addText ", - "path_addText mypath 10.0 20.0 \"some text\""); - DECL_PAINTCOMMAND("path_arcTo", command_path_arcTo, - "^path_arcTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "path_arcTo \n - angles are expressed in degrees", - "path_arcTo mypath 0.0 0.0 10.0 10.0 0.0 360.0"); - DECL_PAINTCOMMAND("path_cubicTo", command_path_cubicTo, - "^path_cubicTo\\s+(\\w*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "path_cubicTo ", - "path_cubicTo mypath 0.0 0.0 10.0 10.0 20.0 20.0"); - DECL_PAINTCOMMAND("path_closeSubpath", command_path_closeSubpath, - "^path_closeSubpath\\s+(\\w*)$", - "path_closeSubpath ", - "path_closeSubpath mypath"); - DECL_PAINTCOMMAND("path_createOutline", command_path_createOutline, - "^path_createOutline\\s+(\\w*)\\s+(\\w*)$", - "path_createOutline ", - "path_createOutline mypath myoutline"); - DECL_PAINTCOMMAND("path_debugPrint", command_path_debugPrint, - "^path_debugPrint\\s+(\\w*)$", - "path_debugPrint ", - "path_debugPrint mypath"); - - DECL_PAINTCOMMANDSECTION("regions"); - DECL_PAINTCOMMAND("region_addRect", command_region_addRect, - "^region_addRect\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", - "region_addRect ", - "region_addRect myregion 0.0 0.0 10.0 10.0"); - DECL_PAINTCOMMAND("region_addEllipse", command_region_addEllipse, - "^region_addEllipse\\s+(\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)$", - "region_addEllipse ", - "region_addEllipse myregion 0.0 0.0 10.0 10.0"); - - DECL_PAINTCOMMANDSECTION("clipping"); - DECL_PAINTCOMMAND("region_getClipRegion", command_region_getClipRegion, - "^region_getClipRegion\\s+(\\w*)$", - "region_getClipRegion ", - "region_getClipRegion myregion"); - DECL_PAINTCOMMAND("setClipRegion", command_setClipRegion, - "^setClipRegion\\s+(\\w*)\\s*(\\w*)$", - "setClipRegion ", - "setClipRegion myregion ReplaceClip"); - DECL_PAINTCOMMAND("path_getClipPath", command_path_getClipPath, - "^path_getClipPath\\s+([\\w0-9]*)$", - "path_getClipPath ", - "path_getClipPath mypath"); - DECL_PAINTCOMMAND("setClipPath", command_setClipPath, - "^setClipPath\\s+(\\w*)\\s*(\\w*)$", - "setClipPath ", - "setClipPath mypath ReplaceClip"); - DECL_PAINTCOMMAND("setClipRect", command_setClipRect, - "^setClipRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)$", - "setClipRect ", - "setClipRect 0.0 0.0 10.0 10.0 ReplaceClip"); - DECL_PAINTCOMMAND("setClipping", command_setClipping, - "^setClipping\\s+(\\w*)$", - "setClipping ", - "setClipping true"); - - DECL_PAINTCOMMANDSECTION("surface"); - DECL_PAINTCOMMAND("surface_begin", command_surface_begin, - "^surface_begin\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "surface_begin ", - "surface_begin 0.0 0.0 10.0 10.0"); - DECL_PAINTCOMMAND("surface_end", command_surface_end, - "^surface_end$", - "surface_end", - "surface_end"); - - DECL_PAINTCOMMANDSECTION("painter states"); - DECL_PAINTCOMMAND("restore", command_restore, - "^restore$", - "restore", - "restore"); - DECL_PAINTCOMMAND("save", command_save, - "^save$", - "save", - "save"); - - DECL_PAINTCOMMANDSECTION("pixmaps'n'images"); - DECL_PAINTCOMMAND("pixmap_load", command_pixmap_load, - "^pixmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", - "pixmap_load ", - "pixmap_load :/images/face.png myPixmap"); - DECL_PAINTCOMMAND("pixmap_setMask", command_pixmap_setMask, - "^pixmap_setMask\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]*)$", - "pixmap_setMask ", - "pixmap_setMask myPixmap :/images/bitmap.png"); - DECL_PAINTCOMMAND("bitmap_load", command_bitmap_load, - "^bitmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", - "bitmap_load \n - note that the image is stored as a pixmap", - "bitmap_load :/images/bitmap.png myBitmap"); - DECL_PAINTCOMMAND("image_convertToFormat", command_image_convertToFormat, - "^image_convertToFormat\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]+)\\s+([\\w0-9_]*)$", - "image_convertToFormat ", - "image_convertToFormat myImage myNewImage Indexed8"); - DECL_PAINTCOMMAND("image_load", command_image_load, - "^image_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$", - "image_load ", - "image_load :/images/face.png myImage"); - DECL_PAINTCOMMAND("image_setColor", command_image_setColor, - "^image_setColor\\s+([\\w.:\\/]*)\\s+([0-9]*)\\s+#([0-9]*)$", - "image_setColor ", - "image_setColor myImage 0 black"); - DECL_PAINTCOMMAND("image_setColorCount", command_image_setColorCount, - "^image_setColorCount\\s+([\\w.:\\/]*)\\s+([0-9]*)$", - "image_setColorCount ", - "image_setColorCount myImage 128"); - - DECL_PAINTCOMMANDSECTION("transformations"); - DECL_PAINTCOMMAND("resetMatrix", command_resetMatrix, - "^resetMatrix$", - "resetMatrix", - "resetMatrix"); - DECL_PAINTCOMMAND("setMatrix", command_setMatrix, - "^setMatrix\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "setMatrix ", - "setMatrix 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"); - DECL_PAINTCOMMAND("translate", command_translate, - "^translate\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "translate ", - "translate 10.0 10.0"); - DECL_PAINTCOMMAND("rotate", command_rotate, - "^rotate\\s+(-?[\\w.]*)$", - "rotate \n - with angle in degrees", - "rotate 30.0"); - DECL_PAINTCOMMAND("rotate_x", command_rotate_x, - "^rotate_x\\s+(-?[\\w.]*)$", - "rotate_x \n - with angle in degrees", - "rotate_x 30.0"); - DECL_PAINTCOMMAND("rotate_y", command_rotate_y, - "^rotate_y\\s+(-?[\\w.]*)$", - "rotate_y \n - with angle in degrees", - "rotate_y 30.0"); - DECL_PAINTCOMMAND("scale", command_scale, - "^scale\\s+(-?[\\w.]*)\\s+(-?[\\w.]*)$", - "scale ", - "scale 2.0 1.0"); - DECL_PAINTCOMMAND("mapQuadToQuad", command_mapQuadToQuad, - "^mapQuadToQuad\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)$", - "mapQuadToQuad " - "\n - where vertices 1 to 4 defines the source quad and 5 to 8 the destination quad", - "mapQuadToQuad 0.0 0.0 1.0 1.0 0.0 0.0 -1.0 -1.0"); - - // populate the command lookup hash - for (int i=0; i T PaintCommands::image_load(const QString &filepath) -{ - T t(filepath); - - if (t.isNull()) - t = T(":images/" + filepath); - - if (t.isNull()) - t = T("images/" + filepath); - - if (t.isNull()) { - QFileInfo fi(filepath); - QDir dir = fi.absoluteDir(); - dir.cdUp(); - dir.cd("images"); - QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(fi.fileName()); - t = T(fileName); - if (t.isNull() && !fileName.endsWith(".png")) { - fileName.append(".png"); - t = T(fileName); - } - } - - return t; -} - -/********************************************************************************* -** setters -**********************************************************************************/ -void PaintCommands::insertAt(int commandIndex, const QStringList &newCommands) -{ - int index = 0; - int left = newCommands.size(); - while (left--) - m_commands.insert(++commandIndex, newCommands.at(index++)); -} - -/********************************************************************************* -** run -**********************************************************************************/ -void PaintCommands::runCommand(const QString &scriptLine) -{ - if (scriptLine.isEmpty()) { - command_noop(QRegExp()); - return; - } - if (scriptLine.startsWith('#')) { - command_comment(QRegExp()); - return; - } - QString firstWord = scriptLine.section(QRegExp("\\s"), 0, 0); - QList indices = s_commandHash.values(firstWord); - foreach(int idx, indices) { - const PaintCommandInfos &command = s_commandInfoTable.at(idx); - if (command.regExp.indexIn(scriptLine) >= 0) { - (this->*(command.paintMethod))(command.regExp); - return; - } - } - qWarning("ERROR: unknown command or argument syntax error in \"%s\"", qPrintable(scriptLine)); -} - -void PaintCommands::runCommands() -{ - staticInit(); - int width = m_painter->window().width(); - int height = m_painter->window().height(); - - if (width <= 0) - width = 800; - if (height <= 0) - height = 800; - - // paint background - if (m_checkers_background) { - QPixmap pm(20, 20); - pm.fill(Qt::white); - QPainter pt(&pm); - pt.fillRect(0, 0, 10, 10, QColor::fromRgba(0xffdfdfdf)); - pt.fillRect(10, 10, 10, 10, QColor::fromRgba(0xffdfdfdf)); - pt.end(); - m_painter->drawTiledPixmap(0, 0, width, height, pm); - } else { - m_painter->fillRect(0, 0, width, height, Qt::white); - } - - // run each command - m_abort = false; - for (int i=0; idevice()->devType() == Qt::Widget) - return m_painter->window().width(); - else - return 800; - } - if (str.toLower() == "height") { - if (m_painter->device()->devType() == Qt::Widget) - return m_painter->window().height(); - else - return 800; - } - if (re.indexIn(str) >= 0) { - int index = re.cap(1).toInt(); - bool is_it_x = re.cap(2) == "x"; - if (index < 0 || index >= m_controlPoints.size()) { - qWarning("ERROR: control point index=%d is out of bounds", index); - return 0; - } - return is_it_x ? m_controlPoints.at(index).x() : m_controlPoints.at(index).y(); - } - return str.toDouble(); -} - -QColor PaintCommands::convertToColor(const QString &str) -{ - static QRegExp alphaColor("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"); - static QRegExp opaqueColor("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"); - - Q_ASSERT(alphaColor.isValid()); - Q_ASSERT(opaqueColor.isValid()); - - if (alphaColor.indexIn(str) >= 0) { - return QColor(alphaColor.cap(2).toInt(0, 16), - alphaColor.cap(3).toInt(0, 16), - alphaColor.cap(4).toInt(0, 16), - alphaColor.cap(1).toInt(0, 16)); - } else if (opaqueColor.indexIn(str) >= 0) { - return QColor(opaqueColor.cap(1).toInt(0, 16), - opaqueColor.cap(2).toInt(0, 16), - opaqueColor.cap(3).toInt(0, 16)); - } - return QColor(str); -} - -/********************************************************************************* -** command implementations -**********************************************************************************/ -void PaintCommands::command_comment(QRegExp) -{ - if (m_verboseMode) - printf(" -(lance) comment: %s\n", qPrintable(m_currentCommand)); -} - -/***************************************************************************************************/ -void PaintCommands::command_import(QRegExp re) -{ - QString importFile(re.cap(1)); - QFileInfo fi(m_filepath); - QDir dir = fi.absoluteDir(); - QFile *file = new QFile(dir.absolutePath() + QDir::separator() + importFile); - - if (importFile.isEmpty() || !file->exists()) { - dir.cdUp(); - dir.cd("data"); - dir.cd("qps"); - delete file; - file = new QFile(dir.absolutePath() + QDir::separator() + importFile); - } - - if (importFile.isEmpty() || !file->exists()) { - dir.cdUp(); - dir.cd("images"); - delete file; - file = new QFile(dir.absolutePath() + QDir::separator() + importFile); - } - - if (importFile.isEmpty() || !file->exists()) { - printf(" - importing non-existing file at line %d (%s)\n", m_currentCommandIndex, - qPrintable(file->fileName())); - delete file; - return; - } - - if (!file->open(QIODevice::ReadOnly)) { - printf(" - failed to read file: '%s'\n", qPrintable(file->fileName())); - delete file; - return; - } - if (m_verboseMode) - printf(" -(lance) importing file at line %d (%s)\n", m_currentCommandIndex, - qPrintable(fi.fileName())); - - QFileInfo fileinfo(*file); - m_commands[m_currentCommandIndex] = QString("# import file (%1) start").arg(fileinfo.fileName()); - QTextStream textFile(file); - QString rawContent = textFile.readAll(); - QStringList importedData = rawContent.split('\n', QString::SkipEmptyParts); - importedData.append(QString("# import file (%1) end ---").arg(fileinfo.fileName())); - insertAt(m_currentCommandIndex, importedData); - - if (m_verboseMode) { - printf(" -(lance) Command buffer now looks like:\n"); - for (int i = 0; i < m_commands.count(); ++i) - printf(" ---> {%s}\n", qPrintable(m_commands.at(i))); - } - delete file; -} - -/***************************************************************************************************/ -void PaintCommands::command_begin_block(QRegExp re) -{ - const QString &blockName = re.cap(1); - if (m_verboseMode) - printf(" -(lance) begin_block (%s)\n", qPrintable(blockName)); - - m_commands[m_currentCommandIndex] = QString("# begin block (%1)").arg(blockName); - QStringList newBlock; - int i = m_currentCommandIndex + 1; - for (; i < m_commands.count(); ++i) { - const QString &nextCmd = m_commands.at(i); - if (nextCmd.startsWith("end_block")) { - m_commands[i] = QString("# end block (%1)").arg(blockName); - break; - } - newBlock += nextCmd; - } - - if (m_verboseMode) - for (int j = 0; j < newBlock.count(); ++j) - printf(" %d: %s\n", j, qPrintable(newBlock.at(j))); - - if (i >= m_commands.count()) - printf(" - Warning! Block doesn't have an 'end_block' marker!\n"); - - m_blockMap.insert(blockName, newBlock); -} - -/***************************************************************************************************/ -void PaintCommands::command_end_block(QRegExp) -{ - printf(" - end_block should be consumed by begin_block command.\n"); - printf(" You will never see this if your block markers are in sync\n"); - printf(" (noop)\n"); -} - -/***************************************************************************************************/ -void PaintCommands::command_repeat_block(QRegExp re) -{ - QString blockName = re.cap(1); - if (m_verboseMode) - printf(" -(lance) repeating block (%s)\n", qPrintable(blockName)); - - QStringList block = m_blockMap.value(blockName); - if (block.isEmpty()) { - printf(" - repeated block (%s) is empty!\n", qPrintable(blockName)); - return; - } - - m_commands[m_currentCommandIndex] = QString("# repeated block (%1)").arg(blockName); - insertAt(m_currentCommandIndex, block); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawLine(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double x1 = convertToDouble(caps.at(1)); - double y1 = convertToDouble(caps.at(2)); - double x2 = convertToDouble(caps.at(3)); - double y2 = convertToDouble(caps.at(4)); - - if (m_verboseMode) - printf(" -(lance) drawLine((%.2f, %.2f), (%.2f, %.2f))\n", x1, y1, x2, y2); - - m_painter->drawLine(QLineF(x1, y1, x2, y2)); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawPath(QRegExp re) -{ - if (m_verboseMode) - printf(" -(lance) drawPath(name=%s)\n", qPrintable(re.cap(1))); - - QPainterPath &path = m_pathMap[re.cap(1)]; - m_painter->drawPath(path); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawPixmap(QRegExp re) -{ - QPixmap pm; - pm = m_pixmapMap[re.cap(1)]; // try cache first - if (pm.isNull()) - pm = image_load(re.cap(1)); - if (pm.isNull()) { - QFileInfo fi(m_filepath); - QDir dir = fi.absoluteDir(); - dir.cdUp(); - dir.cd("images"); - QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(re.cap(1)); - pm = QPixmap(fileName); - if (pm.isNull() && !fileName.endsWith(".png")) { - fileName.append(".png"); - pm = QPixmap(fileName); - } - } - if (pm.isNull()) { - fprintf(stderr, "ERROR(drawPixmap): failed to load pixmap: '%s'\n", - qPrintable(re.cap(1))); - return; - } - - qreal tx = convertToFloat(re.cap(2)); - qreal ty = convertToFloat(re.cap(3)); - qreal tw = convertToFloat(re.cap(4)); - qreal th = convertToFloat(re.cap(5)); - - qreal sx = convertToFloat(re.cap(6)); - qreal sy = convertToFloat(re.cap(7)); - qreal sw = convertToFloat(re.cap(8)); - qreal sh = convertToFloat(re.cap(9)); - - if (tw == 0) tw = -1; - if (th == 0) th = -1; - if (sw == 0) sw = -1; - if (sh == 0) sh = -1; - - if (m_verboseMode) - printf(" -(lance) drawPixmap('%s' dim=(%d, %d), depth=%d, (%f, %f, %f, %f), (%f, %f, %f, %f)\n", - qPrintable(re.cap(1)), pm.width(), pm.height(), pm.depth(), - tx, ty, tw, th, sx, sy, sw, sh); - - m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh)); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawImage(QRegExp re) -{ - QImage im; - im = m_imageMap[re.cap(1)]; // try cache first - if (im.isNull()) - im = image_load(re.cap(1)); - - if (im.isNull()) { - QFileInfo fi(m_filepath); - QDir dir = fi.absoluteDir(); - dir.cdUp(); - dir.cd("images"); - QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(re.cap(1)); - im = QImage(fileName); - if (im.isNull() && !fileName.endsWith(".png")) { - fileName.append(".png"); - im = QImage(fileName); - } - } - if (im.isNull()) { - fprintf(stderr, "ERROR(drawImage): failed to load image: '%s'\n", qPrintable(re.cap(1))); - return; - } - - qreal tx = convertToFloat(re.cap(2)); - qreal ty = convertToFloat(re.cap(3)); - qreal tw = convertToFloat(re.cap(4)); - qreal th = convertToFloat(re.cap(5)); - - qreal sx = convertToFloat(re.cap(6)); - qreal sy = convertToFloat(re.cap(7)); - qreal sw = convertToFloat(re.cap(8)); - qreal sh = convertToFloat(re.cap(9)); - - if (tw == 0) tw = -1; - if (th == 0) th = -1; - if (sw == 0) sw = -1; - if (sh == 0) sh = -1; - - if (m_verboseMode) - printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n", - qPrintable(re.cap(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh); - - m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh), Qt::OrderedDither | Qt::OrderedAlphaDither); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawTiledPixmap(QRegExp re) -{ - QPixmap pm; - pm = m_pixmapMap[re.cap(1)]; // try cache first - if (pm.isNull()) - pm = image_load(re.cap(1)); - if (pm.isNull()) { - QFileInfo fi(m_filepath); - QDir dir = fi.absoluteDir(); - dir.cdUp(); - dir.cd("images"); - QString fileName = QString("%1/%2").arg(dir.absolutePath()).arg(re.cap(1)); - pm = QPixmap(fileName); - if (pm.isNull() && !fileName.endsWith(".png")) { - fileName.append(".png"); - pm = QPixmap(fileName); - } - } - if (pm.isNull()) { - fprintf(stderr, "ERROR(drawTiledPixmap): failed to load pixmap: '%s'\n", - qPrintable(re.cap(1))); - return; - } - - int tx = convertToInt(re.cap(2)); - int ty = convertToInt(re.cap(3)); - int tw = convertToInt(re.cap(4)); - int th = convertToInt(re.cap(5)); - - int sx = convertToInt(re.cap(6)); - int sy = convertToInt(re.cap(7)); - - if (tw == 0) tw = -1; - if (th == 0) th = -1; - - if (m_verboseMode) - printf(" -(lance) drawTiledPixmap('%s' dim=(%d, %d), (%d, %d, %d, %d), (%d, %d)\n", - qPrintable(re.cap(1)), pm.width(), pm.height(), tx, ty, tw, th, sx, sy); - - m_painter->drawTiledPixmap(tx, ty, tw, th, pm, sx, sy); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawPoint(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - float x = convertToFloat(caps.at(1)); - float y = convertToFloat(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) drawPoint(%.2f, %.2f)\n", x, y); - - m_painter->drawPoint(QPointF(x, y)); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawPolygon(QRegExp re) -{ - static QRegExp separators("\\s"); - QStringList caps = re.capturedTexts(); - QString cap = caps.at(1); - QStringList numbers = cap.split(separators, QString::SkipEmptyParts); - - QPolygonF array; - for (int i=0; i + 1drawPolygon(array, caps.at(2).toLower() == "winding" ? Qt::WindingFill : Qt::OddEvenFill); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawPolyline(QRegExp re) -{ - static QRegExp separators("\\s"); - QStringList numbers = re.cap(1).split(separators, QString::SkipEmptyParts); - - QPolygonF array; - for (int i=0; i + 1drawPolyline(array.toPolygon()); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawRect(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - float x = convertToFloat(caps.at(1)); - float y = convertToFloat(caps.at(2)); - float w = convertToFloat(caps.at(3)); - float h = convertToFloat(caps.at(4)); - - if (m_verboseMode) - printf(" -(lance) drawRect(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); - - m_painter->drawRect(QRectF(x, y, w, h)); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawRoundedRect(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - float x = convertToFloat(caps.at(1)); - float y = convertToFloat(caps.at(2)); - float w = convertToFloat(caps.at(3)); - float h = convertToFloat(caps.at(4)); - float xr = convertToFloat(caps.at(5)); - float yr = convertToFloat(caps.at(6)); - - int mode = translateEnum(sizeModeTable, caps.at(7), sizeof(sizeModeTable)/sizeof(char *)); - if (mode < 0) - mode = Qt::AbsoluteSize; - - if (m_verboseMode) - printf(" -(lance) drawRoundRect(%f, %f, %f, %f, %f, %f, %s)\n", x, y, w, h, xr, yr, mode ? "RelativeSize" : "AbsoluteSize"); - - m_painter->drawRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::SizeMode(mode)); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawRoundRect(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - int w = convertToInt(caps.at(3)); - int h = convertToInt(caps.at(4)); - int xs = caps.at(5).isEmpty() ? 50 : convertToInt(caps.at(5)); - int ys = caps.at(6).isEmpty() ? 50 : convertToInt(caps.at(6)); - - if (m_verboseMode) - printf(" -(lance) drawRoundRect(%d, %d, %d, %d, [%d, %d])\n", x, y, w, h, xs, ys); - - m_painter->drawRoundRect(x, y, w, h, xs, ys); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawEllipse(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - float x = convertToFloat(caps.at(1)); - float y = convertToFloat(caps.at(2)); - float w = convertToFloat(caps.at(3)); - float h = convertToFloat(caps.at(4)); - - if (m_verboseMode) - printf(" -(lance) drawEllipse(%.2f, %.2f, %.2f, %.2f)\n", x, y, w, h); - - m_painter->drawEllipse(QRectF(x, y, w, h)); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawPie(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - int w = convertToInt(caps.at(3)); - int h = convertToInt(caps.at(4)); - int angle = convertToInt(caps.at(5)); - int sweep = convertToInt(caps.at(6)); - - if (m_verboseMode) - printf(" -(lance) drawPie(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); - - m_painter->drawPie(x, y, w, h, angle, sweep); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawChord(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - int w = convertToInt(caps.at(3)); - int h = convertToInt(caps.at(4)); - int angle = convertToInt(caps.at(5)); - int sweep = convertToInt(caps.at(6)); - - if (m_verboseMode) - printf(" -(lance) drawChord(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); - - m_painter->drawChord(x, y, w, h, angle, sweep); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawArc(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - int w = convertToInt(caps.at(3)); - int h = convertToInt(caps.at(4)); - int angle = convertToInt(caps.at(5)); - int sweep = convertToInt(caps.at(6)); - - if (m_verboseMode) - printf(" -(lance) drawArc(%d, %d, %d, %d, %d, %d)\n", x, y, w, h, angle, sweep); - - m_painter->drawArc(x, y, w, h, angle, sweep); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawText(QRegExp re) -{ - if (!m_shouldDrawText) - return; - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - QString txt = caps.at(3); - - if (m_verboseMode) - printf(" -(lance) drawText(%d, %d, %s)\n", x, y, qPrintable(txt)); - - m_painter->drawText(x, y, txt); -} - -void PaintCommands::command_drawStaticText(QRegExp re) -{ - if (!m_shouldDrawText) - return; - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - QString txt = caps.at(3); - - if (m_verboseMode) - printf(" -(lance) drawStaticText(%d, %d, %s)\n", x, y, qPrintable(txt)); - - m_painter->drawStaticText(x, y, QStaticText(txt)); -} - -/***************************************************************************************************/ -void PaintCommands::command_noop(QRegExp) -{ - if (m_verboseMode) - printf(" -(lance) noop: %s\n", qPrintable(m_currentCommand)); - - if (!m_currentCommand.trimmed().isEmpty()) { - fprintf(stderr, "unknown command: '%s'\n", qPrintable(m_currentCommand.trimmed())); - } -} - -/***************************************************************************************************/ -void PaintCommands::command_path_addText(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - double x = convertToDouble(caps.at(2)); - double y = convertToDouble(caps.at(3)); - QString text = caps.at(4); - - if (m_verboseMode) - printf(" -(lance) path_addText(%s, %.2f, %.2f, text=%s\n", qPrintable(name), x, y, qPrintable(text)); - - m_pathMap[name].addText(x, y, m_painter->font(), text); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_addEllipse(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - double x = convertToDouble(caps.at(2)); - double y = convertToDouble(caps.at(3)); - double w = convertToDouble(caps.at(4)); - double h = convertToDouble(caps.at(5)); - - if (m_verboseMode) - printf(" -(lance) path_addEllipse(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h); - - m_pathMap[name].addEllipse(x, y, w, h); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_addRect(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - double x = convertToDouble(caps.at(2)); - double y = convertToDouble(caps.at(3)); - double w = convertToDouble(caps.at(4)); - double h = convertToDouble(caps.at(5)); - - if (m_verboseMode) - printf(" -(lance) path_addRect(%s, %.2f, %.2f, %.2f, %.2f)\n", qPrintable(name), x, y, w, h); - - m_pathMap[name].addRect(x, y, w, h); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_addPolygon(QRegExp re) -{ - static QRegExp separators("\\s"); - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - QString cap = caps.at(2); - QStringList numbers = cap.split(separators, QString::SkipEmptyParts); - - QPolygonF array; - for (int i=0; i + 1pen(); - - if (m_verboseMode) - printf(" -(lance) path_createOutline(%s, name=%s, width=%d)\n", - qPrintable(name), qPrintable(newName), pen.width()); - - if (!m_pathMap.contains(name)) { - fprintf(stderr, "createOutline(), unknown path: %s\n", qPrintable(name)); - return; - } - QPainterPathStroker stroker; - stroker.setWidth(pen.widthF()); - stroker.setDashPattern(pen.style()); - stroker.setCapStyle(pen.capStyle()); - stroker.setJoinStyle(pen.joinStyle()); - m_pathMap[newName] = stroker.createStroke(m_pathMap[name]); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_cubicTo(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - double x1 = convertToDouble(caps.at(2)); - double y1 = convertToDouble(caps.at(3)); - double x2 = convertToDouble(caps.at(4)); - double y2 = convertToDouble(caps.at(5)); - double x3 = convertToDouble(caps.at(6)); - double y3 = convertToDouble(caps.at(7)); - - if (m_verboseMode) - printf(" -(lance) path_cubicTo(%s, (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f))\n", qPrintable(name), x1, y1, x2, y2, x3, y3); - - m_pathMap[name].cubicTo(x1, y1, x2, y2, x3, y3); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_moveTo(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - double x1 = convertToDouble(caps.at(2)); - double y1 = convertToDouble(caps.at(3)); - - if (m_verboseMode) - printf(" -(lance) path_moveTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1); - - m_pathMap[name].moveTo(x1, y1); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_lineTo(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - double x1 = convertToDouble(caps.at(2)); - double y1 = convertToDouble(caps.at(3)); - - if (m_verboseMode) - printf(" -(lance) path_lineTo(%s, (%.2f, %.2f))\n", qPrintable(name), x1, y1); - - m_pathMap[name].lineTo(x1, y1); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_setFillRule(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - bool winding = caps.at(2).toLower() == "winding"; - - if (m_verboseMode) - printf(" -(lance) path_setFillRule(name=%s, winding=%d)\n", qPrintable(name), winding); - - m_pathMap[name].setFillRule(winding ? Qt::WindingFill : Qt::OddEvenFill); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_closeSubpath(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - - if (m_verboseMode) - printf(" -(lance) path_closeSubpath(name=%s)\n", qPrintable(name)); - - m_pathMap[name].closeSubpath(); -} - -/***************************************************************************************************/ -void PaintCommands::command_path_getClipPath(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - - if (m_verboseMode) - printf(" -(lance) path_closeSubpath(name=%s)\n", qPrintable(name)); - - m_pathMap[name] = m_painter->clipPath(); -} - -/***************************************************************************************************/ -static void qt_debug_path(const QPainterPath &path, const QString &name) -{ - const char *names[] = { - "MoveTo ", - "LineTo ", - "CurveTo ", - "CurveToData" - }; - - printf("\nQPainterPath (%s): elementCount=%d\n", qPrintable(name), path.elementCount()); - for (int i=0; i= 0 && e.type <= QPainterPath::CurveToDataElement); - printf(" - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); - } -} - -/***************************************************************************************************/ -void PaintCommands::command_path_debugPrint(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - qt_debug_path(m_pathMap[name], name); -} - -/***************************************************************************************************/ -void PaintCommands::command_region_addRect(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - int x = convertToInt(caps.at(2)); - int y = convertToInt(caps.at(3)); - int w = convertToInt(caps.at(4)); - int h = convertToInt(caps.at(5)); - - if (m_verboseMode) - printf(" -(lance) region_addRect(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h); - - m_regionMap[name] += QRect(x, y, w, h); -} - -/***************************************************************************************************/ -void PaintCommands::command_region_addEllipse(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - int x = convertToInt(caps.at(2)); - int y = convertToInt(caps.at(3)); - int w = convertToInt(caps.at(4)); - int h = convertToInt(caps.at(5)); - - if (m_verboseMode) - printf(" -(lance) region_addEllipse(%s, %d, %d, %d, %d)\n", qPrintable(name), x, y, w, h); - - m_regionMap[name] += QRegion(x, y, w, h, QRegion::Ellipse); -} - -/***************************************************************************************************/ -void PaintCommands::command_region_getClipRegion(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString name = caps.at(1); - QRegion region = m_painter->clipRegion(); - - if (m_verboseMode) - printf(" -(lance) region_getClipRegion(name=%s), bounds=[%d, %d, %d, %d]\n", qPrintable(name), - region.boundingRect().x(), - region.boundingRect().y(), - region.boundingRect().width(), - region.boundingRect().height()); - - m_regionMap[name] = region; -} - -/***************************************************************************************************/ -void PaintCommands::command_resetMatrix(QRegExp) -{ - if (m_verboseMode) - printf(" -(lance) resetMatrix()\n"); - - m_painter->resetTransform(); -} - -/***************************************************************************************************/ -void PaintCommands::command_restore(QRegExp) -{ - if (m_verboseMode) - printf(" -(lance) restore()\n"); - - m_painter->restore(); -} - -/***************************************************************************************************/ -void PaintCommands::command_rotate(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double angle = convertToDouble(caps.at(1)); - - if (m_verboseMode) - printf(" -(lance) rotate(%.2f)\n", angle); - - m_painter->rotate(angle); -} - -/***************************************************************************************************/ -void PaintCommands::command_rotate_x(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double angle = convertToDouble(caps.at(1)); - - if (m_verboseMode) - printf(" -(lance) rotate_x(%.2f)\n", angle); - - QTransform transform; - transform.rotate(angle, Qt::XAxis); - m_painter->setTransform(transform, true); -} - -/***************************************************************************************************/ -void PaintCommands::command_rotate_y(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double angle = convertToDouble(caps.at(1)); - - if (m_verboseMode) - printf(" -(lance) rotate_y(%.2f)\n", angle); - - QTransform transform; - transform.rotate(angle, Qt::YAxis); - m_painter->setTransform(transform, true); -} - -/***************************************************************************************************/ -void PaintCommands::command_save(QRegExp) -{ - if (m_verboseMode) - printf(" -(lance) save()\n"); - - m_painter->save(); -} - -/***************************************************************************************************/ -void PaintCommands::command_mapQuadToQuad(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double x1 = convertToDouble(caps.at(1)); - double y1 = convertToDouble(caps.at(2)); - double x2 = convertToDouble(caps.at(3)); - double y2 = convertToDouble(caps.at(4)); - double x3 = convertToDouble(caps.at(5)); - double y3 = convertToDouble(caps.at(6)); - double x4 = convertToDouble(caps.at(7)); - double y4 = convertToDouble(caps.at(8)); - QPolygonF poly1(4); - poly1[0] = QPointF(x1, y1); - poly1[1] = QPointF(x2, y2); - poly1[2] = QPointF(x3, y3); - poly1[3] = QPointF(x4, y4); - - double x5 = convertToDouble(caps.at(9)); - double y5 = convertToDouble(caps.at(10)); - double x6 = convertToDouble(caps.at(11)); - double y6 = convertToDouble(caps.at(12)); - double x7 = convertToDouble(caps.at(13)); - double y7 = convertToDouble(caps.at(14)); - double x8 = convertToDouble(caps.at(15)); - double y8 = convertToDouble(caps.at(16)); - QPolygonF poly2(4); - poly2[0] = QPointF(x5, y5); - poly2[1] = QPointF(x6, y6); - poly2[2] = QPointF(x7, y7); - poly2[3] = QPointF(x8, y8); - - if (m_verboseMode) - printf(" -(lance) mapQuadToQuad(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ->\n\t" - ",%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", - x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7, x8, y8); - - QTransform trans; - - if (!QTransform::quadToQuad(poly1, poly2, trans)) { - qWarning("Couldn't perform quad to quad transformation!"); - } - - m_painter->setTransform(trans, true); -} - -/***************************************************************************************************/ -void PaintCommands::command_setMatrix(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double m11 = convertToDouble(caps.at(1)); - double m12 = convertToDouble(caps.at(2)); - double m13 = convertToDouble(caps.at(3)); - double m21 = convertToDouble(caps.at(4)); - double m22 = convertToDouble(caps.at(5)); - double m23 = convertToDouble(caps.at(6)); - double m31 = convertToDouble(caps.at(7)); - double m32 = convertToDouble(caps.at(8)); - double m33 = convertToDouble(caps.at(9)); - - if (m_verboseMode) - printf(" -(lance) setMatrix(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", - m11, m12, m13, m21, m22, m23, m31, m32, m33); - - QTransform trans; - trans.setMatrix(m11, m12, m13, - m21, m22, m23, - m31, m32, m33); - - m_painter->setTransform(trans, true); -} - -/***************************************************************************************************/ -void PaintCommands::command_scale(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double sx = convertToDouble(caps.at(1)); - double sy = convertToDouble(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) scale(%.2f, %.2f)\n", sx, sy); - - - m_painter->scale(sx, sy); -} - -/***************************************************************************************************/ -void PaintCommands::command_setBackground(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QColor color = convertToColor(caps.at(1)); - QString pattern = caps.at(2); - - int style = translateEnum(brushStyleTable, pattern, Qt::LinearGradientPattern); - if (style < 0) - style = Qt::SolidPattern; - - if (m_verboseMode) - printf(" -(lance) setBackground(%s, %s)\n", qPrintable(color.name()), qPrintable(pattern)); - - m_painter->setBackground(QBrush(color, Qt::BrushStyle(style))); -} - -/***************************************************************************************************/ -void PaintCommands::command_setOpacity(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double opacity = convertToDouble(caps.at(1)); - - if (m_verboseMode) - printf(" -(lance) setOpacity(%lf)\n", opacity); - - m_painter->setOpacity(opacity); -} - -/***************************************************************************************************/ -void PaintCommands::command_setBgMode(QRegExp re) -{ - QString cap = re.cap(2); - Qt::BGMode mode = Qt::TransparentMode; - if (cap.toLower() == QLatin1String("opaquemode") || cap.toLower() == QLatin1String("opaque")) - mode = Qt::OpaqueMode; - - if (m_verboseMode) - printf(" -(lance) setBackgroundMode(%s)\n", mode == Qt::OpaqueMode ? "OpaqueMode" : "TransparentMode"); - - m_painter->setBackgroundMode(mode); -} - -/***************************************************************************************************/ -void PaintCommands::command_setBrush(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QPixmap pm = image_load(caps.at(1)); - if (!pm.isNull()) { // Assume pixmap - if (m_verboseMode) - printf(" -(lance) setBrush(pixmap=%s, width=%d, height=%d)\n", - qPrintable(caps.at(1)), pm.width(), pm.height()); - - m_painter->setBrush(QBrush(pm)); - } else if (caps.at(1).toLower() == "nobrush") { - m_painter->setBrush(Qt::NoBrush); - if (m_verboseMode) - printf(" -(lance) setBrush(Qt::NoBrush)\n"); - } else { - QColor color = convertToColor(caps.at(1)); - QString pattern = caps.at(2); - - int style = translateEnum(brushStyleTable, pattern, Qt::LinearGradientPattern); - if (style < 0) - style = Qt::SolidPattern; - - if (m_verboseMode) - printf(" -(lance) setBrush(%s, %s (%d))\n", qPrintable(color.name()), qPrintable(pattern), style); - - m_painter->setBrush(QBrush(color, Qt::BrushStyle(style))); - } -} - -/***************************************************************************************************/ -void PaintCommands::command_setBrushOrigin(QRegExp re) -{ - int x = convertToInt(re.cap(1)); - int y = convertToInt(re.cap(2)); - - if (m_verboseMode) - printf(" -(lance) setBrushOrigin(%d, %d)\n", x, y); - - m_painter->setBrushOrigin(x, y); -} - -/***************************************************************************************************/ -void PaintCommands::command_brushTranslate(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double dx = convertToDouble(caps.at(1)); - double dy = convertToDouble(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) brushTranslate(%f, %f)\n", dx, dy); - - QBrush new_brush = m_painter->brush(); - QTransform brush_matrix = new_brush.transform(); - brush_matrix.translate(dx, dy); - new_brush.setTransform(brush_matrix); - m_painter->setBrush(new_brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_brushScale(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double sx = convertToDouble(caps.at(1)); - double sy = convertToDouble(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) brushScale(%f, %f)\n", sx, sy); - - QBrush new_brush = m_painter->brush(); - QTransform brush_matrix = new_brush.transform(); - brush_matrix.scale(sx, sy); - new_brush.setTransform(brush_matrix); - m_painter->setBrush(new_brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_brushRotate(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double rot = convertToDouble(caps.at(1)); - - if (m_verboseMode) - printf(" -(lance) brushScale(%f)\n", rot); - - QBrush new_brush = m_painter->brush(); - QTransform brush_matrix = new_brush.transform(); - brush_matrix.rotate(rot); - new_brush.setTransform(brush_matrix); - m_painter->setBrush(new_brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_brushShear(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double sx = convertToDouble(caps.at(1)); - double sy = convertToDouble(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) brushShear(%f, %f)\n", sx, sy); - - QBrush new_brush = m_painter->brush(); - QTransform brush_matrix = new_brush.transform(); - brush_matrix.shear(sx, sy); - new_brush.setTransform(brush_matrix); - m_painter->setBrush(new_brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_setClipping(QRegExp re) -{ - bool clipping = re.cap(1).toLower() == "true"; - - if (m_verboseMode) - printf(" -(lance) setClipping(%d)\n", clipping); - - m_painter->setClipping(clipping); -} - -/***************************************************************************************************/ -void PaintCommands::command_setClipRect(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - int x = convertToInt(caps.at(1)); - int y = convertToInt(caps.at(2)); - int w = convertToInt(caps.at(3)); - int h = convertToInt(caps.at(4)); - - int combine = translateEnum(clipOperationTable, caps.at(5), Qt::IntersectClip + 1); - if (combine == -1) - combine = Qt::ReplaceClip; - - if (m_verboseMode) - printf(" -(lance) setClipRect(%d, %d, %d, %d), %s\n", x, y, w, h, clipOperationTable[combine]); - - m_painter->setClipRect(x, y, w, h, Qt::ClipOperation(combine)); -} - -/***************************************************************************************************/ -void PaintCommands::command_setClipPath(QRegExp re) -{ - int combine = translateEnum(clipOperationTable, re.cap(2), Qt::IntersectClip + 1); - if (combine == -1) - combine = Qt::ReplaceClip; - - if (m_verboseMode) - printf(" -(lance) setClipPath(name=%s), %s\n", qPrintable(re.cap(1)), clipOperationTable[combine]); - - if (!m_pathMap.contains(re.cap(1))) - fprintf(stderr, " - setClipPath, no such path"); - m_painter->setClipPath(m_pathMap[re.cap(1)], Qt::ClipOperation(combine)); -} - -/***************************************************************************************************/ -void PaintCommands::command_setClipRegion(QRegExp re) -{ - int combine = translateEnum(clipOperationTable, re.cap(2), Qt::IntersectClip + 1); - if (combine == -1) - combine = Qt::ReplaceClip; - QRegion r = m_regionMap[re.cap(1)]; - - if (m_verboseMode) - printf(" -(lance) setClipRegion(name=%s), bounds=[%d, %d, %d, %d], %s\n", - qPrintable(re.cap(1)), - r.boundingRect().x(), - r.boundingRect().y(), - r.boundingRect().width(), - r.boundingRect().height(), - clipOperationTable[combine]); - - m_painter->setClipRegion(m_regionMap[re.cap(1)], Qt::ClipOperation(combine)); -} - -/***************************************************************************************************/ -void PaintCommands::command_setFont(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QString family = caps.at(1); - int size = convertToInt(caps.at(2)); - - int weight = translateEnum(fontWeightTable, re.cap(3).toLower(), 5); - if (weight != -1) { - switch (weight) { - case 0: weight = QFont::Light; break; - case 1: weight = QFont::Normal; break; - case 2: weight = QFont::DemiBold; break; - case 3: weight = QFont::Bold; break; - case 4: weight = QFont::Black; break; - } - } else { - weight = convertToInt(re.cap(3)); - } - - bool italic = caps.at(4).toLower() == "true" || caps.at(4).toLower() == "italic"; - - QFont font(family, size, weight, italic); - -#if QT_VERSION >= 0x040800 - int hinting = translateEnum(fontHintingTable, caps.at(5), 4); - if (hinting == -1) - hinting = 0; - else - font.setHintingPreference(QFont::HintingPreference(hinting)); -#else - int hinting = 1; -#endif - if (m_verboseMode) - printf(" -(lance) setFont(family=%s, size=%d, weight=%d, italic=%d hinting=%s\n", - qPrintable(family), size, weight, italic, fontHintingTable[hinting]); - - m_painter->setFont(font); -} - -/***************************************************************************************************/ -void PaintCommands::command_setPen(QRegExp re) -{ - QString cap = re.cap(1); - int style = translateEnum(penStyleTable, cap, Qt::DashDotDotLine + 1); - if (style >= 0) { - if (m_verboseMode) - printf(" -(lance) setPen(%s)\n", qPrintable(cap)); - - m_painter->setPen(Qt::PenStyle(style)); - } else if (cap.toLower() == "brush") { - QPen pen(m_painter->brush(), 0); - if (m_verboseMode) { - printf(" -(lance) setPen(brush), style=%d, color=%08x\n", - pen.brush().style(), pen.color().rgba()); - } - m_painter->setPen(pen); - } else { - QColor color = convertToColor(cap); - if (m_verboseMode) - printf(" -(lance) setPen(%s)\n", qPrintable(color.name())); - - m_painter->setPen(color); - } -} - -/***************************************************************************************************/ -void PaintCommands::command_setPen2(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QBrush brush; - - if (caps.at(1).toLower() == "brush") - brush = m_painter->brush(); - else - brush = convertToColor(caps.at(1)); - - double width = convertToDouble(caps.at(2)); - int penStyle = translateEnum(penStyleTable, caps.at(3), Qt::DashDotDotLine + 1); - if (penStyle < 0) - penStyle = Qt::SolidLine; - - Qt::PenCapStyle capStyle = Qt::SquareCap; - if (caps.at(4).toLower() == "flatcap") capStyle = Qt::FlatCap; - else if (caps.at(4).toLower() == "squarecap") capStyle = Qt::SquareCap; - else if (caps.at(4).toLower() == "roundcap") capStyle = Qt::RoundCap; - else if (!caps.at(4).isEmpty()) - fprintf(stderr, "ERROR: setPen, unknown capStyle: %s\n", qPrintable(caps.at(4))); - - Qt::PenJoinStyle joinStyle = Qt::BevelJoin; - if (caps.at(5).toLower() == "miterjoin") joinStyle = Qt::MiterJoin; - else if (caps.at(5).toLower() == "beveljoin") joinStyle = Qt::BevelJoin; - else if (caps.at(5).toLower() == "roundjoin") joinStyle = Qt::RoundJoin; - else if (!caps.at(5).isEmpty()) - fprintf(stderr, "ERROR: setPen, unknown joinStyle: %s\n", qPrintable(caps.at(5))); - - if (m_verboseMode) - printf(" -(lance) setPen(%s, width=%f, style=%d, cap=%d, join=%d)\n", - qPrintable(brush.color().name()), width, penStyle, capStyle, joinStyle); - - m_painter->setPen(QPen(brush, width, Qt::PenStyle(penStyle), capStyle, joinStyle)); -} - -/***************************************************************************************************/ -void PaintCommands::command_setRenderHint(QRegExp re) -{ - QString hintString = re.cap(1).toLower(); - bool on = re.cap(2).isEmpty() || re.cap(2).toLower() == "true"; - if (hintString.contains("antialiasing")) { - if (m_verboseMode) - printf(" -(lance) setRenderHint Antialiasing\n"); - - m_painter->setRenderHint(QPainter::Antialiasing, on); - } else if (hintString.contains("smoothpixmaptransform")) { - if (m_verboseMode) - printf(" -(lance) setRenderHint SmoothPixmapTransform\n"); - m_painter->setRenderHint(QPainter::SmoothPixmapTransform, on); - } else { - fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(hintString)); - } -} - -/***************************************************************************************************/ -void PaintCommands::command_clearRenderHint(QRegExp /*re*/) -{ - m_painter->setRenderHint(QPainter::Antialiasing, false); - m_painter->setRenderHint(QPainter::SmoothPixmapTransform, false); - if (m_verboseMode) - printf(" -(lance) clearRenderHint\n"); -} - -/***************************************************************************************************/ -void PaintCommands::command_setCompositionMode(QRegExp re) -{ - QString modeString = re.cap(1).toLower(); - int mode = translateEnum(compositionModeTable, modeString, 33); - - if (mode < 0 || mode > QPainter::RasterOp_SourceAndNotDestination) { - fprintf(stderr, "ERROR: invalid mode: %s\n", qPrintable(modeString)); - return; - } - - if (m_verboseMode) - printf(" -(lance) setCompositionMode: %d: %s\n", mode, qPrintable(modeString)); - - m_painter->setCompositionMode(QPainter::CompositionMode(mode)); -} - -/***************************************************************************************************/ -void PaintCommands::command_translate(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double dx = convertToDouble(caps.at(1)); - double dy = convertToDouble(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) translate(%f, %f)\n", dx, dy); - - m_painter->translate(dx, dy); -} - -/***************************************************************************************************/ -void PaintCommands::command_pixmap_load(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString fileName = caps.at(1); - QString name = caps.at(2); - - if (name.isEmpty()) - name = fileName; - - QImage im = image_load(fileName); - QPixmap px = QPixmap::fromImage(im, Qt::OrderedDither | Qt::OrderedAlphaDither); - - if (m_verboseMode) - printf(" -(lance) pixmap_load(%s as %s), size=[%d, %d], depth=%d\n", - qPrintable(fileName), qPrintable(name), - px.width(), px.height(), px.depth()); - - m_pixmapMap[name] = px; -} - -/***************************************************************************************************/ -void PaintCommands::command_bitmap_load(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString fileName = caps.at(1); - QString name = caps.at(2); - - if (name.isEmpty()) - name = fileName; - - QBitmap bm = image_load(fileName); - - if (m_verboseMode) - printf(" -(lance) bitmap_load(%s as %s), size=[%d, %d], depth=%d\n", - qPrintable(fileName), qPrintable(name), - bm.width(), bm.height(), bm.depth()); - - m_pixmapMap[name] = bm; -} - -/***************************************************************************************************/ -void PaintCommands::command_pixmap_setMask(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - QBitmap mask = image_load(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) pixmap_setMask(%s, %s)\n", qPrintable(caps.at(1)), qPrintable(caps.at(2))); - - if (!m_pixmapMap[caps.at(1)].isNull()) - m_pixmapMap[caps.at(1)].setMask(mask); -} - -/***************************************************************************************************/ -void PaintCommands::command_image_load(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString fileName = caps.at(1); - QString name = caps.at(2); - - if (name.isEmpty()) - name = fileName; - - QImage image = image_load(fileName); - - if (m_verboseMode) - printf(" -(lance) image_load(%s as %s), size=[%d, %d], format=%d\n", - qPrintable(fileName), qPrintable(name), - image.width(), image.height(), image.format()); - - m_imageMap[name] = image; -} - -/***************************************************************************************************/ -void PaintCommands::command_image_setColorCount(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString name = caps.at(1); - int count = convertToInt(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) image_setColorCount(%s), %d -> %d\n", - qPrintable(name), m_imageMap[name].colorCount(), count); - - m_imageMap[name].setColorCount(count); -} - -/***************************************************************************************************/ -void PaintCommands::command_image_setColor(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString name = caps.at(1); - int index = convertToInt(caps.at(2)); - QColor color = convertToColor(caps.at(3)); - - if (m_verboseMode) - printf(" -(lance) image_setColor(%s), %d = %08x\n", qPrintable(name), index, color.rgba()); - - m_imageMap[name].setColor(index, color.rgba()); -} - -/***************************************************************************************************/ -void PaintCommands::command_abort(QRegExp) -{ - m_abort = true; -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_clearStops(QRegExp) -{ - if (m_verboseMode) - printf(" -(lance) gradient_clearStops\n"); - m_gradientStops.clear(); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_appendStop(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double pos = convertToDouble(caps.at(1)); - QColor color = convertToColor(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) gradient_appendStop(%.2f, %x)\n", pos, color.rgba()); - - m_gradientStops << QGradientStop(pos, color); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_setLinear(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double x1 = convertToDouble(caps.at(1)); - double y1 = convertToDouble(caps.at(2)); - double x2 = convertToDouble(caps.at(3)); - double y2 = convertToDouble(caps.at(4)); - - if (m_verboseMode) - printf(" -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n", - x1, y1, x2, y2, m_gradientSpread); - - QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2)); - lg.setStops(m_gradientStops); - lg.setSpread(m_gradientSpread); - lg.setCoordinateMode(m_gradientCoordinate); - QBrush brush(lg); - QTransform brush_matrix = m_painter->brush().transform(); - brush.setTransform(brush_matrix); - m_painter->setBrush(brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_setLinearPen(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double x1 = convertToDouble(caps.at(1)); - double y1 = convertToDouble(caps.at(2)); - double x2 = convertToDouble(caps.at(3)); - double y2 = convertToDouble(caps.at(4)); - - if (m_verboseMode) - printf(" -(lance) gradient_setLinear (%.2f, %.2f), (%.2f, %.2f), spread=%d\n", - x1, y1, x2, y2, m_gradientSpread); - - QLinearGradient lg(QPointF(x1, y1), QPointF(x2, y2)); - lg.setStops(m_gradientStops); - lg.setSpread(m_gradientSpread); - lg.setCoordinateMode(m_gradientCoordinate); - QPen pen = m_painter->pen(); - pen.setBrush(lg); - m_painter->setPen(pen); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_setRadial(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double cx = convertToDouble(caps.at(1)); - double cy = convertToDouble(caps.at(2)); - double rad = convertToDouble(caps.at(3)); - double fx = convertToDouble(caps.at(4)); - double fy = convertToDouble(caps.at(5)); - - if (m_verboseMode) - printf(" -(lance) gradient_setRadial center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), " - "spread=%d\n", - cx, cy, rad, fx, fy, m_gradientSpread); - - QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy)); - rg.setStops(m_gradientStops); - rg.setSpread(m_gradientSpread); - rg.setCoordinateMode(m_gradientCoordinate); - QBrush brush(rg); - QTransform brush_matrix = m_painter->brush().transform(); - brush.setTransform(brush_matrix); - m_painter->setBrush(brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_setRadialExtended(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double cx = convertToDouble(caps.at(1)); - double cy = convertToDouble(caps.at(2)); - double rad = convertToDouble(caps.at(3)); - double fx = convertToDouble(caps.at(4)); - double fy = convertToDouble(caps.at(5)); - double frad = convertToDouble(caps.at(6)); - - if (m_verboseMode) - printf(" -(lance) gradient_setRadialExtended center=(%.2f, %.2f), radius=%.2f, focal=(%.2f, %.2f), " - "focal radius=%.2f, spread=%d\n", - cx, cy, rad, fx, fy, frad, m_gradientSpread); - -#if QT_VERSION >= 0x040800 - QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy), frad); -#else - QRadialGradient rg(QPointF(cx, cy), rad, QPointF(fx, fy)); -#endif - rg.setStops(m_gradientStops); - rg.setSpread(m_gradientSpread); - rg.setCoordinateMode(m_gradientCoordinate); - QBrush brush(rg); - QTransform brush_matrix = m_painter->brush().transform(); - brush.setTransform(brush_matrix); - m_painter->setBrush(brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_setConical(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double cx = convertToDouble(caps.at(1)); - double cy = convertToDouble(caps.at(2)); - double angle = convertToDouble(caps.at(3)); - - if (m_verboseMode) { - printf(" -(lance) gradient_setConical center=(%.2f, %.2f), angle=%.2f\n, spread=%d", - cx, cy, angle, m_gradientSpread); - } - - QConicalGradient cg(QPointF(cx, cy), angle); - cg.setStops(m_gradientStops); - cg.setSpread(m_gradientSpread); - cg.setCoordinateMode(m_gradientCoordinate); - QBrush brush(cg); - QTransform brush_matrix = m_painter->brush().transform(); - brush.setTransform(brush_matrix); - m_painter->setBrush(brush); -} - -/***************************************************************************************************/ -void PaintCommands::command_gradient_setSpread(QRegExp re) -{ - int spreadMethod = translateEnum(spreadMethodTable, re.cap(1), 3); - - if (m_verboseMode) - printf(" -(lance) gradient_setSpread %d=[%s]\n", spreadMethod, spreadMethodTable[spreadMethod]); - - m_gradientSpread = QGradient::Spread(spreadMethod); -} - -void PaintCommands::command_gradient_setCoordinateMode(QRegExp re) -{ - int coord = translateEnum(coordinateMethodTable, re.cap(1), 3); - - if (m_verboseMode) - printf(" -(lance) gradient_setCoordinateMode %d=[%s]\n", coord, - coordinateMethodTable[coord]); - - m_gradientCoordinate = QGradient::CoordinateMode(coord); -} - -/***************************************************************************************************/ -void PaintCommands::command_surface_begin(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double x = convertToDouble(caps.at(1)); - double y = convertToDouble(caps.at(2)); - double w = convertToDouble(caps.at(3)); - double h = convertToDouble(caps.at(4)); - - if (m_surface_painter) { - fprintf(stderr, "ERROR: surface already active"); - return; - } - - if (m_verboseMode) - printf(" -(lance) surface_begin, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", x, y, w, h); - - m_surface_painter = m_painter; - - if (m_type == OpenGLType || m_type == OpenGLPBufferType) { -#ifndef QT_NO_OPENGL - m_surface_pbuffer = new QGLPixelBuffer(qRound(w), qRound(h)); - m_painter = new QPainter(m_surface_pbuffer); - m_painter->fillRect(QRect(0, 0, qRound(w), qRound(h)), Qt::transparent); -#endif -#ifdef Q_WS_X11 - } else if (m_type == WidgetType) { - m_surface_pixmap = QPixmap(qRound(w), qRound(h)); - m_surface_pixmap.fill(Qt::transparent); - m_painter = new QPainter(&m_surface_pixmap); -#endif - } else { - m_surface_image = QImage(qRound(w), qRound(h), QImage::Format_ARGB32_Premultiplied); - m_surface_image.fill(0); - m_painter = new QPainter(&m_surface_image); - } - m_surface_rect = QRectF(x, y, w, h); -} - -/***************************************************************************************************/ -void PaintCommands::command_surface_end(QRegExp) -{ - if (!m_surface_painter) { - fprintf(stderr, "ERROR: surface not active"); - return; - } - - if (m_verboseMode) - printf(" -(lance) surface_end, pos=[%.2f, %.2f], size=[%.2f, %.2f]\n", - m_surface_rect.x(), - m_surface_rect.y(), - m_surface_rect.width(), - m_surface_rect.height()); - m_painter->end(); - - delete m_painter; - m_painter = m_surface_painter; - m_surface_painter = 0; - - if (m_type == OpenGLType || m_type == OpenGLPBufferType) { -#ifndef QT_NO_OPENGL - QImage image = m_surface_pbuffer->toImage(); - QImage new_image(image.bits(), image.width(), - image.height(), QImage::Format_ARGB32_Premultiplied); - QPaintDevice *pdev = m_painter->device(); - if (pdev->devType() == QInternal::Widget) { - QWidget *w = static_cast(pdev); - static_cast(w)->makeCurrent(); - } else if (pdev->devType() == QInternal::Pbuffer) { - static_cast(pdev)->makeCurrent(); - } - - m_painter->drawImage(m_surface_rect, new_image); - - delete m_surface_pbuffer; - m_surface_pbuffer = 0; -#endif -#ifdef Q_WS_X11 - } else if (m_type == WidgetType) { - m_painter->drawPixmap(m_surface_rect.topLeft(), m_surface_pixmap); - m_surface_pixmap = QPixmap(); -#endif - } else { - m_painter->drawImage(m_surface_rect, m_surface_image); - m_surface_image = QImage(); - } - m_surface_rect = QRectF(); -} - -/***************************************************************************************************/ -void PaintCommands::command_image_convertToFormat(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString srcName = caps.at(1); - QString destName = caps.at(2); - - if (!m_imageMap.contains(srcName)) { - fprintf(stderr, "ERROR(convertToFormat): no such image '%s'\n", qPrintable(srcName)); - return; - } - - int format = translateEnum(imageFormatTable, caps.at(3), QImage::NImageFormats); - if (format < 0 || format >= QImage::NImageFormats) { - fprintf(stderr, "ERROR(convertToFormat): invalid format %d = '%s'\n", - format, qPrintable(caps.at(3))); - return; - } - - QImage src = m_imageMap[srcName]; - QImage dest = src.convertToFormat(QImage::Format(format), - Qt::OrderedAlphaDither | Qt::OrderedDither); - - if (m_verboseMode) { - printf(" -(lance) convertToFormat %s:%d -> %s:%d\n", - qPrintable(srcName), src.format(), - qPrintable(destName), dest.format()); - } - - m_imageMap[destName] = dest; -} - -/***************************************************************************************************/ -void PaintCommands::command_textlayout_draw(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - - QString text = caps.at(1); - double width = convertToDouble(caps.at(2)); - - if (m_verboseMode) - printf(" -(lance) textlayout_draw text='%s', width=%f\n", - qPrintable(text), width); - - QFont copy = m_painter->font(); - copy.setPointSize(10); - - QTextLayout layout(text, copy, m_painter->device()); - layout.beginLayout(); - - double y_offset = 0; - - while (true) { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; - line.setLineWidth(width); - line.setPosition(QPointF(0, y_offset)); - - y_offset += line.height(); - } - - layout.draw(m_painter, QPointF(0, 0)); -} - -/***************************************************************************************************/ -void PaintCommands::command_pen_setDashOffset(QRegExp re) -{ - QStringList caps = re.capturedTexts(); - double offset = convertToDouble(caps.at(1)); - - if (m_verboseMode) - printf(" -(lance) setDashOffset(%lf)\n", offset); - - QPen p = m_painter->pen(); - p.setDashOffset(offset); - m_painter->setPen(p); -} - -/***************************************************************************************************/ -void PaintCommands::command_pen_setDashPattern(QRegExp re) -{ - static QRegExp separators("\\s"); - QStringList caps = re.capturedTexts(); - QString cap = caps.at(1); - QStringList numbers = cap.split(separators, QString::SkipEmptyParts); - - QVector pattern; - for (int i=0; ipen(); - p.setDashPattern(pattern); - m_painter->setPen(p); -} - -/***************************************************************************************************/ -void PaintCommands::command_pen_setCosmetic(QRegExp re) -{ - QString hm = re.capturedTexts().at(1); - bool on = hm == "true" || hm == "yes" || hm == "on"; - - if (m_verboseMode) { - printf(" -(lance) pen_setCosmetic(%s)\n", on ? "true" : "false"); - } - - QPen p = m_painter->pen(); - p.setCosmetic(on); - - m_painter->setPen(p); -} - -/***************************************************************************************************/ -void PaintCommands::command_drawConvexPolygon(QRegExp re) -{ - static QRegExp separators("\\s"); - QStringList caps = re.capturedTexts(); - QString cap = caps.at(1); - QStringList numbers = cap.split(separators, QString::SkipEmptyParts); - - QPolygonF array; - for (int i=0; i + 1drawConvexPolygon(array); -} diff --git a/tests/auto/lancelot/paintcommands.h b/tests/auto/lancelot/paintcommands.h deleted file mode 100644 index 925a867f2f..0000000000 --- a/tests/auto/lancelot/paintcommands.h +++ /dev/null @@ -1,334 +0,0 @@ -/**************************************************************************** -** -** 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 PAINTCOMMANDS_H -#define PAINTCOMMANDS_H - -#include -#include -#include -#include -#include -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QPainter) -QT_FORWARD_DECLARE_CLASS(QRegExp) -#ifndef QT_NO_OPENGL -QT_FORWARD_DECLARE_CLASS(QGLPixelBuffer) -#endif - -enum DeviceType { - WidgetType, - BitmapType, - PixmapType, - ImageType, - ImageMonoType, - OpenGLType, - OpenGLPBufferType, - PictureType, - PrinterType, - PdfType, - PsType, - GrabType, - CustomDeviceType, - CustomWidgetType, - ImageWidgetType -}; - -/************************************************************************/ -class PaintCommands -{ -public: - // construction / initialization - PaintCommands(const QStringList &cmds, int w, int h) - : m_painter(0) - , m_surface_painter(0) - , m_commands(cmds) - , m_gradientSpread(QGradient::PadSpread) - , m_gradientCoordinate(QGradient::LogicalMode) - , m_width(w) - , m_height(h) - , m_verboseMode(false) - , m_type(WidgetType) - , m_checkers_background(true) - , m_shouldDrawText(true) - { staticInit(); } - -public: - void setCheckersBackground(bool b) { staticInit(); m_checkers_background = b; } - void setContents(const QStringList &cmds) { - staticInit(); - m_blockMap.clear(); - m_pathMap.clear(); - m_pixmapMap.clear(); - m_imageMap.clear(); - m_regionMap.clear(); - m_gradientStops.clear(); - m_controlPoints.clear(); - m_gradientSpread = QGradient::PadSpread; - m_gradientCoordinate = QGradient::LogicalMode; - m_commands = cmds; - - - } - void setPainter(QPainter *pt) { staticInit(); m_painter = pt; } - void setType(DeviceType t) { staticInit(); m_type = t; } - void setFilePath(const QString &path) { staticInit(); m_filepath = path; } - void setControlPoints(const QVector &points) { staticInit(); m_controlPoints = points; } - void setVerboseMode(bool v) { staticInit(); m_verboseMode = v; } - void insertAt(int commandIndex, const QStringList &newCommands); - void setShouldDrawText(bool drawText) { m_shouldDrawText = drawText; } - - // run - void runCommands(); - -private: - // run - void runCommand(const QString &scriptLine); - - // conversion methods - int convertToInt(const QString &str); - double convertToDouble(const QString &str); - float convertToFloat(const QString &str); - QColor convertToColor(const QString &str); - - // commands: comments - void command_comment(QRegExp re); - - // commands: importer - void command_import(QRegExp re); - - // commands: blocks - void command_begin_block(QRegExp re); - void command_end_block(QRegExp re); - void command_repeat_block(QRegExp re); - - // commands: misc - void command_textlayout_draw(QRegExp re); - void command_abort(QRegExp re); - - // commands: noops - void command_noop(QRegExp re); - - // commands: setters - void command_setBgMode(QRegExp re); - void command_setBackground(QRegExp re); - void command_setOpacity(QRegExp re); - void command_path_setFillRule(QRegExp re); - void command_setBrush(QRegExp re); - void command_setBrushOrigin(QRegExp re); - void command_brushTranslate(QRegExp re); - void command_brushRotate(QRegExp re); - void command_brushScale(QRegExp re); - void command_brushShear(QRegExp re); - void command_setClipPath(QRegExp re); - void command_setClipRect(QRegExp re); - void command_setClipRectangle(QRegExp re); - void command_setClipRegion(QRegExp re); - void command_setClipping(QRegExp re); - void command_setCompositionMode(QRegExp re); - void command_setFont(QRegExp re); - void command_setPen(QRegExp re); - void command_setPen2(QRegExp re); - void command_pen_setDashOffset(QRegExp re); - void command_pen_setDashPattern(QRegExp re); - void command_pen_setCosmetic(QRegExp re); - void command_setRenderHint(QRegExp re); - void command_clearRenderHint(QRegExp re); - void command_gradient_appendStop(QRegExp re); - void command_gradient_clearStops(QRegExp re); - void command_gradient_setConical(QRegExp re); - void command_gradient_setLinear(QRegExp re); - void command_gradient_setRadial(QRegExp re); - void command_gradient_setRadialExtended(QRegExp re); - void command_gradient_setLinearPen(QRegExp re); - void command_gradient_setSpread(QRegExp re); - void command_gradient_setCoordinateMode(QRegExp re); - - // commands: drawing ops - void command_drawArc(QRegExp re); - void command_drawChord(QRegExp re); - void command_drawConvexPolygon(QRegExp re); - void command_drawEllipse(QRegExp re); - void command_drawImage(QRegExp re); - void command_drawLine(QRegExp re); - void command_drawPath(QRegExp re); - void command_drawPie(QRegExp re); - void command_drawPixmap(QRegExp re); - void command_drawPoint(QRegExp re); - void command_drawPolygon(QRegExp re); - void command_drawPolyline(QRegExp re); - void command_drawRect(QRegExp re); - void command_drawRoundedRect(QRegExp re); - void command_drawRoundRect(QRegExp re); - void command_drawText(QRegExp re); - void command_drawStaticText(QRegExp re); - void command_drawTiledPixmap(QRegExp re); - void command_path_addEllipse(QRegExp re); - void command_path_addPolygon(QRegExp re); - void command_path_addRect(QRegExp re); - void command_path_addText(QRegExp re); - void command_path_arcTo(QRegExp re); - void command_path_closeSubpath(QRegExp re); - void command_path_createOutline(QRegExp re); - void command_path_cubicTo(QRegExp re); - void command_path_debugPrint(QRegExp re); - void command_path_lineTo(QRegExp re); - void command_path_moveTo(QRegExp re); - void command_region_addEllipse(QRegExp re); - void command_region_addRect(QRegExp re); - - // getters - void command_region_getClipRegion(QRegExp re); - void command_path_getClipPath(QRegExp re); - - // commands: surface begin/end - void command_surface_begin(QRegExp re); - void command_surface_end(QRegExp re); - - // commands: save/restore painter state - void command_restore(QRegExp re); - void command_save(QRegExp re); - - // commands: pixmap/image - void command_pixmap_load(QRegExp re); - void command_pixmap_setMask(QRegExp re); - void command_bitmap_load(QRegExp re); - void command_image_convertToFormat(QRegExp re); - void command_image_load(QRegExp re); - void command_image_setColor(QRegExp re); - void command_image_setColorCount(QRegExp re); - - // commands: transformation - void command_resetMatrix(QRegExp re); - void command_translate(QRegExp re); - void command_rotate(QRegExp re); - void command_rotate_x(QRegExp re); - void command_rotate_y(QRegExp re); - void command_scale(QRegExp re); - void command_mapQuadToQuad(QRegExp re); - void command_setMatrix(QRegExp re); - - // attributes - QPainter *m_painter; - QPainter *m_surface_painter; - QImage m_surface_image; - QPixmap m_surface_pixmap; -#ifndef QT_NO_OPENGL - QGLPixelBuffer *m_surface_pbuffer; -#endif - QRectF m_surface_rect; - QStringList m_commands; - QString m_currentCommand; - int m_currentCommandIndex; - QString m_filepath; - QMap m_blockMap; - QMap m_pathMap; - QMap m_pixmapMap; - QMap m_imageMap; - QMap m_regionMap; - QGradientStops m_gradientStops; - QGradient::Spread m_gradientSpread; - QGradient::CoordinateMode m_gradientCoordinate; - bool m_abort; - int m_width; - int m_height; - - bool m_verboseMode; - DeviceType m_type; - bool m_checkers_background; - bool m_shouldDrawText; - - QVector m_controlPoints; - - // painter functionalities string tables - static const char *brushStyleTable[]; - static const char *penStyleTable[]; - static const char *fontWeightTable[]; - static const char *fontHintingTable[]; - static const char *clipOperationTable[]; - static const char *spreadMethodTable[]; - static const char *coordinateMethodTable[]; - static const char *compositionModeTable[]; - static const char *imageFormatTable[]; - static const char *sizeModeTable[]; - static int translateEnum(const char *table[], const QString &pattern, int limit); - - // utility - template T image_load(const QString &filepath); - - // commands dictionary management - static void staticInit(); - -public: - struct PaintCommandInfos - { - PaintCommandInfos(QString id, void (PaintCommands::*p)(QRegExp), QRegExp r, QString sy, QString sa) - : identifier(id) - , regExp(r) - , syntax(sy) - , sample(sa) - , paintMethod(p) - {} - PaintCommandInfos(QString title) - : identifier(title), paintMethod(0) {} - bool isSectionHeader() const { return paintMethod == 0; } - QString identifier; - QRegExp regExp; - QString syntax; - QString sample; - void (PaintCommands::*paintMethod)(QRegExp); - }; - - static PaintCommandInfos *findCommandById(const QString &identifier) { - for (int i=0; i s_commandInfoTable; - static QList > s_enumsTable; - static QMultiHash s_commandHash; -}; - -#endif // PAINTCOMMANDS_H diff --git a/tests/auto/lancelot/scripts/aliasing.qps b/tests/auto/lancelot/scripts/aliasing.qps deleted file mode 100644 index 59878f9c4d..0000000000 --- a/tests/auto/lancelot/scripts/aliasing.qps +++ /dev/null @@ -1,156 +0,0 @@ - -path_moveTo convexPath 25 0 -path_lineTo convexPath 50 50 -path_lineTo convexPath 25 25 -path_lineTo convexPath 0 50 -path_closeSubpath convexPath - -pixmap_load border.png pixmap - -setRenderHint LineAntialiasing false -translate 10 10 - -begin_block drawing - setPen black 1 - setBrush 7f7fff - drawPath convexPath - - setFont "monospace" 8 - setPen black - drawText 0 68 "QwErTy@" - - - setPen black 1 - setBrush 7f7fff - drawRect 0 80 10 5 - - setPen black 1 - setBrush noBrush - drawRect 20 80 10 5 - - setPen noPen - setBrush 7f7fff - drawRect 40 80 10 5 - - - setPen black 2 - setBrush 7f7fff - drawRect 0 90 10 5 - - setPen black 2 - setBrush noBrush - drawRect 20 90 10 5 - - setPen noPen - setBrush 7f7fff - drawRect 40 90 10 5 - - - setPen black 3 - setBrush 7f7fff - drawRect 0 100 10 5 - - setPen black 3 - setBrush noBrush - drawRect 20 100 10 5 - - setPen noPen - setBrush 7f7fff - drawRect 40 100 10 5 - - - setPen black 1 - setBrush noBrush - drawLine 10 110 20 120 - drawLine 30 120 40 110 - - setPen black 2 - setBrush noBrush - drawLine 10 120 20 130 - drawLine 30 130 40 120 - - setPen black 3 - setBrush noBrush - drawLine 10 130 20 140 - drawLine 30 140 40 130 - - drawPixmap pixmap 0 150 - - setRenderHint SmoothPixmapTransform false - drawPixmap pixmap 20 150 15 15 0 0 10 10 - -end_block - -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -drawText 15 185 "0.0" - -resetMatrix -translate 70.2 10.2 -setRenderHint LineAntialiasing false -repeat_block drawing -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -translate -0.2 -0.2 -drawText 15 185 "0.2" - - -resetMatrix -translate 130.4 10.4 -setRenderHint LineAntialiasing false -repeat_block drawing -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -translate -0.4 -0.4 -drawText 15 185 "0.4" - - -resetMatrix -translate 190.5 10.5 -setRenderHint LineAntialiasing false -repeat_block drawing -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -translate -0.5 -0.5 -drawText 15 185 "0.5" - - -resetMatrix -translate 250.6 10.6 -setRenderHint LineAntialiasing false -repeat_block drawing -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -translate -0.6 -0.6 -drawText 15 185 "0.6" - - -resetMatrix -translate 310.8 10.8 -setRenderHint LineAntialiasing false -repeat_block drawing -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -translate -0.8 -0.8 -drawText 15 185 "0.8" - - -resetMatrix -translate 371 11 -setRenderHint LineAntialiasing false -repeat_block drawing -translate 0 180 -setRenderHint LineAntialiasing true -repeat_block drawing -drawText 15 185 "1.0" - - -resetMatrix -drawText 430 95 "Aliased" -drawText 430 275 "Anti-Aliased" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/arcs.qps b/tests/auto/lancelot/scripts/arcs.qps deleted file mode 100644 index 8a7a468df1..0000000000 --- a/tests/auto/lancelot/scripts/arcs.qps +++ /dev/null @@ -1,68 +0,0 @@ -# Version: 1 -# CheckVsReference: 5 - -setRenderHint LineAntialiasing - -setPen red - -drawEllipse 0 0 600 400 - -path_moveTo arcs 300 200 -path_arcTo arcs 0 0 600 400 0 10 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 0 0 600 400 20 30 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 0 0 600 400 60 45 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 0 0 600 400 115 60 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 0 0 600 400 180 90 -path_closeSubpath arcs - -path_moveTo arcs 590 200 -path_arcTo arcs 10 10 580 380 0 360 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 20 20 560 360 0 -10 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 20 20 560 360 -20 -30 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 20 20 560 360 -60 -45 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 20 20 560 360 -115 -60 -path_closeSubpath arcs - -path_moveTo arcs 300 200 -path_arcTo arcs 20 20 560 360 -180 -90 -path_closeSubpath arcs - -setPen black 1 solidline -setBrush #3f00ff00 -drawPath arcs - -# Then again with a matrix set... -translate 200 400 -rotate 10 -scale 0.5 0.5 -setPen red -setBrush nobrush -drawEllipse 0 0 600 400 - -setPen black 1 solidline -setBrush #3f0000ff -drawPath arcs \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/arcs2.qps b/tests/auto/lancelot/scripts/arcs2.qps deleted file mode 100644 index 411ff08014..0000000000 --- a/tests/auto/lancelot/scripts/arcs2.qps +++ /dev/null @@ -1,47 +0,0 @@ -# Version: 1 -# CheckVsReference: 5 - -drawArc 100 100 100 100 0 1440 -drawArc 100 100 100 100 1440 1440 -drawArc 100 100 100 100 2880 1440 -drawArc 100 100 100 100 4320 1440 - -drawArc 100 200 100 100 0 -1440 -drawArc 100 200 100 100 -1440 -1440 -drawArc 100 200 100 100 -2880 -1440 -drawArc 100 200 100 100 -4320 -1440 - -drawArc 200 100 100 100 720 1440 -drawArc 200 100 100 100 2160 1440 -drawArc 200 100 100 100 3600 1440 -drawArc 200 100 100 100 5040 1440 - -drawArc 200 200 100 100 -720 -1440 -drawArc 200 200 100 100 -2160 -1440 -drawArc 200 200 100 100 -3600 -1440 -drawArc 200 200 100 100 -5040 -1440 - - -drawArc 300 100 100 100 3840 480 -drawArc 300 200 100 100 -3840 -480 - -drawArc 300 100 100 100 1600 1340 - -setPen black -drawArc 400 100 200 200 0 5760 -setPen white -drawArc 400 100 200 200 960 960 -drawArc 400 100 200 200 2880 960 -drawArc 400 100 200 200 4800 960 - -setPen black -drawArc 100 350 300 300 160 5760 -drawArc 100 350 300 300 320 5760 -drawArc 100 350 300 300 1920 5760 -drawArc 100 350 300 300 2080 5760 -drawArc 100 350 300 300 3680 5760 -drawArc 100 350 300 300 3840 5760 -drawArc 100 350 300 300 5440 5760 -drawArc 100 350 300 300 5600 5760 -setPen white -drawArc 100 350 300 300 0 5760 diff --git a/tests/auto/lancelot/scripts/background.qps b/tests/auto/lancelot/scripts/background.qps deleted file mode 100644 index 000cfcdd91..0000000000 --- a/tests/auto/lancelot/scripts/background.qps +++ /dev/null @@ -1,136 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -translate 10 30 -setBackground 7f7fff -setBackgroundMode Transparent -setPen ff7f7f - -path_moveTo path 0 0 -path_lineTo path 25 0 -path_cubicTo path 50 0 25 25 25 50 -path_lineTo path 0 50 - -bitmap_load bitmap.png bitmap - -begin_block drawing - save - drawRect 0 0 50 50 - - translate 60 0 - drawEllipse 0 0 50 50 - - translate 60 0 - drawPolygon [0 0 50 0 25 50 25 25] - - translate 60 0 - drawPath path - - translate 60 0 - drawPie 0 0 50 50 1440 2000 - - translate 60 0 - drawChord 0 0 50 50 1440 2000 - - translate 60 0 - drawLine 0 0 50 0 - drawLine 0 0 50 50 - drawLine 0 0 0 50 - - translate 60 0 - drawPolyline [0 0 50 0 25 50 25 25] - - translate 60 0 - drawArc 0 0 50 50 1440 2000 - - translate 60 0 - drawText 0 10 "Jambi-Bambi" - - translate 80 0 - drawPixmap bitmap 0 0 - restore - - save - setRenderHint Antialiasing - translate 5 55 - drawRect 0 0 50 50 - - translate 60 0 - drawEllipse 0 0 50 50 - - translate 60 0 - drawPolygon [0 0 50 0 25 50 25 25] - - translate 60 0 - drawPath path - - translate 60 0 - drawPie 0 0 50 50 1440 2000 - - translate 60 0 - drawChord 0 0 50 50 1440 2000 - - translate 60 0 - drawLine 0 0 50 0 - drawLine 0 0 50 50 - drawLine 0 0 0 50 - - translate 60 0 - drawPolyline [0 0 50 0 25 50 25 25] - - translate 60 0 - drawArc 0 0 50 50 1440 2000 - - translate 60 0 - drawText 0 10 "Jambi-Bambi" - - translate 80 0 - drawPixmap bitmap 0 0 - restore -end_block - -translate 0 160 -setBackgroundMode Transparent -setPen ff7f7f 0 dotline flatcap beveljoin -repeat_block drawing - -translate 0 160 -setBackgroundMode Opaque -setPen ff7f7f 0 dotline flatcap beveljoin -repeat_block drawing - -translate 0 160 -setBackgroundMode Transparent -setPen ff7f7f 4 dashline flatcap beveljoin -repeat_block drawing - -translate 0 160 -setBackgroundMode OpaqueMode -setPen ff7f7f 4 dashline flatcap beveljoin -repeat_block drawing - -resetMatrix - -translate 5 5 - -setBrush nobrush -setPen black -setBackgroundMode transparent -drawText 10 15 "TransparentMode with solid 0-width pen" -drawRect 0 0 685 135 - -translate 0 160 -drawText 10 15 "TransparentMode with dotted 0-width pen" -drawRect 0 0 685 135 - -translate 0 160 -drawText 10 15 "OpaqueMode with dotted 0-width pen" -drawRect 0 0 685 135 - -translate 0 160 -drawText 10 15 "TransparentMode with dotted 4-width pen" -drawRect 0 0 685 135 - -translate 0 160 -drawText 10 15 "OpaqueMode with solid 4-width pen" -drawRect 0 0 685 135 diff --git a/tests/auto/lancelot/scripts/background_brush.qps b/tests/auto/lancelot/scripts/background_brush.qps deleted file mode 100644 index ca1f944964..0000000000 --- a/tests/auto/lancelot/scripts/background_brush.qps +++ /dev/null @@ -1,5 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -setBrush #00ff00 crosspattern -import "background.qps" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/beziers.qps b/tests/auto/lancelot/scripts/beziers.qps deleted file mode 100644 index 9b47cd05ac..0000000000 --- a/tests/auto/lancelot/scripts/beziers.qps +++ /dev/null @@ -1,147 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -setRenderHint LineAntialiasing - -translate 20 20 -path_moveTo fullSize 0 0 -path_cubicTo fullSize 200 100 -100 100 100 0 - -path_moveTo fullSize 0 200 -path_cubicTo fullSize 0 100 100 100 100 200 - -path_moveTo fullSize 0 250 -path_cubicTo fullSize 50 200 50 200 100 250 -drawPath fullSize - -translate 110 0 -scale 10 10 -path_moveTo medSize 0 0 -path_cubicTo medSize 20 10 -10 10 10 0 - -path_moveTo medSize 0 20 -path_cubicTo medSize 0 10 10 10 10 20 - -path_moveTo medSize 0 25 -path_cubicTo medSize 5 20 5 20 10 25 -drawPath medSize - -resetMatrix -translate 240 20 -scale 100 100 -path_moveTo smallSize 0 0 -path_cubicTo smallSize 2 1 -1 1 1 0 - -path_moveTo smallSize 0 2 -path_cubicTo smallSize 0 1 1 1 1 2 - -path_moveTo smallSize 0 2.5 -path_cubicTo smallSize 0.5 2 0.5 2 1 2.5 -drawPath smallSize - -resetMatrix -translate 20 300 -drawPath medSize - -resetMatrix -translate 250 -100 -path_moveTo maxSize 0 500 -path_cubicTo maxSize 1000 0 -500 0 500 500 -drawPath maxSize - -setRenderHint Antialiasing off -resetMatrix - -path_moveTo path1 0 0 -path_cubicTo path1 10 10 0 10 10 0 - -path_moveTo path2 0 0 -path_cubicTo path2 15 15 -5 15 10 0 - -path_moveTo path3 0 0 -path_cubicTo path3 20 20 -10 20 10 0 - -path_moveTo path4 0 0 -path_cubicTo path4 0 5 10 10 0 15 - -path_moveTo path5 0 10 -path_cubicTo path5 10 10 -10 20 0 0 - -path_moveTo path6 0 0 -path_cubicTo path6 10 5 -10 10 0 15 - -setPen black 2 -setBrush nobrush - -translate 10 500 -scale 3 3 -begin_block paths -save -drawPath path1 -translate 20 0 -drawPath path2 -translate 20 0 -drawPath path3 -translate 20 0 -drawPath path4 -translate 20 0 -drawPath path5 -translate 20 0 -drawPath path6 -restore -end_block - -setPen nopen -setBrush black - -translate 0 20 -repeat_block paths - -setRenderHint Antialiasing - -setPen black 2 -setBrush nobrush - -translate 120 -20 -repeat_block paths - -setPen nopen -setBrush black - -translate 0 20 -repeat_block paths - -resetMatrix -path_moveTo miterPath 20 0 -path_cubicTo miterPath 20 20 0 0 1 0 -path_lineTo miterPath -1 -0.2 - -setBrush nobrush - -translate 50 660 -scale 5 5 - -setPen black 4 solidline flatcap miterjoin -drawPath miterPath -setPen red 0 -drawPath miterPath - -path_moveTo miterPath2 21 0.2 -path_lineTo miterPath2 19 0 -path_cubicTo miterPath2 20 0 0 20 0 0 - -translate 30 0 -setPen black 4 solidline flatcap miterjoin -drawPath miterPath2 -setPen red 0 -drawPath miterPath2 - -path_moveTo wonkyPath 0 0 -path_cubicTo wonkyPath 5 15 20 0 17 0 - -translate 30 0 -setPen black 4 solidline flatcap miterjoin -drawPath wonkyPath -setPen red 0 -drawPath wonkyPath diff --git a/tests/auto/lancelot/scripts/bitmaps.qps b/tests/auto/lancelot/scripts/bitmaps.qps deleted file mode 100644 index a816b9d497..0000000000 --- a/tests/auto/lancelot/scripts/bitmaps.qps +++ /dev/null @@ -1,166 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -#setRenderHint SmoothPixmapTransform - -translate 10 50 -setBackground ff7f7f -setPen 3f3f9f - -bitmap_load dome_mono.png the_pixmap - -save - # Draw with opaque pen/bg in transparent/opaque mode - setBackgroundMode Transparent - drawPixmap the_pixmap 0 0 - setBackgroundMode Opaque - drawPixmap the_pixmap 110 0 - - translate 220 0 - - # Draw with alpha pen/bg in transparent/opaque mode - save - setBackground 7fff7f7f - setPen 7f3f3f9f - setBackgroundMode Transparent - drawPixmap the_pixmap 0 0 - setBackgroundMode Opaque - drawPixmap the_pixmap 110 0 - restore - - translate 220 0 - - # Draw with rotated opaque pen/bg in transparent/opaque mode - setBackgroundMode Transparent - save - translate 50 50 - rotate 10 - translate -50 -50 - drawPixmap the_pixmap 0 0 - restore - setBackgroundMode Opaque - translate 110 0 - save - translate 50 50 - rotate 10 - translate -50 -50 - drawPixmap the_pixmap 0 0 - restore -restore - -translate 0 150 - -save - setBackgroundMode Transparent - drawTiledPixmap the_pixmap 0 0 200 100 - setBackgroundMode Opaque - drawTiledPixmap the_pixmap 210 0 200 100 - - translate 440 -10 - save - rotate 10 - drawTiledPixmap the_pixmap 0 0 200 100 - restore -restore - -translate 0 150 -save - setBackgroundMode Transparent - drawTiledPixmap the_pixmap 0 0 200 100 10 20 - setBackgroundMode Opaque - drawTiledPixmap the_pixmap 210 0 200 100 10 20 - - translate 440 -10 - save - rotate 10 - drawTiledPixmap the_pixmap 0 0 200 100 10 20 - restore -restore - - -pixmap_setMask the_pixmap mask_100.png -drawPixmap the_pixmap 0 150 -setBackgroundMode Opaque -drawPixmap the_pixmap 110 150 - -translate 220 150 -save - translate 50 50 - rotate 10 - translate -50 -50 - setBackgroundMode Transparent - drawPixmap the_pixmap 0 0 -restore - -translate 110 0 -save - translate 50 50 - rotate 10 - translate -50 -50 - setBackgroundMode Opaque - drawPixmap the_pixmap 0 0 -restore - -resetMatrix -translate 10 650 -bitmap_load dome_mono.png the_bitmap -setBackgroundMode Transparent - -begin_block draw_subrected - drawPixmap the_bitmap 0 0 50 50 0 0 50 50 - drawPixmap the_bitmap 50 0 50 50 50 0 50 50 - drawPixmap the_bitmap 0 50 50 50 0 50 50 50 - drawPixmap the_bitmap 50 50 50 50 50 50 50 50 -end_block - -translate 110 0 -setBackgroundMode Opaque -repeat_block draw_subrected - -translate 110 0 -save - translate 20 -10 - rotate 10 - setBackgroundMode Transparent - repeat_block draw_subrected -restore - -translate 110 0 -save - translate 20 -10 - rotate 10 - setBackgroundMode Opaque - repeat_block draw_subrected -restore - -# Some helpful texts - -resetMatrix -setPen black -drawText 10 40 "Transparent" -drawText 120 40 "Opaque" -drawText 230 40 "Trans w/alpha" -drawText 340 40 "Opaque w/alpha" -drawText 450 40 "Trans w/xform" -drawText 560 40 "Opaque w/xform" - -drawText 10 190 "Transparent tiled" -drawText 220 190 "Opaque tiled" -drawText 440 190 "Opaque w/xform" - -drawText 10 340 "Transparent tiled w/offset" -drawText 220 340 "Opaque tiled w/offset" -drawText 440 340 "Opaque w/xform w/offset" - -drawText 10 490 "Trans masked" -drawText 120 490 "Opaque masked" -drawText 230 490 "masked w/xform" -drawText 340 490 "masked w/xform" - -drawText 10 640 "Subrected" -drawText 110 640 "Subrected opaque" -drawText 220 640 "subrect w/xform" -drawText 330 640 "subrect w/xform opaque" - - diff --git a/tests/auto/lancelot/scripts/borderimage.qps b/tests/auto/lancelot/scripts/borderimage.qps deleted file mode 100644 index ebd4f4d249..0000000000 --- a/tests/auto/lancelot/scripts/borderimage.qps +++ /dev/null @@ -1,120 +0,0 @@ -# Version: 1 -# CheckVsReference: 10% - -image_load borderimage.png borderimage -translate -128 -128 -begin_block draw_border -# top -drawImage borderimage 0 0 16 16 0 0 16 16 -drawImage borderimage 16 0 36 16 16 0 32 16 -drawImage borderimage 52 0 16 16 48 0 16 16 -# sides -drawImage borderimage 0 16 16 16 0 16 16 32 -drawImage borderimage 52 16 16 16 48 16 16 32 -#bottom -drawImage borderimage 0 32 16 16 0 48 16 16 -drawImage borderimage 16 32 36 16 16 48 32 16 -drawImage borderimage 52 32 16 16 48 48 16 16 -end_block draw_border -resetMatrix -begin_block draw_column -translate 1 1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -translate 0.1 64.1 -repeat_block draw_border -end_block draw_column -setRenderHint Antialiasing -resetMatrix -translate 72 0 -repeat_block draw_column -resetMatrix -scale 1.25 1.25 -translate 144 0 -repeat_block draw_border -resetMatrix -scale 1.25 1.25 -translate 246 0 -rotate 30 -repeat_block draw_border -setRenderHint SmoothPixmapTransform -resetMatrix -scale 1.25 1.25 -translate 144 120 -repeat_block draw_border -resetMatrix -scale 1.25 1.25 -translate 246 120 -rotate 30 -repeat_block draw_border -resetMatrix -translate 215 260 -scale 3.55 3.55 -rotate 30 -repeat_block draw_border -resetMatrix -setRenderHint SmoothPixmapTransform off -setRenderHint Antialiasing off -translate 480 627 -rotate 180 -repeat_block draw_column -resetMatrix -setRenderHint Antialiasing -translate 552 627 -rotate 180 -repeat_block draw_column -resetMatrix -setRenderHint Antialiasing off -translate 200.1 520.1 -begin_block one_pixel_border -drawImage borderimage 0 0 16 16 0 0 16 16 -drawImage borderimage 16 0 64 16 16 0 1 1 -drawImage borderimage 80 0 16 16 48 0 16 16 -drawImage borderimage 0 16 16 64 16 0 1 1 -drawImage borderimage 80 16 16 64 16 0 1 1 -drawImage borderimage 0 80 16 16 0 48 16 16 -drawImage borderimage 16 80 64 16 16 0 1 1 -drawImage borderimage 80 80 16 16 48 48 16 16 -end_block one_pixel_border -resetMatrix -translate 205.1 626.1 -scale 0.4 0.4 -repeat_block one_pixel_border -resetMatrix -translate 255.1 624.1 -scale 0.4 0.4 -rotate 10 -repeat_block one_pixel_border -resetMatrix -setPen red -drawRect 0 0 70 680 -drawText 10 670 "aa off" -drawRect 72 0 70 680 -drawText 80 670 "aa on" -drawRect 409 0 70 680 -drawText 419 650 "rot 180" -drawText 419 670 "aa off" -drawRect 481 0 70 680 -drawText 491 650 "rot 180" -drawText 491 670 "aa on" -drawRect 164 0 224 124 -drawText 174 114 "smoothpixmaptransform off" -drawRect 164 128 224 134 -drawText 174 252 "smoothpixmaptransform on" -drawRect 200 520 97 188 -drawText 210 698 "1x1 edges" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/brush_pens.qps b/tests/auto/lancelot/scripts/brush_pens.qps deleted file mode 100644 index b9a2bc0ada..0000000000 --- a/tests/auto/lancelot/scripts/brush_pens.qps +++ /dev/null @@ -1,104 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -path_addRect p 0 0 75 75 -path_addEllipse p 25 25 75 75 - -translate 10 10 - -begin_block setup_gradient - gradient_clearStops - gradient_appendStop 0 red - gradient_appendStop 0.1 blue - gradient_appendStop 0.2 yellow - gradient_appendStop 0.3 cyan - gradient_appendStop 0.4 magenta - gradient_appendStop 0.5 green - gradient_appendStop 0.6 black - gradient_appendStop 0.7 indianred - gradient_appendStop 0.8 white - gradient_appendStop 0.9 orange - gradient_appendStop 1 blue - gradient_setLinear 0 0 100 100 -end_block - -setPen brush 0 -setBrush nobrush - -begin_block drawing - save - drawLine 0 0 100 100 - - translate 0 100 - drawPath p - - translate 0 110 - drawRect 0 0 100 100 - - translate 0 110 - drawPolyline [0 0 100 0 50 50] - - drawPoint 40 40 - drawPoint 41 40 - drawPoint 42 40 - drawPoint 43 40 - drawPoint 44 40 - drawPoint 45 40 - drawPoint 46 40 - drawPoint 47 40 - drawPoint 48 40 - drawPoint 49 40 - drawPoint 50 40 - - restore -end_block - -save - translate 110 0 - save - setRenderHint Antialiasing - repeat_block drawing - restore - - setBrush dome_rgb32.png - setPen brush 0 - setBrush nobrush - - translate 110 0 - repeat_block drawing - - translate 110 0 - save - setRenderHint Antialiasing - repeat_block drawing - restore -restore - -translate 0 0 - -save - repeat_block setup_gradient - setPen brush 5 - setBrush nobrush - translate 0 350 - repeat_block drawing - - translate 110 0 - save - setRenderHint Antialiasing - repeat_block drawing - restore - - setBrush dome_rgb32.png - setPen brush 5 - setBrush nobrush - - translate 110 0 - repeat_block drawing - - translate 110 0 - save - setRenderHint Antialiasing - repeat_block drawing - restore -restore \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/brushes.qps b/tests/auto/lancelot/scripts/brushes.qps deleted file mode 100644 index 82cbff48b9..0000000000 --- a/tests/auto/lancelot/scripts/brushes.qps +++ /dev/null @@ -1,79 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -# Fill the background -drawRect 0 0 width height - -setRenderHint Antialiasing -setRenderHint SmoothPixmapTransform - -translate 10 10 -# Draw all the pattern types as 40x40 rects using green, transparent background -begin_block drawrects -setBrush green Dense1Pattern -drawRect 0 0 40 40 -setBrush green Dense2Pattern -drawRect 40 0 40 40 -setBrush green Dense3Pattern -drawRect 80 0 40 40 -setBrush green Dense4Pattern -drawRect 120 0 40 40 -setBrush green Dense5Pattern -drawRect 160 0 40 40 -setBrush green Dense6Pattern -drawRect 200 0 40 40 -setBrush green Dense7Pattern -drawRect 240 0 40 40 -setBrush green HorPattern -drawRect 280 0 40 40 -setBrush green VerPattern -drawRect 320 0 40 40 -setBrush green CrossPattern -drawRect 360 0 40 40 -setBrush green BDiagPattern -drawRect 400 0 40 40 -setBrush green FDiagPattern -drawRect 440 0 40 40 -setBrush green DiagCrossPattern -drawRect 480 0 40 40 -setBrush green SolidPattern -drawRect 520 0 40 40 -setBrush green NoBrush -drawRect 560 0 40 40 -gradient_setLinear 0 0 0 40 -drawRect 600 0 40 40 -setBrush face.png -drawRect 640 0 80 40 -end_block - -# Switch to opaque mode -setBackground #7fff7f -setBackgroundMode OpaqueMode -translate 0 50 - -# Draw all the pattern types as 40x40 rects using green, opaque background -repeat_block drawrects - -translate 50 50 -rotate 10 - - -setBackgroundMode TransparentMode -repeat_block drawrects -setBackgroundMode OpaqueMode -translate 0 40 -repeat_block drawrects - - -setBrush dot.png -setPen nopen -resetMatrix -drawRect 0 200 50 50 -drawRect 50 200 50 50 - -setPen red -setBrushOrigin 0 250 -drawRect 0 250 50 50 -setBrushOrigin 50 250 -drawRect 50 250 50 50 - diff --git a/tests/auto/lancelot/scripts/clippaths.qps b/tests/auto/lancelot/scripts/clippaths.qps deleted file mode 100644 index fba89784df..0000000000 --- a/tests/auto/lancelot/scripts/clippaths.qps +++ /dev/null @@ -1,60 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -path_addRect hor 0 0 50 10 -path_addRect ver 0 0 10 50 - -translate 10 10 -setPen NoPen - -begin_block clipping -save - - setBrush 0x7f7fff - save - setClipPath hor - drawRect 0 0 100 100 - - setClipPath ver IntersectClip - setBrush black CrossPattern - drawRect 0 0 100 100 - restore - - translate 100 0 - save - setClipPath hor - drawRect 0 0 100 100 - - setClipPath ver ReplaceClip - setBrush black CrossPattern - drawRect 0 0 100 100 - restore - - translate 100 0 - save - setClipPath hor - drawRect 0 0 100 100 - - setClipPath ver UniteClip - setBrush black CrossPattern - drawRect 0 0 100 100 - restore - -restore -end_block - -translate 300 0 -setRenderHint Antialiasing -repeat_block clipping - -translate -300 100 -setRenderHint Antialiasing false -scale 1.2 1.2 -repeat_block clipping - -translate 300 0 -setRenderHint Antialiasing -setRenderHint SmoothPixmapTransform -repeat_block clipping - - diff --git a/tests/auto/lancelot/scripts/clipping.qps b/tests/auto/lancelot/scripts/clipping.qps deleted file mode 100644 index 3694ff2ba7..0000000000 --- a/tests/auto/lancelot/scripts/clipping.qps +++ /dev/null @@ -1,182 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -region_addRect clip 50 0 90 190 -region_addRect clip 0 50 180 90 - -region_addRect clip2 30 30 60 60 - -region_addRect clip3 10 10 60 60 - -path_cubicTo path 90 0 50 50 90 90 -path_cubicTo path 0 90 50 50 0 0 - -path_addRect path2 0 0 90 90 -path_moveTo path2 90 45 -path_arcTo path2 0 0 90 90 0 -360 - -path_addRect emptypath 0 0 0 0 -region_addRect emptyregion 0 0 0 0 - -# Normal clip rect -setClipRect 0 0 50 150 -begin_block repaint -save -setBrush red -setPen nopen -resetMatrix -region_getClipRegion tmpclip -path_getClipPath tmpclippath -drawRect 0 0 width height -setBrush #3f0000ff -setClipRegion tmpclip -drawRect 0 0 width height -setClipPath tmpclippath -setBrush #3f00ff00 -drawRect 0 0 width height -restore -end_block - -# Rotated clip rect -translate 100 0 -rotate 10 -setClipRect 0 0 50 150 -repeat_block repaint - -# simple clip region -resetMatrix -translate 0 200 -setClipRegion clip -repeat_block repaint - -# simle rotated clip region -translate 250 -10 -rotate 10 -setClipRegion clip -repeat_block repaint - -# verify that clip is not xformed with painter -resetMatrix -translate 200 0 -setClipRegion clip -rotate 30 -setBrush red -setPen nopen -drawRect 0 0 width height - -resetMatrix -translate 0 400 -save -setClipRegion clip -setClipRegion clip2 IntersectClip -repeat_block repaint -translate 0 100 -rotate 10 -setClipRegion clip -setClipRegion clip2 IntersectClip -restore - -translate 100 0 -save -setClipRegion clip3 -setClipRegion clip2 UniteClip -repeat_block repaint -translate 0 100 -rotate 10 -setClipRegion clip3 -setClipRegion clip2 UniteClip -repeat_block repaint -restore - -translate 100 0 -save -setClipPath path -repeat_block repaint -translate 50 100 -rotate 45 -setClipPath path -repeat_block repaint -restore - -translate 100 0 -save -setClipPath path -setClipPath path2 IntersectClip -repeat_block repaint -translate 0 100 -rotate 10 -setClipPath path -setClipPath path2 IntersectClip -repeat_block repaint -restore - -translate 100 0 -save -setClipPath path -setClipPath path2 UniteClip -repeat_block repaint -translate 0 100 -rotate 10 -setClipPath path -setClipPath path2 UniteClip -repeat_block repaint -restore - -translate 100 0 -save -setClipPath path -setClipRegion clip3 IntersectClip -repeat_block repaint -translate 0 100 -rotate 10 -setClipRegion clip3 -setClipPath path IntersectClip -repeat_block repaint -restore - -translate 100 0 -save -setClipPath path -setClipRegion clip3 UniteClip -repeat_block repaint -translate 0 100 -rotate 10 -setClipRegion clip3 -setClipPath path UniteClip -repeat_block repaint -restore - -# test that an empty region is not drawn. -resetMatrix -setClipRegion emptyregion -setBrush #3f00ff00 -drawRect 0 0 300 300 -drawText 50 50 "Text should be clipped away by region" -setClipping false - -setClipPath emptypath -setBrush #3fffff00 -drawRect 50 50 300 300 -drawText 70 80 "Text should be clipped away by path" - -# Test that we can extract a clipregion when a matrix is set too -resetMatrix -translate 500 10 -scale 2 1 -setBrush blue -setClipping false -rotate 5 -drawRect 0 0 100 100 -setClipRect 0 0 100 100 -resetMatrix -rotate 10 -region_getClipRegion xclip -setClipRegion xclip -resetMatrix -setBrush #7f00ff00 -drawRect 0 0 width height - -# the below used to assert in debug mode -setClipRect 10 10 20 20 -setClipping false -setClipping true \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/clipping_state.qps b/tests/auto/lancelot/scripts/clipping_state.qps deleted file mode 100644 index a29d3738c8..0000000000 --- a/tests/auto/lancelot/scripts/clipping_state.qps +++ /dev/null @@ -1,47 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -path_addRect path1 10 10 50 50 -path_addRect path2 30 30 50 50 -# enable/disable a clip path -setPen nopen -setBrush red -setClipPath path1 -setClipPath path2 UniteClip -drawRect 0 0 100 100 -setClipping false -setBrush #630000ff -drawRect 0 0 100 100 -setClipping true -setBrush #6300ff00 -drawRect 0 0 100 100 -# enable/disable noclip -translate 150 0 -setClipPath path1 NoClip -setClipping false -setBrush #630000ff -drawRect 0 0 100 100 -setClipping true -setBrush #6300ff00 -drawRect 25 25 50 50 -# enable/disable full clipping -translate 150 0 -path_addRect path3 0 0 10 10 -path_addRect path4 20 20 10 10 -setClipPath path3 -setClipPath path4 IntersectClip -setClipping false -setBrush #630000ff -drawRect 0 0 100 100 -setClipping true -setBrush #6300ff00 -drawRect 25 25 50 50 -# disable clipping followed by setClipRect -translate 150 0 -setClipRect 0 0 50 50 ReplaceClip -setClipping false -setBrush #630000ff -drawRect 0 0 100 100 -setClipRect 25 25 75 75 IntersectClip -setBrush #6300ff00 -drawRect 25 25 50 50 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/cliprects.qps b/tests/auto/lancelot/scripts/cliprects.qps deleted file mode 100644 index 0d28b035b4..0000000000 --- a/tests/auto/lancelot/scripts/cliprects.qps +++ /dev/null @@ -1,59 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - - -translate 10 10 -setPen NoPen - -begin_block clipping -save - - setBrush 0x7f7fff - save - setClipRect 0 0 50 10 - drawRect 0 0 100 100 - - setClipRect 0 0 10 50 IntersectClip - setBrush black CrossPattern - drawRect 0 0 100 100 - restore - - translate 100 0 - save - setClipRect 0 0 50 10 - drawRect 0 0 100 100 - - setClipRect 0 0 10 50 ReplaceClip - setBrush black CrossPattern - drawRect 0 0 100 100 - restore - - translate 100 0 - save - setClipRect 0 0 50 10 - drawRect 0 0 100 100 - - setClipRect 0 0 10 50 UniteClip - setBrush black CrossPattern - drawRect 0 0 100 100 - restore - -restore -end_block - -translate 300 0 -setRenderHint Antialiasing -repeat_block clipping - -translate -300 100 -setRenderHint Antialiasing false -scale 1.2 1.2 -repeat_block clipping - -translate 300 0 -setRenderHint Antialiasing -setRenderHint SmoothPixmapTransform -repeat_block clipping - - diff --git a/tests/auto/lancelot/scripts/conical_gradients.qps b/tests/auto/lancelot/scripts/conical_gradients.qps deleted file mode 100644 index 2e897b1813..0000000000 --- a/tests/auto/lancelot/scripts/conical_gradients.qps +++ /dev/null @@ -1,85 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -path_addRect path 300 0 80 80 -path_addEllipse path 340 40 60 60 - -setRenderHint Antialiasing - -setPen black - -begin_block gradients -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setConical 40 40 50 -drawRect 0 0 100 100 - -gradient_setConical 140 40 230 -drawEllipse 100 0 100 100 - -gradient_clearStops -gradient_appendStop 0 3f7f7fff -gradient_appendStop 0.5 dfdfffff -gradient_appendStop 1 7f00007f - -gradient_setConical 240 40 50 -drawPolygon [200 0 290 0 250 99] - -gradient_setConical 340 40 230 -drawPath path - -end_block - -translate 0 100 -scale 1 2 -repeat_block gradients - -resetMatrix -translate 0 300 -brushTranslate 30 0 -brushScale 0.9 0.9 -brushRotate 20 -repeat_block gradients - -# Some helpful info perhaps? -resetMatrix -setPen black - -drawText 410 50 "No XForm" -drawText 410 200 "scale 1x2" -drawText 410 300 "brush transform" -drawText 10 450 "50 deg" -drawText 110 450 "230 deg" -drawText 210 450 "50 deg w/alpha " -drawText 310 450 "230 deg w/alpha" - -setPen 3f000000 -setBrush nobrush - -begin_block ellipse_draw - setClipRect 0 0 100 100 - drawEllipse 35 35 11 11 - save - translate 40 40 - rotate -50 - drawLine -100 0 100 0 - restore - translate 100 0 -end_block - -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw - -resetMatrix -translate 0 100 -scale 1 2 -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/conical_gradients_perspectives.qps b/tests/auto/lancelot/scripts/conical_gradients_perspectives.qps deleted file mode 100644 index a9c14f1ce7..0000000000 --- a/tests/auto/lancelot/scripts/conical_gradients_perspectives.qps +++ /dev/null @@ -1,64 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -setRenderHint Antialiasing - -setPen #00ff00 - -translate 10 10 -# standard draw -begin_block gradient -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 0.9 cyan -gradient_appendStop 1 red - -gradient_setSpread PadSpread -gradient_setConical 140 140 100 -drawRect 0 0 300 300 -end_block gradient - -# Rotation w/o smooth xform -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 - repeat_block gradient -restore -restore - -translate 0 320 - -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 - repeat_block gradient -restore - -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 - repeat_block gradient -restore -restore - - -resetMatrix -setPen black -translate 125 20 -drawText 0 0 "No transform" -translate 350 0 -drawText 0 0 "Left Tilted" -resetMatrix -translate 125 350 -drawText 0 0 "Bottom Tilted" -translate 350 0 -drawText 0 0 "Right Tilted" -translate 120 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/dashes.qps b/tests/auto/lancelot/scripts/dashes.qps deleted file mode 100644 index 649f56cf66..0000000000 --- a/tests/auto/lancelot/scripts/dashes.qps +++ /dev/null @@ -1,268 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -translate 20 20 - -begin_block draw -save - save - setPen black 1 SolidLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 SolidLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 SolidLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 2 SolidLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 SolidLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 SolidLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 6 SolidLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 SolidLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 SolidLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - restore - - - translate 100 0 - save - setPen black 1 DotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 2 DotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 6 DotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 DotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 DotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - restore - - translate 100 0 - save - setPen black 1 DashLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DashLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DashLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 2 DashLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DashLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DashLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 6 DashLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 DashLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 DashLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - restore - - translate 100 0 - - save - setPen black 1 DashDotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DashDotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DashDotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 2 DashDotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DashDotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DashDotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 6 DashDotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 DashDotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 6 DashDotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - restore - - translate 100 0 - - save - setPen black 1 DashDotDotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DashDotDotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 DashDotDotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 2 DashDotDotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DashDotDotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 DashDotDotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 4 DashDotDotLine FlatCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 4 DashDotDotLine SquareCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 4 DashDotDotLine RoundCap BevelJoin - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - restore - - translate 100 0 - - save - setPen black 1 SolidLine FlatCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 SolidLine SquareCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 1 SolidLine RoundCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 2 SolidLine FlatCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 SolidLine SquareCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 2 SolidLine RoundCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - - setPen black 4 SolidLine FlatCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 4 SolidLine SquareCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - setPen black 4 SolidLine RoundCap BevelJoin - pen_setDashPattern [1 4 9 4 27 4] - drawPolyline [0 0 80 0 80 30 40 20 0 30] - translate 0 40 - restore - -restore -end_block - -translate 0 400 -setRenderHint Antialiasing -repeat_block draw - -translate 0 -20 -drawText 30 0 "Solid" - -translate 100 0 -drawText 20 0 "DotLine" - -translate 100 0 -drawText 10 0 "DashLine" - -translate 100 0 -drawText 0 0 "DashDotLine" - -translate 100 0 -drawText 0 0 "DashDotDotLine" - -translate 100 0 -drawText 0 0 "CustomDashLine" - -resetMatrix - -translate 620 40 - -begin_block width_and_caps_texts - drawText 0 0 "Width=1, FlatCap" - translate 0 40 - drawText 0 0 "Width=1, SquareCap" - translate 0 40 - drawText 0 0 "Width=1, RoundCap" - translate 0 40 - drawText 0 0 "Width=2, FlatCap" - translate 0 40 - drawText 0 0 "Width=2, SquareCap" - translate 0 40 - drawText 0 0 "Width=2, RoundCap" - translate 0 40 - drawText 0 0 "Width=6, FlatCap" - translate 0 40 - drawText 0 0 "Width=6, SqareCap" - translate 0 40 - drawText 0 0 "Width=6, RoundCap" -end_block - -translate 0 80 -repeat_block width_and_caps_texts \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/degeneratebeziers.qps b/tests/auto/lancelot/scripts/degeneratebeziers.qps deleted file mode 100644 index fb223d5b1f..0000000000 --- a/tests/auto/lancelot/scripts/degeneratebeziers.qps +++ /dev/null @@ -1,10 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -path_moveTo degenerate 3427.0918499999997948 3872.1318999999998596 -path_cubicTo degenerate 3427.0918499999997948 3872.1318999999994048 4729.4590867905308187 5176.8613451144155988 5389.9325499999995372 5837.8072499999998399 - -scale 0.05 0.05 -translate -2500 -3000 -setPen black 800 -drawPath degenerate \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/deviceclipping.qps b/tests/auto/lancelot/scripts/deviceclipping.qps deleted file mode 100644 index cedfc1e363..0000000000 --- a/tests/auto/lancelot/scripts/deviceclipping.qps +++ /dev/null @@ -1,48 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -setBrush 0xff7f7f -setPen 0x7f0000 - -path_moveTo path -1000000 10000 -path_cubicTo path 100 100 100 150 150 400 -path_closeSubpath path - -begin_block drawing - - drawPath ellipse - - drawLine -1000000 200 200 200 - drawLine 200 -1000000 200 200 - drawLine 200 200 1000000 200 - drawLine 200 200 200 1000000 - drawLine -1000000 -1000000 200 200 - - drawPolygon [-1000000 100 100 -1000000 100 100] - drawRect 300 -500000 1000000 1000000 - - drawPath path - -end_block - -save -translate 20 20 -setBrush #0x7f7f7fff -setPen #0x7f00007f -repeat_block drawing - -translate 20 20 -setRenderHint Antialiasing -setBrush #0x7f7fff7f -setPen #0x7f007f00 -repeat_block drawing -restore - -setPen 0x00007f 2 -setRenderHint Antialiasing - -drawLine 0 -200 200 200 - -setPen 0x007f00 10 - -drawLine 0 -200 200 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/drawpoints.qps b/tests/auto/lancelot/scripts/drawpoints.qps deleted file mode 100644 index c02cd85737..0000000000 --- a/tests/auto/lancelot/scripts/drawpoints.qps +++ /dev/null @@ -1,101 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -#setRenderHint Antialiasing - -setPen red 0 solidline -begin_block points -drawPoint 00 00 -drawPoint 10 00 -drawPoint 20 00 -drawPoint 30 00 -drawPoint 40 00 -drawPoint 50 00 -drawPoint 00 10 -drawPoint 10 10 -drawPoint 20 10 -drawPoint 30 10 -drawPoint 40 10 -drawPoint 50 10 -drawPoint 00 20 -drawPoint 10 20 -drawPoint 20 20 -drawPoint 30 20 -drawPoint 40 20 -drawPoint 50 20 -drawPoint 00 30 -drawPoint 10 30 -drawPoint 20 30 -drawPoint 30 30 -drawPoint 40 30 -drawPoint 50 30 -drawPoint 00 40 -drawPoint 10 40 -drawPoint 20 40 -drawPoint 30 40 -drawPoint 40 40 -drawPoint 50 40 -drawPoint 00 50 -drawPoint 10 50 -drawPoint 20 50 -drawPoint 30 50 -drawPoint 40 50 -drawPoint 50 50 -end_block points - -translate 100 0 -setPen blue 1 solidline -repeat_block points - -translate 100 0 -setPen green 5 solidline roundcap -repeat_block points - -resetMatrix - -translate 0 100 -scale 3 3 -setPen red 0 solidline roundcap -repeat_block points - -translate 60 0 -setPen blue 1 solidline roundcap -repeat_block points - -translate 60 0 -setPen green 5 solidline roundcap -repeat_block points - -resetMatrix - -translate 0 300 -scale 3 3 -setPen red 0 solidline flatcap -repeat_block points - -translate 60 0 -setPen blue 1 solidline flatcap -repeat_block points - -translate 60 0 -setPen green 5 solidline flatcap -repeat_block points - -resetMatrix -translate 10 500 -setPen black 1 solidline flatcap -drawPoint 0 0 -setPen black 2 solidline flatcap -drawPoint 3 0 -setPen black 3 solidline flatcap -drawPoint 8 0 -setPen black 4 solidline flatcap -drawPoint 15 0 -setPen black 5 solidline flatcap -drawPoint 24 0 -setPen black 6 solidline flatcap -drawPoint 35 0 -setPen black 7 solidline flatcap -drawPoint 48 0 -setPen black 8 solidline flatcap -drawPoint 63 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/ellipses.qps b/tests/auto/lancelot/scripts/ellipses.qps deleted file mode 100644 index e2cffd7f27..0000000000 --- a/tests/auto/lancelot/scripts/ellipses.qps +++ /dev/null @@ -1,86 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -surface_begin 0 0 600 600 -translate 0 50 - -setPen nopen -setBrush 0x7f000000 -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setRadial 20 20 220 200 - -drawEllipse 10 10 80 80 -drawEllipse 50 50 120 90 - -translate 100 0 -brushTranslate 40 20 -brushScale 0.25 0.25 - -setPen black - -drawEllipse 10 10 80 80 -setOpacity 0.5 -setCompositionMode SourceIn -drawEllipse 50 50 120 90 -setOpacity 1.0 -setRenderHint Antialiasing -setCompositionMode Xor -brushTranslate 70 0 -translate 100 0 -drawEllipse 10 10 80 80 - -setPen nopen -drawEllipse 50 50 120 90 - -setOpacity 0.7 -setBrush red -translate 100 0 -setCompositionMode SourceOver - -drawEllipse 10 10 80 80 - -setOpacity 0.6 -setPen black 5.0 -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setLinear 20 20 120 100 -drawEllipse 50 50 120 90 - - -translate 100 0 - -setOpacity 1.0 -drawEllipse 10 10 80 80 - -setCompositionMode SourceIn -setOpacity 0.7 -setPen black 3.0 -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setLinear 50 50 80 90 -drawEllipse 50 50 120 90 - -surface_end - -drawText 200 220 "Testing Ellipse drawing with varios combinations" -drawText 200 240 "of features such as brushes, pens and composition modes" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/filltest.qps b/tests/auto/lancelot/scripts/filltest.qps deleted file mode 100644 index 2eeba2ecf6..0000000000 --- a/tests/auto/lancelot/scripts/filltest.qps +++ /dev/null @@ -1,413 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -setPen nopen -setBrush red -translate 0 4 -begin_block polys -drawPolygon [0 0 2 -2 4 0] -drawPolygon [0 2 2 4 4 2] -end_block polys -translate 6 .5 -repeat_block polys -translate 6.5 0 -repeat_block polys -translate 6 .5 -repeat_block polys - -resetMatrix - -translate 0 12 -setPen black -drawPolygon [0 0 5 0 5 5 0 5] - -translate 10 0 -setPen nopen -drawPolygon [0 0 5 0 5 5 0 5] - -translate 10 0 -drawPolygon [0 0 5 0 5 5 0 5] - -setBrush black -path_addRect stroke -.5 -.5 6 6 -path_addRect stroke .5 .5 4 4 -drawPath stroke - -resetMatrix - -translate 0 65 - -setPen red -drawText 0 0 "path" -drawText 40 0 "rect" -drawText 80 0 "img" -drawText 120 0 "pix" -drawText 160 0 "brush" -setPen nopen - -translate 0 5 - -image_load border.png img -pixmap_load border.png pix - -path_addRect rect 0 0 10 10 -begin_block rects -drawPath rect -drawRect 40 0 10 10 -drawImage img 80 0 -drawPixmap pix 120 0 -setBrush border.png -drawRect 160 0 10 10 -setBrush black -end_block rects - -setPen red -drawText 180 10 "0.0" -setPen nopen - -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.1" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.2" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.3" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.4" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.5" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.6" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.7" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.8" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "0.9" -setPen nopen -translate 0.1 20 -repeat_block rects -setPen red -drawText 180 10 "1.0" -setPen nopen - -resetMatrix - -translate 0 400 - -setPen red -drawText 0 10 "path" -drawText 0 30 "rect" -drawText 0 50 "img" -drawText 0 70 "pix" -drawText 0 90 "brush" -drawText 0 110 "stroke" -drawText 0 130 "scale" -drawText 0 170 "rotate" -setPen nopen - -translate 50 0 - -begin_block rects -drawPath rect -drawRect 0 20 10 10 -drawImage img 0 40 -drawPixmap pix 0 60 -save -setBrush border.png -drawRect 0 80 10 10 -translate 0 100 -setBrush red -setPen black -drawRect 0 0 10 10 -setBrush border.png -setPen nopen -translate 0 20 -scale 2 2 -drawRect 0 0 10 10 -translate 10 20 -rotate 90 -drawRect 0 0 10 10 -restore -end_block rects - -setPen red -drawText -5 -10 "0.0" -setPen nopen - -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.1" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.2" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.3" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.4" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.5" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.6" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.7" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.8" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "0.9" -setPen nopen -translate 40 0.1 -repeat_block rects -setPen red -drawText -5 -10 "1.0" -setPen nopen - -resetMatrix - -translate 0 620 - -setPen red -drawText 0 10 "path" -setPen nopen - -path_addRect rect2 -5 -5 10 10 - -translate 55 5 -drawPath rect2 - -translate 20 0 -rotate 10 -drawPath rect2 -rotate -10 -translate 20 0 -rotate 20 -drawPath rect2 -rotate -20 -translate 20 0 -rotate 30 -drawPath rect2 -rotate -30 -translate 20 0 -rotate 40 -drawPath rect2 -rotate -40 -translate 20 0 -rotate 50 -drawPath rect2 -rotate -50 -translate 20 0 -rotate 60 -drawPath rect2 -rotate -60 -translate 20 0 -rotate 70 -drawPath rect2 -rotate -70 -translate 20 0 -rotate 80 -drawPath rect2 -rotate -80 -translate 20 0 -rotate 90 -drawPath rect2 -rotate -90 - -resetMatrix - -translate 0 600 - -setPen red -drawText 0 10 "rect" -setPen nopen - -translate 55 5 -drawRect -5 -5 10 10 - -translate 20 0 -rotate 10 -drawRect -5 -5 10 10 -rotate -10 -translate 20 0 -rotate 20 -drawRect -5 -5 10 10 -rotate -20 -translate 20 0 -rotate 30 -drawRect -5 -5 10 10 -rotate -30 -translate 20 0 -rotate 40 -drawRect -5 -5 10 10 -rotate -40 -translate 20 0 -rotate 50 -drawRect -5 -5 10 10 -rotate -50 -translate 20 0 -rotate 60 -drawRect -5 -5 10 10 -rotate -60 -translate 20 0 -rotate 70 -drawRect -5 -5 10 10 -rotate -70 -translate 20 0 -rotate 80 -drawRect -5 -5 10 10 -rotate -80 -translate 20 0 -rotate 90 -drawRect -5 -5 10 10 -rotate -90 - -resetMatrix -path_addRect vertical 0.1 0.1 0.2 10 - -translate 0 320 -drawPath vertical -translate 2.2 0 -drawPath vertical -translate 2.2 0 -drawPath vertical -translate 2.2 0 -drawPath vertical -translate 2.2 0 -drawPath vertical - -resetMatrix -path_addRect horizontal 0.1 0.1 10 0.2 - -translate 0 340 -drawPath horizontal -translate 0 2.2 -drawPath horizontal -translate 0 2.2 -drawPath horizontal -translate 0 2.2 -drawPath horizontal -translate 0 2.2 -drawPath horizontal - -setOpacity 0.8 -resetMatrix - -translate 0.1 24.7 -translate 400 0 -#rotate 88.8 -rotate 89.9 -setBrush red -drawPolygon [0 0 300 0 0 173] -setBrush green -drawPolygon [0 173 300 0 300 173] - -resetMatrix - -translate 410 24 -path_lineTo left 0 273 -path_lineTo left 300 273 -path_cubicTo left 50 273 250 0 0 0 - -path_cubicTo right 250 0 50 273 300 273 -path_lineTo right 300 0 - -translate 310 0 -rotate 90 -setBrush red -drawPath left -setBrush green -drawPath right - -resetMatrix -translate 0.1 680.1 -setPen red -setOpacity 1 -drawText 115 -20 "0.1" -drawText 0 0 "pixmap w/ opacity" -setOpacity 0.6 -drawPixmap pix 120 -10 -translate 0 20 -setOpacity 1 -drawText 0 0 "image w/ opacity" -setOpacity 0.6 -drawImage img 120 -10 - -resetMatrix -path_lineTo fillpath 0 50 -path_lineTo fillpath 50 50 -path_moveTo fillpath 70 50 -path_lineTo fillpath 70 100 -path_lineTo fillpath 40 100 -translate 500 400 -drawPath fillpath - -resetMatrix -path_moveTo vectorarne 50 10 -path_lineTo vectorarne 50 50 -path_lineTo vectorarne 100 50 -path_addEllipse vectorarne 350 20 230 230 -path_moveTo vectorarne 500 500 -path_cubicTo vectorarne 20 20 250 30 50 150 -translate 500 550 -scale 0.4 0.4 -setRenderHint antialiasing -drawPath vectorarne - -resetMatrix -translate 200 730 -setRenderHint antialiasing off -setOpacity 1 -setPen red -drawText 0 0 "outline/fill consistency" -setPen red -setBrush green -translate 80 -30 -drawPolygon [13.6965 -99.1837 -71.4767 13.823 32.4596 -33.1847] \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/gradients.qps b/tests/auto/lancelot/scripts/gradients.qps deleted file mode 100644 index eb3cda9cad..0000000000 --- a/tests/auto/lancelot/scripts/gradients.qps +++ /dev/null @@ -1,44 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -drawText 75 20 "Linear" -drawText 176 20 "Radial" -drawText 277 20 "Conical" -translate 0 30 -drawText 0 50 "AA off" -drawText 0 151 "AA on" - -setPen nopen - -gradient_clearStops -gradient_appendStop 0 0x00000000 -gradient_appendStop 0.001 red -gradient_appendStop 0.2 blue -gradient_appendStop 0.4 yellow -gradient_appendStop 0.6 cyan -gradient_appendStop 0.8 green -gradient_appendStop 0.999 red -gradient_appendStop 1 0x00000000 - -gradient_setSpread PadSpread -gradient_setCoordinateMode ObjectBoundingMode - -begin_block row -save -gradient_setLinear 0.1 0.0 0.9 0.0 -drawRect 50 0 100 100 - -gradient_setRadial 0.5 0.5 0.5 0.5 0.5 -translate 101 0 -drawRect 50 0 100 100 - -gradient_setConical 0.5 0.5 45 -translate 101 0 -drawRect 50 0 100 100 -restore -end_block row - -setRenderHint Antialiasing - -translate 0 101 -repeat_block row \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/hinting.qps b/tests/auto/lancelot/scripts/hinting.qps deleted file mode 100644 index 7ce21b287a..0000000000 --- a/tests/auto/lancelot/scripts/hinting.qps +++ /dev/null @@ -1,26 +0,0 @@ -translate 10 50 -setFont "sansserif" 10 -drawText 0 0 "Default hinting:" -setFont "times" 12 normal normal default -drawText 0 20 "The quick brown fox jumps over the lazy dog" - -translate 0 50 -setFont "sansserif" 10 -drawText 0 0 "No hinting:" -setFont "times" 12 normal normal none -drawText 0 20 "The quick brown fox jumps over the lazy dog" - -translate 0 50 -setFont "sansserif" 10 -drawText 0 0 "Vertical hinting:" -setFont "times" 12 normal normal vertical -drawText 0 20 "The quick brown fox jumps over the lazy dog" - -translate 0 50 -setFont "sansserif" 10 -drawText 0 0 "Full hinting:" -setFont "times" 12 normal normal full -drawText 0 20 "The quick brown fox jumps over the lazy dog" - - -# Note: there is also the textlayout_draw command which might be interesting here. diff --git a/tests/auto/lancelot/scripts/image_formats.qps b/tests/auto/lancelot/scripts/image_formats.qps deleted file mode 100644 index d817d04bf8..0000000000 --- a/tests/auto/lancelot/scripts/image_formats.qps +++ /dev/null @@ -1,81 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -image_load dome_argb32.png the_pixmap -image_convertToFormat the_pixmap the_pixmap ARGB32_Premultiplied - -begin_block draw_stuff - save - image_convertToFormat the_pixmap converted ARGB32_Premultiplied - drawImage converted 0 0 - translate 0 110 - - image_convertToFormat the_pixmap converted ARGB32 - drawImage converted 0 0 - translate 0 110 - - image_convertToFormat the_pixmap converted RGB32 - drawImage converted 0 0 - translate 0 110 - - image_convertToFormat the_pixmap converted Indexed8 - drawImage converted 0 0 - translate 0 110 - - image_convertToFormat the_pixmap converted MonoLSB - drawImage converted 0 0 - translate 0 110 - - image_convertToFormat the_pixmap converted Mono - drawImage converted 0 0 - translate 0 110 - restore -end_block - - -image_load dome_argb32.png the_pixmap -translate 110 0 -repeat_block draw_stuff - - -image_load dome_rgb32.png the_pixmap -translate 110 0 -repeat_block draw_stuff - -image_load dome_indexed.png the_pixmap -translate 110 0 -repeat_block draw_stuff - - -image_load dome_mono.png the_pixmap -translate 110 0 -repeat_block draw_stuff - -image_load dome_mono_palette.png the_pixmap -translate 110 0 -repeat_block draw_stuff - -image_load dome_indexed_mask.png the_pixmap -translate 110 0 -repeat_block draw_stuff - - -# helpful texts -resetMatrix -setPen black - -drawText 10 670 "ARGB32_PM" -drawText 120 670 "ARGB32" -drawText 230 670 "RGB32" -drawText 340 670 "Indexed" -drawText 450 670 "Mono" -drawText 560 670 "Mono w/lut" -drawText 670 670 "Indexed w/mask" - -drawText 770 50 "ARGB32_PM" -drawText 770 160 "ARGB32" -drawText 770 270 "RGB32" -drawText 770 380 "Indexed" -drawText 770 490 "MonoLSB" -drawText 770 600 "Mono" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/images.qps b/tests/auto/lancelot/scripts/images.qps deleted file mode 100644 index 3f892400e2..0000000000 --- a/tests/auto/lancelot/scripts/images.qps +++ /dev/null @@ -1,106 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -setRenderHint Antialiasing - -setPen #00ff00 - -image_load dome_argb32.png the_image -begin_block draw_stuff - -save - - # standard draw - drawImage the_image 0 0 - - # sub recting - translate 120 0 - drawImage the_image 0 0 40 40 0 0 40 40 - drawImage the_image 60 0 40 40 60 0 40 40 - drawImage the_image 0 60 40 40 0 60 40 40 - drawImage the_image 60 60 40 40 60 60 40 40 - drawImage the_image 0 40 40 20 0 40 40 20 - drawImage the_image 60 40 40 20 60 40 40 20 - drawImage the_image 40 0 20 100 40 0 20 100 - - # subrecting w/scale - translate 120 0 - drawImage the_image 0 0 50 50 0 0 25 25 - drawImage the_image 50 0 50 50 25 0 25 25 - drawImage the_image 0 50 50 50 0 25 25 25 - drawImage the_image 50 50 50 50 25 25 25 25 - - # subrecting w/scale & smooth xform - translate 120 0 - setRenderHint SmoothPixmapTransformation - drawImage the_image 0 0 50 50 0 0 25 25 - drawImage the_image 50 0 50 50 25 0 25 25 - drawImage the_image 0 50 50 50 0 25 25 25 - drawImage the_image 50 50 50 50 25 25 25 25 - - - # Rotation w/o smooth xform - translate 120 0 - save - setRenderHint SmoothPixmapTransform off - rotate 10 - drawImage the_image 0 0 - restore - - # Rotation w smooth xform - translate 120 0 - save - setRenderHint SmoothPixmapTransform - rotate 10 - drawImage the_image 0 0 - restore - -restore - -end_block - - -translate 0 120 -image_load dome_rgb32.png the_image -repeat_block draw_stuff - -translate 0 120 -image_load dome_indexed.png the_image -repeat_block draw_stuff - -translate 0 120 -image_load dome_indexed_mask.png the_image -repeat_block draw_stuff - -translate 0 120 -image_load dome_mono.png the_image -repeat_block draw_stuff - - -resetMatrix -translate 700 60 -setPen black -drawText 0 0 "32 bit w/alpha" -translate 0 120 -drawText 0 0 "32 bit w/o alpha" -translate 0 120 -drawText 0 0 "8 bit indexed" -translate 0 120 -drawText 0 0 "8 bit indexed w/mask" -translate 0 120 -drawText 0 0 "1 bit" -resetMatrix -translate 0 600 -drawText 0 0 "normal" -translate 120 0 -drawText 0 0 "subrect" -translate 120 0 -drawText 0 0 "subrect scale" -translate 120 0 -drawText 0 0 "subrect scale smooth" -translate 120 0 -drawText 0 0 "xform" -translate 120 0 -drawText 0 0 "smooth xform" -translate 120 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/images2.qps b/tests/auto/lancelot/scripts/images2.qps deleted file mode 100644 index 5159abc928..0000000000 --- a/tests/auto/lancelot/scripts/images2.qps +++ /dev/null @@ -1,145 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -image_load dome_argb32.png the_image -begin_block draw_stuff - -save - # standard draw - drawImage the_image 0 0 - - # flip x - translate 220 0 - scale -1 1 - drawImage the_image 0 0 - scale -1 1 - - # flip y - translate 20 100 - scale 1 -1 - drawImage the_image 0 0 - scale 1 -1 - - # flip x and y - translate 220 0 - scale -1 -1 - drawImage the_image 0 0 - scale -1 -1 - - # flip y and scale - translate 20 10 - save - scale 1 -1.1 - drawImage the_image 0 0 - restore - - # flip y and scale - translate 220 -110 - save - scale -1.1 0.9 - drawImage the_image 0 0 - restore -restore -end_block - -setRenderHint Antialiasing - -resetMatrix -translate 0 120 -repeat_block draw_stuff - -resetMatrix -translate 720 60 -setPen black -drawText 0 0 "aliased" -translate 0 120 -drawText 0 0 "antialiased" -resetMatrix -translate 0 260 -drawText 0 0 "normal" -translate 120 0 -drawText 0 0 "flip x" -translate 120 0 -drawText 0 0 "flip y" -translate 120 0 -drawText 0 0 "flip x and y" -translate 120 0 -drawText 0 0 "flip y and scale" -translate 120 0 -drawText 0 0 "flip x and scale" -translate 120 0 - -setRenderHint SmoothPixmapTransform - -resetMatrix -translate 20 300 -drawImage border.png 0 0 100 100 1 1 8 8 -drawText 0 -5 "subrect color bleeding" -translate 0 120 -drawImage border.png 0 0 100 100 0 0 10 10 - -image_load sign.png the_image -resetMatrix -drawText 240 300 "drawImage() with varying sx/sy offsets" -translate 0 10 -drawRect 240 300 50 50 -drawImage the_image 240 300 50 50 20 0 80 80 -drawRect 300 300 50 50 -drawImage the_image 300 300 50 50 -20 0 80 80 -drawRect 240 370 50 50 -drawImage the_image 240 370 50 50 0 20 80 80 -drawRect 300 370 50 50 -drawImage the_image 300 370 50 50 0 -20 80 80 - -pixmap_load sign.png the_pixmap -translate 220 0 -translate 0 -10 -drawText 240 300 "drawPixmap() with varying sx/sy offsets" -translate 0 10 -drawRect 240 300 50 50 -drawPixmap the_pixmap 240 300 50 50 20 0 80 80 -drawRect 300 300 50 50 -drawPixmap the_pixmap 300 300 50 50 -20 0 80 80 -drawRect 240 370 50 50 -drawPixmap the_pixmap 240 370 50 50 0 20 80 80 -drawRect 300 370 50 50 -drawPixmap the_pixmap 300 370 50 50 0 -20 80 80 - - -resetMatrix -translate 0 170 -drawText 240 300 "drawImage() with varying sx/sy offsets" -translate 0 10 -drawRect 240 300 50 50 -drawImage the_image 240 300 50 50 50 0 50 50 -drawRect 300 300 50 50 -drawImage the_image 300 300 50 50 -20 0 50 50 -drawRect 240 370 50 50 -drawImage the_image 240 370 50 50 0 50 50 50 -drawRect 300 370 50 50 -drawImage the_image 300 370 50 50 0 -20 50 50 - -resetMatrix -translate 220 170 -drawText 240 300 "drawPixmap() with varying sx/sy offsets" -translate 0 10 -drawRect 240 300 50 50 -drawPixmap the_pixmap 240 300 50 50 50 0 50 50 -drawRect 300 300 50 50 -drawPixmap the_pixmap 300 300 50 50 -20 0 50 50 -drawRect 240 370 50 50 -drawPixmap the_pixmap 240 370 50 50 0 50 50 50 -drawRect 300 370 50 50 -drawPixmap the_pixmap 300 370 50 50 0 -20 50 50 - -resetMatrix -drawText 10 620 "drawImage/Pixmap() with negative x/y and sx/sy" -setPen red - -translate 20 640 -drawImage the_image -10 -10 -1 -1 -10 -10 0 0 -drawRect 0 0 80 80 - -translate 100 0 -drawPixmap the_pixmap -10 -10 -1 -1 -10 -10 0 0 -drawRect 0 0 80 80 diff --git a/tests/auto/lancelot/scripts/join_cap_styles.qps b/tests/auto/lancelot/scripts/join_cap_styles.qps deleted file mode 100644 index ed823f53f5..0000000000 --- a/tests/auto/lancelot/scripts/join_cap_styles.qps +++ /dev/null @@ -1,63 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -setRenderHint Antialiasing - -path_moveTo p 20 20 -path_cubicTo p 100 20 100 180 180 100 -path_lineTo p 20 180 -path_lineTo p 180 20 - -setPen black 20 solidline roundcap roundjoin -drawPath p -setPen red -drawPath p - -translate 200 0 -setPen black 20 solidline roundcap miterjoin -drawPath p -setPen red -drawPath p - -translate 200 0 -setPen black 20 solidline roundcap beveljoin -drawPath p -setPen red -drawPath p - -translate -400 200 -setPen black 20 solidline squarecap roundjoin -drawPath p -setPen red -drawPath p - -translate 200 0 -setPen black 20 solidline squarecap miterjoin -drawPath p -setPen red -drawPath p - -translate 200 0 -setPen black 20 solidline squarecap beveljoin -drawPath p -setPen red -drawPath p - -translate -400 200 -setPen black 20 solidline flatcap roundjoin -drawPath p -setPen red -drawPath p - -translate 200 0 -setPen black 20 solidline flatcap miterjoin -drawPath p -setPen red -drawPath p - -translate 200 0 -setPen black 20 solidline flatcap beveljoin -drawPath p -setPen red -drawPath p \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/join_cap_styles_duplicate_control_points.qps b/tests/auto/lancelot/scripts/join_cap_styles_duplicate_control_points.qps deleted file mode 100644 index b4630148e2..0000000000 --- a/tests/auto/lancelot/scripts/join_cap_styles_duplicate_control_points.qps +++ /dev/null @@ -1,68 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 600 650) - - -setRenderHint Antialiasing - -path_moveTo p 40 70 -path_lineTo p 20 70 -path_cubicTo p 20 70 40 20 80 80 - -path_moveTo p 20 120 -path_cubicTo p 50 60 80 110 80 110 -path_lineTo p 60 110 - -scale 2 2 - -setPen black 10 solidline roundcap roundjoin -drawPath p -setPen red -drawPath p - -translate 100 0 -setPen black 10 solidline roundcap miterjoin -drawPath p -setPen red -drawPath p - -translate 100 0 -setPen black 10 solidline roundcap beveljoin -drawPath p -setPen red -drawPath p - -translate -200 100 -setPen black 10 solidline squarecap roundjoin -drawPath p -setPen red -drawPath p - -translate 100 0 -setPen black 10 solidline squarecap miterjoin -drawPath p -setPen red -drawPath p - -translate 100 0 -setPen black 10 solidline squarecap beveljoin -drawPath p -setPen red -drawPath p - -translate -200 100 -setPen black 10 solidline flatcap roundjoin -drawPath p -setPen red -drawPath p - -translate 100 0 -setPen black 10 solidline flatcap miterjoin -drawPath p -setPen red -drawPath p - -translate 100 0 -setPen black 10 solidline flatcap beveljoin -drawPath p -setPen red -drawPath p \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/linear_gradients.qps b/tests/auto/lancelot/scripts/linear_gradients.qps deleted file mode 100644 index b1b8dd69e7..0000000000 --- a/tests/auto/lancelot/scripts/linear_gradients.qps +++ /dev/null @@ -1,144 +0,0 @@ -# Version: 1 -# CheckVsReference: 2% (0 0 600 750) - -path_addRect path 400 0 80 80 -path_addEllipse path 440 40 60 60 - -setRenderHint Antialiasing - -setPen black - -begin_block gradients -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setLinear 20 20 70 70 -drawRect 0 0 100 100 - -gradient_setSpread ReflectSpread -gradient_setLinear 120 20 170 70 -drawEllipse 100 0 100 100 - -gradient_setSpread RepeatSpread -gradient_setLinear 220 20 270 70 -drawRoundRect 200 0 100 100 - -gradient_clearStops -gradient_appendStop 0 3f7f7fff -gradient_appendStop 0.5 dfdfffff -gradient_appendStop 1 7f00007f - -gradient_setSpread PadSpread -gradient_setLinear 320 20 340 40 -drawPolygon [300 0 390 0 350 99] - -gradient_setSpread ReflectSpread -gradient_setLinear 420 20 440 40 -drawPath path - -gradient_setSpread RepeatSpread -gradient_setLinear 520 20 540 40 -drawPie 500 0 100 100 720 4320 -end_block - -translate 0 100 -scale 1 2 -repeat_block gradients - -resetMatrix -translate 0 300 -brushTranslate 30 0 -brushScale 0.9 0.9 -brushRotate 20 -repeat_block gradients - -# Vertical gradient tests -resetMatrix -setBrush noBrush -translate 0 400 - -begin_block vertical_gradients -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setLinear 20 20 20 70 -drawRect 0 0 100 100 - -gradient_setSpread ReflectSpread -gradient_setLinear 120 20 120 70 -drawEllipse 100 0 100 100 - -gradient_setSpread RepeatSpread -gradient_setLinear 220 20 220 70 -drawRoundRect 200 0 100 100 - -gradient_clearStops -gradient_appendStop 0 3f7f7fff -gradient_appendStop 0.5 dfdfffff -gradient_appendStop 1 7f00007f - -gradient_setSpread PadSpread -gradient_setLinear 320 20 320 40 -drawPolygon [300 0 390 0 350 99] - -gradient_setSpread ReflectSpread -gradient_setLinear 420 20 420 40 -drawPath path - -gradient_setSpread RepeatSpread -gradient_setLinear 520 20 520 40 -drawPie 500 0 100 100 720 4320 -end_block - -translate 0 100 -scale 1 1.5 -repeat_block vertical_gradients - -resetMatrix -translate 0 650 -brushTranslate 30 0 -brushScale 0.9 0.9 -brushRotate 20 -repeat_block vertical_gradients - -# Some helpful info perhaps? -resetMatrix -setPen black -# gradient line indicators -drawLine 20 20 70 70 -drawLine 120 20 170 70 -drawLine 220 20 270 70 -drawLine 320 20 340 40 -drawLine 420 20 440 40 -drawLine 520 20 540 40 - -drawLine 20 140 70 240 -drawLine 120 140 170 240 -drawLine 220 140 270 240 -drawLine 320 140 340 180 -drawLine 420 140 440 180 -drawLine 520 140 540 180 - -drawText 610 50 "No XForm" -drawText 610 200 "scale 1x2" -drawText 610 350 "brush transform" -drawText 610 450 "vertical brush" -drawText 610 570 "vertical brush scale 1x1.5" -drawText 610 700 "vertical brush transform" - -drawText 10 780 "Pad" -drawText 110 780 "Reflect" -drawText 210 780 "Repeat" -drawText 310 780 "Pad w/alpha" -drawText 410 780 "Reflect w/alpha" -drawText 510 780 "Repeat w/alpha" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/linear_gradients_perspectives.qps b/tests/auto/lancelot/scripts/linear_gradients_perspectives.qps deleted file mode 100644 index 3ea39fbe46..0000000000 --- a/tests/auto/lancelot/scripts/linear_gradients_perspectives.qps +++ /dev/null @@ -1,62 +0,0 @@ -# Version: 1 - - -setRenderHint Antialiasing - -setPen #00ff00 - -translate 10 10 -# standard draw -begin_block gradient -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setLinear 10 10 290 290 -drawRect 0 0 300 300 -end_block gradient - -# Rotation w/o smooth xform -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 - repeat_block gradient -restore -restore - -translate 0 320 - -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 - repeat_block gradient -restore - -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 - repeat_block gradient -restore -restore - - -resetMatrix -setPen black -translate 125 20 -drawText 0 0 "No transform" -translate 350 0 -drawText 0 0 "Left Tilted" -resetMatrix -translate 125 350 -drawText 0 0 "Bottom Tilted" -translate 350 0 -drawText 0 0 "Right Tilted" -translate 120 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/linear_resolving_gradients.qps b/tests/auto/lancelot/scripts/linear_resolving_gradients.qps deleted file mode 100644 index 779760cb9a..0000000000 --- a/tests/auto/lancelot/scripts/linear_resolving_gradients.qps +++ /dev/null @@ -1,66 +0,0 @@ -# Version: 2 -# CheckVsReference: 2% (0 0 500 400) - -setRenderHint Antialiasing - -setPen black - -begin_block gradients -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setCoordinateMode ObjectBoundingMode -gradient_setLinear 0.2 0.2 0.7 0.7 -drawRect 0 0 100 100 - -gradient_setSpread ReflectSpread -gradient_setLinear 0.2 0.2 0.7 0.7 -drawEllipse 100 0 100 100 - -gradient_setSpread RepeatSpread -gradient_setLinear 0.2 0.2 0.7 0.7 -drawRoundRect 200 0 100 100 - -gradient_clearStops -gradient_appendStop 0 3f7f7fff -gradient_appendStop 0.5 dfdfffff -gradient_appendStop 1 7f00007f - -gradient_setSpread PadSpread -gradient_setLinear 0.2 0.2 0.8 0.4 -drawPolygon [300 0 400 0 350 100] - -gradient_setSpread RepeatSpread -gradient_setLinear 0.2 0.2 0.4 0.4 -drawPie 400 0 100 100 0 4320 -end_block - -translate 0 100 -scale 1 2 -repeat_block gradients - -resetMatrix -translate 0 300 -brushTranslate 30 0 -brushScale 0.9 0.9 -brushRotate 20 -repeat_block gradients - -# Some helpful info perhaps? -resetMatrix -setPen black - -drawText 510 50 "No XForm" -drawText 510 200 "scale 1x2" -drawText 510 350 "brush transform" - -drawText 10 450 "Pad" -drawText 110 450 "Reflect" -drawText 210 450 "Repeat" -drawText 310 450 "Pad w/alpha" -drawText 410 450 "Repeat w/alpha" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/lineconsistency.qps b/tests/auto/lancelot/scripts/lineconsistency.qps deleted file mode 100644 index 0b40577659..0000000000 --- a/tests/auto/lancelot/scripts/lineconsistency.qps +++ /dev/null @@ -1,72 +0,0 @@ -# Version: 1 - -begin_block draw -setPen red -drawPolygon [1.1 1 3.3 30.6 23.1 39.2 38.9 6.5] -setPen black -drawLine 1.1 1 3.3 30.6 -drawLine 3.3 30.6 23.1 39.2 -drawLine 23.1 39.2 38.9 6.5 -drawLine 38.9 6.5 1.1 1 -end_block draw -drawText 0 60 "0.0 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.1 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.2 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.3 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.4 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.5 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.6 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.7 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.8 aligned" -translate 0.1 80.1 -repeat_block draw -drawText 0 60 "0.9 aligned" - -resetMatrix -translate 100 0 -setPen black -drawText 0 20 "Line and text, 0.0 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.1 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.2 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.3 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.4 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.5 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.6 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.7 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.8 aligned" -drawLine 0 21 160 21 -translate 0 40.1 -drawText 0 20 "Line and text, 0.9 aligned" -drawLine 0 21 160 21 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/linedashes.qps b/tests/auto/lancelot/scripts/linedashes.qps deleted file mode 100644 index ee7d18b156..0000000000 --- a/tests/auto/lancelot/scripts/linedashes.qps +++ /dev/null @@ -1,94 +0,0 @@ -# Version: 1 - -translate 10 10 - -setPen 0xffff0000 0 solidline squarecap -translate 50 50 -begin_block draw_lines - save - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - restore -end_block - -setPen 0xffff0000 0 dotline squarecap -translate 100 0 -repeat_block draw_lines -setPen 0xffff0000 0 dashdotline squarecap -translate 100 0 -repeat_block draw_lines -setPen 0xffff0000 0 dashdotdotline squarecap -translate 100 0 -repeat_block draw_lines -setPen 0xffff0000 0 dashline squarecap -translate 100 0 -repeat_block draw_lines \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/linedashes2.qps b/tests/auto/lancelot/scripts/linedashes2.qps deleted file mode 100644 index 1dc4fd310e..0000000000 --- a/tests/auto/lancelot/scripts/linedashes2.qps +++ /dev/null @@ -1,154 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% (0 0 800 800) - -translate -30 10 - -setPen 0xffff0000 0 dashline squarecap -pen_setDashPattern [10 5] - -save -translate 100 100 -begin_block lines -drawLine 100 100 200 100 -drawLine 100 100 200 200 -drawLine 100 100 100 200 -end_block - -setPen 0xffff0000 2 dashline squarecap -translate 150 0 -repeat_block lines -restore - -save -save -begin_block horizontal -drawLine 0 0 50 0 -drawLine 3 10 53 10 -drawLine 6 20 56 20 -drawLine 9 30 59 30 - -translate 0 50 - -drawLine 0 0 50 5 -drawLine 3 10 53 15 -drawLine 6 20 56 25 -drawLine 9 30 59 35 - -translate 0 50 - -drawLine 0 0 50 -5 -drawLine 3 10 53 5 -drawLine 6 20 56 15 -drawLine 9 30 59 25 -end_block -restore - -save -translate 80 0 -repeat_block horizontal -restore -save -translate 800 0 -repeat_block horizontal -restore - -translate 180 -40 -save -begin_block vertical -drawLine 0 0 0 50 -drawLine 10 3 10 53 -drawLine 20 6 20 56 -drawLine 30 9 30 59 - -translate 50 0 - -drawLine 0 0 5 50 -drawLine 10 3 15 53 -drawLine 20 6 25 56 -drawLine 30 9 35 59 - -translate 50 0 - -drawLine 0 0 -5 50 -drawLine 10 3 5 53 -drawLine 20 6 15 56 -drawLine 30 9 25 59 -end_block -restore - -save -translate 0 80 -repeat_block vertical -restore -translate 0 800 -repeat_block vertical -restore - -translate 0 200 - -setPen 0xffff0000 2 dashline squarecap -save -repeat_block horizontal -restore -save -translate 80 0 -repeat_block horizontal -restore -save -translate 780 0 -repeat_block horizontal -restore - -translate 360 -240 -save -repeat_block vertical -restore -save -translate 0 80 -repeat_block vertical -restore -translate 0 780 -repeat_block vertical - -resetMatrix -translate 40 400 -setPen 0xffff0000 5 dashdotline flatcap -pen_setDashPattern [1 1 4 1 1 4] -pen_setDashOffset -4 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset -2 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 0 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 2 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 4 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 6 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 8 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 10 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 12 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 14 -drawLine 0 0 300 0 -translate 0 8 -pen_setDashOffset 16 -drawLine 0 0 300 0 - -resetMatrix -setPen black 3 dashdotline -pen_setCosmetic true -translate 0 -150 -drawLine 500 160 500 410 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/linedashes2_aa.qps b/tests/auto/lancelot/scripts/linedashes2_aa.qps deleted file mode 100644 index c818ab62fe..0000000000 --- a/tests/auto/lancelot/scripts/linedashes2_aa.qps +++ /dev/null @@ -1,5 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 800 800) - -setRenderHint LineAntialiasing -import "linedashes2.qps" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/lines.qps b/tests/auto/lancelot/scripts/lines.qps deleted file mode 100644 index c0daffb1b0..0000000000 --- a/tests/auto/lancelot/scripts/lines.qps +++ /dev/null @@ -1,558 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% (0 0 310 425) - - -translate 10 10 - -begin_block draw_lines - save - translate 50 50 - - save - setPen 0x7fff0000 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - restore - - # and then draw the lines the other direction - save - setPen 0x7f0000ff - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - rotate 10 - drawLine 50 0 10 0 - restore - - # and now with a clip - save - setClipRect -30 -30 60 60 - setPen 0x7f00ff00 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - rotate 10 - drawLine 10 0 50 0 - restore - - restore -end_block - -save - translate 100 0 - scale 2 2 - repeat_block draw_lines -restore - -translate 0 10 - -save - translate 0 200 - setRenderHint Antialiasing - repeat_block draw_lines -restore - -save - translate 100 200 - scale 2 2 - setRenderHint Antialiasing - repeat_block draw_lines -restore - -translate 320 0 - -setPen black 0 solidline squarecap - -begin_block lines - -# 0 -> 45 degress -drawLine 100 100 200 90 -drawLine 100 100 200 80 -drawLine 100 100 200 70 -drawLine 100 100 200 60 -drawLine 100 100 200 50 -drawLine 100 100 200 40 -drawLine 100 100 200 30 -drawLine 100 100 200 20 -drawLine 100 100 200 10 - -# 45 -drawLine 100 100 200 0 - -# 45 -> 90 -drawLine 100 100 190 0 -drawLine 100 100 180 0 -drawLine 100 100 170 0 -drawLine 100 100 160 0 -drawLine 100 100 150 0 -drawLine 100 100 140 0 -drawLine 100 100 130 0 -drawLine 100 100 120 0 -drawLine 100 100 110 0 - -# 90 -drawLine 100 100 100 0 - -# 90 -> 135 -drawLine 100 100 90 0 -drawLine 100 100 80 0 -drawLine 100 100 70 0 -drawLine 100 100 60 0 -drawLine 100 100 50 0 -drawLine 100 100 40 0 -drawLine 100 100 30 0 -drawLine 100 100 20 0 -drawLine 100 100 10 0 - -# 135 -drawLine 100 100 0 0 - -# 135 -> 180 degress -drawLine 100 100 0 10 -drawLine 100 100 0 20 -drawLine 100 100 0 30 -drawLine 100 100 0 40 -drawLine 100 100 0 50 -drawLine 100 100 0 60 -drawLine 100 100 0 70 -drawLine 100 100 0 80 -drawLine 100 100 0 90 - -# 180 -drawLine 100 100 0 100 - -# 180 -> 225 -drawLine 100 100 0 110 -drawLine 100 100 0 120 -drawLine 100 100 0 130 -drawLine 100 100 0 140 -drawLine 100 100 0 150 -drawLine 100 100 0 160 -drawLine 100 100 0 170 -drawLine 100 100 0 180 -drawLine 100 100 0 190 - -# 225 -drawLine 100 100 0 200 - -# 225 -> 270 -drawLine 100 100 10 200 -drawLine 100 100 20 200 -drawLine 100 100 30 200 -drawLine 100 100 40 200 -drawLine 100 100 50 200 -drawLine 100 100 60 200 -drawLine 100 100 70 200 -drawLine 100 100 80 200 -drawLine 100 100 90 200 - -# 270 -drawLine 100 100 100 200 - -# 270 -> 315 degrees -drawLine 100 100 110 200 -drawLine 100 100 120 200 -drawLine 100 100 130 200 -drawLine 100 100 140 200 -drawLine 100 100 150 200 -drawLine 100 100 160 200 -drawLine 100 100 170 200 -drawLine 100 100 180 200 -drawLine 100 100 190 200 - -# 315 -drawLine 100 100 200 200 - -# 315 -> 360 degress -drawLine 100 100 200 100 -drawLine 100 100 200 110 -drawLine 100 100 200 120 -drawLine 100 100 200 130 -drawLine 100 100 200 140 -drawLine 100 100 200 150 -drawLine 100 100 200 160 -drawLine 100 100 200 170 -drawLine 100 100 200 180 -drawLine 100 100 200 190 - -end_block - - -setRenderHint Antialiasing -setPen 0x7fff0000 -translate 0.5 0.5 -repeat_block lines - -setPen 0x000000 8 -translate 20 240 -drawText 0 0 "Steep slopes:" - -translate 0 10 - -drawLine 0 0 -8 400 -translate 20 0 -drawLine 0 0 -7 400 -translate 20 0 -drawLine 0 0 -6 400 -translate 20 0 -drawLine 0 0 -5 400 -translate 20 0 -drawLine 0 0 -4 400 -translate 20 0 -drawLine 0 0 -3 400 -translate 20 0 -drawLine 0 0 -2 400 -translate 20 0 -drawLine 0 0 -1 400 -translate 20 0 -drawLine 0 0 0 400 -translate 20 0 -drawLine 0 0 1 400 -translate 20 0 -drawLine 0 0 2 400 -translate 20 0 -drawLine 0 0 3 400 -translate 20 0 -drawLine 0 0 4 400 -translate 20 0 -drawLine 0 0 5 400 -translate 20 0 -drawLine 0 0 6 400 -translate 20 0 -drawLine 0 0 7 400 -translate 20 0 -drawLine 0 0 8 400 - -resetMatrix - -translate 20 450 - -drawText 0 0 "Zero length lines:" - -translate 0 20 -drawText 100 10 "Square cap" -save -begin_block points -setPen 0x000000 1 solidline squarecap -drawLine 0 0 0 0 -setPen 0x000000 2 solidline squarecap -drawLine 8 0 8 0 -setPen 0x000000 3 solidline squarecap -drawLine 16 0 16 0 -setPen 0x000000 4 solidline squarecap -drawLine 24 0 24 0 -setPen 0x000000 5 solidline squarecap -drawLine 32 0 32 0 -setPen 0x000000 6 solidline squarecap -drawLine 40 0 40 0 -setPen 0x000000 7 solidline squarecap -drawLine 48 0 48 0 -setPen 0x000000 8 solidline squarecap -drawLine 57 0 57 0 -setPen 0x000000 9 solidline squarecap -drawLine 67 0 67 0 -setPen 0x000000 10 solidline squarecap -drawLine 78 0 78 0 -end_block points -restore - -translate 0 12 -setRenderHint Antialiasing off -repeat_block points -setRenderHint Antialiasing - -translate 0 20 -drawText 100 10 "Round cap" -save -begin_block points2 -setPen 0x000000 1 solidline roundcap -drawLine 0 0 0 0 -setPen 0x000000 2 solidline roundcap -drawLine 8 0 8 0 -setPen 0x000000 3 solidline roundcap -drawLine 16 0 16 0 -setPen 0x000000 4 solidline roundcap -drawLine 24 0 24 0 -setPen 0x000000 5 solidline roundcap -drawLine 32 0 32 0 -setPen 0x000000 6 solidline roundcap -drawLine 40 0 40 0 -setPen 0x000000 7 solidline roundcap -drawLine 48 0 48 0 -setPen 0x000000 8 solidline roundcap -drawLine 57 0 57 0 -setPen 0x000000 9 solidline roundcap -drawLine 67 0 67 0 -setPen 0x000000 10 solidline roundcap -drawLine 78 0 78 0 -end_block points2 -restore - -translate 0 12 -setRenderHint Antialiasing off -repeat_block points2 -setRenderHint Antialiasing - -translate 0 20 -drawText 100 10 "Flat cap" -save -begin_block points3 -setPen 0x000000 1 solidline flatcap -drawLine 0 0 0 0 -setPen 0x000000 2 solidline flatcap -drawLine 8 0 8 0 -setPen 0x000000 3 solidline flatcap -drawLine 16 0 16 0 -setPen 0x000000 4 solidline flatcap -drawLine 24 0 24 0 -setPen 0x000000 5 solidline flatcap -drawLine 32 0 32 0 -setPen 0x000000 6 solidline flatcap -drawLine 40 0 40 0 -setPen 0x000000 7 solidline flatcap -drawLine 48 0 48 0 -setPen 0x000000 8 solidline flatcap -drawLine 57 0 57 0 -setPen 0x000000 9 solidline flatcap -drawLine 67 0 67 0 -setPen 0x000000 10 solidline flatcap -drawLine 78 0 78 0 -end_block points3 -restore - -translate 0 12 -setRenderHint Antialiasing off -repeat_block points3 - -resetMatrix -translate -220 667.226 -drawText 230 -80 "Task 194266 (should see only one line):" -setPen black -drawRect 230.5 -70.5 122 12 -setRenderHint Antialiasing -setPen red -drawLine 236.842105263 -63.775117299 247.368421053 -63.775437504 - -setRenderHint Antialiasing off -resetMatrix -translate 10 640 -setPen black -drawText 0 -10 "Task 207147 (should see two lines):" -drawRect 0.5 0.5 64 64 -setRenderHint Antialiasing -setPen red - -drawLine 4.5 4.5 4.5001 60.5 -drawLine 4.5 4.5 60.5 4.5001 - -setRenderHint Antialiasing off -resetMatrix -translate 10 730 -setPen black -drawText 0 -10 "Task 229459 (should see one diagonal line):" -drawRect 0.5 0.5 64 64 -setPen red 2 solidline flatcap - -setClipRect 2 2 63 63 -drawLine 1.5 1.5 33560000 33560000 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/lines2.qps b/tests/auto/lancelot/scripts/lines2.qps deleted file mode 100644 index af6ad65939..0000000000 --- a/tests/auto/lancelot/scripts/lines2.qps +++ /dev/null @@ -1,179 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -translate 10 20 -drawText 0 0 "Thin lines" - -translate 60 70 - -save -begin_block lines -translate 0 -60 -translate 0 5 -setPen 0x000000 0.05 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.1 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.15 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.2 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.25 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.3 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.35 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.2 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.25 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.5 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.55 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.6 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.65 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.7 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.75 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.8 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.85 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.9 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 0.95 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.05 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.1 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.15 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.2 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.25 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.3 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.35 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.2 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.25 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.5 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.55 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.6 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.65 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.7 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.75 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.8 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.85 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.9 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 1.95 -drawLine -60 -2 60 2 -translate 0 5 -setPen 0x000000 2 -drawLine -60 -2 60 2 -end_block -restore - -save -translate 150 0 -scale -1 1 -repeat_block lines -restore - -save -translate 80 220 -rotate 90 -repeat_block lines -restore - -save -translate 80 370 -rotate 90 -scale -1 1 -repeat_block lines -restore - -setRenderHint Antialiasing - -translate 300 0 - -save -repeat_block lines -restore - -save -translate 150 0 -scale -1 1 -repeat_block lines -restore - -save -translate 80 220 -rotate 90 -repeat_block lines -restore - -save -translate 80 370 -rotate 90 -scale -1 1 -repeat_block lines -restore \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/pathfill.qps b/tests/auto/lancelot/scripts/pathfill.qps deleted file mode 100644 index 821b4684c9..0000000000 --- a/tests/auto/lancelot/scripts/pathfill.qps +++ /dev/null @@ -1,38 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 850 420) - -setPen afff0000 4 - -setBrush dome_rgb32.png -drawEllipse 10 10 200 200 - -setBrush dome_argb32.png -drawEllipse 220 10 200 200 - -setPen NoPen - -setBrush dome_rgb32.png -drawEllipse 10 220 200 200 - -setBrush dome_argb32.png -drawEllipse 220 220 200 200 - -setBrushOrigin -30 -30 - -setPen afff0000 4 -setBrush dome_rgb32.png -drawEllipse 430 10 200 200 - -setBrush dome_argb32.png -drawEllipse 640 10 200 200 - -setPen NoPen -setBrush dome_rgb32.png -drawEllipse 430 220 200 200 - -setBrush dome_argb32.png -drawEllipse 640 220 200 200 - -setPen black -drawText 150 450 "No offset RGB/ARGB" -drawText 550 450 "-30 offset RGB/ARGB" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/paths.qps b/tests/auto/lancelot/scripts/paths.qps deleted file mode 100644 index 083026ee17..0000000000 --- a/tests/auto/lancelot/scripts/paths.qps +++ /dev/null @@ -1,34 +0,0 @@ -# Version: 1 - -setPen black -setBrush 7f7fff - -path_moveTo star 50 0 -path_lineTo star 30 90 -path_lineTo star 100 60 -path_lineTo star 0 20 -path_lineTo star 80 100 - -setFont "times" 50 -path_addText text 0 50 "ABCD, 1234, abcd, #¤%&" - -path_addRect rectncircle 0 0 75 75 -path_addEllipse rectncircle 25 25 75 75 -path_setFillRule rectncircle winding - -path_moveTo curve 100 0 -path_cubicTo curve 100 100 50 50 0 100 - -begin_block drawing -drawPath star -translate 100 0 -drawPath rectncircle -translate 100 0 -drawPath curve -translate -200 100 -drawPath text -end_block - -translate 50 100 -rotate 10 -repeat_block drawing diff --git a/tests/auto/lancelot/scripts/paths_aa.qps b/tests/auto/lancelot/scripts/paths_aa.qps deleted file mode 100644 index 4812e2fa5f..0000000000 --- a/tests/auto/lancelot/scripts/paths_aa.qps +++ /dev/null @@ -1,4 +0,0 @@ -# Version: 1 - -setRenderHint LineAntialiasing -import "paths.qps" diff --git a/tests/auto/lancelot/scripts/pens.qps b/tests/auto/lancelot/scripts/pens.qps deleted file mode 100644 index c72636dcef..0000000000 --- a/tests/auto/lancelot/scripts/pens.qps +++ /dev/null @@ -1,133 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 800 800) - - -translate 10 10 - -begin_block penstyles -setPen black 0 solidline flatcap -drawLine 0 0 100 0 -setPen black 0 dashline flatcap -drawLine 100 0 100 40 -setPen black 0 dotline flatcap -drawLine 100 40 200 0 -setPen black 0 dashdotline flatcap -drawLine 200 0 300 0 -setPen black 0 dashdotdotline flatcap -drawLine 300 0 400 40 - -translate 0 50 -setPen blue 2 solidline flatcap -drawLine 0 0 100 0 -setPen blue 2 dashline flatcap -drawLine 100 0 100 40 -setPen blue 2 dotline flatcap -drawLine 100 40 200 0 -setPen blue 2 dashdotline flatcap -drawLine 200 0 300 0 -setPen blue 2 dashdotdotline flatcap -drawLine 300 0 400 40 - -translate 0 50 -setPen red 5 solidline flatcap -drawLine 0 0 100 0 -setPen red 5 dashline flatcap -drawLine 100 0 100 40 -setPen red 5 dotline flatcap -drawLine 100 40 200 0 -setPen red 5 dashdotline flatcap -drawLine 200 0 300 0 -setPen red 5 dashdotdotline flatcap -drawLine 300 0 400 40 -end_block - -translate 0 50 -scale 1 2 -repeat_block penstyles - - -# Test cap styles -resetMatrix -translate 420 10 -setPen green 5 dashdotline flatcap -drawLine 0 0 200 0 -setPen green 5 dashdotline roundcap -drawLine 0 20 200 20 -setPen green 5 dashdotline squarecap -drawLine 0 40 200 40 - - -# Test join styles -resetMatrix -translate 420 80 -setBrush nobrush -begin_block joinstyles -setPen orange 10 solidline flatcap miterjoin -drawPolyline [ 0 0 80 0 80 80 0 80 ] - -translate 0 100 -setPen aquamarine 10 solidline squarecap beveljoin -drawPolyline [ 0 0 80 0 80 80 0 80 ] - -translate 0 100 -setPen purple 10 solidline roundcap roundjoin -drawPolyline [ 0 0 80 0 80 80 0 80 ] -end_block - -translate 130 -200 -scale 2 1 -rotate 1 -repeat_block joinstyles - -# transparent lines -resetMatrix -translate 10 400 -setPen #7f000000 -drawLine 0 0 50 0 -setPen #7f000000 1 SolidLine -drawLine 0 10 50 10 -setPen #7f000000 5 SolidLine -drawLine 0 20 50 20 -setPen #7f000000 10 SolidLine -drawLine 0 30 50 30 -setPen #7f000000 -drawLine 0 0 0 50 -setPen #7f000000 1 SolidLine -drawLine 10 0 10 50 -setPen #7f000000 5 SolidLine -drawLine 20 0 20 50 -setPen #7f000000 10 SolidLine -drawLine 30 0 30 50 - -# pen styles -resetMatrix -translate 0 500 -setPen black 0 DashLine -drawLine 20 20 100 20 -translate 0 10 -setPen black 0 DotLine -drawLine 20 20 100 20 -translate 0 10 -setPen black 0 DashDotLine -drawLine 20 20 100 20 -translate 0 10 -setPen black 0 DashDotDotLine -drawLine 20 20 100 20 - -# scaling ellipse -resetMatrix -setPen black 0.008 DashLine -translate 250 550 -rotate 30 -scale 250 250 -drawEllipse -0.4 -0.4 0.8 0.8 - -# scaling path -path_addEllipse star -0.3 -0.3 0.6 0.6 - -resetMatrix -setPen black 0.008 DashLine -translate 250 550 -rotate 30 -scale 250 250 -drawPath star diff --git a/tests/auto/lancelot/scripts/pens_aa.qps b/tests/auto/lancelot/scripts/pens_aa.qps deleted file mode 100644 index 066cac365f..0000000000 --- a/tests/auto/lancelot/scripts/pens_aa.qps +++ /dev/null @@ -1,6 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 800 800) - -setRenderHint LineAntialiasing - -import "pens.qps" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/pens_cosmetic.qps b/tests/auto/lancelot/scripts/pens_cosmetic.qps deleted file mode 100644 index d1a60d150d..0000000000 --- a/tests/auto/lancelot/scripts/pens_cosmetic.qps +++ /dev/null @@ -1,110 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 585 470) - -path_addEllipse path 22 0 7 7 -path_addRect path 25 5 4 4 - -translate 20 20 - -begin_block lines - save - drawLine 0 0 10 10 - drawLine 2 0 10 0 - drawLine 0 2 0 10 - drawPolygon [12 0 20 0 15 10] - drawPath path - drawEllipse 32 0 8 8 - drawPoint 36 4 - - translate 100 0 - save - scale 4 1 - drawLine 0 0 10 10 - drawLine 2 0 10 0 - drawLine 0 2 0 10 - drawPolygon [12 0 20 0 15 10] - drawPath path - drawEllipse 32 0 8 8 - drawPoint 36 4 - restore - - translate 200 0 - save - scale 1 4 - drawLine 0 0 10 10 - drawLine 2 0 10 0 - drawLine 0 2 0 10 - drawPolygon [12 0 20 0 15 10] - drawPath path - drawEllipse 32 0 8 8 - drawPoint 36 4 - restore - - translate 100 0 - save - scale 4 4 - drawLine 0 0 10 10 - drawLine 2 0 10 0 - drawLine 0 2 0 10 - drawPolygon [12 0 20 0 15 10] - drawPath path - drawEllipse 32 0 8 8 - drawPoint 36 4 - restore - restore -end_block - -drawText 580 15 "non-cosmetic, 0-width" -translate 0 50 - -setPen black 2 -repeat_block lines -drawText 580 15 "non-cosmetic, 2-width" - -translate 0 20 -translate 0 50 -setPen black 0 -pen_setCosmetic true -repeat_block lines -drawText 580 15 "cosmetic, 0-width" - -translate 0 50 -setPen black 2 -pen_setCosmetic true -repeat_block lines -drawText 580 15 "cosmetic, 2-width" - - -setRenderHint Antialiasing -translate 0 20 - -translate 0 50 -setPen black 0 -repeat_block lines -drawText 580 15 "non-cosmetic, 0-width" - -translate 0 50 - -setPen black 2 -repeat_block lines -drawText 580 15 "non-cosmetic, 2-width" - -translate 0 20 -translate 0 50 -setPen black 0 -pen_setCosmetic true -repeat_block lines -drawText 580 15 "cosmetic, 0-width" - -translate 0 50 -setPen black 2 -pen_setCosmetic true -repeat_block lines -drawText 580 15 "cosmetic, 2-width" - - -translate 0 70 -drawText 0 0 "scale(1, 1)" -drawText 150 0 "scale(4, 1)" -drawText 300 0 "scale(1, 4)" -drawText 450 0 "scale(4, 4)" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/perspectives.qps b/tests/auto/lancelot/scripts/perspectives.qps deleted file mode 100644 index 0b903e5260..0000000000 --- a/tests/auto/lancelot/scripts/perspectives.qps +++ /dev/null @@ -1,72 +0,0 @@ -# Version: 1 - - -setRenderHint Antialiasing - -setPen #00ff00 - -image_load image.png the_image - -translate 10 10 -# standard draw -drawImage the_image 0 0 - -# Rotation w/o smooth xform -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 - drawImage the_image 0 0 -restore -restore - -translate 0 320 - -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 - drawImage the_image 0 0 -restore - -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 - drawImage the_image 0 0 -restore -restore - -setRenderHint SmoothPixmapTransform on -setBrush red -setPen black -resetMatrix -translate 100 720 -rotate_y 85 -scale 7 0.01 -drawRect -150 -150 300 300 - -resetMatrix -setBrush gam030.png -setPen black 30 -translate 700 700 -rotate_y -85 -scale 7 0.01 -drawRect -150 -150 300 300 - -resetMatrix -setPen black -translate 125 20 -drawText 0 0 "No transform" -translate 350 0 -drawText 0 0 "Left Tilted" -resetMatrix -translate 125 350 -drawText 0 0 "Bottom Tilted" -translate 350 0 -drawText 0 0 "Right Tilted" -translate 120 0 -resetMatrix -translate 300 760 -drawText 0 0 "Perspective Clipping" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/perspectives2.qps b/tests/auto/lancelot/scripts/perspectives2.qps deleted file mode 100644 index 2f6d1d653c..0000000000 --- a/tests/auto/lancelot/scripts/perspectives2.qps +++ /dev/null @@ -1,309 +0,0 @@ -# Version: 1 - -setRenderHint Antialiasing - -image_load zebra.png zebra_png - -image_convertToFormat zebra_png zebra ARGB32_Premultiplied - -translate 75 100 -# standard draw -begin_block row -drawImage zebra -50 -50 - -translate 90 0 -save -rotate_y 50 -drawImage zebra -50 -50 -restore - -translate 65 0 -save -rotate_y 60 -drawImage zebra -50 -50 -restore - -translate 50 0 -save -rotate_y 70 -drawImage zebra -50 -50 -restore - -translate 30 0 -save -rotate_y 80 -drawImage zebra -50 -50 -restore - -translate 24 0 -save -rotate_y 82 -drawImage zebra -50 -50 -restore - -translate 20 0 -save -rotate_y 84 -drawImage zebra -50 -50 -restore - -translate 16 0 -save -rotate_y 86 -drawImage zebra -50 -50 -restore - -translate 12 0 -save -rotate_y 87 -drawImage zebra -50 -50 -restore - -translate 8 0 -save -rotate_y 88 -drawImage zebra -50 -50 -restore - -translate 6 0 -save -rotate_y 89 -drawImage zebra -50 -50 -restore - -translate 6 0 -save -rotate_y 91 -drawImage zebra -50 -50 -restore - -translate 6 0 -save -rotate_y 92 -drawImage zebra -50 -50 -restore - -translate 8 0 -save -rotate_y 93 -drawImage zebra -50 -50 -restore - -translate 12 0 -save -rotate_y 94 -drawImage zebra -50 -50 -restore - -translate 16 0 -save -rotate_y 96 -drawImage zebra -50 -50 -restore - -translate 20 0 -save -rotate_y 98 -drawImage zebra -50 -50 -restore - -translate 24 0 -save -rotate_y 100 -drawImage zebra -50 -50 -restore - -translate 30 0 -save -rotate_y 110 -drawImage zebra -50 -50 -restore - -translate 50 0 -save -rotate_y 120 -drawImage zebra -50 -50 -restore - -translate 65 0 -save -rotate_y 130 -drawImage zebra -50 -50 -restore - -translate 90 0 -save -rotate_y 180 -drawImage zebra -50 -50 -restore -end_block - -resetMatrix -translate 75 280 -setRenderHint SmoothPixmapTransform -repeat_block row - -resetMatrix -setPen black -translate 300 20 -drawText 0 0 "Fast Pixmap Transform" -resetMatrix -translate 300 210 -drawText 0 0 "Smooth Pixmap Transform" - -resetMatrix -translate 0 400 - -image_load dome_argb32.png the_pixmap - -image_convertToFormat the_pixmap dome ARGB32 - -setRenderHint SmoothPixmapTransform false - -translate 75 100 -# standard draw -begin_block row -drawImage dome -50 -50 - -translate 90 0 -save -rotate_y 50 -drawImage dome -50 -50 -restore - -translate 65 0 -save -rotate_y 60 -drawImage dome -50 -50 -restore - -translate 50 0 -save -rotate_y 70 -drawImage dome -50 -50 -restore - -translate 30 0 -save -rotate_y 80 -drawImage dome -50 -50 -restore - -translate 24 0 -save -rotate_y 82 -drawImage dome -50 -50 -restore - -translate 20 0 -save -rotate_y 84 -drawImage dome -50 -50 -restore - -translate 16 0 -save -rotate_y 86 -drawImage dome -50 -50 -restore - -translate 12 0 -save -rotate_y 87 -drawImage dome -50 -50 -restore - -translate 8 0 -save -rotate_y 88 -drawImage dome -50 -50 -restore - -translate 6 0 -save -rotate_y 89 -drawImage dome -50 -50 -restore - -translate 6 0 -save -rotate_y 91 -drawImage dome -50 -50 -restore - -translate 6 0 -save -rotate_y 92 -drawImage dome -50 -50 -restore - -translate 8 0 -save -rotate_y 93 -drawImage dome -50 -50 -restore - -translate 12 0 -save -rotate_y 94 -drawImage dome -50 -50 -restore - -translate 16 0 -save -rotate_y 96 -drawImage dome -50 -50 -restore - -translate 20 0 -save -rotate_y 98 -drawImage dome -50 -50 -restore - -translate 24 0 -save -rotate_y 100 -drawImage dome -50 -50 -restore - -translate 30 0 -save -rotate_y 110 -drawImage dome -50 -50 -restore - -translate 50 0 -save -rotate_y 120 -drawImage dome -50 -50 -restore - -translate 65 0 -save -rotate_y 130 -drawImage dome -50 -50 -restore - -translate 90 0 -save -rotate_y 180 -drawImage dome -50 -50 -restore -end_block - -resetMatrix -translate 0 400 -translate 75 280 -setRenderHint SmoothPixmapTransform -repeat_block row - -resetMatrix -setPen black -translate 0 400 -translate 300 20 -drawText 0 0 "Fast Pixmap Transform" -resetMatrix -translate 0 400 -translate 300 210 -drawText 0 0 "Smooth Pixmap Transform" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/pixmap_rotation.qps b/tests/auto/lancelot/scripts/pixmap_rotation.qps deleted file mode 100644 index 2f1ffb53e6..0000000000 --- a/tests/auto/lancelot/scripts/pixmap_rotation.qps +++ /dev/null @@ -1,30 +0,0 @@ -# Version: 1 -# CheckVsReference: 0% (0 0 440 220) - -translate 120 120 - -begin_block drawing -save - rotate 90 - drawPixmap solid.png 0 0 - - rotate 90 - drawPixmap solid.png 0 0 - - rotate 90 - drawPixmap solid.png 0 0 - - rotate 90 - drawPixmap solid.png 0 0 -restore -end_block - -resetMatrix - -translate 340 120 -repeat_block drawing - -resetMatrix - -drawText 50 240 "Normal X form" -drawText 270 240 "Smooth xform" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/pixmap_scaling.qps b/tests/auto/lancelot/scripts/pixmap_scaling.qps deleted file mode 100644 index 651896f4a3..0000000000 --- a/tests/auto/lancelot/scripts/pixmap_scaling.qps +++ /dev/null @@ -1,224 +0,0 @@ -# Version: 1 -# CheckVsReference: 0% (0 30 600 70) -# CheckVsReference: 0% (290 130 280 60) -# CheckVsReference: 0% (0 180 250 90) - -# Hurra! Force line endings (?) - -translate 5 25 -setFont "arial" 8 - -save - drawText 15 0 "opaque image" - translate 50 50 - save - translate 1 1 - scale 20 20 - drawImage solid2x2.png 0 0 - restore - save - translate -1 1 - scale -20 20 - drawImage solid2x2.png 0 0 - restore - save - translate 1 -1 - scale 20 -20 - drawImage solid2x2.png 0 0 - restore - save - translate -1 -1 - scale -20 -20 - drawImage solid2x2.png 0 0 - restore - - -restore - -save - translate 150 0 - drawText 15 0 "alpha image" - translate 50 50 - save - translate 1 1 - scale 20 20 - drawImage alpha2x2.png 0 0 - restore - save - translate -1 1 - scale -20 20 - drawImage alpha2x2.png 0 0 - restore - save - translate 1 -1 - scale 20 -20 - drawImage alpha2x2.png 0 0 - restore - save - translate -1 -1 - scale -20 -20 - drawImage alpha2x2.png 0 0 - restore -restore - - -save - translate 0 150 - drawText 15 0 "solid pixmap" - translate 50 50 - save - translate 1 1 - scale 20 20 - drawPixmap solid2x2.png 0 0 - restore - save - translate -1 1 - scale -20 20 - drawPixmap solid2x2.png 0 0 - restore - save - translate 1 -1 - scale 20 -20 - drawPixmap solid2x2.png 0 0 - restore - save - translate -1 -1 - scale -20 -20 - drawPixmap solid2x2.png 0 0 - restore -restore - - -save - translate 150 150 - drawText 15 0 "alpha pixmap" - translate 50 50 - save - translate 1 1 - scale 20 20 - drawPixmap alpha2x2.png 0 0 - restore - save - translate -1 1 - scale -20 20 - drawPixmap alpha2x2.png 0 0 - restore - save - translate 1 -1 - scale 20 -20 - drawPixmap alpha2x2.png 0 0 - restore - save - translate -1 -1 - scale -20 -20 - drawPixmap alpha2x2.png 0 0 - restore -restore - - -save - translate 300 10 - save - drawText 0 -10 "subrect solid image" - drawImage solid2x2.png 0 0 50 5 0 0.0 2 0.2 - drawImage solid2x2.png 0 5 50 5 0 0.2 2 0.2 - drawImage solid2x2.png 0 10 50 5 0 0.4 2 0.2 - drawImage solid2x2.png 0 15 50 5 0 0.6 2 0.2 - drawImage solid2x2.png 0 20 50 5 0 0.8 2 0.2 - drawImage solid2x2.png 0 25 50 5 0 1.0 2 0.2 - drawImage solid2x2.png 0 30 50 5 0 1.2 2 0.2 - drawImage solid2x2.png 0 35 50 5 0 1.4 2 0.2 - drawImage solid2x2.png 0 40 50 5 0 1.6 2 0.2 - drawImage solid2x2.png 0 45 50 5 0 1.8 2 0.2 - translate 60 0 - drawImage solid2x2.png 0 0 5 50 0.0 0 0.2 2 - drawImage solid2x2.png 5 0 5 50 0.2 0 0.2 2 - drawImage solid2x2.png 10 0 5 50 0.4 0 0.2 2 - drawImage solid2x2.png 15 0 5 50 0.6 0 0.2 2 - drawImage solid2x2.png 20 0 5 50 0.8 0 0.2 2 - drawImage solid2x2.png 25 0 5 50 1.0 0 0.2 2 - drawImage solid2x2.png 30 0 5 50 1.2 0 0.2 2 - drawImage solid2x2.png 35 0 5 50 1.4 0 0.2 2 - drawImage solid2x2.png 40 0 5 50 1.6 0 0.2 2 - drawImage solid2x2.png 45 0 5 50 1.8 0 0.2 2 - restore - - save - translate 150 0 - drawText 0 -10 "subrect solid image" - drawImage alpha2x2.png 0 0 50 5 0 0.0 2 0.2 - drawImage alpha2x2.png 0 5 50 5 0 0.2 2 0.2 - drawImage alpha2x2.png 0 10 50 5 0 0.4 2 0.2 - drawImage alpha2x2.png 0 15 50 5 0 0.6 2 0.2 - drawImage alpha2x2.png 0 20 50 5 0 0.8 2 0.2 - drawImage alpha2x2.png 0 25 50 5 0 1.0 2 0.2 - drawImage alpha2x2.png 0 30 50 5 0 1.2 2 0.2 - drawImage alpha2x2.png 0 35 50 5 0 1.4 2 0.2 - drawImage alpha2x2.png 0 40 50 5 0 1.6 2 0.2 - drawImage alpha2x2.png 0 45 50 5 0 1.8 2 0.2 - translate 60 0 - drawImage alpha2x2.png 0 0 5 50 0.0 0 0.2 2 - drawImage alpha2x2.png 5 0 5 50 0.2 0 0.2 2 - drawImage alpha2x2.png 10 0 5 50 0.4 0 0.2 2 - drawImage alpha2x2.png 15 0 5 50 0.6 0 0.2 2 - drawImage alpha2x2.png 20 0 5 50 0.8 0 0.2 2 - drawImage alpha2x2.png 25 0 5 50 1.0 0 0.2 2 - drawImage alpha2x2.png 30 0 5 50 1.2 0 0.2 2 - drawImage alpha2x2.png 35 0 5 50 1.4 0 0.2 2 - drawImage alpha2x2.png 40 0 5 50 1.6 0 0.2 2 - drawImage alpha2x2.png 45 0 5 50 1.8 0 0.2 2 - restore - - save - translate 0 100 - drawText 0 -10 "subrect alpha pixmap" - drawPixmap solid2x2.png 0 0 50 5 0 0.0 2 0.2 - drawPixmap solid2x2.png 0 5 50 5 0 0.2 2 0.2 - drawPixmap solid2x2.png 0 10 50 5 0 0.4 2 0.2 - drawPixmap solid2x2.png 0 15 50 5 0 0.6 2 0.2 - drawPixmap solid2x2.png 0 20 50 5 0 0.8 2 0.2 - drawPixmap solid2x2.png 0 25 50 5 0 1.0 2 0.2 - drawPixmap solid2x2.png 0 30 50 5 0 1.2 2 0.2 - drawPixmap solid2x2.png 0 35 50 5 0 1.4 2 0.2 - drawPixmap solid2x2.png 0 40 50 5 0 1.6 2 0.2 - drawPixmap solid2x2.png 0 45 50 5 0 1.8 2 0.2 - translate 60 0 - drawPixmap solid2x2.png 0 0 5 50 0.0 0 0.2 2 - drawPixmap solid2x2.png 5 0 5 50 0.2 0 0.2 2 - drawPixmap solid2x2.png 10 0 5 50 0.4 0 0.2 2 - drawPixmap solid2x2.png 15 0 5 50 0.6 0 0.2 2 - drawPixmap solid2x2.png 20 0 5 50 0.8 0 0.2 2 - drawPixmap solid2x2.png 25 0 5 50 1.0 0 0.2 2 - drawPixmap solid2x2.png 30 0 5 50 1.2 0 0.2 2 - drawPixmap solid2x2.png 35 0 5 50 1.4 0 0.2 2 - drawPixmap solid2x2.png 40 0 5 50 1.6 0 0.2 2 - drawPixmap solid2x2.png 45 0 5 50 1.8 0 0.2 2 - restore - - save - translate 150 100 - drawText 0 -10 "subrect alpha pixmap" - drawPixmap alpha2x2.png 0 0 50 5 0 0.0 2 0.2 - drawPixmap alpha2x2.png 0 5 50 5 0 0.2 2 0.2 - drawPixmap alpha2x2.png 0 10 50 5 0 0.4 2 0.2 - drawPixmap alpha2x2.png 0 15 50 5 0 0.6 2 0.2 - drawPixmap alpha2x2.png 0 20 50 5 0 0.8 2 0.2 - drawPixmap alpha2x2.png 0 25 50 5 0 1.0 2 0.2 - drawPixmap alpha2x2.png 0 30 50 5 0 1.2 2 0.2 - drawPixmap alpha2x2.png 0 35 50 5 0 1.4 2 0.2 - drawPixmap alpha2x2.png 0 40 50 5 0 1.6 2 0.2 - drawPixmap alpha2x2.png 0 45 50 5 0 1.8 2 0.2 - translate 60 0 - drawPixmap alpha2x2.png 0 0 5 50 0.0 0 0.2 2 - drawPixmap alpha2x2.png 5 0 5 50 0.2 0 0.2 2 - drawPixmap alpha2x2.png 10 0 5 50 0.4 0 0.2 2 - drawPixmap alpha2x2.png 15 0 5 50 0.6 0 0.2 2 - drawPixmap alpha2x2.png 20 0 5 50 0.8 0 0.2 2 - drawPixmap alpha2x2.png 25 0 5 50 1.0 0 0.2 2 - drawPixmap alpha2x2.png 30 0 5 50 1.2 0 0.2 2 - drawPixmap alpha2x2.png 35 0 5 50 1.4 0 0.2 2 - drawPixmap alpha2x2.png 40 0 5 50 1.6 0 0.2 2 - drawPixmap alpha2x2.png 45 0 5 50 1.8 0 0.2 2 - restore - -restore \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/pixmap_subpixel.qps b/tests/auto/lancelot/scripts/pixmap_subpixel.qps deleted file mode 100644 index 908f7c3465..0000000000 --- a/tests/auto/lancelot/scripts/pixmap_subpixel.qps +++ /dev/null @@ -1,117 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -translate 50 50 - -# Pixmaps at 0.1 offset, unclipped -begin_block draw_pixmaps -save - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 - drawPixmap border.png 0 0 - translate 20.1 0.1 -restore -end_block - -# Tiled pixmaps at 0.1 offsets, unclipped -translate 0 50 -begin_block draw_tiled -save - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 - drawTiledPixmap border.png 0 0 16 16 0 0 - translate 20.1 0.1 -restore -end_block - - -path_moveTo clip 0 0 -path_lineTo clip width 0 -path_lineTo clip width 400 -path_lineTo clip 0 height -setClipPath clip - -translate 0 50 -# Pixmaps at 0.1 offset, clipped -repeat_block draw_pixmaps - - -# Tiled pixmaps at 0.1 offsets... -translate 0 50 -repeat_block draw_tiled - diff --git a/tests/auto/lancelot/scripts/pixmaps.qps b/tests/auto/lancelot/scripts/pixmaps.qps deleted file mode 100644 index 8e60997acc..0000000000 --- a/tests/auto/lancelot/scripts/pixmaps.qps +++ /dev/null @@ -1,106 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 0 690 580) - - -setRenderHint Antialiasing - -setPen #00ff00 - -pixmap_load dome_argb32.png the_pixmap -begin_block draw_stuff - -save - - # standard draw - drawPixmap the_pixmap 0 0 - - # sub recting - translate 120 0 - drawPixmap the_pixmap 0 0 40 40 0 0 40 40 - drawPixmap the_pixmap 60 0 40 40 60 0 40 40 - drawPixmap the_pixmap 0 60 40 40 0 60 40 40 - drawPixmap the_pixmap 60 60 40 40 60 60 40 40 - drawPixmap the_pixmap 0 40 40 20 0 40 40 20 - drawPixmap the_pixmap 60 40 40 20 60 40 40 20 - drawPixmap the_pixmap 40 0 20 100 40 0 20 100 - - # subrecting w/scale - translate 120 0 - drawPixmap the_pixmap 0 0 50 50 0 0 25 25 - drawPixmap the_pixmap 50 0 50 50 25 0 25 25 - drawPixmap the_pixmap 0 50 50 50 0 25 25 25 - drawPixmap the_pixmap 50 50 50 50 25 25 25 25 - - # subrecting w/scale & smooth xform - translate 120 0 - setRenderHint SmoothPixmapTransformation - drawPixmap the_pixmap 0 0 50 50 0 0 25 25 - drawPixmap the_pixmap 50 0 50 50 25 0 25 25 - drawPixmap the_pixmap 0 50 50 50 0 25 25 25 - drawPixmap the_pixmap 50 50 50 50 25 25 25 25 - - - # Rotation w/o smooth xform - translate 120 0 - save - setRenderHint SmoothPixmapTransform off - rotate 10 - drawPixmap the_pixmap 0 0 - restore - - # Rotation w smooth xform - translate 120 0 - save - setRenderHint SmoothPixmapTransform - rotate 10 - drawPixmap the_pixmap 0 0 - restore - -restore - -end_block - - -translate 0 120 -pixmap_load dome_rgb32.png the_pixmap -repeat_block draw_stuff - -translate 0 120 -pixmap_load dome_indexed.png the_pixmap -repeat_block draw_stuff - -translate 0 120 -pixmap_load dome_indexed_mask.png the_pixmap -repeat_block draw_stuff - -translate 0 120 -pixmap_load dome_mono.png the_pixmap -repeat_block draw_stuff - - -resetMatrix -translate 700 60 -setPen black -drawText 0 0 "32 bit w/alpha" -translate 0 120 -drawText 0 0 "32 bit w/o alpha" -translate 0 120 -drawText 0 0 "8 bit indexed" -translate 0 120 -drawText 0 0 "8 bit indexed w/mask" -translate 0 120 -drawText 0 0 "1 bit" -resetMatrix -translate 0 600 -drawText 0 0 "normal" -translate 120 0 -drawText 0 0 "subrect" -translate 120 0 -drawText 0 0 "subrect scale" -translate 120 0 -drawText 0 0 "subrect scale smooth" -translate 120 0 -drawText 0 0 "xform" -translate 120 0 -drawText 0 0 "smooth xform" -translate 120 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/porter_duff.qps b/tests/auto/lancelot/scripts/porter_duff.qps deleted file mode 100644 index 166e48a57f..0000000000 --- a/tests/auto/lancelot/scripts/porter_duff.qps +++ /dev/null @@ -1,251 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - - -translate 0 50 - -surface_begin 0 0 100 100 - -begin_block predraw -setRenderHint Antialiasing -setPen nopen -setBrush 0x7f000000 -drawEllipse 10 10 80 80 -end_block - -setCompositionMode SourceOver - -begin_block postdraw - - -setBrush 0x1fff0000 -drawRect 0 0 50 50 - -setBrush 0xdf00ff00 -drawRect 50 50 50 50 - -setBrush 0x7f0000ff -drawEllipse 30 30 40 40 - -# a black rectangle around -setCompositionMode SourceOver -setPen black -setBrush nobrush -drawRect 0.5 0.5 99 99 - -end_block -surface_end - - -# Destination over -surface_begin 100 0 100 100 -repeat_block predraw -setCompositionMode DestinationOver -repeat_block postdraw -surface_end - - -# Clear -surface_begin 200 0 100 100 -repeat_block predraw -setCompositionMode Clear -repeat_block postdraw -surface_end - - -# Source -surface_begin 300 0 100 100 -repeat_block predraw -setCompositionMode Source -repeat_block postdraw -surface_end - - -# Destination -surface_begin 400 0 100 100 -repeat_block predraw -setCompositionMode Destination -repeat_block postdraw -surface_end - - -# Source In -surface_begin 500 0 100 100 -repeat_block predraw -setCompositionMode SourceIn -repeat_block postdraw -surface_end - -translate 0 50 - -# Destination In -surface_begin 0 100 100 100 -repeat_block predraw -setCompositionMode DestinationIn -repeat_block postdraw -surface_end - - -# Source Out -surface_begin 100 100 100 100 -repeat_block predraw -setCompositionMode SourceOut -repeat_block postdraw -surface_end - - -# Destination Out -surface_begin 200 100 100 100 -repeat_block predraw -setCompositionMode DestinationOut -repeat_block postdraw -surface_end - - -# SourceAtop -surface_begin 300 100 100 100 -repeat_block predraw -setCompositionMode SourceAtop -repeat_block postdraw -surface_end - - -# DestinationAtop -surface_begin 400 100 100 100 -repeat_block predraw -setCompositionMode DestinationAtop -repeat_block postdraw -surface_end - - -# Xor -surface_begin 500 100 100 100 -repeat_block predraw -setCompositionMode Xor -repeat_block postdraw -surface_end - -translate 0 50 - -# Plus -surface_begin 0 200 100 100 -repeat_block predraw -setCompositionMode Plus -repeat_block postdraw -surface_end - - -# Multiply -surface_begin 100 200 100 100 -repeat_block predraw -setCompositionMode Multiply -repeat_block postdraw -surface_end - - -# Screen -surface_begin 200 200 100 100 -repeat_block predraw -setCompositionMode Screen -repeat_block postdraw -surface_end - - -# Overlay -surface_begin 300 200 100 100 -repeat_block predraw -setCompositionMode Overlay -repeat_block postdraw -surface_end - - -# Darken -surface_begin 400 200 100 100 -repeat_block predraw -setCompositionMode Darken -repeat_block postdraw -surface_end - - -# Lighten -surface_begin 500 200 100 100 -repeat_block predraw -setCompositionMode Lighten -repeat_block postdraw -surface_end - -translate 0 50 - -# ColorDodge -surface_begin 0 300 100 100 -repeat_block predraw -setCompositionMode ColorDodge -repeat_block postdraw -surface_end - - -# Multiply -surface_begin 100 300 100 100 -repeat_block predraw -setCompositionMode ColorBurn -repeat_block postdraw -surface_end - - -# Screen -surface_begin 200 300 100 100 -repeat_block predraw -setCompositionMode HardLight -repeat_block postdraw -surface_end - - -# Overlay -surface_begin 300 300 100 100 -repeat_block predraw -setCompositionMode SoftLight -repeat_block postdraw -surface_end - - -# Darken -surface_begin 400 300 100 100 -repeat_block predraw -setCompositionMode Difference -repeat_block postdraw -surface_end - - -# Lighten -surface_begin 500 300 100 100 -repeat_block predraw -setCompositionMode Exclusion -repeat_block postdraw -surface_end - -resetMatrix - -drawText 0 50 "SourceOver" -drawText 100 50 "DestinationOver" -drawText 200 50 "Clear" -drawText 300 50 "Source" -drawText 400 50 "Destination" -drawText 500 50 "SourceIn" -drawText 0 200 "DestinationIn" -drawText 100 200 "SourceOut" -drawText 200 200 "DestinationOut" -drawText 300 200 "SourceAtop" -drawText 400 200 "DestinationAtop" -drawText 500 200 "Xor" -drawText 0 350 "Plus" -drawText 100 350 "Multiply" -drawText 200 350 "Screen" -drawText 300 350 "Overlay" -drawText 400 350 "Darken" -drawText 500 350 "Lighten" -drawText 0 500 "ColorDodge" -drawText 100 500 "ColorBurn" -drawText 200 500 "HardLight" -drawText 300 500 "SoftLight" -drawText 400 500 "Difference" -drawText 500 500 "Exclusion" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/porter_duff2.qps b/tests/auto/lancelot/scripts/porter_duff2.qps deleted file mode 100644 index a792d9b278..0000000000 --- a/tests/auto/lancelot/scripts/porter_duff2.qps +++ /dev/null @@ -1,261 +0,0 @@ -# Version: 1 -# CheckVsReference: 1% (0 50 600 100) -# CheckVsReference: 1% (0 200 600 100) -# CheckVsReference: 1% (0 350 600 100) -# CheckVsReference: 1% (0 500 600 100) - -translate 0 50 - -surface_begin 0 0 100 100 - -begin_block predraw -setRenderHint Antialiasing -setPen nopen -gradient_clearStops -gradient_appendStop 0 efff0000 -gradient_appendStop 0.5 dfffff00 -gradient_appendStop 1 ef00ff00 - -gradient_setSpread PadSpread -gradient_setLinear 10 10 90 90 -drawEllipse 10 10 80 80 -end_block - -setCompositionMode SourceOver - -begin_block postdraw - -gradient_clearStops -gradient_appendStop 0 afff0000 -gradient_appendStop 0.5 cf0000ff -gradient_appendStop 1 bf00ff00 - -gradient_setSpread PadSpread -gradient_setLinear 0 0 100 0 -drawEllipse 10 10 30 30 -drawEllipse 10 60 30 30 -drawEllipse 60 60 30 30 -drawEllipse 60 10 30 30 -drawEllipse 35 35 30 30 - -# a black rectangle around -setCompositionMode SourceOver -setPen black -setBrush nobrush -drawRect 0.5 0.5 99 99 - -end_block -surface_end - -# Destination over -surface_begin 100 0 100 100 -repeat_block predraw -setCompositionMode DestinationOver -repeat_block postdraw -surface_end - - -# Clear -surface_begin 200 0 100 100 -repeat_block predraw -setCompositionMode Clear -repeat_block postdraw -surface_end - - -# Source -surface_begin 300 0 100 100 -repeat_block predraw -setCompositionMode Source -repeat_block postdraw -surface_end - - -# Destination -surface_begin 400 0 100 100 -repeat_block predraw -setCompositionMode Destination -repeat_block postdraw -surface_end - - -# Source In -surface_begin 500 0 100 100 -repeat_block predraw -setCompositionMode SourceIn -repeat_block postdraw -surface_end - -translate 0 50 - -# Destination In -surface_begin 0 100 100 100 -repeat_block predraw -setCompositionMode DestinationIn -repeat_block postdraw -surface_end - - -# Source Out -surface_begin 100 100 100 100 -repeat_block predraw -setCompositionMode SourceOut -repeat_block postdraw -surface_end - - -# Destination Out -surface_begin 200 100 100 100 -repeat_block predraw -setCompositionMode DestinationOut -repeat_block postdraw -surface_end - - -# SourceAtop -surface_begin 300 100 100 100 -repeat_block predraw -setCompositionMode SourceAtop -repeat_block postdraw -surface_end - - -# DestinationAtop -surface_begin 400 100 100 100 -repeat_block predraw -setCompositionMode DestinationAtop -repeat_block postdraw -surface_end - - -# Xor -surface_begin 500 100 100 100 -repeat_block predraw -setCompositionMode Xor -repeat_block postdraw -surface_end - -translate 0 50 - -# Plus -surface_begin 0 200 100 100 -repeat_block predraw -setCompositionMode Plus -repeat_block postdraw -surface_end - - -# Multiply -surface_begin 100 200 100 100 -repeat_block predraw -setCompositionMode Multiply -repeat_block postdraw -surface_end - - -# Screen -surface_begin 200 200 100 100 -repeat_block predraw -setCompositionMode Screen -repeat_block postdraw -surface_end - - -# Overlay -surface_begin 300 200 100 100 -repeat_block predraw -setCompositionMode Overlay -repeat_block postdraw -surface_end - - -# Darken -surface_begin 400 200 100 100 -repeat_block predraw -setCompositionMode Darken -repeat_block postdraw -surface_end - - -# Lighten -surface_begin 500 200 100 100 -repeat_block predraw -setCompositionMode Lighten -repeat_block postdraw -surface_end - -translate 0 50 - -# ColorDodge -surface_begin 0 300 100 100 -repeat_block predraw -setCompositionMode ColorDodge -repeat_block postdraw -surface_end - - -# Multiply -surface_begin 100 300 100 100 -repeat_block predraw -setCompositionMode ColorBurn -repeat_block postdraw -surface_end - - -# Screen -surface_begin 200 300 100 100 -repeat_block predraw -setCompositionMode HardLight -repeat_block postdraw -surface_end - - -# Overlay -surface_begin 300 300 100 100 -repeat_block predraw -setCompositionMode SoftLight -repeat_block postdraw -surface_end - - -# Darken -surface_begin 400 300 100 100 -repeat_block predraw -setCompositionMode Difference -repeat_block postdraw -surface_end - - -# Lighten -surface_begin 500 300 100 100 -repeat_block predraw -setCompositionMode Exclusion -repeat_block postdraw -surface_end - -resetMatrix - -drawText 0 50 "SourceOver" -drawText 100 50 "DestinationOver" -drawText 200 50 "Clear" -drawText 300 50 "Source" -drawText 400 50 "Destination" -drawText 500 50 "SourceIn" -drawText 0 200 "DestinationIn" -drawText 100 200 "SourceOut" -drawText 200 200 "DestinationOut" -drawText 300 200 "SourceAtop" -drawText 400 200 "DestinationAtop" -drawText 500 200 "Xor" -drawText 0 350 "Plus" -drawText 100 350 "Multiply" -drawText 200 350 "Screen" -drawText 300 350 "Overlay" -drawText 400 350 "Darken" -drawText 500 350 "Lighten" -drawText 0 500 "ColorDodge" -drawText 100 500 "ColorBurn" -drawText 200 500 "HardLight" -drawText 300 500 "SoftLight" -drawText 400 500 "Difference" -drawText 500 500 "Exclusion" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/primitives.qps b/tests/auto/lancelot/scripts/primitives.qps deleted file mode 100644 index f44ba27566..0000000000 --- a/tests/auto/lancelot/scripts/primitives.qps +++ /dev/null @@ -1,184 +0,0 @@ -# Version: 1#Version: 1 -# CheckVsReference: 5% - - -# CheckVsReference: 5% - -setBrush #ff7f7fff -setPen black 1 solidline -translate 20 20 -begin_block testblock -save -drawRect 0 0 10 10 -drawRect 20 0 20 10 -drawRect 0 20 10 20 -drawRect 20 20 20 20 -translate 50 0 -setPen NoPen -drawRect 0 0 10 10 -drawRect 20 0 20 10 -drawRect 0 20 10 20 -drawRect 20 20 20 20 -restore -save -translate 0 50 -drawEllipse 0 0 10 10 -drawEllipse 20 0 20 10 -drawEllipse 0 20 10 20 -drawEllipse 20 20 20 20 -translate 50 0 -setPen NoPen -drawEllipse 0 0 10 10 -drawEllipse 20 0 20 10 -drawEllipse 0 20 10 20 -drawEllipse 20 20 20 20 -restore -save -translate 0 100 -drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] -save -translate 0 50 -drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] Winding -translate 0 45 -drawPolyline [ 0 0 50 0 25 25 ] -restore -setPen NoPen -translate 50 0 -drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] -save -translate 0 50 -drawPolygon [ 0 0 30 0 30 30 10 30 10 10 40 10 40 40 0 40 ] Winding -restore -save -translate -20 100 -drawPie 0 0 50 50 0 1500 -restore -restore -end_block -setPen black 1 SolidLine FlatCap -translate 200 0 -scale 2 1 -rotate 10 -repeat_block testblock -resetMatrix -translate 0 250 -setBrush 7f7f7fff -translate 20 20 -repeat_block testblock -setPen black 1 SolidLine FlatCap -translate 200 0 -scale 2 1 -rotate 10 -repeat_block testblock -resetMatrix -save -setRenderHint LineAntialiasing -setBrush 7f7fff -translate 20 500 -repeat_block testblock -translate 200 0 -scale 2 1 -rotate 10 -repeat_block testblock -restore -setRenderHint LineAntialiasing false -translate 420 20 -begin_block lines -drawLine 0 0 100 0 -drawLine 0 0 100 10 -drawLine 0 0 100 20 -drawLine 0 0 100 30 -drawLine 0 0 100 40 -drawLine 0 0 100 50 -drawLine 0 0 100 60 -drawLine 0 0 100 70 -drawLine 0 0 100 80 -drawLine 0 0 100 90 -drawLine 0 0 100 100 -drawLine 0 0 90 100 -drawLine 0 0 80 100 -drawLine 0 0 70 100 -drawLine 0 0 60 100 -drawLine 0 0 50 100 -drawLine 0 0 40 100 -drawLine 0 0 30 100 -drawLine 0 0 20 100 -drawLine 0 0 10 100 -drawLine 0 0 0 100 -end_block -setRenderHint LineAntialiasing -translate 0 120 -repeat_block lines -translate 0 120 -scale 5 2 -repeat_block lines -resetMatrix -translate 420 500 -begin_block roundedrects -save -drawRoundedRect 0 0 50 30 5 5 -translate 60 0 -drawRoundedRect 0 0 50 30 7.5 7.5 -translate 60 0 -drawRoundedRect 0 0 50 30 10 10 -translate 60 0 -drawRoundedRect 0 0 50 30 12.5 12.5 -translate 60 0 -drawRoundedRect 0 0 50 30 15 15 -restore -save -translate 0 40 -drawRoundedRect 0 0 50 30 20 20 RelativeSize -translate 60 0 -drawRoundedRect 0 0 50 30 40 40 RelativeSize -translate 60 0 -drawRoundedRect 0 0 50 30 60 60 RelativeSize -translate 60 0 -drawRoundedRect 0 0 50 30 80 80 RelativeSize -translate 60 0 -drawRoundedRect 0 0 50 30 100 100 RelativeSize -restore -end_block -translate 0.5 80.5 -repeat_block roundedrects -translate -0.5 79.5 -setRenderHint Antialiasing off -repeat_block roundedrects -resetMatrix -setRenderHint Antialiasing off -setPen black 1 -begin_block drawShapes -translate 550.5 25 -rotate 45 -setBrush nobrush -drawEllipse -10 -10 20 20 -drawLine 10 0 50 0 -drawRect 50 -7 14 14 -resetMatrix -end_block -setPen black 2 -translate 25 0 -repeat_block drawShapes -setPen black 3 -translate 50 0 -repeat_block drawShapes -setPen black 4 -translate 75 0 -repeat_block drawShapes -resetMatrix -setRenderHint Antialiasing off -setPen nopen -translate 550 100 -setBrush #7f7f7fff -drawRect -0.5 -0.5 21 21 -setBrush red -drawEllipse 0 0 20 20 -setBrush nobrush -setPen black -drawEllipse 0 0 20 20 -translate 25 0 -setPen nopen -setBrush #7f7f7fff -drawRect 0 0 20 20 -setBrush red -drawEllipse 0 0 20 20 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/radial_gradients.qps b/tests/auto/lancelot/scripts/radial_gradients.qps deleted file mode 100644 index b55df8bde6..0000000000 --- a/tests/auto/lancelot/scripts/radial_gradients.qps +++ /dev/null @@ -1,99 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% (0 0 600 400) - -path_addRect path 400 0 80 80 -path_addEllipse path 440 40 60 60 - -setRenderHint Antialiasing - -setPen black - -begin_block gradients -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setRadial 20 20 50 40 40 -drawRect 0 0 100 100 - -gradient_setSpread ReflectSpread -gradient_setRadial 120 20 50 140 40 -drawEllipse 100 0 100 100 - -gradient_setSpread RepeatSpread -gradient_setRadial 220 20 50 240 40 -drawRoundRect 200 0 100 100 - -gradient_clearStops -gradient_appendStop 0 3f7f7fff -gradient_appendStop 0.5 dfdfffff -gradient_appendStop 1 7f00007f - -gradient_setSpread PadSpread -gradient_setRadial 320 20 50 340 40 -drawPolygon [300 0 390 0 350 99] - -gradient_setSpread ReflectSpread -gradient_setRadial 420 20 50 440 40 -drawPath path - -gradient_setSpread RepeatSpread -gradient_setRadial 520 20 50 540 40 -drawPie 500 0 100 100 720 4320 -end_block - -translate 0 100 -scale 1 2 -repeat_block gradients - -resetMatrix -translate 0 300 -brushTranslate 30 0 -brushScale 0.9 0.9 -brushRotate 20 -repeat_block gradients - -# Some helpful info perhaps? -resetMatrix -setPen black - -drawText 610 50 "No XForm" -drawText 610 200 "scale 1x2" -drawText 610 300 "brush transform" -drawText 10 450 "Pad" -drawText 110 450 "Reflect" -drawText 210 450 "Repeat" -drawText 310 450 "Pad w/alpha" -drawText 410 450 "Reflect w/alpha" -drawText 510 450 "Repeat w/alpha" - -# Radius and focal indicators -setPen 3f000000 -setBrush nobrush - -begin_block ellipse_draw -setClipRect 0 0 100 100 -drawEllipse -30 -30 100 100 -drawEllipse 35 35 11 11 -translate 100 0 -end_block - -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw - -resetMatrix -translate 0 100 -scale 1 2 -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw -repeat_block ellipse_draw \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/radial_gradients_perspectives.qps b/tests/auto/lancelot/scripts/radial_gradients_perspectives.qps deleted file mode 100644 index 4557354dce..0000000000 --- a/tests/auto/lancelot/scripts/radial_gradients_perspectives.qps +++ /dev/null @@ -1,62 +0,0 @@ -# Version: 1 - - -setRenderHint Antialiasing - -setPen #00ff00 - -translate 10 10 -# standard draw -begin_block gradient -gradient_clearStops -gradient_appendStop 0 red -gradient_appendStop 0.25 orange -gradient_appendStop 0.5 yellow -gradient_appendStop 0.8 green -gradient_appendStop 1 cyan - -gradient_setSpread PadSpread -gradient_setRadial 110 100 230 230 240 -drawRect 0 0 300 300 -end_block gradient - -# Rotation w/o smooth xform -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 - repeat_block gradient -restore -restore - -translate 0 320 - -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 - repeat_block gradient -restore - -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 - repeat_block gradient -restore -restore - - -resetMatrix -setPen black -translate 125 20 -drawText 0 0 "No transform" -translate 350 0 -drawText 0 0 "Left Tilted" -resetMatrix -translate 125 350 -drawText 0 0 "Bottom Tilted" -translate 350 0 -drawText 0 0 "Right Tilted" -translate 120 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/rasterops.qps b/tests/auto/lancelot/scripts/rasterops.qps deleted file mode 100644 index 21f943b543..0000000000 --- a/tests/auto/lancelot/scripts/rasterops.qps +++ /dev/null @@ -1,87 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -setPen NoPen - -setBrush black -drawRect 10 10 60 500 - -setCompositionMode SourceOrDestination -translate 20 20 - -begin_block drawShape - setBrush 0xffff0000 - drawEllipse 5 5 30 30 - setBrush 0xff00ff00 - drawRect 0 0 20 20 - setBrush 0xff0000ff - drawRect 20 20 20 20 -end_block - -begin_block loop - setCompositionMode SourceAndDestination - translate 0 50 -repeat_block drawShape - -setCompositionMode SourceXorDestination -translate 0 50 -repeat_block drawShape - -setCompositionMode NotSourceAndNotDestination -translate 0 50 -repeat_block drawShape - -setCompositionMode NotSourceOrNotDestination -translate 0 50 -repeat_block drawShape - -setCompositionMode NotSourceXorDestination -translate 0 50 -repeat_block drawShape - -setCompositionMode NotSource -translate 0 50 -repeat_block drawShape - -setCompositionMode NotSourceAndDestination -translate 0 50 -repeat_block drawShape - -setCompositionMode SourceAndNotDestination -translate 0 50 -repeat_block drawShape -end_block - -resetMatrix -setCompositionMode Source -setBrush white -drawRect 100 10 60 500 -translate 110 20 -repeat_block loop - -resetMatrix -setCompositionMode Source -translate 190 20 -repeat_block loop - -resetMatrix -setPen black -setCompositionMode SourceOver -translate 250 45 -drawText 20 0 "Or ROP" -translate 0 50 -drawText 20 0 "And ROP" -translate 0 50 -drawText 20 0 "Xor ROP" -translate 0 50 -drawText 20 0 "Nor ROP" -translate 0 50 -drawText 20 0 "Nand ROP" -translate 0 50 -drawText 0 0 "NSrcXorDst ROP" -translate 0 50 -drawText 20 0 "NSrc ROP" -translate 0 50 -drawText 0 0 "NSrcAndDst ROP" -translate 0 50 -drawText 0 0 "SrcAndNDst ROP" \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/sizes.qps b/tests/auto/lancelot/scripts/sizes.qps deleted file mode 100644 index 68e01c3262..0000000000 --- a/tests/auto/lancelot/scripts/sizes.qps +++ /dev/null @@ -1,90 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% - -setPen NoPen -setBrush black - -translate 10 10 - -begin_block testblock -drawRect 0 0 10 10 -drawRect 20 0 11 11 -drawRect 40 0 12 12 -drawRect 60 0 13 13 -drawRect 80 0 14 14 -drawRect 100 0 15 15 -drawRect 120 0 16 16 -drawRect 140 0 17 17 -drawRect 160 0 18 18 -drawRect 180 0 19 19 - -drawEllipse 0 20 10 10 -drawEllipse 20 20 11 11 -drawEllipse 40 20 12 12 -drawEllipse 60 20 13 13 -drawEllipse 80 20 14 14 -drawEllipse 100 20 15 15 -drawEllipse 120 20 16 16 -drawEllipse 140 20 17 17 -drawEllipse 160 20 18 18 -drawEllipse 180 20 19 19 - -drawRoundRect 0 40 10 10 -drawRoundRect 20 40 11 11 -drawRoundRect 40 40 12 12 -drawRoundRect 60 40 13 13 -drawRoundRect 80 40 14 14 -drawRoundRect 100 40 15 15 -drawRoundRect 120 40 16 16 -drawRoundRect 140 40 17 17 -drawRoundRect 160 40 18 18 -drawRoundRect 180 40 19 19 - -drawPie 0 60 10 10 0 4320 -drawPie 20 60 11 11 0 4320 -drawPie 40 60 12 12 0 4320 -drawPie 60 60 13 13 0 4320 -drawPie 80 60 14 14 0 4320 -drawPie 100 60 15 15 0 4320 -drawPie 120 60 16 16 0 4320 -drawPie 140 60 17 17 0 4320 -drawPie 160 60 18 18 0 4320 -drawPie 180 60 19 19 0 4320 - -drawArc 0 80 10 10 0 4320 -drawArc 20 80 11 11 0 4320 -drawArc 40 80 12 12 0 4320 -drawArc 60 80 13 13 0 4320 -drawArc 80 80 14 14 0 4320 -drawArc 100 80 15 15 0 4320 -drawArc 120 80 16 16 0 4320 -drawArc 140 80 17 17 0 4320 -drawArc 160 80 18 18 0 4320 -drawArc 180 80 19 19 0 4320 - -drawChord 0 100 10 10 0 4320 -drawChord 20 100 11 11 0 4320 -drawChord 40 100 12 12 0 4320 -drawChord 60 100 13 13 0 4320 -drawChord 80 100 14 14 0 4320 -drawChord 100 100 15 15 0 4320 -drawChord 120 100 16 16 0 4320 -drawChord 140 100 17 17 0 4320 -drawChord 160 100 18 18 0 4320 -drawChord 180 100 19 19 0 4320 - -end_block - -setPen red -translate 0 150 -repeat_block testblock - -setRenderHint LineAntialiasing - -setPen nopen -translate 0 150 -repeat_block testblock - -setPen red -translate 0 150 -repeat_block testblock diff --git a/tests/auto/lancelot/scripts/statictext.qps b/tests/auto/lancelot/scripts/statictext.qps deleted file mode 100644 index b62b623462..0000000000 --- a/tests/auto/lancelot/scripts/statictext.qps +++ /dev/null @@ -1,122 +0,0 @@ -drawStaticText -5 5 "Text that is drawn outside the bounds..." - -translate 20 20 -begin_block text_drawing -save - setFont "sansserif" 10 normal - drawStaticText 0 20 "sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawStaticText 0 40 "sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawStaticText 0 60 "sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawStaticText 0 80 "sansserif 10pt, bold italic" - - - translate 0 100 - setPen #7fff0000 - - setFont "sansserif" 10 normal - drawStaticText 0 20 "alpha sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawStaticText 0 40 "alpha sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawStaticText 0 60 "alpha sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawStaticText 0 80 "alpha sansserif 10pt, bold italic" - - - translate 0 100 - setPen black - save - scale 0.9 0.9 - - setFont "sansserif" 10 normal - drawStaticText 0 20 "scaled sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawStaticText 0 40 "scaled sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawStaticText 0 60 "scaled sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawStaticText 0 80 "scaled sansserif 10pt, bold italic" - restore - - translate 0 100 - setPen black - save - translate 200 90 - rotate 185 - - setFont "sansserif" 10 normal - drawStaticText 0 20 "scaled sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawStaticText 0 40 "scaled sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawStaticText 0 60 "scaled sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawStaticText 0 80 "scaled sansserif 10pt, bold italic" - restore - - translate 0 100 - gradient_appendStop 0 red - gradient_appendStop 0.5 #00ff00 - gradient_appendStop 1 blue - gradient_setLinear 0 0 200 0 - setPen brush - - setFont "sansserif" 10 normal - drawStaticText 0 0 "gradient sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawStaticText 0 20 "gradient sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawStaticText 0 40 "gradient sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawStaticText 0 60 "gradient sansserif 10pt, bold italic" -restore -end_block - -translate 250 0 -drawStaticText 25 520 "clipped to rectangle" -save - setPen #3f000000 - setBrush nobrush - drawRect 20 0 100 500 - setClipRect 20 0 100 500 - setPen black - repeat_block text_drawing -restore - -translate 150 0 -drawStaticText 25 520 "clipped to path" -save - path_moveTo clip 20 0 - path_cubicTo clip 0 200 40 400 20 400 - path_lineTo clip 30 500 - path_lineTo clip 30 0 - path_lineTo clip 40 0 - path_lineTo clip 40 500 - path_lineTo clip 120 500 - path_lineTo clip 120 0 - path_lineTo clip 20 0 - setPen #3f000000 - setBrush nobrush - drawPath clip - setClipPath clip - setPen black - repeat_block text_drawing -restore diff --git a/tests/auto/lancelot/scripts/text.qps b/tests/auto/lancelot/scripts/text.qps deleted file mode 100644 index d7ee83290b..0000000000 --- a/tests/auto/lancelot/scripts/text.qps +++ /dev/null @@ -1,124 +0,0 @@ -# Version: 1 - -drawText -5 5 "Text that is drawn outside the bounds..." - -translate 20 20 -begin_block text_drawing -save - setFont "sansserif" 10 normal - drawText 0 20 "sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawText 0 40 "sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawText 0 60 "sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawText 0 80 "sansserif 10pt, bold italic" - - - translate 0 100 - setPen #7fff0000 - - setFont "sansserif" 10 normal - drawText 0 20 "alpha sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawText 0 40 "alpha sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawText 0 60 "alpha sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawText 0 80 "alpha sansserif 10pt, bold italic" - - - translate 0 100 - setPen black - save - scale 0.9 0.9 - - setFont "sansserif" 10 normal - drawText 0 20 "scaled sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawText 0 40 "scaled sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawText 0 60 "scaled sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawText 0 80 "scaled sansserif 10pt, bold italic" - restore - - translate 0 100 - setPen black - save - translate 200 90 - rotate 185 - - setFont "sansserif" 10 normal - drawText 0 20 "scaled sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawText 0 40 "scaled sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawText 0 60 "scaled sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawText 0 80 "scaled sansserif 10pt, bold italic" - restore - - translate 0 100 - gradient_appendStop 0 red - gradient_appendStop 0.5 #00ff00 - gradient_appendStop 1 blue - gradient_setLinear 0 0 200 0 - setPen brush - - setFont "sansserif" 10 normal - drawText 0 0 "gradient sansserif 10pt, normal" - - setFont "sansserif" 12 normal - drawText 0 20 "gradient sansserif 12pt, normal" - - setFont "sansserif" 10 bold - drawText 0 40 "gradient sansserif 12pt, bold" - - setFont "sansserif" 10 bold italic - drawText 0 60 "gradient sansserif 10pt, bold italic" -restore -end_block - -translate 250 0 -drawText 25 520 "clipped to rectangle" -save - setPen #3f000000 - setBrush nobrush - drawRect 20 0 100 500 - setClipRect 20 0 100 500 - setPen black - repeat_block text_drawing -restore - -translate 150 0 -drawText 25 520 "clipped to path" -save - path_moveTo clip 20 0 - path_cubicTo clip 0 200 40 400 20 400 - path_lineTo clip 30 500 - path_lineTo clip 30 0 - path_lineTo clip 40 0 - path_lineTo clip 40 500 - path_lineTo clip 120 500 - path_lineTo clip 120 0 - path_lineTo clip 20 0 - setPen #3f000000 - setBrush nobrush - drawPath clip - setClipPath clip - setPen black - repeat_block text_drawing -restore \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/text_perspectives.qps b/tests/auto/lancelot/scripts/text_perspectives.qps deleted file mode 100644 index 4c74306265..0000000000 --- a/tests/auto/lancelot/scripts/text_perspectives.qps +++ /dev/null @@ -1,102 +0,0 @@ -# Version: 1 - - -setRenderHint Antialiasing - -setPen black - -translate 10 10 -# standard draw -begin_block text -setBrush gray -drawRect 0 0 300 300 - -setFont "times" 3 -drawText 10 10 "Hello World...." - -setFont "times" 4 -drawText 10 20 "Hello World...." - -setFont "times" 5 -drawText 10 30 "Hello World...." - -setFont "times" 6 -drawText 10 40 "Hello World...." - -setFont "times" 7 -drawText 10 50 "Hello World...." - -setFont "times" 8 -drawText 10 60 "Hello World...." - -setFont "times" 9 -drawText 10 70 "Hello World...." - -setFont "times" 10 -drawText 10 80 "Hello World...." - -setFont "times" 16 -drawText 10 100 "Hello World...." - -setFont "times" 17 -drawText 10 120 "Hello World...." - -setFont "times" 18 -drawText 10 140 "Hello World...." - -setFont "times" 20 -drawText 10 160 "Hello World...." - -setFont "times" 22 -drawText 10 180 "Hello World...." - -setFont "times" 24 -drawText 10 205 "Hello World...." - -setFont "times" 26 -drawText 10 230 "Hello World...." - -setFont "times" 32 -drawText 10 260 "Hello World...." -end_block text - -# Rotation w/o smooth xform -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 50 0 200 300 300 300 0 - repeat_block text -restore -restore - -translate 0 320 - -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 100 300 200 300 300 0 - repeat_block text -restore - -save -translate 350 0 -save - setRenderHint SmoothPixmapTransform on - mapQuadToQuad 0 0 0 300 300 300 300 0 0 0 0 300 300 250 300 50 - repeat_block text -restore -restore - - -resetMatrix -setPen black -translate 125 20 -drawText 0 0 "No transform" -translate 350 0 -drawText 0 0 "Left Tilted" -resetMatrix -translate 125 350 -drawText 0 0 "Bottom Tilted" -translate 350 0 -drawText 0 0 "Right Tilted" -translate 120 0 \ No newline at end of file diff --git a/tests/auto/lancelot/scripts/tiled_pixmap.qps b/tests/auto/lancelot/scripts/tiled_pixmap.qps deleted file mode 100644 index 9cb5e0dd1f..0000000000 --- a/tests/auto/lancelot/scripts/tiled_pixmap.qps +++ /dev/null @@ -1,84 +0,0 @@ -# Version: 1 -# CheckVsReference: 5% (0 0 639 638) - - -translate 0 10 -setRenderHint Antialiasing - -pixmap_load dome_argb32 the_pixmap - -begin_block draw_stuff -save - - # Standard draw - drawTiledPixmap the_pixmap 0 0 150 100 0 0 - - # Standard draw with offset - translate 160 0 - drawTiledPixmap the_pixmap 0 0 150 100 25 25 - - # xformed - translate 160 0 - save - translate 10 -10 - rotate 10 - setRenderHint SmoothPixmapTransform false - drawTiledPixmap the_pixmap 0 0 150 100 25 25 - restore - - # xformed with smooth xform - translate 160 0 - save - translate 10 -10 - rotate 10 - setRenderHint SmoothPixmapTransform - drawTiledPixmap the_pixmap 0 0 150 100 25 25 - restore -restore -end_block - -translate 0 120 -pixmap_load dome_rgb32 the_pixmap -repeat_block draw_stuff - - -translate 0 120 -pixmap_load dome_indexed the_pixmap -repeat_block draw_stuff - - -translate 0 120 -pixmap_load dome_indexed_mask the_pixmap -repeat_block draw_stuff - - -translate 0 120 -pixmap_load dome_mono the_pixmap -repeat_block draw_stuff - - -################################################################################ -# Some helpful text... -# - -resetMatrix -translate 650 80 -drawText 0 0 "32 bit w/alpha" -translate 0 120 -drawText 0 0 "32 bit w/o alpha" -translate 0 120 -drawText 0 0 "8 bit indexed" -translate 0 120 -drawText 0 0 "8 bit indexed w/mask" -translate 0 120 -drawText 0 0 "1 bit" - -resetMatrix -translate 10 630 -drawText 0 0 "normal" -translate 160 0 -drawText 0 0 "offset" -translate 160 0 -drawText 0 0 "xformed" -translate 160 0 -drawText 0 0 "smooth xformed" diff --git a/tests/auto/lancelot/tst_lancelot.cpp b/tests/auto/lancelot/tst_lancelot.cpp deleted file mode 100644 index 07ed74ec6a..0000000000 --- a/tests/auto/lancelot/tst_lancelot.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/**************************************************************************** -** -** 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 -#include "paintcommands.h" -#include -#include -#include -#include - -#ifndef QT_NO_OPENGL -#include -#endif - -#ifndef SRCDIR -#define SRCDIR "." -#endif - -class tst_Lancelot : public QObject -{ -Q_OBJECT - -public: - tst_Lancelot(); - - static bool simfail; - static PlatformInfo clientInfo; - -private: - enum GraphicsEngine { - Raster = 0, - OpenGL = 1 - }; - - bool setupTestSuite(const QStringList& blacklist); - void runTestSuite(GraphicsEngine engine, QImage::Format format); - ImageItem render(const ImageItem &item, GraphicsEngine engine, QImage::Format format); - void paint(QPaintDevice *device, const QStringList &script, const QString &filePath); - - BaselineProtocol proto; - ImageItemList baseList; - QHash scripts; - bool dryRunMode; - QString scriptsDir; - -private slots: - void initTestCase(); - void cleanupTestCase() {} - - void testRasterARGB32PM_data(); - void testRasterARGB32PM(); - void testRasterRGB32_data(); - void testRasterRGB32(); - void testRasterRGB16_data(); - void testRasterRGB16(); - -#ifndef QT_NO_OPENGL - void testOpenGL_data(); - void testOpenGL(); -#endif -}; - -bool tst_Lancelot::simfail = false; -PlatformInfo tst_Lancelot::clientInfo; - -tst_Lancelot::tst_Lancelot() -{ -} - -void tst_Lancelot::initTestCase() -{ - // Check and setup the environment. We treat failures because of test environment - // (e.g. script files not found) as just warnings, and not QFAILs, to avoid false negatives - // caused by environment or server instability - - if (!proto.connect(QLatin1String("tst_Lancelot"), &dryRunMode, clientInfo)) - QSKIP(qPrintable(proto.errorMessage()), SkipAll); - -#if defined(USE_RUNTIME_DIR) - scriptsDir = QCoreApplication::applicationDirPath() + "/scripts/"; -#else - scriptsDir = SRCDIR "/scripts/"; -#endif - QDir qpsDir(scriptsDir); - QStringList files = qpsDir.entryList(QStringList() << QLatin1String("*.qps"), QDir::Files | QDir::Readable); - if (files.isEmpty()) { - QWARN("No qps script files found in " + qpsDir.path().toLatin1()); - QSKIP("Aborted due to errors.", SkipAll); - } - - baseList.resize(files.count()); - ImageItemList::iterator it = baseList.begin(); - foreach(const QString& fileName, files) { - QFile file(scriptsDir + fileName); - file.open(QFile::ReadOnly); - QByteArray cont = file.readAll(); - scripts.insert(fileName, QString::fromLatin1(cont).split(QLatin1Char('\n'), QString::SkipEmptyParts)); - it->itemName = fileName; - it->itemChecksum = qChecksum(cont.constData(), cont.size()); - it++; - } -} - - -void tst_Lancelot::testRasterARGB32PM_data() -{ - QStringList localBlacklist; - if (!setupTestSuite(localBlacklist)) - QSKIP("Communication with baseline image server failed.", SkipAll); -} - - -void tst_Lancelot::testRasterARGB32PM() -{ - runTestSuite(Raster, QImage::Format_ARGB32_Premultiplied); -} - - -void tst_Lancelot::testRasterRGB32_data() -{ - QStringList localBlacklist; - if (!setupTestSuite(localBlacklist)) - QSKIP("Communication with baseline image server failed.", SkipAll); -} - - -void tst_Lancelot::testRasterRGB32() -{ - runTestSuite(Raster, QImage::Format_RGB32); -} - - -void tst_Lancelot::testRasterRGB16_data() -{ - QStringList localBlacklist; - if (!setupTestSuite(localBlacklist)) - QSKIP("Communication with baseline image server failed.", SkipAll); -} - - -void tst_Lancelot::testRasterRGB16() -{ - runTestSuite(Raster, QImage::Format_RGB16); -} - - -#ifndef QT_NO_OPENGL -void tst_Lancelot::testOpenGL_data() -{ - QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps"); - if (!setupTestSuite(localBlacklist)) - QSKIP("Communication with baseline image server failed.", SkipAll); -} - - -void tst_Lancelot::testOpenGL() -{ - bool ok = false; - QGLWidget glWidget; - if (glWidget.isValid() && glWidget.format().directRendering() - && ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) - || (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)) - && QGLFramebufferObject::hasOpenGLFramebufferObjects()) - { - glWidget.makeCurrent(); - if (!QByteArray((const char *)glGetString(GL_VERSION)).contains("Mesa")) - ok = true; - } - if (ok) - runTestSuite(OpenGL, QImage::Format_RGB32); - else - QSKIP("System under test does not meet preconditions for GL testing. Skipping.", SkipAll); -} -#endif - - -bool tst_Lancelot::setupTestSuite(const QStringList& blacklist) -{ - QTest::addColumn("baseline"); - - ImageItemList itemList(baseList); - if (!proto.requestBaselineChecksums(QTest::currentTestFunction(), &itemList)) { - QWARN(qPrintable(proto.errorMessage())); - return false; - } - - foreach(const ImageItem& item, itemList) { - if (!blacklist.contains(item.itemName)) - QTest::newRow(item.itemName.toLatin1()) << item; - } - return true; -} - - -void tst_Lancelot::runTestSuite(GraphicsEngine engine, QImage::Format format) -{ - QFETCH(ImageItem, baseline); - - if (baseline.status == ImageItem::IgnoreItem) - QSKIP("Blacklisted by baseline server.", SkipSingle); - - ImageItem rendered = render(baseline, engine, format); - static int consecutiveErrs = 0; - if (rendered.image.isNull()) { // Assume an error in the test environment, not Qt - QWARN("Error: Failed to render image."); - if (++consecutiveErrs < 3) { - QSKIP("Aborted due to errors.", SkipSingle); - } else { - consecutiveErrs = 0; - QSKIP("Too many errors, skipping rest of testfunction.", SkipAll); - } - } else { - consecutiveErrs = 0; - } - - - if (baseline.status == ImageItem::BaselineNotFound) { - if (!proto.submitNewBaseline(rendered, 0)) - QWARN("Failed to submit new baseline: " + proto.errorMessage().toLatin1()); - QSKIP("Baseline not found; new baseline created.", SkipSingle); - } - - if (!baseline.imageChecksums.contains(rendered.imageChecksums.at(0))) { - QByteArray serverMsg; - if (!proto.submitMismatch(rendered, &serverMsg)) - serverMsg = "Failed to submit mismatching image to server."; - if (dryRunMode) - qDebug() << "Dryrun mode, ignoring detected mismatch." << serverMsg; - else - QFAIL("Rendered image differs from baseline. Report:\n " + serverMsg); - } -} - - -ImageItem tst_Lancelot::render(const ImageItem &item, GraphicsEngine engine, QImage::Format format) -{ - ImageItem res = item; - res.imageChecksums.clear(); - res.image = QImage(); - QString filePath = scriptsDir + item.itemName; - QStringList script = scripts.value(item.itemName); - - if (engine == Raster) { - QImage img(800, 800, format); - paint(&img, script, QFileInfo(filePath).absoluteFilePath()); // eh yuck (filePath stuff) - res.image = img; - res.imageChecksums.append(ImageItem::computeChecksum(img)); -#ifndef QT_NO_OPENGL - } else if (engine == OpenGL) { - QGLWidget glWidget; - if (glWidget.isValid()) { - glWidget.makeCurrent(); - QGLFramebufferObjectFormat fboFormat; - fboFormat.setSamples(16); - fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - QGLFramebufferObject fbo(800, 800, fboFormat); - paint(&fbo, script, QFileInfo(filePath).absoluteFilePath()); // eh yuck (filePath stuff) - res.image = fbo.toImage().convertToFormat(format); - res.imageChecksums.append(ImageItem::computeChecksum(res.image)); - } -#endif - } - - return res; -} - -void tst_Lancelot::paint(QPaintDevice *device, const QStringList &script, const QString &filePath) -{ - QPainter p(device); - PaintCommands pcmd(script, 800, 800); - //pcmd.setShouldDrawText(false); - pcmd.setType(ImageType); - pcmd.setPainter(&p); - pcmd.setFilePath(filePath); - pcmd.runCommands(); - p.end(); - - if (simfail) { - QPainter p2(device); - p2.setPen(QPen(QBrush(Qt::cyan), 3, Qt::DashLine)); - p2.drawLine(200, 200, 600, 600); - p2.drawLine(600, 200, 200, 600); - simfail = false; - } -} - -#define main rmain -QTEST_MAIN(tst_Lancelot) -#undef main - -int main(int argc, char *argv[]) -{ - tst_Lancelot::clientInfo = PlatformInfo::localHostInfo(); - - char *fargv[20]; - int fargc = 0; - for (int i = 0; i < qMin(argc, 19); i++) { - if (!qstrcmp(argv[i], "-simfail")) { - tst_Lancelot::simfail = true; - } else if (!qstrcmp(argv[i], "-compareto") && i < argc-1) { - QString arg = QString::fromLocal8Bit(argv[++i]); - int split = arg.indexOf(QLC('=')); - if (split < 0) - continue; - QString key = arg.left(split).trimmed(); - QString value = arg.mid(split+1).trimmed(); - if (key.isEmpty() || value.isEmpty()) - continue; - tst_Lancelot::clientInfo.addOverride(key, value); - } else { - fargv[fargc++] = argv[i]; - } - } - fargv[fargc] = 0; - return rmain(fargc, fargv); -} - -#include "tst_lancelot.moc" diff --git a/tests/auto/languagechange/.gitignore b/tests/auto/languagechange/.gitignore deleted file mode 100644 index 1b14ad1503..0000000000 --- a/tests/auto/languagechange/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_languagechange diff --git a/tests/auto/languagechange/languagechange.pro b/tests/auto/languagechange/languagechange.pro deleted file mode 100644 index c51c42ebe1..0000000000 --- a/tests/auto/languagechange/languagechange.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets core-private -SOURCES += tst_languagechange.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/languagechange/tst_languagechange.cpp b/tests/auto/languagechange/tst_languagechange.cpp deleted file mode 100644 index 5e97fd709e..0000000000 --- a/tests/auto/languagechange/tst_languagechange.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include - - -//TESTED_CLASS= -//TESTED_FILES= - -class tst_languageChange : public QObject -{ - Q_OBJECT -public: - tst_languageChange(); - -public slots: - void initTestCase(); - void cleanupTestCase(); -private slots: - void retranslatability_data(); - void retranslatability(); - -}; - - -tst_languageChange::tst_languageChange() - -{ -} - -void tst_languageChange::initTestCase() -{ -} - -void tst_languageChange::cleanupTestCase() -{ -} -/** - * Records all calls to translate() - */ -class TransformTranslator : public QTranslator -{ - Q_OBJECT -public: - TransformTranslator() : QTranslator() {} - TransformTranslator(QObject *parent) : QTranslator(parent) {} - virtual QString translate(const char *context, const char *sourceText, const char *comment = 0) const - { - QByteArray total(context); - total.append("::"); - total.append(sourceText); - if (comment) { - total.append("::"); - total.append(comment); - } - m_translations.insert(total); - QString res; - for (int i = 0; i < int(qstrlen(sourceText)); ++i) { - QChar ch = QLatin1Char(sourceText[i]); - if (ch.isLower()) { - res.append(ch.toUpper()); - } else if (ch.isUpper()) { - res.append(ch.toLower()); - } else { - res.append(ch); - } - } - return res; - } - - virtual bool isEmpty() const { return false; } - -public slots: - void install() { - QCoreApplication::installTranslator(this); - QTest::qWait(2500); - QApplication::closeAllWindows(); - } -public: - mutable QSet m_translations; -}; - -enum DialogType { - InputDialog = 1, - ColorDialog, - FileDialog -}; - -typedef QSet TranslationSet; -Q_DECLARE_METATYPE(TranslationSet) - -void tst_languageChange::retranslatability_data() -{ - QTest::addColumn("dialogType"); - QTest::addColumn("expected"); - - //next we fill it with data - QTest::newRow( "QInputDialog" ) - << int(InputDialog) << (QSet() - << "QDialogButtonBox::Cancel"); - - QTest::newRow( "QColorDialog" ) - << int(ColorDialog) << (QSet() - << "QDialogButtonBox::Cancel" - << "QColorDialog::&Sat:" - << "QColorDialog::&Add to Custom Colors" - << "QColorDialog::&Green:" - << "QColorDialog::&Red:" - << "QColorDialog::Bl&ue:" - << "QColorDialog::A&lpha channel:" - << "QColorDialog::&Basic colors" - << "QColorDialog::&Custom colors" - << "QColorDialog::&Val:" - << "QColorDialog::Hu&e:"); - - QTest::newRow( "QFileDialog" ) - << int(FileDialog) << (QSet() - << "QFileDialog::All Files (*)" - << "QFileDialog::Back" - << "QFileDialog::Create New Folder" - << "QFileDialog::Detail View" -#ifndef Q_OS_MAC - << "QFileDialog::File" -#endif - << "QFileDialog::Files of type:" - << "QFileDialog::Forward" - << "QFileDialog::List View" - << "QFileDialog::Look in:" - << "QFileDialog::Open" - << "QFileDialog::Parent Directory" - << "QFileDialog::Show " - << "QFileDialog::Show &hidden files" - << "QFileDialog::&Delete" - << "QFileDialog::&New Folder" - << "QFileDialog::&Rename" - << "QFileSystemModel::Date Modified" -#ifdef Q_OS_WIN - << "QFileSystemModel::My Computer" -#else - << "QFileSystemModel::Computer" -#endif - << "QFileSystemModel::Size" -#ifdef Q_OS_MAC - << "QFileSystemModel::Kind::Match OS X Finder" -#else - << "QFileSystemModel::Type::All other platforms" -#endif -// << "QFileSystemModel::%1 KB" - << "QDialogButtonBox::Cancel" - << "QDialogButtonBox::Open" - << "QFileDialog::File &name:"); -} - -void tst_languageChange::retranslatability() -{ - QFETCH( int, dialogType); - QFETCH( TranslationSet, expected); - - // This will always be queried for when a language changes - expected.insert("QApplication::QT_LAYOUT_DIRECTION::Translate this string to the string 'LTR' in left-to-right " - "languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to " - "get proper widget layout."); - TransformTranslator translator; - QTimer::singleShot(500, &translator, SLOT(install())); - switch (dialogType) { - case InputDialog: - (void)QInputDialog::getInteger(0, QLatin1String("title"), QLatin1String("label")); - break; - - case ColorDialog: -#ifdef Q_WS_MAC - QSKIP("The native color dialog is used on Mac OS", SkipSingle); -#else - (void)QColorDialog::getColor(); -#endif - break; - case FileDialog: { -#ifdef Q_WS_MAC - QSKIP("The native file dialog is used on Mac OS", SkipSingle); -#endif - QFileDialog dlg; - dlg.setOption(QFileDialog::DontUseNativeDialog); - QString tmpParentDir = QDir::tempPath() + "/languagechangetestdir"; - QString tmpDir = tmpParentDir + "/finaldir"; - QString fooName = tmpParentDir + "/foo"; - QDir dir; - QCOMPARE(dir.mkpath(tmpDir), true); - QCOMPARE(QFile::copy(QApplication::applicationFilePath(), fooName), true); - - dlg.setDirectory(tmpParentDir); -#ifdef Q_OS_WINCE - dlg.setDirectory("\\Windows"); -#endif - dlg.setFileMode(QFileDialog::ExistingFiles); - dlg.setViewMode(QFileDialog::Detail); - dlg.exec(); - QTest::qWait(3000); - QCOMPARE(QFile::remove(fooName), true); - QCOMPARE(dir.rmdir(tmpDir), true); - QCOMPARE(dir.rmdir(tmpParentDir), true); - break; } - } -#if 0 - QList list = translator.m_translations.toList(); - qSort(list); - qDebug() << list; -#endif - // In case we use a Color dialog, we do not want to test for - // strings non existing in the dialog and which do not get - // translated. - if ((dialogType == ColorDialog) && -#ifndef Q_OS_WINCE - (qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350) -#else - true // On Qt/WinCE we always use compact mode -#endif - ) { - expected.remove("QColorDialog::&Basic colors"); - expected.remove("QColorDialog::&Custom colors"); - expected.remove("QColorDialog::&Define Custom Colors >>"); - expected.remove("QColorDialog::&Add to Custom Colors"); - } - - // see if all of our *expected* translations was translated. - // (There might be more, but thats not that bad) - QSet commonTranslations = expected; - commonTranslations.intersect(translator.m_translations); - if (!expected.subtract(commonTranslations).isEmpty()) { - qDebug() << "Missing:" << expected; - if (!translator.m_translations.subtract(commonTranslations).isEmpty()) - qDebug() << "Unexpected:" << translator.m_translations; - } - - QVERIFY(expected.isEmpty()); -} - -QTEST_MAIN(tst_languageChange) -#include "tst_languagechange.moc" diff --git a/tests/auto/macgui/.gitignore b/tests/auto/macgui/.gitignore deleted file mode 100644 index 2b13357fac..0000000000 --- a/tests/auto/macgui/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_macgui diff --git a/tests/auto/macgui/guitest.cpp b/tests/auto/macgui/guitest.cpp deleted file mode 100644 index 521134f6b8..0000000000 --- a/tests/auto/macgui/guitest.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/**************************************************************************** -** -** 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 "guitest.h" -#include -#include -#include -#include -#include - -#ifdef Q_OS_MAC -# include -#endif - - -/* - Not really a test, just prints interface info. -*/ -class PrintTest : public TestBase -{ -public: - bool operator()(InterfaceChildPair candidate) - { - qDebug() << ""; - qDebug() << "Name" << candidate.iface->text(QAccessible::Name, candidate.possibleChild); - qDebug() << "Pos" << candidate.iface->rect(candidate.possibleChild); - if (candidate.possibleChild == 0) - qDebug() << "Number of children" << candidate.iface->childCount(); - return false; - } -}; - -class NameTest : public TestBase -{ -public: - NameTest(const QString &text, QAccessible::Text textType) : text(text), textType(textType) {} - QString text; - QAccessible::Text textType; - - bool operator()(InterfaceChildPair candidate) - { - return (candidate.iface->text(textType, candidate.possibleChild) == text); - } -}; - -void WidgetNavigator::printAll(QWidget *widget) -{ - QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(widget); - deleteInDestructor(iface); - printAll(InterfaceChildPair(iface, 0)); -} - -void WidgetNavigator::printAll(InterfaceChildPair interface) -{ - PrintTest printTest; - recursiveSearch(&printTest, interface.iface, interface.possibleChild); -} - -InterfaceChildPair WidgetNavigator::find(QAccessible::Text textType, const QString &text, QWidget *start) -{ - QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(start); - deleteInDestructor(iface); - return find(textType, text, iface); -} - -InterfaceChildPair WidgetNavigator::find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start) -{ - NameTest nameTest(text, textType); - return recursiveSearch(&nameTest, start, 0); -} - -/* - Recursiveley navigates the accessible hiearchy looking for an interfafce that - passsed the Test (meaning it returns true). -*/ -InterfaceChildPair WidgetNavigator::recursiveSearch(TestBase *test, QAccessibleInterface *iface, int possibleChild) -{ - QStack todoInterfaces; - todoInterfaces.push(InterfaceChildPair(iface, possibleChild)); - - while (todoInterfaces.isEmpty() == false) { - InterfaceChildPair testInterface = todoInterfaces.pop(); - - if ((*test)(testInterface)) - return testInterface; - - if (testInterface.possibleChild != 0) - continue; - - const int numChildren = testInterface.iface->childCount(); - for (int i = 0; i < numChildren; ++i) { - QAccessibleInterface *childInterface = 0; - int newPossibleChild = testInterface.iface->navigate(QAccessible::Child, i + 1, &childInterface); - if (childInterface) { - todoInterfaces.push(InterfaceChildPair(childInterface, newPossibleChild)); - deleteInDestructor(childInterface); - } else if (newPossibleChild != -1) { - todoInterfaces.push(InterfaceChildPair(testInterface.iface, newPossibleChild)); - } - } - } - return InterfaceChildPair(); -} - -void WidgetNavigator::deleteInDestructor(QAccessibleInterface * interface) -{ - interfaces.insert(interface); -} - -QWidget *WidgetNavigator::getWidget(InterfaceChildPair interface) -{ - return qobject_cast(interface.iface->object()); -} - -WidgetNavigator::~WidgetNavigator() -{ - foreach(QAccessibleInterface *interface, interfaces) { - delete interface; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -namespace NativeEvents { -#ifdef Q_OS_MAC - void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse) - { - CGPoint position; - position.x = globalPos.x(); - position.y = globalPos.y(); - - const bool updateMousePosition = (updateMouse == UpdatePosition); - - // Mouse down. - CGPostMouseEvent(position, updateMousePosition, 3, - (buttons & Qt::LeftButton) ? true : false, - (buttons & Qt::MidButton/* Middlebutton! */) ? true : false, - (buttons & Qt::RightButton) ? true : false); - - // Mouse up. - CGPostMouseEvent(position, updateMousePosition, 3, false, false, false); - } -#else -# error Oops, NativeEvents::mouseClick() is not implemented on this platform. -#endif -}; - -/////////////////////////////////////////////////////////////////////////////// - -GuiTester::GuiTester() -{ - clearSequence(); -} - -GuiTester::~GuiTester() -{ - foreach(DelayedAction *action, actions) - delete action; -} - -bool checkPixel(QColor pixel, QColor expected) -{ - const int allowedDiff = 20; - - return !(qAbs(pixel.red() - expected.red()) > allowedDiff || - qAbs(pixel.green() - expected.green()) > allowedDiff || - qAbs(pixel.blue() - expected.blue()) > allowedDiff); -} - -/* - Tests that the pixels inside rect in image all have the given color. -*/ -bool GuiTester::isFilled(const QImage image, const QRect &rect, const QColor &color) -{ - for (int y = rect.top(); y <= rect.bottom(); ++y) - for (int x = rect.left(); x <= rect.right(); ++x) { - const QColor pixel = image.pixel(x, y); - if (checkPixel(pixel, color) == false) { -// qDebug()<< "Wrong pixel value at" << x << y << pixel.red() << pixel.green() << pixel.blue(); - return false; - } - } - return true; -} - - -/* - Tests that stuff is painted to the pixels inside rect. - This test fails if any lines in the given direction have pixels - of only one color. -*/ -bool GuiTester::isContent(const QImage image, const QRect &rect, Directions directions) -{ - if (directions & Horizontal) { - for (int y = rect.top(); y <= rect.bottom(); ++y) { - QColor currentColor = image.pixel(rect.left(), y); - bool fullRun = true; - for (int x = rect.left() + 1; x <= rect.right(); ++x) { - if (checkPixel(image.pixel(x, y), currentColor) == false) { - fullRun = false; - break; - } - } - if (fullRun) { -// qDebug() << "Single-color line at horizontal line " << y << currentColor; - return false; - } - } - return true; - } - - if (directions & Vertical) { - for (int x = rect.left(); x <= rect.right(); ++x) { - QRgb currentColor = image.pixel(x, rect.top()); - bool fullRun = true; - for (int y = rect.top() + 1; y <= rect.bottom(); ++y) { - if (checkPixel(image.pixel(x, y), currentColor) == false) { - fullRun = false; - break; - } - } - if (fullRun) { -// qDebug() << "Single-color line at vertical line" << x << currentColor; - return false; - } - } - return true; - } - return false; // shut the compiler up. -} - -void DelayedAction::run() -{ - if (next) - QTimer::singleShot(next->delay, next, SLOT(run())); -}; - -/* - Schedules a mouse click at an interface using a singleShot timer. - Only one click can be scheduled at a time. -*/ -ClickLaterAction::ClickLaterAction(InterfaceChildPair interface, Qt::MouseButtons buttons) -{ - this->useInterface = true; - this->interface = interface; - this->buttons = buttons; -} - -/* - Schedules a mouse click at a widget using a singleShot timer. - Only one click can be scheduled at a time. -*/ -ClickLaterAction::ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons) -{ - this->useInterface = false; - this->widget = widget; - this->buttons = buttons; -} - -void ClickLaterAction::run() -{ - if (useInterface) { - const QPoint globalCenter = interface.iface->rect(interface.possibleChild).center(); - NativeEvents::mouseClick(globalCenter, buttons); - } else { // use widget - const QSize halfSize = widget->size() / 2; - const QPoint globalCenter = widget->mapToGlobal(QPoint(halfSize.width(), halfSize.height())); - NativeEvents::mouseClick(globalCenter, buttons); - } - DelayedAction::run(); -} - -void GuiTester::clickLater(InterfaceChildPair interface, Qt::MouseButtons buttons, int delay) -{ - clearSequence(); - addToSequence(new ClickLaterAction(interface, buttons), delay); - runSequence(); -} - -void GuiTester::clickLater(QWidget *widget, Qt::MouseButtons buttons, int delay) -{ - clearSequence(); - addToSequence(new ClickLaterAction(widget, buttons), delay); - runSequence(); -} - -void GuiTester::clearSequence() -{ - startAction = new DelayedAction(); - actions.insert(startAction); - lastAction = startAction; -} - -void GuiTester::addToSequence(DelayedAction *action, int delay) -{ - actions.insert(action); - action->delay = delay; - lastAction->next = action; - lastAction = action; -} - -void GuiTester::runSequence() -{ - QTimer::singleShot(0, startAction, SLOT(run())); -} - -void GuiTester::exitLoopSlot() -{ - QTestEventLoop::instance().exitLoop(); -} - diff --git a/tests/auto/macgui/guitest.h b/tests/auto/macgui/guitest.h deleted file mode 100644 index 432021c54a..0000000000 --- a/tests/auto/macgui/guitest.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** 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 GUITEST_H -#define GUITEST_H - -#include -#include -#include -#include - -QT_USE_NAMESPACE - -/* - GuiTest provides tools for: - - navigating the Qt Widget hiearchy using the accessibilty APIs. - - Simulating platform mouse and keybord events. -*/ - -/* - InterfaceChildPair specifies an accessibilty interface item. -*/ -class InterfaceChildPair { -public: - InterfaceChildPair() : iface(0), possibleChild(0) {} - InterfaceChildPair(QAccessibleInterface *iface, int possibleChild) - :iface(iface), possibleChild(possibleChild) - { } - - QAccessibleInterface *iface; - int possibleChild; -}; - -class TestBase { -public: - virtual bool operator()(InterfaceChildPair candidate) = 0; - virtual ~TestBase() {} -}; - -/* - WidgetNavigator navigates a Qt GUI hierarchy using the QAccessibility APIs. -*/ -class WidgetNavigator { -public: - WidgetNavigator() {}; - ~WidgetNavigator(); - - void printAll(QWidget *widget); - void printAll(InterfaceChildPair interface); - - InterfaceChildPair find(QAccessible::Text textType, const QString &text, QWidget *start); - InterfaceChildPair find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start); - - InterfaceChildPair recursiveSearch(TestBase *test, QAccessibleInterface *iface, int possibleChild); - - void deleteInDestructor(QAccessibleInterface * interface); - static QWidget *getWidget(InterfaceChildPair interface); -private: - QSet interfaces; -}; - -/* - NativeEvents contains platform-specific code for simulating mouse and keybord events. - (Implemented so far: mouseClick on Mac) -*/ -namespace NativeEvents { - enum MousePosition { UpdatePosition, DontUpdatePosition }; - /* - Simulates a mouse click with button at globalPos. - */ - void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse = DontUpdatePosition); -}; - -class ColorWidget : public QWidget -{ -public: - ColorWidget(QWidget *parent = 0, QColor color = QColor(Qt::red)) - : QWidget(parent), color(color) {} - - QColor color; - -protected: - void paintEvent(QPaintEvent *) - { - QPainter p(this); - p.fillRect(this->rect(), color); - } -}; - -class DelayedAction : public QObject -{ -Q_OBJECT -public: - DelayedAction() : delay(0), next(0) {} - virtual ~DelayedAction(){} -public slots: - virtual void run(); -public: - int delay; - DelayedAction *next; -}; - -class ClickLaterAction : public DelayedAction -{ -Q_OBJECT -public: - ClickLaterAction(InterfaceChildPair interface, Qt::MouseButtons buttons = Qt::LeftButton); - ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons = Qt::LeftButton); -protected slots: - void run(); -private: - bool useInterface; - InterfaceChildPair interface; - QWidget *widget; - Qt::MouseButtons buttons; -}; - -/* - -*/ -class GuiTester : public QObject -{ -Q_OBJECT -public: - GuiTester(); - ~GuiTester(); - enum Direction {Horizontal = 1, Vertical = 2, HorizontalAndVertical = 3}; - Q_DECLARE_FLAGS(Directions, Direction) - bool isFilled(const QImage image, const QRect &rect, const QColor &color); - bool isContent(const QImage image, const QRect &rect, Directions directions = HorizontalAndVertical); -protected slots: - void exitLoopSlot(); -protected: - void clickLater(InterfaceChildPair interface, Qt::MouseButtons buttons = Qt::LeftButton, int delay = 300); - void clickLater(QWidget *widget, Qt::MouseButtons buttons = Qt::LeftButton, int delay = 300); - - void clearSequence(); - void addToSequence(DelayedAction *action, int delay = 0); - void runSequence(); - WidgetNavigator wn; -private: - QSet actions; - DelayedAction *startAction; - DelayedAction *lastAction; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(GuiTester::Directions) - -#endif diff --git a/tests/auto/macgui/macgui.pro b/tests/auto/macgui/macgui.pro deleted file mode 100644 index 3fbe74f7c8..0000000000 --- a/tests/auto/macgui/macgui.pro +++ /dev/null @@ -1,14 +0,0 @@ -load(qttest_p4) -TEMPLATE = app -DEPENDPATH += . -INCLUDEPATH += . - -# Input -SOURCES += tst_macgui.cpp guitest.cpp -HEADERS += guitest.h - -QT = core-private gui-private widgets - -requires(mac) - -CONFIG+=insignificant_test # QTBUG-20984, fails unstably diff --git a/tests/auto/macgui/tst_macgui.cpp b/tests/auto/macgui/tst_macgui.cpp deleted file mode 100644 index 1552db21ab..0000000000 --- a/tests/auto/macgui/tst_macgui.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include - -#include - -class tst_MacGui : public GuiTester -{ -Q_OBJECT -private slots: - void scrollbarPainting(); - - void dummy(); - void splashScreenModality(); - void nonModalOrder(); - - void spinBoxArrowButtons(); -}; - - -QPixmap grabWindowContents(QWidget * widget) -{ - return QPixmap::grabWindow(widget->winId()); -} - -/* - Test that vertical and horizontal mac-style scrollbars paint their - entire area. -*/ -void tst_MacGui::scrollbarPainting() -{ - ColorWidget colorWidget; - colorWidget.resize(400, 400); - - QSize scrollBarSize; - - QScrollBar verticalScrollbar(&colorWidget); - verticalScrollbar.move(10, 10); - scrollBarSize = verticalScrollbar.sizeHint(); - scrollBarSize.setHeight(200); - verticalScrollbar.resize(scrollBarSize); - - QScrollBar horizontalScrollbar(&colorWidget); - horizontalScrollbar.move(30, 10); - horizontalScrollbar.setOrientation(Qt::Horizontal); - scrollBarSize = horizontalScrollbar.sizeHint(); - scrollBarSize.setWidth(200); - horizontalScrollbar.resize(scrollBarSize); - - colorWidget.show(); - colorWidget.raise(); - QTest::qWait(100); - - QPixmap pixmap = grabWindowContents(&colorWidget); - - QVERIFY(isContent(pixmap.toImage(), verticalScrollbar.geometry(), GuiTester::Horizontal)); - QVERIFY(isContent(pixmap.toImage(), horizontalScrollbar.geometry(), GuiTester::Vertical)); -} - -// When running the auto-tests on scruffy, the first enter-the-event-loop-and-wait-for-a-click -// test that runs always times out, so we have this dummy test. -void tst_MacGui::dummy() -{ - QPixmap pix(100, 100); - QSplashScreen splash(pix); - splash.show(); - - QMessageBox *box = new QMessageBox(); - box->setText("accessible?"); - box->show(); - - // Find the "OK" button and schedule a press. - InterfaceChildPair interface = wn.find(QAccessible::Name, "OK", box); - QVERIFY(interface.iface); - const int delay = 1000; - clickLater(interface, Qt::LeftButton, delay); - - // Show dialog and and enter event loop. - connect(wn.getWidget(interface), SIGNAL(clicked()), SLOT(exitLoopSlot())); - const int timeout = 4; - QTestEventLoop::instance().enterLoop(timeout); -} - -/* - Test that a message box pops up in front of a QSplashScreen. -*/ -void tst_MacGui::splashScreenModality() -{ - QPixmap pix(300, 300); - QSplashScreen splash(pix); - splash.show(); - - QMessageBox box; - //box.setWindowFlags(box.windowFlags() | Qt::WindowStaysOnTopHint); - box.setText("accessible?"); - box.show(); - - // Find the "OK" button and schedule a press. - InterfaceChildPair interface = wn.find(QAccessible::Name, "OK", &box); - QVERIFY(interface.iface); - const int delay = 1000; - clickLater(interface, Qt::LeftButton, delay); - - // Show dialog and and enter event loop. - connect(wn.getWidget(interface), SIGNAL(clicked()), SLOT(exitLoopSlot())); - const int timeout = 4; - QTestEventLoop::instance().enterLoop(timeout); - QVERIFY(QTestEventLoop::instance().timeout() == false); -} - -class PrimaryWindowDialog : public QDialog -{ -Q_OBJECT -public: - PrimaryWindowDialog(); - QWidget *secondaryWindow; - QWidget *frontWidget; -public slots: - void showSecondaryWindow(); - void test(); -}; - -PrimaryWindowDialog::PrimaryWindowDialog() : QDialog(0) -{ - frontWidget = 0; - secondaryWindow = new ColorWidget(this); - secondaryWindow->setWindowFlags(Qt::Window); - secondaryWindow->resize(400, 400); - secondaryWindow->move(100, 100); - QTimer::singleShot(1000, this, SLOT(showSecondaryWindow())); - QTimer::singleShot(2000, this, SLOT(test())); - QTimer::singleShot(3000, this, SLOT(close())); -} - -void PrimaryWindowDialog::showSecondaryWindow() -{ - secondaryWindow->show(); -} - -void PrimaryWindowDialog::test() -{ - frontWidget = QApplication::widgetAt(secondaryWindow->mapToGlobal(QPoint(100, 100))); -} - -/* - Test that a non-modal child window of a modal dialog is shown in front - of the dialog even if the dialog becomes modal after the child window - is created. -*/ -void tst_MacGui::nonModalOrder() -{ - clearSequence(); - PrimaryWindowDialog primary; - primary.resize(400, 400); - primary.move(100, 100); - primary.exec(); - QCOMPARE(primary.frontWidget, primary.secondaryWindow); -} - -/* - Test that the QSpinBox buttons are correctly positioned with the Mac style. -*/ -void tst_MacGui::spinBoxArrowButtons() -{ - ColorWidget colorWidget; - colorWidget.resize(200, 200); - QSpinBox spinBox(&colorWidget); - QSpinBox spinBox2(&colorWidget); - spinBox2.move(0, 100); - colorWidget.show(); - QTest::qWait(100); - - // Grab an unfocused spin box. - const QImage noFocus = grabWindowContents(&colorWidget).toImage(); - - // Set focus by clicking the less button. - InterfaceChildPair lessInterface = wn.find(QAccessible::Name, "Less", &spinBox); - QVERIFY(lessInterface.iface); - const int delay = 500; - clickLater(lessInterface, Qt::LeftButton, delay); - const int timeout = 1; - QTestEventLoop::instance().enterLoop(timeout); - - // Grab a focused spin box. - const QImage focus = grabWindowContents(&colorWidget).toImage(); - - // Compare the arrow area of the less button to see if it moved. - const QRect lessRect = lessInterface.iface->rect(lessInterface.possibleChild); - const QRect lessLocalRect(colorWidget.mapFromGlobal(lessRect.topLeft()), colorWidget.mapFromGlobal(lessRect.bottomRight())); - const QRect compareRect = lessLocalRect.adjusted(5, 3, -5, -7); - QVERIFY(noFocus.copy(compareRect) == focus.copy(compareRect)); -} - -QTEST_MAIN(tst_MacGui) -#include "tst_macgui.moc" - diff --git a/tests/auto/macnativeevents/expectedeventlist.cpp b/tests/auto/macnativeevents/expectedeventlist.cpp deleted file mode 100644 index d603f82f27..0000000000 --- a/tests/auto/macnativeevents/expectedeventlist.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/**************************************************************************** -** -** 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 "expectedeventlist.h" -#include -#include -#include -#include - -ExpectedEventList::ExpectedEventList(QObject *target) - : QObject(target), eventCount(0) -{ - target->installEventFilter(this); - debug = qgetenv("NATIVEDEBUG").toInt(); - if (debug > 0) - qDebug() << "Debug level sat to:" << debug; -} - -ExpectedEventList::~ExpectedEventList() -{ - qDeleteAll(eventList); -} - -void ExpectedEventList::append(QEvent *e) -{ - eventList.append(e); - ++eventCount; -} - -void ExpectedEventList::timerEvent(QTimerEvent *) -{ - timer.stop(); - QAbstractEventDispatcher::instance()->interrupt(); -} - -bool ExpectedEventList::waitForAllEvents(int maxEventWaitTime) -{ - if (eventList.isEmpty()) - return true; - - int eventCount = eventList.size(); - timer.start(maxEventWaitTime, this); - - while (timer.isActive()) { - QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); - if (eventList.isEmpty()) - return true; - - if (eventCount < eventList.size()){ - eventCount = eventList.size(); - timer.start(maxEventWaitTime, this); - } - } - - int eventListNr = eventCount - eventList.size() + 1; - qWarning() << "Stopped waiting for expected event nr" << eventListNr; - return false; -} - -void ExpectedEventList::compareMouseEvents(QEvent *received, QEvent *expected) -{ - QMouseEvent *e1 = static_cast(received); - QMouseEvent *e2 = static_cast(expected); - - // Do a manual check first to be able to write more sensible - // debug output if we know we're going to fail: - if (e1->pos() == e2->pos() - && (e1->globalPos() == e2->globalPos()) - && (e1->button() == e2->button()) - && (e1->buttons() == e2->buttons()) - && (e1->modifiers() == e2->modifiers())) { - if (debug > 0) - qDebug() << " Received (OK):" << e1 << e1->globalPos(); - return; // equal - } - - // INVARIANT: The two events are not equal. So we fail. Depending - // on whether debug mode is no or not, we let QTest fail. Otherwise - // we let the test continue for debugging puposes. - int eventListNr = eventCount - eventList.size(); - if (debug == 0) { - qWarning() << "Expected event" << eventListNr << "differs from received event:"; - QCOMPARE(e1->pos(), e2->pos()); - QCOMPARE(e1->globalPos(), e2->globalPos()); - QCOMPARE(e1->button(), e2->button()); - QCOMPARE(e1->buttons(), e2->buttons()); - QCOMPARE(e1->modifiers(), e2->modifiers()); - } else { - qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:"; - qWarning() << "Received:" << e1 << e1->globalPos(); - qWarning() << "Expected:" << e2 << e2->globalPos(); - } -} - -void ExpectedEventList::compareKeyEvents(QEvent *received, QEvent *expected) -{ - QKeyEvent *e1 = static_cast(received); - QKeyEvent *e2 = static_cast(expected); - - // Do a manual check first to be able to write more sensible - // debug output if we know we're going to fail: - if (e1->key() == e2->key() - && (e1->modifiers() == e2->modifiers()) - && (e1->count() == e2->count()) - && (e1->isAutoRepeat() == e2->isAutoRepeat())) { - if (debug > 0) - qDebug() << " Received (OK):" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText); - return; // equal - } - - // INVARIANT: The two events are not equal. So we fail. Depending - // on whether debug mode is no or not, we let QTest fail. Otherwise - // we let the test continue for debugging puposes. - int eventListNr = eventCount - eventList.size(); - if (debug == 0) { - qWarning() << "Expected event" << eventListNr << "differs from received event:"; - QCOMPARE(e1->key(), e2->key()); - QCOMPARE(e1->modifiers(), e2->modifiers()); - QCOMPARE(e1->count(), e2->count()); - QCOMPARE(e1->isAutoRepeat(), e2->isAutoRepeat()); - } else { - qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:"; - qWarning() << "Received:" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText); - qWarning() << "Expected:" << e2 << QKeySequence(e2->key()).toString(QKeySequence::NativeText); - } -} - -bool ExpectedEventList::eventFilter(QObject *, QEvent *received) -{ - if (debug > 1) - qDebug() << received; - if (eventList.isEmpty()) - return false; - - bool eat = false; - QEvent *expected = eventList.first(); - if (expected->type() == received->type()) { - eventList.removeFirst(); - switch (received->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - case QEvent::MouseButtonDblClick: - case QEvent::NonClientAreaMouseButtonPress: - case QEvent::NonClientAreaMouseButtonRelease: - case QEvent::NonClientAreaMouseButtonDblClick: - case QEvent::NonClientAreaMouseMove: { - compareMouseEvents(received, expected); - eat = true; - break; - } - case QEvent::KeyPress: - case QEvent::KeyRelease: { - compareKeyEvents(received, expected); - eat = true; - break; - } - case QEvent::Resize: { - break; - } - case QEvent::WindowActivate: { - break; - } - case QEvent::WindowDeactivate: { - break; - } - default: - break; - } - if (eventList.isEmpty()) - QAbstractEventDispatcher::instance()->interrupt(); - } - - return eat; -} - diff --git a/tests/auto/macnativeevents/expectedeventlist.h b/tests/auto/macnativeevents/expectedeventlist.h deleted file mode 100644 index e3fef2d56d..0000000000 --- a/tests/auto/macnativeevents/expectedeventlist.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** 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 EVENTFILTER -#define EVENTFILTER - -#include -#include -#include -#include - -class ExpectedEventList : public QObject -{ - QList eventList; - QBasicTimer timer; - int debug; - int eventCount; - void timerEvent(QTimerEvent *); - -public: - ExpectedEventList(QObject *target); - ~ExpectedEventList(); - void append(QEvent *e); - bool waitForAllEvents(int timeoutPerEvent = 2000); - bool eventFilter(QObject *obj, QEvent *event); - -private: - void compareMouseEvents(QEvent *event1, QEvent *event2); - void compareKeyEvents(QEvent *event1, QEvent *event2); -}; - -#endif - diff --git a/tests/auto/macnativeevents/macnativeevents.pro b/tests/auto/macnativeevents/macnativeevents.pro deleted file mode 100644 index 0a0f6c8743..0000000000 --- a/tests/auto/macnativeevents/macnativeevents.pro +++ /dev/null @@ -1,16 +0,0 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Wed Nov 29 22:24:47 2006 -###################################################################### - -load(qttest_p4) -TEMPLATE = app -DEPENDPATH += . -INCLUDEPATH += . -LIBS += -framework Carbon -QT += widgets -HEADERS += qnativeevents.h nativeeventlist.h expectedeventlist.h -SOURCES += qnativeevents.cpp qnativeevents_mac.cpp -SOURCES += expectedeventlist.cpp nativeeventlist.cpp -SOURCES += tst_macnativeevents.cpp - -requires(mac) diff --git a/tests/auto/macnativeevents/nativeeventlist.cpp b/tests/auto/macnativeevents/nativeeventlist.cpp deleted file mode 100644 index 8c7f609d9f..0000000000 --- a/tests/auto/macnativeevents/nativeeventlist.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** 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 "nativeeventlist.h" - -NativeEventList::NativeEventList(int defaultWaitMs) - : playbackMultiplier(1.0) - , currIndex(-1) - , wait(false) - , defaultWaitMs(defaultWaitMs) -{ - debug = qgetenv("NATIVEDEBUG").toInt(); - QString multiplier = qgetenv("NATIVEDEBUGSPEED"); - if (!multiplier.isEmpty()) - setTimeMultiplier(multiplier.toFloat()); -} - -NativeEventList::~NativeEventList() -{ - for (int i=0; i 0) - qDebug() << "Sending:" << *e; - QNativeInput::sendNativeEvent(*e); - } - waitNextEvent(); -} - -void NativeEventList::waitNextEvent() -{ - if (++currIndex >= eventList.size()){ - emit done(); - stop(); - return; - } - - int interval = eventList.at(currIndex).first; - QTimer::singleShot(interval * playbackMultiplier, this, SLOT(sendNextEvent())); -} - -void NativeEventList::append(QNativeEvent *event) -{ - eventList.append(QPair(defaultWaitMs, event)); -} - -void NativeEventList::append(int waitMs, QNativeEvent *event) -{ - eventList.append(QPair(waitMs, event)); -} - -void NativeEventList::play(Playback playback) -{ - waitNextEvent(); - - wait = (playback == WaitUntilFinished); - while (wait) - QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); -} - -void NativeEventList::stop() -{ - wait = false; - QAbstractEventDispatcher::instance()->interrupt(); -} - -void NativeEventList::setTimeMultiplier(float multiplier) -{ - playbackMultiplier = multiplier; -} - diff --git a/tests/auto/macnativeevents/nativeeventlist.h b/tests/auto/macnativeevents/nativeeventlist.h deleted file mode 100644 index 6bebca1613..0000000000 --- a/tests/auto/macnativeevents/nativeeventlist.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** 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 Q_NATIVE_PLAYBACK -#define Q_NATIVE_PLAYBACK - -#include -#include "qnativeevents.h" - -class NativeEventList : public QObject -{ - Q_OBJECT; - - public: - enum Playback {ReturnImmediately, WaitUntilFinished}; - - NativeEventList(int defaultWaitMs = 20); - ~NativeEventList(); - - void append(QNativeEvent *event); - void append(int waitMs, QNativeEvent *event = 0); - - void play(Playback playback = WaitUntilFinished); - void stop(); - void setTimeMultiplier(float multiplier); - -signals: - void done(); - -private slots: - void sendNextEvent(); - -private: - void waitNextEvent(); - - QList > eventList; - float playbackMultiplier; - int currIndex; - bool wait; - int defaultWaitMs; - int debug; -}; - -#endif diff --git a/tests/auto/macnativeevents/qnativeevents.cpp b/tests/auto/macnativeevents/qnativeevents.cpp deleted file mode 100644 index b530d7bbe3..0000000000 --- a/tests/auto/macnativeevents/qnativeevents.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/**************************************************************************** -** -** 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 "qnativeevents.h" - -QNativeInput::QNativeInput(bool subscribe) -{ - if (subscribe) - subscribeForNativeEvents(); -} - -QNativeInput::~QNativeInput() -{ - unsubscribeForNativeEvents(); -} - -void QNativeInput::notify(QNativeEvent *event) -{ - nativeEvent(event); -} - -void QNativeInput::nativeEvent(QNativeEvent *event) -{ - switch (event->id()){ - case QNativeMouseButtonEvent::eventId:{ - QNativeMouseButtonEvent *e = static_cast(event); - (e->clickCount > 0) ? nativeMousePressEvent(e) : nativeMouseReleaseEvent(e); - break; } - case QNativeMouseMoveEvent::eventId: - nativeMouseMoveEvent(static_cast(event)); - break; - case QNativeMouseDragEvent::eventId: - nativeMouseDragEvent(static_cast(event)); - break; - case QNativeMouseWheelEvent::eventId: - nativeMouseWheelEvent(static_cast(event)); - break; - case QNativeKeyEvent::eventId:{ - QNativeKeyEvent *e = static_cast(event); - e->press ? nativeKeyPressEvent(e) : nativeKeyReleaseEvent(e); - break; } - case QNativeModifierEvent::eventId: - nativeModifierEvent(static_cast(event)); - break; - default: - break; - } -} - -Qt::Native::Status QNativeInput::sendNativeEvent(const QNativeEvent &event, int pid) -{ - switch (event.id()){ - case QNativeMouseMoveEvent::eventId: - return sendNativeMouseMoveEvent(static_cast(event)); - case QNativeMouseButtonEvent::eventId: - return sendNativeMouseButtonEvent(static_cast(event)); - case QNativeMouseDragEvent::eventId: - return sendNativeMouseDragEvent(static_cast(event)); - case QNativeMouseWheelEvent::eventId: - return sendNativeMouseWheelEvent(static_cast(event)); - case QNativeKeyEvent::eventId: - return sendNativeKeyEvent(static_cast(event), pid); - case QNativeModifierEvent::eventId: - return sendNativeModifierEvent(static_cast(event)); - case QNativeEvent::eventId: - qWarning() << "Warning: Cannot send a pure native event. Use a sub class."; - default: - return Qt::Native::Failure; - } -} - -QNativeEvent::QNativeEvent(Qt::KeyboardModifiers modifiers) - : modifiers(modifiers){} - -QNativeMouseEvent::QNativeMouseEvent(QPoint pos, Qt::KeyboardModifiers modifiers) - : QNativeEvent(modifiers), globalPos(pos){} - -QNativeMouseMoveEvent::QNativeMouseMoveEvent(QPoint pos, Qt::KeyboardModifiers modifiers) - : QNativeMouseEvent(pos, modifiers){} - -QNativeMouseButtonEvent::QNativeMouseButtonEvent(QPoint globalPos, Qt::MouseButton button, int clickCount, Qt::KeyboardModifiers modifiers) - : QNativeMouseEvent(globalPos, modifiers), button(button), clickCount(clickCount){} - -QNativeMouseDragEvent::QNativeMouseDragEvent(QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers) - : QNativeMouseButtonEvent(globalPos, button, true, modifiers){} - -QNativeMouseWheelEvent::QNativeMouseWheelEvent(QPoint globalPos, int delta, Qt::KeyboardModifiers modifiers) - : QNativeMouseEvent(globalPos, modifiers), delta(delta){} - -QNativeKeyEvent::QNativeKeyEvent(int nativeKeyCode, bool press, Qt::KeyboardModifiers modifiers) - : QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode), press(press), character(QChar()){} - -QNativeModifierEvent::QNativeModifierEvent(Qt::KeyboardModifiers modifiers, int nativeKeyCode) - : QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode){} - -QNativeKeyEvent::QNativeKeyEvent(int nativeKeyCode, bool press, QChar character, Qt::KeyboardModifiers modifiers) - : QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode), press(press), character(character){} - -static QString getButtonAsString(const QNativeMouseButtonEvent *e) -{ - switch (e->button){ - case Qt::LeftButton: - return "button = LeftButton"; - break; - case Qt::RightButton: - return "button = RightButton"; - break; - case Qt::MidButton: - return "button = MidButton"; - break; - default: - return "button = Other"; - break; - } -} - -static QString getModifiersAsString(const QNativeEvent *e) -{ - if (e->modifiers == 0) - return "modifiers = none"; - - QString tmp = "modifiers = "; - if (e->modifiers.testFlag(Qt::ShiftModifier)) - tmp += "Shift"; - if (e->modifiers.testFlag(Qt::ControlModifier)) - tmp += "Control"; - if (e->modifiers.testFlag(Qt::AltModifier)) - tmp += "Alt"; - if (e->modifiers.testFlag(Qt::MetaModifier)) - tmp += "Meta"; - return tmp; -} - -static QString getPosAsString(QPoint pos) -{ - return QString("QPoint(%1, %2)").arg(pos.x()).arg(pos.y()); -} - -static QString getBoolAsString(bool b) -{ - return b ? QString("true") : QString("false"); -} - -QString QNativeMouseMoveEvent::toString() const -{ - return QString("QNativeMouseMoveEvent(globalPos = %1 %2)").arg(getPosAsString(globalPos)) - .arg(getModifiersAsString(this)); -} - -QString QNativeMouseButtonEvent::toString() const -{ - return QString("QNativeMouseButtonEvent(globalPos = %1, %2, clickCount = %3, %4)").arg(getPosAsString(globalPos)) - .arg(getButtonAsString(this)).arg(clickCount).arg(getModifiersAsString(this)); -} - -QString QNativeMouseDragEvent::toString() const -{ - return QString("QNativeMouseDragEvent(globalPos = %1, %2, clickCount = %3, %4)").arg(getPosAsString(globalPos)) - .arg(getButtonAsString(this)).arg(clickCount).arg(getModifiersAsString(this)); -} - -QString QNativeMouseWheelEvent::toString() const -{ - return QString("QNativeMouseWheelEvent(globalPos = %1, delta = %2, %3)").arg(getPosAsString(globalPos)) - .arg(delta).arg(getModifiersAsString(this)); -} - -QString QNativeKeyEvent::toString() const -{ - return QString("QNativeKeyEvent(press = %1, native key code = %2, character = %3, %4)").arg(getBoolAsString(press)) - .arg(nativeKeyCode).arg(character.isPrint() ? character : QString("")) - .arg(getModifiersAsString(this)); -} - -QString QNativeModifierEvent::toString() const -{ - return QString("QNativeModifierEvent(%1, native key code = %2)").arg(getModifiersAsString(this)) - .arg(nativeKeyCode); -} - -QDebug operator<<(QDebug d, QNativeEvent *e) -{ - Q_UNUSED(e); - return d << e->toString(); -} - -QDebug operator<<(QDebug d, const QNativeEvent &e) -{ - Q_UNUSED(e); - return d << e.toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeEvent *e) -{ - return s << e->eventId << " " << e->modifiers << " QNativeEvent"; -} - -QTextStream &operator<<(QTextStream &s, QNativeMouseEvent *e) -{ - return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->modifiers << " " << e->toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeMouseMoveEvent *e) -{ - return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->modifiers << " " << e->toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeMouseButtonEvent *e) -{ - return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->button - << " " << e->clickCount << " " << e->modifiers << " " << e->toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeMouseDragEvent *e) -{ - return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->button << " " << e->clickCount - << " " << e->modifiers << " " << e->toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeMouseWheelEvent *e) -{ - return s << e->eventId << " " << e->globalPos.x() << " " << e->globalPos.y() << " " << e->delta - << " " << e->modifiers << " " << e->toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeKeyEvent *e) -{ - return s << e->eventId << " " << e->press << " " << e->nativeKeyCode << " " << e->character - << " " << e->modifiers << " " << e->toString(); -} - -QTextStream &operator<<(QTextStream &s, QNativeModifierEvent *e) -{ - return s << e->eventId << " " << e->modifiers << " " << e->nativeKeyCode << " " << e->toString(); -} - - - - -QTextStream &operator>>(QTextStream &s, QNativeMouseMoveEvent *e) -{ - // Skip reading eventId. - QString humanReadable; - int x, y, modifiers; - s >> x >> y >> modifiers >> humanReadable; - e->globalPos.setX(x); - e->globalPos.setY(y); - e->modifiers = Qt::KeyboardModifiers(modifiers); - return s; -} - -QTextStream &operator>>(QTextStream &s, QNativeMouseButtonEvent *e) -{ - // Skip reading eventId. - QString humanReadable; - int x, y, button, clickCount, modifiers; - s >> x >> y >> button >> clickCount >> modifiers >> humanReadable; - e->globalPos.setX(x); - e->globalPos.setY(y); - e->clickCount = clickCount; - e->modifiers = Qt::KeyboardModifiers(modifiers); - switch (button){ - case 1: - e->button = Qt::LeftButton; - break; - case 2: - e->button = Qt::RightButton; - break; - case 3: - e->button = Qt::MidButton; - break; - default: - e->button = Qt::NoButton; - break; - } - return s; -} - -QTextStream &operator>>(QTextStream &s, QNativeMouseDragEvent *e) -{ - // Skip reading eventId. - QString humanReadable; - int x, y, button, clickCount, modifiers; - s >> x >> y >> button >> clickCount >> modifiers >> humanReadable; - e->globalPos.setX(x); - e->globalPos.setY(y); - e->clickCount = clickCount; - e->modifiers = Qt::KeyboardModifiers(modifiers); - switch (button){ - case 1: - e->button = Qt::LeftButton; - break; - case 2: - e->button = Qt::RightButton; - break; - case 3: - e->button = Qt::MidButton; - break; - default: - e->button = Qt::NoButton; - break; - } - return s; -} - -QTextStream &operator>>(QTextStream &s, QNativeMouseWheelEvent *e) -{ - // Skip reading eventId. - QString humanReadable; - int x, y, modifiers; - s >> x >> y >> e->delta >> modifiers >> humanReadable; - e->globalPos.setX(x); - e->globalPos.setY(y); - e->modifiers = Qt::KeyboardModifiers(modifiers); - return s; -} - -QTextStream &operator>>(QTextStream &s, QNativeKeyEvent *e) -{ - // Skip reading eventId. - QString humanReadable; - int press, modifiers; - QString character; - s >> press >> e->nativeKeyCode >> character >> modifiers >> humanReadable; - e->press = bool(press); - e->character = character[0]; - e->modifiers = Qt::KeyboardModifiers(modifiers); - return s; -} - -QTextStream &operator>>(QTextStream &s, QNativeModifierEvent *e) -{ - // Skip reading eventId. - QString humanReadable; - int modifiers; - s >> modifiers >> e->nativeKeyCode >> humanReadable; - e->modifiers = Qt::KeyboardModifiers(modifiers); - return s; -} - diff --git a/tests/auto/macnativeevents/qnativeevents.h b/tests/auto/macnativeevents/qnativeevents.h deleted file mode 100644 index 276afc4fb7..0000000000 --- a/tests/auto/macnativeevents/qnativeevents.h +++ /dev/null @@ -1,228 +0,0 @@ -/**************************************************************************** -** -** 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 Q_NATIVE_INPUT -#define Q_NATIVE_INPUT - -#include - -namespace Qt { -namespace Native { - enum Status {Success, Failure}; -}} - -// ---------------------------------------------------------------------------- -// Declare a set of native events that can be used to communicate with -// client applications in an platform independent way -// ---------------------------------------------------------------------------- - -class QNativeEvent -{ -public: - static const int eventId = 1; - - QNativeEvent(Qt::KeyboardModifiers modifiers = Qt::NoModifier); - virtual ~QNativeEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const = 0; - Qt::KeyboardModifiers modifiers; // Yields for mouse events too. -}; - -class QNativeMouseEvent : public QNativeEvent { -public: - static const int eventId = 2; - - QNativeMouseEvent(){}; - QNativeMouseEvent(QPoint globalPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - virtual ~QNativeMouseEvent(){}; - virtual int id() const { return eventId; }; - - QPoint globalPos; -}; - -class QNativeMouseMoveEvent : public QNativeMouseEvent { -public: - static const int eventId = 4; - - QNativeMouseMoveEvent(){}; - QNativeMouseMoveEvent(QPoint globalPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - virtual ~QNativeMouseMoveEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const; -}; - -class QNativeMouseButtonEvent : public QNativeMouseEvent { -public: - static const int eventId = 8; - - QNativeMouseButtonEvent(){}; - QNativeMouseButtonEvent(QPoint globalPos, Qt::MouseButton button, int clickCount, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - virtual ~QNativeMouseButtonEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const; - - Qt::MouseButton button; - int clickCount; -}; - -class QNativeMouseDragEvent : public QNativeMouseButtonEvent { -public: - static const int eventId = 16; - - QNativeMouseDragEvent(){}; - QNativeMouseDragEvent(QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - virtual ~QNativeMouseDragEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const; -}; - -class QNativeMouseWheelEvent : public QNativeMouseEvent { -public: - static const int eventId = 32; - - QNativeMouseWheelEvent(){}; - QNativeMouseWheelEvent(QPoint globalPos, int delta, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - virtual ~QNativeMouseWheelEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const; - - int delta; -}; - -class QNativeKeyEvent : public QNativeEvent { - public: - static const int eventId = 64; - - QNativeKeyEvent(){}; - QNativeKeyEvent(int nativeKeyCode, bool press, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - QNativeKeyEvent(int nativeKeyCode, bool press, QChar character, Qt::KeyboardModifiers modifiers); - virtual ~QNativeKeyEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const; - - int nativeKeyCode; - bool press; - QChar character; - - // Some Qt to Native mappings: - static int Key_A; - static int Key_B; - static int Key_C; - static int Key_1; - static int Key_Backspace; - static int Key_Enter; - static int Key_Del; -}; - -class QNativeModifierEvent : public QNativeEvent { -public: - static const int eventId = 128; - - QNativeModifierEvent(Qt::KeyboardModifiers modifiers = Qt::NoModifier, int nativeKeyCode = 0); - virtual ~QNativeModifierEvent(){}; - virtual int id() const { return eventId; }; - virtual QString toString() const; - - int nativeKeyCode; -}; - -// ---------------------------------------------------------------------------- -// Declare a set of related output / input functions for convenience: -// ---------------------------------------------------------------------------- - -QDebug operator<<(QDebug d, QNativeEvent *e); -QDebug operator<<(QDebug d, const QNativeEvent &e); - -QTextStream &operator<<(QTextStream &s, QNativeEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeMouseEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeMouseMoveEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeMouseButtonEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeMouseDragEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeMouseWheelEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeKeyEvent *e); -QTextStream &operator<<(QTextStream &s, QNativeModifierEvent *e); - -QTextStream &operator>>(QTextStream &s, QNativeMouseMoveEvent *e); -QTextStream &operator>>(QTextStream &s, QNativeMouseButtonEvent *e); -QTextStream &operator>>(QTextStream &s, QNativeMouseDragEvent *e); -QTextStream &operator>>(QTextStream &s, QNativeMouseWheelEvent *e); -QTextStream &operator>>(QTextStream &s, QNativeKeyEvent *e); -QTextStream &operator>>(QTextStream &s, QNativeModifierEvent *e); - -// ---------------------------------------------------------------------------- -// Declare the main class that is supposed to be sub-classed by components -// that are to receive native events -// ---------------------------------------------------------------------------- - -class QNativeInput -{ - public: - QNativeInput(bool subscribe = true); - virtual ~QNativeInput(); - - // Callback methods. Should be implemented by interested sub-classes: - void notify(QNativeEvent *event); - virtual void nativeEvent(QNativeEvent *event); - virtual void nativeMousePressEvent(QNativeMouseButtonEvent *){}; - virtual void nativeMouseReleaseEvent(QNativeMouseButtonEvent *){}; - virtual void nativeMouseMoveEvent(QNativeMouseMoveEvent *){}; - virtual void nativeMouseDragEvent(QNativeMouseDragEvent *){}; - virtual void nativeMouseWheelEvent(QNativeMouseWheelEvent *){}; - virtual void nativeKeyPressEvent(QNativeKeyEvent *){}; - virtual void nativeKeyReleaseEvent(QNativeKeyEvent *){}; - virtual void nativeModifierEvent(QNativeModifierEvent *){}; - - // The following methods will differ in implementation from OS to OS: - static Qt::Native::Status sendNativeMouseButtonEvent(const QNativeMouseButtonEvent &event); - static Qt::Native::Status sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event); - static Qt::Native::Status sendNativeMouseDragEvent(const QNativeMouseDragEvent &event); - static Qt::Native::Status sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event); - static Qt::Native::Status sendNativeKeyEvent(const QNativeKeyEvent &event, int pid = 0); - static Qt::Native::Status sendNativeModifierEvent(const QNativeModifierEvent &event); - // sendNativeEvent will NOT differ from OS to OS. - static Qt::Native::Status sendNativeEvent(const QNativeEvent &event, int pid = 0); - - // The following methods will differ in implementation from OS to OS: - Qt::Native::Status subscribeForNativeEvents(); - Qt::Native::Status unsubscribeForNativeEvents(); -}; - -#endif // Q_NATIVE_INPUT diff --git a/tests/auto/macnativeevents/qnativeevents_mac.cpp b/tests/auto/macnativeevents/qnativeevents_mac.cpp deleted file mode 100644 index 8987a8d502..0000000000 --- a/tests/auto/macnativeevents/qnativeevents_mac.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/**************************************************************************** -** -** 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 "qnativeevents.h" -#include -#include - -// ************************************************************ -// Quartz -// ************************************************************ - -static Qt::KeyboardModifiers getModifiersFromQuartzEvent(CGEventRef inEvent) -{ - Qt::KeyboardModifiers m; - CGEventFlags flags = CGEventGetFlags(inEvent); - if (flags & kCGEventFlagMaskShift || flags & kCGEventFlagMaskAlphaShift) - m |= Qt::ShiftModifier; - if (flags & kCGEventFlagMaskControl) - m |= Qt::ControlModifier; - if (flags & kCGEventFlagMaskAlternate) - m |= Qt::AltModifier; - if (flags & kCGEventFlagMaskCommand) - m |= Qt::MetaModifier; - return m; -} - -static void setModifiersFromQNativeEvent(CGEventRef inEvent, const QNativeEvent &event) -{ - CGEventFlags flags = 0; - if (event.modifiers.testFlag(Qt::ShiftModifier)) - flags |= kCGEventFlagMaskShift; - if (event.modifiers.testFlag(Qt::ControlModifier)) - flags |= kCGEventFlagMaskControl; - if (event.modifiers.testFlag(Qt::AltModifier)) - flags |= kCGEventFlagMaskAlternate; - if (event.modifiers.testFlag(Qt::MetaModifier)) - flags |= kCGEventFlagMaskCommand; - CGEventSetFlags(inEvent, flags); -} - -static QPoint getMouseLocationFromQuartzEvent(CGEventRef inEvent) -{ - CGPoint pos = CGEventGetLocation(inEvent); - QPoint tmp; - tmp.setX(pos.x); - tmp.setY(pos.y); - return tmp; -} - -static QChar getCharFromQuartzEvent(CGEventRef inEvent) -{ - UniCharCount count = 0; - UniChar c; - CGEventKeyboardGetUnicodeString(inEvent, 1, &count, &c); - return QChar(c); -} - -static CGEventRef EventHandler_Quartz(CGEventTapProxy proxy, CGEventType type, CGEventRef inEvent, void *refCon) -{ - Q_UNUSED(proxy); - QNativeInput *nativeInput = static_cast(refCon); - switch (type){ - case kCGEventKeyDown:{ - QNativeKeyEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode); - e.character = getCharFromQuartzEvent(inEvent); - e.press = true; - nativeInput->notify(&e); - break; - } - case kCGEventKeyUp:{ - QNativeKeyEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode); - e.character = getCharFromQuartzEvent(inEvent); - e.press = false; - nativeInput->notify(&e); - break; - } - case kCGEventLeftMouseDown:{ - QNativeMouseButtonEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState); - e.button = Qt::LeftButton; - nativeInput->notify(&e); - break; - } - case kCGEventLeftMouseUp:{ - QNativeMouseButtonEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - e.clickCount = 0; - e.button = Qt::LeftButton; - nativeInput->notify(&e); - break; - } - case kCGEventRightMouseDown:{ - QNativeMouseButtonEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState); - e.button = Qt::RightButton; - nativeInput->notify(&e); - break; - } - case kCGEventRightMouseUp:{ - QNativeMouseButtonEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - e.clickCount = 0; - e.button = Qt::RightButton; - nativeInput->notify(&e); - break; - } - case kCGEventMouseMoved:{ - QNativeMouseMoveEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - nativeInput->notify(&e); - break; - } - case kCGEventLeftMouseDragged:{ - QNativeMouseDragEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState); - e.button = Qt::LeftButton; - nativeInput->notify(&e); - break; - } - case kCGEventScrollWheel:{ - QNativeMouseWheelEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.delta = CGEventGetIntegerValueField(inEvent, kCGScrollWheelEventDeltaAxis1); - e.globalPos = getMouseLocationFromQuartzEvent(inEvent); - nativeInput->notify(&e); - break; - } - case kCGEventFlagsChanged:{ - QNativeModifierEvent e; - e.modifiers = getModifiersFromQuartzEvent(inEvent); - e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode); - nativeInput->notify(&e); - break; - } - - } - - return inEvent; -} - -Qt::Native::Status insertEventHandler_Quartz(QNativeInput *nativeInput, int pid = 0) -{ - uid_t uid = geteuid(); - if (uid != 0) - qWarning("MacNativeEvents: You must be root to listen for key events!"); - - CFMachPortRef port; - if (!pid){ - port = CGEventTapCreate(kCGHIDEventTap, - kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, - kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput); - } else { - ProcessSerialNumber psn; - GetProcessForPID(pid, &psn); - port = CGEventTapCreateForPSN(&psn, - kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, - kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput); - } - - CFRunLoopSourceRef eventSrc = CFMachPortCreateRunLoopSource(NULL, port, 0); - CFRunLoopAddSource((CFRunLoopRef) GetCFRunLoopFromEventLoop(GetMainEventLoop()), - eventSrc, kCFRunLoopCommonModes); - - return Qt::Native::Success; -} - -Qt::Native::Status removeEventHandler_Quartz() -{ - return Qt::Native::Success; // ToDo: -} - -Qt::Native::Status sendNativeKeyEventToProcess_Quartz(const QNativeKeyEvent &event, int pid) -{ - ProcessSerialNumber psn; - GetProcessForPID(pid, &psn); - - CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press); - setModifiersFromQNativeEvent(e, event); - SetFrontProcess(&psn); - CGEventPostToPSN(&psn, e); - CFRelease(e); - return Qt::Native::Success; -} - -Qt::Native::Status sendNativeKeyEvent_Quartz(const QNativeKeyEvent &event) -{ - CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press); - setModifiersFromQNativeEvent(e, event); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); - return Qt::Native::Success; -} - -Qt::Native::Status sendNativeMouseMoveEvent_Quartz(const QNativeMouseMoveEvent &event) -{ - CGPoint pos; - pos.x = event.globalPos.x(); - pos.y = event.globalPos.y(); - - CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0); - setModifiersFromQNativeEvent(e, event); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); - return Qt::Native::Success; -} - -Qt::Native::Status sendNativeMouseButtonEvent_Quartz(const QNativeMouseButtonEvent &event) -{ - CGPoint pos; - pos.x = event.globalPos.x(); - pos.y = event.globalPos.y(); - - CGEventType type = 0; - if (event.button == Qt::LeftButton) - type = (event.clickCount > 0) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp; - else if (event.button == Qt::RightButton) - type = (event.clickCount > 0) ? kCGEventRightMouseDown : kCGEventRightMouseUp; - else - type = (event.clickCount > 0) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp; - - CGEventRef e = CGEventCreateMouseEvent(0, type, pos, event.button); - setModifiersFromQNativeEvent(e, event); - CGEventSetIntegerValueField(e, kCGMouseEventClickState, event.clickCount); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); - return Qt::Native::Success; -} - -Qt::Native::Status sendNativeMouseDragEvent_Quartz(const QNativeMouseDragEvent &event) -{ - CGPoint pos; - pos.x = event.globalPos.x(); - pos.y = event.globalPos.y(); - - CGEventType type = 0; - if (event.button == Qt::LeftButton) - type = kCGEventLeftMouseDragged; - else if (event.button == Qt::RightButton) - type = kCGEventRightMouseDragged; - else - type = kCGEventOtherMouseDragged; - - CGEventRef e = CGEventCreateMouseEvent(0, type, pos, event.button); - setModifiersFromQNativeEvent(e, event); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); - return Qt::Native::Success; -} - -Qt::Native::Status sendNativeMouseWheelEvent_Quartz(const QNativeMouseWheelEvent &event) -{ - CGPoint pos; - pos.x = event.globalPos.x(); - pos.y = event.globalPos.y(); - - CGEventRef e = CGEventCreateScrollWheelEvent(0, kCGScrollEventUnitPixel, 1, 0); - CGEventSetIntegerValueField(e, kCGScrollWheelEventDeltaAxis1, event.delta); - CGEventSetLocation(e, pos); - setModifiersFromQNativeEvent(e, event); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); - - return Qt::Native::Success; -} - -Qt::Native::Status sendNativeModifierEvent_Quartz(const QNativeModifierEvent &event) -{ - CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, 0); - CGEventSetType(e, kCGEventFlagsChanged); - setModifiersFromQNativeEvent(e, event); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); - return Qt::Native::Success; -} - -// ************************************************************ -// QNativeInput methods: -// ************************************************************ - -Qt::Native::Status QNativeInput::sendNativeMouseButtonEvent(const QNativeMouseButtonEvent &event) -{ - return sendNativeMouseButtonEvent_Quartz(event); -} - -Qt::Native::Status QNativeInput::sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event) -{ - return sendNativeMouseMoveEvent_Quartz(event); -} - -Qt::Native::Status QNativeInput::sendNativeMouseDragEvent(const QNativeMouseDragEvent &event) -{ - return sendNativeMouseDragEvent_Quartz(event); -} - -Qt::Native::Status QNativeInput::sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event) -{ - return sendNativeMouseWheelEvent_Quartz(event); -} - -Qt::Native::Status QNativeInput::sendNativeKeyEvent(const QNativeKeyEvent &event, int pid) -{ - if (!pid) - return sendNativeKeyEvent_Quartz(event); - else - return sendNativeKeyEventToProcess_Quartz(event, pid); -} - -Qt::Native::Status QNativeInput::sendNativeModifierEvent(const QNativeModifierEvent &event) -{ - return sendNativeModifierEvent_Quartz(event); -} - -Qt::Native::Status QNativeInput::subscribeForNativeEvents() -{ - return insertEventHandler_Quartz(this); -} - -Qt::Native::Status QNativeInput::unsubscribeForNativeEvents() -{ - return removeEventHandler_Quartz(); -} - -// Some Qt to Mac mappings: -int QNativeKeyEvent::Key_A = 0; -int QNativeKeyEvent::Key_B = 11; -int QNativeKeyEvent::Key_C = 8; -int QNativeKeyEvent::Key_1 = 18; -int QNativeKeyEvent::Key_Backspace = 51; -int QNativeKeyEvent::Key_Enter = 36; -int QNativeKeyEvent::Key_Del = 117; - diff --git a/tests/auto/macnativeevents/tst_macnativeevents.cpp b/tests/auto/macnativeevents/tst_macnativeevents.cpp deleted file mode 100644 index ea30b0b5c2..0000000000 --- a/tests/auto/macnativeevents/tst_macnativeevents.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -#include "qnativeevents.h" -#include "nativeeventlist.h" -#include "expectedeventlist.h" -#include - -QT_USE_NAMESPACE - -class tst_MacNativeEvents : public QObject -{ -Q_OBJECT -private slots: - void testMouseMoveLocation(); - void testPushButtonPressRelease(); - void testMouseLeftDoubleClick(); - void stressTestMouseLeftDoubleClick(); - void testMouseDragInside(); - void testMouseDragOutside(); - void testMouseDragToNonClientArea(); - void testDragWindow(); - void testMouseEnter(); - void testChildDialogInFrontOfModalParent(); -// void testChildWindowInFrontOfParentWindow(); -// void testChildToolWindowInFrontOfChildNormalWindow(); - void testChildWindowInFrontOfStaysOnTopParentWindow(); - void testKeyPressOnToplevel(); - void testModifierShift(); - void testModifierAlt(); - void testModifierCtrl(); - void testModifierCtrlWithDontSwapCtrlAndMeta(); -}; - -void tst_MacNativeEvents::testMouseMoveLocation() -{ - QWidget w; - w.setMouseTracking(true); - w.show(); - QPoint p = w.geometry().center(); - - NativeEventList native; - native.append(new QNativeMouseMoveEvent(p, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p), p, Qt::NoButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testPushButtonPressRelease() -{ - // Check that a native mouse press and release generates the - // same qevents on a pushbutton: - QPushButton w("click me"); - w.show(); - QPoint p = w.geometry().center(); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testMouseLeftDoubleClick() -{ - // Check that a native double click makes - // the test widget receive a press-release-click-release: - QWidget w; - w.show(); - QPoint p = w.geometry().center(); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::stressTestMouseLeftDoubleClick() -{ - // Check that multiple, fast, double clicks makes - // the test widget receive correct click events - QWidget w; - w.show(); - QPoint p = w.geometry().center(); - - NativeEventList native; - ExpectedEventList expected(&w); - - for (int i=0; i<10; ++i){ - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier)); - - expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - } - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testMouseDragInside() -{ - // Check that a mouse drag inside a widget - // will cause press-move-release events to be delivered - QWidget w; - w.show(); - QPoint p1 = w.geometry().center(); - QPoint p2 = p1 - QPoint(10, 0); - QPoint p3 = p1 - QPoint(20, 0); - QPoint p4 = p1 - QPoint(30, 0); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(p1, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(p2, Qt::LeftButton, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(p3, Qt::LeftButton, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(p4, Qt::LeftButton, 0, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p1), p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p2), p2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p3), p3, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p4), p4, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testMouseDragOutside() -{ - // Check that if we drag the mouse from inside the - // widget, and release it outside, we still get mouse move - // and release events when the mouse is outside the widget. - QWidget w; - w.show(); - QPoint inside1 = w.geometry().center(); - QPoint inside2 = inside1 - QPoint(10, 0); - QPoint outside1 = w.geometry().topLeft() - QPoint(50, 0); - QPoint outside2 = outside1 - QPoint(10, 0); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(outside1, Qt::LeftButton, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(outside2, Qt::LeftButton, 0, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(outside1), outside1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(outside2), outside2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testMouseDragToNonClientArea() -{ - // Check that if we drag the mouse from inside the - // widget, and release it on the title bar, we still get mouse move - // and release events when the mouse is on the title bar - QWidget w; - w.show(); - QPoint inside1 = w.geometry().center(); - QPoint inside2 = inside1 - QPoint(10, 0); - QPoint titlebar1 = w.geometry().topLeft() - QPoint(-100, 10); - QPoint titlebar2 = titlebar1 - QPoint(10, 0); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(titlebar1, Qt::LeftButton, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(titlebar2, Qt::LeftButton, 0, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(titlebar1), titlebar1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(titlebar2), titlebar2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testDragWindow() -{ - // Check that if we drag the mouse from inside the - // widgets title bar, we get a move event on the window - QWidget w; - w.show(); - QPoint titlebar = w.geometry().topLeft() - QPoint(-100, 10); - QPoint moveTo = titlebar + QPoint(100, 0); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(titlebar, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseDragEvent(moveTo, Qt::LeftButton, Qt::NoModifier)); - native.append(500, new QNativeMouseButtonEvent(moveTo, Qt::LeftButton, 0, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonPress, w.mapFromGlobal(titlebar), titlebar, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonRelease, w.mapFromGlobal(titlebar), moveTo, Qt::LeftButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testMouseEnter() -{ - // When a mouse enters a widget, both a mouse enter events and a - // mouse move event should be sendt. Lets test this: - QWidget w; - w.setMouseTracking(true); - w.show(); - QPoint outside = w.geometry().topLeft() - QPoint(50, 0); - QPoint inside = w.geometry().center(); - - NativeEventList native; - native.append(new QNativeMouseMoveEvent(outside, Qt::NoModifier)); - native.append(new QNativeMouseMoveEvent(inside, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QEvent(QEvent::Enter)); - expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside), inside, Qt::NoButton, Qt::NoButton, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testChildDialogInFrontOfModalParent() -{ - // Test that a child dialog of a modal parent dialog is - // in front of the parent, and active: - QDialog parent; - parent.setWindowModality(Qt::ApplicationModal); - QDialog child(&parent); - QPushButton button("close", &child); - connect(&button, SIGNAL(clicked()), &child, SLOT(close())); - parent.show(); - child.show(); - QPoint inside = button.mapToGlobal(button.geometry().center()); - - // Post a click on the button to close the child dialog: - NativeEventList native; - native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier)); - - native.play(); - QTest::qWait(100); - QVERIFY(!child.isVisible()); -} - -#if 0 -// This test is disabled as of Qt-4.7.4 because we cannot do it -// unless we use the Cocoa sub window API. But using that opens up -// a world of side effects that we cannot live with. So we rather -// not support child-on-top-of-parent instead. -void tst_MacNativeEvents::testChildWindowInFrontOfParentWindow() -{ - // Test that a child window always stacks in front of its parent window. - // Do this by first click on the parent, then on the child window button. - QWidget parent; - QPushButton child("a button", &parent); - child.setWindowFlags(Qt::Window); - connect(&child, SIGNAL(clicked()), &child, SLOT(close())); - parent.show(); - child.show(); - - QPoint parent_p = parent.geometry().bottomLeft() + QPoint(20, -20); - QPoint child_p = child.geometry().center(); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 0, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 0, Qt::NoModifier)); - - native.play(); - QTest::qWait(100); - QVERIFY(!child.isVisible()); -} -#endif - -/* This test can be enabled once setStackingOrder has been fixed in qwidget_mac.mm -void tst_MacNativeEvents::testChildToolWindowInFrontOfChildNormalWindow() -{ - // Test that a child tool window always stacks in front of normal sibling windows. - // Do this by first click on the sibling, then on the tool window button. - QWidget parent; - QWidget normalChild(&parent, Qt::Window); - QPushButton toolChild("a button", &parent); - toolChild.setWindowFlags(Qt::Tool); - connect(&toolChild, SIGNAL(clicked()), &toolChild, SLOT(close())); - parent.show(); - normalChild.show(); - toolChild.show(); - - QPoint normalChild_p = normalChild.geometry().bottomLeft() + QPoint(20, -20); - QPoint toolChild_p = toolChild.geometry().center(); - - NativeEventList native; - native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 0, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 0, Qt::NoModifier)); - - native.play(); - QTest::qWait(100); - QVERIFY(!toolChild.isVisible()); -} -*/ -void tst_MacNativeEvents::testChildWindowInFrontOfStaysOnTopParentWindow() -{ - // Test that a child window stacks on top of a stays-on-top parent. - QWidget parent(0, Qt::WindowStaysOnTopHint); - QPushButton button("close", &parent); - button.setWindowFlags(Qt::Window); - connect(&button, SIGNAL(clicked()), &button, SLOT(close())); - parent.show(); - button.show(); - QPoint inside = button.geometry().center(); - - // Post a click on the button to close the child dialog: - NativeEventList native; - native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier)); - native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier)); - - native.play(); - QTest::qWait(100); - QVERIFY(!button.isVisible()); -} - -void tst_MacNativeEvents::testKeyPressOnToplevel() -{ - // Check that we receive keyevents for - // toplevel widgets. For leagacy reasons, and according to Qt on - // other platforms (carbon port + linux), we should get these events - // even when the focus policy is set to Qt::NoFocus when there is no - // other focus widget on screen: - QWidget w; - w.show(); - - NativeEventList native; - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::NoModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testModifierShift() -{ - QWidget w; - w.show(); - - NativeEventList native; - native.append(new QNativeModifierEvent(Qt::ShiftModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ShiftModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ShiftModifier)); - native.append(new QNativeModifierEvent(Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier)); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testModifierAlt() -{ - QWidget w; - w.show(); - - NativeEventList native; - native.append(new QNativeModifierEvent(Qt::AltModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::AltModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::AltModifier)); - native.append(new QNativeModifierEvent(Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier)); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::AltModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::AltModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Alt, Qt::AltModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testModifierCtrl() -{ - // On Mac, we switch the Command and Control modifier by default, so that Command - // means Meta, and Control means Command. Lets check that this works: - QWidget w; - w.show(); - - QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]); - QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]); - - NativeEventList native; - native.append(new QNativeModifierEvent(Qt::ControlModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier)); - native.append(new QNativeModifierEvent(Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier)); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::MetaModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::MetaModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::MetaModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); -} - -void tst_MacNativeEvents::testModifierCtrlWithDontSwapCtrlAndMeta() -{ - // On Mac, we switch the Command and Control modifier by default, so that Command - // means Meta, and Control means Command. Lets check that the flag to swith off - // this behaviour works. While working on this test I realized that we actually - // don't (and never have) respected this flag for raw key events. Only for - // menus, through QKeySequence. I don't want to change this behaviour now, at - // least not until someone complains. So I choose to let the test just stop - // any unintended regressions instead. If we decide to resepect the the flag at one - // point, fix the test. - QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta); - QWidget w; - w.show(); - - QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]); - QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]); - - NativeEventList native; - native.append(new QNativeModifierEvent(Qt::ControlModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier)); - native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier)); - native.append(new QNativeModifierEvent(Qt::NoModifier)); - - ExpectedEventList expected(&w); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier)); - expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ControlModifier)); - expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::ControlModifier)); - - native.play(); - QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!"); - QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, false); -} - -QTEST_MAIN(tst_MacNativeEvents) -#include "tst_macnativeevents.moc" diff --git a/tests/auto/macplist/app/app.pro b/tests/auto/macplist/app/app.pro deleted file mode 100644 index c1cf52e0ef..0000000000 --- a/tests/auto/macplist/app/app.pro +++ /dev/null @@ -1,11 +0,0 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Wed Jan 7 13:01:11 2009 -###################################################################### - -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . - -# Input -SOURCES += main.cpp diff --git a/tests/auto/macplist/app/main.cpp b/tests/auto/macplist/app/main.cpp deleted file mode 100644 index ddc47a9a5f..0000000000 --- a/tests/auto/macplist/app/main.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** 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 - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - return 0; -} diff --git a/tests/auto/macplist/macplist.pro b/tests/auto/macplist/macplist.pro deleted file mode 100644 index 3a0e2d43d3..0000000000 --- a/tests/auto/macplist/macplist.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS = app test -CONFIG += ordered - - - diff --git a/tests/auto/macplist/test/test.pro b/tests/auto/macplist/test/test.pro deleted file mode 100644 index 4751b47e00..0000000000 --- a/tests/auto/macplist/test/test.pro +++ /dev/null @@ -1,11 +0,0 @@ -load(qttest_p4) - -SOURCES += ../tst_macplist.cpp -TARGET = ../tst_macplist -win32 { - CONFIG(debug, debug|release) { - TARGET = ../../debug/tst_macplist - } else { - TARGET = ../../release/tst_macplist - } -} diff --git a/tests/auto/macplist/tst_macplist.cpp b/tests/auto/macplist/tst_macplist.cpp deleted file mode 100644 index 5b48c586b5..0000000000 --- a/tests/auto/macplist/tst_macplist.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -class tst_MacPlist : public QObject -{ - Q_OBJECT -public: - tst_MacPlist() {} - -private slots: -#ifdef Q_OS_MAC - void test_plist_data(); - void test_plist(); -#endif -}; - -#ifdef Q_OS_MAC -void tst_MacPlist::test_plist_data() -{ - QTest::addColumn("test_plist"); - - QTest::newRow("control") << QString::fromLatin1( -"" -"\n" -"\n" -"\n" -" CFBundleIconFile\n" -" \n" -" CFBundlePackageType\n" -" APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" -" CFBundleExecutable\n" -" app\n" -" CFBundleIdentifier\n" -" com.yourcompany.app\n" -"\n" -"\n"); - - QTest::newRow("LSUIElement-as-string") << QString::fromLatin1( -"" -"\n" -"\n" -"\n" -" CFBundleIconFile\n" -" \n" -" CFBundlePackageType\n" -" APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" -" CFBundleExecutable\n" -" app\n" -" CFBundleIdentifier\n" -" com.yourcompany.app\n" -" LSUIElement\n" -" false\n" -"\n" -"\n"); - - QTest::newRow("LSUIElement-as-bool") << QString::fromLatin1( -"" -"\n" -"\n" -"\n" -" CFBundleIconFile\n" -" \n" -" CFBundlePackageType\n" -" APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" -" CFBundleExecutable\n" -" app\n" -" CFBundleIdentifier\n" -" com.yourcompany.app\n" -" LSUIElement\n" -" \n" -"\n" -"\n"); - - QTest::newRow("LSUIElement-as-int") << QString::fromLatin1( -"" -"\n" -"\n" -"\n" -" CFBundleIconFile\n" -" \n" -" CFBundlePackageType\n" -" APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" -" CFBundleExecutable\n" -" app\n" -" CFBundleIdentifier\n" -" com.yourcompany.app\n" -" LSUIElement\n" -" 0\n" -"\n" -"\n"); - - QTest::newRow("LSUIElement-as-garbage") << QString::fromLatin1( -"" -"\n" -"\n" -"\n" -" CFBundleIconFile\n" -" \n" -" CFBundlePackageType\n" -" APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" -" CFBundleExecutable\n" -" app\n" -" CFBundleIdentifier\n" -" com.yourcompany.app\n" -" LSUIElement\n" -" 0\n" -"\n" -"\n"); -} - -void tst_MacPlist::test_plist() -{ - QFETCH(QString, test_plist); - - QString infoPlist = QLatin1String("Info.plist"); - QDir dir(QCoreApplication::applicationDirPath()); - QVERIFY(dir.cdUp()); - QVERIFY(dir.cdUp()); - QVERIFY(dir.cdUp()); - QVERIFY(dir.cd(QLatin1String("app"))); - QVERIFY(dir.cd(QLatin1String("app.app"))); - QVERIFY(dir.cd(QLatin1String("Contents"))); - QVERIFY(dir.exists(infoPlist)); - { - QFile file(dir.filePath(infoPlist)); - QVERIFY(file.open(QIODevice::WriteOnly)); - QByteArray ba = test_plist.toUtf8(); - QCOMPARE(file.write(ba), qint64(ba.size())); - } - QVERIFY(dir.cd(QLatin1String("MacOS"))); - QVERIFY(dir.exists(QLatin1String("app"))); - QProcess process; - process.start(dir.filePath("app")); - QCOMPARE(process.waitForFinished(), true); - QCOMPARE(process.exitStatus(), QProcess::NormalExit); -} -#endif - -QTEST_MAIN(tst_MacPlist) -#include "tst_macplist.moc" diff --git a/tests/auto/modeltest/dynamictreemodel.cpp b/tests/auto/modeltest/dynamictreemodel.cpp deleted file mode 100644 index 2f8bb0a730..0000000000 --- a/tests/auto/modeltest/dynamictreemodel.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Stephen Kelly -** 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 "dynamictreemodel.h" - -#include -#include -#include -#include - - -DynamicTreeModel::DynamicTreeModel(QObject *parent) - : QAbstractItemModel(parent), - nextId(1) -{ -} - -QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const -{ -// if (column != 0) -// return QModelIndex(); - - - if ( column < 0 || row < 0 ) - return QModelIndex(); - - QList > childIdColumns = m_childItems.value(parent.internalId()); - - const qint64 grandParent = findParentId(parent.internalId()); - if (grandParent >= 0) { - QList > parentTable = m_childItems.value(grandParent); - if (parent.column() >= parentTable.size()) - qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO); - QList parentSiblings = parentTable.at(parent.column()); - if (parent.row() >= parentSiblings.size()) - qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO); - } - - if (childIdColumns.size() == 0) - return QModelIndex(); - - if (column >= childIdColumns.size()) - return QModelIndex(); - - QList rowIds = childIdColumns.at(column); - - if ( row >= rowIds.size()) - return QModelIndex(); - - qint64 id = rowIds.at(row); - - return createIndex(row, column, reinterpret_cast(id)); - -} - -qint64 DynamicTreeModel::findParentId(qint64 searchId) const -{ - if (searchId <= 0) - return -1; - - QHashIterator > > i(m_childItems); - while (i.hasNext()) - { - i.next(); - QListIterator > j(i.value()); - while (j.hasNext()) - { - QList l = j.next(); - if (l.contains(searchId)) - { - return i.key(); - } - } - } - return -1; -} - -QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - qint64 searchId = index.internalId(); - qint64 parentId = findParentId(searchId); - // Will never happen for valid index, but what the hey... - if (parentId <= 0) - return QModelIndex(); - - qint64 grandParentId = findParentId(parentId); - if (grandParentId < 0) - grandParentId = 0; - - int column = 0; - QList childList = m_childItems.value(grandParentId).at(column); - - int row = childList.indexOf(parentId); - - return createIndex(row, column, reinterpret_cast(parentId)); - -} - -int DynamicTreeModel::rowCount(const QModelIndex &index ) const -{ - QList > cols = m_childItems.value(index.internalId()); - - if (cols.size() == 0 ) - return 0; - - if (index.column() > 0) - return 0; - - return cols.at(0).size(); -} - -int DynamicTreeModel::columnCount(const QModelIndex &index ) const -{ -// Q_UNUSED(index); - return m_childItems.value(index.internalId()).size(); -} - -QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (Qt::DisplayRole == role) - { - return m_items.value(index.internalId()); - } - return QVariant(); -} - -void DynamicTreeModel::clear() -{ - beginResetModel(); - m_items.clear(); - m_childItems.clear(); - nextId = 1; - endResetModel(); -} - - -ModelChangeCommand::ModelChangeCommand( DynamicTreeModel *model, QObject *parent ) - : QObject(parent), m_model(model), m_numCols(1), m_startRow(-1), m_endRow(-1) -{ - -} - -QModelIndex ModelChangeCommand::findIndex(QList rows) -{ - const int col = 0; - QModelIndex parent = QModelIndex(); - QListIterator i(rows); - while (i.hasNext()) - { - parent = m_model->index(i.next(), col, parent); - if (!parent.isValid()) - qFatal("%s: parent must be valid", Q_FUNC_INFO); - } - return parent; -} - -ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent ) - : ModelChangeCommand(model, parent) -{ - -} - -void ModelInsertCommand::doCommand() -{ - QModelIndex parent = findIndex(m_rowNumbers); - m_model->beginInsertRows(parent, m_startRow, m_endRow); - qint64 parentId = parent.internalId(); - for (int row = m_startRow; row <= m_endRow; row++) - { - for(int col = 0; col < m_numCols; col++ ) - { - if (m_model->m_childItems[parentId].size() <= col) - { - m_model->m_childItems[parentId].append(QList()); - } -// QString name = QUuid::createUuid().toString(); - qint64 id = m_model->newId(); - QString name = QString::number(id); - - m_model->m_items.insert(id, name); - m_model->m_childItems[parentId][col].insert(row, id); - - } - } - m_model->endInsertRows(); -} - - -ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) - : ModelChangeCommand(model, parent) -{ - -} -bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) -{ - return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow); -} - -void ModelMoveCommand::doCommand() -{ - QModelIndex srcParent = findIndex(m_rowNumbers); - QModelIndex destParent = findIndex(m_destRowNumbers); - - if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow)) - { - return; - } - - for (int column = 0; column < m_numCols; ++column) - { - QList l = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1 ); - - for (int i = m_startRow; i <= m_endRow ; i++) - { - m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow); - } - int d; - if (m_destRow < m_startRow) - d = m_destRow; - else - { - if (srcParent == destParent) - d = m_destRow - (m_endRow - m_startRow + 1); - else - d = m_destRow - (m_endRow - m_startRow) + 1; - } - - foreach(const qint64 id, l) - { - m_model->m_childItems[destParent.internalId()][column].insert(d++, id); - } - } - - emitPostSignal(); -} - -void ModelMoveCommand::emitPostSignal() -{ - m_model->endMoveRows(); -} - -ModelResetCommand::ModelResetCommand(DynamicTreeModel* model, QObject* parent) - : ModelMoveCommand(model, parent) -{ - -} - -ModelResetCommand::~ModelResetCommand() -{ - -} - -bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) -{ - Q_UNUSED(srcParent); - Q_UNUSED(srcStart); - Q_UNUSED(srcEnd); - Q_UNUSED(destParent); - Q_UNUSED(destRow); - - return true; -} - -void ModelResetCommand::emitPostSignal() -{ - m_model->reset(); -} - -ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent) - : ModelMoveCommand(model, parent) -{ - -} - -ModelResetCommandFixed::~ModelResetCommandFixed() -{ - -} - -bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) -{ - Q_UNUSED(srcParent); - Q_UNUSED(srcStart); - Q_UNUSED(srcEnd); - Q_UNUSED(destParent); - Q_UNUSED(destRow); - - m_model->beginResetModel(); - return true; -} - -void ModelResetCommandFixed::emitPostSignal() -{ - m_model->endResetModel(); -} - diff --git a/tests/auto/modeltest/dynamictreemodel.h b/tests/auto/modeltest/dynamictreemodel.h deleted file mode 100644 index 81ef80cc40..0000000000 --- a/tests/auto/modeltest/dynamictreemodel.h +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Stephen Kelly -** 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 DYNAMICTREEMODEL_H -#define DYNAMICTREEMODEL_H - -#include - -#include -#include - - -class DynamicTreeModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - DynamicTreeModel(QObject *parent = 0); - - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &index = QModelIndex()) const; - int columnCount(const QModelIndex &index = QModelIndex()) const; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - - void clear(); - -protected slots: - - /** - Finds the parent id of the string with id @p searchId. - - Returns -1 if not found. - */ - qint64 findParentId(qint64 searchId) const; - -private: - QHash m_items; - QHash > > m_childItems; - qint64 nextId; - qint64 newId() { return nextId++; }; - - QModelIndex m_nextParentIndex; - int m_nextRow; - - int m_depth; - int maxDepth; - - friend class ModelInsertCommand; - friend class ModelMoveCommand; - friend class ModelResetCommand; - friend class ModelResetCommandFixed; - -}; - - -class ModelChangeCommand : public QObject -{ - Q_OBJECT -public: - - ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 ); - - virtual ~ModelChangeCommand() {} - - void setAncestorRowNumbers(QList rowNumbers) { m_rowNumbers = rowNumbers; } - - QModelIndex findIndex(QList rows); - - void setStartRow(int row) { m_startRow = row; } - - void setEndRow(int row) { m_endRow = row; } - - void setNumCols(int cols) { m_numCols = cols; } - - virtual void doCommand() = 0; - -protected: - DynamicTreeModel* m_model; - QList m_rowNumbers; - int m_numCols; - int m_startRow; - int m_endRow; - -}; - -typedef QList ModelChangeCommandList; - -class ModelInsertCommand : public ModelChangeCommand -{ - Q_OBJECT - -public: - - ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 ); - virtual ~ModelInsertCommand() {} - - virtual void doCommand(); -}; - - -class ModelMoveCommand : public ModelChangeCommand -{ - Q_OBJECT -public: - ModelMoveCommand(DynamicTreeModel *model, QObject *parent); - - virtual ~ModelMoveCommand() {} - - virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); - - virtual void doCommand(); - - virtual void emitPostSignal(); - - void setDestAncestors( QList rows ) { m_destRowNumbers = rows; } - - void setDestRow(int row) { m_destRow = row; } - -protected: - QList m_destRowNumbers; - int m_destRow; -}; - -/** - A command which does a move and emits a reset signal. -*/ -class ModelResetCommand : public ModelMoveCommand -{ - Q_OBJECT -public: - ModelResetCommand(DynamicTreeModel* model, QObject* parent = 0); - - virtual ~ModelResetCommand(); - - virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); - virtual void emitPostSignal(); - -}; - -/** - A command which does a move and emits a beginResetModel and endResetModel signals. -*/ -class ModelResetCommandFixed : public ModelMoveCommand -{ - Q_OBJECT -public: - ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent = 0); - - virtual ~ModelResetCommandFixed(); - - virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); - virtual void emitPostSignal(); - -}; - - -#endif diff --git a/tests/auto/modeltest/modeltest.cpp b/tests/auto/modeltest/modeltest.cpp deleted file mode 100644 index 76803dfbe5..0000000000 --- a/tests/auto/modeltest/modeltest.cpp +++ /dev/null @@ -1,564 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include "modeltest.h" - -#include - -Q_DECLARE_METATYPE ( QModelIndex ) - -/*! - Connect to all of the models signals. Whenever anything happens recheck everything. -*/ -ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) -{ - if (!model) - qFatal("%s: model must not be null", Q_FUNC_INFO); - - connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - - // Special checks for inserting/removing - connect ( model, SIGNAL ( layoutAboutToBeChanged() ), - this, SLOT ( layoutAboutToBeChanged() ) ); - connect ( model, SIGNAL ( layoutChanged() ), - this, SLOT ( layoutChanged() ) ); - - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); - - runAllTests(); -} - -void ModelTest::runAllTests() -{ - if ( fetchingMore ) - return; - nonDestructiveBasicTest(); - rowCount(); - columnCount(); - hasIndex(); - index(); - parent(); - data(); -} - -/*! - nonDestructiveBasicTest tries to call a number of the basic functions (not all) - to make sure the model doesn't outright segfault, testing the functions that makes sense. -*/ -void ModelTest::nonDestructiveBasicTest() -{ - QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() ); - model->canFetchMore ( QModelIndex() ); - QVERIFY( model->columnCount ( QModelIndex() ) >= 0 ); - QVERIFY( model->data ( QModelIndex() ) == QVariant() ); - fetchingMore = true; - model->fetchMore ( QModelIndex() ); - fetchingMore = false; - Qt::ItemFlags flags = model->flags ( QModelIndex() ); - QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 ); - model->hasChildren ( QModelIndex() ); - model->hasIndex ( 0, 0 ); - model->headerData ( 0, Qt::Horizontal ); - model->index ( 0, 0 ); - model->itemData ( QModelIndex() ); - QVariant cache; - model->match ( QModelIndex(), -1, cache ); - model->mimeTypes(); - QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); - QVERIFY( model->rowCount() >= 0 ); - QVariant variant; - model->setData ( QModelIndex(), variant, -1 ); - model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); - model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); - QMap roles; - model->sibling ( 0, 0, QModelIndex() ); - model->span ( QModelIndex() ); - model->supportedDropActions(); -} - -/*! - Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() - - Models that are dynamically populated are not as fully tested here. - */ -void ModelTest::rowCount() -{ -// qDebug() << "rc"; - // check top row - QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); - int rows = model->rowCount ( topIndex ); - QVERIFY( rows >= 0 ); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( topIndex ) ); - - QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); - if ( secondLevelIndex.isValid() ) { // not the top level - // check a row count where parent is valid - rows = model->rowCount ( secondLevelIndex ); - QVERIFY( rows >= 0 ); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( secondLevelIndex ) ); - } - - // The models rowCount() is tested more extensively in checkChildren(), - // but this catches the big mistakes -} - -/*! - Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() - */ -void ModelTest::columnCount() -{ - // check top row - QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); - QVERIFY( model->columnCount ( topIndex ) >= 0 ); - - // check a column count where parent is valid - QModelIndex childIndex = model->index ( 0, 0, topIndex ); - if ( childIndex.isValid() ) - QVERIFY( model->columnCount ( childIndex ) >= 0 ); - - // columnCount() is tested more extensively in checkChildren(), - // but this catches the big mistakes -} - -/*! - Tests model's implementation of QAbstractItemModel::hasIndex() - */ -void ModelTest::hasIndex() -{ -// qDebug() << "hi"; - // Make sure that invalid values returns an invalid index - QVERIFY( !model->hasIndex ( -2, -2 ) ); - QVERIFY( !model->hasIndex ( -2, 0 ) ); - QVERIFY( !model->hasIndex ( 0, -2 ) ); - - int rows = model->rowCount(); - int columns = model->columnCount(); - - // check out of bounds - QVERIFY( !model->hasIndex ( rows, columns ) ); - QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) ); - - if ( rows > 0 ) - QVERIFY( model->hasIndex ( 0, 0 ) ); - - // hasIndex() is tested more extensively in checkChildren(), - // but this catches the big mistakes -} - -/*! - Tests model's implementation of QAbstractItemModel::index() - */ -void ModelTest::index() -{ -// qDebug() << "i"; - // Make sure that invalid values returns an invalid index - QVERIFY( model->index ( -2, -2 ) == QModelIndex() ); - QVERIFY( model->index ( -2, 0 ) == QModelIndex() ); - QVERIFY( model->index ( 0, -2 ) == QModelIndex() ); - - int rows = model->rowCount(); - int columns = model->columnCount(); - - if ( rows == 0 ) - return; - - // Catch off by one errors - QVERIFY( model->index ( rows, columns ) == QModelIndex() ); - QVERIFY( model->index ( 0, 0 ).isValid() ); - - // Make sure that the same index is *always* returned - QModelIndex a = model->index ( 0, 0 ); - QModelIndex b = model->index ( 0, 0 ); - QVERIFY( a == b ); - - // index() is tested more extensively in checkChildren(), - // but this catches the big mistakes -} - -/*! - Tests model's implementation of QAbstractItemModel::parent() - */ -void ModelTest::parent() -{ -// qDebug() << "p"; - // Make sure the model wont crash and will return an invalid QModelIndex - // when asked for the parent of an invalid index. - QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); - - if ( model->rowCount() == 0 ) - return; - - // Column 0 | Column 1 | - // QModelIndex() | | - // \- topIndex | topIndex1 | - // \- childIndex | childIndex1 | - - // Common error test #1, make sure that a top level index has a parent - // that is a invalid QModelIndex. - QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); - QVERIFY( model->parent ( topIndex ) == QModelIndex() ); - - // Common error test #2, make sure that a second level index has a parent - // that is the first level index. - if ( model->rowCount ( topIndex ) > 0 ) { - QModelIndex childIndex = model->index ( 0, 0, topIndex ); - QVERIFY( model->parent ( childIndex ) == topIndex ); - } - - // Common error test #3, the second column should NOT have the same children - // as the first column in a row. - // Usually the second column shouldn't have children. - QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); - if ( model->rowCount ( topIndex1 ) > 0 ) { - QModelIndex childIndex = model->index ( 0, 0, topIndex ); - QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); - QVERIFY( childIndex != childIndex1 ); - } - - // Full test, walk n levels deep through the model making sure that all - // parent's children correctly specify their parent. - checkChildren ( QModelIndex() ); -} - -/*! - Called from the parent() test. - - 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() already 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 ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) -{ - // First just try walking back up the tree. - QModelIndex p = parent; - while ( p.isValid() ) - p = p.parent(); - - // For models that are dynamically populated - if ( model->canFetchMore ( parent ) ) { - fetchingMore = true; - model->fetchMore ( parent ); - fetchingMore = false; - } - - int rows = model->rowCount ( parent ); - int columns = model->columnCount ( parent ); - - if ( rows > 0 ) - QVERIFY( model->hasChildren ( parent ) ); - - // Some further testing against rows(), columns(), and hasChildren() - QVERIFY( rows >= 0 ); - QVERIFY( columns >= 0 ); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( parent ) ); - - //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows - // << "columns:" << columns << "parent column:" << parent.column(); - - QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); - for ( int r = 0; r < rows; ++r ) { - if ( model->canFetchMore ( parent ) ) { - fetchingMore = true; - model->fetchMore ( parent ); - fetchingMore = false; - } - QVERIFY( !model->hasIndex ( r, columns + 1, parent ) ); - for ( int c = 0; c < columns; ++c ) { - QVERIFY( model->hasIndex ( r, c, parent ) ); - QModelIndex index = model->index ( r, c, parent ); - // rowCount() and columnCount() said that it existed... - QVERIFY( index.isValid() ); - - // index() should always return the same index when called twice in a row - QModelIndex modifiedIndex = model->index ( r, c, parent ); - QVERIFY( index == modifiedIndex ); - - // Make sure we get the same index if we request it twice in a row - QModelIndex a = model->index ( r, c, parent ); - QModelIndex b = model->index ( r, c, parent ); - QVERIFY( a == b ); - - // Some basic checking on the index that is returned - QVERIFY( index.model() == model ); - QCOMPARE( index.row(), r ); - QCOMPARE( index.column(), c ); - // While you can technically return a QVariant usually this is a sign - // of a bug in data(). Disable if this really is ok in your model. -// QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() ); - - // If the next test fails here is some somewhat useful debug you play with. - - if (model->parent(index) != parent) { - qDebug() << r << c << currentDepth << model->data(index).toString() - << model->data(parent).toString(); - qDebug() << index << parent << model->parent(index); -// And a view that you can even use to show the model. -// QTreeView view; -// view.setModel(model); -// view.show(); - } - - // Check that we can get back our real parent. - QCOMPARE( model->parent ( index ), parent ); - - // recursively go down the children - if ( model->hasChildren ( index ) && currentDepth < 10 ) { - //qDebug() << r << c << "has children" << model->rowCount(index); - checkChildren ( index, ++currentDepth ); - }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ - - // make sure that after testing the children that the index doesn't change. - QModelIndex newerIndex = model->index ( r, c, parent ); - QVERIFY( index == newerIndex ); - } - } -} - -/*! - Tests model's implementation of QAbstractItemModel::data() - */ -void ModelTest::data() -{ - // Invalid index should return an invalid qvariant - QVERIFY( !model->data ( QModelIndex() ).isValid() ); - - if ( model->rowCount() == 0 ) - return; - - // A valid index should have a valid QVariant data - QVERIFY( model->index ( 0, 0 ).isValid() ); - - // shouldn't be able to set data on an invalid index - QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) ); - - // General Purpose roles that should return a QString - QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); - if ( variant.isValid() ) { - QVERIFY( qVariantCanConvert ( variant ) ); - } - variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); - if ( variant.isValid() ) { - QVERIFY( qVariantCanConvert ( variant ) ); - } - variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); - if ( variant.isValid() ) { - QVERIFY( qVariantCanConvert ( variant ) ); - } - - // General Purpose roles that should return a QSize - variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); - if ( variant.isValid() ) { - QVERIFY( qVariantCanConvert ( variant ) ); - } - - // General Purpose roles that should return a QFont - QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); - if ( fontVariant.isValid() ) { - QVERIFY( qVariantCanConvert ( fontVariant ) ); - } - - // Check that the alignment is one we know about - QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); - if ( textAlignmentVariant.isValid() ) { - int alignment = textAlignmentVariant.toInt(); - QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); - } - - // General Purpose roles that should return a QColor - QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); - if ( colorVariant.isValid() ) { - QVERIFY( qVariantCanConvert ( colorVariant ) ); - } - - colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); - if ( colorVariant.isValid() ) { - QVERIFY( qVariantCanConvert ( colorVariant ) ); - } - - // Check that the "check state" is one we know about. - QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); - if ( checkStateVariant.isValid() ) { - int state = checkStateVariant.toInt(); - QVERIFY( state == Qt::Unchecked || - state == Qt::PartiallyChecked || - state == Qt::Checked ); - } -} - -/*! - Store what is about to be inserted to make sure it actually happens - - \sa rowsInserted() - */ -void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */) -{ -// Q_UNUSED(end); -// qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() -// << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); -// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); - Changing c; - c.parent = parent; - c.oldSize = model->rowCount ( parent ); - c.last = model->data ( model->index ( start - 1, 0, parent ) ); - c.next = model->data ( model->index ( start, 0, parent ) ); - insert.push ( c ); -} - -/*! - Confirm that what was said was going to happen actually did - - \sa rowsAboutToBeInserted() - */ -void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) -{ - Changing c = insert.pop(); - QVERIFY( c.parent == parent ); -// qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize -// << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); - -// for (int ii=start; ii <= end; ii++) -// { -// qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); -// } -// qDebug(); - - QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); - QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); - - if (c.next != model->data(model->index(end + 1, 0, c.parent))) { - qDebug() << start << end; - for (int i=0; i < model->rowCount(); ++i) - qDebug() << model->index(i, 0).data().toString(); - qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); - } - - QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); -} - -void ModelTest::layoutAboutToBeChanged() -{ - for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) - changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); -} - -void ModelTest::layoutChanged() -{ - for ( int i = 0; i < changing.count(); ++i ) { - QPersistentModelIndex p = changing[i]; - QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) ); - } - changing.clear(); -} - -/*! - Store what is about to be inserted to make sure it actually happens - - \sa rowsRemoved() - */ -void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) -{ -qDebug() << "ratbr" << parent << start << end; - Changing c; - c.parent = parent; - c.oldSize = model->rowCount ( parent ); - c.last = model->data ( model->index ( start - 1, 0, parent ) ); - c.next = model->data ( model->index ( end + 1, 0, parent ) ); - remove.push ( c ); -} - -/*! - Confirm that what was said was going to happen actually did - - \sa rowsAboutToBeRemoved() - */ -void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) -{ - qDebug() << "rr" << parent << start << end; - Changing c = remove.pop(); - QVERIFY( c.parent == parent ); - QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); - QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); - QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); -} - - diff --git a/tests/auto/modeltest/modeltest.h b/tests/auto/modeltest/modeltest.h deleted file mode 100644 index e4ef478c5e..0000000000 --- a/tests/auto/modeltest/modeltest.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** 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 MODELTEST_H -#define MODELTEST_H - -#include -#include -#include - -class ModelTest : public QObject -{ - Q_OBJECT - -public: - ModelTest( QAbstractItemModel *model, QObject *parent = 0 ); - -private Q_SLOTS: - void nonDestructiveBasicTest(); - void rowCount(); - void columnCount(); - void hasIndex(); - void index(); - void parent(); - void data(); - -protected Q_SLOTS: - void runAllTests(); - void layoutAboutToBeChanged(); - void layoutChanged(); - void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end ); - void rowsInserted( const QModelIndex & parent, int start, int end ); - void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end ); - void rowsRemoved( const QModelIndex & parent, int start, int end ); - -private: - void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); - - QAbstractItemModel *model; - - struct Changing { - QModelIndex parent; - int oldSize; - QVariant last; - QVariant next; - }; - QStack insert; - QStack remove; - - bool fetchingMore; - - QList changing; -}; - -#endif diff --git a/tests/auto/modeltest/modeltest.pro b/tests/auto/modeltest/modeltest.pro deleted file mode 100644 index d4a8ba971d..0000000000 --- a/tests/auto/modeltest/modeltest.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_modeltest.cpp modeltest.cpp dynamictreemodel.cpp -HEADERS += modeltest.h dynamictreemodel.h - - - diff --git a/tests/auto/modeltest/tst_modeltest.cpp b/tests/auto/modeltest/tst_modeltest.cpp deleted file mode 100644 index 434537a81f..0000000000 --- a/tests/auto/modeltest/tst_modeltest.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#include "modeltest.h" -#include "dynamictreemodel.h" - - -class tst_ModelTest : public QObject -{ - Q_OBJECT - -public: - tst_ModelTest() {} - virtual ~tst_ModelTest() {} - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); - -private slots: - void stringListModel(); - void treeWidgetModel(); - void standardItemModel(); - void testInsertThroughProxy(); - void moveSourceItems(); - void testResetThroughProxy(); -}; - - - -void tst_ModelTest::initTestCase() -{ -} - -void tst_ModelTest::cleanupTestCase() -{ -} - -void tst_ModelTest::init() -{ - -} - -void tst_ModelTest::cleanup() -{ -} -/* - tests -*/ - -void tst_ModelTest::stringListModel() -{ - QStringListModel model; - QSortFilterProxyModel proxy; - - ModelTest t1(&model); - ModelTest t2(&proxy); - - proxy.setSourceModel(&model); - - model.setStringList(QStringList() << "2" << "3" << "1"); - model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c" ); - - proxy.setDynamicSortFilter(true); - proxy.setFilterRegExp(QRegExp("[^b]")); -} - -void tst_ModelTest::treeWidgetModel() -{ - QTreeWidget widget; - - ModelTest t1(widget.model()); - - QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root")); - for (int i = 0; i < 20; ++i) { - new QTreeWidgetItem(root, QStringList(QString::number(i))); - } - QTreeWidgetItem *remove = root->child(2); - root->removeChild(remove); - QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent")); - new QTreeWidgetItem(parent, QStringList("child")); - widget.setItemHidden(parent, true); - - widget.sortByColumn(0); -} - -void tst_ModelTest::standardItemModel() -{ - QStandardItemModel model(10,10); - QSortFilterProxyModel proxy; - - - ModelTest t1(&model); - ModelTest t2(&proxy); - - proxy.setSourceModel(&model); - - model.insertRows(2, 5); - model.removeRows(4, 5); - - model.insertColumns(2, 5); - model.removeColumns(4, 5); - - model.insertRows(0,5, model.index(1,1)); - model.insertColumns(0,5, model.index(1,3)); -} - -void tst_ModelTest::testInsertThroughProxy() -{ - DynamicTreeModel *model = new DynamicTreeModel(this); - - QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); - proxy->setSourceModel(model); - - new ModelTest(proxy, this); - - ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); - insertCommand->setNumCols(4); - insertCommand->setStartRow(0); - insertCommand->setEndRow(9); - // Parent is QModelIndex() - insertCommand->doCommand(); - - insertCommand = new ModelInsertCommand(model, this); - insertCommand->setNumCols(4); - insertCommand->setAncestorRowNumbers(QList() << 5); - insertCommand->setStartRow(0); - insertCommand->setEndRow(9); - insertCommand->doCommand(); - - ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this); - moveCommand->setNumCols(4); - moveCommand->setStartRow(0); - moveCommand->setEndRow(0); - moveCommand->setDestRow(9); - moveCommand->setDestAncestors(QList() << 5); - moveCommand->doCommand(); -} - -/** - Makes the persistent index list publicly accessible -*/ -class AccessibleProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {} - - QModelIndexList persistent() - { - return persistentIndexList(); - } -}; - -class ObservingObject : public QObject -{ - Q_OBJECT -public: - ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0) - : QObject(parent) - , m_proxy(proxy) - , storePersistentFailureCount(0) - , checkPersistentFailureCount(0) - { - connect(m_proxy, SIGNAL(layoutAboutToBeChanged()), SLOT(storePersistent())); - connect(m_proxy, SIGNAL(layoutChanged()), SLOT(checkPersistent())); - } - -public slots: - - void storePersistent(const QModelIndex &parent) - { - for (int row = 0; row < m_proxy->rowCount(parent); ++row) { - QModelIndex proxyIndex = m_proxy->index(row, 0, parent); - QModelIndex sourceIndex = m_proxy->mapToSource(proxyIndex); - if (!proxyIndex.isValid()) { - qWarning("%s: Invalid proxy index", Q_FUNC_INFO); - ++storePersistentFailureCount; - } - if (!sourceIndex.isValid()) { - qWarning("%s: invalid source index", Q_FUNC_INFO); - ++storePersistentFailureCount; - } - m_persistentSourceIndexes.append(sourceIndex); - m_persistentProxyIndexes.append(proxyIndex); - if (m_proxy->hasChildren(proxyIndex)) - storePersistent(proxyIndex); - } - } - - void storePersistent() - { - // This method is called from layoutAboutToBeChanged. Persistent indexes should be valid - foreach(const QModelIndex &idx, m_persistentProxyIndexes) - if (!idx.isValid()) { - qWarning("%s: persistentProxyIndexes contains invalid index", Q_FUNC_INFO); - ++storePersistentFailureCount; - } - - if (!m_proxy->persistent().isEmpty()) { - qWarning("%s: proxy should have no persistent indexes when storePersistent called", - Q_FUNC_INFO); - ++storePersistentFailureCount; - } - storePersistent(QModelIndex()); - if (m_proxy->persistent().isEmpty()) { - qWarning("%s: proxy should have persistent index after storePersistent called", - Q_FUNC_INFO); - ++storePersistentFailureCount; - } - } - - void checkPersistent() - { - for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) { - QModelIndex updatedProxy = m_persistentProxyIndexes.at(row); - QModelIndex updatedSource = m_persistentSourceIndexes.at(row); - } - for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) { - QModelIndex updatedProxy = m_persistentProxyIndexes.at(row); - QModelIndex updatedSource = m_persistentSourceIndexes.at(row); - if (m_proxy->mapToSource(updatedProxy) != updatedSource) { - qWarning("%s: check failed at row %d", Q_FUNC_INFO, row); - ++checkPersistentFailureCount; - } - } - m_persistentSourceIndexes.clear(); - m_persistentProxyIndexes.clear(); - } - -private: - AccessibleProxyModel *m_proxy; - QList m_persistentSourceIndexes; - QList m_persistentProxyIndexes; -public: - int storePersistentFailureCount; - int checkPersistentFailureCount; -}; - -void tst_ModelTest::moveSourceItems() -{ - DynamicTreeModel *model = new DynamicTreeModel(this); - AccessibleProxyModel *proxy = new AccessibleProxyModel(this); - proxy->setSourceModel(model); - - ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); - insertCommand->setStartRow(0); - insertCommand->setEndRow(2); - insertCommand->doCommand(); - - insertCommand = new ModelInsertCommand(model, this); - insertCommand->setAncestorRowNumbers(QList() << 1); - insertCommand->setStartRow(0); - insertCommand->setEndRow(2); - insertCommand->doCommand(); - - ObservingObject observer(proxy); - - ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this); - moveCommand->setStartRow(0); - moveCommand->setEndRow(0); - moveCommand->setDestAncestors(QList() << 1); - moveCommand->setDestRow(0); - moveCommand->doCommand(); - - QCOMPARE(observer.storePersistentFailureCount, 0); - QCOMPARE(observer.checkPersistentFailureCount, 0); -} - -void tst_ModelTest::testResetThroughProxy() -{ - DynamicTreeModel *model = new DynamicTreeModel(this); - - ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); - insertCommand->setStartRow(0); - insertCommand->setEndRow(2); - insertCommand->doCommand(); - - QPersistentModelIndex persistent = model->index(0, 0); - - AccessibleProxyModel *proxy = new AccessibleProxyModel(this); - proxy->setSourceModel(model); - - ObservingObject observer(proxy); - observer.storePersistent(); - - ModelResetCommand *resetCommand = new ModelResetCommand(model, this); - resetCommand->setNumCols(0); - resetCommand->doCommand(); - - QCOMPARE(observer.storePersistentFailureCount, 0); - QCOMPARE(observer.checkPersistentFailureCount, 0); -} - - -QTEST_MAIN(tst_ModelTest) -#include "tst_modeltest.moc" diff --git a/tests/auto/network.pro b/tests/auto/network.pro index 21388bc281..d4d07fa426 100644 --- a/tests/auto/network.pro +++ b/tests/auto/network.pro @@ -5,5 +5,4 @@ TEMPLATE=subdirs SUBDIRS=\ network \ - networkselftest \ qobjectperformance diff --git a/tests/auto/networkselftest/networkselftest.pro b/tests/auto/networkselftest/networkselftest.pro deleted file mode 100644 index 4440dc6cfd..0000000000 --- a/tests/auto/networkselftest/networkselftest.pro +++ /dev/null @@ -1,16 +0,0 @@ -load(qttest_p4) - -SOURCES += tst_networkselftest.cpp -QT = core network - -wince*: { - addFiles.files = rfc3252.txt - addFiles.path = . - DEPLOYMENT += addFiles - DEFINES += SRCDIR=\\\"\\\" -} else:vxworks*: { - DEFINES += SRCDIR=\\\"\\\" -} else { - DEFINES += SRCDIR=\\\"$$PWD/\\\" -} - diff --git a/tests/auto/networkselftest/rfc3252.txt b/tests/auto/networkselftest/rfc3252.txt deleted file mode 100644 index b80c61bf0a..0000000000 --- a/tests/auto/networkselftest/rfc3252.txt +++ /dev/null @@ -1,899 +0,0 @@ - - - - - - -Network Working Group H. Kennedy -Request for Comments: 3252 Mimezine -Category: Informational 1 April 2002 - - - Binary Lexical Octet Ad-hoc Transport - -Status of this Memo - - This memo provides information for the Internet community. It does - not specify an Internet standard of any kind. Distribution of this - memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (2002). All Rights Reserved. - -Abstract - - This document defines a reformulation of IP and two transport layer - protocols (TCP and UDP) as XML applications. - -1. Introduction - -1.1. Overview - - This document describes the Binary Lexical Octet Ad-hoc Transport - (BLOAT): a reformulation of a widely-deployed network-layer protocol - (IP [RFC791]), and two associated transport layer protocols (TCP - [RFC793] and UDP [RFC768]) as XML [XML] applications. It also - describes methods for transporting BLOAT over Ethernet and IEEE 802 - networks as well as encapsulating BLOAT in IP for gatewaying BLOAT - across the public Internet. - -1.2. Motivation - - The wild popularity of XML as a basis for application-level protocols - such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple - Object Access Protocol [SOAP], and Jabber [JABBER] prompted - investigation into the possibility of extending the use of XML in the - protocol stack. Using XML at both the transport and network layer in - addition to the application layer would provide for an amazing amount - of power and flexibility while removing dependencies on proprietary - and hard-to-understand binary protocols. This protocol unification - would also allow applications to use a single XML parser for all - aspects of their operation, eliminating developer time spent figuring - out the intricacies of each new protocol, and moving the hard work of - - - - -Kennedy Informational [Page 1] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - parsing to the XML toolset. The use of XML also mitigates concerns - over "network vs. host" byte ordering which is at the root of many - network application bugs. - -1.3. Relation to Existing Protocols - - The reformulations specified in this RFC follow as closely as - possible the spirit of the RFCs on which they are based, and so MAY - contain elements or attributes that would not be needed in a pure - reworking (e.g. length attributes, which are implicit in XML.) - - The layering of network and transport protocols are maintained in - this RFC despite the optimizations that could be made if the line - were somewhat blurred (i.e. merging TCP and IP into a single, larger - element in the DTD) in order to foster future use of this protocol as - a basis for reformulating other protocols (such as ICMP.) - - Other than the encoding, the behavioral aspects of each of the - existing protocols remain unchanged. Routing, address spaces, TCP - congestion control, etc. behave as specified in the extant standards. - Adapting to new standards and experimental algorithm heuristics for - improving performance will become much easier once the move to BLOAT - has been completed. - -1.4. Requirement Levels - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in BCP 14, RFC 2119 - [RFC2119]. - -2. IPoXML - - This protocol MUST be implemented to be compliant with this RFC. - IPoXML is the root protocol REQUIRED for effective use of TCPoXML - (section 3.) and higher-level application protocols. - - The DTD for this document type can be found in section 7.1. - - The routing of IPoXML can be easily implemented on hosts with an XML - parser, as the regular structure lends itself handily to parsing and - validation of the document/datagram and then processing the - destination address, TTL, and checksum before sending it on to its - next-hop. - - The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the - wider deployment of IPv4 and the fact that implementing IPv6 as XML - would have exceeded the 1500 byte Ethernet MTU. - - - -Kennedy Informational [Page 2] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - All BLOAT implementations MUST use - and specify - the UTF-8 encoding - of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well- - formed and include the XMLDecl. - -2.1. IP Description - - A number of items have changed (for the better) from the original IP - specification. Bit-masks, where present have been converted into - human-readable values. IP addresses are listed in their dotted- - decimal notation [RFC1123]. Length and checksum values are present - as decimal integers. - - To calculate the length and checksum fields of the IP element, a - canonicalized form of the element MUST be used. The canonical form - SHALL have no whitespace (including newline characters) between - elements and only one space character between attributes. There - SHALL NOT be a space following the last attribute in an element. - - An iterative method SHOULD be used to calculate checksums, as the - length field will vary based on the size of the checksum. - - The payload element bears special attention. Due to the character - set restrictions of XML, the payload of IP datagrams (which MAY - contain arbitrary data) MUST be encoded for transport. This RFC - REQUIRES the contents of the payload to be encoded in the base-64 - encoding of RFC 2045 [RFC2045], but removes the requirement that the - encoded output MUST be wrapped on 76-character lines. - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 3] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -2.2. Example Datagram - - The following is an example IPoXML datagram with an empty payload: - - - - -
- - - - - - - - - - - - - - - -
- - -
- -3. TCPoXML - - This protocol MUST be implemented to be compliant with this RFC. The - DTD for this document type can be found in section 7.2. - -3.1. TCP Description - - A number of items have changed from the original TCP specification. - Bit-masks, where present have been converted into human-readable - values. Length and checksum and port values are present as decimal - integers. - - To calculate the length and checksum fields of the TCP element, a - canonicalized form of the element MUST be used as in section 2.1. - - An iterative method SHOULD be used to calculate checksums as in - section 2.1. - - The payload element MUST be encoded as in section 2.1. - - - -Kennedy Informational [Page 4] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - The TCP offset element was expanded to a maximum of 255 from 16 to - allow for the increased size of the header in XML. - - TCPoXML datagrams encapsulated by IPoXML MAY omit the header - as well as the declaration. - -3.2. Example Datagram - - The following is an example TCPoXML datagram with an empty payload: - - - - - - - - - - - - - - - - - - - - - - - - -4. UDPoXML - - This protocol MUST be implemented to be compliant with this RFC. The - DTD for this document type can be found in section 7.3. - -4.1. UDP Description - - A number of items have changed from the original UDP specification. - Bit-masks, where present have been converted into human-readable - values. Length and checksum and port values are present as decimal - integers. - - - - - - - -Kennedy Informational [Page 5] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - To calculate the length and checksum fields of the UDP element, a - canonicalized form of the element MUST be used as in section 2.1. An - iterative method SHOULD be used to calculate checksums as in section - 2.1. - - The payload element MUST be encoded as in section 2.1. - - UDPoXML datagrams encapsulated by IPoXML MAY omit the header - as well as the declaration. - -4.2. Example Datagram - - The following is an example UDPoXML datagram with an empty payload: - - - - - - - - - - - - - - -5. Network Transport - - This document provides for the transmission of BLOAT datagrams over - two common families of physical layer transport. Future RFCs will - address additional transports as routing vendors catch up to the - specification, and we begin to see BLOAT routed across the Internet - backbone. - -5.1. Ethernet - - BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the - exception that the type field of the Ethernet frame MUST contain the - value 0xBEEF. The first 5 octets of the Ethernet frame payload will - be 0x3c 3f 78 6d 6c (" - --> - - - - -Kennedy Informational [Page 7] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 9] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 10] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - - - - - - - - - - - -7.2. TCPoXML DTD - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 11] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 12] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - - - - - - - - - - - - - - - - - - -7.3. UDPoXML DTD - - - - - - - - - - - - - - - -Kennedy Informational [Page 13] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -8. Security Considerations - - XML, as a subset of SGML, has the same security considerations as - specified in SGML Media Types [RFC1874]. Security considerations - that apply to IP, TCP and UDP also likely apply to BLOAT as it does - not attempt to correct for issues not related to message format. - -9. References - - [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt, - February 2002. (Work in Progress) - - [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, - August 1980. - - [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791, - September 1981. - - [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC - 793, September 1981. - - [RFC894] Hornig, C., "Standard for the Transmission of IP - Datagrams over Ethernet Networks.", RFC 894, April 1984. - - [RFC1042] Postel, J. and J. Reynolds, "Standard for the - Transmission of IP Datagrams Over IEEE 802 Networks", STD - 43, RFC 1042, February 1988. - - [RFC1123] Braden, R., "Requirements for Internet Hosts - - Application and Support", RFC 1123, October 1989. - - [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December - 1995. - - [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003, - October 1996. - - [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail - Extensions (MIME) Part One: Format of Internet Message - Bodies", RFC 2045, November 1996. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - - - - -Kennedy Informational [Page 14] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6 - (IPv6) Specification", RFC 2460, December 1998. - - [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core", - RFC 3080, March 2001. - - [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A., - Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D., - "Simple Object Access Protocol (SOAP) 1.1" World Wide Web - Consortium Note, May 2000 http://www.w3.org/TR/SOAP/ - - [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible - Markup Language (XML)" World Wide Web Consortium - Recommendation REC- xml-19980210. - http://www.w3.org/TR/1998/REC-xml-19980210 - -10. Author's Address - - Hugh Kennedy - Mimezine - 1060 West Addison - Chicago, IL 60613 - USA - - EMail: kennedyh@engin.umich.edu - - - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 15] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -11. Full Copyright Statement - - Copyright (C) The Internet Society (2002). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 16] - diff --git a/tests/auto/networkselftest/tst_networkselftest.cpp b/tests/auto/networkselftest/tst_networkselftest.cpp deleted file mode 100644 index 033ee57cdd..0000000000 --- a/tests/auto/networkselftest/tst_networkselftest.cpp +++ /dev/null @@ -1,1029 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -#include - -#ifndef QT_NO_BEARERMANAGEMENT -#include -#include -#include -#endif - -#include "../network-settings.h" - -class tst_NetworkSelfTest: public QObject -{ - Q_OBJECT - QHostAddress cachedIpAddress; -public: - tst_NetworkSelfTest(); - virtual ~tst_NetworkSelfTest(); - - QHostAddress serverIpAddress(); - -private slots: - void initTestCase(); - void hostTest(); - void dnsResolution_data(); - void dnsResolution(); - void serverReachability(); - void remotePortsOpen_data(); - void remotePortsOpen(); - void fileLineEndingTest(); - - // specific protocol tests - void ftpServer(); - void ftpProxyServer(); - void imapServer(); - void httpServer(); - void httpServerFiles_data(); - void httpServerFiles(); - void httpServerCGI_data(); - void httpServerCGI(); -#ifndef QT_NO_OPENSSL - void httpsServer(); -#endif - void httpProxy(); - void httpProxyBasicAuth(); - void httpProxyNtlmAuth(); - void socks5Proxy(); - void socks5ProxyAuth(); - void smbServer(); - - // ssl supported test - void supportsSsl(); -private: -#ifndef QT_NO_BEARERMANAGEMENT - QNetworkConfigurationManager *netConfMan; - QNetworkConfiguration networkConfiguration; - QScopedPointer networkSession; -#endif -}; - -class Chat -{ -public: - enum Type { - Reconnect, - Send, - Expect, - SkipBytes, - DiscardUntil, - DiscardUntilDisconnect, - Disconnect, - RemoteDisconnect, - StartEncryption - }; - Chat(Type t, const QByteArray &d) - : data(d), type(t) - { - } - Chat(Type t, int val = 0) - : value(val), type(t) - { - } - - static inline Chat send(const QByteArray &data) - { return Chat(Send, data); } - static inline Chat expect(const QByteArray &data) - { return Chat(Expect, data); } - static inline Chat discardUntil(const QByteArray &data) - { return Chat(DiscardUntil, data); } - static inline Chat skipBytes(int count) - { return Chat(SkipBytes, count); } - - QByteArray data; - int value; - Type type; -}; - -static QString prettyByteArray(const QByteArray &array) -{ - // any control chars? - QString result; - result.reserve(array.length() + array.length() / 3); - for (int i = 0; i < array.length(); ++i) { - char c = array.at(i); - switch (c) { - case '\n': - result += "\\n"; - continue; - case '\r': - result += "\\r"; - continue; - case '\t': - result += "\\t"; - continue; - case '"': - result += "\\\""; - continue; - default: - break; - } - - if (c < 0x20 || uchar(c) >= 0x7f) { - result += '\\'; - result += QString::number(uchar(c), 8); - } else { - result += c; - } - } - return result; -} - -static bool doSocketRead(QTcpSocket *socket, int minBytesAvailable, int timeout = 4000) -{ - QElapsedTimer timer; - timer.start(); - forever { - if (socket->bytesAvailable() >= minBytesAvailable) - return true; - if (socket->state() == QAbstractSocket::UnconnectedState - || timer.elapsed() >= timeout) - return false; - if (!socket->waitForReadyRead(timeout - timer.elapsed())) - return false; - } -} - -static bool doSocketFlush(QTcpSocket *socket, int timeout = 4000) -{ -#ifndef QT_NO_OPENSSL - QSslSocket *sslSocket = qobject_cast(socket); -#endif - QTime timer; - timer.start(); - forever { - if (socket->bytesToWrite() == 0 -#ifndef QT_NO_OPENSSL - && sslSocket->encryptedBytesToWrite() == 0 -#endif - ) - return true; - if (socket->state() == QAbstractSocket::UnconnectedState - || timer.elapsed() >= timeout) - return false; - if (!socket->waitForBytesWritten(timeout - timer.elapsed())) - return false; - } -} - -static void netChat(int port, const QList &chat) -{ -#ifndef QT_NO_OPENSSL - QSslSocket socket; -#else - QTcpSocket socket; -#endif - - socket.connectToHost(QtNetworkSettings::serverName(), port); - qDebug() << 0 << "Connecting to server on port" << port; - QVERIFY2(socket.waitForConnected(10000), - QString("Failed to connect to server in step 0: %1").arg(socket.errorString()).toLocal8Bit()); - - // now start the chat - QList::ConstIterator it = chat.constBegin(); - for (int i = 1; it != chat.constEnd(); ++it, ++i) { - switch (it->type) { - case Chat::Expect: { - qDebug() << i << "Expecting" << prettyByteArray(it->data); - if (!doSocketRead(&socket, it->data.length())) - QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit()); - - // pop that many bytes off the socket - QByteArray received = socket.read(it->data.length()); - - // is it what we expected? - QVERIFY2(received == it->data, - QString("Did not receive expected data in step %1: data received was:\n%2") - .arg(i).arg(prettyByteArray(received)).toLocal8Bit()); - - break; - } - - case Chat::DiscardUntil: - qDebug() << i << "Discarding until" << prettyByteArray(it->data); - while (true) { - // scan the buffer until we have our string - if (!doSocketRead(&socket, it->data.length())) - QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit()); - - QByteArray buffer; - buffer.resize(socket.bytesAvailable()); - socket.peek(buffer.data(), socket.bytesAvailable()); - - int pos = buffer.indexOf(it->data); - if (pos == -1) { - // data not found, keep trying - continue; - } - - buffer = socket.read(pos + it->data.length()); - qDebug() << i << "Discarded" << prettyByteArray(buffer); - break; - } - break; - - case Chat::SkipBytes: { - qDebug() << i << "Skipping" << it->value << "bytes"; - if (!doSocketRead(&socket, it->value)) - QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit()); - - // now discard the bytes - QByteArray buffer = socket.read(it->value); - qDebug() << i << "Skipped" << prettyByteArray(buffer); - break; - } - - case Chat::Send: { - qDebug() << i << "Sending" << prettyByteArray(it->data); - socket.write(it->data); - if (!doSocketFlush(&socket)) { - QVERIFY2(socket.state() == QAbstractSocket::ConnectedState, - QString("Socket disconnected while sending data in step %1").arg(i).toLocal8Bit()); - QFAIL(QString("Failed to send data in step %1: timeout").arg(i).toLocal8Bit()); - } - break; - } - - case Chat::Disconnect: - qDebug() << i << "Disconnecting from host"; - socket.disconnectFromHost(); - - // is this the last command? - if (it + 1 != chat.constEnd()) - break; - - // fall through: - case Chat::RemoteDisconnect: - case Chat::DiscardUntilDisconnect: - qDebug() << i << "Waiting for remote disconnect"; - if (socket.state() != QAbstractSocket::UnconnectedState) - socket.waitForDisconnected(10000); - QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, - QString("Socket did not disconnect as expected in step %1").arg(i).toLocal8Bit()); - - // any data left? - if (it->type == Chat::DiscardUntilDisconnect) { - QByteArray buffer = socket.readAll(); - qDebug() << i << "Discarded in the process:" << prettyByteArray(buffer); - } - - if (socket.bytesAvailable() != 0) - QFAIL(QString("Unexpected bytes still on buffer when disconnecting in step %1:\n%2") - .arg(i).arg(prettyByteArray(socket.readAll())).toLocal8Bit()); - break; - - case Chat::Reconnect: - qDebug() << i << "Reconnecting to server on port" << port; - socket.connectToHost(QtNetworkSettings::serverName(), port); - QVERIFY2(socket.waitForConnected(10000), - QString("Failed to reconnect to server in step %1: %2").arg(i).arg(socket.errorString()).toLocal8Bit()); - break; - - case Chat::StartEncryption: -#ifdef QT_NO_OPENSSL - QFAIL("Internal error: SSL required for this test"); -#else - qDebug() << i << "Starting client encryption"; - socket.ignoreSslErrors(); - socket.startClientEncryption(); - QVERIFY2(socket.waitForEncrypted(5000), - QString("Failed to start client encryption in step %1: %2").arg(i) - .arg(socket.errorString()).toLocal8Bit()); - break; -#endif - } - } -} - -tst_NetworkSelfTest::tst_NetworkSelfTest() -{ -} - -tst_NetworkSelfTest::~tst_NetworkSelfTest() -{ -} - -QHostAddress tst_NetworkSelfTest::serverIpAddress() -{ - if (cachedIpAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { - // need resolving - QHostInfo resolved = QHostInfo::fromName(QtNetworkSettings::serverName()); - if(resolved.error() != QHostInfo::NoError || - resolved.addresses().isEmpty()) { - qWarning("QHostInfo::fromName failed (%d).", resolved.error()); - return QHostAddress(QHostAddress::Null); - } - cachedIpAddress = resolved.addresses().first(); - } - return cachedIpAddress; -} - -void tst_NetworkSelfTest::initTestCase() -{ -#ifndef QT_NO_BEARERMANAGEMENT - netConfMan = new QNetworkConfigurationManager(this); - networkConfiguration = netConfMan->defaultConfiguration(); - networkSession.reset(new QNetworkSession(networkConfiguration)); - if (!networkSession->isOpen()) { - networkSession->open(); - QVERIFY(networkSession->waitForOpened(30000)); - } -#endif -} - -void tst_NetworkSelfTest::hostTest() -{ - // this is a localhost self-test - QHostInfo localhost = QHostInfo::fromName("localhost"); - QCOMPARE(localhost.error(), QHostInfo::NoError); - QVERIFY(!localhost.addresses().isEmpty()); - - QTcpServer server; - QVERIFY(server.listen()); - - QTcpSocket socket; - socket.connectToHost("127.0.0.1", server.serverPort()); - QVERIFY(socket.waitForConnected(10000)); -} - -void tst_NetworkSelfTest::dnsResolution_data() -{ - QTest::addColumn("hostName"); - QTest::newRow("local-name") << QtNetworkSettings::serverLocalName(); - QTest::newRow("fqdn") << QtNetworkSettings::serverName(); -} - -void tst_NetworkSelfTest::dnsResolution() -{ - QFETCH(QString, hostName); - QHostInfo resolved = QHostInfo::fromName(hostName); - QVERIFY2(resolved.error() == QHostInfo::NoError, - QString("Failed to resolve hostname %1: %2").arg(hostName, resolved.errorString()).toLocal8Bit()); - QVERIFY2(resolved.addresses().size() > 0, "Got 0 addresses for server IP"); - - cachedIpAddress = resolved.addresses().first(); -} - -void tst_NetworkSelfTest::serverReachability() -{ - // check that we get a proper error connecting to port 12346 - QTcpSocket socket; - socket.connectToHost(QtNetworkSettings::serverName(), 12346); - - QTime timer; - timer.start(); - socket.waitForConnected(10000); - QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong"); - - QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!"); - QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError, - QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit()); -} - -void tst_NetworkSelfTest::remotePortsOpen_data() -{ - QTest::addColumn("portNumber"); - QTest::newRow("echo") << 7; - QTest::newRow("daytime") << 13; - QTest::newRow("ftp") << 21; - QTest::newRow("ssh") << 22; - QTest::newRow("imap") << 143; - QTest::newRow("http") << 80; - QTest::newRow("https") << 443; - QTest::newRow("http-proxy") << 3128; - QTest::newRow("http-proxy-auth-basic") << 3129; - QTest::newRow("http-proxy-auth-ntlm") << 3130; - QTest::newRow("socks5-proxy") << 1080; - QTest::newRow("socks5-proxy-auth") << 1081; - QTest::newRow("ftp-proxy") << 2121; - QTest::newRow("smb") << 139; -} - -void tst_NetworkSelfTest::remotePortsOpen() -{ - QFETCH(int, portNumber); - QTcpSocket socket; - socket.connectToHost(QtNetworkSettings::serverName(), portNumber); - - if (!socket.waitForConnected(10000)) { - if (socket.error() == QAbstractSocket::SocketTimeoutError) - QFAIL(QString("Network timeout connecting to the server on port %1").arg(portNumber).toLocal8Bit()); - else - QFAIL(QString("Error connecting to server on port %1: %2").arg(portNumber).arg(socket.errorString()).toLocal8Bit()); - } - QVERIFY(socket.state() == QAbstractSocket::ConnectedState); -} - - -void tst_NetworkSelfTest::fileLineEndingTest() -{ - QString referenceName = SRCDIR "/rfc3252.txt"; - long long expectedReferenceSize = 25962; - - QString lineEndingType("LF"); - - QFile reference(referenceName); - QVERIFY(reference.open(QIODevice::ReadOnly)); - QByteArray byteLine = reference.readLine(); - if(byteLine.endsWith("\r\n")) - lineEndingType = "CRLF"; - else if(byteLine.endsWith("\r")) - lineEndingType = "CR"; - - QString referenceAsTextData; - QFile referenceAsText(referenceName); - QVERIFY(referenceAsText.open(QIODevice::ReadOnly)); - referenceAsTextData = referenceAsText.readAll(); - - QVERIFY2(expectedReferenceSize == referenceAsTextData.length(), QString("Reference file %1 has %2 as line ending and file size not matching - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit()); - QVERIFY2(!lineEndingType.compare("LF"), QString("Reference file %1 has %2 as line ending - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit()); -} - -static QList ftpChat(const QByteArray &userSuffix = QByteArray()) -{ - QList rv; - rv << Chat::expect("220") - << Chat::discardUntil("\r\n") - << Chat::send("USER anonymous" + userSuffix + "\r\n") - << Chat::expect("331") - << Chat::discardUntil("\r\n") - << Chat::send("PASS user@hostname\r\n") - << Chat::expect("230") - << Chat::discardUntil("\r\n") - - << Chat::send("CWD pub\r\n") - << Chat::expect("250") - << Chat::discardUntil("\r\n") - << Chat::send("CWD dir-not-readable\r\n") - << Chat::expect("550") - << Chat::discardUntil("\r\n") - << Chat::send("PWD\r\n") - << Chat::expect("257 \"/pub\"\r\n") - << Chat::send("SIZE file-not-readable.txt\r\n") - << Chat::expect("213 41\r\n") - << Chat::send("CWD qxmlquery\r\n") - << Chat::expect("250") - << Chat::discardUntil("\r\n") - - << Chat::send("CWD /qtest\r\n") - << Chat::expect("250") - << Chat::discardUntil("\r\n") - << Chat::send("SIZE bigfile\r\n") - << Chat::expect("213 519240\r\n") - << Chat::send("SIZE rfc3252\r\n") - << Chat::expect("213 25962\r\n") - << Chat::send("SIZE rfc3252.txt\r\n") - << Chat::expect("213 25962\r\n") -// << Chat::send("SIZE nonASCII/german_\344\366\374\304\326\334\337\r\n") -// << Chat::expect("213 40\r\n") - - << Chat::send("QUIT\r\n"); - rv << Chat::expect("221") - << Chat::discardUntil("\r\n"); - - rv << Chat::RemoteDisconnect; - return rv; -} - -void tst_NetworkSelfTest::ftpServer() -{ - netChat(21, ftpChat()); -} - -void tst_NetworkSelfTest::ftpProxyServer() -{ - netChat(2121, ftpChat("@" + QtNetworkSettings::serverName().toLatin1())); -} - -void tst_NetworkSelfTest::imapServer() -{ - netChat(143, QList() - << Chat::expect("* OK ") - << Chat::discardUntil("\r\n") - << Chat::send("1 CAPABILITY\r\n") - << Chat::expect("* CAPABILITY ") - << Chat::discardUntil("1 OK") - << Chat::discardUntil("\r\n") - << Chat::send("2 LOGOUT\r\n") - << Chat::discardUntil("2 OK") - << Chat::discardUntil("\r\n") - << Chat::RemoteDisconnect); -} - -void tst_NetworkSelfTest::httpServer() -{ - QString uniqueExtension; - qsrand(time(0)); -#ifndef Q_OS_WINCE - uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(qrand()).arg((qulonglong)time(0)); -#else - uniqueExtension = QString("%1%2").arg((qulonglong)this).arg(qrand()); -#endif - - netChat(80, QList() - // HTTP/0.9 chat: - << Chat::send("GET /\r\n") - << Chat::DiscardUntilDisconnect - - // HTTP/1.0 chat: - << Chat::Reconnect - << Chat::send("GET / HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect - - // HTTP/1.0 POST: - << Chat::Reconnect - << Chat::send("POST / HTTP/1.0\r\n" - "Content-Length: 5\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n" - "Hello") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect - - // HTTP protected area - << Chat::Reconnect - << Chat::send("GET /qtest/protected/rfc3252.txt HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("401 ") - << Chat::DiscardUntilDisconnect - - << Chat::Reconnect - << Chat::send("HEAD /qtest/protected/rfc3252.txt HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect - - // DAV area - << Chat::Reconnect - << Chat::send("HEAD /dav/ HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect - - // HTTP/1.0 PUT - << Chat::Reconnect - << Chat::send("PUT /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" - "Content-Length: 5\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n" - "Hello") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("201 ") - << Chat::DiscardUntilDisconnect - - // check that the file did get uploaded - << Chat::Reconnect - << Chat::send("HEAD /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::discardUntil("\r\nContent-Length: 5\r\n") - << Chat::DiscardUntilDisconnect - - // HTTP/1.0 DELETE - << Chat::Reconnect - << Chat::send("DELETE /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("204 ") - << Chat::DiscardUntilDisconnect - ); -} - -void tst_NetworkSelfTest::httpServerFiles_data() -{ - QTest::addColumn("uri"); - QTest::addColumn("size"); - - QTest::newRow("fluke.gif") << "/qtest/fluke.gif" << -1; - QTest::newRow("bigfile") << "/qtest/bigfile" << 519240; - QTest::newRow("rfc3252.txt") << "/qtest/rfc3252.txt" << 25962; - QTest::newRow("protected/rfc3252.txt") << "/qtest/protected/rfc3252.txt" << 25962; - QTest::newRow("completelyEmptyQuery.xq") << "/qtest/qxmlquery/completelyEmptyQuery.xq" << -1; - QTest::newRow("notWellformedViaHttps.xml") << "/qtest/qxmlquery/notWellformedViaHttps.xml" << -1; - QTest::newRow("notWellformed.xml") << "/qtest/qxmlquery/notWellformed.xml" << -1; - QTest::newRow("viaHttp.xq") << "/qtest/qxmlquery/viaHttp.xq" << -1; - QTest::newRow("wellFormedViaHttps.xml") << "/qtest/qxmlquery/wellFormedViaHttps.xml" << -1; - QTest::newRow("wellFormed.xml") << "/qtest/qxmlquery/wellFormed.xml" << -1; -} - -void tst_NetworkSelfTest::httpServerFiles() -{ - QFETCH(QString, uri); - QFETCH(int, size); - - QList chat; - chat << Chat::send("HEAD " + QUrl::toPercentEncoding(uri, "/") + " HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::skipBytes(1) // HTTP/1.0 or 1.1 reply - << Chat::expect(" 200 "); - if (size != -1) - chat << Chat::discardUntil("\r\nContent-Length: " + QByteArray::number(size) + "\r\n"); - chat << Chat::DiscardUntilDisconnect; - netChat(80, chat); -} - -void tst_NetworkSelfTest::httpServerCGI_data() -{ - QTest::addColumn("request"); - QTest::addColumn("result"); - QTest::addColumn("additionalHeader"); - - QTest::newRow("echo.cgi") - << QByteArray("GET /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n" - "Connection: close\r\n" - "\r\n") - << QByteArray("Hello+World") - << QByteArray(); - - QTest::newRow("echo.cgi(POST)") - << QByteArray("POST /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n" - "Connection: close\r\n" - "Content-Length: 15\r\n" - "\r\n" - "Hello, World!\r\n") - << QByteArray("Hello, World!\r\n") - << QByteArray(); - - QTest::newRow("md5sum.cgi") - << QByteArray("POST /qtest/cgi-bin/md5sum.cgi HTTP/1.0\r\n" - "Connection: close\r\n" - "Content-Length: 15\r\n" - "\r\n" - "Hello, World!\r\n") - << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n") - << QByteArray(); - - QTest::newRow("protected/md5sum.cgi") - << QByteArray("POST /qtest/protected/cgi-bin/md5sum.cgi HTTP/1.0\r\n" - "Connection: close\r\n" - "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" - "Content-Length: 15\r\n" - "\r\n" - "Hello, World!\r\n") - << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n") - << QByteArray(); - - QTest::newRow("set-cookie.cgi") - << QByteArray("POST /qtest/cgi-bin/set-cookie.cgi HTTP/1.0\r\n" - "Connection: close\r\n" - "Content-Length: 8\r\n" - "\r\n" - "foo=bar\n") - << QByteArray("Success\n") - << QByteArray("\r\nSet-Cookie: foo=bar\r\n"); -} - -void tst_NetworkSelfTest::httpServerCGI() -{ - QFETCH(QByteArray, request); - QFETCH(QByteArray, result); - QFETCH(QByteArray, additionalHeader); - QList chat; - chat << Chat::send(request) - << Chat::expect("HTTP/1.") << Chat::skipBytes(1) - << Chat::expect(" 200 "); - - if (!additionalHeader.isEmpty()) - chat << Chat::discardUntil(additionalHeader); - - chat << Chat::discardUntil("\r\n\r\n") - << Chat::expect(result) - << Chat::RemoteDisconnect; - netChat(80, chat); -} - -#ifndef QT_NO_OPENSSL -void tst_NetworkSelfTest::httpsServer() -{ - netChat(443, QList() - << Chat::StartEncryption - << Chat::send("GET / HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect); -} -#endif - -void tst_NetworkSelfTest::httpProxy() -{ - netChat(3128, QList() - // proxy GET by IP - << Chat::send("GET http://" + serverIpAddress().toString().toLatin1() + "/ HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Proxy-connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect - - // proxy GET by hostname - << Chat::Reconnect - << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Proxy-connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect - - // proxy CONNECT by IP - << Chat::Reconnect - << Chat::send("CONNECT " + serverIpAddress().toString().toLatin1() + ":21 HTTP/1.0\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::discardUntil("\r\n\r\n") - << ftpChat() - - // proxy CONNECT by hostname - << Chat::Reconnect - << Chat::send("CONNECT " + QtNetworkSettings::serverName().toLatin1() + ":21 HTTP/1.0\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::discardUntil("\r\n\r\n") - << ftpChat() - ); -} - -void tst_NetworkSelfTest::httpProxyBasicAuth() -{ - netChat(3129, QList() - // test auth required response - << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Proxy-connection: close\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("407 ") - << Chat::discardUntil("\r\nProxy-Authenticate: Basic realm=\"") - << Chat::DiscardUntilDisconnect - - // now try sending our credentials - << Chat::Reconnect - << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Proxy-connection: close\r\n" - "Proxy-Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n" - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("200 ") - << Chat::DiscardUntilDisconnect); -} - -void tst_NetworkSelfTest::httpProxyNtlmAuth() -{ - netChat(3130, QList() - // test auth required response - << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n" - "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n" - "Proxy-connection: keep-alive\r\n" // NTLM auth will disconnect - "\r\n") - << Chat::expect("HTTP/1.") - << Chat::discardUntil(" ") - << Chat::expect("407 ") - << Chat::discardUntil("\r\nProxy-Authenticate: NTLM\r\n") - << Chat::DiscardUntilDisconnect - ); -} - -// SOCKSv5 is a binary protocol -static const char handshakeNoAuth[] = "\5\1\0"; -static const char handshakeOkNoAuth[] = "\5\0"; -static const char handshakeAuthPassword[] = "\5\1\2\1\12qsockstest\10password"; -static const char handshakeOkPasswdAuth[] = "\5\2\1\0"; -static const char handshakeAuthNotOk[] = "\5\377"; -static const char connect1[] = "\5\1\0\1\177\0\0\1\0\25"; // Connect IPv4 127.0.0.1 port 21 -static const char connect1a[] = "\5\1\0\1"; // just "Connect to IPv4" -static const char connect1b[] = "\0\25"; // just "port 21" -static const char connect2[] = "\5\1\0\3\11localhost\0\25"; // Connect hostname localhost 21 -static const char connect2a[] = "\5\1\0\3"; // just "Connect to hostname" -static const char connected[] = "\5\0\0"; - -#define QBA(x) (QByteArray::fromRawData(x, -1 + sizeof(x))) - -void tst_NetworkSelfTest::socks5Proxy() -{ - union { - char buf[4]; - quint32 data; - } ip4Address; - ip4Address.data = qToBigEndian(serverIpAddress().toIPv4Address()); - - netChat(1080, QList() - // IP address connection - << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) - << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) - << Chat::send(QByteArray(connect1, -1 + sizeof connect1)) - << Chat::expect(QByteArray(connected, -1 + sizeof connected)) - << Chat::expect("\1") // IPv4 address following - << Chat::skipBytes(6) // the server's local address and port - << ftpChat() - - // connect by IP - << Chat::Reconnect - << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) - << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) - << Chat::send(QBA(connect1a) + QByteArray::fromRawData(ip4Address.buf, 4) + QBA(connect1b)) - << Chat::expect(QByteArray(connected, -1 + sizeof connected)) - << Chat::expect("\1") // IPv4 address following - << Chat::skipBytes(6) // the server's local address and port - << ftpChat() - - // connect to "localhost" by hostname - << Chat::Reconnect - << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) - << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) - << Chat::send(QByteArray(connect2, -1 + sizeof connect2)) - << Chat::expect(QByteArray(connected, -1 + sizeof connected)) - << Chat::expect("\1") // IPv4 address following - << Chat::skipBytes(6) // the server's local address and port - << ftpChat() - - // connect to server by its official name - << Chat::Reconnect - << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) - << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth)) - << Chat::send(QBA(connect2a) + char(QtNetworkSettings::serverName().size()) + QtNetworkSettings::serverName().toLatin1() + QBA(connect1b)) - << Chat::expect(QByteArray(connected, -1 + sizeof connected)) - << Chat::expect("\1") // IPv4 address following - << Chat::skipBytes(6) // the server's local address and port - << ftpChat() - ); -} - -void tst_NetworkSelfTest::socks5ProxyAuth() -{ - netChat(1081, QList() - // unauthenticated connect -- will get error - << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth)) - << Chat::expect(QByteArray(handshakeAuthNotOk, -1 + sizeof handshakeAuthNotOk)) - << Chat::RemoteDisconnect - - // now try to connect with authentication - << Chat::Reconnect - << Chat::send(QByteArray(handshakeAuthPassword, -1 + sizeof handshakeAuthPassword)) - << Chat::expect(QByteArray(handshakeOkPasswdAuth, -1 + sizeof handshakeOkPasswdAuth)) - << Chat::send(QByteArray(connect1, -1 + sizeof connect1)) - << Chat::expect(QByteArray(connected, -1 + sizeof connected)) - << Chat::expect("\1") // IPv4 address following - << Chat::skipBytes(6) // the server's local address and port - << ftpChat() - ); -} - -void tst_NetworkSelfTest::supportsSsl() -{ -#ifdef QT_NO_OPENSSL - QFAIL("SSL not compiled in"); -#else - QVERIFY2(QSslSocket::supportsSsl(), "Could not load SSL libraries"); -#endif -} - -void tst_NetworkSelfTest::smbServer() -{ - static const char contents[] = "This is 34 bytes. Do not change..."; -#ifdef Q_OS_WIN - // use Windows's native UNC support to try and open a file on the server - QString filepath = QString("\\\\%1\\testshare\\test.pri").arg(QtNetworkSettings::winServerName()); - FILE *f = fopen(filepath.toLatin1(), "rb"); - QVERIFY2(f, qt_error_string().toLocal8Bit()); - - char buf[128]; - size_t ret = fread(buf, 1, sizeof buf, f); - fclose(f); - - QCOMPARE(ret, strlen(contents)); - QVERIFY(memcmp(buf, contents, strlen(contents)) == 0); -#else - // try to use Samba - QString progname = "smbclient"; - QProcess smbclient; - smbclient.start(progname, QIODevice::ReadOnly); - if (!smbclient.waitForStarted(2000)) - QSKIP("Could not find smbclient (from Samba), cannot continue testing", SkipAll); - if (!smbclient.waitForFinished(2000) || smbclient.exitStatus() != QProcess::NormalExit) - QSKIP("smbclient isn't working, cannot continue testing", SkipAll); - smbclient.close(); - - // try listing the server - smbclient.start(progname, QStringList() << "-g" << "-N" << "-L" << QtNetworkSettings::winServerName(), QIODevice::ReadOnly); - QVERIFY(smbclient.waitForFinished(5000)); - if (smbclient.exitStatus() != QProcess::NormalExit) - QSKIP("smbclient crashed", SkipAll); - QVERIFY2(smbclient.exitCode() == 0, "Test server not found"); - - QByteArray output = smbclient.readAll(); - QVERIFY(output.contains("Disk|testshare|")); - QVERIFY(output.contains("Disk|testsharewritable|")); - QVERIFY(output.contains("Disk|testsharelargefile|")); - qDebug() << "Test server found and shares are correct"; - - // try getting a file - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("PAGER", "/bin/cat"); // just in case - smbclient.setProcessEnvironment(env); - smbclient.start(progname, QStringList() << "-N" << "-c" << "more test.pri" - << QString("\\\\%1\\testshare").arg(QtNetworkSettings::winServerName()), QIODevice::ReadOnly); - QVERIFY(smbclient.waitForFinished(5000)); - if (smbclient.exitStatus() != QProcess::NormalExit) - QSKIP("smbclient crashed", SkipAll); - QVERIFY2(smbclient.exitCode() == 0, "File //qt-test-server/testshare/test.pri not found"); - - output = smbclient.readAll(); - QCOMPARE(output.constData(), contents); - qDebug() << "Test file is correct"; -#endif -} - -QTEST_MAIN(tst_NetworkSelfTest) -#include "tst_networkselftest.moc" diff --git a/tests/auto/other.pro b/tests/auto/other.pro index 5848cdb755..f15811940b 100644 --- a/tests/auto/other.pro +++ b/tests/auto/other.pro @@ -4,45 +4,4 @@ TEMPLATE=subdirs SUBDIRS=\ other \ -# baselineexample \ Just an example demonstrating qbaselinetest usage - exceptionsafety_objects \ - lancelot \ - macgui \ - macnativeevents \ - macplist \ - qaccessibility \ - qcombobox \ - qdirectpainter \ - qfocusevent \ - qlayout \ - qmdiarea \ - qmenu \ - qmenubar \ - qmultiscreen \ - qsplitter \ - qtabwidget \ - qtextbrowser \ - qtextedit \ - qtoolbutton \ - qwidget \ - qworkspace \ - windowsmobile \ qmetaobjectbuilder - -wince*|!contains(QT_CONFIG, accessibility):SUBDIRS -= qaccessibility - -!mac|qpa: SUBDIRS -= \ - macgui \ - macnativeevents \ - macplist \ - -!embedded|wince*: SUBDIRS -= \ - qdirectpainter \ - qmultiscreen \ - -!linux*-g++*:SUBDIRS -= exceptionsafety_objects - -# Following tests depends on private API -!contains(QT_CONFIG, private_tests): SUBDIRS -= \ - qcombobox \ - qtextedit \ diff --git a/tests/auto/qabstractbutton/.gitignore b/tests/auto/qabstractbutton/.gitignore deleted file mode 100644 index 82f669574c..0000000000 --- a/tests/auto/qabstractbutton/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractbutton diff --git a/tests/auto/qabstractbutton/qabstractbutton.pro b/tests/auto/qabstractbutton/qabstractbutton.pro deleted file mode 100644 index 15d90ed4e1..0000000000 --- a/tests/auto/qabstractbutton/qabstractbutton.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstractbutton.cpp - - diff --git a/tests/auto/qabstractbutton/tst_qabstractbutton.cpp b/tests/auto/qabstractbutton/tst_qabstractbutton.cpp deleted file mode 100644 index f5f60c8fd3..0000000000 --- a/tests/auto/qabstractbutton/tst_qabstractbutton.cpp +++ /dev/null @@ -1,650 +0,0 @@ -/**************************************************************************** -** -** 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 - - - -#include -#include -#include -#include -#include -#include - - - -#include - -//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("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("&ersand"); - QCOMPARE( testWidget->text(), QString("&ersand") ); -#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/qabstractitemview/.gitignore b/tests/auto/qabstractitemview/.gitignore deleted file mode 100644 index 2f9f90e27e..0000000000 --- a/tests/auto/qabstractitemview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractitemview diff --git a/tests/auto/qabstractitemview/qabstractitemview.pro b/tests/auto/qabstractitemview/qabstractitemview.pro deleted file mode 100644 index 7f6c2cb65c..0000000000 --- a/tests/auto/qabstractitemview/qabstractitemview.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstractitemview.cpp diff --git a/tests/auto/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/qabstractitemview/tst_qabstractitemview.cpp deleted file mode 100644 index b9c652f1d3..0000000000 --- a/tests/auto/qabstractitemview/tst_qabstractitemview.cpp +++ /dev/null @@ -1,1504 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//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 ¤t, 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(&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("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(new QListView()); - else if (viewType == "QTableView") - view = reinterpret_cast(new QTableView()); - else if (viewType == "QTreeView") - view = reinterpret_cast(new QTreeView()); - else if (viewType == "QHeaderView") - view = reinterpret_cast(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("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(new QListView()); - else if (viewType == "QTableView") - view = reinterpret_cast(new QTableView()); - else if (viewType == "QTreeView") - view = reinterpret_cast(new QTreeView()); - else if (viewType == "QHeaderView") - view = reinterpret_cast(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 list = qFindChildren(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(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 IntList; -Q_DECLARE_METATYPE(IntList) - -void tst_QAbstractItemView::setItemDelegate_data() -{ - // default is rows, a -1 will switch to columns - QTest::addColumn("rowsOrColumnsWithDelegate"); - QTest::addColumn("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("viewType"); - QTest::addColumn("itemFlags"); - QTest::addColumn("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(new QListView()); - else if (viewType == "QTableView") - view = reinterpret_cast(new QTableView()); - else if (viewType == "QTreeView") - view = reinterpret_cast(new QTreeView()); - else if (viewType == "QHeaderView") - view = reinterpret_cast(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 lineEditors = qFindChildren(treeView.viewport()); - QCOMPARE(lineEditors.count(), 1); - QVERIFY(!lineEditors.first()->size().isEmpty()); - - QTest::qWait(30); - - treeView.edit(model.index(1,0)); - lineEditors = qFindChildren(treeView.viewport()); - QCOMPARE(lineEditors.count(), 1); - QVERIFY(!lineEditors.first()->size().isEmpty()); - - QTest::qWait(30); - - treeView.edit(model.index(2,0)); - lineEditors = qFindChildren(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(&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/qabstractprintdialog/.gitignore b/tests/auto/qabstractprintdialog/.gitignore deleted file mode 100644 index a768494da5..0000000000 --- a/tests/auto/qabstractprintdialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractprintdialog diff --git a/tests/auto/qabstractprintdialog/qabstractprintdialog.pro b/tests/auto/qabstractprintdialog/qabstractprintdialog.pro deleted file mode 100644 index fb72bbf7a9..0000000000 --- a/tests/auto/qabstractprintdialog/qabstractprintdialog.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# 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/qabstractprintdialog/tst_qabstractprintdialog.cpp b/tests/auto/qabstractprintdialog/tst_qabstractprintdialog.cpp deleted file mode 100644 index 5d6165d174..0000000000 --- a/tests/auto/qabstractprintdialog/tst_qabstractprintdialog.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -//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/qabstractproxymodel/.gitignore b/tests/auto/qabstractproxymodel/.gitignore deleted file mode 100644 index bffc04d632..0000000000 --- a/tests/auto/qabstractproxymodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractproxymodel diff --git a/tests/auto/qabstractproxymodel/qabstractproxymodel.pro b/tests/auto/qabstractproxymodel/qabstractproxymodel.pro deleted file mode 100644 index 7a6a841796..0000000000 --- a/tests/auto/qabstractproxymodel/qabstractproxymodel.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstractproxymodel.cpp diff --git a/tests/auto/qabstractproxymodel/tst_qabstractproxymodel.cpp b/tests/auto/qabstractproxymodel/tst_qabstractproxymodel.cpp deleted file mode 100644 index b6557c45ec..0000000000 --- a/tests/auto/qabstractproxymodel/tst_qabstractproxymodel.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -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("proxyIndex"); - QTest::addColumn("role"); - QTest::addColumn("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("index"); - QTest::addColumn("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("section"); - QTest::addColumn("orientation"); - QTest::addColumn("role"); - QTest::addColumn("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("index"); - QTest::addColumn("count"); - - QTest::newRow("null") << QModelIndex() << 0; -} - -// public QMap 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("sourceIndex"); - QTest::addColumn("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("selection"); - QTest::addColumn("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("selection"); - QTest::addColumn("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("proxyIndex"); - QTest::addColumn("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("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("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(sourceModel)); - - QStandardItemModel *sourceModel2 = new QStandardItemModel(&model); - model.setSourceModel(sourceModel2); - QCOMPARE(model.sourceModel(), static_cast(sourceModel2)); - - delete sourceModel2; - QCOMPARE(model.sourceModel(), static_cast(0)); -} - -void tst_QAbstractProxyModel::submit_data() -{ - QTest::addColumn("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 _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 _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 &superSet, const QHash &subSet) -{ - QHash::const_iterator it = subSet.constBegin(); - const QHash::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 rootModelRoleNames = model.roleNames(); - QHash 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 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 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/qabstractscrollarea/.gitignore b/tests/auto/qabstractscrollarea/.gitignore deleted file mode 100644 index ab753b8a0a..0000000000 --- a/tests/auto/qabstractscrollarea/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractscrollarea diff --git a/tests/auto/qabstractscrollarea/qabstractscrollarea.pro b/tests/auto/qabstractscrollarea/qabstractscrollarea.pro deleted file mode 100644 index e4bc3f6495..0000000000 --- a/tests/auto/qabstractscrollarea/qabstractscrollarea.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qabstractscrollarea.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstractscrollarea.cpp - - diff --git a/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp deleted file mode 100644 index 5c9a33cdc6..0000000000 --- a/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include - -//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 vbar = scrollArea.verticalScrollBar(); - QPointer 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("dir"); - QTest::addColumn("key"); - QTest::addColumn("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/qabstractslider/.gitignore b/tests/auto/qabstractslider/.gitignore deleted file mode 100644 index cdbb891214..0000000000 --- a/tests/auto/qabstractslider/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractslider diff --git a/tests/auto/qabstractslider/qabstractslider.pro b/tests/auto/qabstractslider/qabstractslider.pro deleted file mode 100644 index 4507859ace..0000000000 --- a/tests/auto/qabstractslider/qabstractslider.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstractslider.cpp - - diff --git a/tests/auto/qabstractslider/tst_qabstractslider.cpp b/tests/auto/qabstractslider/tst_qabstractslider.cpp deleted file mode 100644 index e78844524e..0000000000 --- a/tests/auto/qabstractslider/tst_qabstractslider.cpp +++ /dev/null @@ -1,1247 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -// 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) -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("sliderAction"); - QTest::addColumn("maximum"); - QTest::addColumn("minimum"); - QTest::addColumn("initialSliderPosition"); - QTest::addColumn("singleStep"); - QTest::addColumn("pageStep"); - QTest::addColumn("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(&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("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("expectedMinimum"); - QTest::addColumn("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("initialSliderPosition"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("stepSize"); - QTest::addColumn("pageSize"); - QTest::addColumn >("keySequence"); - QTest::addColumn("expectedSliderPositionHorizontal"); - QTest::addColumn("expectedSliderPositionVertical"); - QTest::addColumn("expectedSliderPositionHorizontalInverted"); // :) - QTest::addColumn("expectedSliderPositionVerticalInverted"); - - - QList 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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, 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;isliderPosition(), 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;isliderPosition(), 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;isliderPosition(), 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;isliderPosition(), expectedSliderPositionVerticalInverted); -} - -void tst_QAbstractSlider::wheelEvent_data() -{ - QTest::addColumn("initialSliderPosition"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("singleStep"); - QTest::addColumn("pageStep"); - QTest::addColumn("invertedControls"); - QTest::addColumn("wheelScrollLines"); - QTest::addColumn("withModifiers"); // use keyboard modifiers while scrolling? (CTRL and SHIFT) - QTest::addColumn("deltaMultiple"); // multiples of WHEEL_DELTA - QTest::addColumn("sliderOrientation"); - QTest::addColumn("wheelOrientation"); - QTest::addColumn("expectedSliderPosition"); - QTest::addColumn("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(&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(&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("control"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("subControl"); - QTest::addColumn("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("control"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("position"); - QTest::addColumn("sliderDown"); - QTest::addColumn("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("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("newMin"); - QTest::addColumn("newMax"); - QTest::addColumn("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("tracking"); - QTest::addColumn("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("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/qabstractspinbox/.gitignore b/tests/auto/qabstractspinbox/.gitignore deleted file mode 100644 index 07d1d652ee..0000000000 --- a/tests/auto/qabstractspinbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qabstractspinbox diff --git a/tests/auto/qabstractspinbox/qabstractspinbox.pro b/tests/auto/qabstractspinbox/qabstractspinbox.pro deleted file mode 100644 index e156b2493d..0000000000 --- a/tests/auto/qabstractspinbox/qabstractspinbox.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qabstractspinbox.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qabstractspinbox.cpp - - diff --git a/tests/auto/qabstractspinbox/tst_qabstractspinbox.cpp b/tests/auto/qabstractspinbox/tst_qabstractspinbox.cpp deleted file mode 100644 index d14c75bbac..0000000000 --- a/tests/auto/qabstractspinbox/tst_qabstractspinbox.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include - - -//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/qaccessibility/.gitignore b/tests/auto/qaccessibility/.gitignore deleted file mode 100644 index 6fd6ae2d48..0000000000 --- a/tests/auto/qaccessibility/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qaccessibility diff --git a/tests/auto/qaccessibility/qaccessibility.pro b/tests/auto/qaccessibility/qaccessibility.pro deleted file mode 100644 index ae046cc3c3..0000000000 --- a/tests/auto/qaccessibility/qaccessibility.pro +++ /dev/null @@ -1,12 +0,0 @@ -load(qttest_p4) -requires(contains(QT_CONFIG,accessibility)) -QT += widgets -SOURCES += tst_qaccessibility.cpp - -unix:!mac:LIBS+=-lm - -wince*: { - accessneeded.files = $$QT_BUILD_TREE\\plugins\\accessible\\*.dll - accessneeded.path = accessible - DEPLOYMENT += accessneeded -} diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp deleted file mode 100644 index e1bd968534..0000000000 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ /dev/null @@ -1,3372 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#if defined(Q_OS_WIN) && defined(interface) -# undef interface -#endif - - -#include "QtTest/qtestaccessible.h" - -#if defined(Q_OS_WINCE) -extern "C" bool SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); -#define SPI_GETPLATFORMTYPE 257 -inline bool IsValidCEPlatform() { - wchar_t tszPlatform[64]; - if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(*tszPlatform), tszPlatform, 0)) { - QString platform = QString::fromWCharArray(tszPlatform); - if ((platform == QLatin1String("PocketPC")) || (platform == QLatin1String("Smartphone"))) - return false; - } - return true; -} -#endif - -static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface, - int index, const QRect &domain) -{ - if (!child) { - qWarning("tst_QAccessibility::verifyChild: null pointer to child."); - return false; - } - - if (!interface) { - qWarning("tst_QAccessibility::verifyChild: null pointer to interface."); - return false; - } - - // Verify that we get a valid QAccessibleInterface for the child. - QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(child); - if (!childInterface) { - qWarning("tst_QAccessibility::verifyChild: Failed to retrieve interface for child."); - return false; - } - - // QAccessibleInterface::indexOfChild(): - // Verify that indexOfChild() returns an index equal to the index passed in - int indexFromIndexOfChild = interface->indexOfChild(childInterface); - delete childInterface; - if (indexFromIndexOfChild != index) { - qWarning("tst_QAccessibility::verifyChild (indexOfChild()):"); - qWarning() << "Expected:" << index; - qWarning() << "Actual: " << indexFromIndexOfChild; - return false; - } - - // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child). - QAccessibleInterface *navigatedChildInterface = interface->child(index - 1); - if (navigatedChildInterface == 0) - return false; - - const QRect rectFromInterface = navigatedChildInterface->rect(); - delete navigatedChildInterface; - - // QAccessibleInterface::childAt(): - // Calculate global child position and check that the interface - // returns the correct index for that position. - QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0)); - int indexFromChildAt = interface->childAt(globalChildPos.x(), globalChildPos.y()); - if (indexFromChildAt != index) { - qWarning("tst_QAccessibility::verifyChild (childAt()):"); - qWarning() << "Expected:" << index; - qWarning() << "Actual: " << indexFromChildAt; - return false; - } - - // QAccessibleInterface::rect(): - // Calculate global child geometry and check that the interface - // returns a QRect which is equal to the calculated QRect. - const QRect expectedGlobalRect = QRect(globalChildPos, child->size()); - if (expectedGlobalRect != rectFromInterface) { - qWarning("tst_QAccessibility::verifyChild (rect()):"); - qWarning() << "Expected:" << expectedGlobalRect; - qWarning() << "Actual: " << rectFromInterface; - return false; - } - - // Verify that the child is within its domain. - if (!domain.contains(rectFromInterface)) { - qWarning("tst_QAccessibility::verifyChild: Child is not within its domain."); - return false; - } - - return true; -} - -static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget) -{ - if (!parentInterface || !childWidget) - return -1; - QAccessibleInterface *childInterface = QAccessibleInterface::queryAccessibleInterface(childWidget); - if (!childInterface) - return -1; - int index = parentInterface->indexOfChild(childInterface); - delete childInterface; - return index; -} - -#define EXPECT(cond) \ - do { \ - if (!errorAt && !(cond)) { \ - errorAt = __LINE__; \ - qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \ - } \ - } while (0) - -static int verifyHierarchy(QAccessibleInterface *iface) -{ - int errorAt = 0; - static int treelevel = 0; // for error diagnostics - QAccessibleInterface *middleChild, *if2; - middleChild = 0; - ++treelevel; - int middle = iface->childCount()/2 + 1; - if (iface->childCount() >= 2) { - middleChild = iface->child(middle - 1); - } - for (int i = 0; i < iface->childCount() && !errorAt; ++i) { - if2 = iface->child(i); - EXPECT(if2 != 0); - // navigate Ancestor... - QAccessibleInterface *parent = 0; - parent = if2->parent(); - EXPECT(iface->object() == parent->object()); - delete parent; - - // navigate Sibling... -// if (middleChild) { -// entry = if2->navigate(QAccessible::Sibling, middle, &if3); -// EXPECT(entry == 0 && if3->object() == middleChild->object()); -// if (entry == 0) -// delete if3; -// EXPECT(iface->indexOfChild(middleChild) == middle); -// } - - // verify children... - if (!errorAt) - errorAt = verifyHierarchy(if2); - delete if2; - } - delete middleChild; - - --treelevel; - return errorAt; -} - - -//TESTED_FILES= - -class tst_QAccessibility : public QObject -{ - Q_OBJECT -public: - tst_QAccessibility(); - virtual ~tst_QAccessibility(); - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); -private slots: - void eventTest(); - void customWidget(); - void deletedWidget(); - - void navigateGeometric(); - void navigateHierarchy(); - void sliderTest(); - void navigateCovered(); - void textAttributes(); - void hideShowTest(); - - void actionTest(); - - void applicationTest(); - void mainWindowTest(); - void buttonTest(); - void scrollBarTest(); - void tabTest(); - void tabWidgetTest(); - void menuTest(); - void spinBoxTest(); - void doubleSpinBoxTest(); - void textEditTest(); - void textBrowserTest(); - void mdiAreaTest(); - void mdiSubWindowTest(); - void lineEditTest(); - void workspaceTest(); - void dialogButtonBoxTest(); - void dialTest(); - void rubberBandTest(); - void abstractScrollAreaTest(); - void scrollAreaTest(); - - // Accessible table1 interface is no longer supported on X11, - // where it has been replaced by table2 interface. -#ifndef Q_OS_UNIX - void listViewTest(); - void treeWidgetTest(); - void tableWidgetTest(); - void tableViewTest(); -#else - void table2ListTest(); - void table2TreeTest(); - void table2TableTest(); -#endif - - void calendarWidgetTest(); - void dockWidgetTest(); - void comboBoxTest(); - void accessibleName(); - void labelTest(); - void accelerators(); -}; - -const double Q_PI = 3.14159265358979323846; - -QString eventName(const int ev) -{ - switch(ev) { - case 0x0001: return "SoundPlayed"; - case 0x0002: return "Alert"; - case 0x0003: return "ForegroundChanged"; - case 0x0004: return "MenuStart"; - case 0x0005: return "MenuEnd"; - case 0x0006: return "PopupMenuStart"; - case 0x0007: return "PopupMenuEnd"; - case 0x000C: return "ContextHelpStart"; - case 0x000D: return "ContextHelpEnd"; - case 0x000E: return "DragDropStart"; - case 0x000F: return "DragDropEnd"; - case 0x0010: return "DialogStart"; - case 0x0011: return "DialogEnd"; - case 0x0012: return "ScrollingStart"; - case 0x0013: return "ScrollingEnd"; - case 0x0018: return "MenuCommand"; - - case 0x0116: return "TableModelChanged"; - case 0x011B: return "TextCaretMoved"; - - case 0x8000: return "ObjectCreated"; - case 0x8001: return "ObjectDestroyed"; - case 0x8002: return "ObjectShow"; - case 0x8003: return "ObjectHide"; - case 0x8004: return "ObjectReorder"; - case 0x8005: return "Focus"; - case 0x8006: return "Selection"; - case 0x8007: return "SelectionAdd"; - case 0x8008: return "SelectionRemove"; - case 0x8009: return "SelectionWithin"; - case 0x800A: return "StateChanged"; - case 0x800B: return "LocationChanged"; - case 0x800C: return "NameChanged"; - case 0x800D: return "DescriptionChanged"; - case 0x800E: return "ValueChanged"; - case 0x800F: return "ParentChanged"; - case 0x80A0: return "HelpChanged"; - case 0x80B0: return "DefaultActionChanged"; - case 0x80C0: return "AcceleratorChanged"; - default: return "Unknown Event"; - } -} - -QAccessible::State state(QWidget * const widget) -{ - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); - if (!iface) - qWarning() << "Cannot get QAccessibleInterface for widget"; - QAccessible::State state = (iface ? iface->state() : static_cast(0)); - delete iface; - return state; -} - -class QtTestAccessibleWidget: public QWidget -{ - Q_OBJECT -public: - QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent) - { - setObjectName(name); - QPalette pal; - pal.setColor(backgroundRole(), Qt::black);//black is beautiful - setPalette(pal); - setFixedSize(5, 5); - } -}; - -class QtTestAccessibleWidgetIface: public QAccessibleWidget -{ -public: - QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {} - QString text(Text t, int control = 0) const - { - if (t == Help) - return QString::fromLatin1("Help yourself"); - return QAccessibleWidget::text(t, control); - } - static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o) - { - if (key == "QtTestAccessibleWidget") - return new QtTestAccessibleWidgetIface(static_cast(o)); - return 0; - } -}; - -tst_QAccessibility::tst_QAccessibility() -{ -} - -tst_QAccessibility::~tst_QAccessibility() -{ -} - -void tst_QAccessibility::initTestCase() -{ - QTestAccessibility::initialize(); - QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory); -} - -void tst_QAccessibility::cleanupTestCase() -{ - QTestAccessibility::cleanup(); -} - -void tst_QAccessibility::init() -{ - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::cleanup() -{ - const EventList list = QTestAccessibility::events(); - if (!list.isEmpty()) { - qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(), - QString(QTest::currentTestFunction()).toAscii().constData()); - for (int i = 0; i < list.count(); ++i) - qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object, - eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child); - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::eventTest() -{ - QPushButton* button = new QPushButton(0); - button->setObjectName(QString("Olaf")); - - button->show(); - QVERIFY_EVENT(button, 0, QAccessible::ObjectShow); - button->setFocus(Qt::MouseFocusReason); - QTestAccessibility::clearEvents(); - QTest::mouseClick(button, Qt::LeftButton, 0); - QVERIFY_EVENT(button, 0, QAccessible::StateChanged); - QVERIFY_EVENT(button, 0, QAccessible::StateChanged); - - button->setAccessibleName("Olaf the second"); - QVERIFY_EVENT(button, 0, QAccessible::NameChanged); - button->setAccessibleDescription("This is a button labeled Olaf"); - QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged); - - button->hide(); - QVERIFY_EVENT(button, 0, QAccessible::ObjectHide); - - delete button; -} - -void tst_QAccessibility::customWidget() -{ - QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz"); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - QCOMPARE(iface->object(), (QObject*)widget); - QCOMPARE(iface->object()->objectName(), QString("Heinz")); - QCOMPARE(iface->text(QAccessible::Help, 0), QString("Help yourself")); - - delete iface; - delete widget; -} - -void tst_QAccessibility::deletedWidget() -{ - QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf"); - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - QCOMPARE(iface->object(), (QObject*)widget); - - delete widget; - widget = 0; - QVERIFY(!iface->isValid()); - delete iface; -} - -void tst_QAccessibility::navigateGeometric() -{ - { - static const int skip = 20; //speed the test up significantly - static const double step = Q_PI / 180; - QWidget *w = new QWidget(0); - w->setObjectName(QString("Josef")); - w->setFixedSize(400, 400); - - // center widget - QtTestAccessibleWidget *center = new QtTestAccessibleWidget(w, "Sol"); - center->move(200, 200); - - // arrange 360 widgets around it in a circle - QtTestAccessibleWidget *aw = 0; - for (int i = 0; i < 360; i += skip) { - aw = new QtTestAccessibleWidget(w, QString::number(i).toLatin1()); - aw->move( int(200.0 + 100.0 * sin(step * (double)i)), int(200.0 + 100.0 * cos(step * (double)i)) ); - } - - aw = new QtTestAccessibleWidget(w, "Earth"); - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(center); - QAccessibleInterface *target = 0; - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - - w->show(); - QCoreApplication::processEvents(); - QTest::qWait(100); - - // let one widget rotate around center - for (int i = 0; i < 360; i+=skip) { - aw->move( int(200.0 + 75.0 * sin(step * (double)i)), int(200.0 + 75.0 * cos(step * (double)i)) ); - - if (i < 45 || i > 315) { - QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0); - } else if ( i < 135 ) { - QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0); - } else if ( i < 225 ) { - QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0); - } else { - QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0); - } - - QVERIFY(target); - QVERIFY(target->isValid()); - QVERIFY(target->object()); - QCOMPARE(target->object()->objectName(), aw->objectName()); - delete target; target = 0; - } - - // test invisible widget - target = QAccessible::queryAccessibleInterface(aw); - QVERIFY(!(target->state() & QAccessible::Invisible)); - aw->hide(); - QVERIFY(target->state() & QAccessible::Invisible); - delete target; target = 0; - - aw->move(center->x() + 10, center->y()); - QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0); - QVERIFY(target); - QVERIFY(target->isValid()); - QVERIFY(target->object()); - QVERIFY(QString(target->object()->objectName()) != "Earth"); - delete target; target = 0; - - aw->move(center->x() - 10, center->y()); - QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0); - QVERIFY(target); - QVERIFY(target->isValid()); - QVERIFY(target->object()); - QVERIFY(QString(target->object()->objectName()) != "Earth"); - delete target; target = 0; - - aw->move(center->x(), center->y() + 10); - QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0); - QVERIFY(target); - QVERIFY(target->isValid()); - QVERIFY(target->object()); - QVERIFY(QString(target->object()->objectName()) != "Earth"); - delete target; target = 0; - - aw->move(center->x(), center->y() - 10); - QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0); - QVERIFY(target); - QVERIFY(target->isValid()); - QVERIFY(target->object()); - QVERIFY(QString(target->object()->objectName()) != "Earth"); - delete target; target = 0; - - delete iface; - delete w; - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::sliderTest() -{ - { - QSlider *slider = new QSlider(0); - slider->setObjectName(QString("Slidy")); - slider->show(); - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - - QCOMPARE(iface->childCount(), 0); - QCOMPARE(iface->role(), QAccessible::Slider); - - QAccessibleValueInterface *valueIface = iface->valueInterface(); - QVERIFY(valueIface != 0); - QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum()); - QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum()); - slider->setValue(50); - QCOMPARE(valueIface->currentValue().toInt(), slider->value()); - slider->setValue(0); - QCOMPARE(valueIface->currentValue().toInt(), slider->value()); - slider->setValue(100); - QCOMPARE(valueIface->currentValue().toInt(), slider->value()); - valueIface->setCurrentValue(77); - QCOMPARE(77, slider->value()); - - delete iface; - delete slider; - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::navigateCovered() -{ - { - QWidget *w = new QWidget(0); - w->setObjectName(QString("Harry")); - QWidget *w1 = new QWidget(w); - w1->setObjectName(QString("1")); - QWidget *w2 = new QWidget(w); - w2->setObjectName(QString("2")); - w->show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - - w->setFixedSize(6, 6); - w1->setFixedSize(5, 5); - w2->setFixedSize(5, 5); - w2->move(0, 0); - w1->raise(); - - QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1); - QVERIFY(iface1 != 0); - QVERIFY(iface1->isValid()); - QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2); - QVERIFY(iface2 != 0); - QVERIFY(iface2->isValid()); - QAccessibleInterface *iface3 = 0; - - QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1); - QVERIFY(iface3 == 0); - QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1); - QVERIFY(iface3 == 0); - QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1); - QVERIFY(iface3 == 0); - - for (int loop = 0; loop < 2; ++loop) { - for (int x = 0; x < w->width(); ++x) { - for (int y = 0; y < w->height(); ++y) { - w1->move(x, y); - if (w1->geometry().intersects(w2->geometry())) { - QVERIFY(iface1->relationTo(0, iface2, 0) & QAccessible::Covers); - QVERIFY(iface2->relationTo(0, iface1, 0) & QAccessible::Covered); - QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0); - QVERIFY(iface3 != 0); - QVERIFY(iface3->isValid()); - QCOMPARE(iface3->object(), iface2->object()); - delete iface3; iface3 = 0; - QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0); - QVERIFY(iface3 != 0); - QVERIFY(iface3->isValid()); - QCOMPARE(iface3->object(), iface1->object()); - delete iface3; iface3 = 0; - } else { - QVERIFY(!(iface1->relationTo(0, iface2, 0) & QAccessible::Covers)); - QVERIFY(!(iface2->relationTo(0, iface1, 0) & QAccessible::Covered)); - QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1); - QVERIFY(iface3 == 0); - QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1); - QVERIFY(iface3 == 0); - QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1); - QVERIFY(iface3 == 0); - QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1); - QVERIFY(iface3 == 0); - } - } - } - if (!loop) { - // switch children for second loop - w2->raise(); - QAccessibleInterface *temp = iface1; - iface1 = iface2; - iface2 = temp; - } - } - delete iface1; iface1 = 0; - delete iface2; iface2 = 0; - iface1 = QAccessible::queryAccessibleInterface(w1); - QVERIFY(iface1 != 0); - QVERIFY(iface1->isValid()); - iface2 = QAccessible::queryAccessibleInterface(w2); - QVERIFY(iface2 != 0); - QVERIFY(iface2->isValid()); - - w1->move(0,0); - w2->move(0,0); - w1->raise(); - QVERIFY(iface1->relationTo(0, iface2, 0) & QAccessible::Covers); - QVERIFY(iface2->relationTo(0, iface1, 0) & QAccessible::Covered); - QVERIFY(!(iface1->state() & QAccessible::Invisible)); - w1->hide(); - QVERIFY(iface1->state() & QAccessible::Invisible); - QVERIFY(!(iface1->relationTo(0, iface2, 0) & QAccessible::Covers)); - QVERIFY(!(iface2->relationTo(0, iface1, 0) & QAccessible::Covered)); - QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1); - QVERIFY(iface3 == 0); - QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1); - QVERIFY(iface3 == 0); - - delete iface1; iface1 = 0; - delete iface2; iface2 = 0; - delete w; - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::navigateHierarchy() -{ - { - QWidget *w = new QWidget(0); - w->setObjectName(QString("Hans")); - w->show(); - QWidget *w1 = new QWidget(w); - w1->setObjectName(QString("1")); - w1->show(); - QWidget *w2 = new QWidget(w); - w2->setObjectName(QString("2")); - w2->show(); - QWidget *w3 = new QWidget(w); - w3->setObjectName(QString("3")); - w3->show(); - QWidget *w31 = new QWidget(w3); - w31->setObjectName(QString("31")); - w31->show(); - - QAccessibleInterface *target = 0; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - - QCOMPARE(iface->navigate(QAccessible::Sibling, -42, &target), -1); - QVERIFY(target == 0); - QCOMPARE(iface->navigate(QAccessible::Sibling, 42, &target), -1); - QVERIFY(target == 0); - - target = iface->child(14); - QVERIFY(target == 0); - target = iface->child(-1); - QVERIFY(target == 0); - target = iface->child(0); - QAccessibleInterface *interfaceW1 = iface->child(0); - QVERIFY(target); - QVERIFY(target->isValid()); - QCOMPARE(target->object(), (QObject*)w1); - QVERIFY(interfaceW1 != 0); - QVERIFY(interfaceW1->isValid()); - QCOMPARE(interfaceW1->object(), (QObject*)w1); - delete interfaceW1; - delete iface; iface = 0; - - QCOMPARE(target->navigate(QAccessible::Sibling, 0, &iface), -1); - QVERIFY(iface == 0); - QCOMPARE(target->navigate(QAccessible::Sibling, 42, &iface), -1); - QVERIFY(iface == 0); - QCOMPARE(target->navigate(QAccessible::Sibling, -42, &iface), -1); - QVERIFY(iface == 0); - QCOMPARE(target->navigate(QAccessible::Sibling, 2, &iface), 0); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - QCOMPARE(iface->object(), (QObject*)w2); - delete target; target = 0; - QCOMPARE(iface->navigate(QAccessible::Sibling, 3, &target), 0); - QVERIFY(target != 0); - QVERIFY(target->isValid()); - QCOMPARE(target->object(), (QObject*)w3); - delete iface; iface = 0; - - iface = target->child(0); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - QCOMPARE(iface->object(), (QObject*)w31); - delete target; target = 0; - - QCOMPARE(iface->navigate(QAccessible::Sibling, -1, &target), -1); - QVERIFY(target == 0); - QCOMPARE(iface->navigate(QAccessible::Sibling, 0, &target), -1); - QVERIFY(target == 0); - QCOMPARE(iface->navigate(QAccessible::Sibling, 1, &target), 0); - QVERIFY(target != 0); - QVERIFY(target->isValid()); - QCOMPARE(target->object(), (QObject*)w31); - delete iface; iface = 0; - - iface = target->parent(); - QVERIFY(iface != 0); - QVERIFY(iface->isValid()); - QCOMPARE(iface->object(), (QObject*)w3); - delete iface; iface = 0; - delete target; target = 0; - - delete w; - } - QTestAccessibility::clearEvents(); -} - -#define QSETCOMPARE(thetypename, elements, otherelements) \ - QCOMPARE((QSet() << elements), (QSet() << otherelements)) - -static QWidget *createWidgets() -{ - QWidget *w = new QWidget(); - - QHBoxLayout *box = new QHBoxLayout(w); - - int i = 0; - box->addWidget(new QComboBox(w)); - box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QHeaderView(Qt::Vertical, w)); - box->addWidget(new QTreeView(w)); - box->addWidget(new QTreeWidget(w)); - box->addWidget(new QListView(w)); - box->addWidget(new QListWidget(w)); - box->addWidget(new QTableView(w)); - box->addWidget(new QTableWidget(w)); - box->addWidget(new QCalendarWidget(w)); - box->addWidget(new QDialogButtonBox(w)); - box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QFrame(w)); - box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QProgressBar(w)); - box->addWidget(new QTabWidget(w)); - box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QDial(w)); - box->addWidget(new QScrollBar(w)); - box->addWidget(new QSlider(w)); - box->addWidget(new QDateTimeEdit(w)); - box->addWidget(new QDoubleSpinBox(w)); - box->addWidget(new QSpinBox(w)); - box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QLCDNumber(w)); - box->addWidget(new QStackedWidget(w)); - box->addWidget(new QToolBox(w)); - box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w)); - box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w)); - - /* Not in the list - * QAbstractItemView, QGraphicsView, QScrollArea, - * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle, - * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter - */ - return w; -} - -void tst_QAccessibility::accessibleName() -{ - QWidget *toplevel = createWidgets(); - toplevel->show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - QLayout *lout = toplevel->layout(); - for (int i = 0; i < lout->count(); i++) { - QLayoutItem *item = lout->itemAt(i); - QWidget *child = item->widget(); - - QString name = tr("Widget Name %1").arg(i); - child->setAccessibleName(name); - QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child); - QCOMPARE(acc->text(QAccessible::Name), name); - - QString desc = tr("Widget Description %1").arg(i); - child->setAccessibleDescription(desc); - QCOMPARE(acc->text(QAccessible::Description), desc); - - } - - delete toplevel; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::textAttributes() -{ - QTextEdit textEdit; - int startOffset; - int endOffset; - QString attributes; - QString text("" - "Hello, this is an example text." - "Multiple fonts are used." - "Multiple text sizes are used." - "Let's give some color to Qt." - ""); - - textEdit.setText(text); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit); - - QAccessibleTextInterface *textInterface=interface->textInterface(); - - QVERIFY(textInterface); - QCOMPARE(textInterface->characterCount(), 112); - - attributes = textInterface->attributes(10, &startOffset, &endOffset); - QCOMPARE(startOffset, 7); - QCOMPARE(endOffset, 11); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;"))); - - attributes = textInterface->attributes(18, &startOffset, &endOffset); - QCOMPARE(startOffset, 18); - QCOMPARE(endOffset, 25); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;"))); - QVERIFY(attributes.contains(QLatin1String(";font-style:italic;"))); - - attributes = textInterface->attributes(34, &startOffset, &endOffset); - QCOMPARE(startOffset, 31); - QCOMPARE(endOffset, 55); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";"))); - - attributes = textInterface->attributes(65, &startOffset, &endOffset); - QCOMPARE(startOffset, 64); - QCOMPARE(endOffset, 74); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;"))); - - attributes = textInterface->attributes(110, &startOffset, &endOffset); - QCOMPARE(startOffset, 109); - QCOMPARE(endOffset, 111); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);"))); - QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);"))); -} - -void tst_QAccessibility::hideShowTest() -{ - QWidget * const window = new QWidget(); - QWidget * const child = new QWidget(window); - - QVERIFY(state(window) & QAccessible::Invisible); - QVERIFY(state(child) & QAccessible::Invisible); - - QTestAccessibility::clearEvents(); - - // show() and veryfy that both window and child are not invisible and get ObjectShow events. - window->show(); - QVERIFY(state(window) ^ QAccessible::Invisible); - QVERIFY(state(child) ^ QAccessible::Invisible); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow))); - QTestAccessibility::clearEvents(); - - // hide() and veryfy that both window and child are invisible and get ObjectHide events. - window->hide(); - QVERIFY(state(window) & QAccessible::Invisible); - QVERIFY(state(child) & QAccessible::Invisible); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide))); - QTestAccessibility::clearEvents(); - - delete window; - QTestAccessibility::clearEvents(); -} - - -void tst_QAccessibility::actionTest() -{ - QCOMPARE(QAccessibleActionInterface::PressAction, QString("Press")); - - QWidget *widget = new QWidget; - widget->show(); - - QAccessibleInterface *test = QAccessible::queryAccessibleInterface(widget); - QVERIFY(test); - QVERIFY(test->isValid()); - -// QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString()); -// QCOMPARE(test->actionText(0, QAccessible::Name, 1), QString()); -// QCOMPARE(test->actionText(1, QAccessible::Name, 1), QString()); -// QCOMPARE(test->actionText(QAccessible::SetFocus, QAccessible::Name, -1), QString()); - -// QCOMPARE(test->actionText(QAccessible::DefaultAction, QAccessible::Name, 0), QString("SetFocus")); -// QCOMPARE(test->actionText(QAccessible::SetFocus, QAccessible::Name, 0), QString("SetFocus")); - - delete test; - delete widget; - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::applicationTest() -{ - QLatin1String name = QLatin1String("My Name"); - qApp->setApplicationName(name); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp); - QCOMPARE(interface->text(QAccessible::Name, 0), name); - QCOMPARE(interface->role(), QAccessible::Application); - delete interface; -} - -void tst_QAccessibility::mainWindowTest() -{ - QMainWindow *mw = new QMainWindow; - mw->resize(300, 200); - mw->show(); // triggers layout - - QLatin1String name = QLatin1String("I am the main window"); - mw->setWindowTitle(name); - QTest::qWaitForWindowShown(mw); - QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow); - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw); - QCOMPARE(interface->text(QAccessible::Name, 0), name); - QCOMPARE(interface->role(), QAccessible::Window); - delete interface; - delete mw; - QTestAccessibility::clearEvents(); -} - -class CounterButton : public QPushButton { - Q_OBJECT -public: - CounterButton(const QString& name, QWidget* parent) - : QPushButton(name, parent), clickCount(0) - { - connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount())); - } - int clickCount; -public Q_SLOTS: - void incClickCount() { - ++clickCount; - } -}; - -void tst_QAccessibility::buttonTest() -{ - QWidget window; - window.setLayout(new QVBoxLayout); - - // Standard push button - CounterButton pushButton("Ok", &window); - - // toggle button - QPushButton toggleButton("Toggle", &window); - toggleButton.setCheckable(true); - - // standard checkbox - QCheckBox checkBox("Check me!", &window); - - // tristate checkbox - QCheckBox tristate("Tristate!", &window); - tristate.setTristate(TRUE); - - // radiobutton - QRadioButton radio("Radio me!", &window); - - // standard toolbutton - QToolButton toolbutton(&window); - toolbutton.setText("Tool"); - toolbutton.setMinimumSize(20,20); - - // standard toolbutton - QToolButton toggletool(&window); - toggletool.setCheckable(true); - toggletool.setText("Toggle"); - toggletool.setMinimumSize(20,20); - - // test push button - QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton); - QAccessibleActionInterface* actionInterface = interface->actionInterface(); - QVERIFY(actionInterface != 0); - QCOMPARE(interface->role(), QAccessible::PushButton); - - // currently our buttons only have click as action, press and release are missing - QCOMPARE(actionInterface->actionNames().size(), 1); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); - QCOMPARE(pushButton.clickCount, 0); - actionInterface->doAction(QAccessibleActionInterface::PressAction); - QTest::qWait(500); - QCOMPARE(pushButton.clickCount, 1); - delete interface; - - // test toggle button - interface = QAccessible::queryAccessibleInterface(&toggleButton); - actionInterface = interface->actionInterface(); - QCOMPARE(interface->role(), QAccessible::CheckBox); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); - QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::CheckAction), QString("Checks the checkbox")); - QVERIFY(!toggleButton.isChecked()); - QVERIFY((interface->state() & QAccessible::Checked) == 0); - actionInterface->doAction(QAccessibleActionInterface::CheckAction); - QTest::qWait(500); - QVERIFY(toggleButton.isChecked()); - QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::UncheckAction); - QVERIFY(interface->state() & QAccessible::Checked); - delete interface; - - { - // test menu push button - QAction *foo = new QAction("Foo", 0); - foo->setShortcut(QKeySequence("Ctrl+F")); - QMenu *menu = new QMenu(); - menu->addAction(foo); - QPushButton menuButton; - menuButton.setMenu(menu); - menuButton.show(); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton); - QCOMPARE(interface->role(), QAccessible::ButtonMenu); - QVERIFY(interface->state() & QAccessible::HasPopup); - QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); - // showing the menu enters a new event loop... -// interface->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); -// QTest::qWait(500); - delete interface; - delete menu; - } - - // test check box - interface = QAccessible::queryAccessibleInterface(&checkBox); - actionInterface = interface->actionInterface(); - QCOMPARE(interface->role(), QAccessible::CheckBox); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); - QVERIFY((interface->state() & QAccessible::Checked) == 0); - actionInterface->doAction(QAccessibleActionInterface::CheckAction); - QTest::qWait(500); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::UncheckAction); - QVERIFY(interface->state() & QAccessible::Checked); - QVERIFY(checkBox.isChecked()); - delete interface; - - // test radiobutton - interface = QAccessible::queryAccessibleInterface(&radio); - actionInterface = interface->actionInterface(); - QCOMPARE(interface->role(), QAccessible::RadioButton); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); - QVERIFY((interface->state() & QAccessible::Checked) == 0); - actionInterface->doAction(QAccessibleActionInterface::CheckAction); - QTest::qWait(500); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction); - QVERIFY(interface->state() & QAccessible::Checked); - QVERIFY(checkBox.isChecked()); - delete interface; - -// // test standard toolbutton -// QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test)); -// QCOMPARE(test->role(), QAccessible::PushButton); -// QCOMPARE(test->defaultAction(0), QAccessible::Press); -// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press")); -// QCOMPARE(test->state(), (int)QAccessible::Normal); -// test->release(); - -// // toggle tool button -// QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test)); -// QCOMPARE(test->role(), QAccessible::CheckBox); -// QCOMPARE(test->defaultAction(0), QAccessible::Press); -// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check")); -// QCOMPARE(test->state(), (int)QAccessible::Normal); -// QVERIFY(test->doAction(QAccessible::Press, 0)); -// QTest::qWait(500); -// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck")); -// QCOMPARE(test->state(), (int)QAccessible::Checked); -// test->release(); - -// // test menu toolbutton -// QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test)); -// QCOMPARE(test->role(), QAccessible::ButtonMenu); -// QCOMPARE(test->defaultAction(0), 1); -// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open")); -// QCOMPARE(test->state(), (int)QAccessible::HasPopup); -// QCOMPARE(test->actionCount(0), 1); -// QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press")); -// test->release(); - -// // test split menu toolbutton -// QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test)); -// QCOMPARE(test->childCount(), 2); -// QCOMPARE(test->role(), QAccessible::ButtonDropDown); -// QCOMPARE(test->role(1), QAccessible::PushButton); -// QCOMPARE(test->role(2), QAccessible::ButtonMenu); -// QCOMPARE(test->defaultAction(0), QAccessible::Press); -// QCOMPARE(test->defaultAction(1), QAccessible::Press); -// QCOMPARE(test->defaultAction(2), QAccessible::Press); -// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press")); -// QCOMPARE(test->state(), (int)QAccessible::HasPopup); -// QCOMPARE(test->actionCount(0), 1); -// QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open")); -// QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press")); -// QCOMPARE(test->state(1), (int)QAccessible::Normal); -// QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open")); -// QCOMPARE(test->state(2), (int)QAccessible::HasPopup); -// test->release(); - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::scrollBarTest() -{ - QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal); - QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar); - QVERIFY(scrollBarInterface); - QVERIFY(scrollBarInterface->state() & QAccessible::Invisible); - scrollBar->resize(200, 50); - scrollBar->show(); - QVERIFY(scrollBarInterface->state() ^ QAccessible::Invisible); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow))); - QTestAccessibility::clearEvents(); - - scrollBar->hide(); - QVERIFY(scrollBarInterface->state() & QAccessible::Invisible); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide))); - QTestAccessibility::clearEvents(); - - // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum. - scrollBar->show(); - scrollBar->setMinimum(11); - scrollBar->setMaximum(111); - - QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface(); - QVERIFY(valueIface != 0); - QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum()); - QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum()); - scrollBar->setValue(50); - QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value()); - scrollBar->setValue(0); - QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value()); - scrollBar->setValue(100); - QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value()); - valueIface->setCurrentValue(77); - QCOMPARE(77, scrollBar->value()); - - const QRect scrollBarRect = scrollBarInterface->rect(); - QVERIFY(scrollBarRect.isValid()); - - delete scrollBarInterface; - delete scrollBar; - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::tabTest() -{ - QTabBar *tabBar = new QTabBar(); - tabBar->show(); - - QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar); - QVERIFY(interface); - QCOMPARE(interface->childCount(), 2); - - // Test that the Invisible bit for the navigation buttons gets set - // and cleared correctly. - QAccessibleInterface *leftButton = interface->child(0); - QCOMPARE(leftButton->role(), QAccessible::PushButton); - QVERIFY(leftButton->state() & QAccessible::Invisible); - delete leftButton; - - const int lots = 5; - for (int i = 0; i < lots; ++i) - tabBar->addTab("Foo"); - - QAccessibleInterface *child1 = interface->child(0); - QAccessibleInterface *child2 = interface->child(1); - QVERIFY(child1); - QCOMPARE(child1->role(), QAccessible::PageTab); - QVERIFY(child2); - QCOMPARE(child2->role(), QAccessible::PageTab); - - QVERIFY((child1->state() & QAccessible::Invisible) == false); - tabBar->hide(); - - QCoreApplication::processEvents(); - QTest::qWait(100); - - QVERIFY(child1->state() & QAccessible::Invisible); - - tabBar->show(); - tabBar->setCurrentIndex(0); - - // Test that sending a focus action to a tab does not select it. -// child2->doAction(QAccessible::Focus, 2, QVariantList()); - QCOMPARE(tabBar->currentIndex(), 0); - - // Test that sending a press action to a tab selects it. - QVERIFY(child2->actionInterface()); - QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); - QCOMPARE(tabBar->currentIndex(), 0); - child2->actionInterface()->doAction(QAccessibleActionInterface::PressAction); - QCOMPARE(tabBar->currentIndex(), 1); - - delete tabBar; - delete interface; - delete child1; - delete child2; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::tabWidgetTest() -{ - QTabWidget *tabWidget = new QTabWidget(); - tabWidget->show(); - - // the interface for the tab is just a container for tabbar and stacked widget - QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget); - QVERIFY(interface); - QCOMPARE(interface->childCount(), 2); - QCOMPARE(interface->role(), QAccessible::Client); - - // Create pages, check navigation - QLabel *label1 = new QLabel("Page 1", tabWidget); - tabWidget->addTab(label1, "Tab 1"); - QLabel *label2 = new QLabel("Page 2", tabWidget); - tabWidget->addTab(label2, "Tab 2"); - - QCOMPARE(interface->childCount(), 2); - - QAccessibleInterface* tabBarInterface = 0; - // there is no special logic to sort the children, so the contents will be 1, the tab bar 2 - tabBarInterface = interface->child(1); - QVERIFY(tabBarInterface); - QCOMPARE(tabBarInterface->childCount(), 4); - QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList); - - QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0); - QVERIFY(tabButton1Interface); - QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab); - QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1")); - - QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1); - QVERIFY(tabButton1Interface); - QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab); - QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2")); - - QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2); - QVERIFY(tabButtonLeft); - QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton); - QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left")); - - QAccessibleInterface* tabButtonRight = tabBarInterface->child(3); - QVERIFY(tabButtonRight); - QCOMPARE(tabButtonRight->role(), QAccessible::PushButton); - QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right")); - delete tabButton1Interface; - delete tabButton2Interface; - delete tabButtonLeft; - delete tabButtonRight; - - QAccessibleInterface* stackWidgetInterface = interface->child(0); - QVERIFY(stackWidgetInterface); - QCOMPARE(stackWidgetInterface->childCount(), 2); - QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane); - - QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0); - QVERIFY(stackChild1Interface); -#ifndef Q_CC_INTEL - QCOMPARE(stackChild1Interface->childCount(), 0); -#endif - QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText); - QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1")); - QCOMPARE(label1, stackChild1Interface->object()); - - // Navigation in stack widgets should be consistent - QAccessibleInterface* parent = stackChild1Interface->parent(); - QVERIFY(parent); -#ifndef Q_CC_INTEL - QCOMPARE(parent->childCount(), 2); -#endif - QCOMPARE(parent->role(), QAccessible::LayeredPane); - delete parent; - - QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1); - QVERIFY(stackChild2Interface); - QCOMPARE(stackChild2Interface->childCount(), 0); - QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText); - QCOMPARE(label2, stackChild2Interface->object()); - QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name)); - - parent = stackChild2Interface->parent(); - QVERIFY(parent); -#ifndef Q_CC_INTEL - QCOMPARE(parent->childCount(), 2); -#endif - QCOMPARE(parent->role(), QAccessible::LayeredPane); - delete parent; - - delete tabBarInterface; - delete stackChild1Interface; - delete stackChild2Interface; - delete stackWidgetInterface; - delete interface; - delete tabWidget; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::menuTest() -{ - { - QMainWindow mw; - mw.resize(300, 200); - QMenu *file = mw.menuBar()->addMenu("&File"); - QMenu *fileNew = file->addMenu("&New..."); - fileNew->menuAction()->setShortcut(tr("Ctrl+N")); - fileNew->addAction("Text file"); - fileNew->addAction("Image file"); - file->addAction("&Open")->setShortcut(tr("Ctrl+O")); - file->addAction("&Save")->setShortcut(tr("Ctrl+S")); - file->addSeparator(); - file->addAction("E&xit")->setShortcut(tr("Alt+F4")); - - QMenu *edit = mw.menuBar()->addMenu("&Edit"); - edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z")); - edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y")); - edit->addSeparator(); - edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X")); - edit->addAction("&Copy")->setShortcut(tr("Ctrl+C")); - edit->addAction("&Paste")->setShortcut(tr("Ctrl+V")); - edit->addAction("&Delete")->setShortcut(tr("Del")); - edit->addSeparator(); - edit->addAction("Pr&operties"); - - mw.menuBar()->addSeparator(); - - QMenu *help = mw.menuBar()->addMenu("&Help"); - help->addAction("&Contents"); - help->addAction("&About"); - - mw.menuBar()->addAction("Action!"); - - mw.show(); // triggers layout - QTest::qWait(100); - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar()); - QCOMPARE(verifyHierarchy(interface), 0); - - QVERIFY(interface); - QCOMPARE(interface->childCount(), 5); - QCOMPARE(interface->role(), QAccessible::MenuBar); - - QAccessibleInterface *iFile = interface->child(0); - QAccessibleInterface *iEdit = interface->child(1); - QAccessibleInterface *iSeparator = interface->child(2); - QAccessibleInterface *iHelp = interface->child(3); - QAccessibleInterface *iAction = interface->child(4); - - QCOMPARE(iFile->role(), QAccessible::MenuItem); - QCOMPARE(iEdit->role(), QAccessible::MenuItem); - QCOMPARE(iSeparator->role(), QAccessible::Separator); - QCOMPARE(iHelp->role(), QAccessible::MenuItem); - QCOMPARE(iAction->role(), QAccessible::MenuItem); -#ifndef Q_WS_MAC -#ifdef Q_OS_WINCE - if (!IsValidCEPlatform()) { - QSKIP("Tests do not work on Mobile platforms due to native menus", SkipAll); - } -#endif - QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft()); - QCOMPARE(interface->rect().size(), mw.menuBar()->size()); - - QVERIFY(interface->rect().contains(iFile->rect())); - QVERIFY(interface->rect().contains(iEdit->rect())); - // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible - QVERIFY(interface->rect().contains(iHelp->rect())); - QVERIFY(interface->rect().contains(iAction->rect())); -#endif - - QCOMPARE(iFile->text(QAccessible::Name, 0), QString("File")); - QCOMPARE(iEdit->text(QAccessible::Name, 0), QString("Edit")); - QCOMPARE(iSeparator->text(QAccessible::Name, 0), QString()); - QCOMPARE(iHelp->text(QAccessible::Name, 0), QString("Help")); - QCOMPARE(iAction->text(QAccessible::Name, 0), QString("Action!")); - -// TODO: Currently not working, task to fix is #100019. -#ifndef Q_OS_MAC - QCOMPARE(iFile->text(QAccessible::Accelerator, 0), tr("Alt+F")); - QCOMPARE(iEdit->text(QAccessible::Accelerator, 0), tr("Alt+E")); - QCOMPARE(iSeparator->text(QAccessible::Accelerator, 0), QString()); - QCOMPARE(iHelp->text(QAccessible::Accelerator, 0), tr("Alt+H")); - QCOMPARE(iAction->text(QAccessible::Accelerator, 0), QString()); -#endif - - QVERIFY(iFile->actionInterface()); - - QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); - QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList()); - QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); - QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); - - bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu); - int menuFadeDelay = 300; - iFile->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - if(menuFade) - QTest::qWait(menuFadeDelay); - QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible()); - iEdit->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - if(menuFade) - QTest::qWait(menuFadeDelay); - QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible()); - iHelp->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - if(menuFade) - QTest::qWait(menuFadeDelay); - QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible()); - iAction->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - if(menuFade) - QTest::qWait(menuFadeDelay); - QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible()); - - QVERIFY(!interface->actionInterface()); - delete interface; - interface = QAccessible::queryAccessibleInterface(file); - QCOMPARE(interface->childCount(), 5); - QCOMPARE(interface->role(), QAccessible::PopupMenu); - - QAccessibleInterface *iFileNew = interface->child(0); - QAccessibleInterface *iFileOpen = interface->child(1); - QAccessibleInterface *iFileSave = interface->child(2); - QAccessibleInterface *iFileSeparator = interface->child(3); - QAccessibleInterface *iFileExit = interface->child(4); - - QCOMPARE(iFileNew->role(), QAccessible::MenuItem); - QCOMPARE(iFileOpen->role(), QAccessible::MenuItem); - QCOMPARE(iFileSave->role(), QAccessible::MenuItem); - QCOMPARE(iFileSeparator->role(), QAccessible::Separator); - QCOMPARE(iFileExit->role(), QAccessible::MenuItem); - QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); - QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); - QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); - QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList()); - QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction); - - QAccessibleInterface *iface = 0; - QAccessibleInterface *iface2 = 0; - - // traverse siblings with navigate(Sibling, ...) - int entry = interface->navigate(QAccessible::Child, 1, &iface); - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::MenuItem); - - QAccessible::Role fileRoles[5] = { - QAccessible::MenuItem, - QAccessible::MenuItem, - QAccessible::MenuItem, - QAccessible::Separator, - QAccessible::MenuItem - }; - for (int child = 0; child < 5; ++child) { - entry = iface->navigate(QAccessible::Sibling, child + 1, &iface2); - QCOMPARE(entry, 0); - QVERIFY(iface2); - QCOMPARE(iface2->role(), fileRoles[child]); - delete iface2; - } - delete iface; - - // traverse menu items with navigate(Down, ...) - entry = interface->navigate(QAccessible::Child, 1, &iface); - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::MenuItem); - - for (int child = 0; child < 4; ++child) { - entry = iface->navigate(QAccessible::Down, 1, &iface2); - delete iface; - iface = iface2; - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), fileRoles[child + 1]); - } - delete iface; - - // traverse menu items with navigate(Up, ...) - entry = interface->navigate(QAccessible::Child, interface->childCount(), &iface); - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::MenuItem); - - for (int child = 3; child >= 0; --child) { - entry = iface->navigate(QAccessible::Up, 1, &iface2); - delete iface; - iface = iface2; - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), fileRoles[child]); - } - delete iface; - - // "New" item - entry = interface->navigate(QAccessible::Child, 1, &iface); - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::MenuItem); - - // "New" menu - entry = iface->navigate(QAccessible::Child, 1, &iface2); - delete iface; - iface = iface2; - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::PopupMenu); - - // "Text file" menu item - entry = iface->navigate(QAccessible::Child, 1, &iface2); - delete iface; - iface = iface2; - QCOMPARE(entry, 0); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::MenuItem); - - delete iface; - - // move mouse pointer away, since that might influence the - // subsequent tests - QTest::mouseMove(&mw, QPoint(-1, -1)); - QTest::qWait(100); - if (menuFade) - QTest::qWait(menuFadeDelay); - - iFile->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - iFileNew->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - - QVERIFY(file->isVisible()); - QVERIFY(fileNew->isVisible()); - QVERIFY(!edit->isVisible()); - QVERIFY(!help->isVisible()); - - QTestAccessibility::clearEvents(); - mw.hide(); - - delete iFile; - delete iFileNew; - delete iFileOpen; - delete iFileSave; - delete iFileSeparator; - delete iFileExit; - - // Do not crash if the menu don't have a parent - QMenu *menu = new QMenu; - menu->addAction(QLatin1String("one")); - menu->addAction(QLatin1String("two")); - menu->addAction(QLatin1String("three")); - iface = QAccessible::queryAccessibleInterface(menu); - iface2 = iface->parent(); - QVERIFY(iface2); - QCOMPARE(iface2->role(), QAccessible::Application); - // caused a *crash* - iface2->state(); - delete iface2; - delete iface; - delete menu; - - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::spinBoxTest() -{ - QSpinBox * const spinBox = new QSpinBox(); - spinBox->setValue(3); - spinBox->show(); - - QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox); - QVERIFY(interface); - QCOMPARE(interface->role(), QAccessible::SpinBox); - - const QRect widgetRect = spinBox->geometry(); - const QRect accessibleRect = interface->rect(); - QCOMPARE(accessibleRect, widgetRect); - QCOMPARE(interface->text(QAccessible::Value, 0), QLatin1String("3")); - - // one child, the line edit - const int numChildren = interface->childCount(); - QCOMPARE(numChildren, 1); - QAccessibleInterface *lineEdit = interface->child(0); - - QCOMPARE(lineEdit->role(), QAccessible::EditableText); - QCOMPARE(lineEdit->text(QAccessible::Value, 0), QLatin1String("3")); - delete lineEdit; - - QVERIFY(interface->valueInterface()); - QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3); - interface->valueInterface()->setCurrentValue(23); - QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23); - QCOMPARE(spinBox->value(), 23); - - spinBox->setFocus(); - QTestAccessibility::clearEvents(); - QTest::keyPress(spinBox, Qt::Key_Up); - QTest::qWait(200); - EventList events = QTestAccessibility::events(); - QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged); - QVERIFY(events.contains(expectedEvent)); - delete spinBox; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::doubleSpinBoxTest() -{ - QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox; - doubleSpinBox->show(); - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox); - QVERIFY(interface); - - const QRect widgetRect = doubleSpinBox->geometry(); - const QRect accessibleRect = interface->rect(); - QCOMPARE(accessibleRect, widgetRect); - - // Test that we get valid rects for all the spinbox child interfaces. - const int numChildren = interface->childCount(); - for (int i = 1; i <= numChildren; ++i) { - const QRect childRect = interface->rect(i); - QVERIFY(childRect.isValid()); - } - - delete doubleSpinBox; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::textEditTest() -{ - { - QTextEdit edit; - int startOffset; - int endOffset; - QString text = "hello world\nhow are you today?\n"; - edit.setText(text); - edit.show(); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit); - QCOMPARE(iface->text(QAccessible::Value, 0), text); - QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world")); - QCOMPARE(startOffset, 6); - QCOMPARE(endOffset, 11); - QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?")); - QCOMPARE(startOffset, 12); - QCOMPARE(endOffset, 30); - QCOMPARE(iface->textInterface()->characterCount(), 31); - QFontMetrics fm(edit.font()); - QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height())); - QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height())); - QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height())); - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::textBrowserTest() -{ - { - QTextBrowser textBrowser; - QString text = QLatin1String("Hello world\nhow are you today?\n"); - textBrowser.setText(text); - textBrowser.show(); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser); - QVERIFY(iface); - QCOMPARE(iface->role(), QAccessible::StaticText); - QCOMPARE(iface->text(QAccessible::Value, 0), text); - int startOffset; - int endOffset; - QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world")); - QCOMPARE(startOffset, 6); - QCOMPARE(endOffset, 11); - QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?")); - QCOMPARE(startOffset, 12); - QCOMPARE(endOffset, 30); - QCOMPARE(iface->textInterface()->characterCount(), 31); - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::mdiAreaTest() -{ - { - QMdiArea mdiArea; - mdiArea.resize(400,300); - mdiArea.show(); - const int subWindowCount = 3; - for (int i = 0; i < subWindowCount; ++i) - mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show(); - - QList subWindows = mdiArea.subWindowList(); - QCOMPARE(subWindows.count(), subWindowCount); - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea); - QVERIFY(interface); - QCOMPARE(interface->childCount(), subWindowCount); - - // Right, right, right, ... - for (int i = 0; i < subWindowCount; ++i) { - QAccessibleInterface *destination = 0; - int index = interface->navigate(QAccessible::Right, i + 1, &destination); - if (i == subWindowCount - 1) { - QVERIFY(!destination); - QCOMPARE(index, -1); - } else { - QVERIFY(destination); - QCOMPARE(index, 0); - QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1)); - delete destination; - } - } - - // Left, left, left, ... - for (int i = subWindowCount; i > 0; --i) { - QAccessibleInterface *destination = 0; - int index = interface->navigate(QAccessible::Left, i, &destination); - if (i == 1) { - QVERIFY(!destination); - QCOMPARE(index, -1); - } else { - QVERIFY(destination); - QCOMPARE(index, 0); - QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2)); - delete destination; - } - } - // ### Add test for Up and Down. - - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::mdiSubWindowTest() -{ - { - QMdiArea mdiArea; - mdiArea.show(); - qApp->setActiveWindow(&mdiArea); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(150); -#endif - - bool isSubWindowsPlacedNextToEachOther = false; - const int subWindowCount = 5; - for (int i = 0; i < subWindowCount; ++i) { - QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest")); - window->show(); - // Parts of this test requires that the sub windows are placed next - // to each other. In order to achieve that QMdiArea must have - // a width which is larger than subWindow->width() * subWindowCount. - if (i == 0) { - int minimumWidth = window->width() * subWindowCount + 20; - mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0))); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - if (mdiArea.width() >= minimumWidth) - isSubWindowsPlacedNextToEachOther = true; - } - } - - QList subWindows = mdiArea.subWindowList(); - QCOMPARE(subWindows.count(), subWindowCount); - - QMdiSubWindow *testWindow = subWindows.at(3); - QVERIFY(testWindow); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow); - - // childCount - QVERIFY(interface); - QCOMPARE(interface->childCount(), 1); - - // setText / text - QCOMPARE(interface->text(QAccessible::Name, 0), QString()); - QCOMPARE(interface->text(QAccessible::Name, 1), QString()); - testWindow->setWindowTitle(QLatin1String("ReplaceMe")); - QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("ReplaceMe")); - QCOMPARE(interface->text(QAccessible::Name, 1), QLatin1String("ReplaceMe")); - interface->setText(QAccessible::Name, 0, QLatin1String("TitleSetOnWindow")); - QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("TitleSetOnWindow")); - interface->setText(QAccessible::Name, 1, QLatin1String("TitleSetOnChild")); - QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("TitleSetOnChild")); - - mdiArea.setActiveSubWindow(testWindow); - - // state - QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused - | QAccessible::Movable | QAccessible::Sizeable; - QCOMPARE(interface->state(), state); - const QRect originalGeometry = testWindow->geometry(); - testWindow->showMaximized(); - state &= ~QAccessible::Sizeable; - state &= ~QAccessible::Movable; - QCOMPARE(interface->state(), state); - testWindow->showNormal(); - testWindow->move(-10, 0); - QVERIFY(interface->state() & QAccessible::Offscreen); - testWindow->setVisible(false); - QVERIFY(interface->state() & QAccessible::Invisible); - testWindow->setVisible(true); - testWindow->setEnabled(false); - QVERIFY(interface->state() & QAccessible::Unavailable); - testWindow->setEnabled(true); - qApp->setActiveWindow(&mdiArea); - mdiArea.setActiveSubWindow(testWindow); - testWindow->setFocus(); - QVERIFY(testWindow->isAncestorOf(qApp->focusWidget())); - QVERIFY(interface->state() & QAccessible::Focused); - testWindow->setGeometry(originalGeometry); - - if (isSubWindowsPlacedNextToEachOther) { - // This part of the test can only be run if the sub windows are - // placed next to each other. - QAccessibleInterface *destination = 0; - QCOMPARE(interface->navigate(QAccessible::Child, 1, &destination), 0); - QVERIFY(destination); - QCOMPARE(destination->object(), (QObject*)testWindow->widget()); - delete destination; - QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0); - QVERIFY(destination); - QCOMPARE(destination->object(), (QObject*)subWindows.at(2)); - delete destination; - QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0); - QVERIFY(destination); - QCOMPARE(destination->object(), (QObject*)subWindows.at(4)); - delete destination; - } - - // rect - const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0)); - QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size())); - testWindow->hide(); - QCOMPARE(interface->rect(), QRect()); - QCOMPARE(interface->rect(1), QRect()); - testWindow->showMinimized(); - QCOMPARE(interface->rect(1), QRect()); - testWindow->showNormal(); - testWindow->widget()->hide(); - QCOMPARE(interface->rect(1), QRect()); - testWindow->widget()->show(); - const QRect widgetGeometry = testWindow->contentsRect(); - const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(), - globalPos.y() + widgetGeometry.y()); - QCOMPARE(interface->rect(1), QRect(globalWidgetPos, widgetGeometry.size())); - - // childAt - QCOMPARE(interface->childAt(-10, 0), -1); - QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), 0); - QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 1); - testWindow->widget()->hide(); - QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 0); - - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::lineEditTest() -{ - QLineEdit *le = new QLineEdit; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le); - QVERIFY(iface); - le->show(); - - QApplication::processEvents(); - QCOMPARE(iface->childCount(), 0); - QVERIFY(iface->state() & QAccessible::Sizeable); - QVERIFY(iface->state() & QAccessible::Movable); - QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow()); - QVERIFY(iface->state() & QAccessible::Selectable); - QVERIFY(iface->state() & QAccessible::HasPopup); - QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus()); - - QString secret(QLatin1String("secret")); - le->setText(secret); - le->setEchoMode(QLineEdit::Normal); - QVERIFY(!(iface->state() & QAccessible::Protected)); - QCOMPARE(iface->text(QAccessible::Value, 0), secret); - le->setEchoMode(QLineEdit::NoEcho); - QVERIFY(iface->state() & QAccessible::Protected); - QVERIFY(iface->text(QAccessible::Value, 0).isEmpty()); - le->setEchoMode(QLineEdit::Password); - QVERIFY(iface->state() & QAccessible::Protected); - QVERIFY(iface->text(QAccessible::Value, 0).isEmpty()); - le->setEchoMode(QLineEdit::PasswordEchoOnEdit); - QVERIFY(iface->state() & QAccessible::Protected); - QVERIFY(iface->text(QAccessible::Value, 0).isEmpty()); - le->setEchoMode(QLineEdit::Normal); - QVERIFY(!(iface->state() & QAccessible::Protected)); - QCOMPARE(iface->text(QAccessible::Value, 0), secret); - - QWidget *toplevel = new QWidget; - le->setParent(toplevel); - toplevel->show(); - QApplication::processEvents(); - QVERIFY(!(iface->state() & QAccessible::Sizeable)); - QVERIFY(!(iface->state() & QAccessible::Movable)); - QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow()); - QVERIFY(iface->state() & QAccessible::Selectable); - QVERIFY(iface->state() & QAccessible::HasPopup); - QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus()); - - QLineEdit *le2 = new QLineEdit(toplevel); - le2->show(); - QTest::qWait(100); - le2->activateWindow(); - QTest::qWait(100); - le->setFocus(Qt::TabFocusReason); - QTestAccessibility::clearEvents(); - le2->setFocus(Qt::TabFocusReason); - QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus))); - - le->setText(QLatin1String("500")); - le->setValidator(new QIntValidator()); - iface->setText(QAccessible::Value, 0, QLatin1String("This text is not a number")); - QCOMPARE(le->text(), QLatin1String("500")); - - delete iface; - delete le; - delete le2; - QTestAccessibility::clearEvents(); - - // IA2 - QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde"; - QLineEdit *le3 = new QLineEdit(cite, toplevel); - iface = QAccessible::queryAccessibleInterface(le3); - QAccessibleTextInterface* textIface = iface->textInterface(); - le3->deselect(); - le3->setCursorPosition(3); - QCOMPARE(textIface->cursorPosition(), 3); - QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved))); - QCOMPARE(textIface->selectionCount(), 0); - QTestAccessibility::clearEvents(); - - int start, end; - QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always")); - QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I")); - QCOMPARE(start, 0); - QCOMPARE(end, 1); - QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString()); - QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" ")); - QCOMPARE(start, 1); - QCOMPARE(end, 2); - - QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a")); - QCOMPARE(start, 5); - QCOMPARE(end, 6); - QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w")); - QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y")); - - QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); - QCOMPARE(start, 2); - QCOMPARE(end, 8); - - QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); - QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); - QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); - QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice")); - QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself")); - - QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); - QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); - QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. ")); - QCOMPARE(start, 0); - QCOMPARE(end, 30); - - QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. ")); - QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. ")); - - QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite); - QCOMPARE(start, 0); - QCOMPARE(end, cite.length()); - QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite); - QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite); - - delete iface; - delete toplevel; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::workspaceTest() -{ - { - QWorkspace workspace; - workspace.resize(400,300); - workspace.show(); - const int subWindowCount = 3; - for (int i = 0; i < subWindowCount; ++i) { - QWidget *window = workspace.addWindow(new QWidget); - if (i > 0) - window->move(window->x() + 1, window->y()); - window->show(); - window->resize(70, window->height()); - } - - QWidgetList subWindows = workspace.windowList(); - QCOMPARE(subWindows.count(), subWindowCount); - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace); - QVERIFY(interface); - QCOMPARE(interface->childCount(), subWindowCount); - - // Right, right, right, ... - for (int i = 0; i < subWindowCount; ++i) { - QAccessibleInterface *destination = 0; - int index = interface->navigate(QAccessible::Right, i + 1, &destination); - if (i == subWindowCount - 1) { - QVERIFY(!destination); - QCOMPARE(index, -1); - } else { - QVERIFY(destination); - QCOMPARE(index, 0); - QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1)); - delete destination; - } - } - - // Left, left, left, ... - for (int i = subWindowCount; i > 0; --i) { - QAccessibleInterface *destination = 0; - int index = interface->navigate(QAccessible::Left, i, &destination); - if (i == 1) { - QVERIFY(!destination); - QCOMPARE(index, -1); - } else { - QVERIFY(destination); - QCOMPARE(index, 0); - QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2)); - delete destination; - } - } - // ### Add test for Up and Down. - - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::dialogButtonBoxTest() -{ - { - QDialogButtonBox box(QDialogButtonBox::Reset | - QDialogButtonBox::Help | - QDialogButtonBox::Ok, Qt::Horizontal); - - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box); - QVERIFY(iface); - box.show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - - QApplication::processEvents(); - QCOMPARE(iface->childCount(), 3); - QCOMPARE(iface->role(), QAccessible::Grouping); - QCOMPARE(iface->role(1), QAccessible::PushButton); - QCOMPARE(iface->role(2), QAccessible::PushButton); - QCOMPARE(iface->role(3), QAccessible::PushButton); - QStringList actualOrder; - QAccessibleInterface *child; - QAccessibleInterface *leftmost; - child = iface->child(0); - // first find the leftmost button - while (child->navigate(QAccessible::Left, 1, &leftmost) != -1) { - delete child; - child = leftmost; - } - leftmost = child; - - // then traverse from left to right to find the correct order of the buttons - int right = 0; - while (right != -1) { - actualOrder << leftmost->text(QAccessible::Name, 0); - right = leftmost->navigate(QAccessible::Right, 1, &child); - delete leftmost; - leftmost = child; - } - - QStringList expectedOrder; - QDialogButtonBox::ButtonLayout btnlout = - QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout)); - switch (btnlout) { - case QDialogButtonBox::WinLayout: - expectedOrder << QDialogButtonBox::tr("Reset") - << QDialogButtonBox::tr("OK") - << QDialogButtonBox::tr("Help"); - break; - case QDialogButtonBox::GnomeLayout: - case QDialogButtonBox::KdeLayout: - case QDialogButtonBox::MacLayout: - expectedOrder << QDialogButtonBox::tr("Help") - << QDialogButtonBox::tr("Reset") - << QDialogButtonBox::tr("OK"); - break; - } - QCOMPARE(actualOrder, expectedOrder); - delete iface; - QApplication::processEvents(); - QTestAccessibility::clearEvents(); - } - - { - QDialogButtonBox box(QDialogButtonBox::Reset | - QDialogButtonBox::Help | - QDialogButtonBox::Ok, Qt::Horizontal); - - - // Test up and down navigation - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box); - QVERIFY(iface); - box.setOrientation(Qt::Vertical); - box.show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - - QApplication::processEvents(); - QAccessibleInterface *child; - QStringList actualOrder; - child = iface->child(0); - // first find the topmost button - QAccessibleInterface *other; - while (child->navigate(QAccessible::Up, 1, &other) != -1) { - delete child; - child = other; - } - other = child; - - // then traverse from top to bottom to find the correct order of the buttons - actualOrder.clear(); - int right = 0; - while (right != -1) { - actualOrder << other->text(QAccessible::Name, 0); - right = other->navigate(QAccessible::Down, 1, &child); - delete other; - other = child; - } - - QStringList expectedOrder; - expectedOrder << QDialogButtonBox::tr("OK") - << QDialogButtonBox::tr("Reset") - << QDialogButtonBox::tr("Help"); - - QCOMPARE(actualOrder, expectedOrder); - delete iface; - QApplication::processEvents(); - - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::dialTest() -{ - { - QDial dial; - dial.setMinimum(23); - dial.setMaximum(121); - dial.setValue(42); - QCOMPARE(dial.value(), 42); - dial.show(); - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial); - QVERIFY(interface); - QCOMPARE(interface->childCount(), 0); - - QCOMPARE(interface->text(QAccessible::Value, 0), QString::number(dial.value())); - QCOMPARE(interface->rect(), dial.geometry()); - - QAccessibleValueInterface *valueIface = interface->valueInterface(); - QVERIFY(valueIface != 0); - QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum()); - QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum()); - QCOMPARE(valueIface->currentValue().toInt(), 42); - dial.setValue(50); - QCOMPARE(valueIface->currentValue().toInt(), dial.value()); - dial.setValue(0); - QCOMPARE(valueIface->currentValue().toInt(), dial.value()); - dial.setValue(100); - QCOMPARE(valueIface->currentValue().toInt(), dial.value()); - valueIface->setCurrentValue(77); - QCOMPARE(77, dial.value()); - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::rubberBandTest() -{ - QRubberBand rubberBand(QRubberBand::Rectangle); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand); - QVERIFY(interface); - QCOMPARE(interface->role(), QAccessible::Border); - delete interface; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::abstractScrollAreaTest() -{ - { - QAbstractScrollArea abstractScrollArea; - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea); - QVERIFY(interface); - QVERIFY(!interface->rect().isValid()); - QCOMPARE(interface->childAt(200, 200), -1); - - abstractScrollArea.resize(400, 400); - abstractScrollArea.show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)), - abstractScrollArea.size()); - - // Viewport. - QCOMPARE(interface->childCount(), 1); - QWidget *viewport = abstractScrollArea.viewport(); - QVERIFY(viewport); - QVERIFY(verifyChild(viewport, interface, 1, globalGeometry)); - - // Horizontal scrollBar. - abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - QCOMPARE(interface->childCount(), 2); - QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar(); - QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget(); - QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry)); - - // Horizontal scrollBar widgets. - QLabel *secondLeftLabel = new QLabel(QLatin1String("L2")); - abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft); - QCOMPARE(interface->childCount(), 2); - - QLabel *firstLeftLabel = new QLabel(QLatin1String("L1")); - abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft); - QCOMPARE(interface->childCount(), 2); - - QLabel *secondRightLabel = new QLabel(QLatin1String("R2")); - abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight); - QCOMPARE(interface->childCount(), 2); - - QLabel *firstRightLabel = new QLabel(QLatin1String("R1")); - abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight); - QCOMPARE(interface->childCount(), 2); - - // Vertical scrollBar. - abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - QCOMPARE(interface->childCount(), 3); - QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar(); - QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget(); - QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry)); - - // Vertical scrollBar widgets. - QLabel *secondTopLabel = new QLabel(QLatin1String("T2")); - abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop); - QCOMPARE(interface->childCount(), 3); - - QLabel *firstTopLabel = new QLabel(QLatin1String("T1")); - abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop); - QCOMPARE(interface->childCount(), 3); - - QLabel *secondBottomLabel = new QLabel(QLatin1String("B2")); - abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom); - QCOMPARE(interface->childCount(), 3); - - QLabel *firstBottomLabel = new QLabel(QLatin1String("B1")); - abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom); - QCOMPARE(interface->childCount(), 3); - - // CornerWidget. - abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C"))); - QCOMPARE(interface->childCount(), 4); - QWidget *cornerWidget = abstractScrollArea.cornerWidget(); - QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry)); - - // Test navigate. - QAccessibleInterface *target = 0; - - // viewport -> Up -> NOTHING - const int viewportIndex = indexOfChild(interface, viewport); - QVERIFY(viewportIndex != -1); - QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1); - QVERIFY(!target); - - // viewport -> Left -> NOTHING - QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1); - QVERIFY(!target); - - // viewport -> Down -> horizontalScrollBarContainer - const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer); - QVERIFY(horizontalScrollBarContainerIndex != -1); - QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0); - QVERIFY(target); - QCOMPARE(target->object(), static_cast(horizontalScrollBarContainer)); - delete target; - target = 0; - - // horizontalScrollBarContainer -> Left -> NOTHING - QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1); - QVERIFY(!target); - - // horizontalScrollBarContainer -> Down -> NOTHING - QVERIFY(horizontalScrollBarContainerIndex != -1); - QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1); - QVERIFY(!target); - - // horizontalScrollBarContainer -> Right -> cornerWidget - const int cornerWidgetIndex = indexOfChild(interface, cornerWidget); - QVERIFY(cornerWidgetIndex != -1); - QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0); - QVERIFY(target); - QCOMPARE(target->object(), static_cast(cornerWidget)); - delete target; - target = 0; - - // cornerWidget -> Down -> NOTHING - QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1); - QVERIFY(!target); - - // cornerWidget -> Right -> NOTHING - QVERIFY(cornerWidgetIndex != -1); - QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1); - QVERIFY(!target); - - // cornerWidget -> Up -> verticalScrollBarContainer - const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer); - QVERIFY(verticalScrollBarContainerIndex != -1); - QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0); - QVERIFY(target); - QCOMPARE(target->object(), static_cast(verticalScrollBarContainer)); - delete target; - target = 0; - - // verticalScrollBarContainer -> Right -> NOTHING - QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1); - QVERIFY(!target); - - // verticalScrollBarContainer -> Up -> NOTHING - QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1); - QVERIFY(!target); - - // verticalScrollBarContainer -> Left -> viewport - QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0); - QVERIFY(target); - QCOMPARE(target->object(), static_cast(viewport)); - delete target; - target = 0; - - QCOMPARE(verifyHierarchy(interface), 0); - - delete interface; - } - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::scrollAreaTest() -{ - { - QScrollArea scrollArea; - scrollArea.show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea); - QVERIFY(interface); - QCOMPARE(interface->childCount(), 1); // The viewport. - delete interface; - } - QTestAccessibility::clearEvents(); -} - -// Accessible table1 interface is no longer supported on X11, -// where it has been replaced by table2 interface. -#ifndef Q_OS_UNIX - -void tst_QAccessibility::listViewTest() -{ - { - QListView listView; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); - QVERIFY(iface); - QCOMPARE(iface->childCount(), 1); - delete iface; - } - { - QListWidget listView; - listView.addItem(tr("A")); - listView.addItem(tr("B")); - listView.addItem(tr("C")); - listView.resize(400,400); - listView.show(); - QTest::qWait(1); // Need this for indexOfchild to work. - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); - QCOMPARE((int)iface->role(), (int)QAccessible::Client); - QCOMPARE((int)iface->role(1), (int)QAccessible::List); - QCOMPARE(iface->childCount(), 1); - QAccessibleInterface *child; - iface->navigate(QAccessible::Child, 1, &child); - delete iface; - iface = child; - QCOMPARE(iface->text(QAccessible::Name, 1), QString("A")); - QCOMPARE(iface->text(QAccessible::Name, 2), QString("B")); - QCOMPARE(iface->text(QAccessible::Name, 3), QString("C")); - - QCOMPARE(iface->childCount(), 3); - - QAccessibleInterface *childA = 0; - QCOMPARE(iface->navigate(QAccessible::Child, 1, &childA), 0); - QVERIFY(childA); - QCOMPARE(iface->indexOfChild(childA), 1); - QCOMPARE(childA->text(QAccessible::Name, 1), QString("A")); - delete childA; - - QAccessibleInterface *childB = 0; - QCOMPARE(iface->navigate(QAccessible::Child, 2, &childB), 0); - QVERIFY(childB); - QCOMPARE(iface->indexOfChild(childB), 2); - QCOMPARE(childB->text(QAccessible::Name, 1), QString("B")); - delete childB; - - QAccessibleInterface *childC = 0; - QCOMPARE(iface->navigate(QAccessible::Child, 3, &childC), 0); - QVERIFY(childC); - QCOMPARE(iface->indexOfChild(childC), 3); - QCOMPARE(childC->text(QAccessible::Name, 1), QString("C")); - delete childC; - QTestAccessibility::clearEvents(); - - // Check for events - QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(1)).center()); - QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(2)).center()); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView.viewport(), 2, QAccessible::Selection))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView.viewport(), 3, QAccessible::Selection))); - delete iface; - } - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::treeWidgetTest() -{ - QWidget *w = new QWidget; - QTreeWidget *tree = new QTreeWidget(w); - QHBoxLayout *l = new QHBoxLayout(w); - l->addWidget(tree); - for (int i = 0; i < 10; ++i) { - QStringList strings = QStringList() << QString::fromAscii("row: %1").arg(i) - << QString("column 1") << QString("column 2"); - - tree->addTopLevelItem(new QTreeWidgetItem(strings)); - } - w->show(); - - QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(tree); - QAccessibleInterface *accViewport = 0; - int entry = acc->navigate(QAccessible::Child, 1, &accViewport); - QVERIFY(accViewport); - QCOMPARE(entry, 0); - QAccessibleInterface *accTreeItem = 0; - entry = accViewport->navigate(QAccessible::Child, 1, &accTreeItem); - QCOMPARE(entry, 0); - - QAccessibleInterface *accTreeItem2 = 0; - entry = accTreeItem->navigate(QAccessible::Sibling, 3, &accTreeItem2); - QCOMPARE(entry, 0); - QCOMPARE(accTreeItem2->text(QAccessible::Name, 0), QLatin1String("row: 1")); - - // test selected/focused state - QItemSelectionModel *selModel = tree->selectionModel(); - QVERIFY(selModel); - selModel->select(QItemSelection(tree->model()->index(0, 0), tree->model()->index(3, 0)), QItemSelectionModel::Select); - selModel->setCurrentIndex(tree->model()->index(1, 0), QItemSelectionModel::Current); - - for (int i = 1; i < 10 ; ++i) { - QAccessible::State expected; - if (i <= 5 && i >= 2) - expected = QAccessible::Selected; - if (i == 3) - expected |= QAccessible::Focused; - - QCOMPARE(accViewport->state(i) & (QAccessible::Focused | QAccessible::Selected), expected); - } - - // Test sanity of its navigation functions - QCOMPARE(verifyHierarchy(acc), 0); - - delete accTreeItem2; - delete accTreeItem; - delete accViewport; - delete acc; - delete w; - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::tableWidgetTest() -{ - { - QWidget *topLevel = new QWidget; - QTableWidget *w = new QTableWidget(8,4,topLevel); - for (int r = 0; r < 8; ++r) { - for (int c = 0; c < 4; ++c) { - w->setItem(r, c, new QTableWidgetItem(tr("%1,%2").arg(c).arg(r))); - } - } - w->resize(100, 100); - topLevel->show(); - - QAccessibleInterface *client = QAccessible::queryAccessibleInterface(w); - QCOMPARE(client->role(), QAccessible::Client); - QCOMPARE(client->childCount(), 3); - QAccessibleInterface *view = 0; - view = client->child(0); - QCOMPARE(view->role(), QAccessible::Table); - QAccessibleInterface *ifRow; - ifRow = view->child(1); - QCOMPARE(ifRow->role(), QAccessible::Row); - QAccessibleInterface *item; - int entry = ifRow->navigate(QAccessible::Child, 1, &item); - QCOMPARE(entry, 1); - QCOMPARE(item , (QAccessibleInterface*)0); - QCOMPARE(ifRow->text(QAccessible::Name, 2), QLatin1String("0,0")); - QCOMPARE(ifRow->text(QAccessible::Name, 3), QLatin1String("1,0")); - - QCOMPARE(verifyHierarchy(client), 0); - - delete ifRow; - delete view; - delete client; - delete w; - delete topLevel; - } - QTestAccessibility::clearEvents(); -} - -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) {} - - int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; } - int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; } - - 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(); - } - - 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(); - } - - 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(); - } - - void reset() - { - QAbstractTableModel::reset(); - } - - int row_count; - int column_count; -}; - -class QtTestDelegate : public QItemDelegate -{ -public: - QtTestDelegate(QWidget *parent = 0) : QItemDelegate(parent) {} - - virtual QSize sizeHint(const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/) const - { - return QSize(100,50); - } -}; - -void tst_QAccessibility::tableViewTest() -{ - { - QtTestTableModel *model = new QtTestTableModel(3, 4); - QTableView *w = new QTableView(); - w->setModel(model); - w->setItemDelegate(new QtTestDelegate(w)); - w->resize(450,200); - w->resizeColumnsToContents(); - w->resizeRowsToContents(); - w->show(); - - QAccessibleInterface *client = QAccessible::queryAccessibleInterface(w); - QAccessibleInterface *table2; - client->navigate(QAccessible::Child, 1, &table2); - QVERIFY(table2); - QCOMPARE(table2->role(1), QAccessible::Row); - QAccessibleInterface *toprow = 0; - table2->navigate(QAccessible::Child, 1, &toprow); - QVERIFY(toprow); - QCOMPARE(toprow->role(1), QAccessible::RowHeader); - QCOMPARE(toprow->role(2), QAccessible::ColumnHeader); - delete toprow; - - // call childAt() for each child until we reach the bottom, - // and do it for each row in the table - for (int y = 1; y < 5; ++y) { // this includes the special header - for (int x = 1; x < 6; ++x) { - QCOMPARE(client->role(), QAccessible::Client); - QRect globalRect = client->rect(); - QVERIFY(globalRect.isValid()); - // make sure we don't hit the vertical header ##### - QPoint p = globalRect.topLeft() + QPoint(8, 8); - p.ry() += 50 * (y - 1); - p.rx() += 100 * (x - 1); - int index = client->childAt(p.x(), p.y()); - QCOMPARE(index, 1); - QCOMPARE(client->role(index), QAccessible::Table); - - // navigate to table/viewport - QAccessibleInterface *table; - client->navigate(QAccessible::Child, index, &table); - QVERIFY(table); - index = table->childAt(p.x(), p.y()); - QCOMPARE(index, y); - QCOMPARE(table->role(index), QAccessible::Row); - QAccessibleInterface *row; - QCOMPARE(table->role(1), QAccessible::Row); - - // navigate to the row - table->navigate(QAccessible::Child, index, &row); - QVERIFY(row); - QCOMPARE(row->role(1), QAccessible::RowHeader); - index = row->childAt(p.x(), p.y()); - QVERIFY(index > 0); - if (x == 1 && y == 1) { - QCOMPARE(row->role(index), QAccessible::RowHeader); - QCOMPARE(row->text(QAccessible::Name, index), QLatin1String("")); - } else if (x > 1 && y > 1) { - QCOMPARE(row->role(index), QAccessible::Cell); - QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("[%1,%2,0]").arg(y - 2).arg(x - 2)); - } else if (x == 1) { - QCOMPARE(row->role(index), QAccessible::RowHeader); - QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("%1").arg(y - 1)); - } else if (y == 1) { - QCOMPARE(row->role(index), QAccessible::ColumnHeader); - QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("%1").arg(x - 1)); - } - delete table; - delete row; - } - } - delete table2; - delete client; - delete w; - delete model; - } - QTestAccessibility::clearEvents(); -} - -#else -// Test accessible table2 interface on unix - -void tst_QAccessibility::table2ListTest() -{ - QListWidget *listView = new QListWidget; - listView->addItem("Oslo"); - listView->addItem("Berlin"); - listView->addItem("Brisbane"); - listView->resize(400,400); - listView->show(); - QTest::qWait(1); // Need this for indexOfchild to work. - QCoreApplication::processEvents(); - QTest::qWait(100); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); - QCOMPARE(verifyHierarchy(iface), 0); - - QCOMPARE((int)iface->role(), (int)QAccessible::List); - QCOMPARE(iface->childCount(), 3); - - QAccessibleInterface *child1 = 0; - child1 = iface->child(0); - QVERIFY(child1); - QCOMPARE(iface->indexOfChild(child1), 1); - QCOMPARE(child1->text(QAccessible::Name, 0), QString("Oslo")); - QCOMPARE(child1->role(), QAccessible::ListItem); - delete child1; - - QAccessibleInterface *child2 = 0; - child2 = iface->child(1); - QVERIFY(child2); - QCOMPARE(iface->indexOfChild(child2), 2); - QCOMPARE(child2->text(QAccessible::Name, 0), QString("Berlin")); - delete child2; - - QAccessibleInterface *child3 = 0; - child3 = iface->child(2); - QVERIFY(child3); - QCOMPARE(iface->indexOfChild(child3), 3); - QCOMPARE(child3->text(QAccessible::Name, 0), QString("Brisbane")); - delete child3; - QTestAccessibility::clearEvents(); - - // Check for events - QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center()); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus))); - QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center()); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus))); - - listView->addItem("Munich"); - QCOMPARE(iface->childCount(), 4); - - // table 2 - QAccessibleTable2Interface *table2 = iface->table2Interface(); - QVERIFY(table2); - QCOMPARE(table2->columnCount(), 1); - QCOMPARE(table2->rowCount(), 4); - QAccessibleTable2CellInterface *cell1; - QVERIFY(cell1 = table2->cellAt(0,0)); - QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Oslo")); - QAccessibleTable2CellInterface *cell4; - QVERIFY(cell4 = table2->cellAt(3,0)); - QCOMPARE(cell4->text(QAccessible::Name, 0), QString("Munich")); - QCOMPARE(cell4->role(), QAccessible::ListItem); - QCOMPARE(cell4->rowIndex(), 3); - QCOMPARE(cell4->columnIndex(), 0); - QVERIFY(!cell4->isExpandable()); - - delete cell4; - delete cell1; - delete iface; - delete listView; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::table2TreeTest() -{ - QTreeWidget *treeView = new QTreeWidget; - treeView->setColumnCount(2); - QTreeWidgetItem *header = new QTreeWidgetItem; - header->setText(0, "Artist"); - header->setText(1, "Work"); - treeView->setHeaderItem(header); - - QTreeWidgetItem *root1 = new QTreeWidgetItem; - root1->setText(0, "Spain"); - treeView->addTopLevelItem(root1); - - QTreeWidgetItem *item1 = new QTreeWidgetItem; - item1->setText(0, "Picasso"); - item1->setText(1, "Guernica"); - root1->addChild(item1); - - QTreeWidgetItem *item2 = new QTreeWidgetItem; - item2->setText(0, "Tapies"); - item2->setText(1, "Ambrosia"); - root1->addChild(item2); - - QTreeWidgetItem *root2 = new QTreeWidgetItem; - root2->setText(0, "Austria"); - treeView->addTopLevelItem(root2); - - QTreeWidgetItem *item3 = new QTreeWidgetItem; - item3->setText(0, "Klimt"); - item3->setText(1, "The Kiss"); - root2->addChild(item3); - - treeView->resize(400,400); - treeView->show(); - - QCoreApplication::processEvents(); - QTest::qWait(100); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView); - QCOMPARE(verifyHierarchy(iface), 0); - - QCOMPARE((int)iface->role(), (int)QAccessible::Tree); - // header and 2 rows (the others are not expanded, thus not visible) - QCOMPARE(iface->childCount(), 6); - - QAccessibleInterface *header1 = 0; - header1 = iface->child(0); - QVERIFY(header1); - QCOMPARE(iface->indexOfChild(header1), 1); - QCOMPARE(header1->text(QAccessible::Name, 0), QString("Artist")); - QCOMPARE(header1->role(), QAccessible::ColumnHeader); - delete header1; - - QAccessibleInterface *child1 = 0; - child1 = iface->child(2); - QVERIFY(child1); - QCOMPARE(iface->indexOfChild(child1), 3); - QCOMPARE(child1->text(QAccessible::Name, 0), QString("Spain")); - QCOMPARE(child1->role(), QAccessible::TreeItem); - QVERIFY(!(child1->state() & QAccessible::Expanded)); - delete child1; - - QAccessibleInterface *child2 = 0; - child2 = iface->child(4); - QVERIFY(child2); - QCOMPARE(iface->indexOfChild(child2), 5); - QCOMPARE(child2->text(QAccessible::Name, 0), QString("Austria")); - delete child2; - - QTestAccessibility::clearEvents(); - - // table 2 - QAccessibleTable2Interface *table2 = iface->table2Interface(); - QVERIFY(table2); - QCOMPARE(table2->columnCount(), 2); - QCOMPARE(table2->rowCount(), 2); - QAccessibleTable2CellInterface *cell1; - QVERIFY(cell1 = table2->cellAt(0,0)); - QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Spain")); - QAccessibleTable2CellInterface *cell2; - QVERIFY(cell2 = table2->cellAt(1,0)); - QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Austria")); - QCOMPARE(cell2->role(), QAccessible::TreeItem); - QCOMPARE(cell2->rowIndex(), 1); - QCOMPARE(cell2->columnIndex(), 0); - QVERIFY(cell2->isExpandable()); - QCOMPARE(iface->indexOfChild(cell2), 5); - QVERIFY(!(cell2->state() & QAccessible::Expanded)); - QCOMPARE(table2->columnDescription(1), QString("Work")); - delete cell2; - delete cell1; - - treeView->expandAll(); - - // Need this for indexOfchild to work. - QCoreApplication::processEvents(); - QTest::qWait(100); - - QCOMPARE(table2->columnCount(), 2); - QCOMPARE(table2->rowCount(), 5); - cell1 = table2->cellAt(1,0); - QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Picasso")); - QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item - - cell2 = table2->cellAt(4,0); - QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Klimt")); - QCOMPARE(cell2->role(), QAccessible::TreeItem); - QCOMPARE(cell2->rowIndex(), 4); - QCOMPARE(cell2->columnIndex(), 0); - QVERIFY(!cell2->isExpandable()); - QCOMPARE(iface->indexOfChild(cell2), 11); - - QCOMPARE(table2->columnDescription(0), QString("Artist")); - QCOMPARE(table2->columnDescription(1), QString("Work")); - - delete iface; - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::table2TableTest() -{ - QTableWidget *tableView = new QTableWidget(3, 3); - tableView->setColumnCount(3); - QStringList hHeader; - hHeader << "h1" << "h2" << "h3"; - tableView->setHorizontalHeaderLabels(hHeader); - - QStringList vHeader; - vHeader << "v1" << "v2" << "v3"; - tableView->setVerticalHeaderLabels(vHeader); - - for (int i = 0; i<9; ++i) { - QTableWidgetItem *item = new QTableWidgetItem; - item->setText(QString::number(i/3) + QString(".") + QString::number(i%3)); - tableView->setItem(i/3, i%3, item); - } - - tableView->resize(600,600); - tableView->show(); - QTest::qWait(1); // Need this for indexOfchild to work. - QCoreApplication::processEvents(); - QTest::qWait(100); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView); - QCOMPARE(verifyHierarchy(iface), 0); - - QCOMPARE((int)iface->role(), (int)QAccessible::Table); - // header and 2 rows (the others are not expanded, thus not visible) - QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button - - QAccessibleInterface *cornerButton = iface->child(0); - QVERIFY(cornerButton); - QCOMPARE(iface->indexOfChild(cornerButton), 1); - QCOMPARE(cornerButton->role(), QAccessible::Pane); - delete cornerButton; - - QAccessibleInterface *child1 = iface->child(2); - QVERIFY(child1); - QCOMPARE(iface->indexOfChild(child1), 3); - QCOMPARE(child1->text(QAccessible::Name, 0), QString("h2")); - QCOMPARE(child1->role(), QAccessible::ColumnHeader); - QVERIFY(!(child1->state() & QAccessible::Expanded)); - delete child1; - - QAccessibleInterface *child2 = iface->child(10); - QVERIFY(child2); - QCOMPARE(iface->indexOfChild(child2), 11); - QCOMPARE(child2->text(QAccessible::Name, 0), QString("1.1")); - QAccessibleTable2CellInterface *cell2Iface = static_cast(child2); - QCOMPARE(cell2Iface->rowIndex(), 1); - QCOMPARE(cell2Iface->columnIndex(), 1); - delete child2; - - QAccessibleInterface *child3 = iface->child(11); - QCOMPARE(iface->indexOfChild(child3), 12); - QCOMPARE(child3->text(QAccessible::Name, 0), QString("1.2")); - delete child3; - - QTestAccessibility::clearEvents(); - - // table 2 - QAccessibleTable2Interface *table2 = iface->table2Interface(); - QVERIFY(table2); - QCOMPARE(table2->columnCount(), 3); - QCOMPARE(table2->rowCount(), 3); - QAccessibleTable2CellInterface *cell1; - QVERIFY(cell1 = table2->cellAt(0,0)); - QCOMPARE(cell1->text(QAccessible::Name, 0), QString("0.0")); - QCOMPARE(iface->indexOfChild(cell1), 6); - - QAccessibleTable2CellInterface *cell2; - QVERIFY(cell2 = table2->cellAt(0,1)); - QCOMPARE(cell2->text(QAccessible::Name, 0), QString("0.1")); - QCOMPARE(cell2->role(), QAccessible::Cell); - QCOMPARE(cell2->rowIndex(), 0); - QCOMPARE(cell2->columnIndex(), 1); - QCOMPARE(iface->indexOfChild(cell2), 7); - delete cell2; - - QAccessibleTable2CellInterface *cell3; - QVERIFY(cell3 = table2->cellAt(1,2)); - QCOMPARE(cell3->text(QAccessible::Name, 0), QString("1.2")); - QCOMPARE(cell3->role(), QAccessible::Cell); - QCOMPARE(cell3->rowIndex(), 1); - QCOMPARE(cell3->columnIndex(), 2); - QCOMPARE(iface->indexOfChild(cell3), 12); - delete cell3; - - QCOMPARE(table2->columnDescription(0), QString("h1")); - QCOMPARE(table2->columnDescription(1), QString("h2")); - QCOMPARE(table2->columnDescription(2), QString("h3")); - QCOMPARE(table2->rowDescription(0), QString("v1")); - QCOMPARE(table2->rowDescription(1), QString("v2")); - QCOMPARE(table2->rowDescription(2), QString("v3")); - - delete iface; - - delete tableView; - - QTestAccessibility::clearEvents(); -} -#endif - -void tst_QAccessibility::calendarWidgetTest() -{ -#ifndef QT_NO_CALENDARWIDGET - { - QCalendarWidget calendarWidget; - - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget); - QVERIFY(interface); - QCOMPARE(interface->role(), QAccessible::Table); - QVERIFY(!interface->rect().isValid()); - QVERIFY(!interface->rect(1).isValid()); - QCOMPARE(interface->childAt(200, 200), -1); - - calendarWidget.resize(400, 300); - calendarWidget.show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - - // 1 = navigationBar, 2 = view. - QCOMPARE(interface->childCount(), 2); - - const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)), - calendarWidget.size()); - QCOMPARE(interface->rect(), globalGeometry); - - QWidget *navigationBar = 0; - foreach (QObject *child, calendarWidget.children()) { - if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) { - navigationBar = static_cast(child); - break; - } - } - QVERIFY(navigationBar); - QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry)); - - QAbstractItemView *calendarView = 0; - foreach (QObject *child, calendarWidget.children()) { - if (child->objectName() == QLatin1String("qt_calendar_calendarview")) { - calendarView = static_cast(child); - break; - } - } - QVERIFY(calendarView); - QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry)); - - // Hide navigation bar. - calendarWidget.setNavigationBarVisible(false); - QCOMPARE(interface->childCount(), 1); - QVERIFY(!navigationBar->isVisible()); - - QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry)); - - // Show navigation bar. - calendarWidget.setNavigationBarVisible(true); - QCOMPARE(interface->childCount(), 2); - QVERIFY(navigationBar->isVisible()); - - // Navigate to the navigation bar via Child. - QAccessibleInterface *navigationBarInterface = interface->child(0); - QVERIFY(navigationBarInterface); - QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar); - delete navigationBarInterface; - navigationBarInterface = 0; - - // Navigate to the view via Child. - QAccessibleInterface *calendarViewInterface = interface->child(1); - QVERIFY(calendarViewInterface); - QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView); - delete calendarViewInterface; - calendarViewInterface = 0; - - QVERIFY(!interface->child(-1)); - - // Navigate from navigation bar -> view (Down). - QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0); - QVERIFY(calendarViewInterface); - QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView); - delete calendarViewInterface; - calendarViewInterface = 0; - - // Navigate from view -> navigation bar (Up). - QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0); - QVERIFY(navigationBarInterface); - QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar); - delete navigationBarInterface; - navigationBarInterface = 0; - - } - QTestAccessibility::clearEvents(); -#endif // QT_NO_CALENDARWIDGET -} - -void tst_QAccessibility::dockWidgetTest() -{ -#ifndef QT_NO_DOCKWIDGET - // Set up a proper main window with two dock widgets - QMainWindow *mw = new QMainWindow(); - QFrame *central = new QFrame(mw); - mw->setCentralWidget(central); - QMenuBar *mb = new QMenuBar(mw); - mb->addAction(tr("&File")); - mw->setMenuBar(mb); - - QDockWidget *dock1 = new QDockWidget(mw); - mw->addDockWidget(Qt::LeftDockWidgetArea, dock1); - QPushButton *pb1 = new QPushButton(tr("Push me"), dock1); - dock1->setWidget(pb1); - - QDockWidget *dock2 = new QDockWidget(mw); - mw->addDockWidget(Qt::BottomDockWidgetArea, dock2); - QPushButton *pb2 = new QPushButton(tr("Push me"), dock2); - dock2->setWidget(pb2); - - mw->resize(600,400); - mw->show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif - - QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw); - // 4 children: menu bar, dock1, dock2, and central widget - QCOMPARE(accMainWindow->childCount(), 4); - QAccessibleInterface *accDock1 = 0; - for (int i = 1; i <= 4; ++i) { - if (accMainWindow->role(i) == QAccessible::Window) { - accDock1 = accMainWindow->child(i-1); - if (accDock1 && qobject_cast(accDock1->object()) == dock1) { - break; - } else { - delete accDock1; - } - } - } - QVERIFY(accDock1); - QCOMPARE(accDock1->role(), QAccessible::Window); - QCOMPARE(accDock1->role(1), QAccessible::TitleBar); - QVERIFY(accDock1->rect().contains(accDock1->rect(1))); - - QPoint globalPos = dock1->mapToGlobal(QPoint(0,0)); - globalPos.rx()+=5; //### query style - globalPos.ry()+=5; - int entry = accDock1->childAt(globalPos.x(), globalPos.y()); //### - QCOMPARE(entry, 1); - QAccessibleInterface *accTitleBar = accDock1->child(entry - 1); - - QCOMPARE(accTitleBar->role(), QAccessible::TitleBar); - QCOMPARE(accDock1->indexOfChild(accTitleBar), 1); - QAccessibleInterface *acc; - acc = accTitleBar->parent(); - QVERIFY(acc); - QCOMPARE(acc->role(), QAccessible::Window); - - - delete accTitleBar; - delete accDock1; - delete pb1; - delete pb2; - delete dock1; - delete dock2; - delete mw; - QTestAccessibility::clearEvents(); -#endif // QT_NO_DOCKWIDGET -} - -void tst_QAccessibility::comboBoxTest() -{ -#if defined(Q_OS_WINCE) - if (!IsValidCEPlatform()) { - QSKIP("Test skipped on Windows Mobile test hardware", SkipAll); - } -#endif - { // not editable combobox - QComboBox combo; - combo.addItems(QStringList() << "one" << "two" << "three"); - combo.show(); - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo); - QCOMPARE(verifyHierarchy(iface), 0); - - QCOMPARE(iface->role(), QAccessible::ComboBox); - QCOMPARE(iface->childCount(), 1); - -#ifdef Q_OS_UNIX - QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one")); -#endif - QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one")); - combo.setCurrentIndex(2); -#ifdef Q_OS_UNIX - QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three")); -#endif - QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three")); - - QAccessibleInterface *listIface = iface->child(0); - QCOMPARE(listIface->role(), QAccessible::List); - QCOMPARE(listIface->childCount(), 3); - - QVERIFY(!combo.view()->isVisible()); - QVERIFY(iface->actionInterface()); - QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction); - iface->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction); - QVERIFY(combo.view()->isVisible()); - - delete iface; - } - - { // editable combobox - QComboBox editableCombo; - editableCombo.show(); - editableCombo.setEditable(true); - editableCombo.addItems(QStringList() << "foo" << "bar" << "baz"); - - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo); - QCOMPARE(verifyHierarchy(iface), 0); - - QCOMPARE(iface->role(), QAccessible::ComboBox); - QCOMPARE(iface->childCount(), 2); - - QAccessibleInterface *listIface = iface->child(0); - QCOMPARE(listIface->role(), QAccessible::List); - QAccessibleInterface *editIface = iface->child(1); - QCOMPARE(editIface->role(), QAccessible::EditableText); - - delete listIface; - delete editIface; - delete iface; - } - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::labelTest() -{ - QString text = "Hello World"; - QLabel *label = new QLabel(text); - label->show(); - -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); -#endif - QTest::qWait(100); - - QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label); - QVERIFY(acc_label); - - QCOMPARE(acc_label->text(QAccessible::Name, 0), text); - - delete acc_label; - delete label; - QTestAccessibility::clearEvents(); - - QPixmap testPixmap(50, 50); - testPixmap.fill(); - - QLabel imageLabel; - imageLabel.setPixmap(testPixmap); - imageLabel.setToolTip("Test Description"); - - acc_label = QAccessible::queryAccessibleInterface(&imageLabel); - QVERIFY(acc_label); - - QAccessibleImageInterface *imageInterface = acc_label->imageInterface(); - QVERIFY(imageInterface); - - QCOMPARE(imageInterface->imageSize(), testPixmap.size()); - QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description")); - QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry()); - - delete acc_label; - - QTestAccessibility::clearEvents(); -} - -void tst_QAccessibility::accelerators() -{ - QWidget *window = new QWidget; - QHBoxLayout *lay = new QHBoxLayout(window); - QLabel *label = new QLabel(tr("&Line edit"), window); - QLineEdit *le = new QLineEdit(window); - lay->addWidget(label); - lay->addWidget(le); - label->setBuddy(le); - - window->show(); - - QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L")); - label->setText(tr("Q &")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); - label->setText(tr("Q &&")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); - label->setText(tr("Q && A")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); - label->setText(tr("Q &&&A")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A")); - label->setText(tr("Q &&A")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString()); - -#if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC) - QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'"); -#endif - label->setText(tr("Q &A&B")); - QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A")); - -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); -#endif - QTest::qWait(100); - delete window; - QTestAccessibility::clearEvents(); -} - -QTEST_MAIN(tst_QAccessibility) -#include "tst_qaccessibility.moc" diff --git a/tests/auto/qaction/.gitignore b/tests/auto/qaction/.gitignore deleted file mode 100644 index bf81f5bf2c..0000000000 --- a/tests/auto/qaction/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qaction diff --git a/tests/auto/qaction/qaction.pro b/tests/auto/qaction/qaction.pro deleted file mode 100644 index 9c3648d52f..0000000000 --- a/tests/auto/qaction/qaction.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qaction.cpp - - diff --git a/tests/auto/qaction/tst_qaction.cpp b/tests/auto/qaction/tst_qaction.cpp deleted file mode 100644 index 637ec144d2..0000000000 --- a/tests/auto/qaction/tst_qaction.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -//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("text"); - QTest::addColumn("iconText"); - QTest::addColumn("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 list; - act.setShortcuts(list); - act.setShortcuts(QKeySequence::Copy); - QVERIFY(act.shortcut() == act.shortcuts().first()); - - QList 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 shlist = QList() << 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/qactiongroup/.gitignore b/tests/auto/qactiongroup/.gitignore deleted file mode 100644 index daba003e96..0000000000 --- a/tests/auto/qactiongroup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qactiongroup diff --git a/tests/auto/qactiongroup/qactiongroup.pro b/tests/auto/qactiongroup/qactiongroup.pro deleted file mode 100644 index 9b8636968b..0000000000 --- a/tests/auto/qactiongroup/qactiongroup.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qactiongroup.cpp - - diff --git a/tests/auto/qactiongroup/tst_qactiongroup.cpp b/tests/auto/qactiongroup/tst_qactiongroup.cpp deleted file mode 100644 index 406298807a..0000000000 --- a/tests/auto/qactiongroup/tst_qactiongroup.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -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 it(actGroup.actions()); - while (it.hasNext()) - menu.addAction(it.next()); - - QCOMPARE((int)menu.actions().size(), 2 + numSoftkeyActions); - - it = QListIterator(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(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/qapplication/.gitignore b/tests/auto/qapplication/.gitignore deleted file mode 100644 index ca666e480a..0000000000 --- a/tests/auto/qapplication/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -tst_qapplication -desktopsettingsaware/desktopsettingsaware -wincmdline/wincmdline diff --git a/tests/auto/qapplication/desktopsettingsaware/desktopsettingsaware.pro b/tests/auto/qapplication/desktopsettingsaware/desktopsettingsaware.pro deleted file mode 100644 index 216a9710c7..0000000000 --- a/tests/auto/qapplication/desktopsettingsaware/desktopsettingsaware.pro +++ /dev/null @@ -1,14 +0,0 @@ -###################################################################### -# 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/qapplication/desktopsettingsaware/main.cpp b/tests/auto/qapplication/desktopsettingsaware/main.cpp deleted file mode 100644 index 9e2172829a..0000000000 --- a/tests/auto/qapplication/desktopsettingsaware/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -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/qapplication/heart.svg b/tests/auto/qapplication/heart.svg deleted file mode 100644 index 8c982cd93c..0000000000 --- a/tests/auto/qapplication/heart.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - -Heart Left-Highlight -This is a normal valentines day heart. - - -holiday -valentines - -valentine -hash(0x8a091c0) -hash(0x8a0916c) -signs_and_symbols -hash(0x8a091f0) -day - - - - -Jon Phillips - - - - -Jon Phillips - - - - -Jon Phillips - - - -image/svg+xml - - -en - - - - - - - - - - - - - - - diff --git a/tests/auto/qapplication/modal/base.cpp b/tests/auto/qapplication/modal/base.cpp deleted file mode 100644 index 2f7b4ad529..0000000000 --- a/tests/auto/qapplication/modal/base.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** 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/qapplication/modal/base.h b/tests/auto/qapplication/modal/base.h deleted file mode 100644 index e1f36e11bd..0000000000 --- a/tests/auto/qapplication/modal/base.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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/qapplication/modal/main.cpp b/tests/auto/qapplication/modal/main.cpp deleted file mode 100644 index 53c6008eb5..0000000000 --- a/tests/auto/qapplication/modal/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#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/qapplication/modal/modal.pro b/tests/auto/qapplication/modal/modal.pro deleted file mode 100644 index 9ed69769bb..0000000000 --- a/tests/auto/qapplication/modal/modal.pro +++ /dev/null @@ -1,9 +0,0 @@ -TEMPLATE = app -QT += widgets -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -SOURCES += main.cpp \ - base.cpp -DESTDIR = ./ -HEADERS += base.h diff --git a/tests/auto/qapplication/qapplication.pro b/tests/auto/qapplication/qapplication.pro deleted file mode 100644 index becc6c6f4b..0000000000 --- a/tests/auto/qapplication/qapplication.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = test \ - desktopsettingsaware \ - modal \ - wincmdline - - diff --git a/tests/auto/qapplication/test/test.pro b/tests/auto/qapplication/test/test.pro deleted file mode 100644 index 65aae7b0b9..0000000000 --- a/tests/auto/qapplication/test/test.pro +++ /dev/null @@ -1,27 +0,0 @@ -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/qapplication/tmp/README b/tests/auto/qapplication/tmp/README deleted file mode 100644 index e758961ddf..0000000000 --- a/tests/auto/qapplication/tmp/README +++ /dev/null @@ -1,3 +0,0 @@ -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/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp deleted file mode 100644 index c37dfc609e..0000000000 --- a/tests/auto/qapplication/tst_qapplication.cpp +++ /dev/null @@ -1,2107 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include - -#include "qabstracteventdispatcher.h" -#include -#include - -#include "private/qapplication_p.h" -#include "private/qstylesheetstyle_p.h" -#ifdef Q_OS_WINCE -#include -#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 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(&obj1)); - - // Test for self-assignment: - obj1.setInputContext(obj1.inputContext()); - QVERIFY(obj1.inputContext()); - QCOMPARE(static_cast(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(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("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("family"); - QTest::addColumn("pointsize"); - QTest::addColumn("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 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("argc_in"); - QTest::addColumn("args_in"); - QTest::addColumn("argc_out"); - QTest::addColumn("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 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 dialog = new QDialog; - QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose)); - QTimer::singleShot(1000, dialog, SLOT(accept())); - dialog->exec(); - QVERIFY(dialog); - QCOMPARE(spy.count(), 0); - - QPointerwidget = 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 mainWindow = new QMainWindow; - QPointer 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 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::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::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::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::fromList(expected).toList(); -# endif - QVERIFY(isPathListIncluded(app.libraryPaths(), expected)); - - qputenv("QT_PLUGIN_PATH", QByteArray()); - } -} - -class SendPostedEventsTester : public QObject -{ - Q_OBJECT -public: - QList 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 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 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(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(wgt, "deleteLater"); - QVERIFY(stillAlive); - - app.exec(); - - delete wgt; - -} - -class EventLoopNester : public QObject -{ - Q_OBJECT -public slots: - void deleteLaterAndEnterLoop() - { - QEventLoop eventLoop; - QPointer 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 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 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 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 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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(spy.count()-1).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(0).at(0)); - now = qVariantValue(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(spy.at(spy.count()-1).at(0)); - else - old = qVariantValue(spy.at(spy.count()-2).at(0)); - now = qVariantValue(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 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("args"); - QTest::addColumn("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 pressedTouchPoints; - QTouchEvent::TouchPoint press(0); - press.setState(Qt::TouchPointPressed); - pressedTouchPoints << press; - - QList 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/qapplication/wincmdline/main.cpp b/tests/auto/qapplication/wincmdline/main.cpp deleted file mode 100644 index d0f802231a..0000000000 --- a/tests/auto/qapplication/wincmdline/main.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -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/qapplication/wincmdline/wincmdline.pro b/tests/auto/qapplication/wincmdline/wincmdline.pro deleted file mode 100644 index 3ba8f48167..0000000000 --- a/tests/auto/qapplication/wincmdline/wincmdline.pro +++ /dev/null @@ -1,8 +0,0 @@ -TEMPLATE = app -TARGET = -DEPENDPATH += . -INCLUDEPATH += . -QT += widgets -SOURCES += main.cpp - - diff --git a/tests/auto/qboxlayout/.gitignore b/tests/auto/qboxlayout/.gitignore deleted file mode 100644 index 034edba563..0000000000 --- a/tests/auto/qboxlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qboxlayout diff --git a/tests/auto/qboxlayout/qboxlayout.pro b/tests/auto/qboxlayout/qboxlayout.pro deleted file mode 100644 index c37f12f74f..0000000000 --- a/tests/auto/qboxlayout/qboxlayout.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qboxlayout.cpp - - diff --git a/tests/auto/qboxlayout/tst_qboxlayout.cpp b/tests/auto/qboxlayout/tst_qboxlayout.cpp deleted file mode 100644 index 4e5b357de5..0000000000 --- a/tests/auto/qboxlayout/tst_qboxlayout.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -//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/qbuttongroup/.gitignore b/tests/auto/qbuttongroup/.gitignore deleted file mode 100644 index 898b2276b0..0000000000 --- a/tests/auto/qbuttongroup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qbuttongroup diff --git a/tests/auto/qbuttongroup/qbuttongroup.pro b/tests/auto/qbuttongroup/qbuttongroup.pro deleted file mode 100644 index 6f506e8f06..0000000000 --- a/tests/auto/qbuttongroup/qbuttongroup.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qbuttongroup.cpp - - - diff --git a/tests/auto/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/qbuttongroup/tst_qbuttongroup.cpp deleted file mode 100644 index f9f6ec0a54..0000000000 --- a/tests/auto/qbuttongroup/tst_qbuttongroup.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include "qbuttongroup.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef Q_WS_MAC -#include -#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 - -//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 *"); - 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*"); - QSignalSpy spy1(buttons, SIGNAL(buttonClicked(QAbstractButton*))); - QSignalSpy spy2(buttons, SIGNAL(buttonClicked(int))); - - QApplication::setActiveWindow(&dlg); - QTRY_COMPARE(QApplication::activeWindow(), static_cast(&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("deleteButton"); - QTest::addColumn("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 *"); - - 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/qcalendarwidget/.gitignore b/tests/auto/qcalendarwidget/.gitignore deleted file mode 100644 index db8a381e0d..0000000000 --- a/tests/auto/qcalendarwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcalendarwidget diff --git a/tests/auto/qcalendarwidget/qcalendarwidget.pro b/tests/auto/qcalendarwidget/qcalendarwidget.pro deleted file mode 100644 index d250b83537..0000000000 --- a/tests/auto/qcalendarwidget/qcalendarwidget.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qcalendarwidget.cpp - - diff --git a/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp deleted file mode 100644 index 50dc6a1d1c..0000000000 --- a/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include - - -//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(&object, "qt_calendar_prevmonth"); - QTest::mouseClick(button, Qt::LeftButton); - QCOMPARE(month > 1 ? month-1 : 12, object.monthShown()); - button = qFindChild(&object, "qt_calendar_nextmonth"); - QTest::mouseClick(button, Qt::LeftButton); - QCOMPARE(month, object.monthShown()); - - button = qFindChild(&object, "qt_calendar_yearbutton"); - QTest::mouseClick(button, Qt::LeftButton, Qt::NoModifier, button->rect().center(), 2); - QVERIFY(!button->isVisible()); - QSpinBox *spinbox = qFindChild(&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(&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(&object, "qt_calendar_prevmonth"); - QTest::mouseClick(button, Qt::LeftButton); - QCOMPARE(1, object.monthShown()); - - button = qFindChild(&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(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("function"); - QTest::addColumn("dateOrigin"); - QTest::addColumn("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(&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/qcheckbox/.gitignore b/tests/auto/qcheckbox/.gitignore deleted file mode 100644 index b838802077..0000000000 --- a/tests/auto/qcheckbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcheckbox diff --git a/tests/auto/qcheckbox/qcheckbox.pro b/tests/auto/qcheckbox/qcheckbox.pro deleted file mode 100644 index aa1f35b3c9..0000000000 --- a/tests/auto/qcheckbox/qcheckbox.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qcheckbox.cpp - - - diff --git a/tests/auto/qcheckbox/tst_qcheckbox.cpp b/tests/auto/qcheckbox/tst_qcheckbox.cpp deleted file mode 100644 index 33f5af4d0b..0000000000 --- a/tests/auto/qcheckbox/tst_qcheckbox.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include "qcheckbox.h" -#include -#include -#include -#include - -//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("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/qcolordialog/.gitignore b/tests/auto/qcolordialog/.gitignore deleted file mode 100644 index b7a8ebd8f8..0000000000 --- a/tests/auto/qcolordialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcolordialog diff --git a/tests/auto/qcolordialog/qcolordialog.pro b/tests/auto/qcolordialog/qcolordialog.pro deleted file mode 100644 index 4f195dac2b..0000000000 --- a/tests/auto/qcolordialog/qcolordialog.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qcolordialog.cpp - - - diff --git a/tests/auto/qcolordialog/tst_qcolordialog.cpp b/tests/auto/qcolordialog/tst_qcolordialog.cpp deleted file mode 100644 index 3ae1e63a8e..0000000000 --- a/tests/auto/qcolordialog/tst_qcolordialog.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -//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[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/qcolumnview/.gitignore b/tests/auto/qcolumnview/.gitignore deleted file mode 100644 index 580ca0edad..0000000000 --- a/tests/auto/qcolumnview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcolumnview diff --git a/tests/auto/qcolumnview/qcolumnview.pro b/tests/auto/qcolumnview/qcolumnview.pro deleted file mode 100644 index bca9e75ba5..0000000000 --- a/tests/auto/qcolumnview/qcolumnview.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += qttest_p4 -QT += widgets widgets-private -QT += gui-private core-private - -SOURCES += tst_qcolumnview.cpp -TARGET = tst_qcolumnview diff --git a/tests/auto/qcolumnview/tst_qcolumnview.cpp b/tests/auto/qcolumnview/tst_qcolumnview.cpp deleted file mode 100644 index 364f917511..0000000000 --- a/tests/auto/qcolumnview/tst_qcolumnview.cpp +++ /dev/null @@ -1,1040 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include "../../../src/widgets/itemviews/qcolumnviewgrip_p.h" -#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h" -#include -#include -#include -#include -#include -#include - -//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 > 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 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(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(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("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("reverse"); - QTest::addColumn("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("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"); - 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("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(list[i]))) { - break; - } - } - if (!grip) - return; - - QAbstractItemView *column = qobject_cast(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 newSizes; - newSizes << 10 << 4 << 50 << 6; - - QList visibleSizes; - view.setColumnWidths(newSizes); - QCOMPARE(view.columnWidths(), visibleSizes); - - QDirModel model; - view.setModel(&model); - QModelIndex home = model.index(QDir::homePath()); - view.setCurrentIndex(home); - - QList postSizes = view.columnWidths().mid(0, newSizes.count()); - QCOMPARE(postSizes, newSizes.mid(0, postSizes.count())); - - QVERIFY(view.columnWidths().count() > 1); - QList smallerSizes; - smallerSizes << 6; - view.setColumnWidths(smallerSizes); - QList 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 > old = view.createdColumns; - view.setCurrentIndex(second); - - QCOMPARE(old, view.createdColumns); -} - -void tst_QColumnView::parentCurrentIndex_data() -{ - QTest::addColumn("firstRow"); - QTest::addColumn("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("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 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/qcombobox/.gitignore b/tests/auto/qcombobox/.gitignore deleted file mode 100644 index 0db112206b..0000000000 --- a/tests/auto/qcombobox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcombobox diff --git a/tests/auto/qcombobox/qcombobox.pro b/tests/auto/qcombobox/qcombobox.pro deleted file mode 100644 index 7f5b57c237..0000000000 --- a/tests/auto/qcombobox/qcombobox.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private gui-private core-private -SOURCES += tst_qcombobox.cpp diff --git a/tests/auto/qcombobox/tst_qcombobox.cpp b/tests/auto/qcombobox/tst_qcombobox.cpp deleted file mode 100644 index cb4468f6f4..0000000000 --- a/tests/auto/qcombobox/tst_qcombobox.cpp +++ /dev/null @@ -1,2579 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include "qcombobox.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef Q_WS_MAC -#include -#elif defined Q_WS_X11 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_STYLE_CLEANLOOKS -#include -#endif -#include -#include -#ifndef QT_NO_STYLE_WINDOWS -#include -#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 VariantList; -typedef QList IconList; - -Q_DECLARE_METATYPE(VariantList) -Q_DECLARE_METATYPE(IconList) -Q_DECLARE_METATYPE(QComboBox::InsertPolicy) - -tst_QComboBox::tst_QComboBox() -{ - qRegisterMetaType("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(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; icount(); ++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("initialEntries"); - QTest::addColumn("insertPolicy"); - QTest::addColumn("currentIndex"); - QTest::addColumn("userInput"); - QTest::addColumn("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; icount(); ++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("initialItems"); - QTest::addColumn("setCurrentIndex"); - QTest::addColumn("removeIndex"); - QTest::addColumn("insertIndex"); - QTest::addColumn("insertText"); - QTest::addColumn("expectedCurrentIndex"); - QTest::addColumn("expectedCurrentText"); - QTest::addColumn("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("initialItems"); - QTest::addColumn("insertedItems"); - QTest::addColumn("insertIndex"); - QTest::addColumn("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; iitemText(expectedIndex + i), insertedItems.at(i)); -} - -void tst_QComboBox::insertItem_data() -{ - QTest::addColumn("initialItems"); - QTest::addColumn("insertIndex"); - QTest::addColumn("itemLabel"); - QTest::addColumn("expectedIndex"); - QTest::addColumn("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("text"); - QTest::addColumn("icons"); - QTest::addColumn("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; iinsertItem(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; iitemIcon(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; iitemText(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(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("items"); - QTest::addColumn("matchflags"); - QTest::addColumn("search"); - QTest::addColumn("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 IntList; -typedef QList KeyList; -Q_DECLARE_METATYPE(IntList) -Q_DECLARE_METATYPE(KeyList) - -void tst_QComboBox::flaggedItems_data() -{ - QTest::addColumn("itemList"); - QTest::addColumn("deselectFlagList"); - QTest::addColumn("disableFlagList"); - QTest::addColumn("keyMovementList"); - QTest::addColumn("editable"); - QTest::addColumn("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("disabledItems"); - QTest::addColumn("startIndex"); - QTest::addColumn("wheelDirection"); - QTest::addColumn("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("items"); - QTest::addColumn("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(&listCombo); - QVERIFY(container); - QCOMPARE(static_cast(list), qFindChild(container)); - QWidget *top = qFindChild(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(&tableCombo); - QVERIFY(container); - QCOMPARE(static_cast(table), qFindChild(container)); - foreach (QWidget *button, qFindChildren(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(&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(&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(0), Qt::Key_Down); - QTest::keyClick(static_cast(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(&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("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(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(comboBox.itemDelegate()), itemDelegate); - - comboBox.setStyleSheet("QComboBox { border: 1px solid gray; }"); - QCOMPARE(static_cast(comboBox.itemDelegate()), itemDelegate); -} - - -void tst_QComboBox::subControlRectsWithOffset_data() -{ - QTest::addColumn("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(&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(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(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::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/qcommandlinkbutton/.gitignore b/tests/auto/qcommandlinkbutton/.gitignore deleted file mode 100644 index 878121e2e6..0000000000 --- a/tests/auto/qcommandlinkbutton/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcommandlinkbutton diff --git a/tests/auto/qcommandlinkbutton/qcommandlinkbutton.pro b/tests/auto/qcommandlinkbutton/qcommandlinkbutton.pro deleted file mode 100644 index 497b8298a2..0000000000 --- a/tests/auto/qcommandlinkbutton/qcommandlinkbutton.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qcommandlinkbutton.cpp - - - diff --git a/tests/auto/qcommandlinkbutton/tst_qcommandlinkbutton.cpp b/tests/auto/qcommandlinkbutton/tst_qcommandlinkbutton.cpp deleted file mode 100644 index 6a51bf4bba..0000000000 --- a/tests/auto/qcommandlinkbutton/tst_qcommandlinkbutton.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include "qcommandlinkbutton.h" -#include - -#include -#include -#include -#include -#include -#include - -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/qcompleter/.gitignore b/tests/auto/qcompleter/.gitignore deleted file mode 100644 index 4db1c0d5c2..0000000000 --- a/tests/auto/qcompleter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcompleter diff --git a/tests/auto/qcompleter/qcompleter.pro b/tests/auto/qcompleter/qcompleter.pro deleted file mode 100644 index 4d58e6b813..0000000000 --- a/tests/auto/qcompleter/qcompleter.pro +++ /dev/null @@ -1,11 +0,0 @@ -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/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp deleted file mode 100644 index b0720b8776..0000000000 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ /dev/null @@ -1,1519 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include - -#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(Qt::EditRole)); // default value - completer.setCompletionRole(Qt::DisplayRole); - QCOMPARE(completer.completionRole(), static_cast(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("filterText"); - QTest::addColumn("step"); - QTest::addColumn("completion"); - QTest::addColumn("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("filterText"); - QTest::addColumn("step"); - QTest::addColumn("completion"); - QTest::addColumn("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("filterText"); - QTest::addColumn("step"); - QTest::addColumn("completion"); - QTest::addColumn("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("filterText"); - QTest::addColumn("step"); - QTest::addColumn("completion"); - QTest::addColumn("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("filterText"); - QTest::addColumn("step"); - QTest::addColumn("completion"); - QTest::addColumn("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("filterText"); - QTest::addColumn("step"); - QTest::addColumn("completion"); - QTest::addColumn("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("filterText"); - QTest::addColumn("hasChildren"); - QTest::addColumn("rowCount"); - QTest::addColumn("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("filterText"); - QTest::addColumn("hasChildren"); - QTest::addColumn("rowCount"); - QTest::addColumn("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(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(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(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 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("list"); - QTest::addColumn("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(&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(&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/qcomplextext/.gitignore b/tests/auto/qcomplextext/.gitignore deleted file mode 100644 index 8929cd2f89..0000000000 --- a/tests/auto/qcomplextext/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qcomplextext diff --git a/tests/auto/qcomplextext/bidireorderstring.h b/tests/auto/qcomplextext/bidireorderstring.h deleted file mode 100644 index e0bbf6e80b..0000000000 --- a/tests/auto/qcomplextext/bidireorderstring.h +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ -struct LV { - const char *name; - const char *logical; - const char *visual; - int basicDir; -}; - -const LV logical_visual[] = { - { "data0", "Hello", "Hello", QChar::DirL }, - { "data1", "\327\251\327\234\327\225\327\235", "\327\235\327\225\327\234\327\251", QChar::DirR }, - { "data2", "Hello \327\251\327\234\327\225\327\235", "Hello \327\235\327\225\327\234\327\251", QChar::DirL }, - { "data3", "car is \327\236\327\233\327\225\327\240\327\231\327\252 \327\220\327\225\327\230\327\225 in hebrew", "car is \327\225\327\230\327\225\327\220 \327\252\327\231\327\240\327\225\327\233\327\236 in hebrew", QChar::DirL }, - { "data4", "\327\236\327\233\327\225\327\240\327\231\327\252 \327\224\327\231\327\220 the car \327\221\327\251\327\244\327\224 \327\224\327\220\327\240\327\222\327\234\327\231\327\252", "\327\252\327\231\327\234\327\222\327\240\327\220\327\224 \327\224\327\244\327\251\327\221 the car \327\220\327\231\327\224 \327\252\327\231\327\240\327\225\327\233\327\236", QChar::DirR }, - { "data5", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 123, 456, \327\221\327\241\327\223\327\250\" ", "he said \"\327\250\327\223\327\241\327\221 ,456 ,123 \327\224\327\225\327\225\327\251 \327\224\327\226\" ", QChar::DirL }, - { "data6", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 (123, 456), \327\221\327\241\327\223\327\250\"", "he said \"\327\250\327\223\327\241\327\221 ,(456 ,123) \327\224\327\225\327\225\327\251 \327\224\327\226\"", QChar::DirL }, - { "data7", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 123,456, \327\221\327\241\327\223\327\250\"", "he said \"\327\250\327\223\327\241\327\221 ,123,456 \327\224\327\225\327\225\327\251 \327\224\327\226\"", QChar::DirL }, - { "data8", "he said \"\327\226\327\224 \327\251\327\225\327\225\327\224 ,(123,456) \327\221\327\241\327\223\327\250\"", "he said \"\327\250\327\223\327\241\327\221 (123,456), \327\224\327\225\327\225\327\251 \327\224\327\226\"", QChar::DirL }, - { "data9", "\327\224\327\225\327\220 \327\220\327\236\327\250 \"it is 123, 456, ok\"", "\"it is 123, 456, ok\" \327\250\327\236\327\220 \327\220\327\225\327\224", QChar::DirR }, - { "data10", "<\327\233123>shalom", "<123\327\233/>shalom<123\327\233>", QChar::DirR }, - { "data11", "\327\251\327\234\327\225\327\235", "\327\235\327\225\327\234\327\251", QChar::DirL }, - { "data12", "\327\224\327\225\327\220 \327\220\327\236\327\250 \"it is a car!\" \327\225\327\220\327\226 \327\250\327\245", "\327\245\327\250 \327\226\327\220\327\225 \"!it is a car\" \327\250\327\236\327\220 \327\220\327\225\327\224", QChar::DirR }, - { "data13", "\327\224\327\225\327\220 \327\220\327\236\327\250 \"it is a car!x\" \327\225\327\220\327\226 \327\250\327\245", "\327\245\327\250 \327\226\327\220\327\225 \"it is a car!x\" \327\250\327\236\327\220 \327\220\327\225\327\224", QChar::DirR }, - { "data14", "-2 \327\236\327\242\327\234\327\225\327\252 \327\226\327\224 \327\247\327\250", "\327\250\327\247 \327\224\327\226 \327\252\327\225\327\234\327\242\327\236 2-", QChar::DirR }, - { "data15", "-10% \327\251\327\231\327\240\327\225\327\231", "\327\231\327\225\327\240\327\231\327\251 10%-", QChar::DirR }, - { "data16", "\327\224\327\230\327\225\327\225\327\227 \327\224\327\231\327\240\327\225 2.5..5", "5..2.5 \327\225\327\240\327\231\327\224 \327\227\327\225\327\225\327\230\327\224", QChar::DirR }, - { "data17", "he said \"\327\226\327\225 \327\236\327\233\327\225\327\240\327\231\327\252!\"", "he said \"\327\252\327\231\327\240\327\225\327\233\327\236 \327\225\327\226!\"", QChar::DirL }, - { "data18", "he said \"\327\226\327\225 \327\236\327\233\327\225\327\240\327\231\327\252!\327\251\"", "he said \"\327\251!\327\252\327\231\327\240\327\225\327\233\327\236 \327\225\327\226\"", QChar::DirL }, - { "data19", "(\327\240\327\231\327\241\327\225\327\231) abc", "abc (\327\231\327\225\327\241\327\231\327\240)", QChar::DirR }, - { "data20", "abc (\327\240\327\231\327\241\327\225\327\231)", "abc (\327\231\327\225\327\241\327\231\327\240)", QChar::DirL }, - { "data21", "\327\240\327\231\327\241\327\225\327\231 23 \327\231\327\227\327\231\327\223 abc", "abc \327\223\327\231\327\227\327\231 23 \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, - { "data22", "#@$ \327\240\327\231\327\241\327\225\327\231", "\327\231\327\225\327\241\327\231\327\240 $@#", QChar::DirR }, - { "data23", "\327\240\327\231\327\241\327\225\327\231 ~~~23%%% \327\231\327\227\327\231\327\223 abc ", " abc \327\223\327\231\327\227\327\231 23%%%~~~ \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, - { "data24", "\327\240\327\231\327\241\327\225\327\231 abc ~~~23%%% \327\231\327\227\327\231\327\223 abc", "abc \327\223\327\231\327\227\327\231 abc ~~~23%%% \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, - { "data25", "\327\240\327\231\327\241\327\225\327\231 abc@23@cde \327\231\327\227\327\231\327\223", "\327\223\327\231\327\227\327\231 abc@23@cde \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, - { "data26", "\327\240\327\231\327\241\327\225\327\231 abc 23 cde \327\231\327\227\327\231\327\223", "\327\223\327\231\327\227\327\231 abc 23 cde \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, - { "data27", "\327\240\327\231\327\241\327\225\327\231 abc 23 \327\231\327\227\327\231\327\223 cde", "cde \327\223\327\231\327\227\327\231 abc 23 \327\231\327\225\327\241\327\231\327\240", QChar::DirR }, - { "data28", "\327\222a 2 \327\251", "\327\251 a 2\327\222", QChar::DirR }, - { "data29", "\327\244\327\252\327\225\327\250 1*5 1-5 1/5 1+5", "1+5 1/5 1-5 5*1 \327\250\327\225\327\252\327\244", QChar::DirR }, - { "data30", "\330\272 1*5 1-5 1/5 1+5", "5+1 1/5 5-1 5*1 \330\272", QChar::DirR }, - { "data31", "\330\250 \333\261\333\262.\333\263", "\333\261\333\262.\333\263 \330\250", QChar::DirR }, - { "data32", "\330\250 12.3", "12.3 \330\250", QChar::DirR }, - { "data33", "\330\250 1.23", "1.23 \330\250", QChar::DirR }, - { "data34", "\331\276 \333\261.\333\262\333\263", "\333\261.\333\262\333\263 \331\276", QChar::DirR }, - { "data35", "\331\276\333\261.\333\262\333\263", "\333\261.\333\262\333\263\331\276", QChar::DirR }, - { "data36", "1) \327\251", "\327\251 (1", QChar::DirR }, - { "data37", "1) \327\251", "1) \327\251", QChar::DirL }, - { "data38", "\327\224-w3c", "w3c-\327\224", QChar::DirR }, - { "data39", "\327\224-w3c", "\327\224-w3c", QChar::DirL }, - { "data40", "17:25, foo", "17:25, foo", QChar::DirL }, - { "data41", "5, foo", "foo ,5", QChar::DirR }, - { "data42", "foo\nfoo", "foo\nfoo", QChar::DirL }, - { "data43", "\327\251\327\234\327\225\327\235\n\327\251\327\234\327\225\327\235", "\327\235\327\225\327\234\327\251\n\327\235\327\225\327\234\327\251", QChar::DirR }, - { "data44", "foo\n\327\251\327\234\327\225\327\235", "foo\n\327\235\327\225\327\234\327\251", QChar::DirL }, - { "data45", "\327\251\327\234\327\225\327\235\nfoo", "\327\235\327\225\327\234\327\251\nfoo", QChar::DirR }, - { "data46", "\330\250 1.23 \330\250", "\330\250 1.23 \330\250", QChar::DirR }, - { "data47", "\331\204\330\250 1.23 \331\202\330\250", "\330\250\331\202 1.23 \330\250\331\204", QChar::DirR }, - { "data48", "\330\250 1.2 \330\250", "\330\250 1.2 \330\250", QChar::DirR }, - { "data49", "\331\204\330\250 1.2 \331\202\330\250", "\330\250\331\202 1.2 \330\250\331\204", QChar::DirR }, - { "data50", "a\331\204\330\250 1.2 \331\202\330\250", "a\330\250\331\202 1.2 \330\250\331\204", QChar::DirL }, - - { "data51", "ab(\327\240\327\231)cd", "ab(\327\231\327\240)cd", QChar::DirL }, - { "data52", "ab(\327\240\327\231)cd", "cd(\327\231\327\240)ab", QChar::DirR }, - { "data53", "a(\327\231)c", "a(\327\231)c", QChar::DirL }, - { "data54", "a(\327\231)c", "c(\327\231)a", QChar::DirR }, - { "data55", "\"[\327\220]\"", "\"[\327\220]\"", QChar::DirR }, - { "data56", "\"[\327\220]\"", "\"[\327\220]\"", QChar::DirL }, - { "data57", "\331\204\330\250 \331\202\330\250", "\330\250\331\202 \330\250\331\204", QChar::DirR }, - { "data58", "\331\204\330\250 \331\202\330\250", "\330\250\331\202 \330\250\331\204", QChar::DirL }, - { "data59", "3layout", "3layout", QChar::DirL }, - { "data60", "3layout", "3layout", QChar::DirR }, - { "data61", "3l", "3l", QChar::DirR }, - { "data62", "3la", "3la", QChar::DirR }, - { "data63", "3lay", "3lay", QChar::DirR }, - -// explicit levels -// LRE: \342\200\252 -// RLE: \342\200\253 -// PDF: \342\200\254 -// LRO: \342\200\255 -// RLO: \342\200\256 - - { "override1", "\342\200\256hello\342\200\254", "\342\200\254olleh\342\200\256", QChar::DirL }, - { "override2", "\342\200\255hello\342\200\254", "\342\200\255hello\342\200\254", QChar::DirL }, - { "override3", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", QChar::DirL }, - { "override4", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\256", QChar::DirL }, - { "override5", "\342\200\256hello\342\200\254", "\342\200\254olleh\342\200\256", QChar::DirR }, - { "override6", "\342\200\255hello\342\200\254", "\342\200\255hello\342\200\254", QChar::DirR }, - { "override7", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\327\225\327\235\342\200\254", QChar::DirR }, - { "override8", "\342\200\256\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\256", QChar::DirR }, - - { "override9", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\342\200\254olleh\342\200\256\327\225\327\235\342\200\254\327\224", QChar::DirL }, - { "override10", "\327\224\342\200\255\327\251\327\234\342\200\256hello\342\200\254\327\225\327\235\342\200\254", "\342\200\255\327\251\327\234\342\200\254olleh\342\200\256\327\225\327\235\342\200\254\327\224", QChar::DirR }, - - - { "embed1", "\342\200\252hello\342\200\254", "\342\200\252hello\342\200\254", QChar::DirL }, - { "embed2", "\342\200\253hello\342\200\254", "\342\200\254hello\342\200\253", QChar::DirL }, - { "embed3", "\342\200\252hello\342\200\254", "\342\200\252hello\342\200\254", QChar::DirR }, - { "embed4", "\342\200\253hello\342\200\254", "\342\200\254hello\342\200\253", QChar::DirR }, - { "embed5", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\252\327\235\327\225\327\234\327\251\342\200\254", QChar::DirL }, - { "embed6", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\253", QChar::DirL }, - { "embed7", "\342\200\252\327\251\327\234\327\225\327\235\342\200\254", "\342\200\252\327\235\327\225\327\234\327\251\342\200\254", QChar::DirR }, - { "embed8", "\342\200\253\327\251\327\234\327\225\327\235\342\200\254", "\342\200\254\327\235\327\225\327\234\327\251\342\200\253", QChar::DirR }, - - { "embed9", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirL }, - { "embed10", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirL }, - { "embed11", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirR }, - { "embed12", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirR }, - { "zwsp", "+0\342\200\213f-1", "+0\342\200\213f-1", QChar::DirL }, - - { 0, 0, 0, QChar::DirON } -}; diff --git a/tests/auto/qcomplextext/qcomplextext.pro b/tests/auto/qcomplextext/qcomplextext.pro deleted file mode 100644 index e04ebcbc69..0000000000 --- a/tests/auto/qcomplextext/qcomplextext.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private -QT += core-private gui-private -SOURCES += tst_qcomplextext.cpp -INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src diff --git a/tests/auto/qcomplextext/tst_qcomplextext.cpp b/tests/auto/qcomplextext/tst_qcomplextext.cpp deleted file mode 100644 index c72393cfe6..0000000000 --- a/tests/auto/qcomplextext/tst_qcomplextext.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - - -// Horrible hack, but this get this out of the way for now -// Carlos Duclos, 2007-12-11 -#if !defined(Q_WS_MAC) - -#include -#include -#include - -#include "bidireorderstring.h" - - -//TESTED_CLASS= -//TESTED_FILES=gui/widgets/qcombobox.h gui/widgets/qcombobox.cpp - -class tst_QComplexText : public QObject -{ -Q_OBJECT - -public: - tst_QComplexText(); - virtual ~tst_QComplexText(); - - -public slots: - void init(); - void cleanup(); -private slots: - void bidiReorderString_data(); - void bidiReorderString(); - void bidiCursor_qtbug2795(); - void bidiCursor_PDF(); - void bidiCursorMovement_data(); - void bidiCursorMovement(); - void bidiCursorLogicalMovement_data(); - void bidiCursorLogicalMovement(); -}; - -tst_QComplexText::tst_QComplexText() -{ -} - -tst_QComplexText::~tst_QComplexText() -{ - -} - -void tst_QComplexText::init() -{ -// This will be executed immediately before each test is run. -// TODO: Add initialization code here. -} - -void tst_QComplexText::cleanup() -{ -// This will be executed immediately after each test is run. -// TODO: Add cleanup code here. -} - -void tst_QComplexText::bidiReorderString_data() -{ - QTest::addColumn("logical"); - QTest::addColumn("VISUAL"); - QTest::addColumn("basicDir"); - - const LV *data = logical_visual; - while ( data->name ) { - //next we fill it with data - QTest::newRow( data->name ) - << QString::fromUtf8( data->logical ) - << QString::fromUtf8( data->visual ) - << (int) data->basicDir; - data++; - } -} - -void tst_QComplexText::bidiReorderString() -{ - QFETCH( QString, logical ); - QFETCH( int, basicDir ); - - // replace \n with Unicode newline. The new algorithm ignores \n - logical.replace(QChar('\n'), QChar(0x2028)); - - QTextEngine e(logical, QFont()); - e.option.setTextDirection((QChar::Direction)basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); - e.itemize(); - quint8 levels[256]; - int visualOrder[256]; - int nitems = e.layoutData->items.size(); - int i; - for (i = 0; i < nitems; ++i) { - //qDebug("item %d bidiLevel=%d", i, e.items[i].analysis.bidiLevel); - levels[i] = e.layoutData->items[i].analysis.bidiLevel; - } - e.bidiReorder(nitems, levels, visualOrder); - - QString visual; - for (i = 0; i < nitems; ++i) { - QScriptItem &si = e.layoutData->items[visualOrder[i]]; - QString sub = logical.mid(si.position, e.length(visualOrder[i])); - if (si.analysis.bidiLevel % 2) { - // reverse sub - QChar *a = (QChar *)sub.unicode(); - QChar *b = a + sub.length() - 1; - while (a < b) { - QChar tmp = *a; - *a = *b; - *b = tmp; - ++a; - --b; - } - a = (QChar *)sub.unicode(); - b = a + sub.length(); - while (amirroredChar(); - ++a; - } - } - visual += sub; - } - // replace Unicode newline back with \n to compare. - visual.replace(QChar(0x2028), QChar('\n')); - - QTEST(visual, "VISUAL"); -} - -void tst_QComplexText::bidiCursor_qtbug2795() -{ - QString str = QString::fromUtf8("الجزيرة نت"); - QTextLayout l1(str); - - l1.beginLayout(); - QTextLine line1 = l1.createLine(); - l1.endLayout(); - - qreal x1 = line1.cursorToX(0) - line1.cursorToX(str.size()); - - str.append("1"); - QTextLayout l2(str); - l2.beginLayout(); - QTextLine line2 = l2.createLine(); - l2.endLayout(); - - qreal x2 = line2.cursorToX(0) - line2.cursorToX(str.size()); - - // The cursor should remain at the same position after a digit is appended - QVERIFY(x1 == x2); -} - -void tst_QComplexText::bidiCursorMovement_data() -{ - QTest::addColumn("logical"); - QTest::addColumn("basicDir"); - - const LV *data = logical_visual; - while ( data->name ) { - //next we fill it with data - QTest::newRow( data->name ) - << QString::fromUtf8( data->logical ) - << (int) data->basicDir; - data++; - } -} - -void tst_QComplexText::bidiCursorMovement() -{ - QFETCH(QString, logical); - QFETCH(int, basicDir); - - QTextLayout layout(logical); - - QTextOption option = layout.textOption(); - option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); - layout.setTextOption(option); - layout.setCursorMoveStyle(Qt::VisualMoveStyle); - bool moved; - int oldPos, newPos = 0; - qreal x, newX; - - layout.beginLayout(); - QTextLine line = layout.createLine(); - layout.endLayout(); - - newX = line.cursorToX(0); - do { - oldPos = newPos; - x = newX; - newX = line.cursorToX(oldPos); - if (basicDir == QChar::DirL) { - QVERIFY(newX >= x); - newPos = layout.rightCursorPosition(oldPos); - } else - { - QVERIFY(newX <= x); - newPos = layout.leftCursorPosition(oldPos); - } - moved = (oldPos != newPos); - } while (moved); -} - -void tst_QComplexText::bidiCursorLogicalMovement_data() -{ - bidiCursorMovement_data(); -} - -void tst_QComplexText::bidiCursorLogicalMovement() -{ - QFETCH(QString, logical); - QFETCH(int, basicDir); - - QTextLayout layout(logical); - - QTextOption option = layout.textOption(); - option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); - layout.setTextOption(option); - bool moved; - int oldPos, newPos = 0; - - do { - oldPos = newPos; - newPos = layout.nextCursorPosition(oldPos); - QVERIFY(newPos >= oldPos); - moved = (oldPos != newPos); - } while (moved); - - do { - oldPos = newPos; - newPos = layout.previousCursorPosition(oldPos); - QVERIFY(newPos <= oldPos); - moved = (oldPos != newPos); - } while (moved); -} - -void tst_QComplexText::bidiCursor_PDF() -{ - QString str = QString::fromUtf8("\342\200\252hello\342\200\254"); - QTextLayout layout(str); - - layout.beginLayout(); - QTextLine line = layout.createLine(); - layout.endLayout(); - - int size = str.size(); - - QVERIFY(line.cursorToX(size) == line.cursorToX(size - 1)); -} - -QTEST_MAIN(tst_QComplexText) -#include "tst_qcomplextext.moc" - -#endif // Q_WS_MAC - diff --git a/tests/auto/qdatawidgetmapper/.gitignore b/tests/auto/qdatawidgetmapper/.gitignore deleted file mode 100644 index 9b0a1e6399..0000000000 --- a/tests/auto/qdatawidgetmapper/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdatawidgetmapper diff --git a/tests/auto/qdatawidgetmapper/qdatawidgetmapper.pro b/tests/auto/qdatawidgetmapper/qdatawidgetmapper.pro deleted file mode 100644 index 64e3b57291..0000000000 --- a/tests/auto/qdatawidgetmapper/qdatawidgetmapper.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdatawidgetmapper.cpp - - diff --git a/tests/auto/qdatawidgetmapper/tst_qdatawidgetmapper.cpp b/tests/auto/qdatawidgetmapper/tst_qdatawidgetmapper.cpp deleted file mode 100644 index 7488195497..0000000000 --- a/tests/auto/qdatawidgetmapper/tst_qdatawidgetmapper.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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(&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(&lineEdit1)); - QCOMPARE(mapper.mappedWidgetAt(2), static_cast(&lineEdit2)); - - mapper.addMapping(&lineEdit2, 4242); - - QCOMPARE(mapper.mappedWidgetAt(2), (QWidget*)0); - QCOMPARE(mapper.mappedWidgetAt(4242), static_cast(&lineEdit2)); -} - -QTEST_MAIN(tst_QDataWidgetMapper) -#include "tst_qdatawidgetmapper.moc" diff --git a/tests/auto/qdatetimeedit/.gitignore b/tests/auto/qdatetimeedit/.gitignore deleted file mode 100644 index a68e3269d2..0000000000 --- a/tests/auto/qdatetimeedit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdatetimeedit diff --git a/tests/auto/qdatetimeedit/qdatetimeedit.pro b/tests/auto/qdatetimeedit/qdatetimeedit.pro deleted file mode 100644 index 47356d448c..0000000000 --- a/tests/auto/qdatetimeedit/qdatetimeedit.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdatetimeedit.cpp - -wincewm50smart-msvc2005: DEFINES += WINCE_NO_MODIFIER_KEYS - - - diff --git a/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp deleted file mode 100644 index c64c9e7019..0000000000 --- a/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp +++ /dev/null @@ -1,3458 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN -# include -# 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); - -#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 (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 TimeList; -typedef QList 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"); - qRegisterMetaType("QTime"); - qRegisterMetaType("QDateTime"); - qRegisterMetaType >("QList"); -} - -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("parameter"); - QTest::addColumn("displayDateTime"); - QTest::addColumn("minimumDate"); - QTest::addColumn("minimumTime"); - QTest::addColumn("maximumDate"); - QTest::addColumn("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("parameter"); - QTest::addColumn("displayDateTime"); - QTest::addColumn("minimumDate"); - QTest::addColumn("minimumTime"); - QTest::addColumn("maximumDate"); - QTest::addColumn("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("parameter"); - QTest::addColumn("displayDateTime"); - QTest::addColumn("minimumDate"); - QTest::addColumn("minimumTime"); - QTest::addColumn("maximumDate"); - QTest::addColumn("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("minimumDate"); - QTest::addColumn("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("minimumDateTime"); - QTest::addColumn("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("maximumDateTime"); - QTest::addColumn("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("maximumDate"); - QTest::addColumn("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("minimumDate"); - QTest::addColumn("valid"); - QTest::addColumn("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("minimumDateTime"); - QTest::addColumn("valid"); - QTest::addColumn("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("maximumDateTime"); - QTest::addColumn("valid"); - QTest::addColumn("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("maximumDate"); - QTest::addColumn("valid"); - QTest::addColumn("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("format"); - QTest::addColumn("valid"); - QTest::addColumn("text"); - QTest::addColumn("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("minTime"); - QTest::addColumn("maxTime"); - QTest::addColumn("minDate"); - QTest::addColumn("maxDate"); - QTest::addColumn("expectedMin"); - QTest::addColumn("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("startWithMin"); - QTest::addColumn("minimumTime"); - QTest::addColumn("maximumTime"); - QTest::addColumn("section"); - QTest::addColumn("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("ampm"); - QTest::addColumn("keys"); - QTest::addColumn("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("startWithMin"); - QTest::addColumn("minimumDate"); - QTest::addColumn("maximumDate"); - QTest::addColumn("section"); - QTest::addColumn("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("originalDate"); - QTest::addColumn("newDate"); - QTest::addColumn("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 list = dateSpy.takeFirst(); - QDate d; - d = qVariantValue(list.at(0)); - QCOMPARE(d, newDate); - } - QCOMPARE(dateTimeSpy.count(), timesEmitted); - QCOMPARE(timeSpy.count(), 0); -} - -void tst_QDateTimeEdit::timeSignalChecking_data() -{ - QTest::addColumn("originalTime"); - QTest::addColumn("newTime"); - QTest::addColumn("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 list = timeSpy.takeFirst(); - QTime t; - t = qVariantValue(list.at(0)); - QCOMPARE(t, newTime); - } - QCOMPARE(dateTimeSpy.count(), timesEmitted); - QCOMPARE(dateSpy.count(), 0); -} - -void tst_QDateTimeEdit::dateTimeSignalChecking_data() -{ - QTest::addColumn("originalDateTime"); - QTest::addColumn("newDateTime"); - QTest::addColumn("timesDateEmitted"); - QTest::addColumn("timesTimeEmitted"); - QTest::addColumn("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 list = dateSpy.takeFirst(); - QDate d; - d = qVariantValue(list.at(0)); - QCOMPARE(d, newDateTime.date()); - } - QCOMPARE(timeSpy.count(), timesTimeEmitted); - if (timesTimeEmitted > 0) { - QList list = timeSpy.takeFirst(); - QTime t; - t = qVariantValue(list.at(0)); - QCOMPARE(t, newDateTime.time()); - } - QCOMPARE(dateTimeSpy.count(), timesDateTimeEmitted); - if (timesDateTimeEmitted > 0) { - QList list = dateTimeSpy.takeFirst(); - QDateTime dt; - dt = qVariantValue(list.at(0)); - QCOMPARE(dt, newDateTime); - } -} - - -void tst_QDateTimeEdit::sectionText_data() -{ - QTest::addColumn("format"); - QTest::addColumn("dateTime"); - QTest::addColumn("section"); - QTest::addColumn("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("format"); - QTest::addColumn("keys"); - QTest::addColumn("expected"); - QTest::addColumn("start"); - QTest::addColumn("min"); - QTest::addColumn("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; itime(), expected.at(i)); - } -} - - -void tst_QDateTimeEdit::displayedSections_data() -{ - QTest::addColumn("format"); - QTest::addColumn("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("format"); - QTest::addColumn("section"); - QTest::addColumn("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 makeList(int val1, int val2, int val3) -{ - QList ret; - ret << val1 << val2 << val3; - return ret; -} - - -void tst_QDateTimeEdit::setCurrentSection_data() -{ - QTest::addColumn("format"); - QTest::addColumn("dateTime"); - QTest::addColumn >("setCurrentSections"); - QTest::addColumn >("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, setCurrentSections); - QFETCH(QList, 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; isetCurrentSection((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(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(&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(&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("key"); - QTest::addColumn("modifiers"); - QTest::addColumn("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("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("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/qdesktopwidget/.gitignore b/tests/auto/qdesktopwidget/.gitignore deleted file mode 100644 index d6f7cc7ca9..0000000000 --- a/tests/auto/qdesktopwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdesktopwidget diff --git a/tests/auto/qdesktopwidget/qdesktopwidget.pro b/tests/auto/qdesktopwidget/qdesktopwidget.pro deleted file mode 100644 index 730b273c4f..0000000000 --- a/tests/auto/qdesktopwidget/qdesktopwidget.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdesktopwidget.cpp diff --git a/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp b/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp deleted file mode 100644 index e7e3abeb25..0000000000 --- a/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -//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/qdial/.gitignore b/tests/auto/qdial/.gitignore deleted file mode 100644 index 3a640cf1a1..0000000000 --- a/tests/auto/qdial/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdial diff --git a/tests/auto/qdial/qdial.pro b/tests/auto/qdial/qdial.pro deleted file mode 100644 index acf66de430..0000000000 --- a/tests/auto/qdial/qdial.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdial.cpp - - diff --git a/tests/auto/qdial/tst_qdial.cpp b/tests/auto/qdial/tst_qdial.cpp deleted file mode 100644 index 568b82d28b..0000000000 --- a/tests/auto/qdial/tst_qdial.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include - -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/qdialog/.gitignore b/tests/auto/qdialog/.gitignore deleted file mode 100644 index 4a4b5ebcbe..0000000000 --- a/tests/auto/qdialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdialog diff --git a/tests/auto/qdialog/qdialog.pro b/tests/auto/qdialog/qdialog.pro deleted file mode 100644 index a3596b60f6..0000000000 --- a/tests/auto/qdialog/qdialog.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdialog.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qdialog/tst_qdialog.cpp b/tests/auto/qdialog/tst_qdialog.cpp deleted file mode 100644 index 0f4acdcc9e..0000000000 --- a/tests/auto/qdialog/tst_qdialog.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include - -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("dlgSize"); - QTest::addColumn("extSize"); - QTest::addColumn("horizontal"); - QTest::addColumn("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(&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(&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 sizeGrip = qFindChild(&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(&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(&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/qdialogbuttonbox/.gitignore b/tests/auto/qdialogbuttonbox/.gitignore deleted file mode 100644 index edf08554d4..0000000000 --- a/tests/auto/qdialogbuttonbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdialogbuttonbox diff --git a/tests/auto/qdialogbuttonbox/qdialogbuttonbox.pro b/tests/auto/qdialogbuttonbox/qdialogbuttonbox.pro deleted file mode 100644 index efbeca0c1b..0000000000 --- a/tests/auto/qdialogbuttonbox/qdialogbuttonbox.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdialogbuttonbox.cpp - -TARGET = tst_qdialogbuttonbox - - diff --git a/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp deleted file mode 100644 index 449cc5e44d..0000000000 --- a/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp +++ /dev/null @@ -1,810 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -Q_DECLARE_METATYPE(QList) -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 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("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("orientation"); - QTest::addColumn("buttons"); - QTest::addColumn("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("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("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("role"); - QTest::addColumn("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 children = qFindChildren(&buttonBox); - QTEST(children.count(), "totalCount"); - delete button; -} - -void tst_QDialogButtonBox::addButton2_data() -{ - QTest::addColumn("text"); - QTest::addColumn("role"); - QTest::addColumn("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 children = qFindChildren(&buttonBox); - QTEST(children.count(), "totalCount"); -} - -void tst_QDialogButtonBox::addButton3_data() -{ - QTest::addColumn("button"); - QTest::addColumn("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 children = qFindChildren(&buttonBox); - QTEST(children.count(), "totalCount"); -} - -void tst_QDialogButtonBox::clear_data() -{ - QTest::addColumn("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 children = qFindChildren(&buttonBox); - QCOMPARE(children.count(), 0); -} - -void tst_QDialogButtonBox::removeButton_data() -{ - QTest::addColumn("roleToAdd"); - QTest::addColumn("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 children = qFindChildren(&buttonBox); - QCOMPARE(children.count(), 1); - - delete deleteMe; - children = qFindChildren(&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("roleToAdd"); - QTest::addColumn("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("button"); - QTest::addColumn("expectedRole"); - QTest::addColumn("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("buttonToClick"); - QTest::addColumn("clicked2Count"); - QTest::addColumn("acceptCount"); - QTest::addColumn("rejectCount"); - QTest::addColumn("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*"); - 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(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("buttonsToAdd"); - QTest::addColumn("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("whenToSetDefault"); // -1 Do nothing, 0 after accept, 1 before accept - QTest::addColumn("buttonToBeDefault"); - QTest::addColumn("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 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/qdirectpainter/.gitignore b/tests/auto/qdirectpainter/.gitignore deleted file mode 100644 index 615dfa8ddc..0000000000 --- a/tests/auto/qdirectpainter/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tst_qdirectpainter -runDirectPainter/runDirectPainter diff --git a/tests/auto/qdirectpainter/qdirectpainter.pro b/tests/auto/qdirectpainter/qdirectpainter.pro deleted file mode 100644 index e86b3427eb..0000000000 --- a/tests/auto/qdirectpainter/qdirectpainter.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = test runDirectPainter - -requires(embedded) - diff --git a/tests/auto/qdirectpainter/runDirectPainter/main.cpp b/tests/auto/qdirectpainter/runDirectPainter/main.cpp deleted file mode 100644 index af3dd90beb..0000000000 --- a/tests/auto/qdirectpainter/runDirectPainter/main.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -int main(int argc, char** argv) -{ -#ifdef Q_WS_QWS - QApplication app(argc, argv); - QDirectPainter dp; - QImage screenImage(dp.frameBuffer(), dp.screenWidth(), dp.screenHeight(), - dp.linestep(), QScreen::instance()->pixelFormat()); - QPainter p; - - QStringList args = app.arguments(); - - dp.setRegion(QRect(args.at(1).toInt(), - args.at(2).toInt(), - args.at(3).toInt(), - args.at(4).toInt())); - - for (;;) { - dp.startPainting(); - p.begin(&screenImage); - p.setPen(Qt::NoPen); - p.setBrush(Qt::blue); - p.drawRects(dp.allocatedRegion().rects()); - p.end(); - dp.endPainting(dp.allocatedRegion()); - app.processEvents(); - } -#else - Q_UNUSED(argc); - Q_UNUSED(argv); -#endif - - return 0; -} - diff --git a/tests/auto/qdirectpainter/runDirectPainter/runDirectPainter.pro b/tests/auto/qdirectpainter/runDirectPainter/runDirectPainter.pro deleted file mode 100644 index 09524e90c3..0000000000 --- a/tests/auto/qdirectpainter/runDirectPainter/runDirectPainter.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -SOURCES = main.cpp -TARGET = runDirectPainter - -requires(embedded) - diff --git a/tests/auto/qdirectpainter/test/test.pro b/tests/auto/qdirectpainter/test/test.pro deleted file mode 100644 index 3621e11fa9..0000000000 --- a/tests/auto/qdirectpainter/test/test.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += ../tst_qdirectpainter.cpp -TARGET = ../tst_qdirectpainter - -requires(embedded) - diff --git a/tests/auto/qdirectpainter/tst_qdirectpainter.cpp b/tests/auto/qdirectpainter/tst_qdirectpainter.cpp deleted file mode 100644 index 550c2e96c0..0000000000 --- a/tests/auto/qdirectpainter/tst_qdirectpainter.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/**************************************************************************** -** -** 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 - -//TESTED_CLASS= -//TESTED_FILES= - -#include -#include -#include -#include -#include -#include - -class tst_QDirectPainter : public QObject -{ - Q_OBJECT - -public: - tst_QDirectPainter() {} - ~tst_QDirectPainter() {} - -private slots: - void initTestCase(); - void setGeometry_data(); - void setGeometry(); -#ifndef QT_NO_PROCESS - void regionSynchronization(); -#endif - void reservedSynchronous(); - -private: - QWSWindow* getWindow(int windId); - QColor bgColor; -}; - -class ColorPainter : public QDirectPainter -{ -public: - ColorPainter(SurfaceFlag flag = NonReserved, - const QColor &color = QColor(Qt::red)) - : QDirectPainter(0, flag), c(color) {} - - QColor color() { return c; } - -protected: - void regionChanged(const QRegion ®ion) { - QScreen::instance()->solidFill(c, region); - } - -private: - QColor c; - QRegion r; -}; - -Q_DECLARE_METATYPE(QDirectPainter::SurfaceFlag) - -void tst_QDirectPainter::initTestCase() -{ - bgColor = QColor(Qt::green); - - QWSServer *server = QWSServer::instance(); - server->setBackground(bgColor); -} - -QWSWindow* tst_QDirectPainter::getWindow(int winId) -{ - QWSServer *server = QWSServer::instance(); - foreach (QWSWindow *w, server->clientWindows()) { - if (w->winId() == winId) - return w; - } - return 0; -} - -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(rect, color) { \ - 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.fill(color); \ - QCOMPARE(pixmap, expectedPixmap); \ -} - -void tst_QDirectPainter::setGeometry_data() -{ - QTest::addColumn("flag"); - - QTest::newRow("NonReserved") << QDirectPainter::NonReserved; - QTest::newRow("Reserved") << QDirectPainter::Reserved; - QTest::newRow("ReservedSynchronous") << QDirectPainter::ReservedSynchronous; -} - -void tst_QDirectPainter::setGeometry() -{ - QFETCH(QDirectPainter::SurfaceFlag, flag); - - const QRect rect(100, 100, 100, 100); - { - ColorPainter w(flag); - - w.setGeometry(rect); - QApplication::processEvents(); - QCOMPARE(w.geometry(), rect); - VERIFY_COLOR(rect, w.color()); - } - QApplication::processEvents(); - VERIFY_COLOR(rect, bgColor); -} - -#ifndef QT_NO_PROCESS -void tst_QDirectPainter::regionSynchronization() -{ - QRect dpRect(10, 10, 50, 50); - - // Start the direct painter in a different process - QProcess proc; - QStringList args; - args << QString::number(dpRect.x()) - << QString::number(dpRect.y()) - << QString::number(dpRect.width()) - << QString::number(dpRect.height()); - - proc.start("runDirectPainter/runDirectPainter", args); - QVERIFY(proc.waitForStarted(5 * 1000)); - QTest::qWait(1000); - QApplication::processEvents(); - VERIFY_COLOR(dpRect, Qt::blue); // blue hardcoded in runDirectPainter - - QTime t; - t.start(); - static int i = 0; - while (t.elapsed() < 10 * 1000) { - QApplication::processEvents(); - - ColorWidget w; - w.setGeometry(10, 10, 50, 50); - const QRect wRect = dpRect.translated(10, 0); - w.setGeometry(wRect); - w.show(); - - QApplication::processEvents(); - QApplication::processEvents(); //glib event loop workaround - VERIFY_COLOR(wRect, w.color); - ++i; - } - QVERIFY(i > 100); // sanity check - - proc.kill(); -} -#endif - -class MyObject : public QObject -{ -public: - MyObject(QObject *p = 0) : QObject(p), lastEvent(0) {} - - bool event(QEvent *e) { - lastEvent = e; - return true; - } - - QEvent *lastEvent; -}; - -void tst_QDirectPainter::reservedSynchronous() -{ - MyObject o; - QCoreApplication::postEvent(&o, new QEvent(QEvent::None)); - QDirectPainter p(0, QDirectPainter::ReservedSynchronous); - p.setRegion(QRect(5, 5, 50, 50)); - - // The event loop should not have been executed - QVERIFY(o.lastEvent == 0); - QCOMPARE(p.allocatedRegion(), QRegion(QRect(5, 5, 50, 50))); -} - -QTEST_MAIN(tst_QDirectPainter) - -#include "tst_qdirectpainter.moc" diff --git a/tests/auto/qdirmodel/.gitignore b/tests/auto/qdirmodel/.gitignore deleted file mode 100644 index 641c99880f..0000000000 --- a/tests/auto/qdirmodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdirmodel diff --git a/tests/auto/qdirmodel/dirtest/test1/dummy b/tests/auto/qdirmodel/dirtest/test1/dummy deleted file mode 100644 index 4d6a3b44f4..0000000000 --- a/tests/auto/qdirmodel/dirtest/test1/dummy +++ /dev/null @@ -1 +0,0 @@ -ECHO is on. diff --git a/tests/auto/qdirmodel/dirtest/test1/test b/tests/auto/qdirmodel/dirtest/test1/test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/qdirmodel/qdirmodel.pro b/tests/auto/qdirmodel/qdirmodel.pro deleted file mode 100644 index bc4e98d6ff..0000000000 --- a/tests/auto/qdirmodel/qdirmodel.pro +++ /dev/null @@ -1,20 +0,0 @@ -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/qdirmodel/test/file01.tst b/tests/auto/qdirmodel/test/file01.tst deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/qdirmodel/test/file02.tst b/tests/auto/qdirmodel/test/file02.tst deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/qdirmodel/test/file03.tst b/tests/auto/qdirmodel/test/file03.tst deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/qdirmodel/test/file04.tst b/tests/auto/qdirmodel/test/file04.tst deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/qdirmodel/tst_qdirmodel.cpp b/tests/auto/qdirmodel/tst_qdirmodel.cpp deleted file mode 100644 index 70eb17b5e6..0000000000 --- a/tests/auto/qdirmodel/tst_qdirmodel.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -//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("dirName"); // the directory to be made under /dirtest - QTest::addColumn("mkdirSuccess"); - QTest::addColumn("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("dirName"); // /dirtest/dirname - QTest::addColumn("rmdirSuccess"); - QTest::addColumn("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("test_path"); - QTest::addColumn("initial_files"); - QTest::addColumn("remove_row"); - QTest::addColumn("remove_files"); - QTest::addColumn("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"); - - // 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("path"); - QTest::addColumn("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("role"); - QTest::addColumn("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 roles = model.roleNames(); - - QFETCH(int, role); - QVERIFY(roles.contains(role)); - - QFETCH(QByteArray, roleName); - QList values = roles.values(role); - QVERIFY(values.contains(roleName)); -} - - -QTEST_MAIN(tst_QDirModel) -#include "tst_qdirmodel.moc" diff --git a/tests/auto/qdockwidget/.gitignore b/tests/auto/qdockwidget/.gitignore deleted file mode 100644 index 7c79145a67..0000000000 --- a/tests/auto/qdockwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdockwidget diff --git a/tests/auto/qdockwidget/qdockwidget.pro b/tests/auto/qdockwidget/qdockwidget.pro deleted file mode 100644 index e59728207f..0000000000 --- a/tests/auto/qdockwidget/qdockwidget.pro +++ /dev/null @@ -1,7 +0,0 @@ -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/qdockwidget/tst_qdockwidget.cpp b/tests/auto/qdockwidget/tst_qdockwidget.cpp deleted file mode 100644 index 2c1f7c0954..0000000000 --- a/tests/auto/qdockwidget/tst_qdockwidget.cpp +++ /dev/null @@ -1,877 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#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"); - qRegisterMetaType("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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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"); - - 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(spy.at(0).at(0)), - Qt::LeftDockWidgetArea); - spy.clear(); - - mw.addDockWidget(Qt::LeftDockWidgetArea, &dw); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast(spy.at(0).at(0)), - Qt::LeftDockWidgetArea); - spy.clear(); - - mw.addDockWidget(Qt::RightDockWidgetArea, &dw); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast(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(spy.at(0).at(0)), - Qt::TopDockWidgetArea); - spy.clear(); - - mw.splitDockWidget(&dw2, &dw, Qt::Horizontal); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast(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(spy.at(0).at(0)), - Qt::TopDockWidgetArea); - spy.clear(); - - QByteArray ba = mw.saveState(); - mw.restoreState(ba); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast(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(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/qdoublespinbox/.gitignore b/tests/auto/qdoublespinbox/.gitignore deleted file mode 100644 index 7704132e98..0000000000 --- a/tests/auto/qdoublespinbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdoublespinbox diff --git a/tests/auto/qdoublespinbox/qdoublespinbox.pro b/tests/auto/qdoublespinbox/qdoublespinbox.pro deleted file mode 100644 index ff0eb2edae..0000000000 --- a/tests/auto/qdoublespinbox/qdoublespinbox.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdoublespinbox.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp deleted file mode 100644 index 15f38e3334..0000000000 --- a/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp +++ /dev/null @@ -1,1111 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#include - -#include -#include -#include - -#include -#include - -//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 actualValues; - QWidget *testFocusWidget; -}; - -typedef QList 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("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("prefix"); - QTest::addColumn("suffix"); - QTest::addColumn("value"); - QTest::addColumn("decimals"); - QTest::addColumn("expectedText"); - QTest::addColumn("expectedCleanText"); - QTest::addColumn("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("decimals"); - QTest::addColumn("keys"); - QTest::addColumn("texts"); - QTest::addColumn("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("wrapping"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("startValue"); - QTest::addColumn("keys"); - QTest::addColumn("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("specialValueText"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("value"); - QTest::addColumn("decimals"); - QTest::addColumn("expected"); - QTest::addColumn("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("singleStep"); - QTest::addColumn("startValue"); - QTest::addColumn("keys"); - QTest::addColumn("expected"); - QTest::addColumn("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("startValue"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("keys"); - QTest::addColumn("expected"); - QTest::addColumn("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("decimals"); - QTest::addColumn("expectedDecimals"); - QTest::addColumn("startValue"); - QTest::addColumn("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("txt"); - QTest::addColumn("state"); - QTest::addColumn("mini"); - QTest::addColumn("maxi"); - QTest::addColumn("language"); - QTest::addColumn("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(&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(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/qdoublevalidator/.gitignore b/tests/auto/qdoublevalidator/.gitignore deleted file mode 100644 index 95c97bbc30..0000000000 --- a/tests/auto/qdoublevalidator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qdoublevalidator diff --git a/tests/auto/qdoublevalidator/qdoublevalidator.pro b/tests/auto/qdoublevalidator/qdoublevalidator.pro deleted file mode 100644 index 7fbb72bb7f..0000000000 --- a/tests/auto/qdoublevalidator/qdoublevalidator.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qdoublevalidator.cpp - - diff --git a/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp deleted file mode 100644 index 6014ce5165..0000000000 --- a/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include - -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("localeName"); - QTest::addColumn("value"); - QTest::addColumn("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("localeName"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("decimals"); - QTest::addColumn("value"); - QTest::addColumn("scientific_state"); - QTest::addColumn("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"); - 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("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("input"); - QTest::addColumn("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/qerrormessage/.gitignore b/tests/auto/qerrormessage/.gitignore deleted file mode 100644 index 1bb653fb72..0000000000 --- a/tests/auto/qerrormessage/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qerrormessage diff --git a/tests/auto/qerrormessage/qerrormessage.pro b/tests/auto/qerrormessage/qerrormessage.pro deleted file mode 100644 index 363d085cbf..0000000000 --- a/tests/auto/qerrormessage/qerrormessage.pro +++ /dev/null @@ -1,10 +0,0 @@ -load(qttest_p4) -TEMPLATE = app -TARGET = tst_qerrormessage -DEPENDPATH += . -INCLUDEPATH += . - -QT += widgets - -# Input -SOURCES += tst_qerrormessage.cpp diff --git a/tests/auto/qerrormessage/tst_qerrormessage.cpp b/tests/auto/qerrormessage/tst_qerrormessage.cpp deleted file mode 100644 index d3ee640b1a..0000000000 --- a/tests/auto/qerrormessage/tst_qerrormessage.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -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
bar"); - QCheckBox *checkBox = 0; - - QErrorMessage errorMessageDialog(0); - - // show an error with plain string - errorMessageDialog.showMessage(plainString); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&errorMessageDialog); - QVERIFY(checkBox); - QVERIFY(checkBox->isChecked()); - errorMessageDialog.close(); - - errorMessageDialog.showMessage(plainString); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&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(&errorMessageDialog); - QVERIFY(checkBox); - QVERIFY(!checkBox->isChecked()); - checkBox->setChecked(true); - errorMessageDialog.close(); - - errorMessageDialog.showMessage(htmlString); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&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
bar"); - QString htmlString2 = QLatin1String("foo2
bar2"); - QCheckBox *checkBox = 0; - - QErrorMessage errorMessageDialog(0); - - errorMessageDialog.showMessage(htmlString,"Cat 1"); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&errorMessageDialog); - QVERIFY(checkBox); - QVERIFY(checkBox->isChecked()); - checkBox->setChecked(true); - errorMessageDialog.close(); - - errorMessageDialog.showMessage(htmlString,"Cat 1"); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&errorMessageDialog); - QVERIFY(checkBox); - QVERIFY(checkBox->isChecked()); - checkBox->setChecked(true); - errorMessageDialog.close(); - - errorMessageDialog.showMessage(htmlString2,"Cat 1"); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&errorMessageDialog); - QVERIFY(checkBox); - QVERIFY(checkBox->isChecked()); - checkBox->setChecked(true); - errorMessageDialog.close(); - - errorMessageDialog.showMessage(htmlString,"Cat 1"); - QVERIFY(errorMessageDialog.isVisible()); - checkBox = qFindChild(&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/qfiledialog/.gitignore b/tests/auto/qfiledialog/.gitignore deleted file mode 100644 index a696596ee9..0000000000 --- a/tests/auto/qfiledialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfiledialog diff --git a/tests/auto/qfiledialog/qfiledialog.pro b/tests/auto/qfiledialog/qfiledialog.pro deleted file mode 100644 index 92fba98796..0000000000 --- a/tests/auto/qfiledialog/qfiledialog.pro +++ /dev/null @@ -1,23 +0,0 @@ -############################################################ -# 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/qfiledialog/resources/file.txt b/tests/auto/qfiledialog/resources/file.txt deleted file mode 100644 index 8a03e0e55f..0000000000 --- a/tests/auto/qfiledialog/resources/file.txt +++ /dev/null @@ -1 +0,0 @@ -This is a simple text file. diff --git a/tests/auto/qfiledialog/tst_qfiledialog.cpp b/tests/auto/qfiledialog/tst_qfiledialog.cpp deleted file mode 100644 index 2a14ecbc28..0000000000 --- a/tests/auto/qfiledialog/tst_qfiledialog.cpp +++ /dev/null @@ -1,1349 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 -#include - -#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(&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(&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(&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(&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("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(&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(&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(&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(&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 list = qFindChildren(&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("startPath"); - QTest::addColumn("input"); - QTest::addColumn("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 files; - QT_TRY { - for (int i = 0; i < 10; ++i) { - QScopedPointer 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(&fd, "qt_filesystem_model"); - QVERIFY(model); - QLineEdit *lineEdit = qFindChild(&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(&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(&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 views = qFindChildren(&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(&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(&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(&fd, "newFolderButton"); - QAction* renameAction = qFindChild(&fd, "qt_rename_action"); - QAction* deleteAction = qFindChild(&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("file"); - QTest::addColumn("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(&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(&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(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 treeView = qFindChildren(&fd, "treeView"); - QCOMPARE(treeView.count(), 1); - QList listView = qFindChildren(&fd, "listView"); - QCOMPARE(listView.count(), 1); - QList listButton = qFindChildren(&fd, "listModeButton"); - QCOMPARE(listButton.count(), 1); - QList treeButton = qFindChildren(&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(&fd)); - qApp->processEvents(); - - // make sure the tests work with focus follows mouse - QCursor::setPos(fd.geometry().center()); - QApplication::syncX(); - - QList treeView = qFindChildren(&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(&fd, "qt_filesystem_model"); - QVERIFY(model); - QToolButton *backButton = qFindChild(&fd, "backButton"); - QVERIFY(backButton); - QToolButton *forwardButton = qFindChild(&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(spy.last().first()); - QCOMPARE(model->index(currentPath), model->index(temp)); - - backButton->click(); - currentPath = qVariantValue(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(&fd, "backButton"); - QVERIFY(backButton); - QToolButton *forwardButton = qFindChild(&fd, "forwardButton"); - QVERIFY(forwardButton); - - QFileSystemModel *model = qFindChild(&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(spy.last().first())), model->index(temp)); - - forwardButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(desktop)); - QCOMPARE(backButton->isEnabled(), true); - QCOMPARE(forwardButton->isEnabled(), false); - QCOMPARE(spy.count(), 4); - - backButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); - QCOMPARE(backButton->isEnabled(), true); - - backButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(home)); - QCOMPARE(backButton->isEnabled(), false); - QCOMPARE(forwardButton->isEnabled(), true); - QCOMPARE(spy.count(), 6); - - forwardButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); - backButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(home)); - QCOMPARE(spy.count(), 8); - - forwardButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); - forwardButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(desktop)); - - backButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); - backButton->click(); - QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(home)); - fd.setDirectory(desktop); - QCOMPARE(forwardButton->isEnabled(), false); -} - -void tst_QFiledialog::disableSaveButton_data() -{ - QTest::addColumn("path"); - QTest::addColumn("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(&fd, "buttonBox"); - QPushButton *button = buttonBox->button(QDialogButtonBox::Save); - QVERIFY(button); - QCOMPARE(button->isEnabled(), isEnabled); -} - -void tst_QFiledialog::saveButtonText_data() -{ - QTest::addColumn("path"); - QTest::addColumn("label"); - QTest::addColumn("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(&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(&fd, "fileNameEdit"); - QVERIFY(lineEdit); - QVERIFY(lineEdit->text() == "foo"); - fd.setDirectory(QDir::home()); - - QListView* list = qFindChild(&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(&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("tildePath"); - QTest::addColumn("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 (~ 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/qfiledialog2/qfiledialog2.pro b/tests/auto/qfiledialog2/qfiledialog2.pro deleted file mode 100644 index a2149c8a39..0000000000 --- a/tests/auto/qfiledialog2/qfiledialog2.pro +++ /dev/null @@ -1,20 +0,0 @@ -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/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/qfiledialog2/tst_qfiledialog2.cpp deleted file mode 100644 index dad1e903f9..0000000000 --- a/tests/auto/qfiledialog2/tst_qfiledialog2.cpp +++ /dev/null @@ -1,1213 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 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(&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(&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(&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(&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(&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("path"); - QTest::addColumn("directory"); - QTest::addColumn("isEnabled"); - QTest::addColumn("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(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(dlg, "qt_filesystem_model"); - QVERIFY(model); - dlg->setAcceptMode(QFileDialog::AcceptSave); - QCOMPARE(model->index(dlg->directory().absolutePath()), model->index(directory)); - - QDialogButtonBox *buttonBox = qFindChild(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(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(&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(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(&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(&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(&fd, "fileNameEdit"); - QToolButton *buttonParent = qFindChild(&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(&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(&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(&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(&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(&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(&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(&fd, "listView"); - list->setFocus(); - QTest::qWait(200); - QTest::keyClick(list, Qt::Key_Return); - QTest::qWait(1000); - QDialogButtonBox *buttonBox = qFindChild(&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(&fd, "treeView"); - tree->header()->setSortIndicator(3,Qt::DescendingOrder); - QTest::qWait(200); - QDialogButtonBox *buttonBox = qFindChild(&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(&fd2, "treeView"); - tree2->setFocus(); - - QCOMPARE(tree2->rootIndex().data(QFileSystemModel::FilePathRole).toString(),current.absolutePath()); - - QDialogButtonBox *buttonBox2 = qFindChild(&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(&fd3, "treeView"); - tree3->setFocus(); - - QCOMPARE(tree3->rootIndex().data(QFileSystemModel::FilePathRole).toString(), current.absolutePath()); - - QDialogButtonBox *buttonBox3 = qFindChild(&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 comboList = d.findChildren(); - 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 urls; - urls << QUrl::fromLocalFile(hiddenSubDir.absolutePath()); - fd.setSidebarUrls(urls); - fd.show(); - QTest::qWait(250); - - QSidebar *sidebar = qFindChild(&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(&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 idxs = selectionModel()->selectedIndexes(); - QList 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 urls; - urls << QUrl::fromLocalFile(testSubDir.absolutePath()); - urls << QUrl::fromLocalFile("NotFound"); - fd.setSidebarUrls(urls); - fd.show(); - QTest::qWait(250); - - QSidebar *sidebar = qFindChild(&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(&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(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(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 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(&fd, "fileNameEdit"); - QVERIFY(lineEdit); - QCOMPARE(lineEdit->text(),QLatin1String("new_file.txt")); - QListView *list = qFindChild(&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::fromLocalFile(url)); - QSidebar *sidebar = qFindChild(&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(&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(&fd)); - - QTest::qWait(250); - QLineEdit *lineEdit = qFindChild(&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(&fd)); - - QFileSystemModel *model = qFindChild(&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(&fd)); - - QComboBox *filters = qFindChild(&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(&fd2)); - - QComboBox *filters2 = qFindChild(&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(&fd)); - - fd.setDirectory(""); - QLineEdit *lineEdit = qFindChild(&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/qfileiconprovider/.gitignore b/tests/auto/qfileiconprovider/.gitignore deleted file mode 100644 index 1b673b8fd4..0000000000 --- a/tests/auto/qfileiconprovider/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfileiconprovider diff --git a/tests/auto/qfileiconprovider/qfileiconprovider.pro b/tests/auto/qfileiconprovider/qfileiconprovider.pro deleted file mode 100644 index 1e3d26de00..0000000000 --- a/tests/auto/qfileiconprovider/qfileiconprovider.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qfileiconprovider.cpp - - diff --git a/tests/auto/qfileiconprovider/tst_qfileiconprovider.cpp b/tests/auto/qfileiconprovider/tst_qfileiconprovider.cpp deleted file mode 100644 index cf53019ff1..0000000000 --- a/tests/auto/qfileiconprovider/tst_qfileiconprovider.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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("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("info"); - QTest::addColumn("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("info"); - // Return value is _very_ system dependent, hard to test - // QTest::addColumn("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/qfilesystemmodel/.gitignore b/tests/auto/qfilesystemmodel/.gitignore deleted file mode 100644 index 9804e5a3d7..0000000000 --- a/tests/auto/qfilesystemmodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfilesystemmodel diff --git a/tests/auto/qfilesystemmodel/qfilesystemmodel.pro b/tests/auto/qfilesystemmodel/qfilesystemmodel.pro deleted file mode 100644 index a7d042ce5e..0000000000 --- a/tests/auto/qfilesystemmodel/qfilesystemmodel.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += qttest_p4 - -QT += widgets widgets-private -QT += core-private gui - -SOURCES += tst_qfilesystemmodel.cpp -TARGET = tst_qfilesystemmodel diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp deleted file mode 100644 index 26fa58e649..0000000000 --- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ /dev/null @@ -1,1046 +0,0 @@ -/**************************************************************************** -** -** 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 -#ifdef QT_BUILD_INTERNAL -#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h" -#endif -#include -#include -#include -#include -#include -#include -#include - -//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"); - - 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("s1"); - QTest::addColumn("s2"); - QTest::addColumn("caseSensitive"); - QTest::addColumn("result"); - QTest::addColumn("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("count"); - QTest::addColumn("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("files"); - QTest::addColumn("dirs"); - QTest::addColumn("dirFilters"); - QTest::addColumn("nameFilters"); - QTest::addColumn("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("files"); - QTest::addColumn("oldFileName"); - QTest::addColumn("newFileName"); - QTest::addColumn("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 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("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< 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 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 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("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("role"); - QTest::addColumn("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 roles = model.roleNames(); - - QFETCH(int, role); - QVERIFY(roles.contains(role)); - - QFETCH(QByteArray, roleName); - QList values = roles.values(role); - QVERIFY(values.contains(roleName)); -} - -QTEST_MAIN(tst_QFileSystemModel) -#include "tst_qfilesystemmodel.moc" - diff --git a/tests/auto/qfocusevent/.gitignore b/tests/auto/qfocusevent/.gitignore deleted file mode 100644 index f189d8aeb9..0000000000 --- a/tests/auto/qfocusevent/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfocusevent diff --git a/tests/auto/qfocusevent/qfocusevent.pro b/tests/auto/qfocusevent/qfocusevent.pro deleted file mode 100644 index d904a0b0bf..0000000000 --- a/tests/auto/qfocusevent/qfocusevent.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qfocusevent.cpp diff --git a/tests/auto/qfocusevent/tst_qfocusevent.cpp b/tests/auto/qfocusevent/tst_qfocusevent.cpp deleted file mode 100644 index 931059b211..0000000000 --- a/tests/auto/qfocusevent/tst_qfocusevent.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QWidget) - -//TESTED_CLASS= -//TESTED_FILES=gui/kernel/qevent.h gui/kernel/qevent.cpp - -class FocusLineEdit : public QLineEdit -{ -public: - FocusLineEdit( QWidget* parent = 0, const char* name = 0 ) : QLineEdit(name, parent) {} - int focusInEventReason; - int focusOutEventReason; - bool focusInEventRecieved; - bool focusInEventGotFocus; - bool focusOutEventRecieved; - bool focusOutEventLostFocus; -protected: - virtual void keyPressEvent( QKeyEvent *e ) - { -// qDebug( QString("keyPressEvent: %1").arg(e->key()) ); - QLineEdit::keyPressEvent( e ); - } - void focusInEvent( QFocusEvent* e ) - { - QLineEdit::focusInEvent( e ); - focusInEventReason = e->reason(); - focusInEventGotFocus = e->gotFocus(); - focusInEventRecieved = TRUE; - } - void focusOutEvent( QFocusEvent* e ) - { - QLineEdit::focusOutEvent( e ); - focusOutEventReason = e->reason(); - focusOutEventLostFocus = !e->gotFocus(); - focusOutEventRecieved = TRUE; - } -}; - -class tst_QFocusEvent : public QObject -{ - Q_OBJECT - -public: - tst_QFocusEvent(); - virtual ~tst_QFocusEvent(); - - - void initWidget(); - -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); - void cleanup(); -private slots: - void checkReason_Tab(); - void checkReason_ShiftTab(); -#ifndef Q_OS_WIN32 - void checkReason_BackTab(); -#endif - void checkReason_Popup(); - void checkReason_focusWidget(); - void checkReason_Shortcut(); - void checkReason_ActiveWindow(); - -private: - QWidget* testFocusWidget; - FocusLineEdit* childFocusWidgetOne; - FocusLineEdit* childFocusWidgetTwo; -}; - -tst_QFocusEvent::tst_QFocusEvent() -{ -} - -tst_QFocusEvent::~tst_QFocusEvent() -{ - -} - -void tst_QFocusEvent::initTestCase() -{ - testFocusWidget = new QWidget( 0 ); - childFocusWidgetOne = new FocusLineEdit( testFocusWidget ); - childFocusWidgetOne->setGeometry( 10, 10, 180, 20 ); - childFocusWidgetTwo = new FocusLineEdit( testFocusWidget ); - childFocusWidgetTwo->setGeometry( 10, 50, 180, 20 ); - - //qApp->setMainWidget( testFocusWidget ); Qt4 - testFocusWidget->resize( 200,100 ); - testFocusWidget->show(); -// Applications don't get focus when launched from the command line on Mac. -#ifdef Q_WS_MAC - testFocusWidget->raise(); -#endif -} - -void tst_QFocusEvent::cleanupTestCase() -{ - delete testFocusWidget; -} - -void tst_QFocusEvent::init() -{ -} - -void tst_QFocusEvent::cleanup() -{ - childFocusWidgetTwo->setGeometry( 10, 50, 180, 20 ); -} - -void tst_QFocusEvent::initWidget() -{ - // On X11 we have to ensure the event was processed before doing any checking, on Windows - // this is processed straight away. - QApplication::setActiveWindow(childFocusWidgetOne); - - for (int i = 0; i < 1000; ++i) { - if (childFocusWidgetOne->isActiveWindow() && childFocusWidgetOne->hasFocus()) - break; - childFocusWidgetOne->activateWindow(); - childFocusWidgetOne->setFocus(); - qApp->processEvents(); - QTest::qWait(100); - } - - // The first lineedit should have focus - QVERIFY( childFocusWidgetOne->hasFocus() ); - - childFocusWidgetOne->focusInEventRecieved = FALSE; - childFocusWidgetOne->focusInEventGotFocus = FALSE; - childFocusWidgetOne->focusInEventReason = -1; - childFocusWidgetOne->focusOutEventRecieved = FALSE; - childFocusWidgetOne->focusOutEventLostFocus = FALSE; - childFocusWidgetOne->focusOutEventReason = -1; - childFocusWidgetTwo->focusInEventRecieved = FALSE; - childFocusWidgetTwo->focusInEventGotFocus = FALSE; - childFocusWidgetTwo->focusInEventReason = -1; - childFocusWidgetTwo->focusOutEventRecieved = FALSE; - childFocusWidgetTwo->focusOutEventLostFocus = FALSE; - childFocusWidgetTwo->focusOutEventReason = -1; -} - -void tst_QFocusEvent::checkReason_Tab() -{ - initWidget(); - - // Now test the tab key - QTest::keyClick( childFocusWidgetOne, Qt::Key_Tab ); - - QVERIFY(childFocusWidgetOne->focusOutEventRecieved); - QVERIFY(childFocusWidgetTwo->focusInEventRecieved); - QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); - QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); - - QVERIFY( childFocusWidgetTwo->hasFocus() ); - QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int) Qt::TabFocusReason ); - QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int) Qt::TabFocusReason ); -} - -void tst_QFocusEvent::checkReason_ShiftTab() -{ - initWidget(); - - // Now test the shift + tab key - QTest::keyClick( childFocusWidgetOne, Qt::Key_Tab, Qt::ShiftModifier ); - - QVERIFY(childFocusWidgetOne->focusOutEventRecieved); - QVERIFY(childFocusWidgetTwo->focusInEventRecieved); - QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); - QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); - - QVERIFY( childFocusWidgetTwo->hasFocus() ); - QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::BacktabFocusReason ); - QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int)Qt::BacktabFocusReason ); - -} - -/*! - In this test we verify that the Qt::KeyBacktab key is handled in a qfocusevent -*/ -// Backtab is not supported on Windows. -#ifndef Q_OS_WIN32 -void tst_QFocusEvent::checkReason_BackTab() -{ - initWidget(); - QVERIFY( childFocusWidgetOne->hasFocus() ); - - // Now test the backtab key - QTest::keyClick( childFocusWidgetOne, Qt::Key_Backtab ); - QTest::qWait(200); - - QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved); - QVERIFY(childFocusWidgetTwo->focusInEventRecieved); - QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); - QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); - - QVERIFY( childFocusWidgetTwo->hasFocus() ); - QCOMPARE( childFocusWidgetOne->focusOutEventReason, int(Qt::BacktabFocusReason) ); - QCOMPARE( childFocusWidgetTwo->focusInEventReason, int(Qt::BacktabFocusReason) ); -} -#endif - -void tst_QFocusEvent::checkReason_Popup() -{ - initWidget(); - - // Now test the popup reason - QMenu* popupMenu = new QMenu( testFocusWidget ); - popupMenu->addMenu( "Test" ); - popupMenu->popup( QPoint(0,0) ); - QTest::qWait(50); - - QTRY_VERIFY(childFocusWidgetOne->focusOutEventLostFocus); - - QTRY_VERIFY( childFocusWidgetOne->hasFocus() ); - QVERIFY( !childFocusWidgetOne->focusInEventRecieved ); - QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); - QVERIFY( !childFocusWidgetTwo->focusInEventRecieved ); - QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved ); - QCOMPARE( childFocusWidgetOne->focusOutEventReason, int(Qt::PopupFocusReason)); - - popupMenu->hide(); - - QVERIFY(childFocusWidgetOne->focusInEventRecieved); - QVERIFY(childFocusWidgetOne->focusInEventGotFocus); - - QVERIFY( childFocusWidgetOne->hasFocus() ); - QVERIFY( childFocusWidgetOne->focusInEventRecieved ); - QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); - QVERIFY( !childFocusWidgetTwo->focusInEventRecieved ); - QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved ); -} - -#ifdef Q_WS_MAC -QT_BEGIN_NAMESPACE - extern void qt_set_sequence_auto_mnemonic(bool); -QT_END_NAMESPACE -#endif - -void tst_QFocusEvent::checkReason_Shortcut() -{ - initWidget(); -#ifdef Q_WS_MAC - qt_set_sequence_auto_mnemonic(true); -#endif - QLabel* label = new QLabel( "&Test", testFocusWidget ); - label->setBuddy( childFocusWidgetTwo ); - label->setGeometry( 10, 50, 90, 20 ); - childFocusWidgetTwo->setGeometry( 105, 50, 95, 20 ); - label->show(); - - QVERIFY( childFocusWidgetOne->hasFocus() ); - QVERIFY( !childFocusWidgetTwo->hasFocus() ); - - QTest::keyClick( label, Qt::Key_T, Qt::AltModifier ); - - QVERIFY(childFocusWidgetOne->focusOutEventRecieved); - QVERIFY(childFocusWidgetTwo->focusInEventRecieved); - QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); - QVERIFY(childFocusWidgetTwo->focusInEventGotFocus); - - QVERIFY( childFocusWidgetTwo->hasFocus() ); - QVERIFY( !childFocusWidgetOne->focusInEventRecieved ); - QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); - QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::ShortcutFocusReason ); - QVERIFY( childFocusWidgetTwo->focusInEventRecieved ); - QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int)Qt::ShortcutFocusReason ); - QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved ); - - label->hide(); - QVERIFY( childFocusWidgetTwo->hasFocus() ); - QVERIFY( !childFocusWidgetOne->hasFocus() ); -#ifdef Q_WS_MAC - qt_set_sequence_auto_mnemonic(false); -#endif -} - -void tst_QFocusEvent::checkReason_focusWidget() -{ - // This test checks that a widget doesn't loose - // its focuswidget just because the focuswidget looses focus. - QWidget window1; - QWidget frame1; - QWidget frame2; - QLineEdit edit1; - QLineEdit edit2; - - QVBoxLayout outerLayout; - outerLayout.addWidget(&frame1); - outerLayout.addWidget(&frame2); - window1.setLayout(&outerLayout); - - QVBoxLayout leftLayout; - QVBoxLayout rightLayout; - leftLayout.addWidget(&edit1); - rightLayout.addWidget(&edit2); - frame1.setLayout(&leftLayout); - frame2.setLayout(&rightLayout); - window1.show(); - - edit1.setFocus(); - QTest::qWait(100); - edit2.setFocus(); - - QVERIFY(frame1.focusWidget() != 0); - QVERIFY(frame2.focusWidget() != 0); -} - -void tst_QFocusEvent::checkReason_ActiveWindow() -{ - initWidget(); - - QDialog* d = new QDialog( testFocusWidget ); - d->show(); - d->activateWindow(); // ### CDE - QApplication::setActiveWindow(d); - QTest::qWaitForWindowShown(d); - - QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved); - QVERIFY(childFocusWidgetOne->focusOutEventLostFocus); - - QVERIFY( !childFocusWidgetOne->focusInEventRecieved ); - QVERIFY( childFocusWidgetOne->focusOutEventRecieved ); - QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::ActiveWindowFocusReason); - QVERIFY( !childFocusWidgetOne->hasFocus() ); - - d->hide(); - QTest::qWait(100); - -#if defined(Q_OS_IRIX) - QEXPECT_FAIL("", "IRIX requires explicit activateWindow(), so this test does not make any sense.", Abort); -#endif - QTRY_VERIFY(childFocusWidgetOne->focusInEventRecieved); - QVERIFY(childFocusWidgetOne->focusInEventGotFocus); - - QVERIFY( childFocusWidgetOne->hasFocus() ); - QVERIFY( childFocusWidgetOne->focusInEventRecieved ); - QCOMPARE( childFocusWidgetOne->focusInEventReason, (int)Qt::ActiveWindowFocusReason); -} - - -QTEST_MAIN(tst_QFocusEvent) -#include "tst_qfocusevent.moc" diff --git a/tests/auto/qfocusframe/.gitignore b/tests/auto/qfocusframe/.gitignore deleted file mode 100644 index 7a6e000227..0000000000 --- a/tests/auto/qfocusframe/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfocusframe diff --git a/tests/auto/qfocusframe/qfocusframe.pro b/tests/auto/qfocusframe/qfocusframe.pro deleted file mode 100644 index 0fcc9bf23d..0000000000 --- a/tests/auto/qfocusframe/qfocusframe.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qfocusframe.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qfocusframe.cpp - - diff --git a/tests/auto/qfocusframe/tst_qfocusframe.cpp b/tests/auto/qfocusframe/tst_qfocusframe.cpp deleted file mode 100644 index 1658cf3fe5..0000000000 --- a/tests/auto/qfocusframe/tst_qfocusframe.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - - -//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/qfontcombobox/.gitignore b/tests/auto/qfontcombobox/.gitignore deleted file mode 100644 index acc19de07e..0000000000 --- a/tests/auto/qfontcombobox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfontcombobox diff --git a/tests/auto/qfontcombobox/qfontcombobox.pro b/tests/auto/qfontcombobox/qfontcombobox.pro deleted file mode 100644 index 7faa0e36bd..0000000000 --- a/tests/auto/qfontcombobox/qfontcombobox.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qfontcombobox.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/qfontcombobox/tst_qfontcombobox.cpp deleted file mode 100644 index 72b3dfe8ca..0000000000 --- a/tests/auto/qfontcombobox/tst_qfontcombobox.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -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("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("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("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/qfontdialog/.gitignore b/tests/auto/qfontdialog/.gitignore deleted file mode 100644 index 5bd48d4951..0000000000 --- a/tests/auto/qfontdialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfontdialog diff --git a/tests/auto/qfontdialog/qfontdialog.pro b/tests/auto/qfontdialog/qfontdialog.pro deleted file mode 100644 index 5a0c2b66bf..0000000000 --- a/tests/auto/qfontdialog/qfontdialog.pro +++ /dev/null @@ -1,12 +0,0 @@ -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/qfontdialog/tst_qfontdialog.cpp b/tests/auto/qfontdialog/tst_qfontdialog.cpp deleted file mode 100644 index 3f12b7501c..0000000000 --- a/tests/auto/qfontdialog/tst_qfontdialog.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include "qfontdialog.h" -#include - -//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[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(dialog.d_func()->familyList); - QListView *styleList = reinterpret_cast(dialog.d_func()->styleList); - QListView *sizeList = reinterpret_cast(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/qfontdialog/tst_qfontdialog_mac_helpers.mm b/tests/auto/qfontdialog/tst_qfontdialog_mac_helpers.mm deleted file mode 100644 index d12f696f7e..0000000000 --- a/tests/auto/qfontdialog/tst_qfontdialog_mac_helpers.mm +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -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(view) title] isEqualTo:@"OK"]) { - [static_cast(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/qformlayout/.gitignore b/tests/auto/qformlayout/.gitignore deleted file mode 100644 index 24e93d561f..0000000000 --- a/tests/auto/qformlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qformlayout diff --git a/tests/auto/qformlayout/qformlayout.pro b/tests/auto/qformlayout/qformlayout.pro deleted file mode 100644 index 24c452af9f..0000000000 --- a/tests/auto/qformlayout/qformlayout.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qformlayout.cpp diff --git a/tests/auto/qformlayout/tst_qformlayout.cpp b/tests/auto/qformlayout/tst_qformlayout.cpp deleted file mode 100644 index 4425205eb9..0000000000 --- a/tests/auto/qformlayout/tst_qformlayout.cpp +++ /dev/null @@ -1,913 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -//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(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 labels; - QList 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(layout.itemAt(0, QFormLayout::LabelRole)->widget()); - QVERIFY(label1 != 0); - QVERIFY(label1->buddy() == &fld1); - - layout.insertRow(0, "&Email:", &fld2); - QLabel *label2 = qobject_cast(layout.itemAt(0, QFormLayout::LabelRole)->widget()); - QVERIFY(label2 != 0); - QVERIFY(label2->buddy() == &fld2); - - layout.insertRow(5, "&Age:", &fld3); - QLabel *label3 = qobject_cast(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(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(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(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(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/qgraphicsanchorlayout/qgraphicsanchorlayout.pro b/tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro deleted file mode 100644 index 5aa2936e3e..0000000000 --- a/tests/auto/qgraphicsanchorlayout/qgraphicsanchorlayout.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private -QT += core-private gui-private -SOURCES += tst_qgraphicsanchorlayout.cpp -CONFIG += parallel_test diff --git a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp deleted file mode 100644 index 5dbe501ea8..0000000000 --- a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ /dev/null @@ -1,2091 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include - - -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 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"); - - // - 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); - - // - setAnchor(l, b, Qt::AnchorLeft, e, Qt::AnchorLeft, 10); - setAnchor(l, e, Qt::AnchorRight, d, Qt::AnchorLeft, 10); - - // - 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); - - // - 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 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"); - - // - 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/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro b/tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro deleted file mode 100644 index bcad43fc12..0000000000 --- a/tests/auto/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private -QT += core-private gui-private -SOURCES += tst_qgraphicsanchorlayout1.cpp -CONFIG += parallel_test diff --git a/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp b/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp deleted file mode 100644 index 05f08e8719..0000000000 --- a/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp +++ /dev/null @@ -1,3111 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -#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 BasicLayoutTestDataList; -Q_DECLARE_METATYPE(BasicLayoutTestDataList) - -typedef QList BasicLayoutTestResultList; -Q_DECLARE_METATYPE(BasicLayoutTestResultList) - -typedef QList 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("size"); - QTest::addColumn("data"); - QTest::addColumn("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("size"); - QTest::addColumn("data"); - QTest::addColumn("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("size"); - QTest::addColumn("data"); - QTest::addColumn("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("size"); - QTest::addColumn("data"); - QTest::addColumn("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& 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 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("size"); - QTest::addColumn("data"); - QTest::addColumn("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("size"); - QTest::addColumn("data"); - QTest::addColumn("removeData"); - QTest::addColumn("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 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("size"); - QTest::addColumn("policy"); - QTest::addColumn("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("policy1"); - QTest::addColumn("policy2"); - QTest::addColumn("width1"); - QTest::addColumn("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 SizeHintArray; -Q_DECLARE_METATYPE(SizeHintArray) - -void tst_QGraphicsAnchorLayout1::testSizeDistribution_data() -{ - // tests only horizontal direction - QTest::addColumn("sizeHints1"); - QTest::addColumn("sizeHints2"); - QTest::addColumn("width1"); - QTest::addColumn("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("size"); - QTest::addColumn("data"); - QTest::addColumn("sizehint"); - QTest::addColumn("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 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/qgraphicseffect/qgraphicseffect.pro b/tests/auto/qgraphicseffect/qgraphicseffect.pro deleted file mode 100644 index 171ab3ffda..0000000000 --- a/tests/auto/qgraphicseffect/qgraphicseffect.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qgraphicseffect.cpp -CONFIG += parallel_test diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp deleted file mode 100644 index e72dd45667..0000000000 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#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 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 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 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 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/qgraphicseffectsource/qgraphicseffectsource.pro b/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro deleted file mode 100644 index 44ec70eef3..0000000000 --- a/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qgraphicseffectsource.cpp -CONFIG += parallel_test diff --git a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp deleted file mode 100644 index 4f39f991c6..0000000000 --- a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -#include - -//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(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("coordinateMode"); - QTest::addColumn("padMode"); - QTest::addColumn("size"); - QTest::addColumn("offset"); - QTest::addColumn("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/qgraphicsgridlayout/.gitignore b/tests/auto/qgraphicsgridlayout/.gitignore deleted file mode 100644 index e3a8cc317c..0000000000 --- a/tests/auto/qgraphicsgridlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicsgridlayout diff --git a/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro b/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro deleted file mode 100644 index 7db7c1ae6f..0000000000 --- a/tests/auto/qgraphicsgridlayout/qgraphicsgridlayout.pro +++ /dev/null @@ -1,6 +0,0 @@ -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/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp deleted file mode 100644 index e9d9cb67bb..0000000000 --- a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ /dev/null @@ -1,3465 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -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(item)); - } - -//private: - QPair 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 ItemList; -Q_DECLARE_METATYPE(ItemList); - -typedef QList 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("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("columnSpan"); - QTest::addColumn("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("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("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("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("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("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("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("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(0)); - QCOMPARE(layout->itemAt(1,0), static_cast(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(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(layout)); - layout->removeAt(0); - QCOMPARE(item0->parentLayoutItem(), static_cast(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("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("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("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("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("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("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("column"); - QTest::addColumn("spacing"); - QTest::addColumn("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("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("row"); - QTest::addColumn("spacing"); - QTest::addColumn("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("spacing"); - QTest::addColumn("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("itemDescriptions"); - QTest::addColumn("expectedMinimumSizeHint"); - QTest::addColumn("expectedPreferredSizeHint"); - QTest::addColumn("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("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("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("itemDescriptions"); - QTest::addColumn("newSize"); - QTest::addColumn("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 RectList; -Q_DECLARE_METATYPE(RectList); - -void tst_QGraphicsGridLayout::alignment2_data() -{ - QTest::addColumn("itemDescriptions"); - QTest::addColumn("newSize"); - QTest::addColumn("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("itemDescriptions"); - QTest::addColumn("newSize"); - QTest::addColumn("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("sizePolicy"); - QTest::addColumn("itemHeight"); - QTest::addColumn("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("w1_fixed"); - QTest::addColumn("w2_fixed"); - QTest::addColumn("w3_fixed"); - QTest::addColumn("w4_fixed"); - QTest::addColumn("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/qgraphicsitem/.gitignore b/tests/auto/qgraphicsitem/.gitignore deleted file mode 100644 index b766388e3e..0000000000 --- a/tests/auto/qgraphicsitem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicsitem diff --git a/tests/auto/qgraphicsitem/qgraphicsitem.pro b/tests/auto/qgraphicsitem/qgraphicsitem.pro deleted file mode 100644 index 51a4426680..0000000000 --- a/tests/auto/qgraphicsitem/qgraphicsitem.pro +++ /dev/null @@ -1,9 +0,0 @@ -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/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp deleted file mode 100644 index 64824b2048..0000000000 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ /dev/null @@ -1,11402 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QPainterPath) -Q_DECLARE_METATYPE(QPointF) -Q_DECLARE_METATYPE(QRectF) - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) -#include -#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 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 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 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(item), (QGraphicsEllipseItem *)item); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); - QCOMPARE(item->flags(), 0); - break; - case 1: - item = new QGraphicsLineItem; - QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type)); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsLineItem *)item); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); - QCOMPARE(item->flags(), 0); - break; - case 2: - item = new QGraphicsPathItem; - QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type)); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsPathItem *)item); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); - QCOMPARE(item->flags(), 0); - break; - case 3: - item = new QGraphicsPixmapItem; - QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type)); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsPixmapItem *)item); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); - QCOMPARE(item->flags(), 0); - break; - case 4: - item = new QGraphicsPolygonItem; - QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type)); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsPolygonItem *)item); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); - QCOMPARE(item->flags(), 0); - break; - case 5: - item = new QGraphicsRectItem; - QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type)); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)item); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsLineItem *)0); - QCOMPARE(item->flags(), 0); - break; - case 6: - item = new QGraphicsTextItem; - QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type)); - QCOMPARE(qgraphicsitem_cast(item), (QGraphicsTextItem *)item); - QCOMPARE(qgraphicsitem_cast(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() << item2); - QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200)); - - item2->setParentItem(item0); - QCOMPARE(item0->children(), QList() << 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(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 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() << item); - item->setSelected(false); - QVERIFY(scene.selectedItems().isEmpty()); - item->setSelected(true); - QCOMPARE(scene.selectedItems(), QList() << 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() << 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"); - QSignalSpy spy(&scene, SIGNAL(changed(QList))); - 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 rlist = qVariantValue >(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 _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 col1 = rect.collidingItems(); - QCOMPARE(col1.size(), 2); - QCOMPARE(col1.first(), static_cast(&line)); - QCOMPARE(col1.last(), static_cast(&rect2)); - - QList col2 = rect2.collidingItems(); - QCOMPARE(col2.size(), 2); - QCOMPARE(col2.first(), static_cast(&line)); - QCOMPARE(col2.last(), static_cast(&rect)); - - QList col3 = line.collidingItems(); - QCOMPARE(col3.size(), 2); - QCOMPARE(col3.first(), static_cast(&rect2)); - QCOMPARE(col3.last(), static_cast(&rect)); - } -} - -void tst_QGraphicsItem::collidesWith_path_data() -{ - QTest::addColumn("pos"); - QTest::addColumn("matrix"); - QTest::addColumn("shape"); - QTest::addColumn("rectCollides"); - QTest::addColumn("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(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("parent"); - QTest::addColumn("parentPos"); - QTest::addColumn("parentTransform"); - QTest::addColumn("pos"); - QTest::addColumn("transform"); - QTest::addColumn("inputRect"); - QTest::addColumn("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(&pathItem)); - //QVERIFY(qgraphicsitem_cast(&pathItem)); - QVERIFY(qgraphicsitem_cast(&pathItem)); - QVERIFY(qgraphicsitem_cast(pPathItem)); - QVERIFY(qgraphicsitem_cast(pPathItem)); - - QVERIFY(qgraphicsitem_cast(&rectItem)); - QVERIFY(qgraphicsitem_cast(&rectItem)); - QVERIFY(qgraphicsitem_cast(pRectItem)); - QVERIFY(qgraphicsitem_cast(pRectItem)); - - QVERIFY(qgraphicsitem_cast(&ellipseItem)); - QVERIFY(qgraphicsitem_cast(&ellipseItem)); - QVERIFY(qgraphicsitem_cast(pEllipseItem)); - QVERIFY(qgraphicsitem_cast(pEllipseItem)); - - QVERIFY(qgraphicsitem_cast(&polygonItem)); - //QVERIFY(qgraphicsitem_cast(&polygonItem)); - QVERIFY(qgraphicsitem_cast(&polygonItem)); - QVERIFY(qgraphicsitem_cast(pPolygonItem)); - QVERIFY(qgraphicsitem_cast(pPolygonItem)); - - QVERIFY(qgraphicsitem_cast(&lineItem)); - QVERIFY(qgraphicsitem_cast(&lineItem)); - QVERIFY(qgraphicsitem_cast(pLineItem)); - QVERIFY(qgraphicsitem_cast(pLineItem)); - - QVERIFY(qgraphicsitem_cast(&pixmapItem)); - QVERIFY(qgraphicsitem_cast(&pixmapItem)); - QVERIFY(qgraphicsitem_cast(pPixmapItem)); - QVERIFY(qgraphicsitem_cast(pPixmapItem)); - - QVERIFY(qgraphicsitem_cast(&textItem)); - QVERIFY(qgraphicsitem_cast(&textItem)); - QVERIFY(qgraphicsitem_cast(pTextItem)); - QVERIFY(qgraphicsitem_cast(pTextItem)); - - // and some casts that _should_ fail: - QVERIFY(!qgraphicsitem_cast(&pathItem)); - QVERIFY(!qgraphicsitem_cast(pPolygonItem)); - - // and this shouldn't crash - QGraphicsItem *ptr = 0; - QVERIFY(!qgraphicsitem_cast(ptr)); - QVERIFY(!qgraphicsitem_cast(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("item"); - QTest::addColumn("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 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 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 control = item->textControl(); - delete item; - QVERIFY(!control); - - item = new QGraphicsTextItem; - - QPointer 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 changes; - QList values; - QList 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(variant, matrix()); - oldValues << variant; - } - break; - case QGraphicsItem::ItemTransformChange: { - QVariant variant; - qVariantSetValue(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(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(scene()); - if (itemSceneChangeTargetScene - && qVariantValue(value) - && itemSceneChangeTargetScene != qVariantValue(value)) { - return qVariantFromValue(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(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(tester.values.at(tester.values.size() - 2)), - QMatrix().translate(50, 0)); - QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90)))); - QVariant variant; - qVariantSetValue(variant, QMatrix()); - QCOMPARE(tester.oldValues.last(), variant); - QCOMPARE(tester.matrix(), QMatrix().rotate(90)); - } - { - tester.resetTransform(); - ++changeCount; - ++changeCount; // notification sent too - - // ItemTransformChange / ItemTransformHasChanged - qVariantSetValue(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(tester.values.at(tester.values.size() - 2)), - QTransform().translate(50, 0)); - QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 1)), - QTransform().rotate(90)); - QVariant variant; - qVariantSetValue(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(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)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(tester.itemChangeReturnValue, 0); - tester.setParentItem(&testerHelper); - QCOMPARE(tester.changes.size(), ++changeCount); - QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange); - QCOMPARE(qVariantValue(tester.values.last()), (QGraphicsItem *)&testerHelper); - QCOMPARE(qVariantValue(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(tester.values.last()), (QGraphicsItem *)&testerHelper); - } - { - // ItemChildRemovedChange 1 - testerHelper.setParentItem(0); - QCOMPARE(tester.changes.size(), ++changeCount); - QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange); - QCOMPARE(qVariantValue(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(parent.values.last()), (QGraphicsItem *)child); - delete child; - QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange); - QCOMPARE(qVariantValue(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(tester.oldValues.last()), (QGraphicsScene *)0); - QCOMPARE(qVariantValue(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(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene); - QCOMPARE(qVariantValue(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0); - QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0); - QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0); - QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2); - QCOMPARE(qVariantValue(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(tester.oldValues.last()), (QGraphicsScene *)0); - QCOMPARE(qVariantValue(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(tester.oldValues.last()), (QGraphicsScene *)&scene2); - QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0); - QCOMPARE(qVariantValue(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(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2); - QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene); - QCOMPARE(qVariantValue(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 filteredEvents; - QList filteredEventReceivers; - bool handlesSceneEvents; - - QList 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(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(text1)); - QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn); - QCOMPARE(tester->filteredEventReceivers.at(2), static_cast(text2)); - QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut); - QCOMPARE(tester->filteredEventReceivers.at(3), static_cast(text2)); - QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn); - QCOMPARE(tester->filteredEventReceivers.at(4), static_cast(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(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(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 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("flags"); - QTest::addColumn("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("line"); - QTest::addColumn("granularity"); - QTest::addColumn("transform"); - QTest::addColumn("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("p_opacity"); - QTest::addColumn("p_opacityFlags"); - QTest::addColumn("c1_opacity"); - QTest::addColumn("c1_opacityFlags"); - QTest::addColumn("c2_opacity"); - QTest::addColumn("c2_opacityFlags"); - QTest::addColumn("p_effectiveOpacity"); - QTest::addColumn("c1_effectiveOpacity"); - QTest::addColumn("c2_effectiveOpacity"); - QTest::addColumn("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 *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 *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() - << grandChild111 << child11 - << grandChild121 << child12 << parent1 - << grandChild211 << child21 - << grandChild221 << child22 << parent2)); - QTRY_COMPARE(paintedItems, QList() - << 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() - << grandChild121 << child12 << parent1 - << grandChild111 << child11 - << grandChild211 << child21 - << grandChild221 << child22 << parent2)); - QCOMPARE(paintedItems, QList() - << 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() - << parent1 << grandChild111 << child11 - << grandChild121 << child12 - << grandChild211 << child21 - << grandChild221 << child22 << parent2)); - QCOMPARE(paintedItems, QList() - << parent2 << child22 << grandChild221 - << child21 << grandChild211 - << child12 << grandChild121 - << child11 << grandChild111 << parent1); -} - -class ClippingAndTransformsScene : public QGraphicsScene -{ -public: - QList 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 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("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("untransformable1"); - QTest::addColumn("untransformable2"); - QTest::addColumn("untransformable3"); - QTest::addColumn("rotation1"); - QTest::addColumn("rotation2"); - QTest::addColumn("rotation3"); - QTest::addColumn("deviceX"); - QTest::addColumn("mapResult1"); - QTest::addColumn("mapResult2"); - QTest::addColumn("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(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("origin"); - QTest::addColumn("rotation"); - QTest::addColumn("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::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("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() - << 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() << 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 items = scene.items(QPointF(80, 80)); - QCOMPARE(items.size(), 1); - QCOMPARE(items.at(0), static_cast(item3)); - - scene.setItemIndexMethod(QGraphicsScene::NoIndex); - QTest::qWait(100); - - items = scene.items(QPointF(80, 80)); - QCOMPARE(items.size(), 1); - QCOMPARE(items.at(0), static_cast(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 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(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(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 blurEffect = new QGraphicsBlurEffect; - item->setGraphicsEffect(blurEffect); - QCOMPARE(item->graphicsEffect(), static_cast(blurEffect)); - - // Ensure the existing effect is deleted when setting a new one. - QPointer shadowEffect = new QGraphicsDropShadowEffect; - item->setGraphicsEffect(shadowEffect); - QVERIFY(!blurEffect); - QCOMPARE(item->graphicsEffect(), static_cast(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(&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() << 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() << child1 << child3 << child4 << child2)); - - // Move child2 before child1 - child2->stackBefore(child1); // 2134 - QCOMPARE(parent.childItems(), (QList() << child2 << child1 << child3 << child4)); - child2->stackBefore(child2); // 2134 - QCOMPARE(parent.childItems(), (QList() << child2 << child1 << child3 << child4)); - child1->setZValue(1); // 2341 - QCOMPARE(parent.childItems(), (QList() << child2 << child3 << child4 << child1)); - child1->stackBefore(child2); // 2341 - QCOMPARE(parent.childItems(), (QList() << child2 << child3 << child4 << child1)); - child1->setZValue(0); // 1234 - QCOMPARE(parent.childItems(), (QList() << child1 << child2 << child3 << child4)); - child4->stackBefore(child1); // 4123 - QCOMPARE(parent.childItems(), (QList() << child4 << child1 << child2 << child3)); - child4->setZValue(1); // 1234 (4123) - QCOMPARE(parent.childItems(), (QList() << child1 << child2 << child3 << child4)); - child3->stackBefore(child1); // 3124 (4312) - QCOMPARE(parent.childItems(), (QList() << child3 << child1 << child2 << child4)); - child4->setZValue(0); // 4312 - QCOMPARE(parent.childItems(), (QList() << 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() << child1 << child2 << child3 << child4)); - - // Remove and append - scene.removeItem(child2); - scene.addItem(child2); - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child1 << child3 << child4 << child2)); - - // Move child2 before child1 - child2->stackBefore(child1); // 2134 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child1 << child3 << child4)); - child2->stackBefore(child2); // 2134 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child1 << child3 << child4)); - child1->setZValue(1); // 2341 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child3 << child4 << child1)); - child1->stackBefore(child2); // 2341 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child3 << child4 << child1)); - child1->setZValue(0); // 1234 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child1 << child2 << child3 << child4)); - child4->stackBefore(child1); // 4123 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child4 << child1 << child2 << child3)); - child4->setZValue(1); // 1234 (4123) - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child1 << child2 << child3 << child4)); - child3->stackBefore(child1); // 3124 (4312) - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child3 << child1 << child2 << child4)); - child4->setZValue(0); // 4312 - QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << 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(&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("focusFlag"); - QTest::addColumn("useStickyFocus"); - QTest::addColumn("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus - - QTest::newRow("Focus goes through.") - << static_cast(0x0) << false << 1; - - QTest::newRow("Focus goes through, even with sticky scene.") - << static_cast(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(&view)); - QVERIFY(itemWithFocus->hasFocus()); - - const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center()); - const QList itemsAtMousePressPosition = scene.items(mousePressPoint); - QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop)); - - sendMousePress(&scene, mousePressPoint); - - switch (expectedFocusItem) { - case 0: - QCOMPARE(scene.focusItem(), static_cast(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("flag"); - QTest::addColumn("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 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/qgraphicsitemanimation/.gitignore b/tests/auto/qgraphicsitemanimation/.gitignore deleted file mode 100644 index fe9fe0b8ec..0000000000 --- a/tests/auto/qgraphicsitemanimation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicsitemanimation diff --git a/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro b/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro deleted file mode 100644 index 5d723da32e..0000000000 --- a/tests/auto/qgraphicsitemanimation/qgraphicsitemanimation.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qgraphicsitemanimation.cpp -DEFINES += QT_NO_CAST_TO_ASCII -CONFIG += parallel_test - diff --git a/tests/auto/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp b/tests/auto/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp deleted file mode 100644 index f7cf393253..0000000000 --- a/tests/auto/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -//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(0.5, QPointF(5, -5)))); - QCOMPARE(animation.posList().at(1), (QPair(1.0, QPointF(10, -10)))); - QCOMPARE(animation.rotationList().at(0), (QPair(0.3, 2.3))); - QCOMPARE(animation.translationList().at(0), (QPair(0.3, QPointF(15, 15)))); - QCOMPARE(animation.scaleList().at(0), (QPair(0.3, QPointF(2.5, 1.8)))); - QCOMPARE(animation.shearList().at(0), (QPair(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 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/qgraphicslayout/.gitignore b/tests/auto/qgraphicslayout/.gitignore deleted file mode 100644 index b3b27f68a1..0000000000 --- a/tests/auto/qgraphicslayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicslayout diff --git a/tests/auto/qgraphicslayout/qgraphicslayout.pro b/tests/auto/qgraphicslayout/qgraphicslayout.pro deleted file mode 100644 index ea176c98fe..0000000000 --- a/tests/auto/qgraphicslayout/qgraphicslayout.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# 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/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp deleted file mode 100644 index 3eac04e4e5..0000000000 --- a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp +++ /dev/null @@ -1,992 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -//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 functionCount; -private: - QMap 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(0)); - QCOMPARE(w2->parentItem(), static_cast(0)); - scene.addItem(w1); - QCOMPARE(w1->parentItem(), static_cast(0)); - window->setLayout(l1); - QCOMPARE(w1->parentItem(), static_cast(window)); - QCOMPARE(w2->parentItem(), static_cast(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(window2)); - QCOMPARE(w4->parentItem(), static_cast(window2)); - - // graphics item with another parent - QGraphicsLinearLayout *l5 = new QGraphicsLinearLayout(); - l5->addItem(w1); - l5->addItem(w2); - QCOMPARE(w1->parentItem(), static_cast(window)); - QCOMPARE(w2->parentItem(), static_cast(window)); - QGraphicsLinearLayout *l4 = new QGraphicsLinearLayout(); - l4->addItem(l5); - QGraphicsWidget *window3 = new QGraphicsWidget(); - scene.addItem(window3); - window3->setLayout(l4); - - QCOMPARE(w1->parentItem(), static_cast(window3)); - QCOMPARE(w2->parentItem(), static_cast(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 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(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(static_cast(item)); - //clearAllCounters(lay); - } else { - TestGraphicsWidget *wid = static_cast(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 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(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(li->graphicsItem())->setRect(geom); - } - } -private: - QTimeLine m_timeline; - QVector fromGeoms; - QVector 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(li1->graphicsItem())->rect(), QRectF( 0, 0, 33, 99)); - QTRY_COMPARE(static_cast(li2->graphicsItem())->rect(), QRectF(33, 0, 33, 99)); - QTRY_COMPARE(static_cast(li3->graphicsItem())->rect(), QRectF(66, 0, 33, 99)); - - lout->setOrientation(Qt::Vertical); - - QTRY_COMPARE(static_cast(li1->graphicsItem())->rect(), QRectF(0, 0, 99, 33)); - QTRY_COMPARE(static_cast(li2->graphicsItem())->rect(), QRectF(0, 33, 99, 33)); - QTRY_COMPARE(static_cast(li3->graphicsItem())->rect(), QRectF(0, 66, 99, 33)); - -} - -class CustomLayoutItem : public QGraphicsLayoutItem { -public: - CustomLayoutItem(QSet *destructedSet) - : QGraphicsLayoutItem() - { - m_destructedSet = destructedSet; - setOwnedByLayout(true); - } - - QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const; - - ~CustomLayoutItem() { - m_destructedSet->insert(this); - } -private: - QSet *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 *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 *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 &actual, const QSet &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(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(parentItem)); - } -} - -QSizeF sizeHint(Qt::SizeHint /* which */, const QSizeF & /* constraint */) const -{ - return QSizeF(50,50); -} - -QList items; - -}; - -void tst_QGraphicsLayout::ownership() -{ - QGraphicsScene scene; - QGraphicsView view(&scene); - - { - QGraphicsLinearLayout *lay = new QGraphicsLinearLayout; - QSet 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 expected; - expected << li1 << li2 << li3; - QVERIFY(compareSets(destructedSet, expected)); - } - - { - QGraphicsWidget *window = new QGraphicsWidget; - QGraphicsLinearLayout *lay = new QGraphicsLinearLayout; - QSet 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/qgraphicslayoutitem/.gitignore b/tests/auto/qgraphicslayoutitem/.gitignore deleted file mode 100644 index 55a8d18acb..0000000000 --- a/tests/auto/qgraphicslayoutitem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicslayoutitem diff --git a/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro b/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro deleted file mode 100644 index ed9adf87fd..0000000000 --- a/tests/auto/qgraphicslayoutitem/qgraphicslayoutitem.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qgraphicslayoutitem.cpp -CONFIG += parallel_test - diff --git a/tests/auto/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp b/tests/auto/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp deleted file mode 100644 index a8b6c0854e..0000000000 --- a/tests/auto/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -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("sizeHint"); - QTest::addColumn("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("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("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( 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("size"); - QTest::addColumn("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("size"); - QTest::addColumn("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("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("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/qgraphicslinearlayout/.gitignore b/tests/auto/qgraphicslinearlayout/.gitignore deleted file mode 100644 index 95c7dac979..0000000000 --- a/tests/auto/qgraphicslinearlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicslinearlayout diff --git a/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro deleted file mode 100644 index 1f7ff0cc6e..0000000000 --- a/tests/auto/qgraphicslinearlayout/qgraphicslinearlayout.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qgraphicslinearlayout.cpp -CONFIG += parallel_test - diff --git a/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp deleted file mode 100644 index 873a711127..0000000000 --- a/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp +++ /dev/null @@ -1,1650 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -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("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("orientation"); - QTest::addColumn("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("itemCount"); - QTest::addColumn("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("itemCount"); - QTest::addColumn("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("itemCount"); - QTest::addColumn("layoutCount"); - QTest::addColumn("itemSpacing"); - QTest::addColumn("spacing"); - QTest::addColumn("orientation"); - QTest::addColumn("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("itemCount"); - QTest::addColumn("layoutCount"); - QTest::addColumn("insertItemAt"); - QTest::addColumn("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("itemCount"); - QTest::addColumn("layoutCount"); - QTest::addColumn("insertItemAt"); - QTest::addColumn("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); - - QListitems; - 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("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("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(w0)); - QCOMPARE(l->itemAt(1), static_cast(w1)); - QCOMPARE(l->itemAt(2), static_cast(w2)); - QCOMPARE(l->itemAt(3), static_cast(w3)); -} - -void tst_QGraphicsLinearLayout::orientation_data() -{ - QTest::addColumn("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 positions; - - view.show(); - widget->show(); - qApp->processEvents(); - - for (i = 0; i < itemCount; ++i) { - QGraphicsWidget *item = static_cast(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(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("itemCount"); - QTest::addColumn("layoutCount"); - QTest::addColumn("removeItemAt"); - QTest::addColumn("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(&layout)); - layout.removeAt(removeItemAt); - wParent = w->parentLayoutItem(); - QCOMPARE(wParent, static_cast(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("itemCount"); - QTest::addColumn("layoutCount"); - QTest::addColumn("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("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("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("index"); - QTest::addColumn("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 IntList; -Q_DECLARE_METATYPE(IntList) -Q_DECLARE_METATYPE(qreal) - -void tst_QGraphicsLinearLayout::setStretchFactor_data() -{ - QTest::addColumn("totalSize"); - QTest::addColumn("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(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("orientation"); - QTest::addColumn("count"); - QTest::addColumn("preferredSizeHints"); - QTest::addColumn("stretches"); - QTest::addColumn("ignoreFlag"); - QTest::addColumn("newSize"); - QTest::addColumn("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("which"); - QTest::addColumn("constraint"); - QTest::addColumn("spacing"); - QTest::addColumn("layoutMargin"); - QTest::addColumn("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(layout)); - QCOMPARE(layout->parentLayoutItem(), static_cast(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(layout2a)); - QCOMPARE(layout2a->parentLayoutItem(), static_cast(layout2)); - QCOMPARE(layout2->parentLayoutItem(), static_cast(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/qgraphicsobject/qgraphicsobject.pro b/tests/auto/qgraphicsobject/qgraphicsobject.pro deleted file mode 100644 index 5232ec8372..0000000000 --- a/tests/auto/qgraphicsobject/qgraphicsobject.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) - -QT += widgets -QT += core-private - -SOURCES += tst_qgraphicsobject.cpp -CONFIG += parallel_test diff --git a/tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp b/tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp deleted file mode 100644 index 85e36b74b2..0000000000 --- a/tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include - -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/qgraphicspixmapitem/.gitignore b/tests/auto/qgraphicspixmapitem/.gitignore deleted file mode 100644 index 1e92419fd0..0000000000 --- a/tests/auto/qgraphicspixmapitem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicspixmapitem diff --git a/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro b/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro deleted file mode 100644 index 6b1ad34057..0000000000 --- a/tests/auto/qgraphicspixmapitem/qgraphicspixmapitem.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qgraphicspixmapitem.cpp -CONFIG += parallel_test - diff --git a/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp b/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp deleted file mode 100644 index b2dccb0b09..0000000000 --- a/tests/auto/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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("pixmap"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("point"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("otherPixmap"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("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("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("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("pixmap"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("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("pixmap"); - QTest::addColumn("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("variant"); - QTest::addColumn("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("extension"); - QTest::addColumn("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("extension"); - QTest::addColumn("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/qgraphicspolygonitem/.gitignore b/tests/auto/qgraphicspolygonitem/.gitignore deleted file mode 100644 index 595076024b..0000000000 --- a/tests/auto/qgraphicspolygonitem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicspolygonitem diff --git a/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro b/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro deleted file mode 100644 index 2aa16751e6..0000000000 --- a/tests/auto/qgraphicspolygonitem/qgraphicspolygonitem.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qgraphicspolygonitem.cpp -CONFIG += parallel_test - diff --git a/tests/auto/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp b/tests/auto/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp deleted file mode 100644 index 061b3eda81..0000000000 --- a/tests/auto/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -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("polygon"); - QTest::addColumn("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("polygon"); - QTest::addColumn("point"); - QTest::addColumn("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("polygon"); - QTest::addColumn("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("polygon"); - QTest::addColumn("otherPolygon"); - QTest::addColumn("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("polygon"); - QTest::addColumn("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("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("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("variant"); - QTest::addColumn("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("extension"); - QTest::addColumn("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("extension"); - QTest::addColumn("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/qgraphicsproxywidget/.gitignore b/tests/auto/qgraphicsproxywidget/.gitignore deleted file mode 100644 index 530452478b..0000000000 --- a/tests/auto/qgraphicsproxywidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicsproxywidget diff --git a/tests/auto/qgraphicsproxywidget/qgraphicsproxywidget.pro b/tests/auto/qgraphicsproxywidget/qgraphicsproxywidget.pro deleted file mode 100644 index a649ae1a3c..0000000000 --- a/tests/auto/qgraphicsproxywidget/qgraphicsproxywidget.pro +++ /dev/null @@ -1,8 +0,0 @@ -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/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp deleted file mode 100644 index 78c545e25a..0000000000 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ /dev/null @@ -1,3649 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include // qSmartMin functions... -#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) -#include -#endif -#ifdef Q_WS_X11 -#include -#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 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("widgetExists"); - QTest::addColumn("insertWidget"); - QTest::addColumn("hasParent"); - QTest::addColumn("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 proxy = new SubQGraphicsProxyWidget; - SubQGraphicsProxyWidget parentProxy; - scene.addItem(proxy); - scene.addItem(&parentProxy); - if (proxyHasParent) - proxy->setParent(&parentProxy); - QPointer 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(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("eventType"); - QTest::addColumn("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("widgetHasFocus"); - QTest::addColumn("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("hasWidget"); - QTest::addColumn("hasScene"); - QTest::addColumn("next"); - QTest::addColumn("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("

old foo new

"); - 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("hasWidget"); - QTest::addColumn("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("hasWidget"); - QTest::addColumn("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("hasWidget"); - QTest::addColumn("hoverEnabled"); - QTest::addColumn("mouseTracking"); - QTest::addColumn("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("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("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("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("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("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("which"); - QTest::addColumn("constraint"); - QTest::addColumn("sizeHint"); - QTest::addColumn("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(0, 0, 200, 12) << QRect(0, 12, 102, 10)); - QCOMPARE(widget->npaints, 2); - QCOMPARE(widget->paintEventRegion.rects(), - QVector() << 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 lineEdit = new QLineEdit; - QPointer 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 proxy = scene.addWidget(lineEdit2); - - delete lineEdit2; - QVERIFY(!proxy); -} - -void tst_QGraphicsProxyWidget::resize_simple_data() -{ - QTest::addColumn("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(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(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(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("moveCombo"); - QTest::addColumn("comboPos"); - QTest::addColumn("proxyPos"); - QTest::addColumn("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(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(static_cast(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(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) -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"); - QSignalSpy signalSpy(&scene, SIGNAL(changed(const QList &))); - - 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 arguments = signalSpy.takeFirst(); - const QList updateRects = qvariant_cast >(arguments.at(0)); - QCOMPARE(updateRects.size(), 1); - QCOMPARE(updateRects.at(0), proxy->sceneBoundingRect()); -} - -void tst_QGraphicsProxyWidget::stylePropagation() -{ - QPointer 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 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(this)) - embeddedPopup = true; - hide(); - } -}; - -void tst_QGraphicsProxyWidget::actionsContextMenu_data() -{ - QTest::addColumn("actionsContextMenu"); - QTest::addColumn("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("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("proxyFlags"); - QTest::addColumn("widgetFlags"); - QTest::addColumn("resultingProxyFlags"); - QTest::addColumn("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(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/qgraphicsscene/.gitignore b/tests/auto/qgraphicsscene/.gitignore deleted file mode 100644 index df1097ad74..0000000000 --- a/tests/auto/qgraphicsscene/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicsscene diff --git a/tests/auto/qgraphicsscene/Ash_European.jpg b/tests/auto/qgraphicsscene/Ash_European.jpg deleted file mode 100644 index 8581d322ba..0000000000 Binary files a/tests/auto/qgraphicsscene/Ash_European.jpg and /dev/null differ diff --git a/tests/auto/qgraphicsscene/graphicsScene_selection.data b/tests/auto/qgraphicsscene/graphicsScene_selection.data deleted file mode 100644 index 8ff3feebb1..0000000000 Binary files a/tests/auto/qgraphicsscene/graphicsScene_selection.data and /dev/null differ diff --git a/tests/auto/qgraphicsscene/images.qrc b/tests/auto/qgraphicsscene/images.qrc deleted file mode 100644 index cac10bef82..0000000000 --- a/tests/auto/qgraphicsscene/images.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - Ash_European.jpg - - diff --git a/tests/auto/qgraphicsscene/qgraphicsscene.pro b/tests/auto/qgraphicsscene/qgraphicsscene.pro deleted file mode 100644 index 75b4d84fb4..0000000000 --- a/tests/auto/qgraphicsscene/qgraphicsscene.pro +++ /dev/null @@ -1,20 +0,0 @@ -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/qgraphicsscene/testData/render/all-all-45-deg-left.png b/tests/auto/qgraphicsscene/testData/render/all-all-45-deg-left.png deleted file mode 100644 index 526b897c1c..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-45-deg-left.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-45-deg-right.png b/tests/auto/qgraphicsscene/testData/render/all-all-45-deg-right.png deleted file mode 100644 index 83563872c1..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-45-deg-right.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-scale-2x.png b/tests/auto/qgraphicsscene/testData/render/all-all-scale-2x.png deleted file mode 100644 index a929621bca..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-scale-2x.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-translate-0-50.png b/tests/auto/qgraphicsscene/testData/render/all-all-translate-0-50.png deleted file mode 100644 index aeaf20ae41..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-translate-0-50.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-translate-50-0.png b/tests/auto/qgraphicsscene/testData/render/all-all-translate-50-0.png deleted file mode 100644 index ed80dba118..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-translate-50-0.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png b/tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png deleted file mode 100644 index 9b401b41c7..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png b/tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png deleted file mode 100644 index 1c5969870d..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-all-untransformed.png b/tests/auto/qgraphicsscene/testData/render/all-all-untransformed.png deleted file mode 100644 index 3592744bda..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-all-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-bottomleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/all-bottomleft-untransformed.png deleted file mode 100644 index ab15e7228b..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-bottomleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-bottomright-untransformed.png b/tests/auto/qgraphicsscene/testData/render/all-bottomright-untransformed.png deleted file mode 100644 index 82e25762fa..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-bottomright-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/all-topleft-untransformed.png deleted file mode 100644 index 934ee4679b..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/all-topright-untransformed.png b/tests/auto/qgraphicsscene/testData/render/all-topright-untransformed.png deleted file mode 100644 index aced485c75..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/all-topright-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png b/tests/auto/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png deleted file mode 100644 index 5df8ab0612..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/bottom-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/bottom-topleft-untransformed.png deleted file mode 100644 index bb04881763..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/bottom-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/bottomleft-all-untransformed.png b/tests/auto/qgraphicsscene/testData/render/bottomleft-all-untransformed.png deleted file mode 100644 index 907dec647d..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/bottomleft-all-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png deleted file mode 100644 index d37313c06d..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/bottomright-all-untransformed.png b/tests/auto/qgraphicsscene/testData/render/bottomright-all-untransformed.png deleted file mode 100644 index 9fbafe48d5..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/bottomright-all-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png deleted file mode 100644 index 1d0253796e..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/left-bottomright-untransformed.png b/tests/auto/qgraphicsscene/testData/render/left-bottomright-untransformed.png deleted file mode 100644 index bcfda9968b..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/left-bottomright-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/left-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/left-topleft-untransformed.png deleted file mode 100644 index b443a4f991..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/left-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/right-bottomright-untransformed.png b/tests/auto/qgraphicsscene/testData/render/right-bottomright-untransformed.png deleted file mode 100644 index e6922e0920..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/right-bottomright-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/right-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/right-topleft-untransformed.png deleted file mode 100644 index a74f218876..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/right-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/top-bottomright-untransformed.png b/tests/auto/qgraphicsscene/testData/render/top-bottomright-untransformed.png deleted file mode 100644 index 6c51907a6d..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/top-bottomright-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/top-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/top-topleft-untransformed.png deleted file mode 100644 index 0a37133e31..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/top-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/topleft-all-untransformed.png b/tests/auto/qgraphicsscene/testData/render/topleft-all-untransformed.png deleted file mode 100644 index edc7dc9ce6..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/topleft-all-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/topleft-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/topleft-topleft-untransformed.png deleted file mode 100644 index e37051f7d2..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/topleft-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/topright-all-untransformed.png b/tests/auto/qgraphicsscene/testData/render/topright-all-untransformed.png deleted file mode 100644 index a185d14ebd..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/topright-all-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/testData/render/topright-topleft-untransformed.png b/tests/auto/qgraphicsscene/testData/render/topright-topleft-untransformed.png deleted file mode 100644 index 42e07f11ea..0000000000 Binary files a/tests/auto/qgraphicsscene/testData/render/topright-topleft-untransformed.png and /dev/null differ diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp deleted file mode 100644 index 0a34573039..0000000000 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ /dev/null @@ -1,4710 +0,0 @@ -/**************************************************************************** -** -** 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 -#if defined(Q_OS_WINCE) -#include -#endif - -#include -#include -#include -#include -#include -#include "../gui/painting/qpathclipper/pathcompare.h" - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) -#include -#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) -Q_DECLARE_METATYPE(QList) -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 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 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 items; - items< >("rects"); - QTest::addColumn("matrix"); - QTest::addColumn("boundingRect"); - - QMatrix transformationMatrix; - transformationMatrix.translate(50, -50); - transformationMatrix.scale(2, 2); - transformationMatrix.rotate(90); - - QTest::newRow("none") - << QList() - << QMatrix() - << QRectF(); - QTest::newRow("{{0, 0, 10, 10}}") - << (QList() << QRectF(0, 0, 10, 10)) - << QMatrix() - << QRectF(0, 0, 10, 10); - QTest::newRow("{{-10, -10, 10, 10}}") - << (QList() << QRectF(-10, -10, 10, 10)) - << QMatrix() - << QRectF(-10, -10, 10, 10); - QTest::newRow("{{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}") - << (QList() << 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(0, 0, 10, 10)) - << transformationMatrix - << QRectF(30, -50, 20, 20); - QTest::newRow("transformed {{-10, -10, 10, 10}}") - << (QList() << QRectF(-10, -10, 10, 10)) - << transformationMatrix - << QRectF(50, -70, 20, 20); - QTest::newRow("transformed {{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}") - << (QList() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10)) - << transformationMatrix - << QRectF(50, -2050, 2000, 2000); - - QList 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, 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 >("items"); - QTest::addColumn("point"); - QTest::addColumn >("itemsAtPoint"); - - QTest::newRow("empty") - << QList() - << QPointF() - << QList(); - QTest::newRow("1") - << (QList() << QRectF(0, 0, 10, 10)) - << QPointF(0, 0) - << (QList() << 0); - QTest::newRow("2") - << (QList() << QRectF(0, 0, 10, 10)) - << QPointF(5, 5) - << (QList() << 0); - QTest::newRow("3") - << (QList() << QRectF(0, 0, 10, 10)) - << QPointF(9.9, 9.9) - << (QList() << 0); - QTest::newRow("3.5") - << (QList() << QRectF(0, 0, 10, 10)) - << QPointF(10, 10) - << QList(); - QTest::newRow("4") - << (QList() << QRectF(0, 0, 10, 10) << QRectF(9.9, 9.9, 10, 10)) - << QPointF(9.9, 9.9) - << (QList() << 1 << 0); - QTest::newRow("4.5") - << (QList() << QRectF(0, 0, 10, 10) << QRectF(10, 10, 10, 10)) - << QPointF(10, 10) - << (QList() << 1); - QTest::newRow("5") - << (QList() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10)) - << QPointF(10, 10) - << (QList() << 1 << 0); - QTest::newRow("6") - << (QList() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10) << QRectF(0, 0, 20, 30)) - << QPointF(10, 10) - << (QList() << 2 << 1 << 0); -} - -void tst_QGraphicsScene::items_QPointF() -{ - QFETCH(QList, items); - QFETCH(QPointF, point); - QFETCH(QList, itemsAtPoint); - - QGraphicsScene scene; - - int n = 0; - QList 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 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() << item1); - QCOMPARE(scene.items(QRectF(10, -10, 10, 10)), QList() << item2); - QCOMPARE(scene.items(QRectF(10, 10, 10, 10)), QList() << item3); - QCOMPARE(scene.items(QRectF(-10, 10, 10, 10)), QList() << item4); - QCOMPARE(scene.items(QRectF(-10, -10, 1, 1)), QList() << item1); - QCOMPARE(scene.items(QRectF(10, -10, 1, 1)), QList() << item2); - QCOMPARE(scene.items(QRectF(10, 10, 1, 1)), QList() << item3); - QCOMPARE(scene.items(QRectF(-10, 10, 1, 1)), QList() << item4); - - QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList() << item2 << item1); - QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList() << item4 << item3); - - item1->setZValue(3); - item2->setZValue(2); - item3->setZValue(1); - item4->setZValue(0); - - QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList() << item1 << item2); - QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList() << item3 << item4); -} - -void tst_QGraphicsScene::items_QRectF_2_data() -{ - QTest::addColumn("ellipseRect"); - QTest::addColumn("sceneRect"); - QTest::addColumn("selectionMode"); - QTest::addColumn("contained"); - QTest::addColumn("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() << item1); - QCOMPARE(scene.items(poly2), QList() << item2); - QCOMPARE(scene.items(poly3), QList() << item3); - QCOMPARE(scene.items(poly4), QList() << 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() << item1); - QCOMPARE(scene.items(poly2), QList() << item2); - QCOMPARE(scene.items(poly3), QList() << item3); - QCOMPARE(scene.items(poly4), QList() << item4); - - poly1 = QPolygonF(QRectF(-10, -10, 40, 10)); - poly2 = QPolygonF(QRectF(-10, 10, 40, 10)); - - QCOMPARE(scene.items(poly1), QList() << item2 << item1); - QCOMPARE(scene.items(poly2), QList() << item4 << item3); - - item1->setZValue(3); - item2->setZValue(2); - item3->setZValue(1); - item4->setZValue(0); - - QCOMPARE(scene.items(poly1), QList() << item1 << item2); - QCOMPARE(scene.items(poly2), QList() << 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() << item1); - QCOMPARE(scene.items(path2), QList() << item2); - QCOMPARE(scene.items(path3), QList() << item3); - QCOMPARE(scene.items(path4), QList() << 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() << item1); - QCOMPARE(scene.items(path2), QList() << item2); - QCOMPARE(scene.items(path3), QList() << item3); - QCOMPARE(scene.items(path4), QList() << item4); - - path1 = QPainterPath(); path1.addRect(QRectF(-10, -10, 40, 10)); - path2 = QPainterPath(); path2.addRect(QRectF(-10, 10, 40, 10)); - - QCOMPARE(scene.items(path1), QList() << item2 << item1); - QCOMPARE(scene.items(path2), QList() << item4 << item3); - - item1->setZValue(3); - item2->setZValue(2); - item3->setZValue(1); - item4->setZValue(0); - - QCOMPARE(scene.items(path1), QList() << item1 << item2); - QCOMPARE(scene.items(path2), QList() << 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 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 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 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 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() << 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 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 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 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 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 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 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()); - QCOMPARE(emptyGroup->children(), QList()); - QVERIFY(!emptyGroup->parentItem()); - QCOMPARE(emptyGroup->scene(), &scene); -} - -class EventTester : public QGraphicsEllipseItem -{ -public: - EventTester() - : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false) - { } - - bool ignoreMouse; - QList 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 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 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("targetRect"); - QTest::addColumn("sourceRect"); - QTest::addColumn("aspectRatioMode"); - QTest::addColumn("matrix"); - QTest::addColumn("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"); - QSignalSpy spy(&scene, SIGNAL(changed(QList))); - - // 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 >(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 receivedSceneEvents; - QList 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(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(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(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 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("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() - << c_1_2 << c_1_1_1 << c_1 << t_1); - QCOMPARE(scene.items(-53, 47, 136, 3), - QList() - << 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() - << c_2_1_1 << c_1_1_1); - QCOMPARE(scene.items(-26, -3, 92, 79), - QList() - << 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 > changes; - -public slots: - void changed(const QList &dirty) - { - changes << dirty; - } -}; - -void tst_QGraphicsScene::changedSignal_data() -{ - QTest::addColumn("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 &)), &cl, SLOT(changed(const QList &))); - - 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("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("flags"); - QTest::addColumn("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(&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::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::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::GraphicsSceneHoverLeave); - QCOMPARE(tester2->eventTypes, QList() - << 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::GraphicsSceneHoverMove - << QEvent::GrabMouse - << QEvent::GraphicsSceneMousePress - << QEvent::UngrabMouse); - } -} - -void tst_QGraphicsScene::initialFocus_data() -{ - QTest::addColumn("activeScene"); - QTest::addColumn("explicitSetFocus"); - QTest::addColumn("isPanel"); - QTest::addColumn("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 children = item->childItems(); - QCOMPARE(children.count(), 10); - foreach (QGraphicsItem *child, children) - QVERIFY(!static_cast(child)->polished); - - QApplication::sendPostedEvents(&scene, QEvent::MetaCall); - foreach (QGraphicsItem *child, children) - QVERIFY(static_cast(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(&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(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 &)), &cl, SLOT(changed(const QList &))); - - 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/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro deleted file mode 100644 index 5e61034d7c..0000000000 --- a/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro +++ /dev/null @@ -1,6 +0,0 @@ -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/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp deleted file mode 100644 index 7507701267..0000000000 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -//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("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/qgraphicstransform/qgraphicstransform.pro b/tests/auto/qgraphicstransform/qgraphicstransform.pro deleted file mode 100644 index de7f01f36f..0000000000 --- a/tests/auto/qgraphicstransform/qgraphicstransform.pro +++ /dev/null @@ -1,6 +0,0 @@ -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/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp deleted file mode 100644 index 7d5a9578ad..0000000000 --- a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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("axis"); - QTest::addColumn("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("axis"); - QTest::addColumn("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/qgraphicsview/.gitignore b/tests/auto/qgraphicsview/.gitignore deleted file mode 100644 index c8182c9e0d..0000000000 --- a/tests/auto/qgraphicsview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicsview diff --git a/tests/auto/qgraphicsview/qgraphicsview.pro b/tests/auto/qgraphicsview/qgraphicsview.pro deleted file mode 100644 index 9f32522546..0000000000 --- a/tests/auto/qgraphicsview/qgraphicsview.pro +++ /dev/null @@ -1,9 +0,0 @@ -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/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp deleted file mode 100644 index 444e15a788..0000000000 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ /dev/null @@ -1,4558 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include - -#include - -#include -#if !defined(QT_NO_STYLE_MOTIF) -#include -#endif -#if !defined(QT_NO_STYLE_WINDOWS) -#include -#endif -#if !defined(QT_NO_STYLE_PLASTIQUE) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../platformquirks.h" - -//TESTED_CLASS= -//TESTED_FILES= - -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QList) -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 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 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(&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()); - sendMousePress(view.viewport(), QPoint(), Qt::LeftButton); - sendMouseMove(view.viewport(), view.viewport()->rect().center(), - Qt::LeftButton, Qt::LeftButton); - QCOMPARE(scene.selectedItems(), QList() << 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()); - sendMouseMove(view.viewport(), view.viewport()->rect().center(), - Qt::LeftButton, Qt::LeftButton); - QCOMPARE(scene.selectedItems(), QList()); - sendMouseMove(view.viewport(), view.viewport()->rect().bottomRight(), - Qt::LeftButton, Qt::LeftButton); - QCOMPARE(scene.selectedItems(), QList() << 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 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 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("updateRect"); - QTest::addColumn("numPaints"); - QTest::addColumn("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 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 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("viewRect"); - QTest::addColumn("scenePoly"); - QTest::addColumn("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(&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(&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 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(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("savePainter"); - QTest::addColumn("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("transform"); - QTest::addColumn("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(&w3)); - w2.setFlag(QGraphicsItem::ItemIgnoresTransformations, true); - QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(), - static_cast(&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(&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(&widget)); - widget.focusNextPrevChild(true); - QCOMPARE(static_cast(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 > changes; - -public slots: - void changed(const QList &dirty) - { - changes << dirty; - } -}; - -void tst_QGraphicsView::task239729_noViewUpdate_data() -{ - QTest::addColumn("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 &)), &cl, SLOT(changed(const QList &))); - } else { - connect(&scene, SIGNAL(changed(const QList &)), &cl, SLOT(changed(const QList &))); - 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 itemsAtCenter = view.items(view.viewport()->rect().center()); - QCOMPARE(itemsAtCenter, (QList() << child << parent)); - - QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1))); - QList 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("reverse"); - QTest::addColumn("x1"); - QTest::addColumn("x2"); - QTest::addColumn("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("adjustForAntialiasing"); - QTest::addColumn("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)), 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("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(&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(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("penWidth"); - QTest::addColumn("antialiasing"); - QTest::addColumn("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)), 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(scene.addRect(0, 0, 50, 50)); - grandParent->setBrush(Qt::black); - grandParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape); - - QGraphicsRectItem *parent = static_cast(scene.addRect(-50, -50, 100, 100)); - parent->setBrush(QColor(0, 0, 255, 125)); - parent->setParentItem(grandParent); - parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape); - - QGraphicsRectItem *child = static_cast(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(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(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(&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(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(item2)); - - scene.setFocusItem(item); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); - QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true); - QCOMPARE(scene.focusItem(), static_cast(item)); - - view.setScene(0); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); - QCOMPARE(scene.focusItem(), static_cast(item)); - - view.setScene(&scene); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); - QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true); - QCOMPARE(scene.focusItem(), static_cast(item)); - - scene.setFocusItem(item2); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); - QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false); - QCOMPARE(scene.focusItem(), static_cast(item2)); - - view.setScene(0); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); - QCOMPARE(scene.focusItem(), static_cast(item2)); - - scene.setFocusItem(item); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); - QCOMPARE(scene.focusItem(), static_cast(item)); - - view.setScene(&scene); - QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); - QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true); - QCOMPARE(scene.focusItem(), static_cast(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(&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)), &dummyView, SLOT(updateScene(QList))); - view.setScene(&scene1); - - QTest::qWait(12); - - QGraphicsScene scene2; - QObject::connect(&scene2, SIGNAL(changed(QList)), &dummyView, SLOT(updateScene(QList))); - view.setScene(&scene2); - - QTest::qWait(12); - - bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList)), &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("clip"); - QTest::addColumn("ignoreTransformations"); - QTest::addColumn("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(event)->widget(); - } else if (event->type() == QEvent::GraphicsSceneHoverLeave) { - receivedLeaveEvent = true; - leaveWidget = static_cast(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/qgraphicsview/tst_qgraphicsview_2.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview_2.cpp deleted file mode 100644 index 122ffbc875..0000000000 --- a/tests/auto/qgraphicsview/tst_qgraphicsview_2.cpp +++ /dev/null @@ -1,976 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#ifdef Q_OS_WINCE -#include - -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) -Q_DECLARE_METATYPE(QList) -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("viewportSize"); - QTest::addColumn("sceneRect"); - QTest::addColumn("transform"); - QTest::addColumn("hbarpolicy"); - QTest::addColumn("vbarpolicy"); - QTest::addColumn("hmin"); - QTest::addColumn("hmax"); - QTest::addColumn("vmin"); - QTest::addColumn("vmax"); - QTest::addColumn("useMotif"); - QTest::addColumn("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/qgraphicswidget/.gitignore b/tests/auto/qgraphicswidget/.gitignore deleted file mode 100644 index ae39b803e5..0000000000 --- a/tests/auto/qgraphicswidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgraphicswidget diff --git a/tests/auto/qgraphicswidget/qgraphicswidget.pro b/tests/auto/qgraphicswidget/qgraphicswidget.pro deleted file mode 100644 index 330076eafc..0000000000 --- a/tests/auto/qgraphicswidget/qgraphicswidget.pro +++ /dev/null @@ -1,10 +0,0 @@ -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/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp deleted file mode 100644 index e3eb05ca1a..0000000000 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ /dev/null @@ -1,3361 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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("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("scene"); - QTest::addColumn("children"); - QTest::addColumn("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("childCount"); - QTest::addColumn("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 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(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("focusPolicy1"); - QTest::addColumn("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("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("pos"); - QTest::addColumn("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("left"); - QTest::addColumn("top"); - QTest::addColumn("right"); - QTest::addColumn("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, >op, &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, >op, &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("enabled"); - QTest::addColumn("focus"); - QTest::addColumn("underMouse"); - QTest::addColumn("layoutDirection"); - QTest::addColumn("size"); - QTest::addColumn("palette"); - QTest::addColumn("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("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 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(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("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 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("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(&standAlongWidget)); - QCOMPARE(itemChild.parentWidget(), (QGraphicsWidget*)0); - - for (int i = 0; i < childrenCount; ++i) { - SubQGraphicsWidget *item = new SubQGraphicsWidget(&standAlongWidget); - QCOMPARE(item->parentWidget(), static_cast(&standAlongWidget)); - } -} - -void tst_QGraphicsWidget::resize_data() -{ - QTest::addColumn("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("attribute"); - QTest::addColumn("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("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(&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("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 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 &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() << w1 << w2 << w3)); - - QGraphicsWidget *p = new QGraphicsWidget; - p->setData(0, QLatin1String("parent")); - p->setFocusPolicy(Qt::StrongFocus); - - w1->setFocus(); - QVERIFY(compareFocusChain(&view, QList() << w1 << w2 << w3)); - - w1->setParentItem(p); - w2->setFocus(); - QVERIFY(compareFocusChain(&view, QList() << w2 << w3)); - - w2->setParentItem(p); - w3->setFocus(); - QVERIFY(compareFocusChain(&view, QList() << w3)); - w3->setParentItem(p); - QCOMPARE(scene.focusItem(), static_cast(0)); - - scene.addItem(p); - p->setFocus(); - - QVERIFY(compareFocusChain(&view, QList() << 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() << 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() << w2 << w3)); - - scene.addItem(p); - w2->setFocus(); - QVERIFY(compareFocusChain(&view, QList() << w2 << w3 << p << w1 << w4)); -} - -void tst_QGraphicsWidget::topLevelWidget_data() -{ - QTest::addColumn("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("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 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("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() << 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() << 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(&view)); - QTRY_COMPARE(scene.focusItem(), static_cast(w)); -} - -void tst_QGraphicsWidget::sizeHint_data() -{ - QTest::addColumn("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("minSize"); - QTest::addColumn("maxSize"); - QTest::addColumn("geometry"); - QTest::addColumn("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 Inst; - -Q_DECLARE_METATYPE(Inst) -Q_DECLARE_METATYPE(QVector) - -void tst_QGraphicsWidget::setSizes_data() -{ - - QTest::addColumn >("inputInstructions"); - QTest::addColumn >("compareInstructions"); - - QTest::newRow("minSize1") << (QVector() << Inst(Size, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10))) - << (QVector() << Inst(Size, QSize(25,25))); - QTest::newRow("minSize2") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumSize, QSizeF(25, 25))) - << (QVector() << Inst(Size, QSizeF(25, 25))); - QTest::newRow("minWidth1") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0)) - << (QVector() << Inst(Size, QSizeF(20, 20))); - QTest::newRow("minWidth2") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0)) - << (QVector() << Inst(Size, QSizeF(25, 20))); - QTest::newRow("minHeight1") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0)) - << (QVector() << Inst(Size, QSizeF(20, 20))); - QTest::newRow("minHeight2") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0)) - << (QVector() << Inst(Size, QSizeF(20, 25))); - QTest::newRow("maxSize1") << (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, 30))) - << (QVector() << Inst(Size, QSizeF(30, 30))); - QTest::newRow("maxSize2") << (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, -1))) - << (QVector() << Inst(Size, QSizeF(30, 40))); - QTest::newRow("maxSize3") << (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, 30))) - << (QVector() << Inst(Size, QSizeF(40, 30))); - QTest::newRow("maxWidth1")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumWidth, 30)) - << (QVector() << Inst(Size, QSizeF(30, 40))); - QTest::newRow("maxHeight")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumHeight, 20)) - << (QVector() << Inst(Size, QSizeF(40, 20))); - QTest::newRow("unsetMinSize")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MinimumSize, QSizeF(-1, -1))) - << (QVector() << Inst(MinimumSize, QSizeF(5, 5))); - QTest::newRow("unsetMaxSize")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, -1))) - << (QVector() << Inst(MaximumSize, QSizeF(500, 500))); - QTest::newRow("unsetMinSize, expand size to minimumSizeHint") << (QVector() - << Inst(MinimumSize, QSize(0, 0)) - << Inst(Size, QSize(1,1)) - << Inst(MinimumSize, QSize(-1.0, -1.0)) - ) - << (QVector() - << Inst(Size, QSize(5,5)) - << Inst(MinimumSize, QSize(5,5)) - ); - -} - -void tst_QGraphicsWidget::setSizes() -{ - QFETCH(QVector, inputInstructions); - QFETCH(QVector, 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("inputFlags"); - QTest::addColumn("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 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 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 changes; - QList values; - QList 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::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 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 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 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(item->valueDuringEvents.value(QEvent::ParentAboutToChange)), - static_cast(0)); - // ParentChange should be triggered after the parent has changed - QTRY_COMPARE(qVariantValue(item->valueDuringEvents.value(QEvent::ParentChange)), - static_cast(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/qgridlayout/.gitignore b/tests/auto/qgridlayout/.gitignore deleted file mode 100644 index bce8f2f91e..0000000000 --- a/tests/auto/qgridlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgridlayout diff --git a/tests/auto/qgridlayout/qgridlayout.pro b/tests/auto/qgridlayout/qgridlayout.pro deleted file mode 100644 index 6bd42fe432..0000000000 --- a/tests/auto/qgridlayout/qgridlayout.pro +++ /dev/null @@ -1,10 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qgridlayout.cpp -FORMS += sortdialog.ui - - - diff --git a/tests/auto/qgridlayout/sortdialog.ui b/tests/auto/qgridlayout/sortdialog.ui deleted file mode 100644 index 04af84d01b..0000000000 --- a/tests/auto/qgridlayout/sortdialog.ui +++ /dev/null @@ -1,135 +0,0 @@ - - - - - SortDialog - - - - 0 - 0 - 304 - 370 - - - - Sort - - - - 8 - - - 6 - - - - - 0 - - - 6 - - - - - OK - - - true - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - &More - - - true - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - 8 - - - 6 - - - - - - 0 - 100 - - - - - None - - - - - - - - - - - - primaryColumnCombo - okButton - moreButton - - - - - okButton - clicked() - SortDialog - accept() - - - 257 - 25 - - - 283 - 268 - - - - - diff --git a/tests/auto/qgridlayout/tst_qgridlayout.cpp b/tests/auto/qgridlayout/tst_qgridlayout.cpp deleted file mode 100644 index 3b352644f3..0000000000 --- a/tests/auto/qgridlayout/tst_qgridlayout.cpp +++ /dev/null @@ -1,1646 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -//#include - -#include -#include -#include -#include -#include - -#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" <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 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("columns"); - QTest::addColumn("rows"); - QTest::addColumn("sizehint"); - // expected - QTest::addColumn("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 > 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 SizeInfoList; -Q_DECLARE_METATYPE(SizeInfoList) - - -void tst_QGridLayout::minMaxSize_data() -{ - // input - QTest::addColumn("stylename"); - QTest::addColumn("columns"); - QTest::addColumn("rows"); - QTest::addColumn("sizePolicy"); - QTest::addColumn("fixedSize"); - //input and expected output - QTest::addColumn("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(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 > 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("columns"); - QTest::addColumn("rows"); - QTest::addColumn("sizehint"); - // expected - QTest::addColumn("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 > 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("widget"); - // expected - QTest::addColumn("expectedpositions"); - QTest::addColumn("hSpacing"); - QTest::addColumn("vSpacing"); - QTest::addColumn("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/qgroupbox/.gitignore b/tests/auto/qgroupbox/.gitignore deleted file mode 100644 index 16dc39494e..0000000000 --- a/tests/auto/qgroupbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qgroupbox diff --git a/tests/auto/qgroupbox/qgroupbox.pro b/tests/auto/qgroupbox/qgroupbox.pro deleted file mode 100644 index f4181a33ed..0000000000 --- a/tests/auto/qgroupbox/qgroupbox.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qgroupbox.cpp - - - diff --git a/tests/auto/qgroupbox/tst_qgroupbox.cpp b/tests/auto/qgroupbox/tst_qgroupbox.cpp deleted file mode 100644 index 8568ef01d1..0000000000 --- a/tests/auto/qgroupbox/tst_qgroupbox.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -#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("title"); - QTest::addColumn("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("checkable"); - QTest::addColumn("expectedCheckable"); - QTest::newRow( "checkable_true" ) << true << true; - QTest::newRow( "checkable_false" ) << false << false; -} - -void tst_QGroupBox::setChecked_data() -{ - QTest::addColumn("checkable"); - QTest::addColumn("checked"); - QTest::addColumn("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("checkable"); - QTest::addColumn("initialCheck"); - QTest::addColumn("areaToHit"); - QTest::addColumn("clickedCount"); - QTest::addColumn("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(object)) { - QVERIFY(!widget->isEnabled()); - QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); - } - } - - box.setChecked(true); - foreach (QObject *object, box.children()) { - if (QWidget *widget = qobject_cast(object)) { - QVERIFY(widget->isEnabled()); - QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); - } - } - - box.setChecked(false); - foreach (QObject *object, box.children()) { - if (QWidget *widget = qobject_cast(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(&lineEdit)); -} - -QTEST_MAIN(tst_QGroupBox) -#include "tst_qgroupbox.moc" diff --git a/tests/auto/qheaderview/.gitignore b/tests/auto/qheaderview/.gitignore deleted file mode 100644 index dafdb3d2fb..0000000000 --- a/tests/auto/qheaderview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qheaderview diff --git a/tests/auto/qheaderview/qheaderview.pro b/tests/auto/qheaderview/qheaderview.pro deleted file mode 100644 index 3b3afa7e49..0000000000 --- a/tests/auto/qheaderview/qheaderview.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qheaderview.cpp - - diff --git a/tests/auto/qheaderview/tst_qheaderview.cpp b/tests/auto/qheaderview/tst_qheaderview.cpp deleted file mode 100644 index dd087b0e95..0000000000 --- a/tests/auto/qheaderview/tst_qheaderview.cpp +++ /dev/null @@ -1,2135 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -typedef QList IntList; -Q_DECLARE_METATYPE(IntList) - -typedef QList 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("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 >("boundsCheck"); - QTest::addColumn >("defaultSizes"); - QTest::addColumn("initialDefaultSize"); - QTest::addColumn("lastVisibleSectionSize"); - QTest::addColumn("persistentSectionSize"); - - QTest::newRow("data set one") - << (QList() << -1 << 0 << 4 << 9999) - << (QList() << 10 << 30 << 30) - << 30 - << 300 - << 20; -} - -void tst_QHeaderView::sectionSize() -{ - QFETCH(QList, boundsCheck); - QFETCH(QList, 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 >("hidden"); - QTest::addColumn >("from"); - QTest::addColumn >("to"); - QTest::addColumn >("coordinate"); - QTest::addColumn >("visual"); - - QList 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() - << QList() - << QList() - << coordinateList - << (QList() << -1 << 0 << 1 << 3 << -1); - - QTest::newRow("no hidden, moved sections") - << QList() - << (QList() << 0) - << (QList() << 1) - << coordinateList - << (QList() << -1 << 0 << 1 << 3 << -1); - - QTest::newRow("hidden, no moved sections") - << (QList() << 0) - << QList() - << QList() - << coordinateList - << (QList() << -1 << 1 << 2 << 3 << -1); -} - -void tst_QHeaderView::visualIndexAt() -{ - QFETCH(QList, hidden); - QFETCH(QList, from); - QFETCH(QList, to); - QFETCH(QList, coordinate); - QFETCH(QList, 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 logical = (QVector() << 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() << 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 >("hidden"); - QTest::addColumn >("from"); - QTest::addColumn >("to"); - QTest::addColumn >("moved"); - QTest::addColumn >("logical"); - QTest::addColumn("count"); - - QTest::newRow("bad args, no hidden") - << QList() - << (QList() << -1 << 1 << 99999 << 1) - << (QList() << 1 << -1 << 1 << 99999) - << (QList() << false << false << false << false) - << (QList() << 0 << 1 << 2 << 3) - << 0; - - QTest::newRow("good args, no hidden") - << QList() - << (QList() << 1 << 1 << 2 << 1) - << (QList() << 1 << 2 << 1 << 2) - << (QList() << false << true << true << true) - << (QList() << 0 << 2 << 1 << 3) - << 3; - - QTest::newRow("hidden sections") - << (QList() << 0 << 3) - << (QList() << 1 << 1 << 2 << 1) - << (QList() << 1 << 2 << 1 << 2) - << (QList() << false << true << true << true) - << (QList() << 0 << 2 << 1 << 3) - << 3; -} - -void tst_QHeaderView::moveSection() -{ - QFETCH(QList, hidden); - QFETCH(QList, from); - QFETCH(QList, to); - QFETCH(QList, moved); - QFETCH(QList, 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("logicalIndexes"); - QTest::addColumn("sizes"); - QTest::addColumn("logicalFrom"); - QTest::addColumn("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("section"); - QTest::addColumn("initialSize"); - QTest::addColumn("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("section"); - QTest::addColumn("size"); - QTest::addColumn("insert"); - QTest::addColumn("compare"); - QTest::addColumn("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("size"); - QTest::addColumn >("sections"); - QTest::addColumn >("modes"); - QTest::addColumn >("expected"); - - QTest::newRow("stretch first section") - << 600 - << (QList() << 100 << 100 << 100 << 100) - << (QList() << ((int)QHeaderView::Stretch) - << ((int)QHeaderView::Interactive) - << ((int)QHeaderView::Interactive) - << ((int)QHeaderView::Interactive)) - << (QList() << 300 << 100 << 100 << 100); -} - -void tst_QHeaderView::resizeWithResizeModes() -{ - QFETCH(int, size); - QFETCH(QList, sections); - QFETCH(QList, modes); - QFETCH(QList, 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("from"); - QTest::addColumn("to"); - QTest::addColumn("insert"); - QTest::addColumn >("mapping"); - - QTest::newRow("move from 1 to 3, insert 0") - << 1 << 3 << 0 <<(QList() << 0 << 1 << 3 << 4 << 2); - -} - -void tst_QHeaderView::moveAndInsertSection() -{ - QFETCH(int, from); - QFETCH(int, to); - QFETCH(int, insert); - QFETCH(QList, 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("initial"); - QTest::addColumn >("logical"); - QTest::addColumn >("size"); - QTest::addColumn >("mode"); - QTest::addColumn("resized"); - QTest::addColumn >("expected"); - - QTest::newRow("bad args") - << 100 - << (QList() << -1 << -1 << 99999 << 99999 << 4) - << (QList() << -1 << 0 << 99999 << -1 << -1) - << (QList() - << int(QHeaderView::Interactive) - << int(QHeaderView::Interactive) - << int(QHeaderView::Interactive) - << int(QHeaderView::Interactive)) - << 0 - << (QList() << 0 << 0 << 0 << 0 << 0); -} - -void tst_QHeaderView::resizeSection() -{ - - QFETCH(int, initial); - QFETCH(QList, logical); - QFETCH(QList, size); - QFETCH(QList, mode); - QFETCH(int, resized); - QFETCH(QList, 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("direction"); - QTest::addColumn("initial"); - QTest::addColumn("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("direction"); - QTest::addColumn("mode"); - QTest::addColumn("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("direction"); - QTest::addColumn("clickable"); - QTest::addColumn("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("direction"); - QTest::addColumn("oldDefaultSize"); - QTest::addColumn("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("direction"); - QTest::addColumn("hide"); - QTest::addColumn("insert"); - QTest::addColumn("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 >("hide1"); - QTest::addColumn >("hide2"); - - QTest::newRow("set 1") << (QList() << 1 << 3) - << (QList() << 1 << 5); - - QTest::newRow("set 2") << (QList() << 2 << 3) - << (QList() << 1 << 5); - - QTest::newRow("set 3") << (QList() << 0 << 2 << 4) - << (QList() << 2 << 3 << 5); - -} - -void tst_QHeaderView::task236450_hidden() -{ - QFETCH(QList, hide1); - QFETCH(QList, 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 &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() << 2 << 4 << 0 << 3 << 1 << 5) , 0); - - proxy.setSourceModel(&model2); - QApplication::processEvents(); - QCOMPARE(checkHeaderViewOrder(&view, QVector() << 2 << 0 << 1 ) , 0); - - proxy.setSourceModel(&model1); - QApplication::processEvents(); - QCOMPARE(checkHeaderViewOrder(&view, QVector() << 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 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 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/qidentityproxymodel/qidentityproxymodel.pro b/tests/auto/qidentityproxymodel/qidentityproxymodel.pro deleted file mode 100644 index 7df0e65d03..0000000000 --- a/tests/auto/qidentityproxymodel/qidentityproxymodel.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) - -INCLUDEPATH += $$PWD/../modeltest - -QT += widgets -SOURCES += tst_qidentityproxymodel.cpp ../modeltest/dynamictreemodel.cpp ../modeltest/modeltest.cpp -HEADERS += ../modeltest/dynamictreemodel.h ../modeltest/modeltest.h diff --git a/tests/auto/qidentityproxymodel/tst_qidentityproxymodel.cpp b/tests/auto/qidentityproxymodel/tst_qidentityproxymodel.cpp deleted file mode 100644 index 6d73cbe2e1..0000000000 --- a/tests/auto/qidentityproxymodel/tst_qidentityproxymodel.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly -** 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 -#include -#include -#include - -#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"); - - 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() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value())); - QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1)); - QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2)); - - QVERIFY(modelAfterSpy.first().first().value() == m_proxy->mapToSource(proxyAfterSpy.first().first().value())); - 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() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value())); - QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1)); - QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2)); - - QVERIFY(modelAfterSpy.first().first().value() == m_proxy->mapToSource(proxyAfterSpy.first().first().value())); - 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() << 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() << 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() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value())); - QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1)); - QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2)); - QVERIFY(modelBeforeSpy.first().at(3).value() == m_proxy->mapToSource(proxyBeforeSpy.first().at(3).value())); - QVERIFY(modelBeforeSpy.first().at(4) == proxyBeforeSpy.first().at(4)); - - QVERIFY(modelAfterSpy.first().first().value() == m_proxy->mapToSource(proxyAfterSpy.first().first().value())); - QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1)); - QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2)); - QVERIFY(modelAfterSpy.first().at(3).value() == m_proxy->mapToSource(proxyAfterSpy.first().at(3).value())); - 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() << 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() << 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/qinputcontext/qinputcontext.pro b/tests/auto/qinputcontext/qinputcontext.pro deleted file mode 100644 index cdadb0c5ed..0000000000 --- a/tests/auto/qinputcontext/qinputcontext.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qinputcontext.cpp - -mac*:CONFIG+=insignificant_test - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp deleted file mode 100644 index 9b6452851e..0000000000 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef QT_WEBKIT_LIB -#include -#include -#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(&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 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 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 = "" - "
"; - 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 = "" - "
"; - 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/qinputdialog/.gitignore b/tests/auto/qinputdialog/.gitignore deleted file mode 100644 index b62797193c..0000000000 --- a/tests/auto/qinputdialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qinputdialog diff --git a/tests/auto/qinputdialog/qinputdialog.pro b/tests/auto/qinputdialog/qinputdialog.pro deleted file mode 100644 index f7e56bd783..0000000000 --- a/tests/auto/qinputdialog/qinputdialog.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qinputdialog.cpp - - diff --git a/tests/auto/qinputdialog/tst_qinputdialog.cpp b/tests/auto/qinputdialog/tst_qinputdialog.cpp deleted file mode 100644 index 5c74ab217b..0000000000 --- a/tests/auto/qinputdialog/tst_qinputdialog.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -//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 -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(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 -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 -void testGetNumeric(QInputDialog *dialog, SpinBoxType * = 0, ValueType * = 0) -{ - SpinBoxType *sbox = qFindChild(dialog); - QVERIFY(sbox != 0); - - QLineEdit *ledit = qFindChild(static_cast(sbox)); - QVERIFY(ledit != 0); - - QDialogButtonBox *bbox = qFindChild(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(sbox, okButton, ledit); - testTypingValue(sbox, okButton, QString("%1").arg(sbox->minimum())); - testTypingValue(sbox, okButton, QString("%1").arg(sbox->maximum())); - testTypingValue(sbox, okButton, QString("%1").arg(sbox->minimum() - 1)); - testTypingValue(sbox, okButton, QString("%1").arg(sbox->maximum() + 1)); - testTypingValue(sbox, okButton, "0"); - testTypingValue(sbox, okButton, "0.0"); - testTypingValue(sbox, okButton, "foobar"); - - testTypingValue(sbox, okButton, loc.toString(origValue)); -} - -void testGetText(QInputDialog *dialog) -{ - QLineEdit *ledit = qFindChild(dialog); - QVERIFY(ledit); - - QDialogButtonBox *bbox = qFindChild(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(dialog); - QVERIFY(cbox); - - QDialogButtonBox *bbox = qFindChild(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(dialog); -} - -void tst_QInputDialog::testFuncGetDouble(QInputDialog *dialog) -{ - testGetNumeric(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(parent); - QVERIFY(dialog); - if (testFunc) - testFunc(dialog); - dialog->done(doneCode); // cause static function call to return -} - -void tst_QInputDialog::getInteger_data() -{ - QTest::addColumn("min"); - QTest::addColumn("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("min"); - QTest::addColumn("max"); - QTest::addColumn("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(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("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("items"); - QTest::addColumn("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 children = dialog.children(); - QLineEdit *editWidget = 0; - for (int c = 0; c < children.size(); c++) { - editWidget = qobject_cast(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/qintvalidator/.gitignore b/tests/auto/qintvalidator/.gitignore deleted file mode 100644 index c6d5c989f0..0000000000 --- a/tests/auto/qintvalidator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qintvalidator diff --git a/tests/auto/qintvalidator/qintvalidator.pro b/tests/auto/qintvalidator/qintvalidator.pro deleted file mode 100644 index 576621a08b..0000000000 --- a/tests/auto/qintvalidator/qintvalidator.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qintvalidator.cpp - - diff --git a/tests/auto/qintvalidator/tst_qintvalidator.cpp b/tests/auto/qintvalidator/tst_qintvalidator.cpp deleted file mode 100644 index 369e3254e8..0000000000 --- a/tests/auto/qintvalidator/tst_qintvalidator.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -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("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("value"); - QTest::addColumn("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/qitemdelegate/.gitignore b/tests/auto/qitemdelegate/.gitignore deleted file mode 100644 index 5faa678712..0000000000 --- a/tests/auto/qitemdelegate/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qitemdelegate diff --git a/tests/auto/qitemdelegate/qitemdelegate.pro b/tests/auto/qitemdelegate/qitemdelegate.pro deleted file mode 100644 index 9a1a3b5e94..0000000000 --- a/tests/auto/qitemdelegate/qitemdelegate.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qitemdelegate.cpp - -win32:!wince*: LIBS += -lUser32 - diff --git a/tests/auto/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/qitemdelegate/tst_qitemdelegate.cpp deleted file mode 100644 index e419a7f097..0000000000 --- a/tests/auto/qitemdelegate/tst_qitemdelegate.cpp +++ /dev/null @@ -1,1216 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint) - -//TESTED_CLASS= -//TESTED_FILES= - -#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) -#include -#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("text"); - QTest::addColumn("rect"); - QTest::addColumn("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("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("initial"); - QTest::addColumn("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 lineEditors = qFindChildren(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 editors = qFindChildren(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("itemText"); - QTest::addColumn("properties"); - QTest::addColumn("itemFont"); - QTest::addColumn("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("position"); - QTest::addColumn("direction"); - QTest::addColumn("hint"); - QTest::addColumn("itemRect"); - QTest::addColumn("checkRect"); - QTest::addColumn("pixmapRect"); - QTest::addColumn("textRect"); - QTest::addColumn("expectedCheckRect"); - QTest::addColumn("expectedPixmapRect"); - QTest::addColumn("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("role"); - QTest::addColumn("size"); - QTest::addColumn("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"); - - 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("time"); - QTest::addColumn("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(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(widget.viewport()); - QVERIFY(dateEditor); - QCOMPARE(dateEditor->date(), date); - - widget.clearFocus(); - widget.setFocus(); - widget.editItem(item3); - - QTestEventLoop::instance().enterLoop(1); - - QList dateTimeEditors = widget.findChildren(); - 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("type"); - QTest::addColumn("size"); - QTest::addColumn("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(&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("rect"); - QTest::addColumn("text"); - QTest::addColumn("checkState"); - QTest::addColumn("flags"); - QTest::addColumn("inCheck"); - QTest::addColumn("type"); - QTest::addColumn("button"); - QTest::addColumn("edited"); - QTest::addColumn("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("widget"); - QTest::addColumn("key"); - QTest::addColumn("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 lineEditors = qFindChildren(view.viewport(), QString::fromLatin1("TheEditor")); - QCOMPARE(lineEditors.count(), 1); - - QPointer 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 lineEditors = qFindChildren(view.viewport()); - QCOMPARE(lineEditors.count(), 1); - - QPointer 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/qitemeditorfactory/.gitignore b/tests/auto/qitemeditorfactory/.gitignore deleted file mode 100644 index 33a458e65d..0000000000 --- a/tests/auto/qitemeditorfactory/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qitemeditorfactory diff --git a/tests/auto/qitemeditorfactory/qitemeditorfactory.pro b/tests/auto/qitemeditorfactory/qitemeditorfactory.pro deleted file mode 100644 index 89bc944c51..0000000000 --- a/tests/auto/qitemeditorfactory/qitemeditorfactory.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qitemeditorfactory.cpp - - diff --git a/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp b/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp deleted file mode 100644 index 53c00dab0e..0000000000 --- a/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -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 -{ -}; - -void tst_QItemEditorFactory::createCustomEditor() -{ - QPointer creator = new MyEditor; - QPointer 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/qitemselectionmodel/.gitignore b/tests/auto/qitemselectionmodel/.gitignore deleted file mode 100644 index aa543a200a..0000000000 --- a/tests/auto/qitemselectionmodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qitemselectionmodel diff --git a/tests/auto/qitemselectionmodel/qitemselectionmodel.pro b/tests/auto/qitemselectionmodel/qitemselectionmodel.pro deleted file mode 100644 index c675a6eb9d..0000000000 --- a/tests/auto/qitemselectionmodel/qitemselectionmodel.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qitemselectionmodel.cpp - - diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp deleted file mode 100644 index f7ce339854..0000000000 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ /dev/null @@ -1,2714 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include - -//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 IntList; -typedef QPair IntPair; -typedef QList 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(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(ptr)); - return s; -} - -QDataStream &operator<<(QDataStream &s, const QModelIndexList &input) -{ - s << input.count(); - for (int i=0; i>(QDataStream &s, QModelIndexList &output) -{ - QModelIndex tmpIndex; - int count; - s >> count; - for (int i=0; i> 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"); - - 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("indexList"); - QTest::addColumn("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; iselect(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("indexList"); - QTest::addColumn("useRanges"); - QTest::addColumn("commandList"); - QTest::addColumn("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; iselect(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; iisSelected(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; iisRowSelected(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; iisColumnSelected(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("indexList"); - QTest::addColumn("commandList"); - QTest::addColumn("insertRows"); // start, count - QTest::addColumn("insertColumns"); // start, count - QTest::addColumn("deleteRows"); // start, count - QTest::addColumn("deleteColumns"); // start, count - QTest::addColumn("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; iindex(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()); - QVERIFY(qvariant_cast(spy.at(1).at(1)).isEmpty()); -} - -void tst_QItemSelectionModel::removeRows_data() -{ - QTest::addColumn("rowCount"); - QTest::addColumn("columnCount"); - - QTest::addColumn("selectTop"); - QTest::addColumn("selectLeft"); - QTest::addColumn("selectBottom"); - QTest::addColumn("selectRight"); - - QTest::addColumn("removeTop"); - QTest::addColumn("removeBottom"); - - QTest::addColumn("expectedTop"); - QTest::addColumn("expectedLeft"); - QTest::addColumn("expectedBottom"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - - QTest::addColumn("selectTop"); - QTest::addColumn("selectLeft"); - QTest::addColumn("selectBottom"); - QTest::addColumn("selectRight"); - - QTest::addColumn("removeLeft"); - QTest::addColumn("removeRight"); - - QTest::addColumn("expectedTop"); - QTest::addColumn("expectedLeft"); - QTest::addColumn("expectedBottom"); - QTest::addColumn("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 IntListList; -typedef QPair IntPairPair; -typedef QList IntPairPairList; -Q_DECLARE_METATYPE(IntListList) -Q_DECLARE_METATYPE(IntPairPair) -Q_DECLARE_METATYPE(IntPairPairList) - -void tst_QItemSelectionModel::modelLayoutChanged_data() -{ - QTest::addColumn("items"); - QTest::addColumn("initialSelectedRanges"); - QTest::addColumn("sortOrder"); - QTest::addColumn("sortColumn"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("column"); - QTest::addColumn("selectRows"); - QTest::addColumn("expectedRows"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("selectColumns"); - QTest::addColumn("expectedColumns"); - QTest::addColumn("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("init"); - QTest::addColumn("other"); - QTest::addColumn("command"); - QTest::addColumn("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 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 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() << &sub11 << &sub12 << &sub13 << &sub14); - top2.appendColumn(QList() << &sub21 << &sub22 << &sub23 << &sub24); - model.appendColumn(QList() << &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 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 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("parent1"); - QTest::addColumn("top1"); - QTest::addColumn("left1"); - QTest::addColumn("bottom1"); - QTest::addColumn("right1"); - QTest::addColumn("parent2"); - QTest::addColumn("top2"); - QTest::addColumn("left2"); - QTest::addColumn("bottom2"); - QTest::addColumn("right2"); - QTest::addColumn("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() << &top11 << &top12 << &top13); - model2.appendColumn(QList() << &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/qitemview/.gitignore b/tests/auto/qitemview/.gitignore deleted file mode 100644 index c129cad63c..0000000000 --- a/tests/auto/qitemview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qitemview diff --git a/tests/auto/qitemview/qitemview.pro b/tests/auto/qitemview/qitemview.pro deleted file mode 100644 index dbdd4612d5..0000000000 --- a/tests/auto/qitemview/qitemview.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qitemview.cpp - - diff --git a/tests/auto/qitemview/tst_qitemview.cpp b/tests/auto/qitemview/tst_qitemview.cpp deleted file mode 100644 index 4c64d4c52a..0000000000 --- a/tests/auto/qitemview/tst_qitemview.cpp +++ /dev/null @@ -1,928 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include "viewstotest.cpp" -#include - -#if defined(Q_OS_UNIX) -#include -#endif -#if defined(Q_OS_WIN) -#include -#if defined(Q_OS_WINCE) -#include -#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 (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("viewType"); - QTest::addColumn("displays"); - QTest::addColumn("vscroll"); - QTest::addColumn("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 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/qitemview/viewstotest.cpp b/tests/auto/qitemview/viewstotest.cpp deleted file mode 100644 index b61ecd5c2a..0000000000 --- a/tests/auto/qitemview/viewstotest.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -/* - 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 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(view)) { - tableView->setColumnHidden(1, true); - tableView->setRowHidden(1, true); - tableView->setRowHidden(tableView->model()->rowCount()-2, true); - } - if (QTreeView *treeView = qobject_cast(view)) { - treeView->setColumnHidden(1, true); - treeView->setRowHidden(1, QModelIndex(), true); - treeView->setRowHidden(treeView->model()->rowCount()-2, QModelIndex(), true); - } - if (QListView *listView = qobject_cast(view)) { - listView->setRowHidden(1, true); - listView->setRowHidden(listView->model()->rowCount()-2, true); - } -} - diff --git a/tests/auto/qlabel/.gitignore b/tests/auto/qlabel/.gitignore deleted file mode 100644 index e050d7ab5e..0000000000 --- a/tests/auto/qlabel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qlabel diff --git a/tests/auto/qlabel/green.png b/tests/auto/qlabel/green.png deleted file mode 100644 index dfc95d4f37..0000000000 Binary files a/tests/auto/qlabel/green.png and /dev/null differ diff --git a/tests/auto/qlabel/qlabel.pro b/tests/auto/qlabel/qlabel.pro deleted file mode 100644 index 0e0c3a43c4..0000000000 --- a/tests/auto/qlabel/qlabel.pro +++ /dev/null @@ -1,15 +0,0 @@ -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/qlabel/red.png b/tests/auto/qlabel/red.png deleted file mode 100644 index 4a843e744f..0000000000 Binary files a/tests/auto/qlabel/red.png and /dev/null differ diff --git a/tests/auto/qlabel/testdata/acc_01/res_Windows_data0.qsnap b/tests/auto/qlabel/testdata/acc_01/res_Windows_data0.qsnap deleted file mode 100644 index 522c173ac4..0000000000 Binary files a/tests/auto/qlabel/testdata/acc_01/res_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap deleted file mode 100644 index acd881d29a..0000000000 Binary files a/tests/auto/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap deleted file mode 100644 index 9e2c1764d3..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap deleted file mode 100644 index dcd708fdbf..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap deleted file mode 100644 index 2131f59fe9..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap deleted file mode 100644 index 2edd976830..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap deleted file mode 100644 index 2ce28d9816..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap deleted file mode 100644 index 6476f6c26b..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap deleted file mode 100644 index 6039742962..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap deleted file mode 100644 index 477d203960..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap deleted file mode 100644 index c673f4099e..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap deleted file mode 100644 index a490f77118..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap deleted file mode 100644 index 33342d3616..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap deleted file mode 100644 index 3fe9a82c2f..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap deleted file mode 100644 index 175235dc38..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap deleted file mode 100644 index b1ac74b531..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap deleted file mode 100644 index fdd3c7c701..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap deleted file mode 100644 index caa47f7292..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap deleted file mode 100644 index a0d2498e76..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap deleted file mode 100644 index 756d9fe827..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap deleted file mode 100644 index f973d14c38..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap deleted file mode 100644 index 720d807db2..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap deleted file mode 100644 index 20fd48e7cc..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap deleted file mode 100644 index 7db7c97a14..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap deleted file mode 100644 index d9912d8c92..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap deleted file mode 100644 index bfc3a6488e..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap deleted file mode 100644 index 09a35ef761..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap deleted file mode 100644 index 14e11232f0..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap deleted file mode 100644 index 6ef864e635..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap deleted file mode 100644 index eb029008e3..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap deleted file mode 100644 index 439e196b57..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap deleted file mode 100644 index 9637d1741a..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap deleted file mode 100644 index 9a553465c3..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap deleted file mode 100644 index 0d9184c316..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap b/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap deleted file mode 100644 index f2873b1c78..0000000000 Binary files a/tests/auto/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap deleted file mode 100644 index 1385a50d38..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap deleted file mode 100644 index 38223cfba2..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap deleted file mode 100644 index 0b946a4968..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap deleted file mode 100644 index e1d2c41d88..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap deleted file mode 100644 index b7bdee551b..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap deleted file mode 100644 index a20492ee70..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap deleted file mode 100644 index 85e3306d0c..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap deleted file mode 100644 index 3bf991f674..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap b/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap deleted file mode 100644 index f05a9dcebd..0000000000 Binary files a/tests/auto/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap deleted file mode 100644 index d7428df5ef..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap deleted file mode 100644 index 905acd1283..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap deleted file mode 100644 index e1dea4b76b..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap deleted file mode 100644 index 055ccda47e..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap deleted file mode 100644 index 64b70763d4..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap deleted file mode 100644 index fb0ea227ad..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap deleted file mode 100644 index ae9cda541f..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap deleted file mode 100644 index e21af3223a..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap deleted file mode 100644 index 32cc40652b..0000000000 Binary files a/tests/auto/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Motif_data0.qsnap b/tests/auto/qlabel/testdata/setText/res_Motif_data0.qsnap deleted file mode 100644 index 7191b517d2..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Motif_data1.qsnap b/tests/auto/qlabel/testdata/setText/res_Motif_data1.qsnap deleted file mode 100644 index d943ce960a..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Motif_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Motif_data2.qsnap b/tests/auto/qlabel/testdata/setText/res_Motif_data2.qsnap deleted file mode 100644 index 946432e66d..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Motif_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Motif_data3.qsnap b/tests/auto/qlabel/testdata/setText/res_Motif_data3.qsnap deleted file mode 100644 index dc5ac0c56d..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Motif_data3.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_data0.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_data0.qsnap deleted file mode 100644 index 2ab392e50e..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_data1.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_data1.qsnap deleted file mode 100644 index 5769459ab6..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_data2.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_data2.qsnap deleted file mode 100644 index b4206c2a57..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_data3.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_data3.qsnap deleted file mode 100644 index f120ac2e76..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_data3.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data0.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_win32_data0.qsnap deleted file mode 100644 index 7644f53726..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data1.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_win32_data1.qsnap deleted file mode 100644 index 7902b1b087..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data1.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data2.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_win32_data2.qsnap deleted file mode 100644 index 60bd075c78..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data2.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data3.qsnap b/tests/auto/qlabel/testdata/setText/res_Windows_win32_data3.qsnap deleted file mode 100644 index c1dcb272b3..0000000000 Binary files a/tests/auto/qlabel/testdata/setText/res_Windows_win32_data3.qsnap and /dev/null differ diff --git a/tests/auto/qlabel/tst_qlabel.cpp b/tests/auto/qlabel/tst_qlabel.cpp deleted file mode 100644 index 9cab8b328d..0000000000 --- a/tests/auto/qlabel/tst_qlabel.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include "qlabel.h" -#include -#include -#include -#include -#include -#include -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -class Widget : public QWidget -{ -public: - Widget() { } - - QList 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 test_box; - QPointer 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("txt"); - QTest::addColumn("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 bold 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("rich text"); - QVERIFY(!label.wordWrap()); - - label.setWordWrap(false); - label.setText("rich text"); - QVERIFY(!label.wordWrap()); -} - -void tst_QLabel::eventPropagation_data() -{ - QTest::addColumn("text"); - QTest::addColumn("textInteractionFlags"); - QTest::addColumn("focusPolicy"); - QTest::addColumn("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("rich text") << (int)Qt::LinksAccessibleByMouse << (int)Qt::NoFocus << true; - QTest::newRow("rich text2") << QString("rich text") << (int)Qt::TextSelectableByKeyboard << (int)Qt::ClickFocus << true; - QTest::newRow("rich text3") << QString("rich text") << (int)Qt::TextSelectableByMouse << (int)Qt::ClickFocus << false; - QTest::newRow("rich text4") << QString("rich text") << (int)Qt::NoTextInteraction << (int)Qt::NoFocus << true; - QTest::newRow("rich text4") << QString("rich text") << (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("text"); - QTest::addColumn("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("text"); - QTest::addColumn("expectedDocText"); - QTest::addColumn("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 &&") << QString("&With Double &") << 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(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/qlayout/.gitignore b/tests/auto/qlayout/.gitignore deleted file mode 100644 index cc058e7cc3..0000000000 --- a/tests/auto/qlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qlayout diff --git a/tests/auto/qlayout/baseline/smartmaxsize b/tests/auto/qlayout/baseline/smartmaxsize deleted file mode 100644 index 2d3ba2e72f..0000000000 --- a/tests/auto/qlayout/baseline/smartmaxsize +++ /dev/null @@ -1,1792 +0,0 @@ -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/qlayout/qlayout.pro b/tests/auto/qlayout/qlayout.pro deleted file mode 100644 index 28ca9dc86d..0000000000 --- a/tests/auto/qlayout/qlayout.pro +++ /dev/null @@ -1,16 +0,0 @@ -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/qlayout/tst_qlayout.cpp b/tests/auto/qlayout/tst_qlayout.cpp deleted file mode 100644 index ea25700568..0000000000 --- a/tests/auto/qlayout/tst_qlayout.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_WS_MAC -# include -#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(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 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(watched)->geometry(); - } - return false; - } - QRect geom; -}; - -void tst_QLayout::layoutItemRect() -{ -#ifdef Q_WS_MAC - if (qobject_cast(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(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/qlcdnumber/.gitignore b/tests/auto/qlcdnumber/.gitignore deleted file mode 100644 index cbf08a078d..0000000000 --- a/tests/auto/qlcdnumber/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qlcdnumber diff --git a/tests/auto/qlcdnumber/qlcdnumber.pro b/tests/auto/qlcdnumber/qlcdnumber.pro deleted file mode 100644 index cd909de5be..0000000000 --- a/tests/auto/qlcdnumber/qlcdnumber.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qlcdnumber.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qlcdnumber.cpp - - diff --git a/tests/auto/qlcdnumber/tst_qlcdnumber.cpp b/tests/auto/qlcdnumber/tst_qlcdnumber.cpp deleted file mode 100644 index 0976f3f619..0000000000 --- a/tests/auto/qlcdnumber/tst_qlcdnumber.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - - -//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/qlineedit/.gitignore b/tests/auto/qlineedit/.gitignore deleted file mode 100644 index 7fcade47c9..0000000000 --- a/tests/auto/qlineedit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qlineedit diff --git a/tests/auto/qlineedit/qlineedit.pro b/tests/auto/qlineedit/qlineedit.pro deleted file mode 100644 index 077b7c919e..0000000000 --- a/tests/auto/qlineedit/qlineedit.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qlineedit.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png b/tests/auto/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png deleted file mode 100644 index 81a3e3de4d..0000000000 Binary files a/tests/auto/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png b/tests/auto/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png deleted file mode 100644 index 81a3e3de4d..0000000000 Binary files a/tests/auto/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png b/tests/auto/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png deleted file mode 100644 index ed3810c2e7..0000000000 Binary files a/tests/auto/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png b/tests/auto/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png deleted file mode 100644 index fe4456ffbf..0000000000 Binary files a/tests/auto/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png deleted file mode 100644 index 7ab7ffd4da..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png deleted file mode 100644 index 5918bb93f1..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png deleted file mode 100644 index 66119386a3..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png deleted file mode 100644 index 89e81db837..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png deleted file mode 100644 index 2cf5c7a9cf..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png deleted file mode 100644 index 70ec6530b8..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png deleted file mode 100644 index d6708bcd12..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png b/tests/auto/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png deleted file mode 100644 index 9000dfc4cf..0000000000 Binary files a/tests/auto/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png and /dev/null differ diff --git a/tests/auto/qlineedit/tst_qlineedit.cpp b/tests/auto/qlineedit/tst_qlineedit.cpp deleted file mode 100644 index 6e4726e5b5..0000000000 --- a/tests/auto/qlineedit/tst_qlineedit.cpp +++ /dev/null @@ -1,3835 +0,0 @@ -/**************************************************************************** -** -** 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 -#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 // For the random function. -#include // For the random function. -#endif - -#include -#include -#include -#include -#include - -//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 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("mask"); - QTest::addColumn("input"); - QTest::addColumn("expectedText"); - QTest::addColumn("expectedDisplay"); - QTest::addColumn("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;#") - << 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("AAAAaaaaAA>AAA>Aaa>aaa>aHH>Hhh>hsetInputMask(mask); - - // then either insert using insert() or keyboard - if (insert_text) { - testWidget->insert(input); - } else { - psKeyClick(testWidget, Qt::Key_Home); - for (int i=0; itext(), expectedText); - QCOMPARE(testWidget->displayText(), expectedDisplay); -} - -void tst_QLineEdit::inputMask_data() -{ - QTest::addColumn("mask"); - QTest::addColumn("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(">abcdefabcdefsetInputMask(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("mask"); - QTest::addColumn("keys"); - QTest::addColumn("expectedText"); - QTest::addColumn("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("optionalMask"); - QTest::addColumn("requiredMask"); - QTest::addColumn("invalid"); - QTest::addColumn("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("mask"); - QTest::addColumn("input"); - QTest::addColumn("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("insertString"); - QTest::addColumn("insertIndex"); - QTest::addColumn("insertMode"); - QTest::addColumn("expectedString"); - QTest::addColumn("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 -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; itext(), 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 -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; itext(), expectedString[i]); - QVERIFY(testWidget->isUndoAvailable()); - QTest::keyClick(testWidget, Qt::Key_Backspace, Qt::AltModifier); - } -#endif -} - -void tst_QLineEdit::redo_data() -{ - QTest::addColumn("insertString"); - QTest::addColumn("insertIndex"); - QTest::addColumn("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 -1) - testWidget->setCursorPosition(insertIndex[i]); - testWidget->insert(insertString[i]); - } - - QVERIFY(!testWidget->isRedoAvailable()); - - // undo everything - while (!testWidget->text().isEmpty()) - testWidget->undo(); - - for (i=0; iisRedoAvailable()); - 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("keys"); - QTest::addColumn("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; itext() , 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("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("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("insertString"); - QTest::addColumn("expectedString"); - QTest::addColumn("mode"); - QTest::addColumn("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("mask"); - QTest::addColumn("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("insertString"); - QTest::addColumn("expectedString"); - QTest::addColumn("length"); - QTest::addColumn("insertBeforeSettingMaxLength"); - QTest::addColumn("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("input"); - QTest::addColumn("lastPos"); - QTest::addColumn("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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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("inputMask"); - QTest::addColumn("hasValidator"); - QTest::addColumn("input"); - QTest::addColumn("expectedText"); - QTest::addColumn("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'") - << 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'") - << 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'") - << 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'") - << 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'") - << 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'") - << 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 ''") - << 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'", "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(&iv1)); - - testWidget->setValidator(0); - QVERIFY(testWidget->validator() == 0); - - QIntValidator iv2(0, 99, 0); - testWidget->setValidator(&iv2); - QCOMPARE(testWidget->validator(), static_cast(&iv2)); - - testWidget->setValidator(0); - QVERIFY(testWidget->validator() == 0); -} - -void tst_QLineEdit::setValidator_QIntValidator_data() -{ - QTest::addColumn("mini"); - QTest::addColumn("maxi"); - QTest::addColumn("input"); - QTest::addColumn("expectedText"); - QTest::addColumn("useKeys"); - QTest::addColumn("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("noFrame"); - QTest::addColumn("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("left"); - QTest::addColumn("right"); - QTest::addColumn("hcenter"); - QTest::addColumn("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("text"); - QTest::addColumn("start"); - QTest::addColumn("length"); - QTest::addColumn("expectedCursor"); - QTest::addColumn("expectedText"); - QTest::addColumn("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("inputMask"); - QTest::addColumn("keys"); - QTest::addColumn("validateText"); - QTest::addColumn("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("left"); - QTest::addColumn("top"); - QTest::addColumn("right"); - QTest::addColumn("bottom"); - - QTest::addColumn("mousePressPos"); - QTest::addColumn("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("maxLength"); - QTest::addColumn("cursorPos"); - QTest::addColumn("replacementStart"); - QTest::addColumn("replacementLength"); - QTest::addColumn("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(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("logical"); - QTest::addColumn("basicDir"); - QTest::addColumn("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() << 0 << 1 << 2 << 3); - QTest::newRow("Hebrew text after Latin text") - << QString::fromUtf8("abc\327\220\327\221\327\222") - << (int) QChar::DirL - << (QList() << 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() << 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() << 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() << 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() << 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() << 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 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/qlistview/.gitignore b/tests/auto/qlistview/.gitignore deleted file mode 100644 index a0e31d03d4..0000000000 --- a/tests/auto/qlistview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qlistview diff --git a/tests/auto/qlistview/qlistview.pro b/tests/auto/qlistview/qlistview.pro deleted file mode 100644 index 07fabbce35..0000000000 --- a/tests/auto/qlistview/qlistview.pro +++ /dev/null @@ -1,6 +0,0 @@ -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/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp deleted file mode 100644 index b58a306f94..0000000000 --- a/tests/auto/qlistview/tst_qlistview.cpp +++ /dev/null @@ -1,2073 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) -# include -# include -# include -#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 (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 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"); - - 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 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 IntList; -Q_DECLARE_METATYPE(IntList) - -void tst_QListView::selection_data() -{ - QTest::addColumn("itemCount"); - QTest::addColumn("viewMode"); - QTest::addColumn("flow"); - QTest::addColumn("wrapping"); - QTest::addColumn("spacing"); - QTest::addColumn("gridSize"); - QTest::addColumn("hiddenRows"); - QTest::addColumn("selectionRect"); - QTest::addColumn("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("size"); - QTest::addColumn("itemCount"); - QTest::addColumn("flow"); - QTest::addColumn("horizontalScrollBarVisible"); - QTest::addColumn("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() << &sub1); - model.appendColumn(QList() << &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(&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("flow"); - - QTest::newRow("TopToBottom") << static_cast(QListView::TopToBottom); - QTest::newRow("LeftToRight") << static_cast(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(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 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(&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() - << 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/qlistwidget/.gitignore b/tests/auto/qlistwidget/.gitignore deleted file mode 100644 index 085486b2de..0000000000 --- a/tests/auto/qlistwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qlistwidget diff --git a/tests/auto/qlistwidget/qlistwidget.pro b/tests/auto/qlistwidget/qlistwidget.pro deleted file mode 100644 index 7343415e4c..0000000000 --- a/tests/auto/qlistwidget/qlistwidget.pro +++ /dev/null @@ -1,6 +0,0 @@ -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/qlistwidget/tst_qlistwidget.cpp b/tests/auto/qlistwidget/tst_qlistwidget.cpp deleted file mode 100644 index 9ede38f553..0000000000 --- a/tests/auto/qlistwidget/tst_qlistwidget.cpp +++ /dev/null @@ -1,1685 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -#include -#include - -//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 rcParent; - QVector rcFirst; - QVector rcLast; - - void populate(); - void checkDefaultValues(); -}; - - -typedef QList 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("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("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("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 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("initialItems"); - QTest::addColumn("insertIndex"); - QTest::addColumn("itemLabel"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("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; iinsertItems(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; iinsertItems(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; icount(); ++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("row"); - QTest::addColumn("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(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("row"); - QTest::addColumn("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(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("itemCount"); - QTest::addColumn("hiddenRows"); - QTest::addColumn("selectedRows"); - QTest::addColumn("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; isetSelectionMode(QListWidget::SingleSelection); - for (int i=0; iitem(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 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; iitem(i); - if (testWidget->isItemSelected(item)) - QVERIFY(selectedItems.contains(item)); - } -} - -void tst_QListWidget::removeItems_data() -{ - QTest::addColumn("rowCount"); - QTest::addColumn("removeRows"); - QTest::addColumn("row"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("srcRow"); - QTest::addColumn("dstRow"); - QTest::addColumn("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(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 &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 &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("text"); - QTest::addColumn("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("order"); - QTest::addColumn("initialList"); - QTest::addColumn("expectedList"); - QTest::addColumn("expectedRows"); - - QTest::newRow("ascending strings") - << static_cast(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(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(Qt::AscendingOrder) - << (QVariantList() << 1 << 11 << 2 << 22) - << (QVariantList() << 1 << 2 << 11 << 22) - << (IntList() << 0 << 2 << 1 << 3); - - QTest::newRow("descending numbers") - << static_cast(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 persistent; - for (int j = 0; j < model->rowCount(QModelIndex()); ++j) - persistent << model->index(j, 0, QModelIndex()); - - testWidget->sortItems(static_cast(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("order"); - QTest::addColumn("initialList"); - QTest::addColumn("expectedList"); - QTest::addColumn("expectedRows"); - QTest::addColumn("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(Qt::DescendingOrder) - << initial - << expected - << rowOrder - << visible; - - QTest::newRow("ascending order") - << static_cast(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(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 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(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("initialItems"); - QTest::addColumn("itemIndex"); - QTest::addColumn("roles"); - QTest::addColumn("values"); - QTest::addColumn("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*"); - qRegisterMetaType("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("sortOrder"); - QTest::addColumn("initialItems"); - QTest::addColumn("insertItems"); - QTest::addColumn("expectedItems"); - QTest::addColumn("expectedRows"); - - QTest::newRow("() + (a) = (a)") - << static_cast(Qt::AscendingOrder) - << QStringList() - << (QStringList() << "a") - << (QStringList() << "a") - << IntList(); - QTest::newRow("() + (c, b, a) = (a, b, c)") - << static_cast(Qt::AscendingOrder) - << QStringList() - << (QStringList() << "c" << "b" << "a") - << (QStringList() << "a" << "b" << "c") - << IntList(); - QTest::newRow("() + (a, b, c) = (c, b, a)") - << static_cast(Qt::DescendingOrder) - << QStringList() - << (QStringList() << "a" << "b" << "c") - << (QStringList() << "c" << "b" << "a") - << IntList(); - QTest::newRow("(a) + (b) = (a, b)") - << static_cast(Qt::AscendingOrder) - << QStringList("a") - << (QStringList() << "b") - << (QStringList() << "a" << "b") - << (IntList() << 0); - QTest::newRow("(a) + (b) = (b, a)") - << static_cast(Qt::DescendingOrder) - << QStringList("a") - << (QStringList() << "b") - << (QStringList() << "b" << "a") - << (IntList() << 1); - QTest::newRow("(a, c, b) + (d) = (a, b, c, d)") - << static_cast(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(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(Qt::AscendingOrder) - << QStringList() - << ascendingItems - << ascendingItems - << IntList(); - QTest::newRow("(sorted items) + () = (sorted items)") - << static_cast(Qt::AscendingOrder) - << ascendingItems - << QStringList() - << ascendingItems - << ascendingRows; - QTest::newRow("() + (ascending items) = (reverse items)") - << static_cast(Qt::DescendingOrder) - << QStringList() - << ascendingItems - << reverseItems - << IntList(); - QTest::newRow("(reverse items) + () = (ascending items)") - << static_cast(Qt::AscendingOrder) - << reverseItems - << QStringList() - << ascendingItems - << ascendingRows; - QTest::newRow("(reverse items) + () = (reverse items)") - << static_cast(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(sortOrder)); - w.addItems(initialItems); - - QAbstractItemModel *model = w.model(); - QList 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("sortOrder"); - QTest::addColumn("initialItems"); - QTest::addColumn("itemIndex"); - QTest::addColumn("newValue"); - QTest::addColumn("expectedItems"); - QTest::addColumn("expectedRows"); - QTest::addColumn("reorderingExpected"); - - QTest::newRow("change a to b in (a)") - << static_cast(Qt::AscendingOrder) - << (QStringList() << "a") - << 0 << "b" - << (QStringList() << "b") - << (IntList() << 0) - << false; - QTest::newRow("change a to b in (a, c)") - << static_cast(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(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(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(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(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(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 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(sortOrder)); - w.addItems(initialItems); - - QAbstractItemModel *model = w.model(); - QList 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(0)); - list.setItemWidget(item, &widget); - QCOMPARE(list.itemWidget(item), &widget); - list.removeItemWidget(item); - QCOMPARE(list.itemWidget(item), static_cast(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*"); - 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(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/qmacstyle/.gitignore b/tests/auto/qmacstyle/.gitignore deleted file mode 100644 index 9abe0ad6ab..0000000000 --- a/tests/auto/qmacstyle/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmacstyle diff --git a/tests/auto/qmacstyle/qmacstyle.pro b/tests/auto/qmacstyle/qmacstyle.pro deleted file mode 100644 index 5aad7368c6..0000000000 --- a/tests/auto/qmacstyle/qmacstyle.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qmacstyle.cpp - - -mac*:CONFIG+=insignificant_test diff --git a/tests/auto/qmacstyle/tst_qmacstyle.cpp b/tests/auto/qmacstyle/tst_qmacstyle.cpp deleted file mode 100644 index a262712abc..0000000000 --- a/tests/auto/qmacstyle/tst_qmacstyle.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -#include - -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"); } - -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"); - 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("size1"); - QTest::addColumn("size2"); - QTest::addColumn("size3"); - QTest::addColumn("expectedHeight1"); - QTest::addColumn("expectedHeight2"); - QTest::addColumn("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) <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/qmainwindow/.gitignore b/tests/auto/qmainwindow/.gitignore deleted file mode 100644 index 7550c7063f..0000000000 --- a/tests/auto/qmainwindow/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmainwindow diff --git a/tests/auto/qmainwindow/qmainwindow.pro b/tests/auto/qmainwindow/qmainwindow.pro deleted file mode 100644 index c140f76c89..0000000000 --- a/tests/auto/qmainwindow/qmainwindow.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private -SOURCES += tst_qmainwindow.cpp diff --git a/tests/auto/qmainwindow/tst_qmainwindow.cpp b/tests/auto/qmainwindow/tst_qmainwindow.cpp deleted file mode 100644 index d6a8ae793d..0000000000 --- a/tests/auto/qmainwindow/tst_qmainwindow.cpp +++ /dev/null @@ -1,1742 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 var1 = new QMenuBar; - obj1.setMenuBar(var1); - QCOMPARE(static_cast(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 var2 = new QStatusBar; - obj1.setStatusBar(var2); - QCOMPARE(static_cast(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"); - qRegisterMetaType("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(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(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(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(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(mwSpy.first().first().constData()), - Qt::ToolButtonTextOnly); - QCOMPARE(*static_cast(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(mwSpy.first().first().constData()), - Qt::ToolButtonTextBesideIcon); - QCOMPARE(*static_cast(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(mwSpy.first().first().constData()), - Qt::ToolButtonTextUnderIcon); - QCOMPARE(*static_cast(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(mwSpy.first().first().constData()), - Qt::ToolButtonIconOnly); - QCOMPARE(*static_cast(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(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(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(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 mb1 = new QMenuBar; - QPointer 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 topLeftCornerWidget = new QWidget; - mb1->setCornerWidget(topLeftCornerWidget, Qt::TopLeftCorner); - QPointer 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(topLeftCornerWidget)); - QVERIFY(topRightCornerWidget); - QCOMPARE(mb2->cornerWidget(Qt::TopRightCorner), static_cast(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 sb1 = new QStatusBar; - QPointer 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(&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 w1 = new QWidget; - QPointer 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 w1 = new QWidget; - QPointer 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 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 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 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 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(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 MoveList; -Q_DECLARE_METATYPE(MoveList) - -void MoveSeparator::apply(QMainWindow *mw) const -{ - QMainWindowLayout *l = qFindChild(mw); - QVERIFY(l); - - QList path; - if (name.isEmpty()) { - path << area; - } else { - QDockWidget *dw = qFindChild(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 dockWidgetGeometries(QMainWindow *mw) -{ - QMap result; - QList dockWidgets = qFindChildren(mw); - foreach (QDockWidget *dw, dockWidgets) - result.insert(dw->objectName(), dw->geometry()); - return result; -} - -#define COMPARE_DOCK_WIDGET_GEOS(_oldGeos, _newGeos) \ -{ \ - QMap __oldGeos = _oldGeos; \ - QMap __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"); - QTest::addColumn("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 dockWidgetGeos; - QSize size; - - { - QMainWindow mainWindow; - mainWindow.setDockNestingEnabled(true); - QTextEdit centralWidget("The rain in Spain falls mainly on the plains"); - mainWindow.setCentralWidget(¢ralWidget); - - 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", ¢ralWidget); - 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(¢ralWidget); - - 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(¢ralWidget); - - 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/qmdiarea/.gitignore b/tests/auto/qmdiarea/.gitignore deleted file mode 100644 index 2632dbea40..0000000000 --- a/tests/auto/qmdiarea/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmdiarea diff --git a/tests/auto/qmdiarea/qmdiarea.pro b/tests/auto/qmdiarea/qmdiarea.pro deleted file mode 100644 index 6a12152fcc..0000000000 --- a/tests/auto/qmdiarea/qmdiarea.pro +++ /dev/null @@ -1,14 +0,0 @@ -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/qmdiarea/tst_qmdiarea.cpp b/tests/auto/qmdiarea/tst_qmdiarea.cpp deleted file mode 100644 index bbc3d27e27..0000000000 --- a/tests/auto/qmdiarea/tst_qmdiarea.cpp +++ /dev/null @@ -1,2773 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_OPENGL -#include -#endif -#include - -#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) -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 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(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 &expectedIndices) -{ - if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty()) - return false; - - const QList 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(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 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(); -} - -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("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 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 -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 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(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(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("windowOrder"); - QTest::addColumn("windowCount"); - QTest::addColumn("activeSubWindow"); - QTest::addColumn("staysOnTop1"); - QTest::addColumn("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 activationOrder; - QVector windows; - for (int i = 0; i < windowCount; ++i) { - windows.append(qobject_cast(workspace.addSubWindow(new QWidget))); - windows[i]->show(); - activationOrder.append(windows[i]); - } - - { - QList 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 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 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 windowsBeforeViewportChange = workspace.subWindowList(); - QCOMPARE(windowsBeforeViewportChange.count(), windowCount); - - workspace.setViewport(new QWidget); - qApp->processEvents(); - QVERIFY(workspace.viewport() != firstViewport); - - QList 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 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 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("startSize"); - QTest::addColumn("increment"); - QTest::addColumn("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 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(lineEdit2)); - - QMdiArea mdiArea; - mdiArea.addSubWindow(view); - QCOMPARE(view->focusWidget(), static_cast(lineEdit2)); - - mdiArea.show(); - view->show(); - qApp->setActiveWindow(&mdiArea); - QCOMPARE(qApp->focusWidget(), static_cast(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 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("activationOrder"); - QTest::addColumn("subWindowCount"); - QTest::addColumn("staysOnTopIndex"); - QTest::addColumn("firstActiveIndex"); - QTest::addColumn >("expectedActivationIndices"); - // The order of expectedCascadeIndices: - // window 1 -> (index 0) - // window 2 -> (index 1) - // window 3 -> (index 2) - // .... - QTest::addColumn >("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 >("expectedTileIndices"); - - QList list; - QList list2; - QList 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(); - list << 3 << 1 << 4 << 3 << 1 << 2 << 0; - list2 = QList(); - list2 << 0 << 2 << 4 << 1 << 3; - list3 = QList(); - list3 << 1 << 3 << 4 << 1 << 2 << 0; - QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3; - - list = QList(); - list << 0 << 1 << 0 << 1 << 4 << 3 << 2; - list2 = QList(); - list2 << 0 << 2 << 3 << 4 << 1; - list3 = QList(); - 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, expectedActivationIndices); - QFETCH(QList, expectedCascadeIndices); - QFETCH(QList, expectedTileIndices); - - // Default order. - QMdiArea mdiArea; - QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder); - - // New order. - mdiArea.setActivationOrder(activationOrder); - QCOMPARE(mdiArea.activationOrder(), activationOrder); - - QList 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 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 subWindows = mdiArea.subWindowList(); - - // Default. - QVERIFY(!activeSubWindow->isMaximized()); - QTabBar *tabBar = qFindChild(&mdiArea); - QVERIFY(!tabBar); - QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView); - - // Tabbed view. - mdiArea.setViewMode(QMdiArea::TabbedView); - QCOMPARE(mdiArea.viewMode(), QMdiArea::TabbedView); - tabBar = qFindChild(&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(&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(&mdiArea); - QVERIFY(!tabBar); - mdiArea.setTabsClosable(true); - QCOMPARE(mdiArea.tabsClosable(), true); - - // force tab bar creation - mdiArea.setViewMode(QMdiArea::TabbedView); - tabBar = qFindChild(&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(&mdiArea); - QVERIFY(!tabBar); - mdiArea.setTabsMovable(true); - QCOMPARE(mdiArea.tabsMovable(), true); - - // force tab bar creation - mdiArea.setViewMode(QMdiArea::TabbedView); - tabBar = qFindChild(&mdiArea); - QVERIFY(tabBar); - - // value must've been propagated - QCOMPARE(tabBar->isMovable(), true); - - // test tab moving - QList 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(&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("tabPosition"); - QTest::addColumn("hasLeftMargin"); - QTest::addColumn("hasTopMargin"); - QTest::addColumn("hasRightMargin"); - QTest::addColumn("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(&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/qmdisubwindow/.gitignore b/tests/auto/qmdisubwindow/.gitignore deleted file mode 100644 index f83a9b0895..0000000000 --- a/tests/auto/qmdisubwindow/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmdisubwindow diff --git a/tests/auto/qmdisubwindow/qmdisubwindow.pro b/tests/auto/qmdisubwindow/qmdisubwindow.pro deleted file mode 100644 index 5c5bd525df..0000000000 --- a/tests/auto/qmdisubwindow/qmdisubwindow.pro +++ /dev/null @@ -1,8 +0,0 @@ -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/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp deleted file mode 100644 index f7593336e1..0000000000 --- a/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp +++ /dev/null @@ -1,2032 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include "qmdisubwindow.h" -#include "qmdiarea.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) -#include -#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"); -} - -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 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(&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(widget)); - QCOMPARE(widget->parentWidget(), static_cast(&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(&window)); - - delete window.widget(); - QVERIFY(!widget); - QVERIFY(!window.widget()); -} - -void tst_QMdiSubWindow::setWindowState_data() -{ - QTest::addColumn("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(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 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(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(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("signal"); - QTest::addColumn("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(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(spy.at(i).at(0)); - Qt::WindowStates newState = qvariant_cast(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(window->style())) - mouseReceiver = qFindChild(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("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("opaqueMode"); - QTest::addColumn("geometryCount"); - QTest::addColumn("expectedGeometryCount"); - QTest::addColumn("workspaceSize"); - QTest::addColumn("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(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(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("windowType"); - QTest::addColumn("expectedWindowType"); - QTest::addColumn("customFlags"); - QTest::addColumn("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(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(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); - QPointersystemMenu = 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(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(systemMenu)); - QCOMPARE(subWindow->systemMenu()->parentWidget(), static_cast(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(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(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(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(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(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(expectedFocusWindow)); - - complexWindow->showMinimized(); - qApp->processEvents(); - QVERIFY(complexWindow->isMinimized()); - QCOMPARE(qApp->focusWidget(), static_cast(complexWindow)); - - complexWindow->showNormal(); - qApp->processEvents(); - QVERIFY(!complexWindow->isMinimized()); - QCOMPARE(qApp->focusWidget(), static_cast(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(firstLineEdit)); - - // Next - QTest::keyPress(widget, Qt::Key_Tab); - QCOMPARE(qApp->focusWidget(), static_cast(secondLineEdit)); - - // Next - QTest::keyPress(widget, Qt::Key_Tab); - QCOMPARE(qApp->focusWidget(), static_cast(thirdLineEdit)); - - // Previous - QTest::keyPress(widget, Qt::Key_Backtab); - QCOMPARE(qApp->focusWidget(), static_cast(secondLineEdit)); - - // Previous - QTest::keyPress(widget, Qt::Key_Backtab); - QCOMPARE(qApp->focusWidget(), static_cast(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("windowState"); - QTest::addColumn("expectedWindowResizeEvents"); - QTest::addColumn("expectedWidgetResizeEvents"); - QTest::addColumn("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(windowWithDecoration)); - - // ...but not on windows without decoration (Qt::FramelessWindowHint). - QMdiSubWindow *windowWithoutDecoration = mdiArea.addSubWindow(new QWidget, Qt::FramelessWindowHint); - windowWithoutDecoration->show(); - QVERIFY(!qFindChild(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(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 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 systemMenu = subWindow->systemMenu(); - QVERIFY(systemMenu); - QVERIFY(systemMenu->isVisible()); - - sendMouseDoubleClick(systemMenu, QPoint(10, 10)); - if (qApp->activePopupWidget() == static_cast(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/qmenu/.gitignore b/tests/auto/qmenu/.gitignore deleted file mode 100644 index 775539a653..0000000000 --- a/tests/auto/qmenu/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmenu diff --git a/tests/auto/qmenu/qmenu.pro b/tests/auto/qmenu/qmenu.pro deleted file mode 100644 index 1fc1a7ff9d..0000000000 --- a/tests/auto/qmenu/qmenu.pro +++ /dev/null @@ -1,5 +0,0 @@ -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/qmenu/tst_qmenu.cpp b/tests/auto/qmenu/tst_qmenu.cpp deleted file mode 100644 index d115da865b..0000000000 --- a/tests/auto/qmenu/tst_qmenu.cpp +++ /dev/null @@ -1,943 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -//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(sender()); -} - -void tst_QMenu::onActivated(QAction *action) -{ - activated = action; - lastMenu = qobject_cast(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("key"); - QTest::addColumn("expected_action"); - QTest::addColumn("expected_menu"); - QTest::addColumn("init"); - QTest::addColumn("expected_activated"); - QTest::addColumn("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(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(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 torn = 0; - foreach (QWidget *w, QApplication::allWidgets()) { - if (w->inherits("QTornOffMenu")) { - torn = static_cast(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(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 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/qmenubar/.gitignore b/tests/auto/qmenubar/.gitignore deleted file mode 100644 index b72cc79d94..0000000000 --- a/tests/auto/qmenubar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmenubar diff --git a/tests/auto/qmenubar/qmenubar.pro b/tests/auto/qmenubar/qmenubar.pro deleted file mode 100644 index 73c2545710..0000000000 --- a/tests/auto/qmenubar/qmenubar.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qmenubar.cpp diff --git a/tests/auto/qmenubar/tst_qmenubar.cpp b/tests/auto/qmenubar/tst_qmenubar.cpp deleted file mode 100644 index dc3b81920d..0000000000 --- a/tests/auto/qmenubar/tst_qmenubar.cpp +++ /dev/null @@ -1,1291 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_WS_WIN -#include -#endif - -#include - -QT_FORWARD_DECLARE_CLASS(QMainWindow) - -#include - -//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 - -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(0), Qt::Key_A, AltKey ); - QTest::keyClick(static_cast(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(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; kaddAction( 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("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 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 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 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 menuBarActions2 = mb->actions(); - QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") ); - QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") ); - } - break; - } - QList menuBarActions2 = mb->actions(); - QVERIFY( menuBarActions2.size() == 2 ); -} - -void tst_QMenuBar::removeItemAt_data() -{ - QTest::addColumn("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 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 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 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(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(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(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(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(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(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(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(0), Qt::Key_Down ); - // and an Enter key - QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); - - // Simulate some cursor keys - QTest::keyClick(static_cast(0), Qt::Key_Left ); - QTest::keyClick(static_cast(0), Qt::Key_Down ); - QTest::keyClick(static_cast(0), Qt::Key_Right ); - QTest::keyClick(static_cast(0), Qt::Key_Down ); - // and an Enter key - QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); - - // Simulate some keys - QTest::keyClick(static_cast(0), Qt::Key_Left ); - QTest::keyClick(static_cast(0), Qt::Key_Down ); - // and press ENTER - QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); - - // Simulate some keys - QTest::keyClick(static_cast(0), Qt::Key_Down ); - QTest::keyClick(static_cast(0), Qt::Key_Down ); - QTest::keyClick(static_cast(0), Qt::Key_Down ); - QTest::keyClick(static_cast(0), Qt::Key_Home ); - // and press ENTER - QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); - - // Simulate some keys - QTest::keyClick(static_cast(0), Qt::Key_End ); - // and press ENTER - QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); - QVERIFY( !pm1->isActiveWindow() ); - QVERIFY( pm2->isActiveWindow() ); - - // If we press ESC, the popup should disappear - QTest::keyClick(static_cast(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(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("popup_item"); -// QTest::addColumn("itemA_count"); -// QTest::addColumn("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("label"); -// QTest::addColumn("itemA_count"); -// QTest::addColumn("itemB_count"); -// QTest::addColumn("itemC_count"); -// QTest::addColumn("itemD_count"); -// QTest::addColumn("itemE_count"); -// QTest::addColumn("itemF_count"); -// QTest::addColumn("itemG_count"); -// QTest::addColumn("itemH_count"); -// QTest::addColumn("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(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 *"); - //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(0), Qt::Key_Escape); - QVERIFY(!menu.isVisible()); - QTRY_VERIFY(menubar.hasFocus()); - QCOMPARE(menubar.activeAction(), first); - QTest::keyClick(static_cast(0), Qt::Key_Escape); - QVERIFY(!menubar.activeAction()); - QTest::keyClick(static_cast(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(0), Qt::Key_Right); - QCOMPARE(menubar.activeAction(), a); - QTest::keyClick(static_cast(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(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/qmessagebox/.gitignore b/tests/auto/qmessagebox/.gitignore deleted file mode 100644 index 19a0a35121..0000000000 --- a/tests/auto/qmessagebox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmessagebox diff --git a/tests/auto/qmessagebox/qmessagebox.pro b/tests/auto/qmessagebox/qmessagebox.pro deleted file mode 100644 index e3f6ddb1f6..0000000000 --- a/tests/auto/qmessagebox/qmessagebox.pro +++ /dev/null @@ -1,9 +0,0 @@ -load(qttest_p4) -TEMPLATE = app -TARGET = tst_qmessagebox -QT += widgets -DEPENDPATH += . -INCLUDEPATH += . - -# Input -SOURCES += tst_qmessagebox.cpp diff --git a/tests/auto/qmessagebox/tst_qmessagebox.cpp b/tests/auto/qmessagebox/tst_qmessagebox.cpp deleted file mode 100644 index a07d7cf7a9..0000000000 --- a/tests/auto/qmessagebox/tst_qmessagebox.cpp +++ /dev/null @@ -1,674 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) -#include -#endif -#if !defined(QT_NO_STYLE_CLEANLOOKS) -#include -#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(qApp->style())) - expectedButton = int(QMessageBox::No); -#elif !defined(QT_NO_STYLE_CLEANLOOKS) - if (qobject_cast(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("qt_msgbox_buttonbox"); - QVERIFY(bb); //get the detail button - - QList 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/qmultiscreen/.gitignore b/tests/auto/qmultiscreen/.gitignore deleted file mode 100644 index 82e8d449ad..0000000000 --- a/tests/auto/qmultiscreen/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qmultiscreen diff --git a/tests/auto/qmultiscreen/qmultiscreen.pro b/tests/auto/qmultiscreen/qmultiscreen.pro deleted file mode 100644 index c4a983c5be..0000000000 --- a/tests/auto/qmultiscreen/qmultiscreen.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qmultiscreen.cpp - -requires(embedded) - diff --git a/tests/auto/qmultiscreen/tst_qmultiscreen.cpp b/tests/auto/qmultiscreen/tst_qmultiscreen.cpp deleted file mode 100644 index 9d74d59f85..0000000000 --- a/tests/auto/qmultiscreen/tst_qmultiscreen.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** 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 - -//TESTED_CLASS= -//TESTED_FILES= - -#include -#include -#include -#include - -class tst_QMultiScreen : public QObject -{ - Q_OBJECT - -public: - tst_QMultiScreen() : screen(0), oldScreen(0) {} - ~tst_QMultiScreen() {} - -private slots: - void initTestCase(); - void cleanupTestCase(); - void widgetSetFixedSize(); - void grabWindow(); - -private: - QScreen *screen; - QScreen *oldScreen; -}; - -void tst_QMultiScreen::cleanupTestCase() -{ - screen->shutdownDevice(); - screen->disconnect(); - delete screen; - screen = 0; - - qt_screen = oldScreen; -} - -void tst_QMultiScreen::initTestCase() -{ - oldScreen = qt_screen; - - QVERIFY(QScreenDriverFactory::keys().contains(QLatin1String("Multi"))); - QVERIFY(QScreenDriverFactory::keys().contains(QLatin1String("VNC"))); - - const int id = 10; - screen = QScreenDriverFactory::create("Multi", id); - QVERIFY(screen); - QVERIFY(screen->connect(QString("Multi: " - "VNC:size=640x480:depth=32:offset=0,0:%1 " - "VNC:size=640x480:depth=32:offset=640,0:%2 " - "VNC:size=640x480:depth=16:offset=0,480:%3 " - ":%4") - .arg(id+1).arg(id+2).arg(id+3).arg(id))); - QVERIFY(screen->initDevice()); - - QDesktopWidget desktop; - QCOMPARE(desktop.numScreens(), 3); -} - -void tst_QMultiScreen::widgetSetFixedSize() -{ - QDesktopWidget desktop; - QRect maxRect; - for (int i = 0; i < desktop.numScreens(); ++i) - maxRect |= desktop.availableGeometry(i); - - maxRect = maxRect.adjusted(50, 50, -50, -50); - - // make sure we can set a size larger than a single screen (task 166368) - QWidget w; - w.setFixedSize(maxRect.size()); - w.show(); - QApplication::processEvents(); - QCOMPARE(w.geometry().size(), maxRect.size()); -} - -void tst_QMultiScreen::grabWindow() -{ - QDesktopWidget desktop; - - QVERIFY(desktop.numScreens() >= 2); - - const QRect r0 = desktop.availableGeometry(0).adjusted(50, 50, -50, -50); - const QRect r1 = desktop.availableGeometry(1).adjusted(60, 60, -60, -60); - - QWidget w; - w.setGeometry(r0); - w.show(); - - QLabel l("hi there"); - l.setGeometry(r1); - l.show(); - - QApplication::processEvents(); - QApplication::sendPostedEvents(); // workaround for glib event loop - QVERIFY(desktop.screenNumber(&w) == 0); - QVERIFY(desktop.screenNumber(&l) == 1); - - const QPixmap p0 = QPixmap::grabWindow(w.winId()); - const QPixmap p1 = QPixmap::grabWindow(l.winId()); - -// p0.save("w.png", "PNG"); -// p1.save("l.png", "PNG"); - QCOMPARE(p0.size(), w.size()); - QCOMPARE(p1.size(), l.size()); - - const QImage img0 = p0.toImage(); - const QImage img1 = p1.toImage(); - -// QPixmap::grabWidget(&w).toImage().convertToFormat(img0.format()).save("w_img.png", "PNG"); -// QPixmap::grabWidget(&l).toImage().convertToFormat(img1.format()).save("l_img.png", "PNG"); - - QImage::Format format = QImage::Format_RGB16; - QCOMPARE(img0.convertToFormat(format), - QPixmap::grabWidget(&w).toImage().convertToFormat(format)); - QCOMPARE(img1.convertToFormat(format), - QPixmap::grabWidget(&l).toImage().convertToFormat(format)); -} - -QTEST_MAIN(tst_QMultiScreen) - -#include "tst_qmultiscreen.moc" diff --git a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro b/tests/auto/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro deleted file mode 100644 index 9e3fcf28ba..0000000000 --- a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/qnetworkaccessmanager_and_qprogressdialog.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qnetworkaccessmanager_and_qprogressdialog.cpp -QT += network widgets diff --git a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp b/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp deleted file mode 100644 index d22f72261b..0000000000 --- a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include - -#include "../network-settings.h" - - -class tst_QNetworkAccessManager_And_QProgressDialog : public QObject -{ - Q_OBJECT -public: - tst_QNetworkAccessManager_And_QProgressDialog(); -private slots: - void downloadCheck(); - void downloadCheck_data(); -}; - -class DownloadCheckWidget : public QWidget -{ - Q_OBJECT -public: - DownloadCheckWidget(QWidget *parent = 0) : - QWidget(parent), lateReadyRead(true), zeroCopy(false), - progressDlg(this), netmanager(this) - { - progressDlg.setRange(1, 100); - QMetaObject::invokeMethod(this, "go", Qt::QueuedConnection); - } - bool lateReadyRead; - bool zeroCopy; -public slots: - void go() - { - QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile")); - if (zeroCopy) - request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 10*1024*1024); - - QNetworkReply *reply = netmanager.get( - QNetworkRequest( - QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") - )); - connect(reply, SIGNAL(downloadProgress(qint64, qint64)), - this, SLOT(dataReadProgress(qint64, qint64))); - connect(reply, SIGNAL(readyRead()), - this, SLOT(dataReadyRead())); - connect(reply, SIGNAL(finished()), this, SLOT(finishedFromReply())); - - progressDlg.exec(); - } - void dataReadProgress(qint64 done, qint64 total) - { - QNetworkReply *reply = qobject_cast(sender()); - Q_UNUSED(reply); - progressDlg.setMaximum(total); - progressDlg.setValue(done); - } - void dataReadyRead() - { - QNetworkReply *reply = qobject_cast(sender()); - Q_UNUSED(reply); - lateReadyRead = true; - } - void finishedFromReply() - { - QNetworkReply *reply = qobject_cast(sender()); - lateReadyRead = false; - reply->deleteLater(); - QTestEventLoop::instance().exitLoop(); - } - -private: - QProgressDialog progressDlg; - QNetworkAccessManager netmanager; -}; - - -tst_QNetworkAccessManager_And_QProgressDialog::tst_QNetworkAccessManager_And_QProgressDialog() -{ -} - -void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck_data() -{ - QTest::addColumn("useZeroCopy"); - QTest::newRow("with-zeroCopy") << true; - QTest::newRow("without-zeroCopy") << false; -} - -void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck() -{ - QFETCH(bool, useZeroCopy); - - DownloadCheckWidget widget; - widget.zeroCopy = useZeroCopy; - widget.show(); - // run and exit on finished() - QTestEventLoop::instance().enterLoop(10); - QVERIFY(!QTestEventLoop::instance().timeout()); - // run some more to catch the late readyRead() (or: to not catch it) - QTestEventLoop::instance().enterLoop(1); - QVERIFY(QTestEventLoop::instance().timeout()); - // the following fails when a readyRead() was received after finished() - QVERIFY(!widget.lateReadyRead); -} - - - -QTEST_MAIN(tst_QNetworkAccessManager_And_QProgressDialog) -#include "tst_qnetworkaccessmanager_and_qprogressdialog.moc" diff --git a/tests/auto/qplaintextedit/.gitignore b/tests/auto/qplaintextedit/.gitignore deleted file mode 100644 index 5d47310409..0000000000 --- a/tests/auto/qplaintextedit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qplaintextedit diff --git a/tests/auto/qplaintextedit/qplaintextedit.pro b/tests/auto/qplaintextedit/qplaintextedit.pro deleted file mode 100644 index feac5e3f43..0000000000 --- a/tests/auto/qplaintextedit/qplaintextedit.pro +++ /dev/null @@ -1,10 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += gui-private - -INCLUDEPATH += ../ - -HEADERS += -SOURCES += tst_qplaintextedit.cpp - diff --git a/tests/auto/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/qplaintextedit/tst_qplaintextedit.cpp deleted file mode 100644 index d847f295e0..0000000000 --- a/tests/auto/qplaintextedit/tst_qplaintextedit.cpp +++ /dev/null @@ -1,1524 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "qplaintextedit.h" - -//Used in copyAvailable -typedef QPair keyPairType; -typedef QList pairListType; -Q_DECLARE_METATYPE(pairListType); -Q_DECLARE_METATYPE(keyPairType); -Q_DECLARE_METATYPE(QList); - -#ifdef Q_WS_MAC -#include -#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 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("Some Bold Text"); - 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("Second para"); - 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("input"); - QTest::addColumn("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("Blah"); - 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("keystrokes"); - QTest::addColumn >("copyAvailable"); - QTest::addColumn("function"); - - pairListType keystrokes; - QList 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, 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;idocument()->isUndoAvailable()); - QVERIFY(!ed->document()->isRedoAvailable()); - ed->setPlainText("Foobar"); - QVERIFY(!ed->document()->isUndoAvailable()); - QVERIFY(!ed->document()->isRedoAvailable()); - ed->setPlainText("

bleh

"); - 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(&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("testString"); - QTest::addColumn("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("
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() << 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() << sel); - - QList 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("

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/qprogressbar/.gitignore b/tests/auto/qprogressbar/.gitignore deleted file mode 100644 index 3cb22a2560..0000000000 --- a/tests/auto/qprogressbar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qprogressbar diff --git a/tests/auto/qprogressbar/qprogressbar.pro b/tests/auto/qprogressbar/qprogressbar.pro deleted file mode 100644 index 70d8c9111f..0000000000 --- a/tests/auto/qprogressbar/qprogressbar.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qprogressbar.cpp - - - diff --git a/tests/auto/qprogressbar/tst_qprogressbar.cpp b/tests/auto/qprogressbar/tst_qprogressbar.cpp deleted file mode 100644 index 55285b42ff..0000000000 --- a/tests/auto/qprogressbar/tst_qprogressbar.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** -** -** 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 -#include "qprogressbar.h" -#include -#include -#include -#include -#include - -//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 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("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("value"); - QTest::addColumn("format"); - QTest::addColumn("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("style1_str"); - QTest::addColumn("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/qprogressdialog/.gitignore b/tests/auto/qprogressdialog/.gitignore deleted file mode 100644 index ce3cd0d7dd..0000000000 --- a/tests/auto/qprogressdialog/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qprogressdialog diff --git a/tests/auto/qprogressdialog/qprogressdialog.pro b/tests/auto/qprogressdialog/qprogressdialog.pro deleted file mode 100644 index f3861e4cd3..0000000000 --- a/tests/auto/qprogressdialog/qprogressdialog.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qprogressdialog.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qprogressdialog.cpp - - diff --git a/tests/auto/qprogressdialog/tst_qprogressdialog.cpp b/tests/auto/qprogressdialog/tst_qprogressdialog.cpp deleted file mode 100644 index 5fbd5d747a..0000000000 --- a/tests/auto/qprogressdialog/tst_qprogressdialog.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - - -//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(&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/qpushbutton/.gitignore b/tests/auto/qpushbutton/.gitignore deleted file mode 100644 index ac5b16970b..0000000000 --- a/tests/auto/qpushbutton/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qpushbutton diff --git a/tests/auto/qpushbutton/qpushbutton.pro b/tests/auto/qpushbutton/qpushbutton.pro deleted file mode 100644 index e2fd455951..0000000000 --- a/tests/auto/qpushbutton/qpushbutton.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qpushbutton.cpp - - - diff --git a/tests/auto/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap b/tests/auto/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap deleted file mode 100644 index 8c2c08aee9..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap b/tests/auto/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap deleted file mode 100644 index 3c455887da..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap b/tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap deleted file mode 100644 index e655b09d29..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap b/tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap deleted file mode 100644 index 8f59499d72..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap b/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap deleted file mode 100644 index a6967a17f7..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap b/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap deleted file mode 100644 index d7c721c960..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap b/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap deleted file mode 100644 index ae0261a22c..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setText/simple_Motif_data0.qsnap b/tests/auto/qpushbutton/testdata/setText/simple_Motif_data0.qsnap deleted file mode 100644 index 039bdce748..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setText/simple_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setText/simple_Windows_data0.qsnap b/tests/auto/qpushbutton/testdata/setText/simple_Windows_data0.qsnap deleted file mode 100644 index db40dc4726..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setText/simple_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap b/tests/auto/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap deleted file mode 100644 index c0e1279f46..0000000000 Binary files a/tests/auto/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap and /dev/null differ diff --git a/tests/auto/qpushbutton/tst_qpushbutton.cpp b/tests/auto/qpushbutton/tst_qpushbutton.cpp deleted file mode 100644 index e5083553e2..0000000000 --- a/tests/auto/qpushbutton/tst_qpushbutton.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include "qpushbutton.h" -#include - -#include -#include -#include -#include -#include -#include -#include - -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("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/qradiobutton/.gitignore b/tests/auto/qradiobutton/.gitignore deleted file mode 100644 index ac5e20c562..0000000000 --- a/tests/auto/qradiobutton/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qradiobutton diff --git a/tests/auto/qradiobutton/qradiobutton.pro b/tests/auto/qradiobutton/qradiobutton.pro deleted file mode 100644 index 82b2ff20a8..0000000000 --- a/tests/auto/qradiobutton/qradiobutton.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qradiobutton.cpp - - - diff --git a/tests/auto/qradiobutton/tst_qradiobutton.cpp b/tests/auto/qradiobutton/tst_qradiobutton.cpp deleted file mode 100644 index 79d3c8ef9a..0000000000 --- a/tests/auto/qradiobutton/tst_qradiobutton.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include - - -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/qregexpvalidator/.gitignore b/tests/auto/qregexpvalidator/.gitignore deleted file mode 100644 index cff9b076b2..0000000000 --- a/tests/auto/qregexpvalidator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qregexpvalidator diff --git a/tests/auto/qregexpvalidator/qregexpvalidator.pro b/tests/auto/qregexpvalidator/qregexpvalidator.pro deleted file mode 100644 index 68e5c51677..0000000000 --- a/tests/auto/qregexpvalidator/qregexpvalidator.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qregexpvalidator.cpp - - diff --git a/tests/auto/qregexpvalidator/tst_qregexpvalidator.cpp b/tests/auto/qregexpvalidator/tst_qregexpvalidator.cpp deleted file mode 100644 index 23cd5b1ef1..0000000000 --- a/tests/auto/qregexpvalidator/tst_qregexpvalidator.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - - -#include - -//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("rx"); - QTest::addColumn("value"); - QTest::addColumn("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/qscrollarea/.gitignore b/tests/auto/qscrollarea/.gitignore deleted file mode 100644 index aace58e9b1..0000000000 --- a/tests/auto/qscrollarea/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qscrollarea diff --git a/tests/auto/qscrollarea/qscrollarea.pro b/tests/auto/qscrollarea/qscrollarea.pro deleted file mode 100644 index 5b2602bbdb..0000000000 --- a/tests/auto/qscrollarea/qscrollarea.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qscrollarea.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qscrollarea.cpp - - diff --git a/tests/auto/qscrollarea/tst_qscrollarea.cpp b/tests/auto/qscrollarea/tst_qscrollarea.cpp deleted file mode 100644 index 8dcfb079d2..0000000000 --- a/tests/auto/qscrollarea/tst_qscrollarea.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -//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/qscrollbar/.gitignore b/tests/auto/qscrollbar/.gitignore deleted file mode 100644 index ae4ffe1e02..0000000000 --- a/tests/auto/qscrollbar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qscrollbar diff --git a/tests/auto/qscrollbar/qscrollbar.pro b/tests/auto/qscrollbar/qscrollbar.pro deleted file mode 100644 index 262855452f..0000000000 --- a/tests/auto/qscrollbar/qscrollbar.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qscrollbar.cpp - -mac*:CONFIG+=insignificant_test -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qscrollbar/tst_qscrollbar.cpp b/tests/auto/qscrollbar/tst_qscrollbar.cpp deleted file mode 100644 index c4b64f3f1e..0000000000 --- a/tests/auto/qscrollbar/tst_qscrollbar.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -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/qscroller/qscroller.pro b/tests/auto/qscroller/qscroller.pro deleted file mode 100644 index de202d66aa..0000000000 --- a/tests/auto/qscroller/qscroller.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) - -QT += widgets -SOURCES += tst_qscroller.cpp diff --git a/tests/auto/qscroller/tst_qscroller.cpp b/tests/auto/qscroller/tst_qscroller.cpp deleted file mode 100644 index 9ed4965d45..0000000000 --- a/tests/auto/qscroller/tst_qscroller.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -// #include - -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(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(e); - // qDebug() << "Scroll for"<scrollPos()<<"ov"<overshoot()<<"first"<isFirst()<<"last"<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() << 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() << 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() << 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() << 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() << 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() << 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(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::OvershootAlwaysOff); - - sp1.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn)); - QCOMPARE(sp1.scrollMetric(QScrollerProperties::VerticalOvershootPolicy).value(), QScrollerProperties::OvershootAlwaysOn); - - sp1.setScrollMetric(QScrollerProperties::FrameRate, QVariant::fromValue(QScrollerProperties::Fps20)); - QCOMPARE(sp1.scrollMetric(QScrollerProperties::FrameRate).value(), 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: "<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: "<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: "<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/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro b/tests/auto/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro deleted file mode 100644 index c947e7a246..0000000000 --- a/tests/auto/qsharedpointer_and_qwidget/qsharedpointer_and_qwidget.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qsharedpointer_and_qwidget.cpp -DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp b/tests/auto/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp deleted file mode 100644 index 90b71c517c..0000000000 --- a/tests/auto/qsharedpointer_and_qwidget/tst_qsharedpointer_and_qwidget.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -QT_BEGIN_NAMESPACE -namespace QtSharedPointer { - Q_CORE_EXPORT void internalSafetyCheckCleanCheck(); -} -QT_END_NAMESPACE - -class tst_QSharedPointer_and_QWidget: public QObject -{ - Q_OBJECT -private slots: - void weak_externalDelete(); - void weak_parentDelete(); - void weak_parentDelete_setParent(); - - void strong_weak(); - - void strong_sharedptrDelete(); - -public slots: - void cleanup() { check(); } - -public: - inline void check() - { -#ifdef QT_BUILD_INTERNAL - QtSharedPointer::internalSafetyCheckCleanCheck(); -#endif - } -}; - -void tst_QSharedPointer_and_QWidget::weak_externalDelete() -{ - QWidget *w = new QWidget; - QWeakPointer ptr = w; - - QVERIFY(!ptr.isNull()); - - delete w; - QVERIFY(ptr.isNull()); -} - -void tst_QSharedPointer_and_QWidget::weak_parentDelete() -{ - QWidget *parent = new QWidget; - QWidget *w = new QWidget(parent); - QWeakPointer ptr = w; - - QVERIFY(!ptr.isNull()); - - delete parent; - QVERIFY(ptr.isNull()); -} - -void tst_QSharedPointer_and_QWidget::weak_parentDelete_setParent() -{ - QWidget *parent = new QWidget; - QWidget *w = new QWidget; - QWeakPointer ptr = w; - w->setParent(parent); - - QVERIFY(!ptr.isNull()); - - delete parent; - QVERIFY(ptr.isNull()); -} - -// -- mixed -- - -void tst_QSharedPointer_and_QWidget::strong_weak() -{ - QSharedPointer ptr(new QWidget); - QWeakPointer weak = ptr.data(); - QWeakPointer weak2 = ptr; - - QVERIFY(!weak.isNull()); - QVERIFY(!weak2.isNull()); - - ptr.clear(); // deletes - - QVERIFY(weak.isNull()); - QVERIFY(weak2.isNull()); -} - - -// ---- strong management ---- - -void tst_QSharedPointer_and_QWidget::strong_sharedptrDelete() -{ - QWidget *parent = new QWidget; - QSharedPointer ptr(new QWidget(parent)); - QWeakPointer weak = ptr; - QPointer check = ptr.data(); - - QVERIFY(!check.isNull()); - QVERIFY(!weak.isNull()); - - ptr.clear(); // deletes - - QVERIFY(check.isNull()); - QVERIFY(weak.isNull()); - - delete parent; // mustn't crash -} - -QTEST_MAIN(tst_QSharedPointer_and_QWidget) - -#include "tst_qsharedpointer_and_qwidget.moc" diff --git a/tests/auto/qsidebar/.gitignore b/tests/auto/qsidebar/.gitignore deleted file mode 100644 index 194ca9f244..0000000000 --- a/tests/auto/qsidebar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsidebar diff --git a/tests/auto/qsidebar/qsidebar.pro b/tests/auto/qsidebar/qsidebar.pro deleted file mode 100644 index 9f6e094784..0000000000 --- a/tests/auto/qsidebar/qsidebar.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += qttest_p4 - -QT += core-private -QT += widgets widgets-private -SOURCES += tst_qsidebar.cpp -TARGET = tst_qsidebar diff --git a/tests/auto/qsidebar/tst_qsidebar.cpp b/tests/auto/qsidebar/tst_qsidebar.cpp deleted file mode 100644 index 912719f76a..0000000000 --- a/tests/auto/qsidebar/tst_qsidebar.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/**************************************************************************** -** -** 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 -#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 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 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 emptyUrls; - QFileSystemModel fsmodel; - QSidebar qsidebar; - qsidebar.init(&fsmodel, emptyUrls); - QAbstractItemModel *model = qsidebar.model(); - QDir testDir = QDir::home(); - - // default - QCOMPARE(model->rowCount(), 0); - - QList 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 moreUrls; - moreUrls << QUrl::fromLocalFile(testDir.absolutePath()); - qsidebar.addUrls(moreUrls, -1); - QCOMPARE(model->rowCount(), 3); - - // make sure invalid urls are still added - QList 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(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 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 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/qsizegrip/.gitignore b/tests/auto/qsizegrip/.gitignore deleted file mode 100644 index ec480bcbad..0000000000 --- a/tests/auto/qsizegrip/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsizegrip diff --git a/tests/auto/qsizegrip/qsizegrip.pro b/tests/auto/qsizegrip/qsizegrip.pro deleted file mode 100644 index da6dd5af49..0000000000 --- a/tests/auto/qsizegrip/qsizegrip.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -INCLUDEPATH += . -QT += widgets -SOURCES += tst_qsizegrip.cpp - - diff --git a/tests/auto/qsizegrip/tst_qsizegrip.cpp b/tests/auto/qsizegrip/tst_qsizegrip.cpp deleted file mode 100644 index cc0710a65a..0000000000 --- a/tests/auto/qsizegrip/tst_qsizegrip.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -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("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/qslider/.gitignore b/tests/auto/qslider/.gitignore deleted file mode 100644 index f8d833e8b4..0000000000 --- a/tests/auto/qslider/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qslider diff --git a/tests/auto/qslider/qslider.pro b/tests/auto/qslider/qslider.pro deleted file mode 100644 index 41f011649d..0000000000 --- a/tests/auto/qslider/qslider.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qslider.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qslider.cpp - - diff --git a/tests/auto/qslider/tst_qslider.cpp b/tests/auto/qslider/tst_qslider.cpp deleted file mode 100644 index 50ee9e6a63..0000000000 --- a/tests/auto/qslider/tst_qslider.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -//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/qsortfilterproxymodel/.gitignore b/tests/auto/qsortfilterproxymodel/.gitignore deleted file mode 100644 index d3672fe4ae..0000000000 --- a/tests/auto/qsortfilterproxymodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsortfilterproxymodel diff --git a/tests/auto/qsortfilterproxymodel/qsortfilterproxymodel.pro b/tests/auto/qsortfilterproxymodel/qsortfilterproxymodel.pro deleted file mode 100644 index a60fbac944..0000000000 --- a/tests/auto/qsortfilterproxymodel/qsortfilterproxymodel.pro +++ /dev/null @@ -1,9 +0,0 @@ -load(qttest_p4) - -QT += gui widgets - -INCLUDEPATH += $$PWD/../modeltest - -SOURCES += tst_qsortfilterproxymodel.cpp ../modeltest/dynamictreemodel.cpp ../modeltest/modeltest.cpp -HEADERS += ../modeltest/dynamictreemodel.h ../modeltest/modeltest.h - diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp deleted file mode 100644 index 96f7249e3c..0000000000 --- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ /dev/null @@ -1,3274 +0,0 @@ -/**************************************************************************** -** -** 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 -#include "dynamictreemodel.h" -#include "modeltest.h" - -#include -#include -#include - -#include - -//TESTED CLASS= -//TESTED_FILES= - -typedef QList IntList; -typedef QPair IntPair; -typedef QList 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"); - qRegisterMetaType("IntList"); - qRegisterMetaType("IntPair"); - qRegisterMetaType("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("sortOrder"); - QTest::addColumn("sortCaseSensitivity"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - - QTest::newRow("flat descending") << static_cast(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(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(Qt::AscendingOrder) - << int(Qt::CaseInsensitive) - << (QStringList() - << "alpha" << "BETA" << "Gamma" << "delta") - << (QStringList() - << "alpha" << "BETA" << "delta" << "Gamma"); - QTest::newRow("case sensitive") << static_cast(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(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 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(sortOrder)); - m_proxy->setSortCaseSensitivity(static_cast(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("sortOrder"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - -#if 1 - QTest::newRow("flat ascending") - << static_cast(Qt::AscendingOrder) - << (QStringList() - << "c" << "f" << "d" << "e" << "a" << "b") - << (QStringList() - << "a" << "b" << "c" << "d" << "e" << "f"); -#endif - QTest::newRow("simple hierarchy") - << static_cast(Qt::AscendingOrder) - << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">") - << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">"); - -#if 1 - QTest::newRow("hierarchical ascending") - << static_cast(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(sortOrder)); - checkHierarchy(initial, m_model); - checkHierarchy(expected, m_proxy); -} - -void tst_QSortFilterProxyModel::insertRows_data() -{ - QTest::addColumn("initial"); - QTest::addColumn("expected"); - QTest::addColumn("insert"); - QTest::addColumn("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("initial"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("position"); - QTest::addColumn("count"); - QTest::addColumn("success"); - QTest::addColumn("expectedProxy"); - QTest::addColumn("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(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(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(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(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(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("initial"); - QTest::addColumn("filter"); - QTest::addColumn("position"); - QTest::addColumn("count"); - QTest::addColumn("success"); - QTest::addColumn("expectedProxy"); - QTest::addColumn("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("pattern"); - QTest::addColumn("initial"); - QTest::addColumn("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("pattern"); - QTest::addColumn("initial"); - QTest::addColumn("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("pattern"); - QTest::addColumn("initial"); - QTest::addColumn("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 row_stack; - QModelIndex parent; - QStack 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 row_stack; - QModelIndex parent; - QStack 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 persistentSourceIndexes; - QList 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("sourceItems"); - QTest::addColumn("start"); - QTest::addColumn("count"); - QTest::addColumn("sortOrder"); - QTest::addColumn("expectedRemovedProxyIntervals"); - QTest::addColumn("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(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(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(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(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(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(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 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 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("sourceItems"); - QTest::addColumn("start"); - QTest::addColumn("newItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("proxyItems"); - - QTest::newRow("insert (1)") - << (QStringList() << "c" << "b") // sourceItems - << 1 // start - << (QStringList() << "a") // newItems - << static_cast(Qt::AscendingOrder) // sortOrder - << (QStringList() << "a" << "b" << "c") // proxyItems - ; - - QTest::newRow("insert (2)") - << (QStringList() << "d" << "b" << "c") // sourceItems - << 3 // start - << (QStringList() << "a") // newItems - << static_cast(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(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("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("initialFilter"); - QTest::addColumn("initialRemoveIntervals"); - QTest::addColumn("initialProxyItems"); - QTest::addColumn("finalFilter"); - QTest::addColumn("finalRemoveIntervals"); - QTest::addColumn("insertIntervals"); - QTest::addColumn("finalProxyItems"); - - QTest::newRow("filter (1)") - << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems - << static_cast(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(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(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(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 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 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 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("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("dynamic"); - QTest::addColumn("row"); - QTest::addColumn("newValue"); - QTest::addColumn("removeIntervals"); - QTest::addColumn("insertIntervals"); - QTest::addColumn("proxyItems"); - - QTest::newRow("changeSourceData (1)") - << (QStringList() << "c" << "b" << "a") // sourceItems - << static_cast(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(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(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(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(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(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(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 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 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 > sourceItems; - sourceItems = QList >() - << QPair("b", 3) - << QPair("c", 2) - << QPair("a", 1); - - QList orderedItems; - orderedItems = QList() - << 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("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("proxyStartRow"); - QTest::addColumn("what"); - QTest::addColumn("matchFlags"); - QTest::addColumn("expectedProxyItems"); - QTest::newRow("1") - << (QStringList() << "a") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << 0 // proxyStartRow - << "a" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 0); // expectedProxyItems - QTest::newRow("2") - << (QStringList() << "a" << "b") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << 0 // proxyStartRow - << "b" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 1); // expectedProxyItems - QTest::newRow("3") - << (QStringList() << "a" << "b") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "" // filter - << 0 // proxyStartRow - << "a" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 1); // expectedProxyItems - QTest::newRow("4") - << (QStringList() << "b" << "d" << "a" << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << 1 // proxyStartRow - << "a" // what - << static_cast(Qt::MatchExactly) // matchFlags - << IntList(); // expectedProxyItems - QTest::newRow("5") - << (QStringList() << "b" << "d" << "a" << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|b" // filter - << 0 // proxyStartRow - << "c" // what - << static_cast(Qt::MatchExactly) // matchFlags - << IntList(); // expectedProxyItems - QTest::newRow("6") - << (QStringList() << "b" << "d" << "a" << "c") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "a|b" // filter - << 0 // proxyStartRow - << "b" // what - << static_cast(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(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(args.at(0)), proxy.mapFromSource(itemB->index())); - QCOMPARE(qvariant_cast(args.at(1)), 0); - QCOMPARE(qvariant_cast(args.at(2)), 0); - - args = rowsInsertedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), proxy.mapFromSource(itemB->index())); - QCOMPARE(qvariant_cast(args.at(1)), 0); - QCOMPARE(qvariant_cast(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(&model)); - } - QCOMPARE(proxyModel.sourceModel(), static_cast(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 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 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 fetched; - int rows, cols; - mutable bool wrongIndex; - mutable QMap 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 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 sourceIndexes; - QList 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 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("test"); - QTest::addColumn("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/qsound/.gitignore b/tests/auto/qsound/.gitignore deleted file mode 100644 index c9d313c2cf..0000000000 --- a/tests/auto/qsound/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsound diff --git a/tests/auto/qsound/4.wav b/tests/auto/qsound/4.wav deleted file mode 100644 index e31b060908..0000000000 Binary files a/tests/auto/qsound/4.wav and /dev/null differ diff --git a/tests/auto/qsound/qsound.pro b/tests/auto/qsound/qsound.pro deleted file mode 100644 index 18ebaf16a4..0000000000 --- a/tests/auto/qsound/qsound.pro +++ /dev/null @@ -1,10 +0,0 @@ -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/qsound/tst_qsound.cpp b/tests/auto/qsound/tst_qsound.cpp deleted file mode 100644 index 7450549f47..0000000000 --- a/tests/auto/qsound/tst_qsound.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -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/qspinbox/.gitignore b/tests/auto/qspinbox/.gitignore deleted file mode 100644 index 84599cf955..0000000000 --- a/tests/auto/qspinbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qspinbox diff --git a/tests/auto/qspinbox/qspinbox.pro b/tests/auto/qspinbox/qspinbox.pro deleted file mode 100644 index c88dc0ee8f..0000000000 --- a/tests/auto/qspinbox/qspinbox.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qspinbox.cpp diff --git a/tests/auto/qspinbox/tst_qspinbox.cpp b/tests/auto/qspinbox/tst_qspinbox.cpp deleted file mode 100644 index 608dcd6705..0000000000 --- a/tests/auto/qspinbox/tst_qspinbox.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#ifdef Q_WS_X11 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//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 actualValues; - QWidget *testFocusWidget; -}; - -typedef QList 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("set"); - QTest::addColumn("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("prefix"); - QTest::addColumn("suffix"); - QTest::addColumn("value"); - QTest::addColumn("expectedText"); - QTest::addColumn("expectedCleanText"); - QTest::addColumn("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("keys"); - QTest::addColumn("texts"); - QTest::addColumn("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("wrapping"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("startValue"); - QTest::addColumn("keys"); - QTest::addColumn("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("specialValueText"); - QTest::addColumn("minimum"); - QTest::addColumn("maximum"); - QTest::addColumn("value"); - QTest::addColumn("expected"); - QTest::addColumn("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("singleStep"); - QTest::addColumn("startValue"); - QTest::addColumn("keys"); - QTest::addColumn("expected"); - QTest::addColumn("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("startValue"); - QTest::addColumn("mini"); - QTest::addColumn("maxi"); - QTest::addColumn("keys"); - QTest::addColumn("expected"); - QTest::addColumn("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("txt"); - QTest::addColumn("state"); - QTest::addColumn("mini"); - QTest::addColumn("maxi"); - QTest::addColumn("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("loc"); - QTest::addColumn("value"); - QTest::addColumn("textFromVal"); - QTest::addColumn("text"); - QTest::addColumn("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(&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(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/qsplitter/.gitignore b/tests/auto/qsplitter/.gitignore deleted file mode 100644 index 311db65ff0..0000000000 --- a/tests/auto/qsplitter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsplitter diff --git a/tests/auto/qsplitter/extradata.txt b/tests/auto/qsplitter/extradata.txt deleted file mode 100644 index ceb46d4a82..0000000000 --- a/tests/auto/qsplitter/extradata.txt +++ /dev/null @@ -1,10067 +0,0 @@ -// 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/qsplitter/qsplitter.pro b/tests/auto/qsplitter/qsplitter.pro deleted file mode 100644 index 9942c899ca..0000000000 --- a/tests/auto/qsplitter/qsplitter.pro +++ /dev/null @@ -1,12 +0,0 @@ -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/qsplitter/setSizes3.dat b/tests/auto/qsplitter/setSizes3.dat deleted file mode 100644 index 5d8a73d6f9..0000000000 --- a/tests/auto/qsplitter/setSizes3.dat +++ /dev/null @@ -1,2250 +0,0 @@ -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/qsplitter/tst_qsplitter.cpp b/tests/auto/qsplitter/tst_qsplitter.cpp deleted file mode 100644 index 836286e8ae..0000000000 --- a/tests/auto/qsplitter/tst_qsplitter.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // 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() << 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 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("minimumSizes"); - QTest::addColumn("splitterSizes"); - QTest::addColumn("expectedSizes"); - QTest::addColumn("collapsibleStates"); - QTest::addColumn("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 l1 = splitter->sizes(); - QList 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("initialSizes"); - QTest::addColumn("hideWidget1"); - QTest::addColumn("hideWidget2"); - QTest::addColumn("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("orientation"); - QTest::addColumn("widgetIndex"); - QTest::addColumn("stretchFactor"); - QTest::addColumn("expectedHStretch"); - QTest::addColumn("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("hideWidget1"); - QTest::addColumn("hideWidget2"); - QTest::addColumn >("finalValues"); - QTest::addColumn("handleVisible"); - - QSplitter *split = new QSplitter(Qt::Horizontal); - QTest::newRow("hideNone") << false << false << (QList() << 200 << 200) << true; - QTest::newRow("hide2") << false << true << (QList() << 400 + split->handleWidth() << 0) << false; - QTest::newRow("hide1") << true << false << (QList() << 0 << 400 + split->handleWidth()) << false; - QTest::newRow("hideall") << true << true << (QList() << 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() << 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("className"); - QTest::addColumn("addInConstructor"); - QTest::addColumn("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("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/qstackedlayout/.gitignore b/tests/auto/qstackedlayout/.gitignore deleted file mode 100644 index 4dca3e87bd..0000000000 --- a/tests/auto/qstackedlayout/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstackedlayout diff --git a/tests/auto/qstackedlayout/qstackedlayout.pro b/tests/auto/qstackedlayout/qstackedlayout.pro deleted file mode 100644 index 30f074d9b1..0000000000 --- a/tests/auto/qstackedlayout/qstackedlayout.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qstackedlayout.cpp - - - diff --git a/tests/auto/qstackedlayout/tst_qstackedlayout.cpp b/tests/auto/qstackedlayout/tst_qstackedlayout.cpp deleted file mode 100644 index de734877d7..0000000000 --- a/tests/auto/qstackedlayout/tst_qstackedlayout.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -//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(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(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(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(top)); - - // focus should stay at the 'top' widget - testLayout->removeWidget(w1); - - QCOMPARE(QApplication::focusWidget(), static_cast(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(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/qstackedwidget/.gitignore b/tests/auto/qstackedwidget/.gitignore deleted file mode 100644 index 172554eedb..0000000000 --- a/tests/auto/qstackedwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstackedwidget diff --git a/tests/auto/qstackedwidget/qstackedwidget.pro b/tests/auto/qstackedwidget/qstackedwidget.pro deleted file mode 100644 index c9436c6a86..0000000000 --- a/tests/auto/qstackedwidget/qstackedwidget.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qstackedwidget.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qstackedwidget.cpp - - diff --git a/tests/auto/qstackedwidget/tst_qstackedwidget.cpp b/tests/auto/qstackedwidget/tst_qstackedwidget.cpp deleted file mode 100644 index a4e71eca51..0000000000 --- a/tests/auto/qstackedwidget/tst_qstackedwidget.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include - -//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/qstandarditem/.gitignore b/tests/auto/qstandarditem/.gitignore deleted file mode 100644 index 6da85cc6c8..0000000000 --- a/tests/auto/qstandarditem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstandarditem diff --git a/tests/auto/qstandarditem/qstandarditem.pro b/tests/auto/qstandarditem/qstandarditem.pro deleted file mode 100644 index 1d280fc2f5..0000000000 --- a/tests/auto/qstandarditem/qstandarditem.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qstandarditem.cpp - - diff --git a/tests/auto/qstandarditem/tst_qstandarditem.cpp b/tests/auto/qstandarditem/tst_qstandarditem.cpp deleted file mode 100644 index 206d469884..0000000000 --- a/tests/auto/qstandarditem/tst_qstandarditem.cpp +++ /dev/null @@ -1,1110 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include - -//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(item.data(Qt::DisplayRole)), text); - QCOMPARE(qvariant_cast(item.data(Qt::DecorationRole)), icon); - QCOMPARE(qvariant_cast(item.data(Qt::ToolTipRole)), toolTip); - QCOMPARE(qvariant_cast(item.data(Qt::StatusTipRole)), statusTip); - QCOMPARE(qvariant_cast(item.data(Qt::WhatsThisRole)), whatsThis); - QCOMPARE(qvariant_cast(item.data(Qt::SizeHintRole)), sizeHint); - QCOMPARE(qvariant_cast(item.data(Qt::FontRole)), font); - QCOMPARE(qvariant_cast(item.data(Qt::TextAlignmentRole)), int(textAlignment)); - QCOMPARE(qvariant_cast(item.data(Qt::BackgroundColorRole)), QBrush(backgroundColor)); - QCOMPARE(qvariant_cast(item.data(Qt::BackgroundRole)), QBrush(backgroundColor)); - QCOMPARE(qvariant_cast(item.data(Qt::TextColorRole)), QBrush(textColor)); - QCOMPARE(qvariant_cast(item.data(Qt::ForegroundRole)), QBrush(textColor)); - QCOMPARE(qvariant_cast(item.data(Qt::CheckStateRole)), int(checkState)); - QCOMPARE(qvariant_cast(item.data(Qt::AccessibleTextRole)), accessibleText); - QCOMPARE(qvariant_cast(item.data(Qt::AccessibleDescriptionRole)), accessibleDescription); - - item.setBackground(pixmap); - QCOMPARE(item.background().texture(), pixmap); - QCOMPARE(qvariant_cast(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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("row"); - QTest::addColumn("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(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(0)); -} - -void tst_QStandardItem::parent() -{ - { - QStandardItem item; - QStandardItem *child = new QStandardItem; - QCOMPARE(child->parent(), static_cast(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(0)); - } -} - -void tst_QStandardItem::insertColumn_data() -{ - QTest::addColumn("rows"); - QTest::addColumn("columns"); - QTest::addColumn("column"); - QTest::addColumn("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 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(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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("row"); - QTest::addColumn("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 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(0)); - } else { - QCOMPARE(item.columnCount(), columns); - QCOMPARE(item.rowCount(), rows); - qDeleteAll(rowItems); - } -} - -void tst_QStandardItem::insertRows_data() -{ - QTest::addColumn("rows"); - QTest::addColumn("columns"); - QTest::addColumn("insertAt"); - QTest::addColumn("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 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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("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 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 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(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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("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 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 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(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 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(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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("column"); - QTest::addColumn("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 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 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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("row"); - QTest::addColumn("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 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 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(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(); - - 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(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/qstandarditemmodel/.gitignore b/tests/auto/qstandarditemmodel/.gitignore deleted file mode 100644 index c218efce58..0000000000 --- a/tests/auto/qstandarditemmodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstandarditemmodel diff --git a/tests/auto/qstandarditemmodel/qstandarditemmodel.pro b/tests/auto/qstandarditemmodel/qstandarditemmodel.pro deleted file mode 100644 index 8c634b9630..0000000000 --- a/tests/auto/qstandarditemmodel/qstandarditemmodel.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) - -QT += widgets widgets-private -QT += core-private gui-private - -SOURCES += tst_qstandarditemmodel.cpp - - diff --git a/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp deleted file mode 100644 index 84a33107aa..0000000000 --- a/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ /dev/null @@ -1,1666 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include - -//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 rcParent; - QVector rcFirst; - QVector 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"); - qRegisterMetaType("QStandardItem*"); - qRegisterMetaType("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("insertRow"); - QTest::addColumn("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 items; - QStandardItemModel *m = qobject_cast(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(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("insertColumn"); - QTest::addColumn("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(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("sortOrder"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - - QTest::newRow("flat descending") << static_cast(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(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(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(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("initialText"); - QTest::addColumn("initialData"); - QTest::addColumn("sortRole"); - QTest::addColumn("sortOrder"); - QTest::addColumn("expectedText"); - QTest::addColumn("expectedData"); - - QTest::newRow("sort ascending with Qt::DisplayRole") - << (QStringList() << "b" << "a" << "c") - << (QVariantList() << 2 << 3 << 1) - << static_cast(Qt::DisplayRole) - << static_cast(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(Qt::UserRole) - << static_cast(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(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 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(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(0)); - - QCOMPARE(model.verticalHeaderItem(0), static_cast(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(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(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(QStandardItem::UserType)); - - model.setItemPrototype(0); - QCOMPARE(model.itemPrototype(), static_cast(0)); -} - -void tst_QStandardItemModel::getSetItemData() -{ - QMap 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("rows"); - QTest::addColumn("columns"); - QTest::addColumn("orientation"); - QTest::addColumn("labels"); - QTest::addColumn("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 args; - args = dataChangedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), index); - QCOMPARE(qvariant_cast(args.at(1)), index); - args = itemChangedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), &item); - - item.setData(QLatin1String("foo"), Qt::DisplayRole); - QCOMPARE(dataChangedSpy.count(), 1); - QCOMPARE(itemChangedSpy.count(), 1); - args = dataChangedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), index); - QCOMPARE(qvariant_cast(args.at(1)), index); - args = itemChangedSpy.takeFirst(); - QCOMPARE(qvariant_cast(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(args.at(0)), index); - QCOMPARE(qvariant_cast(args.at(1)), index); - args = itemChangedSpy.takeFirst(); - QCOMPARE(qvariant_cast(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(0)); - QCOMPARE(vheader->model(), static_cast(0)); - QCOMPARE(model.takeHorizontalHeaderItem(0), static_cast(0)); - QCOMPARE(model.takeVerticalHeaderItem(0), static_cast(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(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()); - 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(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 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 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 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 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 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 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 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 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 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 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/qstatusbar/.gitignore b/tests/auto/qstatusbar/.gitignore deleted file mode 100644 index 14454b0693..0000000000 --- a/tests/auto/qstatusbar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstatusbar diff --git a/tests/auto/qstatusbar/qstatusbar.pro b/tests/auto/qstatusbar/qstatusbar.pro deleted file mode 100644 index 51ec0e9cdb..0000000000 --- a/tests/auto/qstatusbar/qstatusbar.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qstatusbar.cpp - - - diff --git a/tests/auto/qstatusbar/tst_qstatusbar.cpp b/tests/auto/qstatusbar/tst_qstatusbar.cpp deleted file mode 100644 index a4a232951a..0000000000 --- a/tests/auto/qstatusbar/tst_qstatusbar.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include - -//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 statusBar = mainWindow.statusBar(); - QVERIFY(statusBar); - mainWindow.show(); -#ifdef Q_WS_X11 - qt_x11_wait_for_window_manager(&mainWindow); -#endif - - QTRY_VERIFY(statusBar->isVisible()); - QPointer sizeGrip = qFindChild(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(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()->isVisible()); -#endif - main.showNormal(); - QTest::qWaitForWindowShown(&main); - QVERIFY(statusbar.findChild()->isVisible()); - main.showFullScreen(); - QTest::qWaitForWindowShown(&main); - QVERIFY(!statusbar.findChild()->isVisible()); -} - -QTEST_MAIN(tst_QStatusBar) -#include "tst_qstatusbar.moc" diff --git a/tests/auto/qstringlistmodel/.gitignore b/tests/auto/qstringlistmodel/.gitignore deleted file mode 100644 index 9c14561e3c..0000000000 --- a/tests/auto/qstringlistmodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstringlistmodel diff --git a/tests/auto/qstringlistmodel/qmodellistener.h b/tests/auto/qstringlistmodel/qmodellistener.h deleted file mode 100644 index f3ed3c1793..0000000000 --- a/tests/auto/qstringlistmodel/qmodellistener.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - - -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/qstringlistmodel/qstringlistmodel.pro b/tests/auto/qstringlistmodel/qstringlistmodel.pro deleted file mode 100644 index fe70ed7345..0000000000 --- a/tests/auto/qstringlistmodel/qstringlistmodel.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) -QT += widgets -HEADERS += qmodellistener.h - -SOURCES += tst_qstringlistmodel.cpp - - - diff --git a/tests/auto/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/qstringlistmodel/tst_qstringlistmodel.cpp deleted file mode 100644 index 2542496f14..0000000000 --- a/tests/auto/qstringlistmodel/tst_qstringlistmodel.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include "qmodellistener.h" -#include - -//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("input"); - QTest::addColumn("row"); - QTest::addColumn("count"); - QTest::addColumn("aboutto"); - QTest::addColumn("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("input"); - QTest::addColumn("row"); - QTest::addColumn("count"); - QTest::addColumn("aboutto"); - QTest::addColumn("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/qstyle/.gitignore b/tests/auto/qstyle/.gitignore deleted file mode 100644 index 64709f11f7..0000000000 --- a/tests/auto/qstyle/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstyle diff --git a/tests/auto/qstyle/images/mac/button.png b/tests/auto/qstyle/images/mac/button.png deleted file mode 100644 index 7b11325e87..0000000000 Binary files a/tests/auto/qstyle/images/mac/button.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/combobox.png b/tests/auto/qstyle/images/mac/combobox.png deleted file mode 100644 index ded0b11f29..0000000000 Binary files a/tests/auto/qstyle/images/mac/combobox.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/lineedit.png b/tests/auto/qstyle/images/mac/lineedit.png deleted file mode 100644 index 8d2861b65b..0000000000 Binary files a/tests/auto/qstyle/images/mac/lineedit.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/mdi.png b/tests/auto/qstyle/images/mac/mdi.png deleted file mode 100644 index 8c09ae4338..0000000000 Binary files a/tests/auto/qstyle/images/mac/mdi.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/menu.png b/tests/auto/qstyle/images/mac/menu.png deleted file mode 100644 index 5dd9111d69..0000000000 Binary files a/tests/auto/qstyle/images/mac/menu.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/radiobutton.png b/tests/auto/qstyle/images/mac/radiobutton.png deleted file mode 100644 index 8828e220a2..0000000000 Binary files a/tests/auto/qstyle/images/mac/radiobutton.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/slider.png b/tests/auto/qstyle/images/mac/slider.png deleted file mode 100644 index fc65035631..0000000000 Binary files a/tests/auto/qstyle/images/mac/slider.png and /dev/null differ diff --git a/tests/auto/qstyle/images/mac/spinbox.png b/tests/auto/qstyle/images/mac/spinbox.png deleted file mode 100644 index ee88441ecb..0000000000 Binary files a/tests/auto/qstyle/images/mac/spinbox.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/button.png b/tests/auto/qstyle/images/vista/button.png deleted file mode 100644 index a6c45276ca..0000000000 Binary files a/tests/auto/qstyle/images/vista/button.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/combobox.png b/tests/auto/qstyle/images/vista/combobox.png deleted file mode 100644 index 9b82f64d32..0000000000 Binary files a/tests/auto/qstyle/images/vista/combobox.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/lineedit.png b/tests/auto/qstyle/images/vista/lineedit.png deleted file mode 100644 index b2c6ac1ae4..0000000000 Binary files a/tests/auto/qstyle/images/vista/lineedit.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/menu.png b/tests/auto/qstyle/images/vista/menu.png deleted file mode 100644 index b114099cc3..0000000000 Binary files a/tests/auto/qstyle/images/vista/menu.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/radiobutton.png b/tests/auto/qstyle/images/vista/radiobutton.png deleted file mode 100644 index c8aa7864df..0000000000 Binary files a/tests/auto/qstyle/images/vista/radiobutton.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/slider.png b/tests/auto/qstyle/images/vista/slider.png deleted file mode 100644 index 7c156ded9d..0000000000 Binary files a/tests/auto/qstyle/images/vista/slider.png and /dev/null differ diff --git a/tests/auto/qstyle/images/vista/spinbox.png b/tests/auto/qstyle/images/vista/spinbox.png deleted file mode 100644 index b8d0823ab2..0000000000 Binary files a/tests/auto/qstyle/images/vista/spinbox.png and /dev/null differ diff --git a/tests/auto/qstyle/qstyle.pro b/tests/auto/qstyle/qstyle.pro deleted file mode 100644 index 2016316737..0000000000 --- a/tests/auto/qstyle/qstyle.pro +++ /dev/null @@ -1,13 +0,0 @@ -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/qstyle/task_25863.png b/tests/auto/qstyle/task_25863.png deleted file mode 100644 index a2de8d6f78..0000000000 Binary files a/tests/auto/qstyle/task_25863.png and /dev/null differ diff --git a/tests/auto/qstyle/tst_qstyle.cpp b/tests/auto/qstyle/tst_qstyle.cpp deleted file mode 100644 index 0045dbbb52..0000000000 --- a/tests/auto/qstyle/tst_qstyle.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include "qstyle.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef Q_WS_MAC -#include -#endif - -#ifdef Q_WS_WIN -#include -#include -#endif - -#ifdef Q_OS_WINCE -#include -#endif - -#ifdef Q_OS_WINCE_WM -#include -#include - -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 (QString::fromLatin1("Smartphone").utf16()), tszPlatform)) - return true; - return false; -} -#endif - -#include - -//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(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() << 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(&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/qstyleoption/.gitignore b/tests/auto/qstyleoption/.gitignore deleted file mode 100644 index 70bf7781ce..0000000000 --- a/tests/auto/qstyleoption/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstyleoption diff --git a/tests/auto/qstyleoption/qstyleoption.pro b/tests/auto/qstyleoption/qstyleoption.pro deleted file mode 100644 index ccbb39d55b..0000000000 --- a/tests/auto/qstyleoption/qstyleoption.pro +++ /dev/null @@ -1,11 +0,0 @@ -###################################################################### -# 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/qstyleoption/tst_qstyleoption.cpp b/tests/auto/qstyleoption/tst_qstyleoption.cpp deleted file mode 100644 index c1d4bd8166..0000000000 --- a/tests/auto/qstyleoption/tst_qstyleoption.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - - -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 -struct StyleOptionPointer: public StyleOptionPointerBase -{ - StyleOptionPointer(T *p = 0): StyleOptionPointerBase(p) {} - ~StyleOptionPointer() { delete static_cast(pointer); pointer = 0; } -}; - -Q_DECLARE_METATYPE(StyleOptionPointerBase*) - -template -inline StyleOptionPointerBase *stylePtr(T *ptr) { return new StyleOptionPointer(ptr); } - -void tst_QStyleOption::qstyleoptioncast_data() -{ - QTest::addColumn("testOption"); - QTest::addColumn("canCastToComplex"); - QTest::addColumn("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(testOption->pointer); - QVERIFY(castOption != 0); - - // Cast to complex base class - castOption = qstyleoption_cast(testOption->pointer); - QCOMPARE(canCastToComplex, (castOption != 0)); - - // Cast to combo box - castOption = qstyleoption_cast(testOption->pointer); - QCOMPARE((castOption != 0),(testOption->pointer->type == QStyleOption::SO_ComboBox)); - - // Cast to button - castOption = qstyleoption_cast(testOption->pointer); - QCOMPARE((castOption != 0),(testOption->pointer->type == QStyleOption::SO_Button)); - - // Cast to lower version - testOption->pointer->version += 1; - castOption = qstyleoption_cast(testOption->pointer); - QVERIFY(castOption); - - // Cast a null pointer - castOption = qstyleoption_cast((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/qstylesheetstyle/.gitignore b/tests/auto/qstylesheetstyle/.gitignore deleted file mode 100644 index df0251385e..0000000000 --- a/tests/auto/qstylesheetstyle/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qstylesheetstyle diff --git a/tests/auto/qstylesheetstyle/images/testimage.png b/tests/auto/qstylesheetstyle/images/testimage.png deleted file mode 100644 index 06fb34f0d6..0000000000 Binary files a/tests/auto/qstylesheetstyle/images/testimage.png and /dev/null differ diff --git a/tests/auto/qstylesheetstyle/qstylesheetstyle.pro b/tests/auto/qstylesheetstyle/qstylesheetstyle.pro deleted file mode 100644 index 9dc296a51c..0000000000 --- a/tests/auto/qstylesheetstyle/qstylesheetstyle.pro +++ /dev/null @@ -1,7 +0,0 @@ -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/qstylesheetstyle/resources.qrc b/tests/auto/qstylesheetstyle/resources.qrc deleted file mode 100644 index 248bf80f50..0000000000 --- a/tests/auto/qstylesheetstyle/resources.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - - images/testimage.png - - \ No newline at end of file diff --git a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp deleted file mode 100644 index 98e64eb17d..0000000000 --- a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ /dev/null @@ -1,1644 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -#include -#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 pstyle1 = &style1; - QPointer 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(&style1), window1->style()); - - // Setting another style must not delete the older style - window1->setStyle(&style2); - QCOMPARE(static_cast(&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 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(&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(&style1)); // the same guy - - // Remove the stylesheet - proxy = (QStyleSheetStyle *)window1->style(); - window1->setStyleSheet(""); - QVERIFY(proxy.isNull()); // should have disappeared - QCOMPARE(window1->style(), static_cast(&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(&style1)); - - // Style Sheet propagation on a child widget with a custom style already set - window2->setStyleSheet(""); - QCOMPARE(window2->style(), static_cast(&style2)); - QCOMPARE(widget2->style(), static_cast(&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(newStyle)); // magic ;) the widget still follows the application - QCOMPARE(static_cast(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(&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 style1 = new QWindowsStyle; - QPointer 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 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(&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 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 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 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"); - - 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(&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(&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(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 widgets; - QList 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(); - 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(); - QVERIFY(embedded); - QTest::qWait(20); - QCOMPARE(box.font().pixelSize(), 32); - QCOMPARE(embedded->font().pixelSize(), 32); -} - -void tst_QStyleSheetStyle::opaquePaintEvent_data() -{ - QTest::addColumn("stylesheet"); - QTest::addColumn("transparent"); - QTest::addColumn("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 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/qsystemtrayicon/.gitignore b/tests/auto/qsystemtrayicon/.gitignore deleted file mode 100644 index 6da1f79209..0000000000 --- a/tests/auto/qsystemtrayicon/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsystemtrayicon diff --git a/tests/auto/qsystemtrayicon/icons/icon.png b/tests/auto/qsystemtrayicon/icons/icon.png deleted file mode 100644 index 7528931ed8..0000000000 Binary files a/tests/auto/qsystemtrayicon/icons/icon.png and /dev/null differ diff --git a/tests/auto/qsystemtrayicon/qsystemtrayicon.pro b/tests/auto/qsystemtrayicon/qsystemtrayicon.pro deleted file mode 100644 index 8a6ea3d0a9..0000000000 --- a/tests/auto/qsystemtrayicon/qsystemtrayicon.pro +++ /dev/null @@ -1,9 +0,0 @@ -############################################################ -# Project file for autotest for file qsystemtrayicon.h -############################################################ - -load(qttest_p4) -QT += widgets -SOURCES += tst_qsystemtrayicon.cpp - - diff --git a/tests/auto/qsystemtrayicon/tst_qsystemtrayicon.cpp b/tests/auto/qsystemtrayicon/tst_qsystemtrayicon.cpp deleted file mode 100644 index a4a5ed7ad9..0000000000 --- a/tests/auto/qsystemtrayicon/tst_qsystemtrayicon.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include - -//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/qtabbar/.gitignore b/tests/auto/qtabbar/.gitignore deleted file mode 100644 index 3f8338e1fe..0000000000 --- a/tests/auto/qtabbar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtabbar diff --git a/tests/auto/qtabbar/qtabbar.pro b/tests/auto/qtabbar/qtabbar.pro deleted file mode 100644 index befe5704ba..0000000000 --- a/tests/auto/qtabbar/qtabbar.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtabbar.cpp - - - diff --git a/tests/auto/qtabbar/tst_qtabbar.cpp b/tests/auto/qtabbar/tst_qtabbar.cpp deleted file mode 100644 index a1a8f3b0aa..0000000000 --- a/tests/auto/qtabbar/tst_qtabbar.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#include -#include - -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("sizeToSet"); - QTest::addColumn("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("tabToSet"); - QTest::addColumn("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("currentIndex"); - QTest::addColumn("deleteIndex"); - QTest::addColumn("spyCount"); - QTest::addColumn("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("tabElideMode"); - QTest::addColumn("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("usesArrows"); - QTest::addColumn("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(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("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(button)); - QTRY_VERIFY(!button->isHidden()); - QVERIFY(tabbar.tabButton(0, otherSide) == 0); - QCOMPARE(button->parent(), static_cast(&tabbar)); - QVERIFY(button->pos() != QPoint(0, 0)); - - QPushButton *button2 = new QPushButton; - tabbar.setTabButton(0, position, button2); - QVERIFY(button->isHidden()); -} - -typedef QList IntList; -Q_DECLARE_METATYPE(QTabBar::SelectionBehavior) -Q_DECLARE_METATYPE(IntList) -#define ONE(x) (IntList() << x) -void tst_QTabBar::selectionBehaviorOnRemove_data() -{ - QTest::addColumn("selectionBehavior"); - QTest::addColumn("tabs"); - QTest::addColumn("select"); - QTest::addColumn("remove"); - QTest::addColumn("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("shape"); - QTest::addColumn("tabs"); - QTest::addColumn("from"); - QTest::addColumn("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/qtableview/.gitignore b/tests/auto/qtableview/.gitignore deleted file mode 100644 index e2c6365d65..0000000000 --- a/tests/auto/qtableview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtableview diff --git a/tests/auto/qtableview/qtableview.pro b/tests/auto/qtableview/qtableview.pro deleted file mode 100644 index 408119a782..0000000000 --- a/tests/auto/qtableview/qtableview.pro +++ /dev/null @@ -1,7 +0,0 @@ -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/qtableview/tst_qtableview.cpp b/tests/auto/qtableview/tst_qtableview.cpp deleted file mode 100644 index 2242490a44..0000000000 --- a/tests/auto/qtableview/tst_qtableview.cpp +++ /dev/null @@ -1,4075 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#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(QObjectPrivate::get(TEST_VIEW_))->spans.checkConsistency()) -#else -#define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) (void)false -#endif - -typedef QList IntList; -Q_DECLARE_METATYPE(IntList) - -typedef QList 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 disabled_rows; - QSet 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("rowCount"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("tabKeyNavigation"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowHeight"); - QTest::addColumn("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 IntPair; -Q_DECLARE_METATYPE(IntPair) - -void tst_QTableView::moveCursor_data() -{ - QTest::addColumn("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("hideRow"); - QTest::addColumn("hideColumn"); - - QTest::addColumn("startRow"); - QTest::addColumn("startColumn"); - - QTest::addColumn("cursorMoveAction"); - QTest::addColumn("modifier"); - - QTest::addColumn("expectedRow"); - QTest::addColumn("expectedColumn"); - QTest::addColumn("moveRow"); - QTest::addColumn("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("hideRow"); - QTest::addColumn("hideColumn"); - QTest::addColumn("disableRows"); - QTest::addColumn("disableColumns"); - QTest::addColumn("span"); - - QTest::addColumn("startRow"); - QTest::addColumn("startColumn"); - QTest::addColumn("cursorMoveActions"); - QTest::addColumn("expectedRow"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("showRow"); // hide, then show - QTest::addColumn("hideRow"); // hide only - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("showColumn"); // hide, then show - QTest::addColumn("hideColumn"); // hide only - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("columnSpan"); - QTest::addColumn("hideRow"); - QTest::addColumn("hideColumn"); - QTest::addColumn("moveRowFrom"); - QTest::addColumn("moveRowTo"); - QTest::addColumn("moveColumnFrom"); - QTest::addColumn("moveColumnTo"); - QTest::addColumn("rowHeight"); - QTest::addColumn("columnWidth"); - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::addColumn("width"); - QTest::addColumn("height"); - QTest::addColumn("command"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("mode"); - QTest::addColumn("behavior"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("column"); - QTest::addColumn("mode"); - QTest::addColumn("behavior"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("hideRow"); - QTest::addColumn("hideColumn"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowHeight"); - QTest::addColumn("columnWidth"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("showGrid"); - QTest::addColumn("cellWidth"); - QTest::addColumn("cellHeight"); - QTest::addColumn("rowHeight"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("showGrid"); - QTest::addColumn("cellWidth"); - QTest::addColumn("cellHeight"); - QTest::addColumn("rowHeight"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("rowHeight"); - QTest::addColumn("row"); - QTest::addColumn("verticalScrollMode"); - QTest::addColumn("verticalScrollValue"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("rowHeight"); - QTest::addColumn("hiddenRows"); - QTest::addColumn("coordinate"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("rowHeights"); - QTest::addColumn("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("columnCount"); - QTest::addColumn("columnWidth"); - QTest::addColumn("column"); - QTest::addColumn("horizontalScrollMode"); - QTest::addColumn("horizontalScrollValue"); - QTest::addColumn("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("columnCount"); - QTest::addColumn("columnWidth"); - QTest::addColumn("hiddenColumns"); - QTest::addColumn("coordinate"); - QTest::addColumn("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("columnCount"); - QTest::addColumn("columnWidths"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("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("columnCount"); - QTest::addColumn("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("columnCount"); -} - -void tst_QTableView::sortingEnabled() -{ -// QFETCH(int, columnCount); -} - -void tst_QTableView::scrollTo_data() -{ - QTest::addColumn("verticalScrollMode"); - QTest::addColumn("horizontalScrollMode"); - QTest::addColumn("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("rowHeight"); - QTest::addColumn("columnWidth"); - QTest::addColumn("hiddenRow"); - QTest::addColumn("hiddenColumn"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("columnSpan"); - QTest::addColumn("horizontalScroll"); - QTest::addColumn("verticalScroll"); - QTest::addColumn("scrollHint"); - QTest::addColumn("expectedHorizontalScroll"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - - QTest::addColumn("rowHeight"); - QTest::addColumn("columnWidth"); - - QTest::addColumn("hiddenRow"); - QTest::addColumn("hiddenColumn"); - - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("columnSpan"); - QTest::addColumn("horizontalScroll"); - QTest::addColumn("verticalScroll"); - QTest::addColumn("x"); - QTest::addColumn("y"); - QTest::addColumn("expectedRow"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("hiddenRow"); - QTest::addColumn("hiddenColumn"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("rowSpan"); - QTest::addColumn("columnSpan"); - QTest::addColumn("expectedRowSpan"); - QTest::addColumn("expectedColumnSpan"); - QTest::addColumn("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 SpanList; -Q_DECLARE_METATYPE(SpanList) - -void tst_QTableView::spans_data() -{ - QTest::addColumn("rows"); - QTest::addColumn("columns"); - QTest::addColumn("spans"); - QTest::addColumn("hideRowLastRowOfFirstSpan"); - QTest::addColumn("pos"); - QTest::addColumn("expectedRowSpan"); - QTest::addColumn("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 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 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 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 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;iprocessEvents(); - - 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() << &item1 << &item2); - - - //setup the first table as a child of the first item - for ( int row = 0; row < 40; ++row ) { - item1.appendRow(QList() << 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() << 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("scrollMode"); - QTest::addColumn("delta"); - QTest::addColumn("horizontalPositon"); - QTest::addColumn("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 editor = qFindChild(&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 -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 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()); - 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/qtablewidget/.gitignore b/tests/auto/qtablewidget/.gitignore deleted file mode 100644 index 13a9c67c0a..0000000000 --- a/tests/auto/qtablewidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtablewidget diff --git a/tests/auto/qtablewidget/qtablewidget.pro b/tests/auto/qtablewidget/qtablewidget.pro deleted file mode 100644 index eff12c83dc..0000000000 --- a/tests/auto/qtablewidget/qtablewidget.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtablewidget.cpp diff --git a/tests/auto/qtablewidget/tst_qtablewidget.cpp b/tests/auto/qtablewidget/tst_qtablewidget.cpp deleted file mode 100644 index 6c32caadbb..0000000000 --- a/tests/auto/qtablewidget/tst_qtablewidget.cpp +++ /dev/null @@ -1,1500 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -#include - -//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 IntPair; -typedef QList IntList; -typedef QList 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"); - 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 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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("createItems"); - QTest::addColumn("hiddenRows"); - QTest::addColumn("hiddenColumns"); - QTest::addColumn("selectionRange"); - QTest::addColumn("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 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; rowrowCount(); ++row) { - bool hidden = false; - foreach (int hiddenRow, hiddenRows){ - if(hiddenRow == row){ - hidden = true; - break; - } - } - if (hidden) - continue; - - for (int column = 0; columncolumnCount(); ++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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("expectedRowCount"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("column"); - QTest::addColumn("expectedRowCount"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("row"); - QTest::addColumn("expectedRowCount"); - QTest::addColumn("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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("column"); - QTest::addColumn("expectedRowCount"); - QTest::addColumn("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("text"); - QTest::addColumn("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 item; - QPointer 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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("sortOrder"); - QTest::addColumn("sortColumn"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - QTest::addColumn("rows"); - QTest::addColumn("initialHidden"); - QTest::addColumn("expectedHidden"); - - QTest::newRow("ascending") - << 4 << 5 - << static_cast(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(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(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(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(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(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(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(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(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(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(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(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 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(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("rowCount"); - QTest::addColumn("columnCount"); - QTest::addColumn("sortOrder"); - QTest::addColumn("sortColumn"); - QTest::addColumn("initialValues"); - QTest::addColumn("row"); - QTest::addColumn("column"); - QTest::addColumn("newValue"); - QTest::addColumn("expectedValues"); - QTest::addColumn("expectedRows"); - QTest::addColumn("reorderingExpected"); - - QTest::newRow("2x1 no change (ascending)") - << 2 << 1 - << static_cast(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(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(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(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(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(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(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(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(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 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(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 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(dataChangedSpy.takeFirst().at(0)); - - QMap 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(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(0)); - table.setCellWidget(5, 5, &widget); - QCOMPARE(table.cellWidget(5, 5), &widget); - table.removeCellWidget(5, 5); - QCOMPARE(table.cellWidget(5, 5), static_cast(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/qtabwidget/.gitignore b/tests/auto/qtabwidget/.gitignore deleted file mode 100644 index d8f924a3df..0000000000 --- a/tests/auto/qtabwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtabwidget diff --git a/tests/auto/qtabwidget/qtabwidget.pro b/tests/auto/qtabwidget/qtabwidget.pro deleted file mode 100644 index d551c66500..0000000000 --- a/tests/auto/qtabwidget/qtabwidget.pro +++ /dev/null @@ -1,12 +0,0 @@ -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/qtabwidget/tst_qtabwidget.cpp b/tests/auto/qtabwidget/tst_qtabwidget.cpp deleted file mode 100644 index 6d356dee9b..0000000000 --- a/tests/auto/qtabwidget/tst_qtabwidget.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) -# include -#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 -# include -#elif defined(Q_WS_QWS) -# include -#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 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("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/qtextbrowser/.gitignore b/tests/auto/qtextbrowser/.gitignore deleted file mode 100644 index 1ec6f00de1..0000000000 --- a/tests/auto/qtextbrowser/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtextbrowser diff --git a/tests/auto/qtextbrowser/anchor.html b/tests/auto/qtextbrowser/anchor.html deleted file mode 100644 index e347a2bb4c..0000000000 --- a/tests/auto/qtextbrowser/anchor.html +++ /dev/null @@ -1,11 +0,0 @@ - - -Sample Anchor - - -

Click Me!

-

-Here's a destination to jump to. -

- - diff --git a/tests/auto/qtextbrowser/bigpage.html b/tests/auto/qtextbrowser/bigpage.html deleted file mode 100644 index 125c7a096e..0000000000 --- a/tests/auto/qtextbrowser/bigpage.html +++ /dev/null @@ -1,934 +0,0 @@ - -

-Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -Blah blah blah blah blah blah blah blah blah -

-

Paragraph with id

-Here's the bottom of the page. - diff --git a/tests/auto/qtextbrowser/firstpage.html b/tests/auto/qtextbrowser/firstpage.html deleted file mode 100644 index fa35fce92c..0000000000 --- a/tests/auto/qtextbrowser/firstpage.html +++ /dev/null @@ -1,2 +0,0 @@ -

Blah blah Link to second page blah -

Another link here: Link to third page diff --git a/tests/auto/qtextbrowser/pagewithbg.html b/tests/auto/qtextbrowser/pagewithbg.html deleted file mode 100644 index 07609a2b06..0000000000 --- a/tests/auto/qtextbrowser/pagewithbg.html +++ /dev/null @@ -1 +0,0 @@ -Page With BGThis page has a blue background diff --git a/tests/auto/qtextbrowser/pagewithimage.html b/tests/auto/qtextbrowser/pagewithimage.html deleted file mode 100644 index 49060d3792..0000000000 --- a/tests/auto/qtextbrowser/pagewithimage.html +++ /dev/null @@ -1 +0,0 @@ -

diff --git a/tests/auto/qtextbrowser/pagewithoutbg.html b/tests/auto/qtextbrowser/pagewithoutbg.html deleted file mode 100644 index 5a7f9f592b..0000000000 --- a/tests/auto/qtextbrowser/pagewithoutbg.html +++ /dev/null @@ -1 +0,0 @@ -This page has no background color diff --git a/tests/auto/qtextbrowser/qtextbrowser.pro b/tests/auto/qtextbrowser/qtextbrowser.pro deleted file mode 100644 index ae5177686b..0000000000 --- a/tests/auto/qtextbrowser/qtextbrowser.pro +++ /dev/null @@ -1,15 +0,0 @@ -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/qtextbrowser/secondpage.html b/tests/auto/qtextbrowser/secondpage.html deleted file mode 100644 index 39018a71b2..0000000000 --- a/tests/auto/qtextbrowser/secondpage.html +++ /dev/null @@ -1 +0,0 @@ -

blub blub Link to third page from second page diff --git a/tests/auto/qtextbrowser/subdir/index.html b/tests/auto/qtextbrowser/subdir/index.html deleted file mode 100644 index 95593cc925..0000000000 --- a/tests/auto/qtextbrowser/subdir/index.html +++ /dev/null @@ -1 +0,0 @@ -This is a dummy, do not remove me! diff --git a/tests/auto/qtextbrowser/thirdpage.html b/tests/auto/qtextbrowser/thirdpage.html deleted file mode 100644 index 215dc08aa0..0000000000 --- a/tests/auto/qtextbrowser/thirdpage.html +++ /dev/null @@ -1 +0,0 @@ -

this is the third page... diff --git a/tests/auto/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/qtextbrowser/tst_qtextbrowser.cpp deleted file mode 100644 index a1592e5e2b..0000000000 --- a/tests/auto/qtextbrowser/tst_qtextbrowser.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -#include -#include - -//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"); - 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(""); - 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("

Hello Link" - "

Blah

"); - 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("foobar"); - 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("link"); - 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/qtextedit/.gitignore b/tests/auto/qtextedit/.gitignore deleted file mode 100644 index 8665a3a3d3..0000000000 --- a/tests/auto/qtextedit/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tst_qtextedit -foo.png diff --git a/tests/auto/qtextedit/fullWidthSelection/centered-fully-selected.png b/tests/auto/qtextedit/fullWidthSelection/centered-fully-selected.png deleted file mode 100644 index ced6eb6e5b..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/centered-fully-selected.png and /dev/null differ diff --git a/tests/auto/qtextedit/fullWidthSelection/centered-partly-selected.png b/tests/auto/qtextedit/fullWidthSelection/centered-partly-selected.png deleted file mode 100644 index 481b99c7fc..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/centered-partly-selected.png and /dev/null differ diff --git a/tests/auto/qtextedit/fullWidthSelection/last-char-on-line.png b/tests/auto/qtextedit/fullWidthSelection/last-char-on-line.png deleted file mode 100644 index 292d3f9d4c..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/last-char-on-line.png and /dev/null differ diff --git a/tests/auto/qtextedit/fullWidthSelection/last-char-on-parag.png b/tests/auto/qtextedit/fullWidthSelection/last-char-on-parag.png deleted file mode 100644 index 69b72ede09..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/last-char-on-parag.png and /dev/null differ diff --git a/tests/auto/qtextedit/fullWidthSelection/multiple-full-width-lines.png b/tests/auto/qtextedit/fullWidthSelection/multiple-full-width-lines.png deleted file mode 100644 index 467b91e6e0..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/multiple-full-width-lines.png and /dev/null differ diff --git a/tests/auto/qtextedit/fullWidthSelection/nowrap_long.png b/tests/auto/qtextedit/fullWidthSelection/nowrap_long.png deleted file mode 100644 index cce921b0cc..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/nowrap_long.png and /dev/null differ diff --git a/tests/auto/qtextedit/fullWidthSelection/single-full-width-line.png b/tests/auto/qtextedit/fullWidthSelection/single-full-width-line.png deleted file mode 100644 index 937494ac3c..0000000000 Binary files a/tests/auto/qtextedit/fullWidthSelection/single-full-width-line.png and /dev/null differ diff --git a/tests/auto/qtextedit/qtextedit.pro b/tests/auto/qtextedit/qtextedit.pro deleted file mode 100644 index f29a2d2850..0000000000 --- a/tests/auto/qtextedit/qtextedit.pro +++ /dev/null @@ -1,18 +0,0 @@ -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/qtextedit/tst_qtextedit.cpp b/tests/auto/qtextedit/tst_qtextedit.cpp deleted file mode 100644 index 481bda962a..0000000000 --- a/tests/auto/qtextedit/tst_qtextedit.cpp +++ /dev/null @@ -1,2391 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -//Used in copyAvailable -typedef QPair keyPairType; -typedef QList pairListType; -Q_DECLARE_METATYPE(pairListType); -Q_DECLARE_METATYPE(keyPairType); -Q_DECLARE_METATYPE(QList); -Q_DECLARE_METATYPE(QList); - -#ifdef Q_WS_MAC -#include -#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() << 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 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 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("Some Bold Text"); - 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("Second para"); - 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("

Foo

"); - 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("input"); - QTest::addColumn("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("Blah"); - 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("keystrokes"); - QTest::addColumn >("copyAvailable"); - QTest::addColumn("function"); - - pairListType keystrokes; - QList 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, 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;idocument()->isUndoAvailable()); - QVERIFY(!ed->document()->isRedoAvailable()); - ed->setPlainText("Foobar"); - QVERIFY(!ed->document()->isUndoAvailable()); - QVERIFY(!ed->document()->isRedoAvailable()); - ed->setHtml("

bleh

"); - 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(&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("testString"); - QTest::addColumn("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("
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() << 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() << sel); - - QList 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("

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("
Foo
"); - - 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("bold bold")); - 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("cursorFrom"); - QTest::addColumn("cursorTo"); - QTest::addColumn("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 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 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(image.scanLine(y)); - const QRgb * const secondLine = reinterpret_cast(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(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("

QTextEdit is an "); - - QMimeData mimeData; - mimeData.setData("application/x-qrichtext", richtext); - - static_cast(ed)->publicInsertFromMimeData(&mimeData); - - QCOMPARE(ed->toPlainText(), QString::fromLatin1(" QTextEdit is an ")); - ed->clear(); - - richtext = " QTextEdit is an "; - mimeData.setData("application/x-qrichtext", richtext); - - static_cast(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 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("logical"); - QTest::addColumn("basicDir"); - QTest::addColumn >("positionList"); - - QTest::newRow("Latin text") - << QString::fromUtf8("abc") - << (int) QChar::DirL - << (QList() << 0 << 1 << 2 << 3); - QTest::newRow("Hebrew text, one item") - << QString::fromUtf8("\327\220\327\221\327\222") - << (int) QChar::DirR - << (QList() << 0 << 1 << 2 << 3); - QTest::newRow("Hebrew text after Latin text") - << QString::fromUtf8("abc\327\220\327\221\327\222") - << (int) QChar::DirL - << (QList() << 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() << 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() << 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() << 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() << 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() << 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, 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 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/qtoolbar/.gitignore b/tests/auto/qtoolbar/.gitignore deleted file mode 100644 index 971c9f9dfe..0000000000 --- a/tests/auto/qtoolbar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtoolbar diff --git a/tests/auto/qtoolbar/qtoolbar.pro b/tests/auto/qtoolbar/qtoolbar.pro deleted file mode 100644 index b340097d81..0000000000 --- a/tests/auto/qtoolbar/qtoolbar.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -QT += widgets widgets-private -QT += gui-private -SOURCES += tst_qtoolbar.cpp - - - diff --git a/tests/auto/qtoolbar/tst_qtoolbar.cpp b/tests/auto/qtoolbar/tst_qtoolbar.cpp deleted file mode 100644 index eb043aced8..0000000000 --- a/tests/auto/qtoolbar/tst_qtoolbar.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/**************************************************************************** -** -** 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 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//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"); - qRegisterMetaType("Qt::Orientation"); - qRegisterMetaType("Qt::ToolBarAreas"); - qRegisterMetaType("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(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(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(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(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(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(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(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(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(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(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(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(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(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 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 extensions = tb.findChildren(); - - 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(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 extensions = tb.findChildren(); - - 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(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(tb.childAt(rect1.center())); - QVERIFY(button1 != 0); - } - if (!rect02.isValid()) { - button2 = qobject_cast(tb.childAt(rect2.center())); - QVERIFY(button2 != 0); - } - if (!rect03.isValid()) { - button3 = qobject_cast(tb.childAt(rect3.center())); - QVERIFY(button3 != 0); - } - if (!rect04.isValid()) { - button4 = qobject_cast(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 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 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(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(&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/qtoolbox/.gitignore b/tests/auto/qtoolbox/.gitignore deleted file mode 100644 index f586175dcb..0000000000 --- a/tests/auto/qtoolbox/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtoolbox diff --git a/tests/auto/qtoolbox/qtoolbox.pro b/tests/auto/qtoolbox/qtoolbox.pro deleted file mode 100644 index 24f3ea6cb9..0000000000 --- a/tests/auto/qtoolbox/qtoolbox.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtoolbox.cpp - - - diff --git a/tests/auto/qtoolbox/tst_qtoolbox.cpp b/tests/auto/qtoolbox/tst_qtoolbox.cpp deleted file mode 100644 index 2288eee5f4..0000000000 --- a/tests/auto/qtoolbox/tst_qtoolbox.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include - - -//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 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/qtoolbutton/.gitignore b/tests/auto/qtoolbutton/.gitignore deleted file mode 100644 index 91e11101e1..0000000000 --- a/tests/auto/qtoolbutton/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtoolbutton diff --git a/tests/auto/qtoolbutton/qtoolbutton.pro b/tests/auto/qtoolbutton/qtoolbutton.pro deleted file mode 100644 index 5f082682ad..0000000000 --- a/tests/auto/qtoolbutton/qtoolbutton.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtoolbutton.cpp diff --git a/tests/auto/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/qtoolbutton/tst_qtoolbutton.cpp deleted file mode 100644 index 0e21ea6611..0000000000 --- a/tests/auto/qtoolbutton/tst_qtoolbutton.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include - -//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 *"); - 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(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(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/qtooltip/.gitignore b/tests/auto/qtooltip/.gitignore deleted file mode 100644 index 552a2a5dc6..0000000000 --- a/tests/auto/qtooltip/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtooltip diff --git a/tests/auto/qtooltip/qtooltip.pro b/tests/auto/qtooltip/qtooltip.pro deleted file mode 100644 index 4da8917921..0000000000 --- a/tests/auto/qtooltip/qtooltip.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtooltip.cpp - -CONFIG += insignificant_test # QTBUG-21402 diff --git a/tests/auto/qtooltip/tst_qtooltip.cpp b/tests/auto/qtooltip/tst_qtooltip.cpp deleted file mode 100644 index 3ff31ead62..0000000000 --- a/tests/auto/qtooltip/tst_qtooltip.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -//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("key"); - QTest::addColumn("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 - -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/qtreeview/.gitignore b/tests/auto/qtreeview/.gitignore deleted file mode 100644 index 4e72cdb157..0000000000 --- a/tests/auto/qtreeview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtreeview diff --git a/tests/auto/qtreeview/qtreeview.pro b/tests/auto/qtreeview/qtreeview.pro deleted file mode 100644 index ea53bbdc1d..0000000000 --- a/tests/auto/qtreeview/qtreeview.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtreeview.cpp diff --git a/tests/auto/qtreeview/tst_qtreeview.cpp b/tests/auto/qtreeview/tst_qtreeview.cpp deleted file mode 100644 index d6cdf00218..0000000000 --- a/tests/auto/qtreeview/tst_qtreeview.cpp +++ /dev/null @@ -1,3942 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -//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 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"); -} - -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(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("row"); - QTest::addColumn("column"); - QTest::addColumn("indexRow"); - QTest::addColumn("indexColumn"); - QTest::addColumn("parentIndexRow"); - QTest::addColumn("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("dragDropMode"); - QTest::addColumn("acceptDrops"); - QTest::addColumn("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("dragEnabled"); - QTest::addColumn("acceptDrops"); - QTest::addColumn("dragDropMode"); - QTest::addColumn("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("editTriggers"); - QTest::addColumn("triggeredTrigger"); - QTest::addColumn("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(&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(&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() - << 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(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(widget)); - - QCOMPARE(widget->parentWidget(), view.viewport()); - QCOMPARE(widget->geometry(), view.visualRect(index).intersect(widget->geometry())); - QCOMPARE(widget->toPlainText(), text); -} - -void tst_QTreeView::itemDelegate() -{ - QPointer oldDelegate; - QPointer otherItemDelegate; - - { - QTreeView view; - QVERIFY(qobject_cast(view.itemDelegate())); - QPointer 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() - << 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 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 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(view.viewport())); - view.openPersistentEditor(view.model()->index(0, 0)); - QVERIFY(qFindChild(view.viewport())); - - view.closePersistentEditor(view.model()->index(0, 0)); - QVERIFY(!qFindChild(view.viewport())->isVisible()); - - qApp->sendPostedEvents(0, QEvent::DeferredDelete); - QVERIFY(!qFindChild(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 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("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(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(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(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(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(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(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(args.at(0)), a); - args = expandedSpy.takeFirst(); - QCOMPARE(qvariant_cast(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(args.at(0)), a); - args = collapsedSpy.takeFirst(); - QCOMPARE(qvariant_cast(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 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 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("uniformRowHeights"); - QTest::addColumn("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 PointList; -Q_DECLARE_METATYPE(PointList) - -void tst_QTreeView::setSelection_data() -{ - QTest::addColumn("selectionRect"); - QTest::addColumn("selectionMode"); - QTest::addColumn("selectionCommand"); - QTest::addColumn("expectedItems"); - QTest::addColumn("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 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(&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() << &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("mousePressPos"); - QTest::addColumn("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("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 children; - QList 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 > oldListPath; - for (int i = 0; i < oldList.count(); ++i) { - QModelIndex idx = oldList.at(i); - QStack 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 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(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(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(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(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("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 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(&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() - << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") ); - QStandardItem *par1 = new QStandardItem("Beginning HasChildren"); - model.appendRow(QList() - << par1 << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") ); - model.appendRow(QList() - << 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() - << new QStandardItem("Beginning") << checkable << checked << new QStandardItem("End") ); - model.appendRow(QList() - << new QStandardItem("Beginning Last") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") ); - - par1->appendRow(QList() - << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") ); - QStandardItem *par2 = new QStandardItem("Beginning HasChildren"); - par1->appendRow(QList() - << par2 << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") ); - par2->appendRow(QList() - << 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() - << par3 << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") ); - par3->appendRow(QList() - << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Asser") ); - view.setRowHidden(0, par3->index(), true); - par1->appendRow(QList() - << 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() << item0); - view.setModel(&model2); - QApplication::processEvents(); - QTRY_VERIFY(delegate.count >= 1); - QApplication::processEvents(); - - QStandardItem *item00 = new QStandardItem("OnlyOne Last"); - item0->appendRow(QList() << 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() << 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() << 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() << 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() << 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() << item00); - item01 = new QStandardItem("Assert"); - item0->appendRow(QList() << item01); - view.setRowHidden(1, item0->index(), true); - view.expandAll(); - QStandardItem *item02 = new QStandardItem("OnlyOne Last"); - item0->appendRow(QList() << 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 ¤t, 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() << &root << &root2); - root.appendRow( QList() << &subitem << &subitem2); - subitem.appendRow( QList() << &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 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() << &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() << &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 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 paintedIndexes; - }; - - QTreeView view; - QStandardItemModel model; - view.setModel(&model); - MyDelegate delegate; - view.setItemDelegate(&delegate); - QStandardItem root0("root0"), root1("root1"); - model.invisibleRootItem()->appendRow(QList() << &root0 << &root1); - QStandardItem sub0("sub0"), sub00("sub00"); - root0.appendRow(QList() << &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() << &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 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(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 ¤t,const QModelIndex &) - { - if (m_block) - return; - - if (current.isValid()) { - int selectedRow = current.row(); - quint32 parentRowPlusOne = static_cast(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/qtreewidget/.gitignore b/tests/auto/qtreewidget/.gitignore deleted file mode 100644 index 08c63b4b52..0000000000 --- a/tests/auto/qtreewidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtreewidget diff --git a/tests/auto/qtreewidget/qtreewidget.pro b/tests/auto/qtreewidget/qtreewidget.pro deleted file mode 100644 index 763c0d3c63..0000000000 --- a/tests/auto/qtreewidget/qtreewidget.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtreewidget.cpp diff --git a/tests/auto/qtreewidget/tst_qtreewidget.cpp b/tests/auto/qtreewidget/tst_qtreewidget.cpp deleted file mode 100644 index 5e1faf97c4..0000000000 --- a/tests/auto/qtreewidget/tst_qtreewidget.cpp +++ /dev/null @@ -1,3349 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//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 IntList; -typedef QList ListIntList; - -Q_DECLARE_METATYPE(IntList) -Q_DECLARE_METATYPE(ListIntList) -Q_DECLARE_METATYPE(QModelIndex) -Q_DECLARE_METATYPE(Qt::Orientation) - -typedef QTreeWidgetItem TreeItem; -typedef QList TreeItemList; - -Q_DECLARE_METATYPE(QTreeWidgetItem*) -Q_DECLARE_METATYPE(TreeItemList) - -tst_QTreeWidget::tst_QTreeWidget(): testWidget(0) -{ -} - -tst_QTreeWidget::~tst_QTreeWidget() -{ -} - -void tst_QTreeWidget::initTestCase() -{ - qMetaTypeId(); - qMetaTypeId(); - qRegisterMetaType("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 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(0)); - QCOMPARE(tree.indexOfTopLevelItem(ti), i); - QCOMPARE(ti->parent(), static_cast(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("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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(0)); -} - -void tst_QTreeWidget::editItem_data() -{ - QTest::addColumn("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(&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(args.at(0)), item); - QCOMPARE(qvariant_cast(args.at(1)), col); - } else { - QVERIFY(!(item->flags() & Qt::ItemIsEditable)); - } - } - } -} - -void tst_QTreeWidget::takeItem_data() -{ - QTest::addColumn("index"); - QTest::addColumn("topLevel"); - QTest::addColumn("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("childCount"); - QTest::addColumn("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("topLevel"); - QTest::addColumn("children"); - QTest::addColumn("closeTopLevel"); - QTest::addColumn("selectedItems"); - QTest::addColumn("hiddenItems"); - QTest::addColumn("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; tsetText(0, QString("top%1").arg(t)); - for (int c=0; csetText(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; itopLevelItemCount(); ++i) { - if (closeTopLevel) - testWidget->collapseItem(testWidget->topLevelItem(i)); - else - testWidget->expandItem(testWidget->topLevelItem(i)); - } - - // check selectedItems - QList 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; ttopLevelItemCount(); ++t) { - QTreeWidgetItem *top = testWidget->topLevelItem(t); - if (testWidget->isItemSelected(top) && !testWidget->isItemHidden(top)) - QVERIFY(sel.contains(top)); - for (int c=0; cchildCount(); ++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(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("column"); - QTest::addColumn("topLevelIndex"); - QTest::addColumn("childIndex"); - QTest::addColumn("topLevelText"); - QTest::addColumn("childText"); - QTest::addColumn("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("topLevelIndex"); - QTest::addColumn("topLevelCount"); - QTest::addColumn("childIndex"); - QTest::addColumn("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("column"); - QTest::addColumn("topLevelText"); - QTest::addColumn("childText"); - QTest::addColumn("pattern"); - QTest::addColumn("resultCount"); - QTest::addColumn("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 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 items = testWidget->findItems("400", Qt::MatchExactly|Qt::MatchRecursive, 1); - QCOMPARE(items.count(), 1); -} - -void tst_QTreeWidget::sortItems_data() -{ - QTest::addColumn("column"); - QTest::addColumn("order"); - QTest::addColumn("topLevelText"); - QTest::addColumn("childText"); - QTest::addColumn("topLevelResult"); - QTest::addColumn("childResult"); - QTest::addColumn("expectedTopRows"); - QTest::addColumn("expectedChildRows"); - - QTest::newRow("ascending order") - << 0 - << static_cast(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(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 tops; - for (int r = 0; r < model->rowCount(QModelIndex()); ++r) { - QPersistentModelIndex p = model->index(r, 0, QModelIndex()); - tops << p; - } - QList 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(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("topLevelCount"); - QTest::addColumn("childCount"); - QTest::addColumn("grandChildCount"); - - QTest::addColumn("deleteTopLevelCount"); - QTest::addColumn("deleteChildCount"); - QTest::addColumn("deleteGrandChildCount"); - - QTest::addColumn("expectedTopLevelCount"); - QTest::addColumn("expectedChildCount"); - QTest::addColumn("expectedGrandChildCount"); - - QTest::addColumn("persistentRow"); - QTest::addColumn("persistentColumn"); - QTest::addColumn("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("text"); - QTest::addColumn("toolTip"); - QTest::addColumn("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("initialText"); - QTest::addColumn("insertText"); - QTest::addColumn("insertTopLevelIndex"); - QTest::addColumn("expectedTopLevelIndex"); - QTest::addColumn("insertChildIndex"); - QTest::addColumn("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 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(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 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 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(0)); - QCOMPARE(taken.at(i)->treeWidget(), static_cast(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()); - QCOMPARE(item->childCount(), count); - } - - // add many at a time - const int count = 10; - for (int i = 0; i < 100; i += count) { - QList 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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(args.at(0)), item); - QCOMPARE(qvariant_cast(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(item->data(j, Qt::DisplayRole)), text); - QCOMPARE(qvariant_cast(item->data(j, Qt::DecorationRole)), icon); - QCOMPARE(qvariant_cast(item->data(j, Qt::ToolTipRole)), toolTip); - QCOMPARE(qvariant_cast(item->data(j, Qt::StatusTipRole)), statusTip); - QCOMPARE(qvariant_cast(item->data(j, Qt::WhatsThisRole)), whatsThis); - QCOMPARE(qvariant_cast(item->data(j, Qt::SizeHintRole)), sizeHint); - QCOMPARE(qvariant_cast(item->data(j, Qt::FontRole)), font); - QCOMPARE(qvariant_cast(item->data(j, Qt::TextAlignmentRole)), int(textAlignment)); - QCOMPARE(qvariant_cast(item->data(j, Qt::BackgroundColorRole)), QBrush(backgroundColor)); - QCOMPARE(qvariant_cast(item->data(j, Qt::BackgroundRole)), QBrush(backgroundColor)); - QCOMPARE(qvariant_cast(item->data(j, Qt::TextColorRole)), textColor); - QCOMPARE(qvariant_cast(item->data(j, Qt::CheckStateRole)), int(checkState)); - - item->setBackground(j, pixmap); - QCOMPARE(item->background(j).texture(), pixmap); - QCOMPARE(qvariant_cast(item->data(j, Qt::BackgroundRole)).texture(), pixmap); - args = itemChangedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), item); - QCOMPARE(qvariant_cast(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 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(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(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(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(&tree); - QVERIFY(editor != 0); - tree.closePersistentEditor(item, col); - } - } - } - } -} - -void tst_QTreeWidget::insertItemsWithSorting_data() -{ - QTest::addColumn("sortOrder"); - QTest::addColumn("initialItems"); - QTest::addColumn("insertItems"); - QTest::addColumn("expectedItems"); - QTest::addColumn("expectedRows"); - - QTest::newRow("() + (a) = (a)") - << static_cast(Qt::AscendingOrder) - << QStringList() - << (QStringList() << "a") - << (QStringList() << "a") - << IntList(); - QTest::newRow("() + (c, b, a) = (a, b, c)") - << static_cast(Qt::AscendingOrder) - << QStringList() - << (QStringList() << "c" << "b" << "a") - << (QStringList() << "a" << "b" << "c") - << IntList(); - QTest::newRow("() + (a, b, c) = (c, b, a)") - << static_cast(Qt::DescendingOrder) - << QStringList() - << (QStringList() << "a" << "b" << "c") - << (QStringList() << "c" << "b" << "a") - << IntList(); - QTest::newRow("(a) + (b) = (a, b)") - << static_cast(Qt::AscendingOrder) - << QStringList("a") - << (QStringList() << "b") - << (QStringList() << "a" << "b") - << (IntList() << 0); - QTest::newRow("(a) + (b) = (b, a)") - << static_cast(Qt::DescendingOrder) - << QStringList("a") - << (QStringList() << "b") - << (QStringList() << "b" << "a") - << (IntList() << 1); - QTest::newRow("(a, c, b) + (d) = (a, b, c, d)") - << static_cast(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(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(Qt::AscendingOrder) - << QStringList() - << ascendingItems - << ascendingItems - << IntList(); - QTest::newRow("(sorted items) + () = (sorted items)") - << static_cast(Qt::AscendingOrder) - << ascendingItems - << QStringList() - << ascendingItems - << ascendingRows; - QTest::newRow("() + (ascending items) = (reverse items)") - << static_cast(Qt::DescendingOrder) - << QStringList() - << ascendingItems - << reverseItems - << IntList(); - QTest::newRow("(reverse items) + () = (ascending items)") - << static_cast(Qt::AscendingOrder) - << reverseItems - << QStringList() - << ascendingItems - << ascendingRows; - QTest::newRow("(reverse items) + () = (reverse items)") - << static_cast(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(sortOrder)); - for (int i = 0; i < initialItems.count(); ++i) - w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i))); - - QAbstractItemModel *model = w.model(); - QList 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 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 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("parentText"); - QTest::addColumn("childText"); - QTest::addColumn("parentResult"); - QTest::addColumn("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 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(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 parents; - for (int i = 0; i < model->rowCount(QModelIndex()); ++i) { - QPersistentModelIndex parent = model->index(i, 0, QModelIndex()); - parents << parent; - } - QList 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("sortOrder"); - QTest::addColumn("initialItems"); - QTest::addColumn("itemIndex"); - QTest::addColumn("newValue"); - QTest::addColumn("expectedItems"); - QTest::addColumn("expectedRows"); - QTest::addColumn("reorderingExpected"); - - QTest::newRow("change a to b in (a)") - << static_cast(Qt::AscendingOrder) - << (QStringList() << "a") - << 0 << "b" - << (QStringList() << "b") - << (IntList() << 0) - << false; - QTest::newRow("change a to b in (a, c)") - << static_cast(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(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(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(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(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(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(sortOrder)); - for (int i = 0; i < initialItems.count(); ++i) - w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i))); - - QAbstractItemModel *model = w.model(); - QList 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("sortOrder"); - QTest::addColumn("initialItems"); - QTest::addColumn("itemIndex"); - QTest::addColumn("newValue"); - QTest::addColumn("expectedItems"); - QTest::addColumn("expectedRows"); - QTest::addColumn("reorderingExpected"); - QTest::addColumn("forceChange"); - - QTest::newRow("change a to c in (a, c, c, c, e)") - << static_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(sortOrder)); - for (int i = 0; i < initialItems.count(); ++i) - w.addTopLevelItem(new StableItem(QStringList() << initialItems.at(i))); - - QAbstractItemModel *model = w.model(); - QList 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(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("sortOrder"); - QTest::addColumn("itemTexts"); - QTest::addColumn >("expectedIndexes"); - - QTest::newRow("three ascending") - << int(Qt::AscendingOrder) - << (QStringList() << "A" << "B" << "C") - << (QList() << 0 << 1 << 2); - - - QTest::newRow("three descending") - << int(Qt::DescendingOrder) - << (QStringList() << "A" << "B" << "C") - << (QList() << 2 << 1 << 0); -} - -void tst_QTreeWidget::sortedIndexOfChild() -{ - QFETCH(int, sortOrder); - QFETCH(QStringList, itemTexts); - QFETCH(QList, expectedIndexes); - - QTreeWidget tw; - QList 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 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 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; jcolumnCount() - 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 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/qtreewidgetitemiterator/.gitignore b/tests/auto/qtreewidgetitemiterator/.gitignore deleted file mode 100644 index 6595518de7..0000000000 --- a/tests/auto/qtreewidgetitemiterator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtreewidgetitemiterator diff --git a/tests/auto/qtreewidgetitemiterator/qtreewidgetitemiterator.pro b/tests/auto/qtreewidgetitemiterator/qtreewidgetitemiterator.pro deleted file mode 100644 index de7762e773..0000000000 --- a/tests/auto/qtreewidgetitemiterator/qtreewidgetitemiterator.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qtreewidgetitemiterator.cpp - - diff --git a/tests/auto/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp b/tests/auto/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp deleted file mode 100644 index 92a1b7cce3..0000000000 --- a/tests/auto/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp +++ /dev/null @@ -1,1243 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include - -//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("start"); - QTest::addColumn("iteratorflags"); - QTest::addColumn("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("start"); - QTest::addColumn("addition"); - QTest::addColumn("iteratorflags"); - QTest::addColumn("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("start"); - QTest::addColumn("subtraction"); - QTest::addColumn("iteratorflags"); - QTest::addColumn("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("topLevelItems"); - QTest::addColumn("childItems"); - QTest::addColumn("grandChildItems"); - QTest::addColumn("iteratorflags"); - QTest::addColumn("removeindex"); - QTest::addColumn("expecteditemindex"); - QTest::addColumn("expecteditemvalue"); - QTest::addColumn("expectedUpdatedCurrent"); - QTest::addColumn("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("topLevelItems"); - QTest::addColumn("childItems"); - QTest::addColumn("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("removeindex"); // The index of the node we want to remove - QTest::addColumn("iterator_initial_index"); // The new expected index of - QTest::addColumn("iterator_advance_after_removal"); - QTest::addColumn("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("indextoitem"); - QTest::addColumn("iteratorflags"); - QTest::addColumn("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(0)); -} - -QTEST_MAIN(tst_QTreeWidgetItemIterator) -#include "tst_qtreewidgetitemiterator.moc" diff --git a/tests/auto/qundogroup/.gitignore b/tests/auto/qundogroup/.gitignore deleted file mode 100644 index bc3e8c4691..0000000000 --- a/tests/auto/qundogroup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qundogroup diff --git a/tests/auto/qundogroup/qundogroup.pro b/tests/auto/qundogroup/qundogroup.pro deleted file mode 100644 index c2b6ceb038..0000000000 --- a/tests/auto/qundogroup/qundogroup.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += qttest_p4 -QT += widgets -SOURCES += tst_qundogroup.cpp -TARGET = tst_qundogroup diff --git a/tests/auto/qundogroup/testdata/qundogroup.ts b/tests/auto/qundogroup/testdata/qundogroup.ts deleted file mode 100644 index a059bcb486..0000000000 --- a/tests/auto/qundogroup/testdata/qundogroup.ts +++ /dev/null @@ -1,25 +0,0 @@ - - - - - QUndoGroup - - Undo %1 - undo-prefix %1 undo-suffix - - - Undo - Default text for undo action - Undo-default-text - - - Redo %1 - redo-prefix %1 redo-suffix - - - Redo - Default text for redo action - Redo-default-text - - - diff --git a/tests/auto/qundogroup/tst_qundogroup.cpp b/tests/auto/qundogroup/tst_qundogroup.cpp deleted file mode 100644 index 6d51252e22..0000000000 --- a/tests/auto/qundogroup/tst_qundogroup.cpp +++ /dev/null @@ -1,668 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -// 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(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() << &stack1); - - QUndoStack stack2; - group.addStack(&stack2); - QCOMPARE(group.stacks(), QList() << &stack1 << &stack2); - - group.addStack(&stack1); - QCOMPARE(group.stacks(), QList() << &stack1 << &stack2); - - group.removeStack(&stack1); - QCOMPARE(group.stacks(), QList() << &stack2); - - group.removeStack(&stack1); - QCOMPARE(group.stacks(), QList() << &stack2); - - group.removeStack(&stack2); - QCOMPARE(group.stacks(), QList()); -} - -void tst_QUndoGroup::deleteStack() -{ - QUndoGroup group; - - QUndoStack *stack1 = new QUndoStack(&group); - QCOMPARE(group.stacks(), QList() << stack1); - QCOMPARE(group.activeStack(), (QUndoStack*)0); - - stack1->setActive(); - QCOMPARE(group.activeStack(), stack1); - - QUndoStack *stack2 = new QUndoStack(&group); - QCOMPARE(group.stacks(), QList() << stack1 << stack2); - QCOMPARE(group.activeStack(), stack1); - - QUndoStack *stack3 = new QUndoStack(&group); - QCOMPARE(group.stacks(), QList() << stack1 << stack2 << stack3); - QCOMPARE(group.activeStack(), stack1); - - delete stack2; - QCOMPARE(group.stacks(), QList() << stack1 << stack3); - QCOMPARE(group.activeStack(), stack1); - - delete stack1; - QCOMPARE(group.stacks(), QList() << 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()); - 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/qundostack/.gitignore b/tests/auto/qundostack/.gitignore deleted file mode 100644 index f8faf2771f..0000000000 --- a/tests/auto/qundostack/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qundostack diff --git a/tests/auto/qundostack/qundostack.pro b/tests/auto/qundostack/qundostack.pro deleted file mode 100644 index c8cfb70059..0000000000 --- a/tests/auto/qundostack/qundostack.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += qttest_p4 -QT += widgets -SOURCES += tst_qundostack.cpp -TARGET = tst_qundostack diff --git a/tests/auto/qundostack/testdata/qundostack.ts b/tests/auto/qundostack/testdata/qundostack.ts deleted file mode 100644 index 4584036af2..0000000000 --- a/tests/auto/qundostack/testdata/qundostack.ts +++ /dev/null @@ -1,25 +0,0 @@ - - - - - QUndoStack - - Undo %1 - undo-prefix %1 undo-suffix - - - Undo - Default text for undo action - Undo-default-text - - - Redo %1 - redo-prefix %1 redo-suffix - - - Redo - Default text for redo action - Redo-default-text - - - diff --git a/tests/auto/qundostack/tst_qundostack.cpp b/tests/auto/qundostack/tst_qundostack.cpp deleted file mode 100644 index 834c2d5d50..0000000000 --- a/tests/auto/qundostack/tst_qundostack.cpp +++ /dev/null @@ -1,3039 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -//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(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/qwidget/.gitignore b/tests/auto/qwidget/.gitignore deleted file mode 100644 index 82a0ac9eba..0000000000 --- a/tests/auto/qwidget/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qwidget diff --git a/tests/auto/qwidget/geometry-fullscreen.dat b/tests/auto/qwidget/geometry-fullscreen.dat deleted file mode 100644 index 9802ee8b9e..0000000000 Binary files a/tests/auto/qwidget/geometry-fullscreen.dat and /dev/null differ diff --git a/tests/auto/qwidget/geometry-maximized.dat b/tests/auto/qwidget/geometry-maximized.dat deleted file mode 100644 index df5bc2f94e..0000000000 Binary files a/tests/auto/qwidget/geometry-maximized.dat and /dev/null differ diff --git a/tests/auto/qwidget/geometry.dat b/tests/auto/qwidget/geometry.dat deleted file mode 100644 index e5dcb2dc44..0000000000 Binary files a/tests/auto/qwidget/geometry.dat and /dev/null differ diff --git a/tests/auto/qwidget/qwidget.pro b/tests/auto/qwidget/qwidget.pro deleted file mode 100644 index 9c34e0c254..0000000000 --- a/tests/auto/qwidget/qwidget.pro +++ /dev/null @@ -1,23 +0,0 @@ -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/qwidget/qwidget.qrc b/tests/auto/qwidget/qwidget.qrc deleted file mode 100644 index 1399c4c9db..0000000000 --- a/tests/auto/qwidget/qwidget.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - geometry.dat - geometry-maximized.dat - geometry-fullscreen.dat - - diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data0.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Motif_data0.qsnap deleted file mode 100644 index b3473cdefe..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data0.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data1.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Motif_data1.qsnap deleted file mode 100644 index 10007733ca..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data1.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data2.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Motif_data2.qsnap deleted file mode 100644 index cde5964a30..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data2.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data3.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Motif_data3.qsnap deleted file mode 100644 index 23ea1410e4..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Motif_data3.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data0.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Windows_data0.qsnap deleted file mode 100644 index a8918c1d1b..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data0.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data1.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Windows_data1.qsnap deleted file mode 100644 index 0981cf5dd1..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data1.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data2.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Windows_data2.qsnap deleted file mode 100644 index 75d09136cf..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data2.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data3.qsnap b/tests/auto/qwidget/testdata/paintEvent/res_Windows_data3.qsnap deleted file mode 100644 index f58f74d030..0000000000 Binary files a/tests/auto/qwidget/testdata/paintEvent/res_Windows_data3.qsnap and /dev/null differ diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp deleted file mode 100644 index ded0c5e061..0000000000 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ /dev/null @@ -1,9472 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef Q_WS_QWS -# include -#endif - -// I *MUST* have QtTest afterwards or this test won't work with newer headers -#if defined(Q_WS_MAC) -# include -#undef verify -#include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile. -#endif - -#include - -#if defined(Q_OS_WIN) -# include -# include -# include -# include - -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(handle); - qWarning() << "Cannot obtain native handle for " << w; - return 0; -} -#endif - -#if defined(Q_WS_WIN) -# include -# 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 -# include -#elif defined(Q_WS_QWS) -# include -#endif - -#if !defined(Q_WS_WIN) -#define Q_CHECK_PAINTEVENTS -#endif - -#if defined(Q_OS_WINCE_WM) -#include -// 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 (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 -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(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(var11), obj1.layout()); - obj1.setLayout((QLayout *)0); - QCOMPARE(static_cast(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(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("windowHidden"); - QTest::addColumn("subWindow1Hidden"); - QTest::addColumn("subWindow2Hidden"); - QTest::addColumn("subSubWindowHidden"); - QTest::addColumn("windowMinimized"); - QTest::addColumn("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(0)); - QCOMPARE(qApp->focusWidget(), static_cast(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(0)); - QCOMPARE(qApp->focusWidget(), static_cast(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(0)); - QCOMPARE(qApp->focusWidget(), static_cast(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(0)); - QCOMPARE(qApp->focusWidget(), static_cast(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(0)); -#ifdef Q_WS_QWS - QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue); -#endif - QTRY_COMPARE(qApp->focusWidget(), static_cast(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 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 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 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 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 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 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 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 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 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 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 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(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("fileName"); - QTest::addColumn("expectedWindowState"); - QTest::addColumn("expectedPosition"); - QTest::addColumn("expectedSize"); - QTest::addColumn("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(text_prop.value); - } else { - text_prop.nitems = strlen(reinterpret_cast(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 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 sibling; -}; - - -void tst_QWidget::childDeletesItsSibling() -{ - QWidget *commonParent = new QWidget(0); - QPointer child = new QWidget(0); - QPointer 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 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("show"); - QTest::addColumn("hide"); - QTest::addColumn("create"); - QTest::addColumn("expectedShowEvents"); - QTest::addColumn("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(object) != 0 || object->isWidgetType()); - } -}; - -/* - Test that qobject_cast 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) - -// 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 >("rects"); - QTest::addColumn("windowFlags"); - - QList > rects; - rects << (QList() - << 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() - << 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(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(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(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 windowFlags; - windowFlags << 0 << Qt::FramelessWindowHint; - - foreach (QList 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, 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, 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("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(&w1)); - QTest::qWait(50); - QTest::mouseDClick(&w1, Qt::LeftButton); - QTRY_COMPARE(QApplication::focusWidget(), static_cast(w1.edit)); - - w2.activateWindow(); - QApplication::setActiveWindow(&w2); - QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), static_cast(&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(w2.edit)); - - w1.activateWindow(); - QApplication::setActiveWindow(&w1); - QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), static_cast(&w1)); - QTest::mouseDClick(&w1, Qt::LeftButton); - QTRY_COMPARE(QApplication::focusWidget(), static_cast(w1.edit)); - - w2.activateWindow(); - QApplication::setActiveWindow(&w2); - QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), static_cast(&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(0)); - - child2.setFocus(); - QVERIFY(!child2.hasFocus()); - QCOMPARE(window.focusWidget(), &child2); - QCOMPARE(QApplication::focusWidget(), static_cast(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(0)); - - child2.setFocus(); - QVERIFY(!child2.hasFocus()); - QCOMPARE(window.focusWidget(), &child2); - QCOMPARE(QApplication::focusWidget(), static_cast(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(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(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(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(0)); - - child1.hide(); - QVERIFY(!child1.hasFocus()); - QCOMPARE(window.focusWidget(), static_cast(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(0)); - - child1.show(); - QVERIFY(!child1.hasFocus()); - QCOMPARE(window.focusWidget(), static_cast(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(0)); - - child2.setFocus(); - QVERIFY(!child2.hasFocus()); - QCOMPARE(window.focusWidget(), static_cast(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(0)); - - child2.hide(); - QVERIFY(!child2.hasFocus()); - QCOMPARE(window.focusWidget(), static_cast(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(0)); - - child2.show(); - QVERIFY(!child2.hasFocus()); - QCOMPARE(window.focusWidget(), static_cast(0)); - QCOMPARE(QApplication::focusWidget(), static_cast(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 applicationEventSpies; - QList 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 > 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(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(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(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(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("autoFillBackground"); - QTest::addColumn("usePaintEvent"); - QTest::addColumn("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("size"); - QTest::addColumn("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("initial"); - QTest::addColumn("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("sizeHint"); - QTest::addColumn("hPolicy"); - QTest::addColumn("vPolicy"); - QTest::addColumn("hfwSP"); - QTest::addColumn("layout"); - QTest::addColumn("hfwLayout"); - QTest::addColumn("haveParent"); - QTest::addColumn("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("minSize"); - QTest::addColumn("shouldInvalidate"); - QTest::addColumn("maxSize"); - QTest::addColumn("shouldInvalidate2"); - QTest::addColumn("verticalSizePolicy"); - QTest::addColumn("shouldInvalidate3"); - QTest::addColumn("setVisible"); - QTest::addColumn("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(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(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(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(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 blurEffect = new QGraphicsBlurEffect; - widget->setGraphicsEffect(blurEffect); - QCOMPARE(widget->graphicsEffect(), static_cast(blurEffect)); - - // Ensure the existing effect is deleted when setting a new one. - QPointer shadowEffect = new QGraphicsDropShadowEffect; - widget->setGraphicsEffect(shadowEffect); - QVERIFY(!blurEffect); - QCOMPARE(widget->graphicsEffect(), static_cast(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(d_ptr.data())->topData()->backingStoreTracker.destroy(); - } - void enableBackingStore() - { - if (!static_cast(d_ptr.data())->maybeBackingStore()) { - static_cast(d_ptr.data())->topData()->backingStoreTracker.create(this); - static_cast(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(toolBar)); - QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(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(toolBar)); - QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(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(p1)); -#endif - - QTest::qWait(1000); -} - -QTEST_MAIN(tst_QWidget) -#include "tst_qwidget.moc" diff --git a/tests/auto/qwidget/tst_qwidget_mac_helpers.h b/tests/auto/qwidget/tst_qwidget_mac_helpers.h deleted file mode 100644 index d7bc3f33c7..0000000000 --- a/tests/auto/qwidget/tst_qwidget_mac_helpers.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include - -#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 WidgetViewPair; -bool testAndRelease(const WId); -WidgetViewPair createAndRetain(QWidget * const parent = 0); diff --git a/tests/auto/qwidget/tst_qwidget_mac_helpers.mm b/tests/auto/qwidget/tst_qwidget_mac_helpers.mm deleted file mode 100644 index 10e137c06c..0000000000 --- a/tests/auto/qwidget/tst_qwidget_mac_helpers.mm +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - - -QString nativeWindowTitle(QWidget *window, Qt::WindowState state) -{ - OSWindowRef windowRef = qt_mac_window_for(window); - QCFString macTitle; - if (state == Qt::WindowMinimized) { - macTitle = reinterpret_cast([[windowRef miniwindowTitle] retain]); - } else { - macTitle = reinterpret_cast([[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/qwidget_window/.gitignore b/tests/auto/qwidget_window/.gitignore deleted file mode 100644 index 7f0bd8d631..0000000000 --- a/tests/auto/qwidget_window/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qwidget_window diff --git a/tests/auto/qwidget_window/qwidget_window.pro b/tests/auto/qwidget_window/qwidget_window.pro deleted file mode 100644 index dd5837012c..0000000000 --- a/tests/auto/qwidget_window/qwidget_window.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qwidget_window.cpp - -x11 { - LIBS += $$QMAKE_LIBS_X11 -} - diff --git a/tests/auto/qwidget_window/tst_qwidget_window.cpp b/tests/auto/qwidget_window/tst_qwidget_window.cpp deleted file mode 100644 index eb8b555bd6..0000000000 --- a/tests/auto/qwidget_window/tst_qwidget_window.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include - -#include - -#ifdef Q_WS_X11 -#include -#include -#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("setWindowTitleBefore"); - QTest::addColumn("setWindowTitleAfter"); - QTest::addColumn("filePath"); - QTest::addColumn("applicationName"); - QTest::addColumn("indyWindowTitle"); - QTest::addColumn("finalTitleBefore"); - QTest::addColumn("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("filePath"); - QTest::addColumn("result"); - QTest::addColumn("again"); - QTest::addColumn("filePath2"); - QTest::addColumn("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/qwidgetaction/.gitignore b/tests/auto/qwidgetaction/.gitignore deleted file mode 100644 index 56d519d851..0000000000 --- a/tests/auto/qwidgetaction/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qwidgetaction diff --git a/tests/auto/qwidgetaction/qwidgetaction.pro b/tests/auto/qwidgetaction/qwidgetaction.pro deleted file mode 100644 index 3e037c2efb..0000000000 --- a/tests/auto/qwidgetaction/qwidgetaction.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qwidgetaction.cpp - - diff --git a/tests/auto/qwidgetaction/tst_qwidgetaction.cpp b/tests/auto/qwidgetaction/tst_qwidgetaction.cpp deleted file mode 100644 index 5f51f6d316..0000000000 --- a/tests/auto/qwidgetaction/tst_qwidgetaction.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/**************************************************************************** -** -** 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 - -#include -#include -#include -#include -#include -#include -#include -#include - -//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 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 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 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 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 combo1 = new QComboBox; - a->setDefaultWidget(combo1); - QVERIFY(a->defaultWidget() == combo1); - a->setDefaultWidget(combo1); - QVERIFY(combo1); - QVERIFY(a->defaultWidget() == combo1); - - QPointer 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 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 combos = action->createdWidgets(); - QCOMPARE(combos.count(), 1); - - QPointer combo1 = qobject_cast(combos.at(0)); - QVERIFY(combo1); - - tb2.addAction(action); - - combos = action->createdWidgets(); - QCOMPARE(combos.count(), 2); - - QVERIFY(combos.at(0) == combo1); - QPointer combo2 = qobject_cast(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 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 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/qwizard/.gitignore b/tests/auto/qwizard/.gitignore deleted file mode 100644 index 9494c96da2..0000000000 --- a/tests/auto/qwizard/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qwizard diff --git a/tests/auto/qwizard/images/background.png b/tests/auto/qwizard/images/background.png deleted file mode 100644 index db7d67dc3d..0000000000 Binary files a/tests/auto/qwizard/images/background.png and /dev/null differ diff --git a/tests/auto/qwizard/images/banner.png b/tests/auto/qwizard/images/banner.png deleted file mode 100644 index be36202d99..0000000000 Binary files a/tests/auto/qwizard/images/banner.png and /dev/null differ diff --git a/tests/auto/qwizard/images/logo.png b/tests/auto/qwizard/images/logo.png deleted file mode 100644 index 9cf3350c4b..0000000000 Binary files a/tests/auto/qwizard/images/logo.png and /dev/null differ diff --git a/tests/auto/qwizard/images/watermark.png b/tests/auto/qwizard/images/watermark.png deleted file mode 100644 index 9305675549..0000000000 Binary files a/tests/auto/qwizard/images/watermark.png and /dev/null differ diff --git a/tests/auto/qwizard/qwizard.pro b/tests/auto/qwizard/qwizard.pro deleted file mode 100644 index c27801b82f..0000000000 --- a/tests/auto/qwizard/qwizard.pro +++ /dev/null @@ -1,4 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qwizard.cpp -RESOURCES = qwizard.qrc diff --git a/tests/auto/qwizard/qwizard.qrc b/tests/auto/qwizard/qwizard.qrc deleted file mode 100644 index 471da9def6..0000000000 --- a/tests/auto/qwizard/qwizard.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - images/background.png - images/banner.png - images/logo.png - images/watermark.png - - diff --git a/tests/auto/qwizard/tst_qwizard.cpp b/tests/auto/qwizard/tst_qwizard.cpp deleted file mode 100644 index 2e05eb5bab..0000000000 --- a/tests/auto/qwizard/tst_qwizard.cpp +++ /dev/null @@ -1,2645 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//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 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 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(wizard.button(QWizard::NextButton))); - QVERIFY(qobject_cast(wizard.button(QWizard::CustomButton2))); - QVERIFY(qobject_cast(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(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 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 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 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()); - - page = new QWizardPage(parent); - wizard.setPage(0, page); - QCOMPARE(spy.count(), 1); - QList 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()); - - 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()); - - 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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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::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::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(""); // 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::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::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(wizard.button(QWizard::NextButton))) - pb->setAutoDefault(false); - if (QPushButton *pb = qobject_cast(wizard.button(QWizard::FinishButton))) - pb->setAutoDefault(false); - - wizard.show(); - qApp->processEvents(); - QVERIFY(qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); - QVERIFY(wizard.button(QWizard::FinishButton)->isEnabled()); - - wizard.next(); - QVERIFY(qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); - - wizard.back(); - QVERIFY(qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); - - wizard.setOption(QWizard::NoDefaultButton, true); - QVERIFY(!qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); - QVERIFY(!qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); - - wizard.next(); - QVERIFY(!qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); - QVERIFY(!qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); - - wizard.back(); - QVERIFY(!qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); - QVERIFY(!qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); - - wizard.setOption(QWizard::NoDefaultButton, false); - QVERIFY(qobject_cast(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 operations_; - foreach (QWizard::WizardOption option, tags.keys()) - operations_[option] = new SetOption(option, i == 1); - operations << operations_; - } - } - OptionInfo(OptionInfo const&); - OptionInfo& operator=(OptionInfo const&); - QMap tags; - QList > 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 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) - -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 &add() - { combinations << new QList; 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 *> 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 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 &operations) - { - foreach (Operation * op, operations) { - if (op) { - op->apply(this); - opsDescr += QString("(%1) ").arg(op->describe()); - } - } - } - - QImage createImage() const - { - return QPixmap::grabWidget(const_cast(this)) - .toImage().convertToFormat(QImage::Format_ARGB32); - } - - QString operationsDescription() const { return opsDescr; } -}; - -class CombinationsTestData -{ - TestGroup testGroup; - QList pageOps; - QList styleOps; - QMap *> setAllOptions; -public: - CombinationsTestData() - { - QTest::addColumn("ref"); - QTest::addColumn("testEquality"); - QTest::addColumn >("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; - setAllOptions[true] = new QList; - 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 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 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 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 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, 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 pages; -public: - void add(WizardPage *page) { pages << page; } - QList all() const { return pages; } - QList shown() const - { - QList 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 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(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(&wizard)); - QCOMPARE(w2->window(), static_cast(&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(page1)); - - // ---- - page2->disableVerticalExpansion(); - wizard.next(); - QCOMPARE(wizard.currentPage(), static_cast(page2)); - QVERIFY(page2->treeWidgetHeight() == page2->treeWidgetSizeHintHeight()); - - wizard.back(); - QCOMPARE(wizard.currentPage(), static_cast(page1)); - - // ---- - page2->enableVerticalExpansion(); - wizard.next(); - QCOMPARE(wizard.currentPage(), static_cast(page2)); - QVERIFY(page2->treeWidgetHeight() > page2->treeWidgetSizeHintHeight()); - - wizard.back(); - QCOMPARE(wizard.currentPage(), static_cast(page1)); - - // ---- - page2->disableVerticalExpansion(); - wizard.next(); - QCOMPARE(wizard.currentPage(), static_cast(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(&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/qworkspace/.gitignore b/tests/auto/qworkspace/.gitignore deleted file mode 100644 index 73facc366e..0000000000 --- a/tests/auto/qworkspace/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qworkspace diff --git a/tests/auto/qworkspace/qworkspace.pro b/tests/auto/qworkspace/qworkspace.pro deleted file mode 100644 index 0b8a604fe8..0000000000 --- a/tests/auto/qworkspace/qworkspace.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -QT += widgets -SOURCES += tst_qworkspace.cpp diff --git a/tests/auto/qworkspace/tst_qworkspace.cpp b/tests/auto/qworkspace/tst_qworkspace.cpp deleted file mode 100644 index a996c38438..0000000000 --- a/tests/auto/qworkspace/tst_qworkspace.cpp +++ /dev/null @@ -1,679 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -//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("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/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 + +#include +#include +#include +#include + +//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 +#include +#include + +//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[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 + +#include +#include +#include +#include +#include +#include +#include + +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("dlgSize"); + QTest::addColumn("extSize"); + QTest::addColumn("horizontal"); + QTest::addColumn("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(&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(&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 sizeGrip = qFindChild(&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(&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(&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 +#include +#include +#include + +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
bar"); + QCheckBox *checkBox = 0; + + QErrorMessage errorMessageDialog(0); + + // show an error with plain string + errorMessageDialog.showMessage(plainString); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&errorMessageDialog); + QVERIFY(checkBox); + QVERIFY(checkBox->isChecked()); + errorMessageDialog.close(); + + errorMessageDialog.showMessage(plainString); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&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(&errorMessageDialog); + QVERIFY(checkBox); + QVERIFY(!checkBox->isChecked()); + checkBox->setChecked(true); + errorMessageDialog.close(); + + errorMessageDialog.showMessage(htmlString); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&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
bar"); + QString htmlString2 = QLatin1String("foo2
bar2"); + QCheckBox *checkBox = 0; + + QErrorMessage errorMessageDialog(0); + + errorMessageDialog.showMessage(htmlString,"Cat 1"); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&errorMessageDialog); + QVERIFY(checkBox); + QVERIFY(checkBox->isChecked()); + checkBox->setChecked(true); + errorMessageDialog.close(); + + errorMessageDialog.showMessage(htmlString,"Cat 1"); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&errorMessageDialog); + QVERIFY(checkBox); + QVERIFY(checkBox->isChecked()); + checkBox->setChecked(true); + errorMessageDialog.close(); + + errorMessageDialog.showMessage(htmlString2,"Cat 1"); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&errorMessageDialog); + QVERIFY(checkBox); + QVERIFY(checkBox->isChecked()); + checkBox->setChecked(true); + errorMessageDialog.close(); + + errorMessageDialog.showMessage(htmlString,"Cat 1"); + QVERIFY(errorMessageDialog.isVisible()); + checkBox = qFindChild(&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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include + +#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(&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(&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(&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(&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("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(&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(&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(&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(&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 list = qFindChildren(&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("startPath"); + QTest::addColumn("input"); + QTest::addColumn("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 files; + QT_TRY { + for (int i = 0; i < 10; ++i) { + QScopedPointer 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(&fd, "qt_filesystem_model"); + QVERIFY(model); + QLineEdit *lineEdit = qFindChild(&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(&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(&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 views = qFindChildren(&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(&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(&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(&fd, "newFolderButton"); + QAction* renameAction = qFindChild(&fd, "qt_rename_action"); + QAction* deleteAction = qFindChild(&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("file"); + QTest::addColumn("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(&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(&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(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 treeView = qFindChildren(&fd, "treeView"); + QCOMPARE(treeView.count(), 1); + QList listView = qFindChildren(&fd, "listView"); + QCOMPARE(listView.count(), 1); + QList listButton = qFindChildren(&fd, "listModeButton"); + QCOMPARE(listButton.count(), 1); + QList treeButton = qFindChildren(&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(&fd)); + qApp->processEvents(); + + // make sure the tests work with focus follows mouse + QCursor::setPos(fd.geometry().center()); + QApplication::syncX(); + + QList treeView = qFindChildren(&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(&fd, "qt_filesystem_model"); + QVERIFY(model); + QToolButton *backButton = qFindChild(&fd, "backButton"); + QVERIFY(backButton); + QToolButton *forwardButton = qFindChild(&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(spy.last().first()); + QCOMPARE(model->index(currentPath), model->index(temp)); + + backButton->click(); + currentPath = qVariantValue(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(&fd, "backButton"); + QVERIFY(backButton); + QToolButton *forwardButton = qFindChild(&fd, "forwardButton"); + QVERIFY(forwardButton); + + QFileSystemModel *model = qFindChild(&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(spy.last().first())), model->index(temp)); + + forwardButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(desktop)); + QCOMPARE(backButton->isEnabled(), true); + QCOMPARE(forwardButton->isEnabled(), false); + QCOMPARE(spy.count(), 4); + + backButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); + QCOMPARE(backButton->isEnabled(), true); + + backButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(home)); + QCOMPARE(backButton->isEnabled(), false); + QCOMPARE(forwardButton->isEnabled(), true); + QCOMPARE(spy.count(), 6); + + forwardButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); + backButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(home)); + QCOMPARE(spy.count(), 8); + + forwardButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); + forwardButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(desktop)); + + backButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(temp)); + backButton->click(); + QCOMPARE(model->index(qVariantValue(spy.last().first())), model->index(home)); + fd.setDirectory(desktop); + QCOMPARE(forwardButton->isEnabled(), false); +} + +void tst_QFiledialog::disableSaveButton_data() +{ + QTest::addColumn("path"); + QTest::addColumn("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(&fd, "buttonBox"); + QPushButton *button = buttonBox->button(QDialogButtonBox::Save); + QVERIFY(button); + QCOMPARE(button->isEnabled(), isEnabled); +} + +void tst_QFiledialog::saveButtonText_data() +{ + QTest::addColumn("path"); + QTest::addColumn("label"); + QTest::addColumn("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(&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(&fd, "fileNameEdit"); + QVERIFY(lineEdit); + QVERIFY(lineEdit->text() == "foo"); + fd.setDirectory(QDir::home()); + + QListView* list = qFindChild(&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(&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("tildePath"); + QTest::addColumn("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 (~ 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 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(&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(&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(&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(&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(&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("path"); + QTest::addColumn("directory"); + QTest::addColumn("isEnabled"); + QTest::addColumn("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(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(dlg, "qt_filesystem_model"); + QVERIFY(model); + dlg->setAcceptMode(QFileDialog::AcceptSave); + QCOMPARE(model->index(dlg->directory().absolutePath()), model->index(directory)); + + QDialogButtonBox *buttonBox = qFindChild(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(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(&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(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(&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(&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(&fd, "fileNameEdit"); + QToolButton *buttonParent = qFindChild(&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(&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(&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(&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(&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(&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(&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(&fd, "listView"); + list->setFocus(); + QTest::qWait(200); + QTest::keyClick(list, Qt::Key_Return); + QTest::qWait(1000); + QDialogButtonBox *buttonBox = qFindChild(&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(&fd, "treeView"); + tree->header()->setSortIndicator(3,Qt::DescendingOrder); + QTest::qWait(200); + QDialogButtonBox *buttonBox = qFindChild(&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(&fd2, "treeView"); + tree2->setFocus(); + + QCOMPARE(tree2->rootIndex().data(QFileSystemModel::FilePathRole).toString(),current.absolutePath()); + + QDialogButtonBox *buttonBox2 = qFindChild(&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(&fd3, "treeView"); + tree3->setFocus(); + + QCOMPARE(tree3->rootIndex().data(QFileSystemModel::FilePathRole).toString(), current.absolutePath()); + + QDialogButtonBox *buttonBox3 = qFindChild(&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 comboList = d.findChildren(); + 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 urls; + urls << QUrl::fromLocalFile(hiddenSubDir.absolutePath()); + fd.setSidebarUrls(urls); + fd.show(); + QTest::qWait(250); + + QSidebar *sidebar = qFindChild(&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(&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 idxs = selectionModel()->selectedIndexes(); + QList 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 urls; + urls << QUrl::fromLocalFile(testSubDir.absolutePath()); + urls << QUrl::fromLocalFile("NotFound"); + fd.setSidebarUrls(urls); + fd.show(); + QTest::qWait(250); + + QSidebar *sidebar = qFindChild(&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(&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(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(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 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(&fd, "fileNameEdit"); + QVERIFY(lineEdit); + QCOMPARE(lineEdit->text(),QLatin1String("new_file.txt")); + QListView *list = qFindChild(&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::fromLocalFile(url)); + QSidebar *sidebar = qFindChild(&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(&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(&fd)); + + QTest::qWait(250); + QLineEdit *lineEdit = qFindChild(&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(&fd)); + + QFileSystemModel *model = qFindChild(&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(&fd)); + + QComboBox *filters = qFindChild(&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(&fd2)); + + QComboBox *filters2 = qFindChild(&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(&fd)); + + fd.setDirectory(""); + QLineEdit *lineEdit = qFindChild(&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 +#ifdef QT_BUILD_INTERNAL +#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +//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"); + + 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("s1"); + QTest::addColumn("s2"); + QTest::addColumn("caseSensitive"); + QTest::addColumn("result"); + QTest::addColumn("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("count"); + QTest::addColumn("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("files"); + QTest::addColumn("dirs"); + QTest::addColumn("dirFilters"); + QTest::addColumn("nameFilters"); + QTest::addColumn("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("files"); + QTest::addColumn("oldFileName"); + QTest::addColumn("newFileName"); + QTest::addColumn("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 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("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< 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 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 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("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("role"); + QTest::addColumn("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 roles = model.roleNames(); + + QFETCH(int, role); + QVERIFY(roles.contains(role)); + + QFETCH(QByteArray, roleName); + QList 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 + + +#include +#include +#include +#include +#include +#include "qfontdialog.h" +#include + +//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[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(dialog.d_func()->familyList); + QListView *styleList = reinterpret_cast(dialog.d_func()->styleList); + QListView *sizeList = reinterpret_cast(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 +#include + +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(view) title] isEqualTo:@"OK"]) { + [static_cast(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 +#include +#include +#include +#include +#include +#include +#include + +//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 +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(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 +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 +void testGetNumeric(QInputDialog *dialog, SpinBoxType * = 0, ValueType * = 0) +{ + SpinBoxType *sbox = qFindChild(dialog); + QVERIFY(sbox != 0); + + QLineEdit *ledit = qFindChild(static_cast(sbox)); + QVERIFY(ledit != 0); + + QDialogButtonBox *bbox = qFindChild(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(sbox, okButton, ledit); + testTypingValue(sbox, okButton, QString("%1").arg(sbox->minimum())); + testTypingValue(sbox, okButton, QString("%1").arg(sbox->maximum())); + testTypingValue(sbox, okButton, QString("%1").arg(sbox->minimum() - 1)); + testTypingValue(sbox, okButton, QString("%1").arg(sbox->maximum() + 1)); + testTypingValue(sbox, okButton, "0"); + testTypingValue(sbox, okButton, "0.0"); + testTypingValue(sbox, okButton, "foobar"); + + testTypingValue(sbox, okButton, loc.toString(origValue)); +} + +void testGetText(QInputDialog *dialog) +{ + QLineEdit *ledit = qFindChild(dialog); + QVERIFY(ledit); + + QDialogButtonBox *bbox = qFindChild(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(dialog); + QVERIFY(cbox); + + QDialogButtonBox *bbox = qFindChild(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(dialog); +} + +void tst_QInputDialog::testFuncGetDouble(QInputDialog *dialog) +{ + testGetNumeric(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(parent); + QVERIFY(dialog); + if (testFunc) + testFunc(dialog); + dialog->done(doneCode); // cause static function call to return +} + +void tst_QInputDialog::getInteger_data() +{ + QTest::addColumn("min"); + QTest::addColumn("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("min"); + QTest::addColumn("max"); + QTest::addColumn("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(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("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("items"); + QTest::addColumn("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 children = dialog.children(); + QLineEdit *editWidget = 0; + for (int c = 0; c < children.size(); c++) { + editWidget = qobject_cast(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) +#include +#endif +#if !defined(QT_NO_STYLE_CLEANLOOKS) +#include +#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(qApp->style())) + expectedButton = int(QMessageBox::No); +#elif !defined(QT_NO_STYLE_CLEANLOOKS) + if (qobject_cast(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("qt_msgbox_buttonbox"); + QVERIFY(bb); //get the detail button + + QList 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 + +#include +#include +#include +#include + + +//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(&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 +#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 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 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 emptyUrls; + QFileSystemModel fsmodel; + QSidebar qsidebar; + qsidebar.init(&fsmodel, emptyUrls); + QAbstractItemModel *model = qsidebar.model(); + QDir testDir = QDir::home(); + + // default + QCOMPARE(model->rowCount(), 0); + + QList 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 moreUrls; + moreUrls << QUrl::fromLocalFile(testDir.absolutePath()); + qsidebar.addUrls(moreUrls, -1); + QCOMPARE(model->rowCount(), 3); + + // make sure invalid urls are still added + QList 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(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 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 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 Binary files /dev/null and b/tests/auto/widgets/dialogs/qwizard/images/background.png 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 Binary files /dev/null and b/tests/auto/widgets/dialogs/qwizard/images/banner.png 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 Binary files /dev/null and b/tests/auto/widgets/dialogs/qwizard/images/logo.png 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 Binary files /dev/null and b/tests/auto/widgets/dialogs/qwizard/images/watermark.png 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 @@ + + + images/background.png + images/banner.png + images/logo.png + images/watermark.png + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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 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 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(wizard.button(QWizard::NextButton))); + QVERIFY(qobject_cast(wizard.button(QWizard::CustomButton2))); + QVERIFY(qobject_cast(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(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 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 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 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()); + + page = new QWizardPage(parent); + wizard.setPage(0, page); + QCOMPARE(spy.count(), 1); + QList 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()); + + 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()); + + 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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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() << -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::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::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(""); // 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::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::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(wizard.button(QWizard::NextButton))) + pb->setAutoDefault(false); + if (QPushButton *pb = qobject_cast(wizard.button(QWizard::FinishButton))) + pb->setAutoDefault(false); + + wizard.show(); + qApp->processEvents(); + QVERIFY(qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); + QVERIFY(wizard.button(QWizard::FinishButton)->isEnabled()); + + wizard.next(); + QVERIFY(qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); + + wizard.back(); + QVERIFY(qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); + + wizard.setOption(QWizard::NoDefaultButton, true); + QVERIFY(!qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); + QVERIFY(!qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); + + wizard.next(); + QVERIFY(!qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); + QVERIFY(!qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); + + wizard.back(); + QVERIFY(!qobject_cast(wizard.button(QWizard::NextButton))->isDefault()); + QVERIFY(!qobject_cast(wizard.button(QWizard::FinishButton))->isDefault()); + + wizard.setOption(QWizard::NoDefaultButton, false); + QVERIFY(qobject_cast(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 operations_; + foreach (QWizard::WizardOption option, tags.keys()) + operations_[option] = new SetOption(option, i == 1); + operations << operations_; + } + } + OptionInfo(OptionInfo const&); + OptionInfo& operator=(OptionInfo const&); + QMap tags; + QList > 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 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) + +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 &add() + { combinations << new QList; 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 *> 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 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 &operations) + { + foreach (Operation * op, operations) { + if (op) { + op->apply(this); + opsDescr += QString("(%1) ").arg(op->describe()); + } + } + } + + QImage createImage() const + { + return QPixmap::grabWidget(const_cast(this)) + .toImage().convertToFormat(QImage::Format_ARGB32); + } + + QString operationsDescription() const { return opsDescr; } +}; + +class CombinationsTestData +{ + TestGroup testGroup; + QList pageOps; + QList styleOps; + QMap *> setAllOptions; +public: + CombinationsTestData() + { + QTest::addColumn("ref"); + QTest::addColumn("testEquality"); + QTest::addColumn >("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; + setAllOptions[true] = new QList; + 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 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 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 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 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, 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 pages; +public: + void add(WizardPage *page) { pages << page; } + QList all() const { return pages; } + QList shown() const + { + QList 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 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(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(&wizard)); + QCOMPARE(w2->window(), static_cast(&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(page1)); + + // ---- + page2->disableVerticalExpansion(); + wizard.next(); + QCOMPARE(wizard.currentPage(), static_cast(page2)); + QVERIFY(page2->treeWidgetHeight() == page2->treeWidgetSizeHintHeight()); + + wizard.back(); + QCOMPARE(wizard.currentPage(), static_cast(page1)); + + // ---- + page2->enableVerticalExpansion(); + wizard.next(); + QCOMPARE(wizard.currentPage(), static_cast(page2)); + QVERIFY(page2->treeWidgetHeight() > page2->treeWidgetSizeHintHeight()); + + wizard.back(); + QCOMPARE(wizard.currentPage(), static_cast(page1)); + + // ---- + page2->disableVerticalExpansion(); + wizard.next(); + QCOMPARE(wizard.currentPage(), static_cast(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(&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 +#include +#include +#include +#include +#include +#include +#include + +#include +#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 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 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 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 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 +#include +#include +#include +#include +#include +#include + + +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 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"); + + // + 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); + + // + setAnchor(l, b, Qt::AnchorLeft, e, Qt::AnchorLeft, 10); + setAnchor(l, e, Qt::AnchorRight, d, Qt::AnchorLeft, 10); + + // + 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); + + // + 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 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"); + + // + 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 +#include +#include +#include +#include +#include + +#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 BasicLayoutTestDataList; +Q_DECLARE_METATYPE(BasicLayoutTestDataList) + +typedef QList BasicLayoutTestResultList; +Q_DECLARE_METATYPE(BasicLayoutTestResultList) + +typedef QList 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("size"); + QTest::addColumn("data"); + QTest::addColumn("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("size"); + QTest::addColumn("data"); + QTest::addColumn("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("size"); + QTest::addColumn("data"); + QTest::addColumn("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("size"); + QTest::addColumn("data"); + QTest::addColumn("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& 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 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("size"); + QTest::addColumn("data"); + QTest::addColumn("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("size"); + QTest::addColumn("data"); + QTest::addColumn("removeData"); + QTest::addColumn("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 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("size"); + QTest::addColumn("policy"); + QTest::addColumn("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("policy1"); + QTest::addColumn("policy2"); + QTest::addColumn("width1"); + QTest::addColumn("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 SizeHintArray; +Q_DECLARE_METATYPE(SizeHintArray) + +void tst_QGraphicsAnchorLayout1::testSizeDistribution_data() +{ + // tests only horizontal direction + QTest::addColumn("sizeHints1"); + QTest::addColumn("sizeHints2"); + QTest::addColumn("width1"); + QTest::addColumn("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("size"); + QTest::addColumn("data"); + QTest::addColumn("sizehint"); + QTest::addColumn("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 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 +#include +#include +#include +#include +#include + +#include + +//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(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("coordinateMode"); + QTest::addColumn("padMode"); + QTest::addColumn("size"); + QTest::addColumn("offset"); + QTest::addColumn("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 +#include +#include +#include +#include + +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(item)); + } + +//private: + QPair 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 ItemList; +Q_DECLARE_METATYPE(ItemList); + +typedef QList 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("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("columnSpan"); + QTest::addColumn("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("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("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("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("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("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("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("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(0)); + QCOMPARE(layout->itemAt(1,0), static_cast(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(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(layout)); + layout->removeAt(0); + QCOMPARE(item0->parentLayoutItem(), static_cast(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("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("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("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("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("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("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("column"); + QTest::addColumn("spacing"); + QTest::addColumn("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("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("row"); + QTest::addColumn("spacing"); + QTest::addColumn("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("spacing"); + QTest::addColumn("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("itemDescriptions"); + QTest::addColumn("expectedMinimumSizeHint"); + QTest::addColumn("expectedPreferredSizeHint"); + QTest::addColumn("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("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("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("itemDescriptions"); + QTest::addColumn("newSize"); + QTest::addColumn("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 RectList; +Q_DECLARE_METATYPE(RectList); + +void tst_QGraphicsGridLayout::alignment2_data() +{ + QTest::addColumn("itemDescriptions"); + QTest::addColumn("newSize"); + QTest::addColumn("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("itemDescriptions"); + QTest::addColumn("newSize"); + QTest::addColumn("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("sizePolicy"); + QTest::addColumn("itemHeight"); + QTest::addColumn("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("w1_fixed"); + QTest::addColumn("w2_fixed"); + QTest::addColumn("w3_fixed"); + QTest::addColumn("w4_fixed"); + QTest::addColumn("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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QPainterPath) +Q_DECLARE_METATYPE(QPointF) +Q_DECLARE_METATYPE(QRectF) + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#include +#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 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 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 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(item), (QGraphicsEllipseItem *)item); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); + QCOMPARE(item->flags(), 0); + break; + case 1: + item = new QGraphicsLineItem; + QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type)); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsLineItem *)item); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); + QCOMPARE(item->flags(), 0); + break; + case 2: + item = new QGraphicsPathItem; + QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type)); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsPathItem *)item); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); + QCOMPARE(item->flags(), 0); + break; + case 3: + item = new QGraphicsPixmapItem; + QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type)); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsPixmapItem *)item); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); + QCOMPARE(item->flags(), 0); + break; + case 4: + item = new QGraphicsPolygonItem; + QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type)); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsPolygonItem *)item); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)0); + QCOMPARE(item->flags(), 0); + break; + case 5: + item = new QGraphicsRectItem; + QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type)); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsRectItem *)item); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsLineItem *)0); + QCOMPARE(item->flags(), 0); + break; + case 6: + item = new QGraphicsTextItem; + QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type)); + QCOMPARE(qgraphicsitem_cast(item), (QGraphicsTextItem *)item); + QCOMPARE(qgraphicsitem_cast(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() << item2); + QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200)); + + item2->setParentItem(item0); + QCOMPARE(item0->children(), QList() << 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(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 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() << item); + item->setSelected(false); + QVERIFY(scene.selectedItems().isEmpty()); + item->setSelected(true); + QCOMPARE(scene.selectedItems(), QList() << 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() << 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"); + QSignalSpy spy(&scene, SIGNAL(changed(QList))); + 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 rlist = qVariantValue >(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 _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 col1 = rect.collidingItems(); + QCOMPARE(col1.size(), 2); + QCOMPARE(col1.first(), static_cast(&line)); + QCOMPARE(col1.last(), static_cast(&rect2)); + + QList col2 = rect2.collidingItems(); + QCOMPARE(col2.size(), 2); + QCOMPARE(col2.first(), static_cast(&line)); + QCOMPARE(col2.last(), static_cast(&rect)); + + QList col3 = line.collidingItems(); + QCOMPARE(col3.size(), 2); + QCOMPARE(col3.first(), static_cast(&rect2)); + QCOMPARE(col3.last(), static_cast(&rect)); + } +} + +void tst_QGraphicsItem::collidesWith_path_data() +{ + QTest::addColumn("pos"); + QTest::addColumn("matrix"); + QTest::addColumn("shape"); + QTest::addColumn("rectCollides"); + QTest::addColumn("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(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("parent"); + QTest::addColumn("parentPos"); + QTest::addColumn("parentTransform"); + QTest::addColumn("pos"); + QTest::addColumn("transform"); + QTest::addColumn("inputRect"); + QTest::addColumn("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(&pathItem)); + //QVERIFY(qgraphicsitem_cast(&pathItem)); + QVERIFY(qgraphicsitem_cast(&pathItem)); + QVERIFY(qgraphicsitem_cast(pPathItem)); + QVERIFY(qgraphicsitem_cast(pPathItem)); + + QVERIFY(qgraphicsitem_cast(&rectItem)); + QVERIFY(qgraphicsitem_cast(&rectItem)); + QVERIFY(qgraphicsitem_cast(pRectItem)); + QVERIFY(qgraphicsitem_cast(pRectItem)); + + QVERIFY(qgraphicsitem_cast(&ellipseItem)); + QVERIFY(qgraphicsitem_cast(&ellipseItem)); + QVERIFY(qgraphicsitem_cast(pEllipseItem)); + QVERIFY(qgraphicsitem_cast(pEllipseItem)); + + QVERIFY(qgraphicsitem_cast(&polygonItem)); + //QVERIFY(qgraphicsitem_cast(&polygonItem)); + QVERIFY(qgraphicsitem_cast(&polygonItem)); + QVERIFY(qgraphicsitem_cast(pPolygonItem)); + QVERIFY(qgraphicsitem_cast(pPolygonItem)); + + QVERIFY(qgraphicsitem_cast(&lineItem)); + QVERIFY(qgraphicsitem_cast(&lineItem)); + QVERIFY(qgraphicsitem_cast(pLineItem)); + QVERIFY(qgraphicsitem_cast(pLineItem)); + + QVERIFY(qgraphicsitem_cast(&pixmapItem)); + QVERIFY(qgraphicsitem_cast(&pixmapItem)); + QVERIFY(qgraphicsitem_cast(pPixmapItem)); + QVERIFY(qgraphicsitem_cast(pPixmapItem)); + + QVERIFY(qgraphicsitem_cast(&textItem)); + QVERIFY(qgraphicsitem_cast(&textItem)); + QVERIFY(qgraphicsitem_cast(pTextItem)); + QVERIFY(qgraphicsitem_cast(pTextItem)); + + // and some casts that _should_ fail: + QVERIFY(!qgraphicsitem_cast(&pathItem)); + QVERIFY(!qgraphicsitem_cast(pPolygonItem)); + + // and this shouldn't crash + QGraphicsItem *ptr = 0; + QVERIFY(!qgraphicsitem_cast(ptr)); + QVERIFY(!qgraphicsitem_cast(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("item"); + QTest::addColumn("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 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 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 control = item->textControl(); + delete item; + QVERIFY(!control); + + item = new QGraphicsTextItem; + + QPointer 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 changes; + QList values; + QList 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(variant, matrix()); + oldValues << variant; + } + break; + case QGraphicsItem::ItemTransformChange: { + QVariant variant; + qVariantSetValue(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(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(scene()); + if (itemSceneChangeTargetScene + && qVariantValue(value) + && itemSceneChangeTargetScene != qVariantValue(value)) { + return qVariantFromValue(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(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(tester.values.at(tester.values.size() - 2)), + QMatrix().translate(50, 0)); + QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90)))); + QVariant variant; + qVariantSetValue(variant, QMatrix()); + QCOMPARE(tester.oldValues.last(), variant); + QCOMPARE(tester.matrix(), QMatrix().rotate(90)); + } + { + tester.resetTransform(); + ++changeCount; + ++changeCount; // notification sent too + + // ItemTransformChange / ItemTransformHasChanged + qVariantSetValue(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(tester.values.at(tester.values.size() - 2)), + QTransform().translate(50, 0)); + QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 1)), + QTransform().rotate(90)); + QVariant variant; + qVariantSetValue(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(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)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(tester.itemChangeReturnValue, 0); + tester.setParentItem(&testerHelper); + QCOMPARE(tester.changes.size(), ++changeCount); + QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange); + QCOMPARE(qVariantValue(tester.values.last()), (QGraphicsItem *)&testerHelper); + QCOMPARE(qVariantValue(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(tester.values.last()), (QGraphicsItem *)&testerHelper); + } + { + // ItemChildRemovedChange 1 + testerHelper.setParentItem(0); + QCOMPARE(tester.changes.size(), ++changeCount); + QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange); + QCOMPARE(qVariantValue(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(parent.values.last()), (QGraphicsItem *)child); + delete child; + QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange); + QCOMPARE(qVariantValue(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(tester.oldValues.last()), (QGraphicsScene *)0); + QCOMPARE(qVariantValue(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(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene); + QCOMPARE(qVariantValue(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0); + QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0); + QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0); + QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2); + QCOMPARE(qVariantValue(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(tester.oldValues.last()), (QGraphicsScene *)0); + QCOMPARE(qVariantValue(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(tester.oldValues.last()), (QGraphicsScene *)&scene2); + QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0); + QCOMPARE(qVariantValue(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(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2); + QCOMPARE(qVariantValue(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene); + QCOMPARE(qVariantValue(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 filteredEvents; + QList filteredEventReceivers; + bool handlesSceneEvents; + + QList 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(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(text1)); + QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn); + QCOMPARE(tester->filteredEventReceivers.at(2), static_cast(text2)); + QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut); + QCOMPARE(tester->filteredEventReceivers.at(3), static_cast(text2)); + QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn); + QCOMPARE(tester->filteredEventReceivers.at(4), static_cast(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(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(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 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("flags"); + QTest::addColumn("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("line"); + QTest::addColumn("granularity"); + QTest::addColumn("transform"); + QTest::addColumn("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("p_opacity"); + QTest::addColumn("p_opacityFlags"); + QTest::addColumn("c1_opacity"); + QTest::addColumn("c1_opacityFlags"); + QTest::addColumn("c2_opacity"); + QTest::addColumn("c2_opacityFlags"); + QTest::addColumn("p_effectiveOpacity"); + QTest::addColumn("c1_effectiveOpacity"); + QTest::addColumn("c2_effectiveOpacity"); + QTest::addColumn("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 *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 *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() + << grandChild111 << child11 + << grandChild121 << child12 << parent1 + << grandChild211 << child21 + << grandChild221 << child22 << parent2)); + QTRY_COMPARE(paintedItems, QList() + << 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() + << grandChild121 << child12 << parent1 + << grandChild111 << child11 + << grandChild211 << child21 + << grandChild221 << child22 << parent2)); + QCOMPARE(paintedItems, QList() + << 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() + << parent1 << grandChild111 << child11 + << grandChild121 << child12 + << grandChild211 << child21 + << grandChild221 << child22 << parent2)); + QCOMPARE(paintedItems, QList() + << parent2 << child22 << grandChild221 + << child21 << grandChild211 + << child12 << grandChild121 + << child11 << grandChild111 << parent1); +} + +class ClippingAndTransformsScene : public QGraphicsScene +{ +public: + QList 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 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("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("untransformable1"); + QTest::addColumn("untransformable2"); + QTest::addColumn("untransformable3"); + QTest::addColumn("rotation1"); + QTest::addColumn("rotation2"); + QTest::addColumn("rotation3"); + QTest::addColumn("deviceX"); + QTest::addColumn("mapResult1"); + QTest::addColumn("mapResult2"); + QTest::addColumn("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(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("origin"); + QTest::addColumn("rotation"); + QTest::addColumn("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::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("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() + << 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() << 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 items = scene.items(QPointF(80, 80)); + QCOMPARE(items.size(), 1); + QCOMPARE(items.at(0), static_cast(item3)); + + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + QTest::qWait(100); + + items = scene.items(QPointF(80, 80)); + QCOMPARE(items.size(), 1); + QCOMPARE(items.at(0), static_cast(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 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(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(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 blurEffect = new QGraphicsBlurEffect; + item->setGraphicsEffect(blurEffect); + QCOMPARE(item->graphicsEffect(), static_cast(blurEffect)); + + // Ensure the existing effect is deleted when setting a new one. + QPointer shadowEffect = new QGraphicsDropShadowEffect; + item->setGraphicsEffect(shadowEffect); + QVERIFY(!blurEffect); + QCOMPARE(item->graphicsEffect(), static_cast(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(&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() << 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() << child1 << child3 << child4 << child2)); + + // Move child2 before child1 + child2->stackBefore(child1); // 2134 + QCOMPARE(parent.childItems(), (QList() << child2 << child1 << child3 << child4)); + child2->stackBefore(child2); // 2134 + QCOMPARE(parent.childItems(), (QList() << child2 << child1 << child3 << child4)); + child1->setZValue(1); // 2341 + QCOMPARE(parent.childItems(), (QList() << child2 << child3 << child4 << child1)); + child1->stackBefore(child2); // 2341 + QCOMPARE(parent.childItems(), (QList() << child2 << child3 << child4 << child1)); + child1->setZValue(0); // 1234 + QCOMPARE(parent.childItems(), (QList() << child1 << child2 << child3 << child4)); + child4->stackBefore(child1); // 4123 + QCOMPARE(parent.childItems(), (QList() << child4 << child1 << child2 << child3)); + child4->setZValue(1); // 1234 (4123) + QCOMPARE(parent.childItems(), (QList() << child1 << child2 << child3 << child4)); + child3->stackBefore(child1); // 3124 (4312) + QCOMPARE(parent.childItems(), (QList() << child3 << child1 << child2 << child4)); + child4->setZValue(0); // 4312 + QCOMPARE(parent.childItems(), (QList() << 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() << child1 << child2 << child3 << child4)); + + // Remove and append + scene.removeItem(child2); + scene.addItem(child2); + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child1 << child3 << child4 << child2)); + + // Move child2 before child1 + child2->stackBefore(child1); // 2134 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child1 << child3 << child4)); + child2->stackBefore(child2); // 2134 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child1 << child3 << child4)); + child1->setZValue(1); // 2341 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child3 << child4 << child1)); + child1->stackBefore(child2); // 2341 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child2 << child3 << child4 << child1)); + child1->setZValue(0); // 1234 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child1 << child2 << child3 << child4)); + child4->stackBefore(child1); // 4123 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child4 << child1 << child2 << child3)); + child4->setZValue(1); // 1234 (4123) + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child1 << child2 << child3 << child4)); + child3->stackBefore(child1); // 3124 (4312) + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << child3 << child1 << child2 << child4)); + child4->setZValue(0); // 4312 + QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList() << 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(&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("focusFlag"); + QTest::addColumn("useStickyFocus"); + QTest::addColumn("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus + + QTest::newRow("Focus goes through.") + << static_cast(0x0) << false << 1; + + QTest::newRow("Focus goes through, even with sticky scene.") + << static_cast(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(&view)); + QVERIFY(itemWithFocus->hasFocus()); + + const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center()); + const QList itemsAtMousePressPosition = scene.items(mousePressPoint); + QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop)); + + sendMousePress(&scene, mousePressPoint); + + switch (expectedFocusItem) { + case 0: + QCOMPARE(scene.focusItem(), static_cast(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("flag"); + QTest::addColumn("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 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 + +#include +#include +#include + +//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(0.5, QPointF(5, -5)))); + QCOMPARE(animation.posList().at(1), (QPair(1.0, QPointF(10, -10)))); + QCOMPARE(animation.rotationList().at(0), (QPair(0.3, 2.3))); + QCOMPARE(animation.translationList().at(0), (QPair(0.3, QPointF(15, 15)))); + QCOMPARE(animation.scaleList().at(0), (QPair(0.3, QPointF(2.5, 1.8)))); + QCOMPARE(animation.shearList().at(0), (QPair(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 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 +#include +#include +#include + +//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 functionCount; +private: + QMap 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(0)); + QCOMPARE(w2->parentItem(), static_cast(0)); + scene.addItem(w1); + QCOMPARE(w1->parentItem(), static_cast(0)); + window->setLayout(l1); + QCOMPARE(w1->parentItem(), static_cast(window)); + QCOMPARE(w2->parentItem(), static_cast(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(window2)); + QCOMPARE(w4->parentItem(), static_cast(window2)); + + // graphics item with another parent + QGraphicsLinearLayout *l5 = new QGraphicsLinearLayout(); + l5->addItem(w1); + l5->addItem(w2); + QCOMPARE(w1->parentItem(), static_cast(window)); + QCOMPARE(w2->parentItem(), static_cast(window)); + QGraphicsLinearLayout *l4 = new QGraphicsLinearLayout(); + l4->addItem(l5); + QGraphicsWidget *window3 = new QGraphicsWidget(); + scene.addItem(window3); + window3->setLayout(l4); + + QCOMPARE(w1->parentItem(), static_cast(window3)); + QCOMPARE(w2->parentItem(), static_cast(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 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(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(static_cast(item)); + //clearAllCounters(lay); + } else { + TestGraphicsWidget *wid = static_cast(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 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(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(li->graphicsItem())->setRect(geom); + } + } +private: + QTimeLine m_timeline; + QVector fromGeoms; + QVector 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(li1->graphicsItem())->rect(), QRectF( 0, 0, 33, 99)); + QTRY_COMPARE(static_cast(li2->graphicsItem())->rect(), QRectF(33, 0, 33, 99)); + QTRY_COMPARE(static_cast(li3->graphicsItem())->rect(), QRectF(66, 0, 33, 99)); + + lout->setOrientation(Qt::Vertical); + + QTRY_COMPARE(static_cast(li1->graphicsItem())->rect(), QRectF(0, 0, 99, 33)); + QTRY_COMPARE(static_cast(li2->graphicsItem())->rect(), QRectF(0, 33, 99, 33)); + QTRY_COMPARE(static_cast(li3->graphicsItem())->rect(), QRectF(0, 66, 99, 33)); + +} + +class CustomLayoutItem : public QGraphicsLayoutItem { +public: + CustomLayoutItem(QSet *destructedSet) + : QGraphicsLayoutItem() + { + m_destructedSet = destructedSet; + setOwnedByLayout(true); + } + + QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const; + + ~CustomLayoutItem() { + m_destructedSet->insert(this); + } +private: + QSet *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 *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 *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 &actual, const QSet &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(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(parentItem)); + } +} + +QSizeF sizeHint(Qt::SizeHint /* which */, const QSizeF & /* constraint */) const +{ + return QSizeF(50,50); +} + +QList items; + +}; + +void tst_QGraphicsLayout::ownership() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + + { + QGraphicsLinearLayout *lay = new QGraphicsLinearLayout; + QSet 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 expected; + expected << li1 << li2 << li3; + QVERIFY(compareSets(destructedSet, expected)); + } + + { + QGraphicsWidget *window = new QGraphicsWidget; + QGraphicsLinearLayout *lay = new QGraphicsLinearLayout; + QSet 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 +#include +#include +#include + +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("sizeHint"); + QTest::addColumn("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("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("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( 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("size"); + QTest::addColumn("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("size"); + QTest::addColumn("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("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("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 +#include +#include +#include +#include +#include +#include +#include + +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("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("orientation"); + QTest::addColumn("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("itemCount"); + QTest::addColumn("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("itemCount"); + QTest::addColumn("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("itemCount"); + QTest::addColumn("layoutCount"); + QTest::addColumn("itemSpacing"); + QTest::addColumn("spacing"); + QTest::addColumn("orientation"); + QTest::addColumn("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("itemCount"); + QTest::addColumn("layoutCount"); + QTest::addColumn("insertItemAt"); + QTest::addColumn("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("itemCount"); + QTest::addColumn("layoutCount"); + QTest::addColumn("insertItemAt"); + QTest::addColumn("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); + + QListitems; + 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("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("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(w0)); + QCOMPARE(l->itemAt(1), static_cast(w1)); + QCOMPARE(l->itemAt(2), static_cast(w2)); + QCOMPARE(l->itemAt(3), static_cast(w3)); +} + +void tst_QGraphicsLinearLayout::orientation_data() +{ + QTest::addColumn("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 positions; + + view.show(); + widget->show(); + qApp->processEvents(); + + for (i = 0; i < itemCount; ++i) { + QGraphicsWidget *item = static_cast(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(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("itemCount"); + QTest::addColumn("layoutCount"); + QTest::addColumn("removeItemAt"); + QTest::addColumn("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(&layout)); + layout.removeAt(removeItemAt); + wParent = w->parentLayoutItem(); + QCOMPARE(wParent, static_cast(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("itemCount"); + QTest::addColumn("layoutCount"); + QTest::addColumn("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("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("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("index"); + QTest::addColumn("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 IntList; +Q_DECLARE_METATYPE(IntList) +Q_DECLARE_METATYPE(qreal) + +void tst_QGraphicsLinearLayout::setStretchFactor_data() +{ + QTest::addColumn("totalSize"); + QTest::addColumn("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(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("orientation"); + QTest::addColumn("count"); + QTest::addColumn("preferredSizeHints"); + QTest::addColumn("stretches"); + QTest::addColumn("ignoreFlag"); + QTest::addColumn("newSize"); + QTest::addColumn("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("which"); + QTest::addColumn("constraint"); + QTest::addColumn("spacing"); + QTest::addColumn("layoutMargin"); + QTest::addColumn("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(layout)); + QCOMPARE(layout->parentLayoutItem(), static_cast(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(layout2a)); + QCOMPARE(layout2a->parentLayoutItem(), static_cast(layout2)); + QCOMPARE(layout2->parentLayoutItem(), static_cast(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 +#include +#include +#include +#include +#include +#include + +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 +#include +#include + +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("pixmap"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("point"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("otherPixmap"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("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("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("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("pixmap"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("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("pixmap"); + QTest::addColumn("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("variant"); + QTest::addColumn("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("extension"); + QTest::addColumn("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("extension"); + QTest::addColumn("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 +#include + +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("polygon"); + QTest::addColumn("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("polygon"); + QTest::addColumn("point"); + QTest::addColumn("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("polygon"); + QTest::addColumn("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("polygon"); + QTest::addColumn("otherPolygon"); + QTest::addColumn("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("polygon"); + QTest::addColumn("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("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("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("variant"); + QTest::addColumn("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("extension"); + QTest::addColumn("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("extension"); + QTest::addColumn("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 +#include +#include +#include +#include // qSmartMin functions... +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) +#include +#endif +#ifdef Q_WS_X11 +#include +#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 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("widgetExists"); + QTest::addColumn("insertWidget"); + QTest::addColumn("hasParent"); + QTest::addColumn("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 proxy = new SubQGraphicsProxyWidget; + SubQGraphicsProxyWidget parentProxy; + scene.addItem(proxy); + scene.addItem(&parentProxy); + if (proxyHasParent) + proxy->setParent(&parentProxy); + QPointer 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(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("eventType"); + QTest::addColumn("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("widgetHasFocus"); + QTest::addColumn("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("hasWidget"); + QTest::addColumn("hasScene"); + QTest::addColumn("next"); + QTest::addColumn("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("

old foo new

"); + 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("hasWidget"); + QTest::addColumn("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("hasWidget"); + QTest::addColumn("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("hasWidget"); + QTest::addColumn("hoverEnabled"); + QTest::addColumn("mouseTracking"); + QTest::addColumn("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("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("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("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("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("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("which"); + QTest::addColumn("constraint"); + QTest::addColumn("sizeHint"); + QTest::addColumn("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(0, 0, 200, 12) << QRect(0, 12, 102, 10)); + QCOMPARE(widget->npaints, 2); + QCOMPARE(widget->paintEventRegion.rects(), + QVector() << 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 lineEdit = new QLineEdit; + QPointer 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 proxy = scene.addWidget(lineEdit2); + + delete lineEdit2; + QVERIFY(!proxy); +} + +void tst_QGraphicsProxyWidget::resize_simple_data() +{ + QTest::addColumn("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(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(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(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("moveCombo"); + QTest::addColumn("comboPos"); + QTest::addColumn("proxyPos"); + QTest::addColumn("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(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(static_cast(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(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) +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"); + QSignalSpy signalSpy(&scene, SIGNAL(changed(const QList &))); + + 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 arguments = signalSpy.takeFirst(); + const QList updateRects = qvariant_cast >(arguments.at(0)); + QCOMPARE(updateRects.size(), 1); + QCOMPARE(updateRects.at(0), proxy->sceneBoundingRect()); +} + +void tst_QGraphicsProxyWidget::stylePropagation() +{ + QPointer 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 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(this)) + embeddedPopup = true; + hide(); + } +}; + +void tst_QGraphicsProxyWidget::actionsContextMenu_data() +{ + QTest::addColumn("actionsContextMenu"); + QTest::addColumn("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("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("proxyFlags"); + QTest::addColumn("widgetFlags"); + QTest::addColumn("resultingProxyFlags"); + QTest::addColumn("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(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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data 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 @@ + + + Ash_European.jpg + + 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png 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 Binary files /dev/null and b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png 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 +#if defined(Q_OS_WINCE) +#include +#endif + +#include +#include +#include +#include +#include +#include "../../../gui/painting/qpathclipper/pathcompare.h" + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#include +#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) +Q_DECLARE_METATYPE(QList) +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 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 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 items; + items< >("rects"); + QTest::addColumn("matrix"); + QTest::addColumn("boundingRect"); + + QMatrix transformationMatrix; + transformationMatrix.translate(50, -50); + transformationMatrix.scale(2, 2); + transformationMatrix.rotate(90); + + QTest::newRow("none") + << QList() + << QMatrix() + << QRectF(); + QTest::newRow("{{0, 0, 10, 10}}") + << (QList() << QRectF(0, 0, 10, 10)) + << QMatrix() + << QRectF(0, 0, 10, 10); + QTest::newRow("{{-10, -10, 10, 10}}") + << (QList() << QRectF(-10, -10, 10, 10)) + << QMatrix() + << QRectF(-10, -10, 10, 10); + QTest::newRow("{{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}") + << (QList() << 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(0, 0, 10, 10)) + << transformationMatrix + << QRectF(30, -50, 20, 20); + QTest::newRow("transformed {{-10, -10, 10, 10}}") + << (QList() << QRectF(-10, -10, 10, 10)) + << transformationMatrix + << QRectF(50, -70, 20, 20); + QTest::newRow("transformed {{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}") + << (QList() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10)) + << transformationMatrix + << QRectF(50, -2050, 2000, 2000); + + QList 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, 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 >("items"); + QTest::addColumn("point"); + QTest::addColumn >("itemsAtPoint"); + + QTest::newRow("empty") + << QList() + << QPointF() + << QList(); + QTest::newRow("1") + << (QList() << QRectF(0, 0, 10, 10)) + << QPointF(0, 0) + << (QList() << 0); + QTest::newRow("2") + << (QList() << QRectF(0, 0, 10, 10)) + << QPointF(5, 5) + << (QList() << 0); + QTest::newRow("3") + << (QList() << QRectF(0, 0, 10, 10)) + << QPointF(9.9, 9.9) + << (QList() << 0); + QTest::newRow("3.5") + << (QList() << QRectF(0, 0, 10, 10)) + << QPointF(10, 10) + << QList(); + QTest::newRow("4") + << (QList() << QRectF(0, 0, 10, 10) << QRectF(9.9, 9.9, 10, 10)) + << QPointF(9.9, 9.9) + << (QList() << 1 << 0); + QTest::newRow("4.5") + << (QList() << QRectF(0, 0, 10, 10) << QRectF(10, 10, 10, 10)) + << QPointF(10, 10) + << (QList() << 1); + QTest::newRow("5") + << (QList() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10)) + << QPointF(10, 10) + << (QList() << 1 << 0); + QTest::newRow("6") + << (QList() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10) << QRectF(0, 0, 20, 30)) + << QPointF(10, 10) + << (QList() << 2 << 1 << 0); +} + +void tst_QGraphicsScene::items_QPointF() +{ + QFETCH(QList, items); + QFETCH(QPointF, point); + QFETCH(QList, itemsAtPoint); + + QGraphicsScene scene; + + int n = 0; + QList 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 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() << item1); + QCOMPARE(scene.items(QRectF(10, -10, 10, 10)), QList() << item2); + QCOMPARE(scene.items(QRectF(10, 10, 10, 10)), QList() << item3); + QCOMPARE(scene.items(QRectF(-10, 10, 10, 10)), QList() << item4); + QCOMPARE(scene.items(QRectF(-10, -10, 1, 1)), QList() << item1); + QCOMPARE(scene.items(QRectF(10, -10, 1, 1)), QList() << item2); + QCOMPARE(scene.items(QRectF(10, 10, 1, 1)), QList() << item3); + QCOMPARE(scene.items(QRectF(-10, 10, 1, 1)), QList() << item4); + + QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList() << item2 << item1); + QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList() << item4 << item3); + + item1->setZValue(3); + item2->setZValue(2); + item3->setZValue(1); + item4->setZValue(0); + + QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList() << item1 << item2); + QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList() << item3 << item4); +} + +void tst_QGraphicsScene::items_QRectF_2_data() +{ + QTest::addColumn("ellipseRect"); + QTest::addColumn("sceneRect"); + QTest::addColumn("selectionMode"); + QTest::addColumn("contained"); + QTest::addColumn("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() << item1); + QCOMPARE(scene.items(poly2), QList() << item2); + QCOMPARE(scene.items(poly3), QList() << item3); + QCOMPARE(scene.items(poly4), QList() << 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() << item1); + QCOMPARE(scene.items(poly2), QList() << item2); + QCOMPARE(scene.items(poly3), QList() << item3); + QCOMPARE(scene.items(poly4), QList() << item4); + + poly1 = QPolygonF(QRectF(-10, -10, 40, 10)); + poly2 = QPolygonF(QRectF(-10, 10, 40, 10)); + + QCOMPARE(scene.items(poly1), QList() << item2 << item1); + QCOMPARE(scene.items(poly2), QList() << item4 << item3); + + item1->setZValue(3); + item2->setZValue(2); + item3->setZValue(1); + item4->setZValue(0); + + QCOMPARE(scene.items(poly1), QList() << item1 << item2); + QCOMPARE(scene.items(poly2), QList() << 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() << item1); + QCOMPARE(scene.items(path2), QList() << item2); + QCOMPARE(scene.items(path3), QList() << item3); + QCOMPARE(scene.items(path4), QList() << 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() << item1); + QCOMPARE(scene.items(path2), QList() << item2); + QCOMPARE(scene.items(path3), QList() << item3); + QCOMPARE(scene.items(path4), QList() << item4); + + path1 = QPainterPath(); path1.addRect(QRectF(-10, -10, 40, 10)); + path2 = QPainterPath(); path2.addRect(QRectF(-10, 10, 40, 10)); + + QCOMPARE(scene.items(path1), QList() << item2 << item1); + QCOMPARE(scene.items(path2), QList() << item4 << item3); + + item1->setZValue(3); + item2->setZValue(2); + item3->setZValue(1); + item4->setZValue(0); + + QCOMPARE(scene.items(path1), QList() << item1 << item2); + QCOMPARE(scene.items(path2), QList() << 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 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 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 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 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() << 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 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 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 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 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 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 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()); + QCOMPARE(emptyGroup->children(), QList()); + QVERIFY(!emptyGroup->parentItem()); + QCOMPARE(emptyGroup->scene(), &scene); +} + +class EventTester : public QGraphicsEllipseItem +{ +public: + EventTester() + : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false) + { } + + bool ignoreMouse; + QList 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 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 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("targetRect"); + QTest::addColumn("sourceRect"); + QTest::addColumn("aspectRatioMode"); + QTest::addColumn("matrix"); + QTest::addColumn("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"); + QSignalSpy spy(&scene, SIGNAL(changed(QList))); + + // 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 >(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 receivedSceneEvents; + QList 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(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(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(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 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("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() + << c_1_2 << c_1_1_1 << c_1 << t_1); + QCOMPARE(scene.items(-53, 47, 136, 3), + QList() + << 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() + << c_2_1_1 << c_1_1_1); + QCOMPARE(scene.items(-26, -3, 92, 79), + QList() + << 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 > changes; + +public slots: + void changed(const QList &dirty) + { + changes << dirty; + } +}; + +void tst_QGraphicsScene::changedSignal_data() +{ + QTest::addColumn("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 &)), &cl, SLOT(changed(const QList &))); + + 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("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("flags"); + QTest::addColumn("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(&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::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::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::GraphicsSceneHoverLeave); + QCOMPARE(tester2->eventTypes, QList() + << 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::GraphicsSceneHoverMove + << QEvent::GrabMouse + << QEvent::GraphicsSceneMousePress + << QEvent::UngrabMouse); + } +} + +void tst_QGraphicsScene::initialFocus_data() +{ + QTest::addColumn("activeScene"); + QTest::addColumn("explicitSetFocus"); + QTest::addColumn("isPanel"); + QTest::addColumn("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 children = item->childItems(); + QCOMPARE(children.count(), 10); + foreach (QGraphicsItem *child, children) + QVERIFY(!static_cast(child)->polished); + + QApplication::sendPostedEvents(&scene, QEvent::MetaCall); + foreach (QGraphicsItem *child, children) + QVERIFY(static_cast(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(&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(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 &)), &cl, SLOT(changed(const QList &))); + + 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 +#include +#include +#include +#include + +//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("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 +#include +#include + +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("axis"); + QTest::addColumn("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("axis"); + QTest::addColumn("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 + +#include +#include +#include +#include +#include +#include + +#include + +#include +#if !defined(QT_NO_STYLE_MOTIF) +#include +#endif +#if !defined(QT_NO_STYLE_WINDOWS) +#include +#endif +#if !defined(QT_NO_STYLE_PLASTIQUE) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../platformquirks.h" + +//TESTED_CLASS= +//TESTED_FILES= + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +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 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 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(&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()); + sendMousePress(view.viewport(), QPoint(), Qt::LeftButton); + sendMouseMove(view.viewport(), view.viewport()->rect().center(), + Qt::LeftButton, Qt::LeftButton); + QCOMPARE(scene.selectedItems(), QList() << 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()); + sendMouseMove(view.viewport(), view.viewport()->rect().center(), + Qt::LeftButton, Qt::LeftButton); + QCOMPARE(scene.selectedItems(), QList()); + sendMouseMove(view.viewport(), view.viewport()->rect().bottomRight(), + Qt::LeftButton, Qt::LeftButton); + QCOMPARE(scene.selectedItems(), QList() << 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 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 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("updateRect"); + QTest::addColumn("numPaints"); + QTest::addColumn("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 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 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("viewRect"); + QTest::addColumn("scenePoly"); + QTest::addColumn("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(&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(&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 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(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("savePainter"); + QTest::addColumn("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("transform"); + QTest::addColumn("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(&w3)); + w2.setFlag(QGraphicsItem::ItemIgnoresTransformations, true); + QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(), + static_cast(&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(&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(&widget)); + widget.focusNextPrevChild(true); + QCOMPARE(static_cast(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 > changes; + +public slots: + void changed(const QList &dirty) + { + changes << dirty; + } +}; + +void tst_QGraphicsView::task239729_noViewUpdate_data() +{ + QTest::addColumn("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 &)), &cl, SLOT(changed(const QList &))); + } else { + connect(&scene, SIGNAL(changed(const QList &)), &cl, SLOT(changed(const QList &))); + 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 itemsAtCenter = view.items(view.viewport()->rect().center()); + QCOMPARE(itemsAtCenter, (QList() << child << parent)); + + QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1))); + QList 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("reverse"); + QTest::addColumn("x1"); + QTest::addColumn("x2"); + QTest::addColumn("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("adjustForAntialiasing"); + QTest::addColumn("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)), 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("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(&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(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("penWidth"); + QTest::addColumn("antialiasing"); + QTest::addColumn("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)), 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(scene.addRect(0, 0, 50, 50)); + grandParent->setBrush(Qt::black); + grandParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape); + + QGraphicsRectItem *parent = static_cast(scene.addRect(-50, -50, 100, 100)); + parent->setBrush(QColor(0, 0, 255, 125)); + parent->setParentItem(grandParent); + parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape); + + QGraphicsRectItem *child = static_cast(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(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(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(&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(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(item2)); + + scene.setFocusItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true); + QCOMPARE(scene.focusItem(), static_cast(item)); + + view.setScene(0); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + QCOMPARE(scene.focusItem(), static_cast(item)); + + view.setScene(&scene); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true); + QCOMPARE(scene.focusItem(), static_cast(item)); + + scene.setFocusItem(item2); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false); + QCOMPARE(scene.focusItem(), static_cast(item2)); + + view.setScene(0); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + QCOMPARE(scene.focusItem(), static_cast(item2)); + + scene.setFocusItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + QCOMPARE(scene.focusItem(), static_cast(item)); + + view.setScene(&scene); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true); + QCOMPARE(scene.focusItem(), static_cast(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(&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)), &dummyView, SLOT(updateScene(QList))); + view.setScene(&scene1); + + QTest::qWait(12); + + QGraphicsScene scene2; + QObject::connect(&scene2, SIGNAL(changed(QList)), &dummyView, SLOT(updateScene(QList))); + view.setScene(&scene2); + + QTest::qWait(12); + + bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList)), &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("clip"); + QTest::addColumn("ignoreTransformations"); + QTest::addColumn("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(event)->widget(); + } else if (event->type() == QEvent::GraphicsSceneHoverLeave) { + receivedLeaveEvent = true; + leaveWidget = static_cast(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 +#include +#include +#include + +#ifdef Q_OS_WINCE +#include + +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) +Q_DECLARE_METATYPE(QList) +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("viewportSize"); + QTest::addColumn("sceneRect"); + QTest::addColumn("transform"); + QTest::addColumn("hbarpolicy"); + QTest::addColumn("vbarpolicy"); + QTest::addColumn("hmin"); + QTest::addColumn("hmax"); + QTest::addColumn("vmin"); + QTest::addColumn("vmax"); + QTest::addColumn("useMotif"); + QTest::addColumn("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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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("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("scene"); + QTest::addColumn("children"); + QTest::addColumn("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("childCount"); + QTest::addColumn("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 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(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("focusPolicy1"); + QTest::addColumn("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("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("pos"); + QTest::addColumn("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("left"); + QTest::addColumn("top"); + QTest::addColumn("right"); + QTest::addColumn("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, >op, &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, >op, &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("enabled"); + QTest::addColumn("focus"); + QTest::addColumn("underMouse"); + QTest::addColumn("layoutDirection"); + QTest::addColumn("size"); + QTest::addColumn("palette"); + QTest::addColumn("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("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 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(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("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 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("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(&standAlongWidget)); + QCOMPARE(itemChild.parentWidget(), (QGraphicsWidget*)0); + + for (int i = 0; i < childrenCount; ++i) { + SubQGraphicsWidget *item = new SubQGraphicsWidget(&standAlongWidget); + QCOMPARE(item->parentWidget(), static_cast(&standAlongWidget)); + } +} + +void tst_QGraphicsWidget::resize_data() +{ + QTest::addColumn("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("attribute"); + QTest::addColumn("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("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(&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("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 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 &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() << w1 << w2 << w3)); + + QGraphicsWidget *p = new QGraphicsWidget; + p->setData(0, QLatin1String("parent")); + p->setFocusPolicy(Qt::StrongFocus); + + w1->setFocus(); + QVERIFY(compareFocusChain(&view, QList() << w1 << w2 << w3)); + + w1->setParentItem(p); + w2->setFocus(); + QVERIFY(compareFocusChain(&view, QList() << w2 << w3)); + + w2->setParentItem(p); + w3->setFocus(); + QVERIFY(compareFocusChain(&view, QList() << w3)); + w3->setParentItem(p); + QCOMPARE(scene.focusItem(), static_cast(0)); + + scene.addItem(p); + p->setFocus(); + + QVERIFY(compareFocusChain(&view, QList() << 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() << 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() << w2 << w3)); + + scene.addItem(p); + w2->setFocus(); + QVERIFY(compareFocusChain(&view, QList() << w2 << w3 << p << w1 << w4)); +} + +void tst_QGraphicsWidget::topLevelWidget_data() +{ + QTest::addColumn("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("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 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("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() << 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() << 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(&view)); + QTRY_COMPARE(scene.focusItem(), static_cast(w)); +} + +void tst_QGraphicsWidget::sizeHint_data() +{ + QTest::addColumn("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("minSize"); + QTest::addColumn("maxSize"); + QTest::addColumn("geometry"); + QTest::addColumn("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 Inst; + +Q_DECLARE_METATYPE(Inst) +Q_DECLARE_METATYPE(QVector) + +void tst_QGraphicsWidget::setSizes_data() +{ + + QTest::addColumn >("inputInstructions"); + QTest::addColumn >("compareInstructions"); + + QTest::newRow("minSize1") << (QVector() << Inst(Size, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10))) + << (QVector() << Inst(Size, QSize(25,25))); + QTest::newRow("minSize2") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumSize, QSizeF(25, 25))) + << (QVector() << Inst(Size, QSizeF(25, 25))); + QTest::newRow("minWidth1") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0)) + << (QVector() << Inst(Size, QSizeF(20, 20))); + QTest::newRow("minWidth2") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0)) + << (QVector() << Inst(Size, QSizeF(25, 20))); + QTest::newRow("minHeight1") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0)) + << (QVector() << Inst(Size, QSizeF(20, 20))); + QTest::newRow("minHeight2") << (QVector() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0)) + << (QVector() << Inst(Size, QSizeF(20, 25))); + QTest::newRow("maxSize1") << (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, 30))) + << (QVector() << Inst(Size, QSizeF(30, 30))); + QTest::newRow("maxSize2") << (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, -1))) + << (QVector() << Inst(Size, QSizeF(30, 40))); + QTest::newRow("maxSize3") << (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, 30))) + << (QVector() << Inst(Size, QSizeF(40, 30))); + QTest::newRow("maxWidth1")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumWidth, 30)) + << (QVector() << Inst(Size, QSizeF(30, 40))); + QTest::newRow("maxHeight")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumHeight, 20)) + << (QVector() << Inst(Size, QSizeF(40, 20))); + QTest::newRow("unsetMinSize")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MinimumSize, QSizeF(-1, -1))) + << (QVector() << Inst(MinimumSize, QSizeF(5, 5))); + QTest::newRow("unsetMaxSize")<< (QVector() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, -1))) + << (QVector() << Inst(MaximumSize, QSizeF(500, 500))); + QTest::newRow("unsetMinSize, expand size to minimumSizeHint") << (QVector() + << Inst(MinimumSize, QSize(0, 0)) + << Inst(Size, QSize(1,1)) + << Inst(MinimumSize, QSize(-1.0, -1.0)) + ) + << (QVector() + << Inst(Size, QSize(5,5)) + << Inst(MinimumSize, QSize(5,5)) + ); + +} + +void tst_QGraphicsWidget::setSizes() +{ + QFETCH(QVector, inputInstructions); + QFETCH(QVector, 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("inputFlags"); + QTest::addColumn("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 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 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 changes; + QList values; + QList 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::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 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 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 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(item->valueDuringEvents.value(QEvent::ParentAboutToChange)), + static_cast(0)); + // ParentChange should be triggered after the parent has changed + QTRY_COMPARE(qVariantValue(item->valueDuringEvents.value(QEvent::ParentChange)), + static_cast(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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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 ¤t, 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(&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("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(new QListView()); + else if (viewType == "QTableView") + view = reinterpret_cast(new QTableView()); + else if (viewType == "QTreeView") + view = reinterpret_cast(new QTreeView()); + else if (viewType == "QHeaderView") + view = reinterpret_cast(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("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(new QListView()); + else if (viewType == "QTableView") + view = reinterpret_cast(new QTableView()); + else if (viewType == "QTreeView") + view = reinterpret_cast(new QTreeView()); + else if (viewType == "QHeaderView") + view = reinterpret_cast(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 list = qFindChildren(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(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 IntList; +Q_DECLARE_METATYPE(IntList) + +void tst_QAbstractItemView::setItemDelegate_data() +{ + // default is rows, a -1 will switch to columns + QTest::addColumn("rowsOrColumnsWithDelegate"); + QTest::addColumn("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("viewType"); + QTest::addColumn("itemFlags"); + QTest::addColumn("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(new QListView()); + else if (viewType == "QTableView") + view = reinterpret_cast(new QTableView()); + else if (viewType == "QTreeView") + view = reinterpret_cast(new QTreeView()); + else if (viewType == "QHeaderView") + view = reinterpret_cast(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 lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); + + QTest::qWait(30); + + treeView.edit(model.index(1,0)); + lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); + + QTest::qWait(30); + + treeView.edit(model.index(2,0)); + lineEditors = qFindChildren(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(&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 +#include +#include +#include + +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("proxyIndex"); + QTest::addColumn("role"); + QTest::addColumn("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("index"); + QTest::addColumn("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("section"); + QTest::addColumn("orientation"); + QTest::addColumn("role"); + QTest::addColumn("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("index"); + QTest::addColumn("count"); + + QTest::newRow("null") << QModelIndex() << 0; +} + +// public QMap 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("sourceIndex"); + QTest::addColumn("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("selection"); + QTest::addColumn("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("selection"); + QTest::addColumn("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("proxyIndex"); + QTest::addColumn("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("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("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(sourceModel)); + + QStandardItemModel *sourceModel2 = new QStandardItemModel(&model); + model.setSourceModel(sourceModel2); + QCOMPARE(model.sourceModel(), static_cast(sourceModel2)); + + delete sourceModel2; + QCOMPARE(model.sourceModel(), static_cast(0)); +} + +void tst_QAbstractProxyModel::submit_data() +{ + QTest::addColumn("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 _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 _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 &superSet, const QHash &subSet) +{ + QHash::const_iterator it = subSet.constBegin(); + const QHash::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 rootModelRoleNames = model.roleNames(); + QHash 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 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 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 +#include +#include +#include +#include "../../../src/widgets/itemviews/qcolumnviewgrip_p.h" +#include "../../../src/widgets/dialogs/qfilesystemmodel_p.h" +#include +#include +#include +#include +#include +#include + +//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 > 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 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(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(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("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("reverse"); + QTest::addColumn("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("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"); + 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("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(list[i]))) { + break; + } + } + if (!grip) + return; + + QAbstractItemView *column = qobject_cast(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 newSizes; + newSizes << 10 << 4 << 50 << 6; + + QList visibleSizes; + view.setColumnWidths(newSizes); + QCOMPARE(view.columnWidths(), visibleSizes); + + QDirModel model; + view.setModel(&model); + QModelIndex home = model.index(QDir::homePath()); + view.setCurrentIndex(home); + + QList postSizes = view.columnWidths().mid(0, newSizes.count()); + QCOMPARE(postSizes, newSizes.mid(0, postSizes.count())); + + QVERIFY(view.columnWidths().count() > 1); + QList smallerSizes; + smallerSizes << 6; + view.setColumnWidths(smallerSizes); + QList 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 > old = view.createdColumns; + view.setCurrentIndex(second); + + QCOMPARE(old, view.createdColumns); +} + +void tst_QColumnView::parentCurrentIndex_data() +{ + QTest::addColumn("firstRow"); + QTest::addColumn("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("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 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 +#include +#include + +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(&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(&lineEdit1)); + QCOMPARE(mapper.mappedWidgetAt(2), static_cast(&lineEdit2)); + + mapper.addMapping(&lineEdit2, 4242); + + QCOMPARE(mapper.mappedWidgetAt(2), (QWidget*)0); + QCOMPARE(mapper.mappedWidgetAt(4242), static_cast(&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 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 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 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 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 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 +#include +#include +#include +#include +#include + +//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("dirName"); // the directory to be made under /dirtest + QTest::addColumn("mkdirSuccess"); + QTest::addColumn("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("dirName"); // /dirtest/dirname + QTest::addColumn("rmdirSuccess"); + QTest::addColumn("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("test_path"); + QTest::addColumn("initial_files"); + QTest::addColumn("remove_row"); + QTest::addColumn("remove_files"); + QTest::addColumn("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"); + + // 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("path"); + QTest::addColumn("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("role"); + QTest::addColumn("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 roles = model.roleNames(); + + QFETCH(int, role); + QVERIFY(roles.contains(role)); + + QFETCH(QByteArray, roleName); + QList 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 +#include +#include + +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("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("info"); + QTest::addColumn("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("info"); + // Return value is _very_ system dependent, hard to test + // QTest::addColumn("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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef QList IntList; +Q_DECLARE_METATYPE(IntList) + +typedef QList 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("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 >("boundsCheck"); + QTest::addColumn >("defaultSizes"); + QTest::addColumn("initialDefaultSize"); + QTest::addColumn("lastVisibleSectionSize"); + QTest::addColumn("persistentSectionSize"); + + QTest::newRow("data set one") + << (QList() << -1 << 0 << 4 << 9999) + << (QList() << 10 << 30 << 30) + << 30 + << 300 + << 20; +} + +void tst_QHeaderView::sectionSize() +{ + QFETCH(QList, boundsCheck); + QFETCH(QList, 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 >("hidden"); + QTest::addColumn >("from"); + QTest::addColumn >("to"); + QTest::addColumn >("coordinate"); + QTest::addColumn >("visual"); + + QList 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() + << QList() + << QList() + << coordinateList + << (QList() << -1 << 0 << 1 << 3 << -1); + + QTest::newRow("no hidden, moved sections") + << QList() + << (QList() << 0) + << (QList() << 1) + << coordinateList + << (QList() << -1 << 0 << 1 << 3 << -1); + + QTest::newRow("hidden, no moved sections") + << (QList() << 0) + << QList() + << QList() + << coordinateList + << (QList() << -1 << 1 << 2 << 3 << -1); +} + +void tst_QHeaderView::visualIndexAt() +{ + QFETCH(QList, hidden); + QFETCH(QList, from); + QFETCH(QList, to); + QFETCH(QList, coordinate); + QFETCH(QList, 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 logical = (QVector() << 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() << 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 >("hidden"); + QTest::addColumn >("from"); + QTest::addColumn >("to"); + QTest::addColumn >("moved"); + QTest::addColumn >("logical"); + QTest::addColumn("count"); + + QTest::newRow("bad args, no hidden") + << QList() + << (QList() << -1 << 1 << 99999 << 1) + << (QList() << 1 << -1 << 1 << 99999) + << (QList() << false << false << false << false) + << (QList() << 0 << 1 << 2 << 3) + << 0; + + QTest::newRow("good args, no hidden") + << QList() + << (QList() << 1 << 1 << 2 << 1) + << (QList() << 1 << 2 << 1 << 2) + << (QList() << false << true << true << true) + << (QList() << 0 << 2 << 1 << 3) + << 3; + + QTest::newRow("hidden sections") + << (QList() << 0 << 3) + << (QList() << 1 << 1 << 2 << 1) + << (QList() << 1 << 2 << 1 << 2) + << (QList() << false << true << true << true) + << (QList() << 0 << 2 << 1 << 3) + << 3; +} + +void tst_QHeaderView::moveSection() +{ + QFETCH(QList, hidden); + QFETCH(QList, from); + QFETCH(QList, to); + QFETCH(QList, moved); + QFETCH(QList, 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("logicalIndexes"); + QTest::addColumn("sizes"); + QTest::addColumn("logicalFrom"); + QTest::addColumn("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("section"); + QTest::addColumn("initialSize"); + QTest::addColumn("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("section"); + QTest::addColumn("size"); + QTest::addColumn("insert"); + QTest::addColumn("compare"); + QTest::addColumn("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("size"); + QTest::addColumn >("sections"); + QTest::addColumn >("modes"); + QTest::addColumn >("expected"); + + QTest::newRow("stretch first section") + << 600 + << (QList() << 100 << 100 << 100 << 100) + << (QList() << ((int)QHeaderView::Stretch) + << ((int)QHeaderView::Interactive) + << ((int)QHeaderView::Interactive) + << ((int)QHeaderView::Interactive)) + << (QList() << 300 << 100 << 100 << 100); +} + +void tst_QHeaderView::resizeWithResizeModes() +{ + QFETCH(int, size); + QFETCH(QList, sections); + QFETCH(QList, modes); + QFETCH(QList, 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("from"); + QTest::addColumn("to"); + QTest::addColumn("insert"); + QTest::addColumn >("mapping"); + + QTest::newRow("move from 1 to 3, insert 0") + << 1 << 3 << 0 <<(QList() << 0 << 1 << 3 << 4 << 2); + +} + +void tst_QHeaderView::moveAndInsertSection() +{ + QFETCH(int, from); + QFETCH(int, to); + QFETCH(int, insert); + QFETCH(QList, 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("initial"); + QTest::addColumn >("logical"); + QTest::addColumn >("size"); + QTest::addColumn >("mode"); + QTest::addColumn("resized"); + QTest::addColumn >("expected"); + + QTest::newRow("bad args") + << 100 + << (QList() << -1 << -1 << 99999 << 99999 << 4) + << (QList() << -1 << 0 << 99999 << -1 << -1) + << (QList() + << int(QHeaderView::Interactive) + << int(QHeaderView::Interactive) + << int(QHeaderView::Interactive) + << int(QHeaderView::Interactive)) + << 0 + << (QList() << 0 << 0 << 0 << 0 << 0); +} + +void tst_QHeaderView::resizeSection() +{ + + QFETCH(int, initial); + QFETCH(QList, logical); + QFETCH(QList, size); + QFETCH(QList, mode); + QFETCH(int, resized); + QFETCH(QList, 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("direction"); + QTest::addColumn("initial"); + QTest::addColumn("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("direction"); + QTest::addColumn("mode"); + QTest::addColumn("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("direction"); + QTest::addColumn("clickable"); + QTest::addColumn("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("direction"); + QTest::addColumn("oldDefaultSize"); + QTest::addColumn("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("direction"); + QTest::addColumn("hide"); + QTest::addColumn("insert"); + QTest::addColumn("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 >("hide1"); + QTest::addColumn >("hide2"); + + QTest::newRow("set 1") << (QList() << 1 << 3) + << (QList() << 1 << 5); + + QTest::newRow("set 2") << (QList() << 2 << 3) + << (QList() << 1 << 5); + + QTest::newRow("set 3") << (QList() << 0 << 2 << 4) + << (QList() << 2 << 3 << 5); + +} + +void tst_QHeaderView::task236450_hidden() +{ + QFETCH(QList, hide1); + QFETCH(QList, 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 &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() << 2 << 4 << 0 << 3 << 1 << 5) , 0); + + proxy.setSourceModel(&model2); + QApplication::processEvents(); + QCOMPARE(checkHeaderViewOrder(&view, QVector() << 2 << 0 << 1 ) , 0); + + proxy.setSourceModel(&model1); + QApplication::processEvents(); + QCOMPARE(checkHeaderViewOrder(&view, QVector() << 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 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 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 +** 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 +#include +#include +#include + +#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"); + + 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() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value())); + QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1)); + QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2)); + + QVERIFY(modelAfterSpy.first().first().value() == m_proxy->mapToSource(proxyAfterSpy.first().first().value())); + 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() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value())); + QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1)); + QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2)); + + QVERIFY(modelAfterSpy.first().first().value() == m_proxy->mapToSource(proxyAfterSpy.first().first().value())); + 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() << 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() << 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() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value())); + QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1)); + QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2)); + QVERIFY(modelBeforeSpy.first().at(3).value() == m_proxy->mapToSource(proxyBeforeSpy.first().at(3).value())); + QVERIFY(modelBeforeSpy.first().at(4) == proxyBeforeSpy.first().at(4)); + + QVERIFY(modelAfterSpy.first().first().value() == m_proxy->mapToSource(proxyAfterSpy.first().first().value())); + QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1)); + QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2)); + QVERIFY(modelAfterSpy.first().at(3).value() == m_proxy->mapToSource(proxyAfterSpy.first().at(3).value())); + 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() << 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() << 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint) + +//TESTED_CLASS= +//TESTED_FILES= + +#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) +#include +#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("text"); + QTest::addColumn("rect"); + QTest::addColumn("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("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("initial"); + QTest::addColumn("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 lineEditors = qFindChildren(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 editors = qFindChildren(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("itemText"); + QTest::addColumn("properties"); + QTest::addColumn("itemFont"); + QTest::addColumn("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("position"); + QTest::addColumn("direction"); + QTest::addColumn("hint"); + QTest::addColumn("itemRect"); + QTest::addColumn("checkRect"); + QTest::addColumn("pixmapRect"); + QTest::addColumn("textRect"); + QTest::addColumn("expectedCheckRect"); + QTest::addColumn("expectedPixmapRect"); + QTest::addColumn("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("role"); + QTest::addColumn("size"); + QTest::addColumn("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"); + + 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("time"); + QTest::addColumn("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(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(widget.viewport()); + QVERIFY(dateEditor); + QCOMPARE(dateEditor->date(), date); + + widget.clearFocus(); + widget.setFocus(); + widget.editItem(item3); + + QTestEventLoop::instance().enterLoop(1); + + QList dateTimeEditors = widget.findChildren(); + 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("type"); + QTest::addColumn("size"); + QTest::addColumn("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(&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("rect"); + QTest::addColumn("text"); + QTest::addColumn("checkState"); + QTest::addColumn("flags"); + QTest::addColumn("inCheck"); + QTest::addColumn("type"); + QTest::addColumn("button"); + QTest::addColumn("edited"); + QTest::addColumn("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("widget"); + QTest::addColumn("key"); + QTest::addColumn("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 lineEditors = qFindChildren(view.viewport(), QString::fromLatin1("TheEditor")); + QCOMPARE(lineEditors.count(), 1); + + QPointer 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 lineEditors = qFindChildren(view.viewport()); + QCOMPARE(lineEditors.count(), 1); + + QPointer 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 +#include +#include + +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 +{ +}; + +void tst_QItemEditorFactory::createCustomEditor() +{ + QPointer creator = new MyEditor; + QPointer 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 + +#include +#include + +//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 IntList; +typedef QPair IntPair; +typedef QList 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(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(ptr)); + return s; +} + +QDataStream &operator<<(QDataStream &s, const QModelIndexList &input) +{ + s << input.count(); + for (int i=0; i>(QDataStream &s, QModelIndexList &output) +{ + QModelIndex tmpIndex; + int count; + s >> count; + for (int i=0; i> 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"); + + 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("indexList"); + QTest::addColumn("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; iselect(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("indexList"); + QTest::addColumn("useRanges"); + QTest::addColumn("commandList"); + QTest::addColumn("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; iselect(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; iisSelected(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; iisRowSelected(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; iisColumnSelected(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("indexList"); + QTest::addColumn("commandList"); + QTest::addColumn("insertRows"); // start, count + QTest::addColumn("insertColumns"); // start, count + QTest::addColumn("deleteRows"); // start, count + QTest::addColumn("deleteColumns"); // start, count + QTest::addColumn("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; iindex(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()); + QVERIFY(qvariant_cast(spy.at(1).at(1)).isEmpty()); +} + +void tst_QItemSelectionModel::removeRows_data() +{ + QTest::addColumn("rowCount"); + QTest::addColumn("columnCount"); + + QTest::addColumn("selectTop"); + QTest::addColumn("selectLeft"); + QTest::addColumn("selectBottom"); + QTest::addColumn("selectRight"); + + QTest::addColumn("removeTop"); + QTest::addColumn("removeBottom"); + + QTest::addColumn("expectedTop"); + QTest::addColumn("expectedLeft"); + QTest::addColumn("expectedBottom"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + + QTest::addColumn("selectTop"); + QTest::addColumn("selectLeft"); + QTest::addColumn("selectBottom"); + QTest::addColumn("selectRight"); + + QTest::addColumn("removeLeft"); + QTest::addColumn("removeRight"); + + QTest::addColumn("expectedTop"); + QTest::addColumn("expectedLeft"); + QTest::addColumn("expectedBottom"); + QTest::addColumn("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 IntListList; +typedef QPair IntPairPair; +typedef QList IntPairPairList; +Q_DECLARE_METATYPE(IntListList) +Q_DECLARE_METATYPE(IntPairPair) +Q_DECLARE_METATYPE(IntPairPairList) + +void tst_QItemSelectionModel::modelLayoutChanged_data() +{ + QTest::addColumn("items"); + QTest::addColumn("initialSelectedRanges"); + QTest::addColumn("sortOrder"); + QTest::addColumn("sortColumn"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("column"); + QTest::addColumn("selectRows"); + QTest::addColumn("expectedRows"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("selectColumns"); + QTest::addColumn("expectedColumns"); + QTest::addColumn("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("init"); + QTest::addColumn("other"); + QTest::addColumn("command"); + QTest::addColumn("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 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 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() << &sub11 << &sub12 << &sub13 << &sub14); + top2.appendColumn(QList() << &sub21 << &sub22 << &sub23 << &sub24); + model.appendColumn(QList() << &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 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 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("parent1"); + QTest::addColumn("top1"); + QTest::addColumn("left1"); + QTest::addColumn("bottom1"); + QTest::addColumn("right1"); + QTest::addColumn("parent2"); + QTest::addColumn("top2"); + QTest::addColumn("left2"); + QTest::addColumn("bottom2"); + QTest::addColumn("right2"); + QTest::addColumn("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() << &top11 << &top12 << &top13); + model2.appendColumn(QList() << &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 +#include +#include "viewstotest.cpp" +#include + +#if defined(Q_OS_UNIX) +#include +#endif +#if defined(Q_OS_WIN) +#include +#if defined(Q_OS_WINCE) +#include +#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 (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("viewType"); + QTest::addColumn("displays"); + QTest::addColumn("vscroll"); + QTest::addColumn("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 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 +#include +#include +#include + +/* + 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 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(view)) { + tableView->setColumnHidden(1, true); + tableView->setRowHidden(1, true); + tableView->setRowHidden(tableView->model()->rowCount()-2, true); + } + if (QTreeView *treeView = qobject_cast(view)) { + treeView->setColumnHidden(1, true); + treeView->setRowHidden(1, QModelIndex(), true); + treeView->setRowHidden(treeView->model()->rowCount()-2, QModelIndex(), true); + } + if (QListView *listView = qobject_cast(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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) +# include +# include +# include +#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 (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 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"); + + 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 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 IntList; +Q_DECLARE_METATYPE(IntList) + +void tst_QListView::selection_data() +{ + QTest::addColumn("itemCount"); + QTest::addColumn("viewMode"); + QTest::addColumn("flow"); + QTest::addColumn("wrapping"); + QTest::addColumn("spacing"); + QTest::addColumn("gridSize"); + QTest::addColumn("hiddenRows"); + QTest::addColumn("selectionRect"); + QTest::addColumn("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("size"); + QTest::addColumn("itemCount"); + QTest::addColumn("flow"); + QTest::addColumn("horizontalScrollBarVisible"); + QTest::addColumn("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() << &sub1); + model.appendColumn(QList() << &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(&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("flow"); + + QTest::newRow("TopToBottom") << static_cast(QListView::TopToBottom); + QTest::newRow("LeftToRight") << static_cast(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(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 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(&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() + << 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 +#include +#include +#include +#include + +#include +#include + +//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 rcParent; + QVector rcFirst; + QVector rcLast; + + void populate(); + void checkDefaultValues(); +}; + + +typedef QList 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("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("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("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 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("initialItems"); + QTest::addColumn("insertIndex"); + QTest::addColumn("itemLabel"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("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; iinsertItems(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; iinsertItems(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; icount(); ++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("row"); + QTest::addColumn("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(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("row"); + QTest::addColumn("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(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("itemCount"); + QTest::addColumn("hiddenRows"); + QTest::addColumn("selectedRows"); + QTest::addColumn("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; isetSelectionMode(QListWidget::SingleSelection); + for (int i=0; iitem(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 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; iitem(i); + if (testWidget->isItemSelected(item)) + QVERIFY(selectedItems.contains(item)); + } +} + +void tst_QListWidget::removeItems_data() +{ + QTest::addColumn("rowCount"); + QTest::addColumn("removeRows"); + QTest::addColumn("row"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("srcRow"); + QTest::addColumn("dstRow"); + QTest::addColumn("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(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 &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 &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("text"); + QTest::addColumn("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("order"); + QTest::addColumn("initialList"); + QTest::addColumn("expectedList"); + QTest::addColumn("expectedRows"); + + QTest::newRow("ascending strings") + << static_cast(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(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(Qt::AscendingOrder) + << (QVariantList() << 1 << 11 << 2 << 22) + << (QVariantList() << 1 << 2 << 11 << 22) + << (IntList() << 0 << 2 << 1 << 3); + + QTest::newRow("descending numbers") + << static_cast(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 persistent; + for (int j = 0; j < model->rowCount(QModelIndex()); ++j) + persistent << model->index(j, 0, QModelIndex()); + + testWidget->sortItems(static_cast(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("order"); + QTest::addColumn("initialList"); + QTest::addColumn("expectedList"); + QTest::addColumn("expectedRows"); + QTest::addColumn("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(Qt::DescendingOrder) + << initial + << expected + << rowOrder + << visible; + + QTest::newRow("ascending order") + << static_cast(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(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 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(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("initialItems"); + QTest::addColumn("itemIndex"); + QTest::addColumn("roles"); + QTest::addColumn("values"); + QTest::addColumn("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*"); + qRegisterMetaType("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("sortOrder"); + QTest::addColumn("initialItems"); + QTest::addColumn("insertItems"); + QTest::addColumn("expectedItems"); + QTest::addColumn("expectedRows"); + + QTest::newRow("() + (a) = (a)") + << static_cast(Qt::AscendingOrder) + << QStringList() + << (QStringList() << "a") + << (QStringList() << "a") + << IntList(); + QTest::newRow("() + (c, b, a) = (a, b, c)") + << static_cast(Qt::AscendingOrder) + << QStringList() + << (QStringList() << "c" << "b" << "a") + << (QStringList() << "a" << "b" << "c") + << IntList(); + QTest::newRow("() + (a, b, c) = (c, b, a)") + << static_cast(Qt::DescendingOrder) + << QStringList() + << (QStringList() << "a" << "b" << "c") + << (QStringList() << "c" << "b" << "a") + << IntList(); + QTest::newRow("(a) + (b) = (a, b)") + << static_cast(Qt::AscendingOrder) + << QStringList("a") + << (QStringList() << "b") + << (QStringList() << "a" << "b") + << (IntList() << 0); + QTest::newRow("(a) + (b) = (b, a)") + << static_cast(Qt::DescendingOrder) + << QStringList("a") + << (QStringList() << "b") + << (QStringList() << "b" << "a") + << (IntList() << 1); + QTest::newRow("(a, c, b) + (d) = (a, b, c, d)") + << static_cast(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(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(Qt::AscendingOrder) + << QStringList() + << ascendingItems + << ascendingItems + << IntList(); + QTest::newRow("(sorted items) + () = (sorted items)") + << static_cast(Qt::AscendingOrder) + << ascendingItems + << QStringList() + << ascendingItems + << ascendingRows; + QTest::newRow("() + (ascending items) = (reverse items)") + << static_cast(Qt::DescendingOrder) + << QStringList() + << ascendingItems + << reverseItems + << IntList(); + QTest::newRow("(reverse items) + () = (ascending items)") + << static_cast(Qt::AscendingOrder) + << reverseItems + << QStringList() + << ascendingItems + << ascendingRows; + QTest::newRow("(reverse items) + () = (reverse items)") + << static_cast(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(sortOrder)); + w.addItems(initialItems); + + QAbstractItemModel *model = w.model(); + QList 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("sortOrder"); + QTest::addColumn("initialItems"); + QTest::addColumn("itemIndex"); + QTest::addColumn("newValue"); + QTest::addColumn("expectedItems"); + QTest::addColumn("expectedRows"); + QTest::addColumn("reorderingExpected"); + + QTest::newRow("change a to b in (a)") + << static_cast(Qt::AscendingOrder) + << (QStringList() << "a") + << 0 << "b" + << (QStringList() << "b") + << (IntList() << 0) + << false; + QTest::newRow("change a to b in (a, c)") + << static_cast(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(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(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(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(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(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 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(sortOrder)); + w.addItems(initialItems); + + QAbstractItemModel *model = w.model(); + QList 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(0)); + list.setItemWidget(item, &widget); + QCOMPARE(list.itemWidget(item), &widget); + list.removeItemWidget(item); + QCOMPARE(list.itemWidget(item), static_cast(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*"); + 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(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 +#include "dynamictreemodel.h" +#include "modeltest.h" + +#include +#include +#include + +#include + +//TESTED CLASS= +//TESTED_FILES= + +typedef QList IntList; +typedef QPair IntPair; +typedef QList 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"); + qRegisterMetaType("IntList"); + qRegisterMetaType("IntPair"); + qRegisterMetaType("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("sortOrder"); + QTest::addColumn("sortCaseSensitivity"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + + QTest::newRow("flat descending") << static_cast(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(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(Qt::AscendingOrder) + << int(Qt::CaseInsensitive) + << (QStringList() + << "alpha" << "BETA" << "Gamma" << "delta") + << (QStringList() + << "alpha" << "BETA" << "delta" << "Gamma"); + QTest::newRow("case sensitive") << static_cast(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(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 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(sortOrder)); + m_proxy->setSortCaseSensitivity(static_cast(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("sortOrder"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + +#if 1 + QTest::newRow("flat ascending") + << static_cast(Qt::AscendingOrder) + << (QStringList() + << "c" << "f" << "d" << "e" << "a" << "b") + << (QStringList() + << "a" << "b" << "c" << "d" << "e" << "f"); +#endif + QTest::newRow("simple hierarchy") + << static_cast(Qt::AscendingOrder) + << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">") + << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">"); + +#if 1 + QTest::newRow("hierarchical ascending") + << static_cast(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(sortOrder)); + checkHierarchy(initial, m_model); + checkHierarchy(expected, m_proxy); +} + +void tst_QSortFilterProxyModel::insertRows_data() +{ + QTest::addColumn("initial"); + QTest::addColumn("expected"); + QTest::addColumn("insert"); + QTest::addColumn("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("initial"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("position"); + QTest::addColumn("count"); + QTest::addColumn("success"); + QTest::addColumn("expectedProxy"); + QTest::addColumn("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(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(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(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(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(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("initial"); + QTest::addColumn("filter"); + QTest::addColumn("position"); + QTest::addColumn("count"); + QTest::addColumn("success"); + QTest::addColumn("expectedProxy"); + QTest::addColumn("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("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("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("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("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("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("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 row_stack; + QModelIndex parent; + QStack 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 row_stack; + QModelIndex parent; + QStack 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 persistentSourceIndexes; + QList 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("sourceItems"); + QTest::addColumn("start"); + QTest::addColumn("count"); + QTest::addColumn("sortOrder"); + QTest::addColumn("expectedRemovedProxyIntervals"); + QTest::addColumn("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(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(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(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(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(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(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 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 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("sourceItems"); + QTest::addColumn("start"); + QTest::addColumn("newItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("proxyItems"); + + QTest::newRow("insert (1)") + << (QStringList() << "c" << "b") // sourceItems + << 1 // start + << (QStringList() << "a") // newItems + << static_cast(Qt::AscendingOrder) // sortOrder + << (QStringList() << "a" << "b" << "c") // proxyItems + ; + + QTest::newRow("insert (2)") + << (QStringList() << "d" << "b" << "c") // sourceItems + << 3 // start + << (QStringList() << "a") // newItems + << static_cast(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(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("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("initialFilter"); + QTest::addColumn("initialRemoveIntervals"); + QTest::addColumn("initialProxyItems"); + QTest::addColumn("finalFilter"); + QTest::addColumn("finalRemoveIntervals"); + QTest::addColumn("insertIntervals"); + QTest::addColumn("finalProxyItems"); + + QTest::newRow("filter (1)") + << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems + << static_cast(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(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(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(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 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 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 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("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("dynamic"); + QTest::addColumn("row"); + QTest::addColumn("newValue"); + QTest::addColumn("removeIntervals"); + QTest::addColumn("insertIntervals"); + QTest::addColumn("proxyItems"); + + QTest::newRow("changeSourceData (1)") + << (QStringList() << "c" << "b" << "a") // sourceItems + << static_cast(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(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(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(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(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(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(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 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 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 > sourceItems; + sourceItems = QList >() + << QPair("b", 3) + << QPair("c", 2) + << QPair("a", 1); + + QList orderedItems; + orderedItems = QList() + << 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("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("proxyStartRow"); + QTest::addColumn("what"); + QTest::addColumn("matchFlags"); + QTest::addColumn("expectedProxyItems"); + QTest::newRow("1") + << (QStringList() << "a") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << 0 // proxyStartRow + << "a" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 0); // expectedProxyItems + QTest::newRow("2") + << (QStringList() << "a" << "b") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << 0 // proxyStartRow + << "b" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 1); // expectedProxyItems + QTest::newRow("3") + << (QStringList() << "a" << "b") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "" // filter + << 0 // proxyStartRow + << "a" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 1); // expectedProxyItems + QTest::newRow("4") + << (QStringList() << "b" << "d" << "a" << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << 1 // proxyStartRow + << "a" // what + << static_cast(Qt::MatchExactly) // matchFlags + << IntList(); // expectedProxyItems + QTest::newRow("5") + << (QStringList() << "b" << "d" << "a" << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|b" // filter + << 0 // proxyStartRow + << "c" // what + << static_cast(Qt::MatchExactly) // matchFlags + << IntList(); // expectedProxyItems + QTest::newRow("6") + << (QStringList() << "b" << "d" << "a" << "c") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "a|b" // filter + << 0 // proxyStartRow + << "b" // what + << static_cast(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(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(args.at(0)), proxy.mapFromSource(itemB->index())); + QCOMPARE(qvariant_cast(args.at(1)), 0); + QCOMPARE(qvariant_cast(args.at(2)), 0); + + args = rowsInsertedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), proxy.mapFromSource(itemB->index())); + QCOMPARE(qvariant_cast(args.at(1)), 0); + QCOMPARE(qvariant_cast(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(&model)); + } + QCOMPARE(proxyModel.sourceModel(), static_cast(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 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 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 fetched; + int rows, cols; + mutable bool wrongIndex; + mutable QMap 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 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 sourceIndexes; + QList 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 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("test"); + QTest::addColumn("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 + +#include + +//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(item.data(Qt::DisplayRole)), text); + QCOMPARE(qvariant_cast(item.data(Qt::DecorationRole)), icon); + QCOMPARE(qvariant_cast(item.data(Qt::ToolTipRole)), toolTip); + QCOMPARE(qvariant_cast(item.data(Qt::StatusTipRole)), statusTip); + QCOMPARE(qvariant_cast(item.data(Qt::WhatsThisRole)), whatsThis); + QCOMPARE(qvariant_cast(item.data(Qt::SizeHintRole)), sizeHint); + QCOMPARE(qvariant_cast(item.data(Qt::FontRole)), font); + QCOMPARE(qvariant_cast(item.data(Qt::TextAlignmentRole)), int(textAlignment)); + QCOMPARE(qvariant_cast(item.data(Qt::BackgroundColorRole)), QBrush(backgroundColor)); + QCOMPARE(qvariant_cast(item.data(Qt::BackgroundRole)), QBrush(backgroundColor)); + QCOMPARE(qvariant_cast(item.data(Qt::TextColorRole)), QBrush(textColor)); + QCOMPARE(qvariant_cast(item.data(Qt::ForegroundRole)), QBrush(textColor)); + QCOMPARE(qvariant_cast(item.data(Qt::CheckStateRole)), int(checkState)); + QCOMPARE(qvariant_cast(item.data(Qt::AccessibleTextRole)), accessibleText); + QCOMPARE(qvariant_cast(item.data(Qt::AccessibleDescriptionRole)), accessibleDescription); + + item.setBackground(pixmap); + QCOMPARE(item.background().texture(), pixmap); + QCOMPARE(qvariant_cast(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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("row"); + QTest::addColumn("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(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(0)); +} + +void tst_QStandardItem::parent() +{ + { + QStandardItem item; + QStandardItem *child = new QStandardItem; + QCOMPARE(child->parent(), static_cast(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(0)); + } +} + +void tst_QStandardItem::insertColumn_data() +{ + QTest::addColumn("rows"); + QTest::addColumn("columns"); + QTest::addColumn("column"); + QTest::addColumn("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 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(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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("row"); + QTest::addColumn("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 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(0)); + } else { + QCOMPARE(item.columnCount(), columns); + QCOMPARE(item.rowCount(), rows); + qDeleteAll(rowItems); + } +} + +void tst_QStandardItem::insertRows_data() +{ + QTest::addColumn("rows"); + QTest::addColumn("columns"); + QTest::addColumn("insertAt"); + QTest::addColumn("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 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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("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 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 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(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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("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 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 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(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 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(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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("column"); + QTest::addColumn("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 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 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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("row"); + QTest::addColumn("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 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 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(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(); + + 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(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 + +#include +#include +#include + +//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 rcParent; + QVector rcFirst; + QVector 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"); + qRegisterMetaType("QStandardItem*"); + qRegisterMetaType("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("insertRow"); + QTest::addColumn("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 items; + QStandardItemModel *m = qobject_cast(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(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("insertColumn"); + QTest::addColumn("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(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("sortOrder"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + + QTest::newRow("flat descending") << static_cast(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(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(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(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("initialText"); + QTest::addColumn("initialData"); + QTest::addColumn("sortRole"); + QTest::addColumn("sortOrder"); + QTest::addColumn("expectedText"); + QTest::addColumn("expectedData"); + + QTest::newRow("sort ascending with Qt::DisplayRole") + << (QStringList() << "b" << "a" << "c") + << (QVariantList() << 2 << 3 << 1) + << static_cast(Qt::DisplayRole) + << static_cast(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(Qt::UserRole) + << static_cast(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(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 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(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(0)); + + QCOMPARE(model.verticalHeaderItem(0), static_cast(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(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(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(QStandardItem::UserType)); + + model.setItemPrototype(0); + QCOMPARE(model.itemPrototype(), static_cast(0)); +} + +void tst_QStandardItemModel::getSetItemData() +{ + QMap 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("rows"); + QTest::addColumn("columns"); + QTest::addColumn("orientation"); + QTest::addColumn("labels"); + QTest::addColumn("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 args; + args = dataChangedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), index); + QCOMPARE(qvariant_cast(args.at(1)), index); + args = itemChangedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), &item); + + item.setData(QLatin1String("foo"), Qt::DisplayRole); + QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.count(), 1); + args = dataChangedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), index); + QCOMPARE(qvariant_cast(args.at(1)), index); + args = itemChangedSpy.takeFirst(); + QCOMPARE(qvariant_cast(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(args.at(0)), index); + QCOMPARE(qvariant_cast(args.at(1)), index); + args = itemChangedSpy.takeFirst(); + QCOMPARE(qvariant_cast(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(0)); + QCOMPARE(vheader->model(), static_cast(0)); + QCOMPARE(model.takeHorizontalHeaderItem(0), static_cast(0)); + QCOMPARE(model.takeVerticalHeaderItem(0), static_cast(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(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()); + 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(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 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 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 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 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 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 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 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 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 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 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 +#include +#include + + +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 +#include +#include +#include +#include +#include +#include +#include "qmodellistener.h" +#include + +//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("input"); + QTest::addColumn("row"); + QTest::addColumn("count"); + QTest::addColumn("aboutto"); + QTest::addColumn("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("input"); + QTest::addColumn("row"); + QTest::addColumn("count"); + QTest::addColumn("aboutto"); + QTest::addColumn("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 +#include +#include +#include +#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(QObjectPrivate::get(TEST_VIEW_))->spans.checkConsistency()) +#else +#define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) (void)false +#endif + +typedef QList IntList; +Q_DECLARE_METATYPE(IntList) + +typedef QList 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 disabled_rows; + QSet 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("rowCount"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("tabKeyNavigation"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowHeight"); + QTest::addColumn("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 IntPair; +Q_DECLARE_METATYPE(IntPair) + +void tst_QTableView::moveCursor_data() +{ + QTest::addColumn("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("hideRow"); + QTest::addColumn("hideColumn"); + + QTest::addColumn("startRow"); + QTest::addColumn("startColumn"); + + QTest::addColumn("cursorMoveAction"); + QTest::addColumn("modifier"); + + QTest::addColumn("expectedRow"); + QTest::addColumn("expectedColumn"); + QTest::addColumn("moveRow"); + QTest::addColumn("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("hideRow"); + QTest::addColumn("hideColumn"); + QTest::addColumn("disableRows"); + QTest::addColumn("disableColumns"); + QTest::addColumn("span"); + + QTest::addColumn("startRow"); + QTest::addColumn("startColumn"); + QTest::addColumn("cursorMoveActions"); + QTest::addColumn("expectedRow"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("showRow"); // hide, then show + QTest::addColumn("hideRow"); // hide only + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("showColumn"); // hide, then show + QTest::addColumn("hideColumn"); // hide only + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("columnSpan"); + QTest::addColumn("hideRow"); + QTest::addColumn("hideColumn"); + QTest::addColumn("moveRowFrom"); + QTest::addColumn("moveRowTo"); + QTest::addColumn("moveColumnFrom"); + QTest::addColumn("moveColumnTo"); + QTest::addColumn("rowHeight"); + QTest::addColumn("columnWidth"); + QTest::addColumn("x"); + QTest::addColumn("y"); + QTest::addColumn("width"); + QTest::addColumn("height"); + QTest::addColumn("command"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("mode"); + QTest::addColumn("behavior"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("column"); + QTest::addColumn("mode"); + QTest::addColumn("behavior"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("hideRow"); + QTest::addColumn("hideColumn"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowHeight"); + QTest::addColumn("columnWidth"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("showGrid"); + QTest::addColumn("cellWidth"); + QTest::addColumn("cellHeight"); + QTest::addColumn("rowHeight"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("showGrid"); + QTest::addColumn("cellWidth"); + QTest::addColumn("cellHeight"); + QTest::addColumn("rowHeight"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("rowHeight"); + QTest::addColumn("row"); + QTest::addColumn("verticalScrollMode"); + QTest::addColumn("verticalScrollValue"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("rowHeight"); + QTest::addColumn("hiddenRows"); + QTest::addColumn("coordinate"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("rowHeights"); + QTest::addColumn("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("columnCount"); + QTest::addColumn("columnWidth"); + QTest::addColumn("column"); + QTest::addColumn("horizontalScrollMode"); + QTest::addColumn("horizontalScrollValue"); + QTest::addColumn("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("columnCount"); + QTest::addColumn("columnWidth"); + QTest::addColumn("hiddenColumns"); + QTest::addColumn("coordinate"); + QTest::addColumn("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("columnCount"); + QTest::addColumn("columnWidths"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("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("columnCount"); + QTest::addColumn("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("columnCount"); +} + +void tst_QTableView::sortingEnabled() +{ +// QFETCH(int, columnCount); +} + +void tst_QTableView::scrollTo_data() +{ + QTest::addColumn("verticalScrollMode"); + QTest::addColumn("horizontalScrollMode"); + QTest::addColumn("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("rowHeight"); + QTest::addColumn("columnWidth"); + QTest::addColumn("hiddenRow"); + QTest::addColumn("hiddenColumn"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("columnSpan"); + QTest::addColumn("horizontalScroll"); + QTest::addColumn("verticalScroll"); + QTest::addColumn("scrollHint"); + QTest::addColumn("expectedHorizontalScroll"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + + QTest::addColumn("rowHeight"); + QTest::addColumn("columnWidth"); + + QTest::addColumn("hiddenRow"); + QTest::addColumn("hiddenColumn"); + + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("columnSpan"); + QTest::addColumn("horizontalScroll"); + QTest::addColumn("verticalScroll"); + QTest::addColumn("x"); + QTest::addColumn("y"); + QTest::addColumn("expectedRow"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("hiddenRow"); + QTest::addColumn("hiddenColumn"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("rowSpan"); + QTest::addColumn("columnSpan"); + QTest::addColumn("expectedRowSpan"); + QTest::addColumn("expectedColumnSpan"); + QTest::addColumn("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 SpanList; +Q_DECLARE_METATYPE(SpanList) + +void tst_QTableView::spans_data() +{ + QTest::addColumn("rows"); + QTest::addColumn("columns"); + QTest::addColumn("spans"); + QTest::addColumn("hideRowLastRowOfFirstSpan"); + QTest::addColumn("pos"); + QTest::addColumn("expectedRowSpan"); + QTest::addColumn("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 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 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 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 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;iprocessEvents(); + + 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() << &item1 << &item2); + + + //setup the first table as a child of the first item + for ( int row = 0; row < 40; ++row ) { + item1.appendRow(QList() << 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() << 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("scrollMode"); + QTest::addColumn("delta"); + QTest::addColumn("horizontalPositon"); + QTest::addColumn("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 editor = qFindChild(&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 +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 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()); + 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 +#include +#include +#include +#include + +#include + +//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 IntPair; +typedef QList IntList; +typedef QList 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"); + 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 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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("createItems"); + QTest::addColumn("hiddenRows"); + QTest::addColumn("hiddenColumns"); + QTest::addColumn("selectionRange"); + QTest::addColumn("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 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; rowrowCount(); ++row) { + bool hidden = false; + foreach (int hiddenRow, hiddenRows){ + if(hiddenRow == row){ + hidden = true; + break; + } + } + if (hidden) + continue; + + for (int column = 0; columncolumnCount(); ++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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("expectedRowCount"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("column"); + QTest::addColumn("expectedRowCount"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("row"); + QTest::addColumn("expectedRowCount"); + QTest::addColumn("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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("column"); + QTest::addColumn("expectedRowCount"); + QTest::addColumn("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("text"); + QTest::addColumn("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 item; + QPointer 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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("sortOrder"); + QTest::addColumn("sortColumn"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + QTest::addColumn("rows"); + QTest::addColumn("initialHidden"); + QTest::addColumn("expectedHidden"); + + QTest::newRow("ascending") + << 4 << 5 + << static_cast(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(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(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(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(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(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(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(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(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(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(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(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 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(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("rowCount"); + QTest::addColumn("columnCount"); + QTest::addColumn("sortOrder"); + QTest::addColumn("sortColumn"); + QTest::addColumn("initialValues"); + QTest::addColumn("row"); + QTest::addColumn("column"); + QTest::addColumn("newValue"); + QTest::addColumn("expectedValues"); + QTest::addColumn("expectedRows"); + QTest::addColumn("reorderingExpected"); + + QTest::newRow("2x1 no change (ascending)") + << 2 << 1 + << static_cast(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(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(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(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(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(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(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(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(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 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(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 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(dataChangedSpy.takeFirst().at(0)); + + QMap 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(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(0)); + table.setCellWidget(5, 5, &widget); + QCOMPARE(table.cellWidget(5, 5), &widget); + table.removeCellWidget(5, 5); + QCOMPARE(table.cellWidget(5, 5), static_cast(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 +#include +#include +#include + +//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 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"); +} + +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(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("row"); + QTest::addColumn("column"); + QTest::addColumn("indexRow"); + QTest::addColumn("indexColumn"); + QTest::addColumn("parentIndexRow"); + QTest::addColumn("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("dragDropMode"); + QTest::addColumn("acceptDrops"); + QTest::addColumn("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("dragEnabled"); + QTest::addColumn("acceptDrops"); + QTest::addColumn("dragDropMode"); + QTest::addColumn("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("editTriggers"); + QTest::addColumn("triggeredTrigger"); + QTest::addColumn("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(&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(&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() + << 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(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(widget)); + + QCOMPARE(widget->parentWidget(), view.viewport()); + QCOMPARE(widget->geometry(), view.visualRect(index).intersect(widget->geometry())); + QCOMPARE(widget->toPlainText(), text); +} + +void tst_QTreeView::itemDelegate() +{ + QPointer oldDelegate; + QPointer otherItemDelegate; + + { + QTreeView view; + QVERIFY(qobject_cast(view.itemDelegate())); + QPointer 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() + << 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 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 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(view.viewport())); + view.openPersistentEditor(view.model()->index(0, 0)); + QVERIFY(qFindChild(view.viewport())); + + view.closePersistentEditor(view.model()->index(0, 0)); + QVERIFY(!qFindChild(view.viewport())->isVisible()); + + qApp->sendPostedEvents(0, QEvent::DeferredDelete); + QVERIFY(!qFindChild(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 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("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(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(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(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(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(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(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(args.at(0)), a); + args = expandedSpy.takeFirst(); + QCOMPARE(qvariant_cast(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(args.at(0)), a); + args = collapsedSpy.takeFirst(); + QCOMPARE(qvariant_cast(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 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 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("uniformRowHeights"); + QTest::addColumn("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 PointList; +Q_DECLARE_METATYPE(PointList) + +void tst_QTreeView::setSelection_data() +{ + QTest::addColumn("selectionRect"); + QTest::addColumn("selectionMode"); + QTest::addColumn("selectionCommand"); + QTest::addColumn("expectedItems"); + QTest::addColumn("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 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(&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() << &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("mousePressPos"); + QTest::addColumn("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("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 children; + QList 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 > oldListPath; + for (int i = 0; i < oldList.count(); ++i) { + QModelIndex idx = oldList.at(i); + QStack 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 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(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(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(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(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("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 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(&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() + << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") ); + QStandardItem *par1 = new QStandardItem("Beginning HasChildren"); + model.appendRow(QList() + << par1 << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") ); + model.appendRow(QList() + << 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() + << new QStandardItem("Beginning") << checkable << checked << new QStandardItem("End") ); + model.appendRow(QList() + << new QStandardItem("Beginning Last") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") ); + + par1->appendRow(QList() + << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") ); + QStandardItem *par2 = new QStandardItem("Beginning HasChildren"); + par1->appendRow(QList() + << par2 << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") ); + par2->appendRow(QList() + << 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() + << par3 << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") ); + par3->appendRow(QList() + << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Asser") ); + view.setRowHidden(0, par3->index(), true); + par1->appendRow(QList() + << 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() << item0); + view.setModel(&model2); + QApplication::processEvents(); + QTRY_VERIFY(delegate.count >= 1); + QApplication::processEvents(); + + QStandardItem *item00 = new QStandardItem("OnlyOne Last"); + item0->appendRow(QList() << 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() << 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() << 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() << 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() << 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() << item00); + item01 = new QStandardItem("Assert"); + item0->appendRow(QList() << item01); + view.setRowHidden(1, item0->index(), true); + view.expandAll(); + QStandardItem *item02 = new QStandardItem("OnlyOne Last"); + item0->appendRow(QList() << 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 ¤t, 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() << &root << &root2); + root.appendRow( QList() << &subitem << &subitem2); + subitem.appendRow( QList() << &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 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() << &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() << &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 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 paintedIndexes; + }; + + QTreeView view; + QStandardItemModel model; + view.setModel(&model); + MyDelegate delegate; + view.setItemDelegate(&delegate); + QStandardItem root0("root0"), root1("root1"); + model.invisibleRootItem()->appendRow(QList() << &root0 << &root1); + QStandardItem sub0("sub0"), sub00("sub00"); + root0.appendRow(QList() << &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() << &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 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(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 ¤t,const QModelIndex &) + { + if (m_block) + return; + + if (current.isValid()) { + int selectedRow = current.row(); + quint32 parentRowPlusOne = static_cast(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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 IntList; +typedef QList ListIntList; + +Q_DECLARE_METATYPE(IntList) +Q_DECLARE_METATYPE(ListIntList) +Q_DECLARE_METATYPE(QModelIndex) +Q_DECLARE_METATYPE(Qt::Orientation) + +typedef QTreeWidgetItem TreeItem; +typedef QList TreeItemList; + +Q_DECLARE_METATYPE(QTreeWidgetItem*) +Q_DECLARE_METATYPE(TreeItemList) + +tst_QTreeWidget::tst_QTreeWidget(): testWidget(0) +{ +} + +tst_QTreeWidget::~tst_QTreeWidget() +{ +} + +void tst_QTreeWidget::initTestCase() +{ + qMetaTypeId(); + qMetaTypeId(); + qRegisterMetaType("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 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(0)); + QCOMPARE(tree.indexOfTopLevelItem(ti), i); + QCOMPARE(ti->parent(), static_cast(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("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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(0)); +} + +void tst_QTreeWidget::editItem_data() +{ + QTest::addColumn("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(&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(args.at(0)), item); + QCOMPARE(qvariant_cast(args.at(1)), col); + } else { + QVERIFY(!(item->flags() & Qt::ItemIsEditable)); + } + } + } +} + +void tst_QTreeWidget::takeItem_data() +{ + QTest::addColumn("index"); + QTest::addColumn("topLevel"); + QTest::addColumn("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("childCount"); + QTest::addColumn("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("topLevel"); + QTest::addColumn("children"); + QTest::addColumn("closeTopLevel"); + QTest::addColumn("selectedItems"); + QTest::addColumn("hiddenItems"); + QTest::addColumn("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; tsetText(0, QString("top%1").arg(t)); + for (int c=0; csetText(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; itopLevelItemCount(); ++i) { + if (closeTopLevel) + testWidget->collapseItem(testWidget->topLevelItem(i)); + else + testWidget->expandItem(testWidget->topLevelItem(i)); + } + + // check selectedItems + QList 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; ttopLevelItemCount(); ++t) { + QTreeWidgetItem *top = testWidget->topLevelItem(t); + if (testWidget->isItemSelected(top) && !testWidget->isItemHidden(top)) + QVERIFY(sel.contains(top)); + for (int c=0; cchildCount(); ++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(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("column"); + QTest::addColumn("topLevelIndex"); + QTest::addColumn("childIndex"); + QTest::addColumn("topLevelText"); + QTest::addColumn("childText"); + QTest::addColumn("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("topLevelIndex"); + QTest::addColumn("topLevelCount"); + QTest::addColumn("childIndex"); + QTest::addColumn("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("column"); + QTest::addColumn("topLevelText"); + QTest::addColumn("childText"); + QTest::addColumn("pattern"); + QTest::addColumn("resultCount"); + QTest::addColumn("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 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 items = testWidget->findItems("400", Qt::MatchExactly|Qt::MatchRecursive, 1); + QCOMPARE(items.count(), 1); +} + +void tst_QTreeWidget::sortItems_data() +{ + QTest::addColumn("column"); + QTest::addColumn("order"); + QTest::addColumn("topLevelText"); + QTest::addColumn("childText"); + QTest::addColumn("topLevelResult"); + QTest::addColumn("childResult"); + QTest::addColumn("expectedTopRows"); + QTest::addColumn("expectedChildRows"); + + QTest::newRow("ascending order") + << 0 + << static_cast(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(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 tops; + for (int r = 0; r < model->rowCount(QModelIndex()); ++r) { + QPersistentModelIndex p = model->index(r, 0, QModelIndex()); + tops << p; + } + QList 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(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("topLevelCount"); + QTest::addColumn("childCount"); + QTest::addColumn("grandChildCount"); + + QTest::addColumn("deleteTopLevelCount"); + QTest::addColumn("deleteChildCount"); + QTest::addColumn("deleteGrandChildCount"); + + QTest::addColumn("expectedTopLevelCount"); + QTest::addColumn("expectedChildCount"); + QTest::addColumn("expectedGrandChildCount"); + + QTest::addColumn("persistentRow"); + QTest::addColumn("persistentColumn"); + QTest::addColumn("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("text"); + QTest::addColumn("toolTip"); + QTest::addColumn("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("initialText"); + QTest::addColumn("insertText"); + QTest::addColumn("insertTopLevelIndex"); + QTest::addColumn("expectedTopLevelIndex"); + QTest::addColumn("insertChildIndex"); + QTest::addColumn("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 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(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 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 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(0)); + QCOMPARE(taken.at(i)->treeWidget(), static_cast(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()); + QCOMPARE(item->childCount(), count); + } + + // add many at a time + const int count = 10; + for (int i = 0; i < 100; i += count) { + QList 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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(args.at(0)), item); + QCOMPARE(qvariant_cast(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(item->data(j, Qt::DisplayRole)), text); + QCOMPARE(qvariant_cast(item->data(j, Qt::DecorationRole)), icon); + QCOMPARE(qvariant_cast(item->data(j, Qt::ToolTipRole)), toolTip); + QCOMPARE(qvariant_cast(item->data(j, Qt::StatusTipRole)), statusTip); + QCOMPARE(qvariant_cast(item->data(j, Qt::WhatsThisRole)), whatsThis); + QCOMPARE(qvariant_cast(item->data(j, Qt::SizeHintRole)), sizeHint); + QCOMPARE(qvariant_cast(item->data(j, Qt::FontRole)), font); + QCOMPARE(qvariant_cast(item->data(j, Qt::TextAlignmentRole)), int(textAlignment)); + QCOMPARE(qvariant_cast(item->data(j, Qt::BackgroundColorRole)), QBrush(backgroundColor)); + QCOMPARE(qvariant_cast(item->data(j, Qt::BackgroundRole)), QBrush(backgroundColor)); + QCOMPARE(qvariant_cast(item->data(j, Qt::TextColorRole)), textColor); + QCOMPARE(qvariant_cast(item->data(j, Qt::CheckStateRole)), int(checkState)); + + item->setBackground(j, pixmap); + QCOMPARE(item->background(j).texture(), pixmap); + QCOMPARE(qvariant_cast(item->data(j, Qt::BackgroundRole)).texture(), pixmap); + args = itemChangedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), item); + QCOMPARE(qvariant_cast(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 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(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(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(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(&tree); + QVERIFY(editor != 0); + tree.closePersistentEditor(item, col); + } + } + } + } +} + +void tst_QTreeWidget::insertItemsWithSorting_data() +{ + QTest::addColumn("sortOrder"); + QTest::addColumn("initialItems"); + QTest::addColumn("insertItems"); + QTest::addColumn("expectedItems"); + QTest::addColumn("expectedRows"); + + QTest::newRow("() + (a) = (a)") + << static_cast(Qt::AscendingOrder) + << QStringList() + << (QStringList() << "a") + << (QStringList() << "a") + << IntList(); + QTest::newRow("() + (c, b, a) = (a, b, c)") + << static_cast(Qt::AscendingOrder) + << QStringList() + << (QStringList() << "c" << "b" << "a") + << (QStringList() << "a" << "b" << "c") + << IntList(); + QTest::newRow("() + (a, b, c) = (c, b, a)") + << static_cast(Qt::DescendingOrder) + << QStringList() + << (QStringList() << "a" << "b" << "c") + << (QStringList() << "c" << "b" << "a") + << IntList(); + QTest::newRow("(a) + (b) = (a, b)") + << static_cast(Qt::AscendingOrder) + << QStringList("a") + << (QStringList() << "b") + << (QStringList() << "a" << "b") + << (IntList() << 0); + QTest::newRow("(a) + (b) = (b, a)") + << static_cast(Qt::DescendingOrder) + << QStringList("a") + << (QStringList() << "b") + << (QStringList() << "b" << "a") + << (IntList() << 1); + QTest::newRow("(a, c, b) + (d) = (a, b, c, d)") + << static_cast(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(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(Qt::AscendingOrder) + << QStringList() + << ascendingItems + << ascendingItems + << IntList(); + QTest::newRow("(sorted items) + () = (sorted items)") + << static_cast(Qt::AscendingOrder) + << ascendingItems + << QStringList() + << ascendingItems + << ascendingRows; + QTest::newRow("() + (ascending items) = (reverse items)") + << static_cast(Qt::DescendingOrder) + << QStringList() + << ascendingItems + << reverseItems + << IntList(); + QTest::newRow("(reverse items) + () = (ascending items)") + << static_cast(Qt::AscendingOrder) + << reverseItems + << QStringList() + << ascendingItems + << ascendingRows; + QTest::newRow("(reverse items) + () = (reverse items)") + << static_cast(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(sortOrder)); + for (int i = 0; i < initialItems.count(); ++i) + w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i))); + + QAbstractItemModel *model = w.model(); + QList 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 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 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("parentText"); + QTest::addColumn("childText"); + QTest::addColumn("parentResult"); + QTest::addColumn("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 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(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 parents; + for (int i = 0; i < model->rowCount(QModelIndex()); ++i) { + QPersistentModelIndex parent = model->index(i, 0, QModelIndex()); + parents << parent; + } + QList 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("sortOrder"); + QTest::addColumn("initialItems"); + QTest::addColumn("itemIndex"); + QTest::addColumn("newValue"); + QTest::addColumn("expectedItems"); + QTest::addColumn("expectedRows"); + QTest::addColumn("reorderingExpected"); + + QTest::newRow("change a to b in (a)") + << static_cast(Qt::AscendingOrder) + << (QStringList() << "a") + << 0 << "b" + << (QStringList() << "b") + << (IntList() << 0) + << false; + QTest::newRow("change a to b in (a, c)") + << static_cast(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(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(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(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(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(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(sortOrder)); + for (int i = 0; i < initialItems.count(); ++i) + w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i))); + + QAbstractItemModel *model = w.model(); + QList 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("sortOrder"); + QTest::addColumn("initialItems"); + QTest::addColumn("itemIndex"); + QTest::addColumn("newValue"); + QTest::addColumn("expectedItems"); + QTest::addColumn("expectedRows"); + QTest::addColumn("reorderingExpected"); + QTest::addColumn("forceChange"); + + QTest::newRow("change a to c in (a, c, c, c, e)") + << static_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(sortOrder)); + for (int i = 0; i < initialItems.count(); ++i) + w.addTopLevelItem(new StableItem(QStringList() << initialItems.at(i))); + + QAbstractItemModel *model = w.model(); + QList 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(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("sortOrder"); + QTest::addColumn("itemTexts"); + QTest::addColumn >("expectedIndexes"); + + QTest::newRow("three ascending") + << int(Qt::AscendingOrder) + << (QStringList() << "A" << "B" << "C") + << (QList() << 0 << 1 << 2); + + + QTest::newRow("three descending") + << int(Qt::DescendingOrder) + << (QStringList() << "A" << "B" << "C") + << (QList() << 2 << 1 << 0); +} + +void tst_QTreeWidget::sortedIndexOfChild() +{ + QFETCH(int, sortOrder); + QFETCH(QStringList, itemTexts); + QFETCH(QList, expectedIndexes); + + QTreeWidget tw; + QList 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 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 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; jcolumnCount() - 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 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 + +#include +#include +#include +#include +#include + +//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("start"); + QTest::addColumn("iteratorflags"); + QTest::addColumn("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("start"); + QTest::addColumn("addition"); + QTest::addColumn("iteratorflags"); + QTest::addColumn("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("start"); + QTest::addColumn("subtraction"); + QTest::addColumn("iteratorflags"); + QTest::addColumn("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("topLevelItems"); + QTest::addColumn("childItems"); + QTest::addColumn("grandChildItems"); + QTest::addColumn("iteratorflags"); + QTest::addColumn("removeindex"); + QTest::addColumn("expecteditemindex"); + QTest::addColumn("expecteditemvalue"); + QTest::addColumn("expectedUpdatedCurrent"); + QTest::addColumn("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("topLevelItems"); + QTest::addColumn("childItems"); + QTest::addColumn("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("removeindex"); // The index of the node we want to remove + QTest::addColumn("iterator_initial_index"); // The new expected index of + QTest::addColumn("iterator_advance_after_removal"); + QTest::addColumn("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("indextoitem"); + QTest::addColumn("iteratorflags"); + QTest::addColumn("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(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 + +#include +#include +#include +#include + +//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("text"); + QTest::addColumn("iconText"); + QTest::addColumn("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 list; + act.setShortcuts(list); + act.setShortcuts(QKeySequence::Copy); + QVERIFY(act.shortcut() == act.shortcuts().first()); + + QList 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 shlist = QList() << 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 + +#include +#include +#include + +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 it(actGroup.actions()); + while (it.hasNext()) + menu.addAction(it.next()); + + QCOMPARE((int)menu.actions().size(), 2 + numSoftkeyActions); + + it = QListIterator(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(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 +#include + +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 @@ + + + + + +Heart Left-Highlight +This is a normal valentines day heart. + + +holiday +valentines + +valentine +hash(0x8a091c0) +hash(0x8a0916c) +signs_and_symbols +hash(0x8a091f0) +day + + + + +Jon Phillips + + + + +Jon Phillips + + + + +Jon Phillips + + + +image/svg+xml + + +en + + + + + + + + + + + + + + + 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 +#include +#include + +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 + +#include +#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 + +#include + +#include "qabstracteventdispatcher.h" +#include +#include + +#include "private/qapplication_p.h" +#include "private/qstylesheetstyle_p.h" +#ifdef Q_OS_WINCE +#include +#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 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(&obj1)); + + // Test for self-assignment: + obj1.setInputContext(obj1.inputContext()); + QVERIFY(obj1.inputContext()); + QCOMPARE(static_cast(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(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("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("family"); + QTest::addColumn("pointsize"); + QTest::addColumn("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 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("argc_in"); + QTest::addColumn("args_in"); + QTest::addColumn("argc_out"); + QTest::addColumn("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 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 dialog = new QDialog; + QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose)); + QTimer::singleShot(1000, dialog, SLOT(accept())); + dialog->exec(); + QVERIFY(dialog); + QCOMPARE(spy.count(), 0); + + QPointerwidget = 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 mainWindow = new QMainWindow; + QPointer 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 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::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::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::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::fromList(expected).toList(); +# endif + QVERIFY(isPathListIncluded(app.libraryPaths(), expected)); + + qputenv("QT_PLUGIN_PATH", QByteArray()); + } +} + +class SendPostedEventsTester : public QObject +{ + Q_OBJECT +public: + QList 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 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 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(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(wgt, "deleteLater"); + QVERIFY(stillAlive); + + app.exec(); + + delete wgt; + +} + +class EventLoopNester : public QObject +{ + Q_OBJECT +public slots: + void deleteLaterAndEnterLoop() + { + QEventLoop eventLoop; + QPointer 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 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 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 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 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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(spy.count()-1).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(0).at(0)); + now = qVariantValue(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(spy.at(spy.count()-1).at(0)); + else + old = qVariantValue(spy.at(spy.count()-2).at(0)); + now = qVariantValue(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 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("args"); + QTest::addColumn("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 pressedTouchPoints; + QTouchEvent::TouchPoint press(0); + press.setState(Qt::TouchPointPressed); + pressedTouchPoints << press; + + QList 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 +#include +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 +#include +#include + +//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 +#include +#include + +//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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +//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(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 labels; + QList 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(layout.itemAt(0, QFormLayout::LabelRole)->widget()); + QVERIFY(label1 != 0); + QVERIFY(label1->buddy() == &fld1); + + layout.insertRow(0, "&Email:", &fld2); + QLabel *label2 = qobject_cast(layout.itemAt(0, QFormLayout::LabelRole)->widget()); + QVERIFY(label2 != 0); + QVERIFY(label2->buddy() == &fld2); + + layout.insertRow(5, "&Age:", &fld3); + QLabel *label3 = qobject_cast(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(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(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(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(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 @@ + + + + + SortDialog + + + + 0 + 0 + 304 + 370 + + + + Sort + + + + 8 + + + 6 + + + + + 0 + + + 6 + + + + + OK + + + true + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + &More + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + 8 + + + 6 + + + + + + 0 + 100 + + + + + None + + + + + + + + + + + + primaryColumnCombo + okButton + moreButton + + + + + okButton + clicked() + SortDialog + accept() + + + 257 + 25 + + + 283 + 268 + + + + + 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 +#include +#include +#include +#include +#include +//#include + +#include +#include +#include +#include +#include + +#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" <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 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("columns"); + QTest::addColumn("rows"); + QTest::addColumn("sizehint"); + // expected + QTest::addColumn("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 > 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 SizeInfoList; +Q_DECLARE_METATYPE(SizeInfoList) + + +void tst_QGridLayout::minMaxSize_data() +{ + // input + QTest::addColumn("stylename"); + QTest::addColumn("columns"); + QTest::addColumn("rows"); + QTest::addColumn("sizePolicy"); + QTest::addColumn("fixedSize"); + //input and expected output + QTest::addColumn("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(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 > 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("columns"); + QTest::addColumn("rows"); + QTest::addColumn("sizehint"); + // expected + QTest::addColumn("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 > 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("widget"); + // expected + QTest::addColumn("expectedpositions"); + QTest::addColumn("hSpacing"); + QTest::addColumn("vSpacing"); + QTest::addColumn("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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef QT_WEBKIT_LIB +#include +#include +#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(&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 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 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 = "" + "
"; + 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 = "" + "
"; + 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_WS_MAC +# include +#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(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 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(watched)->geometry(); + } + return false; + } + QRect geom; +}; + +void tst_QLayout::layoutItemRect() +{ +#ifdef Q_WS_MAC + if (qobject_cast(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(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 Binary files /dev/null and b/tests/auto/widgets/kernel/qsound/4.wav 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 +#include + +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 +#include +#include +#include +#include +#include + +//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(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(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(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(top)); + + // focus should stay at the 'top' widget + testLayout->removeWidget(w1); + + QCOMPARE(QApplication::focusWidget(), static_cast(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(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 +#include + +//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("key"); + QTest::addColumn("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 + +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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/geometry.dat 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 @@ + + + geometry.dat + geometry-maximized.dat + geometry-fullscreen.dat + + 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef Q_WS_QWS +# include +#endif + +// I *MUST* have QtTest afterwards or this test won't work with newer headers +#if defined(Q_WS_MAC) +# include +#undef verify +#include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile. +#endif + +#include + +#if defined(Q_OS_WIN) +# include +# include +# include +# include + +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(handle); + qWarning() << "Cannot obtain native handle for " << w; + return 0; +} +#endif + +#if defined(Q_WS_WIN) +# include +# 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 +# include +#elif defined(Q_WS_QWS) +# include +#endif + +#if !defined(Q_WS_WIN) +#define Q_CHECK_PAINTEVENTS +#endif + +#if defined(Q_OS_WINCE_WM) +#include +// 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 (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 +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(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(var11), obj1.layout()); + obj1.setLayout((QLayout *)0); + QCOMPARE(static_cast(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(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("windowHidden"); + QTest::addColumn("subWindow1Hidden"); + QTest::addColumn("subWindow2Hidden"); + QTest::addColumn("subSubWindowHidden"); + QTest::addColumn("windowMinimized"); + QTest::addColumn("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(0)); + QCOMPARE(qApp->focusWidget(), static_cast(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(0)); + QCOMPARE(qApp->focusWidget(), static_cast(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(0)); + QCOMPARE(qApp->focusWidget(), static_cast(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(0)); + QCOMPARE(qApp->focusWidget(), static_cast(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(0)); +#ifdef Q_WS_QWS + QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue); +#endif + QTRY_COMPARE(qApp->focusWidget(), static_cast(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 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 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 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 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 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 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 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 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 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 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 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(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("fileName"); + QTest::addColumn("expectedWindowState"); + QTest::addColumn("expectedPosition"); + QTest::addColumn("expectedSize"); + QTest::addColumn("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(text_prop.value); + } else { + text_prop.nitems = strlen(reinterpret_cast(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 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 sibling; +}; + + +void tst_QWidget::childDeletesItsSibling() +{ + QWidget *commonParent = new QWidget(0); + QPointer child = new QWidget(0); + QPointer 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 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("show"); + QTest::addColumn("hide"); + QTest::addColumn("create"); + QTest::addColumn("expectedShowEvents"); + QTest::addColumn("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(object) != 0 || object->isWidgetType()); + } +}; + +/* + Test that qobject_cast 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) + +// 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 >("rects"); + QTest::addColumn("windowFlags"); + + QList > rects; + rects << (QList() + << 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() + << 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(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(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(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 windowFlags; + windowFlags << 0 << Qt::FramelessWindowHint; + + foreach (QList 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, 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, 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("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(&w1)); + QTest::qWait(50); + QTest::mouseDClick(&w1, Qt::LeftButton); + QTRY_COMPARE(QApplication::focusWidget(), static_cast(w1.edit)); + + w2.activateWindow(); + QApplication::setActiveWindow(&w2); + QApplication::processEvents(); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&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(w2.edit)); + + w1.activateWindow(); + QApplication::setActiveWindow(&w1); + QApplication::processEvents(); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&w1)); + QTest::mouseDClick(&w1, Qt::LeftButton); + QTRY_COMPARE(QApplication::focusWidget(), static_cast(w1.edit)); + + w2.activateWindow(); + QApplication::setActiveWindow(&w2); + QApplication::processEvents(); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&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(0)); + + child2.setFocus(); + QVERIFY(!child2.hasFocus()); + QCOMPARE(window.focusWidget(), &child2); + QCOMPARE(QApplication::focusWidget(), static_cast(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(0)); + + child2.setFocus(); + QVERIFY(!child2.hasFocus()); + QCOMPARE(window.focusWidget(), &child2); + QCOMPARE(QApplication::focusWidget(), static_cast(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(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(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(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(0)); + + child1.hide(); + QVERIFY(!child1.hasFocus()); + QCOMPARE(window.focusWidget(), static_cast(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(0)); + + child1.show(); + QVERIFY(!child1.hasFocus()); + QCOMPARE(window.focusWidget(), static_cast(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(0)); + + child2.setFocus(); + QVERIFY(!child2.hasFocus()); + QCOMPARE(window.focusWidget(), static_cast(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(0)); + + child2.hide(); + QVERIFY(!child2.hasFocus()); + QCOMPARE(window.focusWidget(), static_cast(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(0)); + + child2.show(); + QVERIFY(!child2.hasFocus()); + QCOMPARE(window.focusWidget(), static_cast(0)); + QCOMPARE(QApplication::focusWidget(), static_cast(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 applicationEventSpies; + QList 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 > 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(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(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(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(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("autoFillBackground"); + QTest::addColumn("usePaintEvent"); + QTest::addColumn("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("size"); + QTest::addColumn("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("initial"); + QTest::addColumn("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("sizeHint"); + QTest::addColumn("hPolicy"); + QTest::addColumn("vPolicy"); + QTest::addColumn("hfwSP"); + QTest::addColumn("layout"); + QTest::addColumn("hfwLayout"); + QTest::addColumn("haveParent"); + QTest::addColumn("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("minSize"); + QTest::addColumn("shouldInvalidate"); + QTest::addColumn("maxSize"); + QTest::addColumn("shouldInvalidate2"); + QTest::addColumn("verticalSizePolicy"); + QTest::addColumn("shouldInvalidate3"); + QTest::addColumn("setVisible"); + QTest::addColumn("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(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(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(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(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 blurEffect = new QGraphicsBlurEffect; + widget->setGraphicsEffect(blurEffect); + QCOMPARE(widget->graphicsEffect(), static_cast(blurEffect)); + + // Ensure the existing effect is deleted when setting a new one. + QPointer shadowEffect = new QGraphicsDropShadowEffect; + widget->setGraphicsEffect(shadowEffect); + QVERIFY(!blurEffect); + QCOMPARE(widget->graphicsEffect(), static_cast(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(d_ptr.data())->topData()->backingStoreTracker.destroy(); + } + void enableBackingStore() + { + if (!static_cast(d_ptr.data())->maybeBackingStore()) { + static_cast(d_ptr.data())->topData()->backingStoreTracker.create(this); + static_cast(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(toolBar)); + QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(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(toolBar)); + QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(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(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 +#include +#include + +#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 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 +#include + + +QString nativeWindowTitle(QWidget *window, Qt::WindowState state) +{ + OSWindowRef windowRef = qt_mac_window_for(window); + QCFString macTitle; + if (state == Qt::WindowMinimized) { + macTitle = reinterpret_cast([[windowRef miniwindowTitle] retain]); + } else { + macTitle = reinterpret_cast([[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 +#include +#include +#include + +#include + +#ifdef Q_WS_X11 +#include +#include +#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("setWindowTitleBefore"); + QTest::addColumn("setWindowTitleAfter"); + QTest::addColumn("filePath"); + QTest::addColumn("applicationName"); + QTest::addColumn("indyWindowTitle"); + QTest::addColumn("finalTitleBefore"); + QTest::addColumn("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("filePath"); + QTest::addColumn("result"); + QTest::addColumn("again"); + QTest::addColumn("filePath2"); + QTest::addColumn("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 + +#include +#include +#include +#include +#include +#include +#include +#include + +//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 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 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 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 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 combo1 = new QComboBox; + a->setDefaultWidget(combo1); + QVERIFY(a->defaultWidget() == combo1); + a->setDefaultWidget(combo1); + QVERIFY(combo1); + QVERIFY(a->defaultWidget() == combo1); + + QPointer 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 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 combos = action->createdWidgets(); + QCOMPARE(combos.count(), 1); + + QPointer combo1 = qobject_cast(combos.at(0)); + QVERIFY(combo1); + + tb2.addAction(action); + + combos = action->createdWidgets(); + QCOMPARE(combos.count(), 2); + + QVERIFY(combos.at(0) == combo1); + QPointer combo2 = qobject_cast(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 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 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 +#include + +#include + +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"); } + +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"); + 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("size1"); + QTest::addColumn("size2"); + QTest::addColumn("size3"); + QTest::addColumn("expectedHeight1"); + QTest::addColumn("expectedHeight2"); + QTest::addColumn("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) <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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/button.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/combobox.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/mdi.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/menu.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/slider.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/button.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/combobox.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/menu.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/slider.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png 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 Binary files /dev/null and b/tests/auto/widgets/styles/qstyle/task_25863.png 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 +#include +#include "qstyle.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef Q_WS_MAC +#include +#endif + +#ifdef Q_WS_WIN +#include +#include +#endif + +#ifdef Q_OS_WINCE +#include +#endif + +#ifdef Q_OS_WINCE_WM +#include +#include + +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 (QString::fromLatin1("Smartphone").utf16()), tszPlatform)) + return true; + return false; +} +#endif + +#include + +//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(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() << 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(&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 +#include + + +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 +struct StyleOptionPointer: public StyleOptionPointerBase +{ + StyleOptionPointer(T *p = 0): StyleOptionPointerBase(p) {} + ~StyleOptionPointer() { delete static_cast(pointer); pointer = 0; } +}; + +Q_DECLARE_METATYPE(StyleOptionPointerBase*) + +template +inline StyleOptionPointerBase *stylePtr(T *ptr) { return new StyleOptionPointer(ptr); } + +void tst_QStyleOption::qstyleoptioncast_data() +{ + QTest::addColumn("testOption"); + QTest::addColumn("canCastToComplex"); + QTest::addColumn("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(testOption->pointer); + QVERIFY(castOption != 0); + + // Cast to complex base class + castOption = qstyleoption_cast(testOption->pointer); + QCOMPARE(canCastToComplex, (castOption != 0)); + + // Cast to combo box + castOption = qstyleoption_cast(testOption->pointer); + QCOMPARE((castOption != 0),(testOption->pointer->type == QStyleOption::SO_ComboBox)); + + // Cast to button + castOption = qstyleoption_cast(testOption->pointer); + QCOMPARE((castOption != 0),(testOption->pointer->type == QStyleOption::SO_Button)); + + // Cast to lower version + testOption->pointer->version += 1; + castOption = qstyleoption_cast(testOption->pointer); + QVERIFY(castOption); + + // Cast a null pointer + castOption = qstyleoption_cast((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 Binary files /dev/null and b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png 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 @@ + + + + images/testimage.png + + \ 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 +#include +#include +#include +#include +#include + +#include +#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 pstyle1 = &style1; + QPointer 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(&style1), window1->style()); + + // Setting another style must not delete the older style + window1->setStyle(&style2); + QCOMPARE(static_cast(&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 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(&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(&style1)); // the same guy + + // Remove the stylesheet + proxy = (QStyleSheetStyle *)window1->style(); + window1->setStyleSheet(""); + QVERIFY(proxy.isNull()); // should have disappeared + QCOMPARE(window1->style(), static_cast(&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(&style1)); + + // Style Sheet propagation on a child widget with a custom style already set + window2->setStyleSheet(""); + QCOMPARE(window2->style(), static_cast(&style2)); + QCOMPARE(widget2->style(), static_cast(&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(newStyle)); // magic ;) the widget still follows the application + QCOMPARE(static_cast(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(&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 style1 = new QWindowsStyle; + QPointer 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 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(&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 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 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 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"); + + 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(&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(&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(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 widgets; + QList 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(); + 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(); + QVERIFY(embedded); + QTest::qWait(20); + QCOMPARE(box.font().pixelSize(), 32); + QCOMPARE(embedded->font().pixelSize(), 32); +} + +void tst_QStyleSheetStyle::opaquePaintEvent_data() +{ + QTest::addColumn("stylesheet"); + QTest::addColumn("transparent"); + QTest::addColumn("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 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 +#include +#include +#include +#include +#include +#include + +#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(Qt::EditRole)); // default value + completer.setCompletionRole(Qt::DisplayRole); + QCOMPARE(completer.completionRole(), static_cast(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("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("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("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("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("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("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("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("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("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("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("filterText"); + QTest::addColumn("step"); + QTest::addColumn("completion"); + QTest::addColumn("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("filterText"); + QTest::addColumn("hasChildren"); + QTest::addColumn("rowCount"); + QTest::addColumn("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("filterText"); + QTest::addColumn("hasChildren"); + QTest::addColumn("rowCount"); + QTest::addColumn("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(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(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(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 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("list"); + QTest::addColumn("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(&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(&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 +#include +#include +// #include + +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(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(e); + // qDebug() << "Scroll for"<scrollPos()<<"ov"<overshoot()<<"first"<isFirst()<<"last"<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() << 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() << 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() << 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() << 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() << 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() << 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(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::OvershootAlwaysOff); + + sp1.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn)); + QCOMPARE(sp1.scrollMetric(QScrollerProperties::VerticalOvershootPolicy).value(), QScrollerProperties::OvershootAlwaysOn); + + sp1.setScrollMetric(QScrollerProperties::FrameRate, QVariant::fromValue(QScrollerProperties::Fps20)); + QCOMPARE(sp1.scrollMetric(QScrollerProperties::FrameRate).value(), 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: "<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: "<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: "<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 Binary files /dev/null and b/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png 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 + +#include +#include +#include +#include + +//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 @@ + + + + + QUndoGroup + + Undo %1 + undo-prefix %1 undo-suffix + + + Undo + Default text for undo action + Undo-default-text + + + Redo %1 + redo-prefix %1 redo-suffix + + + Redo + Default text for redo action + Redo-default-text + + + 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 +#include +#include +#include + +// 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(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() << &stack1); + + QUndoStack stack2; + group.addStack(&stack2); + QCOMPARE(group.stacks(), QList() << &stack1 << &stack2); + + group.addStack(&stack1); + QCOMPARE(group.stacks(), QList() << &stack1 << &stack2); + + group.removeStack(&stack1); + QCOMPARE(group.stacks(), QList() << &stack2); + + group.removeStack(&stack1); + QCOMPARE(group.stacks(), QList() << &stack2); + + group.removeStack(&stack2); + QCOMPARE(group.stacks(), QList()); +} + +void tst_QUndoGroup::deleteStack() +{ + QUndoGroup group; + + QUndoStack *stack1 = new QUndoStack(&group); + QCOMPARE(group.stacks(), QList() << stack1); + QCOMPARE(group.activeStack(), (QUndoStack*)0); + + stack1->setActive(); + QCOMPARE(group.activeStack(), stack1); + + QUndoStack *stack2 = new QUndoStack(&group); + QCOMPARE(group.stacks(), QList() << stack1 << stack2); + QCOMPARE(group.activeStack(), stack1); + + QUndoStack *stack3 = new QUndoStack(&group); + QCOMPARE(group.stacks(), QList() << stack1 << stack2 << stack3); + QCOMPARE(group.activeStack(), stack1); + + delete stack2; + QCOMPARE(group.stacks(), QList() << stack1 << stack3); + QCOMPARE(group.activeStack(), stack1); + + delete stack1; + QCOMPARE(group.stacks(), QList() << 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()); + 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 @@ + + + + + QUndoStack + + Undo %1 + undo-prefix %1 undo-suffix + + + Undo + Default text for undo action + Undo-default-text + + + Redo %1 + redo-prefix %1 redo-suffix + + + Redo + Default text for redo action + Redo-default-text + + + 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 +#include +#include + +//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(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 + + + +#include +#include +#include +#include +#include +#include + + + +#include + +//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("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("&ersand"); + QCOMPARE( testWidget->text(), QString("&ersand") ); +#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 + +#include +#include +#include +#include +#include +#include +#include +#include + +//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 vbar = scrollArea.verticalScrollBar(); + QPointer 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("dir"); + QTest::addColumn("key"); + QTest::addColumn("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 +#include +#include +#include +#include +#include +#include +#include + +// 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) +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("sliderAction"); + QTest::addColumn("maximum"); + QTest::addColumn("minimum"); + QTest::addColumn("initialSliderPosition"); + QTest::addColumn("singleStep"); + QTest::addColumn("pageStep"); + QTest::addColumn("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(&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("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("expectedMinimum"); + QTest::addColumn("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("initialSliderPosition"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("stepSize"); + QTest::addColumn("pageSize"); + QTest::addColumn >("keySequence"); + QTest::addColumn("expectedSliderPositionHorizontal"); + QTest::addColumn("expectedSliderPositionVertical"); + QTest::addColumn("expectedSliderPositionHorizontalInverted"); // :) + QTest::addColumn("expectedSliderPositionVerticalInverted"); + + + QList 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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, 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;isliderPosition(), 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;isliderPosition(), 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;isliderPosition(), 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;isliderPosition(), expectedSliderPositionVerticalInverted); +} + +void tst_QAbstractSlider::wheelEvent_data() +{ + QTest::addColumn("initialSliderPosition"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("singleStep"); + QTest::addColumn("pageStep"); + QTest::addColumn("invertedControls"); + QTest::addColumn("wheelScrollLines"); + QTest::addColumn("withModifiers"); // use keyboard modifiers while scrolling? (CTRL and SHIFT) + QTest::addColumn("deltaMultiple"); // multiples of WHEEL_DELTA + QTest::addColumn("sliderOrientation"); + QTest::addColumn("wheelOrientation"); + QTest::addColumn("expectedSliderPosition"); + QTest::addColumn("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(&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(&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("control"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("subControl"); + QTest::addColumn("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("control"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("position"); + QTest::addColumn("sliderDown"); + QTest::addColumn("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("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("newMin"); + QTest::addColumn("newMax"); + QTest::addColumn("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("tracking"); + QTest::addColumn("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("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 + +#include +#include +#include +#include +#include + + +//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 + + +#include "qbuttongroup.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef Q_WS_MAC +#include +#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 + +//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 *"); + 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*"); + QSignalSpy spy1(buttons, SIGNAL(buttonClicked(QAbstractButton*))); + QSignalSpy spy2(buttons, SIGNAL(buttonClicked(int))); + + QApplication::setActiveWindow(&dlg); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&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("deleteButton"); + QTest::addColumn("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 *"); + + 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 + +#include +#include +#include +#include +#include +#include +#include + + +//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(&object, "qt_calendar_prevmonth"); + QTest::mouseClick(button, Qt::LeftButton); + QCOMPARE(month > 1 ? month-1 : 12, object.monthShown()); + button = qFindChild(&object, "qt_calendar_nextmonth"); + QTest::mouseClick(button, Qt::LeftButton); + QCOMPARE(month, object.monthShown()); + + button = qFindChild(&object, "qt_calendar_yearbutton"); + QTest::mouseClick(button, Qt::LeftButton, Qt::NoModifier, button->rect().center(), 2); + QVERIFY(!button->isVisible()); + QSpinBox *spinbox = qFindChild(&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(&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(&object, "qt_calendar_prevmonth"); + QTest::mouseClick(button, Qt::LeftButton); + QCOMPARE(1, object.monthShown()); + + button = qFindChild(&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(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("function"); + QTest::addColumn("dateOrigin"); + QTest::addColumn("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(&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 + + +#include "qcheckbox.h" +#include +#include +#include +#include + +//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("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 + +#include "qcombobox.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef Q_WS_MAC +#include +#elif defined Q_WS_X11 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_STYLE_CLEANLOOKS +#include +#endif +#include +#include +#ifndef QT_NO_STYLE_WINDOWS +#include +#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 VariantList; +typedef QList IconList; + +Q_DECLARE_METATYPE(VariantList) +Q_DECLARE_METATYPE(IconList) +Q_DECLARE_METATYPE(QComboBox::InsertPolicy) + +tst_QComboBox::tst_QComboBox() +{ + qRegisterMetaType("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(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; icount(); ++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("initialEntries"); + QTest::addColumn("insertPolicy"); + QTest::addColumn("currentIndex"); + QTest::addColumn("userInput"); + QTest::addColumn("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; icount(); ++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("initialItems"); + QTest::addColumn("setCurrentIndex"); + QTest::addColumn("removeIndex"); + QTest::addColumn("insertIndex"); + QTest::addColumn("insertText"); + QTest::addColumn("expectedCurrentIndex"); + QTest::addColumn("expectedCurrentText"); + QTest::addColumn("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("initialItems"); + QTest::addColumn("insertedItems"); + QTest::addColumn("insertIndex"); + QTest::addColumn("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; iitemText(expectedIndex + i), insertedItems.at(i)); +} + +void tst_QComboBox::insertItem_data() +{ + QTest::addColumn("initialItems"); + QTest::addColumn("insertIndex"); + QTest::addColumn("itemLabel"); + QTest::addColumn("expectedIndex"); + QTest::addColumn("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("text"); + QTest::addColumn("icons"); + QTest::addColumn("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; iinsertItem(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; iitemIcon(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; iitemText(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(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("items"); + QTest::addColumn("matchflags"); + QTest::addColumn("search"); + QTest::addColumn("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 IntList; +typedef QList KeyList; +Q_DECLARE_METATYPE(IntList) +Q_DECLARE_METATYPE(KeyList) + +void tst_QComboBox::flaggedItems_data() +{ + QTest::addColumn("itemList"); + QTest::addColumn("deselectFlagList"); + QTest::addColumn("disableFlagList"); + QTest::addColumn("keyMovementList"); + QTest::addColumn("editable"); + QTest::addColumn("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("disabledItems"); + QTest::addColumn("startIndex"); + QTest::addColumn("wheelDirection"); + QTest::addColumn("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("items"); + QTest::addColumn("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(&listCombo); + QVERIFY(container); + QCOMPARE(static_cast(list), qFindChild(container)); + QWidget *top = qFindChild(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(&tableCombo); + QVERIFY(container); + QCOMPARE(static_cast(table), qFindChild(container)); + foreach (QWidget *button, qFindChildren(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(&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(&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(0), Qt::Key_Down); + QTest::keyClick(static_cast(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(&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("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(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(comboBox.itemDelegate()), itemDelegate); + + comboBox.setStyleSheet("QComboBox { border: 1px solid gray; }"); + QCOMPARE(static_cast(comboBox.itemDelegate()), itemDelegate); +} + + +void tst_QComboBox::subControlRectsWithOffset_data() +{ + QTest::addColumn("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(&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(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(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::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 + + +#include "qcommandlinkbutton.h" +#include + +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_WIN +# include +# 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); + +#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 (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 TimeList; +typedef QList 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"); + qRegisterMetaType("QTime"); + qRegisterMetaType("QDateTime"); + qRegisterMetaType >("QList"); +} + +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("parameter"); + QTest::addColumn("displayDateTime"); + QTest::addColumn("minimumDate"); + QTest::addColumn("minimumTime"); + QTest::addColumn("maximumDate"); + QTest::addColumn("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("parameter"); + QTest::addColumn("displayDateTime"); + QTest::addColumn("minimumDate"); + QTest::addColumn("minimumTime"); + QTest::addColumn("maximumDate"); + QTest::addColumn("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("parameter"); + QTest::addColumn("displayDateTime"); + QTest::addColumn("minimumDate"); + QTest::addColumn("minimumTime"); + QTest::addColumn("maximumDate"); + QTest::addColumn("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("minimumDate"); + QTest::addColumn("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("minimumDateTime"); + QTest::addColumn("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("maximumDateTime"); + QTest::addColumn("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("maximumDate"); + QTest::addColumn("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("minimumDate"); + QTest::addColumn("valid"); + QTest::addColumn("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("minimumDateTime"); + QTest::addColumn("valid"); + QTest::addColumn("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("maximumDateTime"); + QTest::addColumn("valid"); + QTest::addColumn("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("maximumDate"); + QTest::addColumn("valid"); + QTest::addColumn("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("format"); + QTest::addColumn("valid"); + QTest::addColumn("text"); + QTest::addColumn("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("minTime"); + QTest::addColumn("maxTime"); + QTest::addColumn("minDate"); + QTest::addColumn("maxDate"); + QTest::addColumn("expectedMin"); + QTest::addColumn("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("startWithMin"); + QTest::addColumn("minimumTime"); + QTest::addColumn("maximumTime"); + QTest::addColumn("section"); + QTest::addColumn("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("ampm"); + QTest::addColumn("keys"); + QTest::addColumn("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("startWithMin"); + QTest::addColumn("minimumDate"); + QTest::addColumn("maximumDate"); + QTest::addColumn("section"); + QTest::addColumn("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("originalDate"); + QTest::addColumn("newDate"); + QTest::addColumn("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 list = dateSpy.takeFirst(); + QDate d; + d = qVariantValue(list.at(0)); + QCOMPARE(d, newDate); + } + QCOMPARE(dateTimeSpy.count(), timesEmitted); + QCOMPARE(timeSpy.count(), 0); +} + +void tst_QDateTimeEdit::timeSignalChecking_data() +{ + QTest::addColumn("originalTime"); + QTest::addColumn("newTime"); + QTest::addColumn("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 list = timeSpy.takeFirst(); + QTime t; + t = qVariantValue(list.at(0)); + QCOMPARE(t, newTime); + } + QCOMPARE(dateTimeSpy.count(), timesEmitted); + QCOMPARE(dateSpy.count(), 0); +} + +void tst_QDateTimeEdit::dateTimeSignalChecking_data() +{ + QTest::addColumn("originalDateTime"); + QTest::addColumn("newDateTime"); + QTest::addColumn("timesDateEmitted"); + QTest::addColumn("timesTimeEmitted"); + QTest::addColumn("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 list = dateSpy.takeFirst(); + QDate d; + d = qVariantValue(list.at(0)); + QCOMPARE(d, newDateTime.date()); + } + QCOMPARE(timeSpy.count(), timesTimeEmitted); + if (timesTimeEmitted > 0) { + QList list = timeSpy.takeFirst(); + QTime t; + t = qVariantValue(list.at(0)); + QCOMPARE(t, newDateTime.time()); + } + QCOMPARE(dateTimeSpy.count(), timesDateTimeEmitted); + if (timesDateTimeEmitted > 0) { + QList list = dateTimeSpy.takeFirst(); + QDateTime dt; + dt = qVariantValue(list.at(0)); + QCOMPARE(dt, newDateTime); + } +} + + +void tst_QDateTimeEdit::sectionText_data() +{ + QTest::addColumn("format"); + QTest::addColumn("dateTime"); + QTest::addColumn("section"); + QTest::addColumn("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("format"); + QTest::addColumn("keys"); + QTest::addColumn("expected"); + QTest::addColumn("start"); + QTest::addColumn("min"); + QTest::addColumn("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; itime(), expected.at(i)); + } +} + + +void tst_QDateTimeEdit::displayedSections_data() +{ + QTest::addColumn("format"); + QTest::addColumn("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("format"); + QTest::addColumn("section"); + QTest::addColumn("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 makeList(int val1, int val2, int val3) +{ + QList ret; + ret << val1 << val2 << val3; + return ret; +} + + +void tst_QDateTimeEdit::setCurrentSection_data() +{ + QTest::addColumn("format"); + QTest::addColumn("dateTime"); + QTest::addColumn >("setCurrentSections"); + QTest::addColumn >("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, setCurrentSections); + QFETCH(QList, 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; isetCurrentSection((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(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(&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(&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("key"); + QTest::addColumn("modifiers"); + QTest::addColumn("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("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("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 + +#include + +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 +#include +#include +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +Q_DECLARE_METATYPE(QList) +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 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("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("orientation"); + QTest::addColumn("buttons"); + QTest::addColumn("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("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("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("role"); + QTest::addColumn("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 children = qFindChildren(&buttonBox); + QTEST(children.count(), "totalCount"); + delete button; +} + +void tst_QDialogButtonBox::addButton2_data() +{ + QTest::addColumn("text"); + QTest::addColumn("role"); + QTest::addColumn("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 children = qFindChildren(&buttonBox); + QTEST(children.count(), "totalCount"); +} + +void tst_QDialogButtonBox::addButton3_data() +{ + QTest::addColumn("button"); + QTest::addColumn("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 children = qFindChildren(&buttonBox); + QTEST(children.count(), "totalCount"); +} + +void tst_QDialogButtonBox::clear_data() +{ + QTest::addColumn("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 children = qFindChildren(&buttonBox); + QCOMPARE(children.count(), 0); +} + +void tst_QDialogButtonBox::removeButton_data() +{ + QTest::addColumn("roleToAdd"); + QTest::addColumn("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 children = qFindChildren(&buttonBox); + QCOMPARE(children.count(), 1); + + delete deleteMe; + children = qFindChildren(&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("roleToAdd"); + QTest::addColumn("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("button"); + QTest::addColumn("expectedRole"); + QTest::addColumn("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("buttonToClick"); + QTest::addColumn("clicked2Count"); + QTest::addColumn("acceptCount"); + QTest::addColumn("rejectCount"); + QTest::addColumn("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*"); + 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(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("buttonsToAdd"); + QTest::addColumn("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("whenToSetDefault"); // -1 Do nothing, 0 after accept, 1 before accept + QTest::addColumn("buttonToBeDefault"); + QTest::addColumn("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 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 + + +#include +#include +#include +#include +#include +#include +#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"); + qRegisterMetaType("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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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"); + + 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(spy.at(0).at(0)), + Qt::LeftDockWidgetArea); + spy.clear(); + + mw.addDockWidget(Qt::LeftDockWidgetArea, &dw); + QCOMPARE(spy.count(), 1); + QCOMPARE(qvariant_cast(spy.at(0).at(0)), + Qt::LeftDockWidgetArea); + spy.clear(); + + mw.addDockWidget(Qt::RightDockWidgetArea, &dw); + QCOMPARE(spy.count(), 1); + QCOMPARE(qvariant_cast(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(spy.at(0).at(0)), + Qt::TopDockWidgetArea); + spy.clear(); + + mw.splitDockWidget(&dw2, &dw, Qt::Horizontal); + QCOMPARE(spy.count(), 1); + QCOMPARE(qvariant_cast(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(spy.at(0).at(0)), + Qt::TopDockWidgetArea); + spy.clear(); + + QByteArray ba = mw.saveState(); + mw.restoreState(ba); + QCOMPARE(spy.count(), 1); + QCOMPARE(qvariant_cast(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(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 +#include +#include + +#include + +#include +#include +#include + +#include +#include + +//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 actualValues; + QWidget *testFocusWidget; +}; + +typedef QList 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("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("prefix"); + QTest::addColumn("suffix"); + QTest::addColumn("value"); + QTest::addColumn("decimals"); + QTest::addColumn("expectedText"); + QTest::addColumn("expectedCleanText"); + QTest::addColumn("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("decimals"); + QTest::addColumn("keys"); + QTest::addColumn("texts"); + QTest::addColumn("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("wrapping"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("startValue"); + QTest::addColumn("keys"); + QTest::addColumn("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("specialValueText"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("value"); + QTest::addColumn("decimals"); + QTest::addColumn("expected"); + QTest::addColumn("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("singleStep"); + QTest::addColumn("startValue"); + QTest::addColumn("keys"); + QTest::addColumn("expected"); + QTest::addColumn("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("startValue"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("keys"); + QTest::addColumn("expected"); + QTest::addColumn("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("decimals"); + QTest::addColumn("expectedDecimals"); + QTest::addColumn("startValue"); + QTest::addColumn("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("txt"); + QTest::addColumn("state"); + QTest::addColumn("mini"); + QTest::addColumn("maxi"); + QTest::addColumn("language"); + QTest::addColumn("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(&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(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 + + +#include + +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("localeName"); + QTest::addColumn("value"); + QTest::addColumn("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("localeName"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("decimals"); + QTest::addColumn("value"); + QTest::addColumn("scientific_state"); + QTest::addColumn("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"); + 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("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("input"); + QTest::addColumn("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 + +#include +#include +#include + + +//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 +#include + +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("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("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("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 +#include +#include +#include +#include +#include + +#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("title"); + QTest::addColumn("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("checkable"); + QTest::addColumn("expectedCheckable"); + QTest::newRow( "checkable_true" ) << true << true; + QTest::newRow( "checkable_false" ) << false << false; +} + +void tst_QGroupBox::setChecked_data() +{ + QTest::addColumn("checkable"); + QTest::addColumn("checked"); + QTest::addColumn("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("checkable"); + QTest::addColumn("initialCheck"); + QTest::addColumn("areaToHit"); + QTest::addColumn("clickedCount"); + QTest::addColumn("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(object)) { + QVERIFY(!widget->isEnabled()); + QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); + } + } + + box.setChecked(true); + foreach (QObject *object, box.children()) { + if (QWidget *widget = qobject_cast(object)) { + QVERIFY(widget->isEnabled()); + QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); + } + } + + box.setChecked(false); + foreach (QObject *object, box.children()) { + if (QWidget *widget = qobject_cast(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(&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 +#include + +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("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("value"); + QTest::addColumn("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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/green.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/red.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/acc_01/res_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data10.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data3.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data4.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data5.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data6.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data7.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data8.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Motif_data9.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data10.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data3.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data4.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data5.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data6.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data7.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data8.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_data9.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data10.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data3.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data4.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data5.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data6.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data7.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data8.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setAlignment/alignRes_Windows_win32_data9.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Motif_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setIndent/indentRes_Windows_win32_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/empty_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setPixmap/scaledVpix_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Motif_data3.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_data3.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data1.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data2.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/testdata/setText/res_Windows_win32_data3.qsnap 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 + + +#include "qlabel.h" +#include +#include +#include +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class Widget : public QWidget +{ +public: + Widget() { } + + QList 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 test_box; + QPointer 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("txt"); + QTest::addColumn("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 bold 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("rich text"); + QVERIFY(!label.wordWrap()); + + label.setWordWrap(false); + label.setText("rich text"); + QVERIFY(!label.wordWrap()); +} + +void tst_QLabel::eventPropagation_data() +{ + QTest::addColumn("text"); + QTest::addColumn("textInteractionFlags"); + QTest::addColumn("focusPolicy"); + QTest::addColumn("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("rich text") << (int)Qt::LinksAccessibleByMouse << (int)Qt::NoFocus << true; + QTest::newRow("rich text2") << QString("rich text") << (int)Qt::TextSelectableByKeyboard << (int)Qt::ClickFocus << true; + QTest::newRow("rich text3") << QString("rich text") << (int)Qt::TextSelectableByMouse << (int)Qt::ClickFocus << false; + QTest::newRow("rich text4") << QString("rich text") << (int)Qt::NoTextInteraction << (int)Qt::NoFocus << true; + QTest::newRow("rich text4") << QString("rich text") << (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("text"); + QTest::addColumn("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("text"); + QTest::addColumn("expectedDocText"); + QTest::addColumn("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 &&") << QString("&With Double &") << 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(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 + +#include +#include +#include + + +//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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Motif-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/frame/noFrame_Windows-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Motif-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/frame/useFrame_Windows-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Motif-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/auto_Windows-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Motif-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/hcenter_Windows-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Motif-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/left_Windows-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Motif-32x96x96_win.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qlineedit/testdata/setAlignment/right_Windows-32x96x96_win.png 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 +#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 // For the random function. +#include // For the random function. +#endif + +#include +#include +#include +#include +#include + +//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 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("mask"); + QTest::addColumn("input"); + QTest::addColumn("expectedText"); + QTest::addColumn("expectedDisplay"); + QTest::addColumn("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;#") + << 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("AAAAaaaaAA>AAA>Aaa>aaa>aHH>Hhh>hsetInputMask(mask); + + // then either insert using insert() or keyboard + if (insert_text) { + testWidget->insert(input); + } else { + psKeyClick(testWidget, Qt::Key_Home); + for (int i=0; itext(), expectedText); + QCOMPARE(testWidget->displayText(), expectedDisplay); +} + +void tst_QLineEdit::inputMask_data() +{ + QTest::addColumn("mask"); + QTest::addColumn("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(">abcdefabcdefsetInputMask(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("mask"); + QTest::addColumn("keys"); + QTest::addColumn("expectedText"); + QTest::addColumn("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("optionalMask"); + QTest::addColumn("requiredMask"); + QTest::addColumn("invalid"); + QTest::addColumn("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("mask"); + QTest::addColumn("input"); + QTest::addColumn("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("insertString"); + QTest::addColumn("insertIndex"); + QTest::addColumn("insertMode"); + QTest::addColumn("expectedString"); + QTest::addColumn("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 -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; itext(), 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 -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; itext(), expectedString[i]); + QVERIFY(testWidget->isUndoAvailable()); + QTest::keyClick(testWidget, Qt::Key_Backspace, Qt::AltModifier); + } +#endif +} + +void tst_QLineEdit::redo_data() +{ + QTest::addColumn("insertString"); + QTest::addColumn("insertIndex"); + QTest::addColumn("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 -1) + testWidget->setCursorPosition(insertIndex[i]); + testWidget->insert(insertString[i]); + } + + QVERIFY(!testWidget->isRedoAvailable()); + + // undo everything + while (!testWidget->text().isEmpty()) + testWidget->undo(); + + for (i=0; iisRedoAvailable()); + 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("keys"); + QTest::addColumn("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; itext() , 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("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("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("insertString"); + QTest::addColumn("expectedString"); + QTest::addColumn("mode"); + QTest::addColumn("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("mask"); + QTest::addColumn("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("insertString"); + QTest::addColumn("expectedString"); + QTest::addColumn("length"); + QTest::addColumn("insertBeforeSettingMaxLength"); + QTest::addColumn("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("input"); + QTest::addColumn("lastPos"); + QTest::addColumn("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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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") << 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("inputMask"); + QTest::addColumn("hasValidator"); + QTest::addColumn("input"); + QTest::addColumn("expectedText"); + QTest::addColumn("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'") + << 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'") + << 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'") + << 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'") + << 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'") + << 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'") + << 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 ''") + << 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'", "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(&iv1)); + + testWidget->setValidator(0); + QVERIFY(testWidget->validator() == 0); + + QIntValidator iv2(0, 99, 0); + testWidget->setValidator(&iv2); + QCOMPARE(testWidget->validator(), static_cast(&iv2)); + + testWidget->setValidator(0); + QVERIFY(testWidget->validator() == 0); +} + +void tst_QLineEdit::setValidator_QIntValidator_data() +{ + QTest::addColumn("mini"); + QTest::addColumn("maxi"); + QTest::addColumn("input"); + QTest::addColumn("expectedText"); + QTest::addColumn("useKeys"); + QTest::addColumn("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("noFrame"); + QTest::addColumn("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("left"); + QTest::addColumn("right"); + QTest::addColumn("hcenter"); + QTest::addColumn("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("text"); + QTest::addColumn("start"); + QTest::addColumn("length"); + QTest::addColumn("expectedCursor"); + QTest::addColumn("expectedText"); + QTest::addColumn("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("inputMask"); + QTest::addColumn("keys"); + QTest::addColumn("validateText"); + QTest::addColumn("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("left"); + QTest::addColumn("top"); + QTest::addColumn("right"); + QTest::addColumn("bottom"); + + QTest::addColumn("mousePressPos"); + QTest::addColumn("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("maxLength"); + QTest::addColumn("cursorPos"); + QTest::addColumn("replacementStart"); + QTest::addColumn("replacementLength"); + QTest::addColumn("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(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("logical"); + QTest::addColumn("basicDir"); + QTest::addColumn("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() << 0 << 1 << 2 << 3); + QTest::newRow("Hebrew text after Latin text") + << QString::fromUtf8("abc\327\220\327\221\327\222") + << (int) QChar::DirL + << (QList() << 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() << 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() << 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() << 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() << 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() << 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 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 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 var1 = new QMenuBar; + obj1.setMenuBar(var1); + QCOMPARE(static_cast(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 var2 = new QStatusBar; + obj1.setStatusBar(var2); + QCOMPARE(static_cast(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"); + qRegisterMetaType("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(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(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(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(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(mwSpy.first().first().constData()), + Qt::ToolButtonTextOnly); + QCOMPARE(*static_cast(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(mwSpy.first().first().constData()), + Qt::ToolButtonTextBesideIcon); + QCOMPARE(*static_cast(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(mwSpy.first().first().constData()), + Qt::ToolButtonTextUnderIcon); + QCOMPARE(*static_cast(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(mwSpy.first().first().constData()), + Qt::ToolButtonIconOnly); + QCOMPARE(*static_cast(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(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(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(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 mb1 = new QMenuBar; + QPointer 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 topLeftCornerWidget = new QWidget; + mb1->setCornerWidget(topLeftCornerWidget, Qt::TopLeftCorner); + QPointer 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(topLeftCornerWidget)); + QVERIFY(topRightCornerWidget); + QCOMPARE(mb2->cornerWidget(Qt::TopRightCorner), static_cast(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 sb1 = new QStatusBar; + QPointer 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(&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 w1 = new QWidget; + QPointer 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 w1 = new QWidget; + QPointer 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 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 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 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 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(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 MoveList; +Q_DECLARE_METATYPE(MoveList) + +void MoveSeparator::apply(QMainWindow *mw) const +{ + QMainWindowLayout *l = qFindChild(mw); + QVERIFY(l); + + QList path; + if (name.isEmpty()) { + path << area; + } else { + QDockWidget *dw = qFindChild(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 dockWidgetGeometries(QMainWindow *mw) +{ + QMap result; + QList dockWidgets = qFindChildren(mw); + foreach (QDockWidget *dw, dockWidgets) + result.insert(dw->objectName(), dw->geometry()); + return result; +} + +#define COMPARE_DOCK_WIDGET_GEOS(_oldGeos, _newGeos) \ +{ \ + QMap __oldGeos = _oldGeos; \ + QMap __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"); + QTest::addColumn("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 dockWidgetGeos; + QSize size; + + { + QMainWindow mainWindow; + mainWindow.setDockNestingEnabled(true); + QTextEdit centralWidget("The rain in Spain falls mainly on the plains"); + mainWindow.setCentralWidget(¢ralWidget); + + 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", ¢ralWidget); + 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(¢ralWidget); + + 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(¢ralWidget); + + 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_OPENGL +#include +#endif +#include + +#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) +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 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(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 &expectedIndices) +{ + if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty()) + return false; + + const QList 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(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 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(); +} + +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("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 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 +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 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(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(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("windowOrder"); + QTest::addColumn("windowCount"); + QTest::addColumn("activeSubWindow"); + QTest::addColumn("staysOnTop1"); + QTest::addColumn("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 activationOrder; + QVector windows; + for (int i = 0; i < windowCount; ++i) { + windows.append(qobject_cast(workspace.addSubWindow(new QWidget))); + windows[i]->show(); + activationOrder.append(windows[i]); + } + + { + QList 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 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 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 windowsBeforeViewportChange = workspace.subWindowList(); + QCOMPARE(windowsBeforeViewportChange.count(), windowCount); + + workspace.setViewport(new QWidget); + qApp->processEvents(); + QVERIFY(workspace.viewport() != firstViewport); + + QList 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 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 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("startSize"); + QTest::addColumn("increment"); + QTest::addColumn("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 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(lineEdit2)); + + QMdiArea mdiArea; + mdiArea.addSubWindow(view); + QCOMPARE(view->focusWidget(), static_cast(lineEdit2)); + + mdiArea.show(); + view->show(); + qApp->setActiveWindow(&mdiArea); + QCOMPARE(qApp->focusWidget(), static_cast(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 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("activationOrder"); + QTest::addColumn("subWindowCount"); + QTest::addColumn("staysOnTopIndex"); + QTest::addColumn("firstActiveIndex"); + QTest::addColumn >("expectedActivationIndices"); + // The order of expectedCascadeIndices: + // window 1 -> (index 0) + // window 2 -> (index 1) + // window 3 -> (index 2) + // .... + QTest::addColumn >("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 >("expectedTileIndices"); + + QList list; + QList list2; + QList 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(); + list << 3 << 1 << 4 << 3 << 1 << 2 << 0; + list2 = QList(); + list2 << 0 << 2 << 4 << 1 << 3; + list3 = QList(); + list3 << 1 << 3 << 4 << 1 << 2 << 0; + QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3; + + list = QList(); + list << 0 << 1 << 0 << 1 << 4 << 3 << 2; + list2 = QList(); + list2 << 0 << 2 << 3 << 4 << 1; + list3 = QList(); + 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, expectedActivationIndices); + QFETCH(QList, expectedCascadeIndices); + QFETCH(QList, expectedTileIndices); + + // Default order. + QMdiArea mdiArea; + QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder); + + // New order. + mdiArea.setActivationOrder(activationOrder); + QCOMPARE(mdiArea.activationOrder(), activationOrder); + + QList 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 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 subWindows = mdiArea.subWindowList(); + + // Default. + QVERIFY(!activeSubWindow->isMaximized()); + QTabBar *tabBar = qFindChild(&mdiArea); + QVERIFY(!tabBar); + QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView); + + // Tabbed view. + mdiArea.setViewMode(QMdiArea::TabbedView); + QCOMPARE(mdiArea.viewMode(), QMdiArea::TabbedView); + tabBar = qFindChild(&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(&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(&mdiArea); + QVERIFY(!tabBar); + mdiArea.setTabsClosable(true); + QCOMPARE(mdiArea.tabsClosable(), true); + + // force tab bar creation + mdiArea.setViewMode(QMdiArea::TabbedView); + tabBar = qFindChild(&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(&mdiArea); + QVERIFY(!tabBar); + mdiArea.setTabsMovable(true); + QCOMPARE(mdiArea.tabsMovable(), true); + + // force tab bar creation + mdiArea.setViewMode(QMdiArea::TabbedView); + tabBar = qFindChild(&mdiArea); + QVERIFY(tabBar); + + // value must've been propagated + QCOMPARE(tabBar->isMovable(), true); + + // test tab moving + QList 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(&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("tabPosition"); + QTest::addColumn("hasLeftMargin"); + QTest::addColumn("hasTopMargin"); + QTest::addColumn("hasRightMargin"); + QTest::addColumn("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(&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 + +#include "qmdisubwindow.h" +#include "qmdiarea.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) +#include +#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"); +} + +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 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(&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(widget)); + QCOMPARE(widget->parentWidget(), static_cast(&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(&window)); + + delete window.widget(); + QVERIFY(!widget); + QVERIFY(!window.widget()); +} + +void tst_QMdiSubWindow::setWindowState_data() +{ + QTest::addColumn("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(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 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(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(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("signal"); + QTest::addColumn("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(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(spy.at(i).at(0)); + Qt::WindowStates newState = qvariant_cast(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(window->style())) + mouseReceiver = qFindChild(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("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("opaqueMode"); + QTest::addColumn("geometryCount"); + QTest::addColumn("expectedGeometryCount"); + QTest::addColumn("workspaceSize"); + QTest::addColumn("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(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(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("windowType"); + QTest::addColumn("expectedWindowType"); + QTest::addColumn("customFlags"); + QTest::addColumn("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(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(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); + QPointersystemMenu = 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(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(systemMenu)); + QCOMPARE(subWindow->systemMenu()->parentWidget(), static_cast(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(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(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(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(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(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(expectedFocusWindow)); + + complexWindow->showMinimized(); + qApp->processEvents(); + QVERIFY(complexWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), static_cast(complexWindow)); + + complexWindow->showNormal(); + qApp->processEvents(); + QVERIFY(!complexWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), static_cast(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(firstLineEdit)); + + // Next + QTest::keyPress(widget, Qt::Key_Tab); + QCOMPARE(qApp->focusWidget(), static_cast(secondLineEdit)); + + // Next + QTest::keyPress(widget, Qt::Key_Tab); + QCOMPARE(qApp->focusWidget(), static_cast(thirdLineEdit)); + + // Previous + QTest::keyPress(widget, Qt::Key_Backtab); + QCOMPARE(qApp->focusWidget(), static_cast(secondLineEdit)); + + // Previous + QTest::keyPress(widget, Qt::Key_Backtab); + QCOMPARE(qApp->focusWidget(), static_cast(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("windowState"); + QTest::addColumn("expectedWindowResizeEvents"); + QTest::addColumn("expectedWidgetResizeEvents"); + QTest::addColumn("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(windowWithDecoration)); + + // ...but not on windows without decoration (Qt::FramelessWindowHint). + QMdiSubWindow *windowWithoutDecoration = mdiArea.addSubWindow(new QWidget, Qt::FramelessWindowHint); + windowWithoutDecoration->show(); + QVERIFY(!qFindChild(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(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 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 systemMenu = subWindow->systemMenu(); + QVERIFY(systemMenu); + QVERIFY(systemMenu->isVisible()); + + sendMouseDoubleClick(systemMenu, QPoint(10, 10)); + if (qApp->activePopupWidget() == static_cast(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//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(sender()); +} + +void tst_QMenu::onActivated(QAction *action) +{ + activated = action; + lastMenu = qobject_cast(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("key"); + QTest::addColumn("expected_action"); + QTest::addColumn("expected_menu"); + QTest::addColumn("init"); + QTest::addColumn("expected_activated"); + QTest::addColumn("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(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(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 torn = 0; + foreach (QWidget *w, QApplication::allWidgets()) { + if (w->inherits("QTornOffMenu")) { + torn = static_cast(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(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 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_WS_WIN +#include +#endif + +#include + +QT_FORWARD_DECLARE_CLASS(QMainWindow) + +#include + +//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 + +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(0), Qt::Key_A, AltKey ); + QTest::keyClick(static_cast(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(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; kaddAction( 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("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 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 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 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 menuBarActions2 = mb->actions(); + QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") ); + QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") ); + } + break; + } + QList menuBarActions2 = mb->actions(); + QVERIFY( menuBarActions2.size() == 2 ); +} + +void tst_QMenuBar::removeItemAt_data() +{ + QTest::addColumn("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 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 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 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(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(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(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(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(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(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(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(0), Qt::Key_Down ); + // and an Enter key + QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); + + // Simulate some cursor keys + QTest::keyClick(static_cast(0), Qt::Key_Left ); + QTest::keyClick(static_cast(0), Qt::Key_Down ); + QTest::keyClick(static_cast(0), Qt::Key_Right ); + QTest::keyClick(static_cast(0), Qt::Key_Down ); + // and an Enter key + QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); + + // Simulate some keys + QTest::keyClick(static_cast(0), Qt::Key_Left ); + QTest::keyClick(static_cast(0), Qt::Key_Down ); + // and press ENTER + QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); + + // Simulate some keys + QTest::keyClick(static_cast(0), Qt::Key_Down ); + QTest::keyClick(static_cast(0), Qt::Key_Down ); + QTest::keyClick(static_cast(0), Qt::Key_Down ); + QTest::keyClick(static_cast(0), Qt::Key_Home ); + // and press ENTER + QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); + + // Simulate some keys + QTest::keyClick(static_cast(0), Qt::Key_End ); + // and press ENTER + QTest::keyClick(static_cast(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(0), Qt::Key_2, Qt::AltModifier ); + QVERIFY( !pm1->isActiveWindow() ); + QVERIFY( pm2->isActiveWindow() ); + + // If we press ESC, the popup should disappear + QTest::keyClick(static_cast(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(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("popup_item"); +// QTest::addColumn("itemA_count"); +// QTest::addColumn("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("label"); +// QTest::addColumn("itemA_count"); +// QTest::addColumn("itemB_count"); +// QTest::addColumn("itemC_count"); +// QTest::addColumn("itemD_count"); +// QTest::addColumn("itemE_count"); +// QTest::addColumn("itemF_count"); +// QTest::addColumn("itemG_count"); +// QTest::addColumn("itemH_count"); +// QTest::addColumn("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(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 *"); + //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(0), Qt::Key_Escape); + QVERIFY(!menu.isVisible()); + QTRY_VERIFY(menubar.hasFocus()); + QCOMPARE(menubar.activeAction(), first); + QTest::keyClick(static_cast(0), Qt::Key_Escape); + QVERIFY(!menubar.activeAction()); + QTest::keyClick(static_cast(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(0), Qt::Key_Right); + QCOMPARE(menubar.activeAction(), a); + QTest::keyClick(static_cast(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(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 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "qplaintextedit.h" + +//Used in copyAvailable +typedef QPair keyPairType; +typedef QList pairListType; +Q_DECLARE_METATYPE(pairListType); +Q_DECLARE_METATYPE(keyPairType); +Q_DECLARE_METATYPE(QList); + +#ifdef Q_WS_MAC +#include +#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 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("Some Bold Text"); + 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("Second para"); + 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("input"); + QTest::addColumn("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("Blah"); + 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("keystrokes"); + QTest::addColumn >("copyAvailable"); + QTest::addColumn("function"); + + pairListType keystrokes; + QList 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, 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;idocument()->isUndoAvailable()); + QVERIFY(!ed->document()->isRedoAvailable()); + ed->setPlainText("Foobar"); + QVERIFY(!ed->document()->isUndoAvailable()); + QVERIFY(!ed->document()->isRedoAvailable()); + ed->setPlainText("

bleh

"); + 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(&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("testString"); + QTest::addColumn("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("
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() << 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() << sel); + + QList 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("

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 +#include "qprogressbar.h" +#include +#include +#include +#include +#include + +//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 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("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("value"); + QTest::addColumn("format"); + QTest::addColumn("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("style1_str"); + QTest::addColumn("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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/disabled_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setEnabled/enabled_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setPixmap/Vpix_Windows_win32_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Motif_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_data0.qsnap 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qpushbutton/testdata/setText/simple_Windows_win32_data0.qsnap 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 + + +#include "qpushbutton.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +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("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 + + +#include +#include +#include +#include + + +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 +#include + + +#include + +//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("rx"); + QTest::addColumn("value"); + QTest::addColumn("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 + +#include +#include +#include +#include + +//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 +#include +#include +#include + +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 +#include +#include +#include +#include +#include + +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("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 + +#include +#include +#include + +//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 +#include +#include +#include + +#ifdef Q_WS_X11 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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 actualValues; + QWidget *testFocusWidget; +}; + +typedef QList 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("set"); + QTest::addColumn("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("prefix"); + QTest::addColumn("suffix"); + QTest::addColumn("value"); + QTest::addColumn("expectedText"); + QTest::addColumn("expectedCleanText"); + QTest::addColumn("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("keys"); + QTest::addColumn("texts"); + QTest::addColumn("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("wrapping"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("startValue"); + QTest::addColumn("keys"); + QTest::addColumn("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("specialValueText"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("value"); + QTest::addColumn("expected"); + QTest::addColumn("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("singleStep"); + QTest::addColumn("startValue"); + QTest::addColumn("keys"); + QTest::addColumn("expected"); + QTest::addColumn("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("startValue"); + QTest::addColumn("mini"); + QTest::addColumn("maxi"); + QTest::addColumn("keys"); + QTest::addColumn("expected"); + QTest::addColumn("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("txt"); + QTest::addColumn("state"); + QTest::addColumn("mini"); + QTest::addColumn("maxi"); + QTest::addColumn("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("loc"); + QTest::addColumn("value"); + QTest::addColumn("textFromVal"); + QTest::addColumn("text"); + QTest::addColumn("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(&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(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // 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() << 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 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("minimumSizes"); + QTest::addColumn("splitterSizes"); + QTest::addColumn("expectedSizes"); + QTest::addColumn("collapsibleStates"); + QTest::addColumn("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 l1 = splitter->sizes(); + QList 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("initialSizes"); + QTest::addColumn("hideWidget1"); + QTest::addColumn("hideWidget2"); + QTest::addColumn("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("orientation"); + QTest::addColumn("widgetIndex"); + QTest::addColumn("stretchFactor"); + QTest::addColumn("expectedHStretch"); + QTest::addColumn("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("hideWidget1"); + QTest::addColumn("hideWidget2"); + QTest::addColumn >("finalValues"); + QTest::addColumn("handleVisible"); + + QSplitter *split = new QSplitter(Qt::Horizontal); + QTest::newRow("hideNone") << false << false << (QList() << 200 << 200) << true; + QTest::newRow("hide2") << false << true << (QList() << 400 + split->handleWidth() << 0) << false; + QTest::newRow("hide1") << true << false << (QList() << 0 << 400 + split->handleWidth()) << false; + QTest::newRow("hideall") << true << true << (QList() << 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() << 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("className"); + QTest::addColumn("addInConstructor"); + QTest::addColumn("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("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 + +#include +#include +#include +#include +#include + +//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 + + +#include +#include +#include +#include + +//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 statusBar = mainWindow.statusBar(); + QVERIFY(statusBar); + mainWindow.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mainWindow); +#endif + + QTRY_VERIFY(statusBar->isVisible()); + QPointer sizeGrip = qFindChild(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(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()->isVisible()); +#endif + main.showNormal(); + QTest::qWaitForWindowShown(&main); + QVERIFY(statusbar.findChild()->isVisible()); + main.showFullScreen(); + QTest::qWaitForWindowShown(&main); + QVERIFY(!statusbar.findChild()->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 +#include +#include + +#include +#include + +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("sizeToSet"); + QTest::addColumn("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("tabToSet"); + QTest::addColumn("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("currentIndex"); + QTest::addColumn("deleteIndex"); + QTest::addColumn("spyCount"); + QTest::addColumn("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("tabElideMode"); + QTest::addColumn("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("usesArrows"); + QTest::addColumn("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(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("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(button)); + QTRY_VERIFY(!button->isHidden()); + QVERIFY(tabbar.tabButton(0, otherSide) == 0); + QCOMPARE(button->parent(), static_cast(&tabbar)); + QVERIFY(button->pos() != QPoint(0, 0)); + + QPushButton *button2 = new QPushButton; + tabbar.setTabButton(0, position, button2); + QVERIFY(button->isHidden()); +} + +typedef QList IntList; +Q_DECLARE_METATYPE(QTabBar::SelectionBehavior) +Q_DECLARE_METATYPE(IntList) +#define ONE(x) (IntList() << x) +void tst_QTabBar::selectionBehaviorOnRemove_data() +{ + QTest::addColumn("selectionBehavior"); + QTest::addColumn("tabs"); + QTest::addColumn("select"); + QTest::addColumn("remove"); + QTest::addColumn("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("shape"); + QTest::addColumn("tabs"); + QTest::addColumn("from"); + QTest::addColumn("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 +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +# include +#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 +# include +#elif defined(Q_WS_QWS) +# include +#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 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("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 @@ + + +Sample Anchor + + +

Click Me!

+

+Here's a destination to jump to. +

+ + 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 @@ + +

+Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +Blah blah blah blah blah blah blah blah blah +

+

Paragraph with id

+Here's the bottom of the page. + 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 @@ +

Blah blah Link to second page blah +

Another link here: Link to third page 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 @@ +Page With BGThis page has a blue background 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 @@ +

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 @@ +This page has no background color 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 @@ +

blub blub Link to third page from second page 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 @@ +

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 +#include +#include +#include +#include + +#include +#include + +//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"); + 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(""); + 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("

Hello Link" + "

Blah

"); + 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("foobar"); + 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("link"); + 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-fully-selected.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/centered-partly-selected.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-line.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/last-char-on-parag.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/multiple-full-width-lines.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/nowrap_long.png 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 Binary files /dev/null and b/tests/auto/widgets/widgets/qtextedit/fullWidthSelection/single-full-width-line.png 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//Used in copyAvailable +typedef QPair keyPairType; +typedef QList pairListType; +Q_DECLARE_METATYPE(pairListType); +Q_DECLARE_METATYPE(keyPairType); +Q_DECLARE_METATYPE(QList); +Q_DECLARE_METATYPE(QList); + +#ifdef Q_WS_MAC +#include +#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() << 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 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 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("Some Bold Text"); + 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("Second para"); + 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("

Foo

"); + 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("input"); + QTest::addColumn("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("Blah"); + 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("keystrokes"); + QTest::addColumn >("copyAvailable"); + QTest::addColumn("function"); + + pairListType keystrokes; + QList 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, 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;idocument()->isUndoAvailable()); + QVERIFY(!ed->document()->isRedoAvailable()); + ed->setPlainText("Foobar"); + QVERIFY(!ed->document()->isUndoAvailable()); + QVERIFY(!ed->document()->isRedoAvailable()); + ed->setHtml("

bleh

"); + 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(&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("testString"); + QTest::addColumn("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("
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() << 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() << sel); + + QList 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("

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("
Foo
"); + + 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("bold bold")); + 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("cursorFrom"); + QTest::addColumn("cursorTo"); + QTest::addColumn("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 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 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(image.scanLine(y)); + const QRgb * const secondLine = reinterpret_cast(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(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("

QTextEdit is an "); + + QMimeData mimeData; + mimeData.setData("application/x-qrichtext", richtext); + + static_cast(ed)->publicInsertFromMimeData(&mimeData); + + QCOMPARE(ed->toPlainText(), QString::fromLatin1(" QTextEdit is an ")); + ed->clear(); + + richtext = " QTextEdit is an "; + mimeData.setData("application/x-qrichtext", richtext); + + static_cast(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 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("logical"); + QTest::addColumn("basicDir"); + QTest::addColumn >("positionList"); + + QTest::newRow("Latin text") + << QString::fromUtf8("abc") + << (int) QChar::DirL + << (QList() << 0 << 1 << 2 << 3); + QTest::newRow("Hebrew text, one item") + << QString::fromUtf8("\327\220\327\221\327\222") + << (int) QChar::DirR + << (QList() << 0 << 1 << 2 << 3); + QTest::newRow("Hebrew text after Latin text") + << QString::fromUtf8("abc\327\220\327\221\327\222") + << (int) QChar::DirL + << (QList() << 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() << 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() << 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() << 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() << 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() << 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, 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 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 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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"); + qRegisterMetaType("Qt::Orientation"); + qRegisterMetaType("Qt::ToolBarAreas"); + qRegisterMetaType("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(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(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(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(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(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(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(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(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(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(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(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(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(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 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 extensions = tb.findChildren(); + + 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(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 extensions = tb.findChildren(); + + 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(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(tb.childAt(rect1.center())); + QVERIFY(button1 != 0); + } + if (!rect02.isValid()) { + button2 = qobject_cast(tb.childAt(rect2.center())); + QVERIFY(button2 != 0); + } + if (!rect03.isValid()) { + button3 = qobject_cast(tb.childAt(rect3.center())); + QVERIFY(button3 != 0); + } + if (!rect04.isValid()) { + button4 = qobject_cast(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 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 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(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(&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 + +#include + + +//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 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 + +#include +#include +#include +#include +#include +#include +#include + +//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 *"); + 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(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(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 +#include +#include +#include +#include + +//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("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 \ diff --git a/tests/auto/windowsmobile/test/ddhelper.cpp b/tests/auto/windowsmobile/test/ddhelper.cpp deleted file mode 100644 index 55469f5901..0000000000 --- a/tests/auto/windowsmobile/test/ddhelper.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifdef Q_OS_WINCE_WM - -#include -#include - -static LPDIRECTDRAW g_pDD = NULL; // DirectDraw object -static LPDIRECTDRAWSURFACE g_pDDSSurface = NULL; // DirectDraw primary surface - -static DDSCAPS ddsCaps; -static DDSURFACEDESC ddsSurfaceDesc; -static void *buffer = NULL; - -static int width = 0; -static int height = 0; -static int pitch = 0; -static int bitCount = 0; -static int windowId = 0; - -static bool initialized = false; -static bool locked = false; - -void q_lock() -{ - if (locked) { - qWarning("Direct Painter already locked (QDirectPainter::lock())"); - return; - } - locked = true; - - - memset(&ddsSurfaceDesc, 0, sizeof(ddsSurfaceDesc)); - ddsSurfaceDesc.dwSize = sizeof(ddsSurfaceDesc); - - HRESULT h = g_pDDSSurface->Lock(0, &ddsSurfaceDesc, DDLOCK_WRITEONLY, 0); - if (h != DD_OK) - qDebug() << "GetSurfaceDesc failed!"; - - width = ddsSurfaceDesc.dwWidth; - height = ddsSurfaceDesc.dwHeight; - bitCount = ddsSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; - pitch = ddsSurfaceDesc.lPitch; - buffer = ddsSurfaceDesc.lpSurface; -} - -void q_unlock() -{ - if( !locked) { - qWarning("Direct Painter not locked (QDirectPainter::unlock()"); - return; - } - g_pDDSSurface->Unlock(0); - locked = false; -} - -void q_initDD() -{ - if (initialized) - return; - - DirectDrawCreate(NULL, &g_pDD, NULL); - - HRESULT h; - h = g_pDD->SetCooperativeLevel(0, DDSCL_NORMAL); - - if (h != DD_OK) - qDebug() << "cooperation level failed"; - - h = g_pDD->TestCooperativeLevel(); - if (h != DD_OK) - qDebug() << "cooperation level failed test"; - - DDSURFACEDESC ddsd; - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - - ddsd.dwFlags = DDSD_CAPS; - - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - h = g_pDD->CreateSurface(&ddsd, &g_pDDSSurface, NULL); - - if (h != DD_OK) - qDebug() << "CreateSurface failed!"; - - if (g_pDDSSurface->GetCaps(&ddsCaps) != DD_OK) - qDebug() << "GetCaps failed"; - - q_lock(); - q_unlock(); - initialized = true; -} - -uchar* q_frameBuffer() -{ - return (uchar*) buffer; -} - -int q_screenDepth() -{ - return bitCount; -} - -int q_screenWidth() -{ - return width; -} - -int q_screenHeight() -{ - return height; -} - -int q_linestep() -{ - return pitch; -} - -#endif //Q_OS_WINCE_WM - - diff --git a/tests/auto/windowsmobile/test/ddhelper.h b/tests/auto/windowsmobile/test/ddhelper.h deleted file mode 100644 index 3d2f06aa36..0000000000 --- a/tests/auto/windowsmobile/test/ddhelper.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** 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 __DDHELPER__ -#define __DDHELPER__ - -extern uchar* q_frameBuffer(); - -extern int q_screenDepth(); - -extern int q_screenWidth(); - -extern int q_screenHeight(); - -extern int q_linestep(); - -extern void q_initDD(); - -extern void q_unlock(); - -extern void q_lock(); - -#endif //__DDHELPER__ - diff --git a/tests/auto/windowsmobile/test/test.pro b/tests/auto/windowsmobile/test/test.pro deleted file mode 100644 index 595a619d2a..0000000000 --- a/tests/auto/windowsmobile/test/test.pro +++ /dev/null @@ -1,23 +0,0 @@ - -load(qttest_p4) -QT += widgets -HEADERS += ddhelper.h -SOURCES += tst_windowsmobile.cpp ddhelper.cpp -RESOURCES += windowsmobile.qrc - -TARGET = ../tst_windowsmobile - -wincewm*: { - addFiles.files = $$OUT_PWD/../testQMenuBar/*.exe - - - addFiles.path = "\\Program Files\\tst_windowsmobile" - DEPLOYMENT += addFiles -} - -wincewm*: { - LIBS += Ddraw.lib -} - - - diff --git a/tests/auto/windowsmobile/test/testQMenuBar_current.png b/tests/auto/windowsmobile/test/testQMenuBar_current.png deleted file mode 100644 index f0042b8fe0..0000000000 Binary files a/tests/auto/windowsmobile/test/testQMenuBar_current.png and /dev/null differ diff --git a/tests/auto/windowsmobile/test/testSimpleWidget_current.png b/tests/auto/windowsmobile/test/testSimpleWidget_current.png deleted file mode 100644 index 8086c41ce9..0000000000 Binary files a/tests/auto/windowsmobile/test/testSimpleWidget_current.png and /dev/null differ diff --git a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp deleted file mode 100644 index 0dc7f578c1..0000000000 --- a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#ifdef Q_OS_WINCE_WM -#include -#include "ddhelper.h" -#endif - - - -class tst_WindowsMobile : public QObject -{ - Q_OBJECT -public: - tst_WindowsMobile() - { - qApp->setCursorFlashTime (24 * 3600 * 1000); // once a day - // qApp->setCursorFlashTime (INT_MAX); -#ifdef Q_OS_WINCE_WM - q_initDD(); -#endif - } - -#if defined(Q_OS_WINCE_WM) && defined(_WIN32_WCE) && _WIN32_WCE <= 0x501 - private slots: - void testMainWindowAndMenuBar(); - void testSimpleWidget(); -#endif -}; - -#if defined(Q_OS_WINCE_WM) && defined(_WIN32_WCE) && _WIN32_WCE <= 0x501 - -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 (platformString.utf16()), tszPlatform)) - return true; - return false; -} - -bool qt_wince_is_smartphone() { - return qt_wince_is_platform(QString::fromLatin1("Smartphone")); -} - -void openMenu() -{ - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,450,630,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,450,630,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,55535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,55535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,58535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,58535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,40535,55535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,40535,55535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,32535,55535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,32535,55535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,65535,65535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,50535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,50535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,55535,40535,0,0); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,55535,40535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE,48535,45535,0,0); - QTest::qWait(2000); - ::mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE,48535,45535,0,0); -} - -void compareScreenshots(const QString &image1, const QString &image2) -{ - QImage screenShot(image1); - QImage original(image2); - - // cut away the title bar before comparing - QDesktopWidget desktop; - QRect desktopFrameRect = desktop.frameGeometry(); - QRect desktopClientRect = desktop.availableGeometry(); - - QPainter p1(&screenShot); - QPainter p2(&original); - - //screenShot.save("scr1.png", "PNG"); - p1.fillRect(0, 0, desktopFrameRect.width(), desktopClientRect.y(), Qt::black); - p2.fillRect(0, 0, desktopFrameRect.width(), desktopClientRect.y(), Qt::black); - - //screenShot.save("scr2.png", "PNG"); - //original.save("orig1.png", "PNG"); - - QVERIFY(original == screenShot); -} - -void takeScreenShot(const QString filename) -{ - q_lock(); - QImage image = QImage(( uchar *) q_frameBuffer(), q_screenWidth(), - q_screenHeight(), q_screenWidth() * q_screenDepth() / 8, QImage::Format_RGB16); - image.save(filename, "PNG"); - q_unlock(); -} - -void tst_WindowsMobile::testMainWindowAndMenuBar() -{ - if (qt_wince_is_smartphone()) - QSKIP("This test is only for Windows Mobile", SkipAll); - - QProcess process; - process.start("testQMenuBar.exe"); - QCOMPARE(process.state(), QProcess::Running); - QTest::qWait(6000); - openMenu(); - QTest::qWait(1000); - takeScreenShot("testQMenuBar_current.png"); - process.close(); - compareScreenshots("testQMenuBar_current.png", ":/testQMenuBar_current.png"); -} - -void tst_WindowsMobile::testSimpleWidget() -{ - if (qt_wince_is_smartphone()) - QSKIP("This test is only for Windows Mobile", SkipAll); - - QMenuBar menubar; - menubar.show(); - QWidget maximized; - QPalette pal = maximized.palette(); - pal.setColor(QPalette::Background, Qt::red); - maximized.setPalette(pal); - maximized.showMaximized(); - QWidget widget; - widget.setGeometry(100, 100, 200, 200); - widget.setWindowTitle("Widget"); - widget.show(); - qApp->processEvents(); - QTest::qWait(1000); - - QWidget widget2; - widget2.setGeometry(100, 380, 300, 200); - widget2.setWindowTitle("Widget 2"); - widget2.setWindowFlags(Qt::Popup); - widget2.show(); - - qApp->processEvents(); - QTest::qWait(1000); - takeScreenShot("testSimpleWidget_current.png"); - compareScreenshots("testSimpleWidget_current.png", ":/testSimpleWidget_current.png"); -} - - -#endif //Q_OS_WINCE_WM - - -QTEST_MAIN(tst_WindowsMobile) -#include "tst_windowsmobile.moc" - diff --git a/tests/auto/windowsmobile/test/windowsmobile.qrc b/tests/auto/windowsmobile/test/windowsmobile.qrc deleted file mode 100644 index 5d6f61459e..0000000000 --- a/tests/auto/windowsmobile/test/windowsmobile.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - testQMenuBar_current.png - testSimpleWidget_current.png - - diff --git a/tests/auto/windowsmobile/testQMenuBar/main.cpp b/tests/auto/windowsmobile/testQMenuBar/main.cpp deleted file mode 100644 index c2099a648b..0000000000 --- a/tests/auto/windowsmobile/testQMenuBar/main.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include -#include - -int main(int argc, char * argv[]) -{ - QList widgets; - QApplication app(argc, argv); - - QMainWindow mainWindow; - mainWindow.setWindowTitle("Test"); - QMenu *fileMenu = mainWindow.menuBar()->addMenu("File"); - QMenu *editMenu = mainWindow.menuBar()->addMenu("Edit"); - QMenu *viewMenu = mainWindow.menuBar()->addMenu("View"); - QMenu *toolsMenu = mainWindow.menuBar()->addMenu("Tools"); - QMenu *optionsMenu = mainWindow.menuBar()->addMenu("Options"); - QMenu *helpMenu = mainWindow.menuBar()->addMenu("Help"); - - qApp->processEvents(); - - fileMenu->addAction("Open"); - QAction *close = fileMenu->addAction("Close"); - fileMenu->addSeparator(); - fileMenu->addAction("Exit"); - - close->setEnabled(false); - - editMenu->addAction("Cut"); - editMenu->addAction("Pase"); - editMenu->addAction("Copy"); - editMenu->addSeparator(); - editMenu->addAction("Find"); - - viewMenu->addAction("Hide"); - viewMenu->addAction("Show"); - viewMenu->addAction("Explore"); - QAction *visible = viewMenu->addAction("Visible"); - visible->setCheckable(true); - visible->setChecked(true); - - toolsMenu->addMenu("Hammer"); - toolsMenu->addMenu("Caliper"); - toolsMenu->addMenu("Helm"); - - optionsMenu->addMenu("Settings"); - optionsMenu->addMenu("Standard"); - optionsMenu->addMenu("Extended"); - - QMenu *subMenu = helpMenu->addMenu("Help"); - subMenu->addAction("Index"); - subMenu->addSeparator(); - subMenu->addAction("Vodoo Help"); - helpMenu->addAction("Contens"); - helpMenu->addSeparator(); - helpMenu->addAction("About"); - - QToolBar toolbar; - mainWindow.addToolBar(&toolbar); - toolbar.addAction(QIcon(qApp->style()->standardPixmap(QStyle::SP_FileIcon)), QString("textAction")); - - QTextEdit textEdit; - mainWindow.setCentralWidget(&textEdit); - - mainWindow.showMaximized(); - - app.exec(); -} diff --git a/tests/auto/windowsmobile/testQMenuBar/testQMenuBar.pro b/tests/auto/windowsmobile/testQMenuBar/testQMenuBar.pro deleted file mode 100644 index 6b84ae937c..0000000000 --- a/tests/auto/windowsmobile/testQMenuBar/testQMenuBar.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES += main.cpp -QT += widgets -TARGET = ../testQMenuBar - diff --git a/tests/auto/windowsmobile/windowsmobile.pro b/tests/auto/windowsmobile/windowsmobile.pro deleted file mode 100644 index 2e6b444d7b..0000000000 --- a/tests/auto/windowsmobile/windowsmobile.pro +++ /dev/null @@ -1,9 +0,0 @@ - -TEMPLATE = subdirs - -wincewm* { - SUBDIRS = testQMenuBar -} - SUBDIRS += test - - -- cgit v1.2.3